UNPKG

@morjs/plugin-compiler-alipay

Version:

mor complier plugin for alipay mini program

151 lines 7.79 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getModuleExportsName = void 0; const utils_1 = require("@morjs/utils"); const constants_1 = require("../constants"); /** * 从 module.exports.xxx 中提取 xxx 变量名 */ function getModuleExportsName(content) { const result = []; const regex = /module\.exports\.(\w+)/gim; const matchResult = content.match(regex); if (!matchResult) return result; matchResult.map((param) => { const name = param.split('.')[2]; result.push(name); }); return result; } exports.getModuleExportsName = getModuleExportsName; /** * 支付宝 sjs 文件转译 */ class AlipayCompilerSjsParserPlugin { constructor() { this.name = 'AlipayCompilerSjsParserPlugin'; } apply(runner) { runner.hooks.beforeRun.tap(this.name, () => { const { sourceType, target } = runner.userConfig; const isAlipaySimilarTarget = (0, constants_1.isSimilarTarget)(target); // 微信 DSL 转 支付宝或者类似小程序平台时的兼容逻辑 if (sourceType === utils_1.SourceTypes.wechat && isAlipaySimilarTarget) { return this.transformCommonjsToESModule(runner); } // 仅当 sjs 是 支付宝 源码 且 编译目标不是 支付宝小程序 时执行后续逻辑 if (sourceType !== utils_1.SourceTypes.alipay) return; if (sourceType === target) return; if (isAlipaySimilarTarget) return; runner.hooks.beforeBuildEntries.tap(this.name, (entryBuilder) => { this.entryBuilder = entryBuilder; }); runner.hooks.sjsParser.tap(this.name, (transformers, options) => { this.removeEsModuleMarkAndFixVoidZeroExpression(transformers); if (options.fileInfo.content.includes('import') || options.fileInfo.content.includes('export')) { this.transformESModuleToCommonjs(transformers); } return transformers; }); }); } /** * 微信转支付宝的场景下 ,wxs 内联文件中使用 module.exports.property 在支付宝中无法正常通过 name.var 调用, * 需要将这种场景下的导出进行拓展,增加 export default { property } * 这样在 webpack 打包时就可以正确导出 export default 文件 * NOTE: 该功能需要配合 cjsToEsmTransformer 使用,并放在 after 阶段 */ transformCommonjsToESModule(runner) { runner.hooks.sjsParser.tap(this.name, (transformers, options) => { if (options.fileInfo.content.includes('module.exports.') && !/module.exports( |\t|\n)*=/.test(options.fileInfo.content)) { // 提取 module.exports.var 中的变量名 const names = getModuleExportsName(options.fileInfo.content); if (names.length <= 0 || names.indexOf('default') > -1) return transformers; transformers.after.push((0, utils_1.tsTransformerFactory)((node, ctx) => { const factory = ctx.factory; if (utils_1.typescript.isSourceFile(node)) { return factory.updateSourceFile(node, [ ...node.statements, factory.createExportAssignment(void 0, void 0, void 0, factory.createObjectLiteralExpression(names.map((name) => factory.createShorthandPropertyAssignment(factory.createIdentifier(name))))) ]); } return node; })); } return transformers; }); } transformESModuleToCommonjs(transformers) { transformers.before.push((0, utils_1.tsTransformerFactory)((node, ctx) => { var _a; const factory = ctx.factory; /** * export {} 替换为 module.exports */ if (utils_1.typescript.isExportAssignment(node)) { const expression = node.expression; return factory.createExpressionStatement(factory.createBinaryExpression(factory.createPropertyAccessExpression(factory.createIdentifier('module'), factory.createIdentifier('exports')), factory.createToken(utils_1.typescript.SyntaxKind.EqualsToken), expression)); } /** * 处理 export default function name() {} 的情况 * 原因: 微信不支持 exports.default = name 这种语法,会报错 * 这里转换为 module.exports = function name() {} */ if (utils_1.typescript.isFunctionDeclaration(node) && ((_a = node.modifiers) === null || _a === void 0 ? void 0 : _a.length)) { const exportKeyword = node.modifiers[0]; const exportDefaultKeyword = node.modifiers[1]; if (utils_1.typescript.isToken(exportKeyword) && exportKeyword.kind === utils_1.typescript.SyntaxKind.ExportKeyword && utils_1.typescript.isToken(exportDefaultKeyword) && exportDefaultKeyword.kind === utils_1.typescript.SyntaxKind.DefaultKeyword) { return factory.createExpressionStatement(factory.createBinaryExpression(factory.createPropertyAccessExpression(factory.createIdentifier('module'), factory.createIdentifier('exports')), factory.createToken(utils_1.typescript.SyntaxKind.EqualsToken), factory.createFunctionExpression(undefined, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body))); } } return node; })); } /** * 支付宝小程序的 sjs 是 esmodule * 这里主要是用于处理 esmodule 转换为 commonjs 之后的兼容性问题 */ removeEsModuleMarkAndFixVoidZeroExpression(transformers) { transformers.after.push((0, utils_1.tsTransformerFactory)((node, ctx) => { /** * 移除表达式: * Object.defineProperty(exports, "__esModule", { value: true }) */ if (utils_1.typescript.isExpressionStatement(node) && utils_1.typescript.isCallExpression(node.expression) && utils_1.typescript.isPropertyAccessExpression(node.expression.expression) && utils_1.typescript.isIdentifier(node.expression.expression.expression) && node.expression.expression.expression.escapedText === 'Object' && utils_1.typescript.isIdentifier(node.expression.expression.name) && node.expression.expression.name.escapedText === 'defineProperty' && node.expression.arguments.length && utils_1.typescript.isIdentifier(node.expression.arguments[0]) && node.expression.arguments[0].escapedText === 'exports') { return undefined; } /* * 在微信的 wxs 中, 存在如下 BUG * x = a === void 0 ? [] : a 这样的三目运算符会返回 true 而不是表达式中的值 * 经过测试是 void 0 引起的,为了兼容这个问题,统一改为 undefined */ if (utils_1.typescript.isVoidExpression(node) && utils_1.typescript.isNumericLiteral(node.expression) && node.expression.text === '0') { return ctx.factory.createIdentifier('undefined'); } return node; })); } } exports.default = AlipayCompilerSjsParserPlugin; //# sourceMappingURL=SjsParserPlugin.js.map