UNPKG

@tarojs/plugin-generator

Version:
260 lines 9.87 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.updateBabelConfig = void 0; /* eslint-disable no-console */ /* eslint-disable brace-style */ const node_path_1 = __importDefault(require("node:path")); const generator_1 = __importDefault(require("@babel/generator")); const parser = __importStar(require("@babel/parser")); const traverse_1 = __importDefault(require("@babel/traverse")); const t = __importStar(require("@babel/types")); const dedent_1 = __importDefault(require("dedent")); const error_1 = require("../../utils/error"); const USE_BUILT_INS = 'useBuiltIns'; const config = (0, dedent_1.default)(` [ 'taro', { framework: 'react', ts: true, compiler: 'vite', ${USE_BUILT_INS}: process.env.TARO_ENV === 'h5' ? 'usage' : false } ] `); const modifyConfigError = new error_1.GeneratorError({ type: error_1.GeneratorErrorType.modifyConfig, message: (0, dedent_1.default)(`{ presets: [ [ 'taro', { framework: 'react', ts: true, compiler: 'vite', ${USE_BUILT_INS}: process.env.TARO_ENV === 'h5' ? 'usage' : false } ] ] }`), targetFile: 'babel.config.js', }); /** * 更新 babel.config.js * 主要处理模板里的写法 * 1. * ```js * module.exports = { * presets: [ * ['taro', { * framework: 'react', * ts: true, * compiler: 'webpack5', * }] * ] * } * ``` * 2. * ```js * const taroBabelConfig = { * framework: 'react', * ts: true, * compiler: 'webpack5', * } * module.exports = { * presets: [ * ['taro', taroBabelConfig] * ] * } * ``` */ async function updateBabelConfig(ctx) { const { fs } = ctx.helper; const babelConfigPath = node_path_1.default.join(ctx.paths.appPath, 'babel.config.js'); if (!(await fs.pathExists(babelConfigPath))) { await fs.writeFile(babelConfigPath, (0, dedent_1.default)(` module.exports = { presets: [ [ 'taro', { framework: 'react', ts: true, compiler: 'vite', ${USE_BUILT_INS}: process.env.TARO_ENV === 'h5' ? 'usage' : false } ] ] } `), { encoding: 'utf-8', flag: 'w' }); return; } const sourceCode = await fs.readFile(node_path_1.default.join(babelConfigPath), { encoding: 'utf-8' }); const ast = parser.parse(sourceCode, { sourceType: 'module', plugins: ['typescript'], }); (0, traverse_1.default)(ast, { AssignmentExpression: (expr) => { const { node } = expr; // module.exports = {} if (t.isMemberExpression(node.left) && t.isIdentifier(node.left.object) && node.left.object.name === 'module' && t.isIdentifier(node.left.property) && node.left.property.name === 'exports') { if (t.isObjectExpression(node.right)) { const presetsProp = node.right.properties.find((p) => t.isObjectProperty(p) && t.isIdentifier(p.key) && p.key.name === 'presets'); // 没有 presets 属性,直接创建 if (!presetsProp) { node.right.properties.push(t.objectProperty(t.identifier('presets'), t.arrayExpression([parser.parseExpression(config)]))); } // presets: [...] else if (t.isArrayExpression(presetsProp.value)) { handlePresets(presetsProp.value, expr); } // presets是变量的情况:presets: presets else if (t.isIdentifier(presetsProp.value)) { const variable = presetsProp.value.name; const binding = expr.scope.getBinding(variable); // const presets = [...] if (binding?.path.isVariableDeclarator()) { const init = binding.path.node.init; if (t.isArrayExpression(init)) { handlePresets(init, expr); } else { // 不是合法的 presets throw modifyConfigError; } } } } } }, }); await fs.writeFile(babelConfigPath, (0, generator_1.default)(ast).code, { encoding: 'utf-8', flag: 'w' }); console.log('✅ 更新 babel.config.js 成功\n'); } exports.updateBabelConfig = updateBabelConfig; /** * 处理 presets * 遍历 presets 数组 * - 如果元素是字符串,且是 'taro',则替换为 config * - 如果元素是数组,且第一个元素是字符串,且是 'taro',处理 options,插入 useBuiltIns 属性 * - 如果元素是变量,且变量的值是 'taro',则替换为 config,变量的值为数组,那么执行元素为数组的情况的处理逻辑 */ function handlePresets(presets, nodePath) { const { elements } = presets; let modified = false; /** * 处理 presets 里的 taro preset * - 元组第一项必须是 'taro' * - 元组第二项是对象或者变量 * - - 对象的情况,插入 useBuiltIns 属性。 * - - 变量的情况,找到变量定义的地方,如果值是对象,插入 useBuiltIns 属性 */ const handleTaroPreset = (preset) => { const first = preset.elements[0]; if (t.isStringLiteral(first) && first.value === 'taro') { const options = preset.elements[1]; if (t.isObjectExpression(options)) { insertUseBuiltInsProp(options); modified = true; } if (t.isIdentifier(options)) { const variable = options.name; const binding = nodePath.scope.getBinding(variable); if (binding?.path.isVariableDeclarator()) { // const options = init {} const init = binding.path.node.init; if (t.isObjectExpression(init)) { insertUseBuiltInsProp(init); modified = true; return; } } throw modifyConfigError; } } }; // 扫描 presets 数组每一项,presets 每一项可能是字符串、元组、变量 for (let i = 0; i < elements.length; i += 1) { if (modified) { break; } const el = elements[i]; // ["taro", ...] -> presets: [['taro', {...}], ...] if (t.isStringLiteral(el)) { if (el.value === 'taro') { elements[i] = parser.parseExpression(config); modified = true; } } // [["taro", {...}], ...] if (t.isArrayExpression(el)) { handleTaroPreset(el); } /** * const taroPreset = ['taro', {}]; * presets: [taroPreset, ...] */ if (t.isIdentifier(el)) { const variable = el.name; const binding = nodePath.scope.getBinding(variable); if (binding?.path.isVariableDeclarator()) { const init = binding.path.node.init; // const taroPreset = 'taro'; if (t.isStringLiteral(init) && init.value === 'taro') { binding.path.node.init = parser.parseExpression(config); } // const taroPreset = ['taro', {...}]; if (t.isArrayExpression(init)) { handleTaroPreset(init); } } } } if (!modified) { elements.push(parser.parseExpression(config)); } } function insertUseBuiltInsProp(obj) { const useBuiltInProp = obj.properties.find((p) => t.isObjectProperty(p) && t.isIdentifier(p.key) && p.key.name === USE_BUILT_INS); const builtInValue = parser.parseExpression("process.env.TARO_ENV === 'h5' ? 'usage' : false"); // 如果有 useBuiltIns 属性,直接替换值 if (useBuiltInProp) { useBuiltInProp.value = builtInValue; } // 没有 useBuiltIns 属性,直接添加 else { obj.properties.push(t.objectProperty(t.identifier(USE_BUILT_INS), builtInValue)); } } //# sourceMappingURL=babel.js.map