uni-ticket-system/node_modules/@dcloudio/uni-cli-shared/dist/mp/usingComponents.js

407 lines
15 KiB
JavaScript
Raw Normal View History

2023-12-05 02:11:10 +00:00
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.transformDynamicImports = exports.parseScriptDescriptor = exports.parseTemplateDescriptor = exports.updateMiniProgramComponentsByMainFilename = exports.updateMiniProgramGlobalComponents = exports.updateMiniProgramComponentsByTemplateFilename = exports.updateMiniProgramComponentsByScriptFilename = exports.parseMainDescriptor = void 0;
const types_1 = require("@babel/types");
const estree_walker_1 = require("estree-walker");
const magic_string_1 = __importDefault(require("magic-string"));
const shared_1 = require("@vue/shared");
const uni_shared_1 = require("@dcloudio/uni-shared");
const messages_1 = require("../messages");
const constants_1 = require("../constants");
const utils_1 = require("../utils");
const utils_2 = require("../vite/utils");
const jsonFile_1 = require("../json/mp/jsonFile");
const mainDescriptors = new Map();
const scriptDescriptors = new Map();
const templateDescriptors = new Map();
function findImportTemplateSource(ast) {
const importDeclaration = ast.body.find((node) => (0, types_1.isImportDeclaration)(node) &&
node.source.value.includes('vue&type=template'));
if (importDeclaration) {
return importDeclaration.source.value;
}
}
function findImportScriptSource(ast) {
const importDeclaration = ast.body.find((node) => (0, types_1.isImportDeclaration)(node) && node.source.value.includes('vue&type=script'));
if (importDeclaration) {
return importDeclaration.source.value;
}
}
async function resolveSource(filename, source, resolve) {
if (!source) {
return;
}
const resolveId = await resolve(source, filename);
if (resolveId) {
return resolveId.id;
}
}
async function parseMainDescriptor(filename, ast, resolve) {
const script = await resolveSource(filename, findImportScriptSource(ast), resolve);
const template = await resolveSource(filename, findImportTemplateSource(ast), resolve);
const imports = await parseVueComponentImports(filename, ast.body.filter((node) => (0, types_1.isImportDeclaration)(node)), resolve);
if (!script) {
// inline script
await parseScriptDescriptor(filename, ast, { resolve, isExternal: false });
}
if (!template) {
// inline template
await parseTemplateDescriptor(filename, ast, { resolve, isExternal: false });
}
const descriptor = {
imports,
script: script ? (0, utils_2.parseVueRequest)(script).filename : filename,
template: template ? (0, utils_2.parseVueRequest)(template).filename : filename,
};
mainDescriptors.set(filename, descriptor);
return descriptor;
}
exports.parseMainDescriptor = parseMainDescriptor;
function updateMiniProgramComponentsByScriptFilename(scriptFilename, inputDir, normalizeComponentName) {
const mainFilename = findMainFilenameByScriptFilename(scriptFilename);
if (mainFilename) {
updateMiniProgramComponentsByMainFilename(mainFilename, inputDir, normalizeComponentName);
}
}
exports.updateMiniProgramComponentsByScriptFilename = updateMiniProgramComponentsByScriptFilename;
function updateMiniProgramComponentsByTemplateFilename(templateFilename, inputDir, normalizeComponentName) {
const mainFilename = findMainFilenameByTemplateFilename(templateFilename);
if (mainFilename) {
updateMiniProgramComponentsByMainFilename(mainFilename, inputDir, normalizeComponentName);
}
}
exports.updateMiniProgramComponentsByTemplateFilename = updateMiniProgramComponentsByTemplateFilename;
function findMainFilenameByScriptFilename(scriptFilename) {
const keys = [...mainDescriptors.keys()];
return keys.find((key) => mainDescriptors.get(key).script === scriptFilename);
}
function findMainFilenameByTemplateFilename(templateFilename) {
const keys = [...mainDescriptors.keys()];
return keys.find((key) => mainDescriptors.get(key).template === templateFilename);
}
async function updateMiniProgramGlobalComponents(filename, ast, { inputDir, resolve, normalizeComponentName, }) {
const { bindingComponents, imports } = await parseGlobalDescriptor(filename, ast, resolve);
(0, jsonFile_1.addMiniProgramUsingComponents)('app', createUsingComponents(bindingComponents, imports, inputDir, normalizeComponentName));
return {
imports,
};
}
exports.updateMiniProgramGlobalComponents = updateMiniProgramGlobalComponents;
function createUsingComponents(bindingComponents, imports, inputDir, normalizeComponentName) {
const usingComponents = {};
imports.forEach(({ source: { value }, specifiers: [specifier] }) => {
const { name } = specifier.local;
if (!bindingComponents[name]) {
return;
}
const componentName = normalizeComponentName((0, shared_1.hyphenate)(bindingComponents[name].tag));
if (!usingComponents[componentName]) {
usingComponents[componentName] = (0, uni_shared_1.addLeadingSlash)((0, utils_1.removeExt)((0, utils_1.normalizeMiniProgramFilename)(value, inputDir)));
}
});
return usingComponents;
}
function updateMiniProgramComponentsByMainFilename(mainFilename, inputDir, normalizeComponentName) {
const mainDescriptor = mainDescriptors.get(mainFilename);
if (!mainDescriptor) {
return;
}
const templateDescriptor = templateDescriptors.get(mainDescriptor.template);
if (!templateDescriptor) {
return;
}
const scriptDescriptor = scriptDescriptors.get(mainDescriptor.script);
if (!scriptDescriptor) {
return;
}
const bindingComponents = parseBindingComponents({
...templateDescriptor.bindingComponents,
...scriptDescriptor.setupBindingComponents,
}, scriptDescriptor.bindingComponents);
const imports = parseImports(mainDescriptor.imports, scriptDescriptor.imports, templateDescriptor.imports);
(0, jsonFile_1.addMiniProgramUsingComponents)((0, utils_1.removeExt)((0, utils_1.normalizeMiniProgramFilename)(mainFilename, inputDir)), createUsingComponents(bindingComponents, imports, inputDir, normalizeComponentName));
}
exports.updateMiniProgramComponentsByMainFilename = updateMiniProgramComponentsByMainFilename;
function findBindingComponent(tag, bindingComponents) {
return Object.keys(bindingComponents).find((name) => {
const componentTag = bindingComponents[name].tag;
const camelName = (0, shared_1.camelize)(componentTag);
const PascalName = (0, shared_1.capitalize)(camelName);
return tag === componentTag || tag === camelName || tag === PascalName;
});
}
function normalizeComponentId(id) {
// _unref(test) => test
if (id.includes('_unref(')) {
return id.replace('_unref(', '').replace(')', '');
}
// $setup["test"] => test
if (id.includes('$setup[')) {
return id.replace('$setup["', '').replace('"', '');
}
return id;
}
function parseBindingComponents(templateBindingComponents, scriptBindingComponents) {
const bindingComponents = {};
Object.keys(templateBindingComponents).forEach((id) => {
bindingComponents[normalizeComponentId(id)] = templateBindingComponents[id];
});
Object.keys(scriptBindingComponents).forEach((id) => {
const { tag } = scriptBindingComponents[id];
const name = findBindingComponent(tag, templateBindingComponents);
if (name) {
bindingComponents[id] = bindingComponents[name];
}
});
return bindingComponents;
}
function parseImports(mainImports, scriptImports, templateImports) {
const imports = [...mainImports, ...templateImports, ...scriptImports];
return imports;
}
/**
* 解析 template
* @param filename
* @param code
* @param ast
* @param options
* @returns
*/
async function parseTemplateDescriptor(filename, ast, options) {
// 外置时查找所有 vue component import
const imports = options.isExternal
? await parseVueComponentImports(filename, ast.body.filter((node) => (0, types_1.isImportDeclaration)(node)), options.resolve)
: [];
const descriptor = {
bindingComponents: findBindingComponents(ast.body),
imports,
};
templateDescriptors.set(filename, descriptor);
return descriptor;
}
exports.parseTemplateDescriptor = parseTemplateDescriptor;
async function parseGlobalDescriptor(filename, ast, resolve) {
// 外置时查找所有 vue component import
const imports = (await parseVueComponentImports(filename, ast.body.filter((node) => (0, types_1.isImportDeclaration)(node)), resolve)).filter((item) => !(0, utils_1.isAppVue)((0, utils_2.cleanUrl)(item.source.value)));
return {
bindingComponents: parseGlobalComponents(ast),
imports,
};
}
/**
* 解析 script
* @param filename
* @param code
* @param ast
* @param options
* @returns
*/
async function parseScriptDescriptor(filename, ast, options) {
// 外置时查找所有 vue component import
const imports = options.isExternal
? await parseVueComponentImports(filename, ast.body.filter((node) => (0, types_1.isImportDeclaration)(node)), options.resolve)
: [];
const descriptor = {
bindingComponents: parseComponents(ast),
setupBindingComponents: findBindingComponents(ast.body),
imports,
};
scriptDescriptors.set(filename, descriptor);
return descriptor;
}
exports.parseScriptDescriptor = parseScriptDescriptor;
/**
* 解析编译器生成的 bindingComponents
* @param ast
* @returns
*/
function findBindingComponents(ast) {
const mapping = findUnpluginComponents(ast);
for (const node of ast) {
if (!(0, types_1.isVariableDeclaration)(node)) {
continue;
}
const declarator = node.declarations[0];
if ((0, types_1.isIdentifier)(declarator.id) &&
declarator.id.name === constants_1.BINDING_COMPONENTS) {
const bindingComponents = JSON.parse(declarator.init.value);
return Object.keys(bindingComponents).reduce((bindings, tag) => {
const { name, type } = bindingComponents[tag];
bindings[mapping[name] || name] = {
tag,
type: type,
};
return bindings;
}, {});
}
}
return {};
}
/**
* 兼容unplugin_components
* https://github.com/dcloudio/uni-app/issues/3057
* @param ast
* @returns
*/
function findUnpluginComponents(ast) {
const res = Object.create(null);
// if(!Array){}
const ifStatement = ast.find((statement) => (0, types_1.isIfStatement)(statement) &&
(0, types_1.isUnaryExpression)(statement.test) &&
statement.test.operator === '!' &&
(0, types_1.isIdentifier)(statement.test.argument) &&
statement.test.argument.name === 'Array');
if (!ifStatement) {
return res;
}
if (!(0, types_1.isBlockStatement)(ifStatement.consequent)) {
return res;
}
for (const node of ifStatement.consequent.body) {
if (!(0, types_1.isVariableDeclaration)(node)) {
continue;
}
const { id, init } = node.declarations[0];
if ((0, types_1.isIdentifier)(id) &&
(0, types_1.isIdentifier)(init) &&
init.name.includes('unplugin_components')) {
res[id.name] = init.name;
}
}
return res;
}
/**
* 查找全局组件定义app.component('component-a',{})
* @param ast
* @returns
*/
function parseGlobalComponents(ast) {
const bindingComponents = {};
estree_walker_1.walk(ast, {
enter(child) {
if (!(0, types_1.isCallExpression)(child)) {
return;
}
const { callee } = child;
// .component
if (!(0, types_1.isMemberExpression)(callee) ||
!(0, types_1.isIdentifier)(callee.property) ||
callee.property.name !== 'component') {
return;
}
// .component('component-a',{})
const args = child.arguments;
if (args.length !== 2) {
return;
}
const [name, value] = args;
if (!(0, types_1.isStringLiteral)(name)) {
return console.warn(messages_1.M['mp.component.args[0]']);
}
if (!(0, types_1.isIdentifier)(value)) {
return console.warn(messages_1.M['mp.component.args[1]']);
}
bindingComponents[value.name] = {
tag: name.value,
type: 'unknown',
};
},
});
return bindingComponents;
}
/**
* components 中查找定义的组件
* @param ast
* @param bindingComponents
*/
function parseComponents(ast) {
const bindingComponents = {};
estree_walker_1.walk(ast, {
enter(child) {
if (!(0, types_1.isObjectExpression)(child)) {
return;
}
const componentsProp = child.properties.find((prop) => (0, types_1.isObjectProperty)(prop) &&
(0, types_1.isIdentifier)(prop.key) &&
prop.key.name === 'components');
if (!componentsProp) {
return;
}
const componentsExpr = componentsProp.value;
if (!(0, types_1.isObjectExpression)(componentsExpr)) {
return;
}
componentsExpr.properties.forEach((prop) => {
if (!(0, types_1.isObjectProperty)(prop)) {
return;
}
if (!(0, types_1.isIdentifier)(prop.key) && !(0, types_1.isStringLiteral)(prop.key)) {
return;
}
if (!(0, types_1.isIdentifier)(prop.value)) {
return;
}
bindingComponents[prop.value.name] = {
tag: (0, types_1.isIdentifier)(prop.key) ? prop.key.name : prop.key.value,
type: 'unknown',
};
});
},
});
return bindingComponents;
}
/**
* vue component imports
* @param filename
* @param imports
* @param resolve
* @returns
*/
async function parseVueComponentImports(importer, imports, resolve) {
const vueComponentImports = [];
for (let i = 0; i < imports.length; i++) {
const { source } = imports[i];
if ((0, utils_2.parseVueRequest)(source.value).query.vue) {
continue;
}
const resolveId = await resolve(source.value, importer);
if (!resolveId) {
continue;
}
const { filename } = (0, utils_2.parseVueRequest)(resolveId.id);
if (constants_1.EXTNAME_VUE_RE.test(filename)) {
source.value = resolveId.id;
vueComponentImports.push(imports[i]);
}
}
return vueComponentImports;
}
/**
* static import => dynamic import
* @param code
* @param imports
* @param dynamicImport
* @returns
*/
async function transformDynamicImports(code, imports, { id, sourceMap, dynamicImport, }) {
if (!imports.length) {
return {
code,
map: null,
};
}
const s = new magic_string_1.default(code);
for (let i = 0; i < imports.length; i++) {
const { start, end, specifiers: [specifier], source, } = imports[i];
s.overwrite(start, end, dynamicImport(specifier.local.name, source.value) + ';');
}
return {
code: s.toString(),
map: null,
};
}
exports.transformDynamicImports = transformDynamicImports;