diff --git a/lib/mp-compiler/index.js b/lib/mp-compiler/index.js index 1ca8536..9931079 100644 --- a/lib/mp-compiler/index.js +++ b/lib/mp-compiler/index.js @@ -2,7 +2,11 @@ const compiler = require('mpvue-template-compiler') const babel = require('babel-core') +const path = require('path') +const fs = require('fs') + const { parseConfig, parseComponentsDeps } = require('./parse') +const { parseComponentsDeps: parseComponentsDepsTs } = require('./parse-ts') const { genScript, genStyle, genPageWxml } = require('./templates') const { @@ -93,7 +97,19 @@ function compileWxml (compiled, html) { // 处理出当前单文件组件的子组件依赖 function compileMPScript (script, mpOptioins, moduleId) { const babelrc = getBabelrc(mpOptioins.globalBabelrc) - const { metadata } = babel.transform(script.content, { extends: babelrc, plugins: [parseComponentsDeps] }) + let result, metadata + let scriptContent = script.content + const babelOptions = { extends: babelrc, plugins: [parseComponentsDeps] } + if (script.src) { // 处理src + const scriptpath = path.join(path.dirname(this.resourcePath), script.src) + scriptContent = fs.readFileSync(scriptpath).toString() + } + if (script.lang === 'ts') { // 处理ts + metadata = parseComponentsDepsTs(scriptContent) + } else { + result = babel.transform(scriptContent, babelOptions) + metadata = result.metadata + } // metadata: importsMap, components const { importsMap, components: originComponents } = metadata diff --git a/lib/mp-compiler/parse-ts.js b/lib/mp-compiler/parse-ts.js new file mode 100644 index 0000000..5792a1f --- /dev/null +++ b/lib/mp-compiler/parse-ts.js @@ -0,0 +1,84 @@ +let ts +try { + ts = require('typescript') +} catch (e) { + +} + +function parseComponentsDeps (scriptContent) { + const sourceFile = ts.createSourceFile('test', scriptContent, ts.ScriptTarget.ESNext, /* setParentNodes */ true) + return delint(sourceFile) +} + +function delint (sourceFile) { + const compNames = {} + const importsMap = {} + + delintNode(sourceFile) + + function parseDecorator (node) { + // 只处理 @Component({components:{aaa}}) + if (node.expression.expression && node.expression.expression.escapedText === 'Component') { + const compArgs = node.expression.arguments + if (compArgs && compArgs.length === 1) { + const vueClassArg = compArgs[0] + if (vueClassArg.properties) { + vueClassArg.properties.forEach((classProp) => { + // 处理components属性 + if (classProp.name.escapedText === 'components') { + classProp.initializer.properties.forEach((comp) => { + let compName + switch (comp.kind) { + case ts.SyntaxKind.ShorthandPropertyAssignment: // {Comp} + compName = comp.name.escapedText + // report(comp, '1') + break + case ts.SyntaxKind.PropertyAssignment: // {a:Comp} + compName = comp.initializer.escapedText + // report(comp, '2') + break + } + compNames[compName] = true + }) + } + }) + } + } + } + } + + function delintNode (node) { + switch (node.kind) { + case ts.SyntaxKind.ImportDeclaration: + // 只处理 import Comp from 'xxx.vue' + if (node.importClause.name) { + importsMap[node.importClause.name.escapedText] = node.moduleSpecifier.text + } + // report(node, 'import') + break + case ts.SyntaxKind.Decorator: + parseDecorator(node) + break + } + + ts.forEachChild(node, delintNode) + } + + function report(node, message) { // eslint-disable-line + const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart()) + console.log(`${sourceFile.fileName} (${line + 1},${character + 1}): ${message}`) + } + + const components = {} + for (const k in compNames) { + if (importsMap.hasOwnProperty(k)) { + components[k] = importsMap[k] + } + } + return { + importsMap, + components + } +} + +module.exports = { parseComponentsDeps } diff --git a/package.json b/package.json index 68741d9..2851c72 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mpvue-loader", - "version": "1.0.9", + "version": "1.0.10", "description": "mpvue single-file component loader for Webpack", "main": "index.js", "repository": {