| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- "use strict";
- var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
- };
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.uniViteInjectPlugin = void 0;
- const path_1 = require("path");
- const debug_1 = __importDefault(require("debug"));
- const pluginutils_1 = require("@rollup/pluginutils");
- const estree_walker_1 = require("estree-walker");
- const shared_1 = require("@vue/shared");
- const magic_string_1 = __importDefault(require("magic-string"));
- const utils_1 = require("../utils");
- const debugInject = (0, debug_1.default)('uni:inject');
- const debugInjectTry = (0, debug_1.default)('uni:inject-try');
- function uniViteInjectPlugin(name, options) {
- if (!options)
- throw new Error('Missing options');
- const filter = (0, pluginutils_1.createFilter)(options.include, options.exclude);
- const modules = (0, shared_1.extend)({}, options);
- delete modules.include;
- delete modules.exclude;
- delete modules.sourceMap;
- delete modules.callback;
- const reassignments = new Set();
- const modulesMap = new Map();
- const namespaceModulesMap = new Map();
- Object.keys(modules).forEach((name) => {
- if (name.endsWith('.')) {
- namespaceModulesMap.set(name, modules[name]);
- }
- modulesMap.set(name, modules[name]);
- });
- const hasNamespace = namespaceModulesMap.size > 0;
- // Fix paths on Windows
- if (path_1.sep !== '/') {
- normalizeModulesMap(modulesMap);
- normalizeModulesMap(namespaceModulesMap);
- }
- const firstpass = new RegExp(`(?:${Array.from(modulesMap.keys()).map(escape).join('|')})`, 'g');
- const sourceMap = options.sourceMap !== false;
- const callback = options.callback;
- return {
- name,
- // 确保在 commonjs 之后,否则会混合 es6 module 与 cjs 的代码,导致 commonjs 失效
- enforce: options.enforce ?? 'post',
- transform(code, id) {
- if (!filter(id))
- return null;
- if (!(0, utils_1.isJsFile)(id))
- return null;
- debugInjectTry(id);
- if (code.search(firstpass) === -1)
- return null;
- if (path_1.sep !== '/')
- id = id.split(path_1.sep).join('/');
- const ast = this.parse(code);
- const imports = new Set();
- ast.body.forEach((node) => {
- if (node.type === 'ImportDeclaration') {
- node.specifiers.forEach((specifier) => {
- imports.add(specifier.local.name);
- });
- }
- });
- // analyse scopes
- let scope = (0, pluginutils_1.attachScopes)(ast, 'scope');
- const magicString = new magic_string_1.default(code);
- const newImports = new Map();
- function handleReference(node, name, keypath, parent) {
- let mod = modulesMap.get(keypath);
- if (!mod && hasNamespace) {
- const mods = keypath.split('.');
- if (mods.length === 2) {
- mod = namespaceModulesMap.get(mods[0] + '.');
- if (mod) {
- if ((0, shared_1.isArray)(mod)) {
- const testFn = mod[1];
- if (testFn(mods[1])) {
- mod = [mod[0], mods[1]];
- }
- else {
- mod = undefined;
- }
- }
- else {
- mod = [mod, mods[1]];
- }
- }
- }
- }
- if (mod && !imports.has(name) && !scope.contains(name)) {
- if ((0, shared_1.isString)(mod))
- mod = [mod, 'default'];
- if (mod[0] === id)
- return false;
- const hash = `${keypath}:${mod[0]}:${mod[1]}`;
- // 当 API 被覆盖定义后,不再摇树
- if (reassignments.has(hash)) {
- return false;
- }
- if (parent &&
- (0, utils_1.isAssignmentExpression)(parent) &&
- parent.left === node) {
- reassignments.add(hash);
- return false;
- }
- const importLocalName = name === keypath ? name : (0, pluginutils_1.makeLegalIdentifier)(`$inject_${keypath}`);
- if (!newImports.has(hash)) {
- if (mod[1] === '*') {
- newImports.set(hash, `import * as ${importLocalName} from '${mod[0]}';`);
- }
- else {
- newImports.set(hash, `import { ${mod[1]} as ${importLocalName} } from '${mod[0]}';`);
- callback && callback(newImports, mod);
- }
- }
- if (name !== keypath) {
- magicString.overwrite(node.start, node.end, importLocalName, {
- storeName: true,
- });
- }
- return true;
- }
- return false;
- }
- (0, estree_walker_1.walk)(ast, {
- enter(node, parent) {
- if (sourceMap) {
- magicString.addSourcemapLocation(node.start);
- magicString.addSourcemapLocation(node.end);
- }
- if (node.scope) {
- scope = node.scope;
- }
- if ((0, utils_1.isProperty)(node) && node.shorthand) {
- const { name } = node.key;
- handleReference(node, name, name);
- this.skip();
- return;
- }
- if ((0, utils_1.isReference)(node, parent)) {
- const { name, keypath } = flatten(node);
- const handled = handleReference(node, name, keypath, parent);
- if (handled) {
- this.skip();
- }
- }
- },
- leave(node) {
- if (node.scope) {
- scope = scope.parent;
- }
- },
- });
- debugInject(id, newImports.size);
- if (newImports.size === 0) {
- return {
- code,
- // 不能返回 ast ,否则会导致代码不能被再次修改
- // 比如 App.vue 中,console.log('uniCloud') 触发了 inject 检测,检测完,发现不需要
- // 此时返回 ast,会导致 import { setupApp } from '@dcloudio/uni-h5' 不会被编译
- // ast
- map: null,
- };
- }
- const importBlock = Array.from(newImports.values()).join('\n\n');
- magicString.prepend(`${importBlock}\n\n`);
- return {
- code: magicString.toString(),
- map: sourceMap ? magicString.generateMap({ hires: true }) : null,
- };
- },
- };
- }
- exports.uniViteInjectPlugin = uniViteInjectPlugin;
- const escape = (str) => str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
- const flatten = (startNode) => {
- const parts = [];
- let node = startNode;
- while ((0, utils_1.isMemberExpression)(node)) {
- parts.unshift(node.property.name);
- node = node.object;
- }
- const { name } = node;
- parts.unshift(name);
- return { name, keypath: parts.join('.') };
- };
- function normalizeModulesMap(modulesMap) {
- modulesMap.forEach((mod, key) => {
- modulesMap.set(key, (0, shared_1.isArray)(mod)
- ? [mod[0].split(path_1.sep).join('/'), mod[1]]
- : mod.split(path_1.sep).join('/'));
- });
- }
|