"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _path = require("path"); var _helperModuleImports = require("@babel/helper-module-imports"); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function transCamel(_str, symbol) { const str = _str[0].toLowerCase() + _str.substr(1); return str.replace(/([A-Z])/g, $1 => `${symbol}${$1.toLowerCase()}`); } function winPath(path) { return path.replace(/\\/g, '/'); } function normalizeCustomName(originCustomName) { // If set to a string, treat it as a JavaScript source file path. if (typeof originCustomName === 'string') { // eslint-disable-next-line import/no-dynamic-require const customNameExports = require(originCustomName); return typeof customNameExports === 'function' ? customNameExports : customNameExports.default; } return originCustomName; } class Plugin { constructor(libraryName, libraryDirectory, style, styleLibraryDirectory, customStyleName, camel2DashComponentName, camel2UnderlineComponentName, fileName, customName, transformToDefaultImport, types, index = 0) { this.libraryName = libraryName; this.libraryDirectory = typeof libraryDirectory === 'undefined' ? 'lib' : libraryDirectory; this.camel2DashComponentName = typeof camel2DashComponentName === 'undefined' ? true : camel2DashComponentName; this.camel2UnderlineComponentName = camel2UnderlineComponentName; this.style = style || false; this.styleLibraryDirectory = styleLibraryDirectory; this.customStyleName = normalizeCustomName(customStyleName); this.fileName = fileName || ''; this.customName = normalizeCustomName(customName); this.transformToDefaultImport = typeof transformToDefaultImport === 'undefined' ? true : transformToDefaultImport; this.types = types; this.pluginStateKey = `importPluginState${index}`; } getPluginState(state) { if (!state[this.pluginStateKey]) { state[this.pluginStateKey] = {}; // eslint-disable-line } return state[this.pluginStateKey]; } importMethod(methodName, file, pluginState) { if (!pluginState.selectedMethods[methodName]) { const style = this.style, libraryDirectory = this.libraryDirectory; const transformedMethodName = this.camel2UnderlineComponentName // eslint-disable-line ? transCamel(methodName, '_') : this.camel2DashComponentName ? transCamel(methodName, '-') : methodName; const path = winPath(this.customName ? this.customName(transformedMethodName, file) : (0, _path.join)(this.libraryName, libraryDirectory, transformedMethodName, this.fileName) // eslint-disable-line ); pluginState.selectedMethods[methodName] = this.transformToDefaultImport // eslint-disable-line ? (0, _helperModuleImports.addDefault)(file.path, path, { nameHint: methodName }) : (0, _helperModuleImports.addNamed)(file.path, methodName, path); if (this.customStyleName) { const stylePath = winPath(this.customStyleName(transformedMethodName, file)); (0, _helperModuleImports.addSideEffect)(file.path, `${stylePath}`); } else if (this.styleLibraryDirectory) { const stylePath = winPath((0, _path.join)(this.libraryName, this.styleLibraryDirectory, transformedMethodName, this.fileName)); (0, _helperModuleImports.addSideEffect)(file.path, `${stylePath}`); } else if (style === true) { (0, _helperModuleImports.addSideEffect)(file.path, `${path}/style`); } else if (style === 'css') { (0, _helperModuleImports.addSideEffect)(file.path, `${path}/style/css`); } else if (typeof style === 'function') { const stylePath = style(path, file); if (stylePath) { (0, _helperModuleImports.addSideEffect)(file.path, stylePath); } } } return _objectSpread({}, pluginState.selectedMethods[methodName]); } buildExpressionHandler(node, props, path, state) { const file = path && path.hub && path.hub.file || state && state.file; const types = this.types; const pluginState = this.getPluginState(state); props.forEach(prop => { if (!types.isIdentifier(node[prop])) return; if (pluginState.specified[node[prop].name] && types.isImportSpecifier(path.scope.getBinding(node[prop].name).path)) { node[prop] = this.importMethod(pluginState.specified[node[prop].name], file, pluginState); // eslint-disable-line } }); } buildDeclaratorHandler(node, prop, path, state) { const file = path && path.hub && path.hub.file || state && state.file; const types = this.types; const pluginState = this.getPluginState(state); const checkScope = targetNode => pluginState.specified[targetNode.name] && // eslint-disable-line path.scope.hasBinding(targetNode.name) && // eslint-disable-line path.scope.getBinding(targetNode.name).path.type === 'ImportSpecifier'; // eslint-disable-line if (types.isIdentifier(node[prop]) && checkScope(node[prop])) { node[prop] = this.importMethod(pluginState.specified[node[prop].name], file, pluginState); // eslint-disable-line } else if (types.isSequenceExpression(node[prop])) { node[prop].expressions.forEach((expressionNode, index) => { if (types.isIdentifier(expressionNode) && checkScope(expressionNode)) { node[prop].expressions[index] = this.importMethod(pluginState.specified[expressionNode.name], file, pluginState); // eslint-disable-line } }); } } ProgramEnter(path, state) { const pluginState = this.getPluginState(state); pluginState.specified = Object.create(null); pluginState.libraryObjs = Object.create(null); pluginState.selectedMethods = Object.create(null); pluginState.pathsToRemove = []; } ProgramExit(path, state) { this.getPluginState(state).pathsToRemove.forEach(p => !p.removed && p.remove()); } ImportDeclaration(path, state) { const node = path.node; // path maybe removed by prev instances. if (!node) return; const value = node.source.value; const libraryName = this.libraryName; const types = this.types; const pluginState = this.getPluginState(state); if (value === libraryName) { node.specifiers.forEach(spec => { if (types.isImportSpecifier(spec)) { pluginState.specified[spec.local.name] = spec.imported.name; } else { pluginState.libraryObjs[spec.local.name] = true; } }); pluginState.pathsToRemove.push(path); } } CallExpression(path, state) { const node = path.node; const file = path && path.hub && path.hub.file || state && state.file; const name = node.callee.name; const types = this.types; const pluginState = this.getPluginState(state); if (types.isIdentifier(node.callee)) { if (pluginState.specified[name]) { node.callee = this.importMethod(pluginState.specified[name], file, pluginState); } } node.arguments = node.arguments.map(arg => { const argName = arg.name; if (pluginState.specified[argName] && path.scope.hasBinding(argName) && path.scope.getBinding(argName).path.type === 'ImportSpecifier') { return this.importMethod(pluginState.specified[argName], file, pluginState); } return arg; }); } MemberExpression(path, state) { const node = path.node; const file = path && path.hub && path.hub.file || state && state.file; const pluginState = this.getPluginState(state); // multiple instance check. if (!node.object || !node.object.name) return; if (pluginState.libraryObjs[node.object.name]) { // antd.Button -> _Button path.replaceWith(this.importMethod(node.property.name, file, pluginState)); } else if (pluginState.specified[node.object.name] && path.scope.hasBinding(node.object.name)) { const _path$scope$getBindin = path.scope.getBinding(node.object.name), scope = _path$scope$getBindin.scope; // global variable in file scope if (scope.path.parent.type === 'File') { node.object = this.importMethod(pluginState.specified[node.object.name], file, pluginState); } } } Property(path, state) { const node = path.node; this.buildDeclaratorHandler(node, 'value', path, state); } VariableDeclarator(path, state) { const node = path.node; this.buildDeclaratorHandler(node, 'init', path, state); } ArrayExpression(path, state) { const node = path.node; const props = node.elements.map((_, index) => index); this.buildExpressionHandler(node.elements, props, path, state); } LogicalExpression(path, state) { const node = path.node; this.buildExpressionHandler(node, ['left', 'right'], path, state); } ConditionalExpression(path, state) { const node = path.node; this.buildExpressionHandler(node, ['test', 'consequent', 'alternate'], path, state); } IfStatement(path, state) { const node = path.node; this.buildExpressionHandler(node, ['test'], path, state); this.buildExpressionHandler(node.test, ['left', 'right'], path, state); } ExpressionStatement(path, state) { const node = path.node; const types = this.types; if (types.isAssignmentExpression(node.expression)) { this.buildExpressionHandler(node.expression, ['right'], path, state); } } ReturnStatement(path, state) { const node = path.node; this.buildExpressionHandler(node, ['argument'], path, state); } ExportDefaultDeclaration(path, state) { const node = path.node; this.buildExpressionHandler(node, ['declaration'], path, state); } BinaryExpression(path, state) { const node = path.node; this.buildExpressionHandler(node, ['left', 'right'], path, state); } NewExpression(path, state) { const node = path.node; this.buildExpressionHandler(node, ['callee'], path, state); const argumentsProps = node.arguments.map((_, index) => index); this.buildExpressionHandler(node.arguments, argumentsProps, path, state); } SwitchStatement(path, state) { const node = path.node; this.buildExpressionHandler(node, ['discriminant'], path, state); } SwitchCase(path, state) { const node = path.node; this.buildExpressionHandler(node, ['test'], path, state); } ClassDeclaration(path, state) { const node = path.node; this.buildExpressionHandler(node, ['superClass'], path, state); } } exports.default = Plugin;