UNPKG

mpvue-webpack4-loader

Version:

mpvue single-file component loader for Webpack

183 lines (157 loc) 5.32 kB
// babel-plugin-parse-mp-info.js const generate = require('babel-generator').default const babelon = require('babelon7') const compilerContext = require('../context') const path = require('path') // 解析 config const traverseConfigVisitor = { Property: function (path) { const k = path.node.key.name || path.node.key.value if (k !== 'config') { return } path.stop() const { metadata } = path.hub.file const { code } = generate(path.node.value, {}, '') metadata.config = { code, node: path.node.value, value: babelon.eval(code) } // path.remove() } } // config 的遍历器 const configVisitor = { ExportDefaultDeclaration: function (path) { path.traverse(traverseConfigVisitor) path.remove() }, ImportDeclaration: parseImports, NewExpression: function (path) { const { metadata } = path.hub.file const { importsMap = {} } = metadata const calleeName = path.node.callee.name const isVue = /(vue$)|vue-property-decorator/.test(importsMap[calleeName]) if (!isVue) { return } const arg = path.node.arguments[0] const v = arg.type === 'Identifier' ? importsMap[arg.name] : importsMap['App'] metadata.rootComponent = v || importsMap['index'] || importsMap['main'] } } function parseConfig(babel) { return { visitor: configVisitor } } // 解析 components const traverseComponentsVisitor = { Property: function (path) { if (path.node.key.name !== 'components') { return } path.stop() const { metadata } = path.hub.file const { importsMap = {} } = metadata; // 找到所有的 imports const { properties } = path.node.value const components = {} properties.forEach(p => { const k = p.key.name || p.key.value const v = p.value.name || p.value.value components[k] = getComponents(importsMap[v], k) }) metadata.components = components } } // components 的遍历器 const componentsVisitor = { ExportDefaultDeclaration: function (path) { path.traverse(traverseComponentsVisitor) }, ImportDeclaration: function(path){ return parseImports(path); }, CallExpression: function (path) { if (path.node.callee && path.node.callee.name === 'Component') { path.traverse(traverseComponentsVisitor) } } } function parseImports(path){ const node = path.node; const { metadata } = path.hub.file; const moduleName = node.source.value; const specifiers = node.specifiers || []; if (!metadata.importsMap) { metadata.importsMap = {}; } const importMaps = metadata.importsMap || {}; specifiers.forEach((element) => { importMaps[element.local.name] = moduleName; }); } function parseComponentsDeps(babel) { return { visitor: componentsVisitor } } function getComponents(libraryName, methodName) { const dynamic = compilerContext.getQueryOptions().dynamic || [] for (var i = 0, k = dynamic.length; i < k; i++) { var info = dynamic[i] if (info.libraryName === libraryName) { var camel2DashComponentName = typeof info.camel2DashComponentName === 'undefined' ? true : info.camel2DashComponentName var transformedMethodName = info.camel2UnderlineComponentName // eslint-disable-line ? camel2Underline(methodName) : camel2DashComponentName ? camel2Dash(methodName) : methodName var using = winPath( info.customName ? info.customName(transformedMethodName) : path.join(info.libraryName, info.libraryDirectory || 'lib', transformedMethodName, info.fileName || '') ) // eslint-disable-line return using } } return libraryName } function camel2Dash(_str) { var str = _str[0].toLowerCase() + _str.substr(1) return str.replace(/([A-Z])/g, function ($1) { return '-'.concat($1.toLowerCase()) }) } function winPath(path) { return path.replace(/\\/g, '/') } function camel2Underline(_str) { var str = _str[0].toLowerCase() + _str.substr(1) return str.replace(/([A-Z])/g, function ($1) { return '_'.concat($1.toLowerCase()) }) } // 解析全局components let globalComponents = {} const globalComponentsVisitor = { ImportDeclaration: function(path){ return parseImports(path); }, CallExpression (path) { const { callee, arguments: args } = path.node const { metadata } = path.hub.file if (!callee.object || !callee.property) { return } if (callee.object.name === 'Vue' && callee.property.name === 'component') { if (!args[0] || args[0].type !== 'StringLiteral') { throw new Error('Vue.component()的第一个参数必须为静态字符串') } if (!args[1]) { throw new Error('Vue.component()需要两个参数') } const { importsMap = {} } = metadata; globalComponents[args[0].value] = importsMap[args[0].value] } metadata.globalComponents = globalComponents } } function parseGlobalComponents (babel) { return { visitor: globalComponentsVisitor } } function clearGlobalComponents () { globalComponents = {} } module.exports = { parseConfig, parseComponentsDeps,parseGlobalComponents,clearGlobalComponents }