'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var generate = _interopDefault(require('@babel/generator'));
var traverse = _interopDefault(require('@babel/traverse'));
var utils = _interopDefault(require('@babel/types'));
var parser = require('@babel/parser');
var loaderUtils = require('loader-utils');
var schemaUtils = require('schema-utils');
var schema = {
type: 'object',
properties: {
importPath: {
type: 'string'
},
isPage: {
"instanceof": 'Function'
},
componentName: {
type: 'string'
}
},
additionalProperties: false
};
function index (source) {
// @ts-ignore
var webpackEnv = this;
var options = loaderUtils.getOptions(webpackEnv);
schemaUtils.validate(schema, options, {
name: 'taro-inject-component-loader'
});
var _ref = options || {},
_ref$importPath = _ref.importPath,
importPath = _ref$importPath === void 0 ? '' : _ref$importPath,
_ref$componentName = _ref.componentName,
componentName = _ref$componentName === void 0 ? 'WebpackInjected' : _ref$componentName,
_ref$isPage = _ref.isPage,
isPage = _ref$isPage === void 0 ? defaultJudgePage : _ref$isPage; // 获取原始文件地址
var filePath = webpackEnv.resourcePath;
if (typeof isPage === 'function' && isPage(filePath)) {
// 生成 AST
var ast = parser.parse(source, {
sourceType: 'module',
plugins: ['jsx', 'typescript', 'classProperties']
}); // 如果有导入申明,则默认表示已手动导入了组件
var insert = false; // 保存所有顶层的声明
var declarations = new Map();
traverse(ast, {
// 查找是否有导入
ImportDeclaration: function ImportDeclaration(path) {
if (path.node.source.value === importPath) {
insert = true;
}
},
// 收集页面文件里的所有申明
// 类组件
ClassDeclaration: function ClassDeclaration(path) {
// 如果不是顶层的申明,则直接返回
if (path.parent.type !== 'Program') return;
var type = path.node.type;
var name = path.node.id.name;
declarations.set(name, type);
},
// 函数申明
FunctionDeclaration: function FunctionDeclaration(path) {
var _path$node$id;
// 如果不是顶层的申明,则直接返回
if (path.parent.type !== 'Program') return;
var type = path.node.type;
var name = (_path$node$id = path.node.id) == null ? void 0 : _path$node$id.name;
if (!name) return;
declarations.set(name, type);
},
// 表达式申明
VariableDeclaration: function VariableDeclaration(path) {
// 如果不是顶层的申明,则直接返回
if (path.parent.type !== 'Program') return;
path.node.declarations.forEach(function (declaration) {
var _declaration$init, _declaration$init3, _declaration$init4;
// const a = () => {}
if (((_declaration$init = declaration.init) == null ? void 0 : _declaration$init.type) === 'ArrowFunctionExpression') {
var _declaration$init2, _declaration$id;
var type = (_declaration$init2 = declaration.init) == null ? void 0 : _declaration$init2.type;
var name = (_declaration$id = declaration.id) == null ? void 0 : _declaration$id.name;
declarations.set(name, type);
} // const a = function(){}
if (((_declaration$init3 = declaration.init) == null ? void 0 : _declaration$init3.type) === 'FunctionExpression') {
var _type = declaration.init.type;
var _name = declaration.id.name;
declarations.set(_name, _type);
} // const a = class {}
if (((_declaration$init4 = declaration.init) == null ? void 0 : _declaration$init4.type) === 'ClassExpression') {
var _type2 = declaration.init.type;
var _name2 = declaration.id.name;
declarations.set(_name2, _type2);
}
});
}
});
if (!insert) {
// 记录组件插入状态
var state = {
importedDeclaration: false,
importedComponent: false
};
traverse(ast, {
// 添加申明
ImportDeclaration: function ImportDeclaration(path) {
if (!state.importedDeclaration) {
state.importedDeclaration = true;
path.insertBefore(utils.importDeclaration([utils.importDefaultSpecifier(utils.identifier('' + componentName))], utils.stringLiteral('' + importPath)));
}
},
// 默认导出的为页面组件
ExportDefaultDeclaration: function ExportDefaultDeclaration(path) {
// 如果默认导出的是函数
if (path.node.declaration.type === 'FunctionDeclaration') {
var mainFnBody = path.node.declaration.body.body;
var length = mainFnBody.length;
var last = mainFnBody[length - 1];
insertComponent(last, '' + componentName, state);
} // 默认导出箭头函数
if (path.node.declaration.type === 'ArrowFunctionExpression') {
// export default () => { return