UNPKG

babel-plugin-codegen

Version:
201 lines (168 loc) 5.34 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getReplacers = getReplacers; var _helpers = require("./helpers"); function getReplacers(babel) { function asProgram(path, fileOpts) { var _result$code; const result = babel.transformFromAstSync(path.node, path.getSource(), { filename: fileOpts.filename, plugins: fileOpts.plugins, presets: fileOpts.presets }); // istanbul ignore next because this should never happen, but TypeScript needs me to handle it const code = (_result$code = result == null ? void 0 : result.code) != null ? _result$code : ''; const replacement = (0, _helpers.getReplacement)({ code, fileOpts }, babel); path.node.body = Array.isArray(replacement) ? replacement : [replacement]; } function asImportDeclaration(path, fileOpts) { var _path$node$source$lea, _path$node$source$lea2; const filename = (0, _helpers.getFilename)(fileOpts); const codegenComment = (_path$node$source$lea = path.node.source.leadingComments) == null ? void 0 : (_path$node$source$lea2 = _path$node$source$lea.find(_helpers.isCodegenComment)) == null ? void 0 : _path$node$source$lea2.value.trim(); // istanbul ignore next because we don't even call `asImportDeclaration` if // there's not a codegen comment, but TypeScript gets mad otherwise if (!codegenComment) return; const { code, resolvedPath } = (0, _helpers.resolveModuleContents)({ filename, module: path.node.source.value }); let args; if (codegenComment !== 'codegen') { args = (0, _helpers.requireFromString)(`module.exports = [${codegenComment.replace(/codegen\((.*)\)/, '$1').trim()}]`, filename); } (0, _helpers.replace)({ path, code, fileOpts: { ...fileOpts, filename: resolvedPath }, args }, babel); } // eslint-disable-next-line complexity function asIdentifier(path, fileOpts) { const targetPath = path.parentPath; switch (targetPath.type) { case 'TaggedTemplateExpression': { return asTag(targetPath, fileOpts); } case 'CallExpression': { const isCallee = targetPath.get('callee') === path; if (isCallee) { return asFunction(targetPath, fileOpts); } else { return false; } } case 'JSXOpeningElement': { const jsxElement = targetPath.parentPath; return asJSX(jsxElement, fileOpts); } case 'JSXClosingElement': { // ignore the closing element // but don't mark as unhandled (return false) // we already handled the opening element return true; } case 'MemberExpression': { const callPath = targetPath.parentPath; // istanbul ignore if (don't know when this could happen) if (!callPath) return false; const isRequireCall = (0, _helpers.isPropertyCall)(callPath, 'require'); if (isRequireCall) { return asImportCall(callPath, fileOpts); } else { return false; } } default: { return false; } } } function asImportCall(path, fileOpts) { const [source, ...args] = path.get('arguments'); const { code, resolvedPath } = (0, _helpers.resolveModuleContents)({ filename: (0, _helpers.getFilename)(fileOpts), module: source.node.value }); const argValues = args.map(a => { const result = a.evaluate(); if (!result.confident) { throw new Error('codegen cannot determine the value of an argument in codegen.require'); } return result.value; }); (0, _helpers.replace)({ path, code, fileOpts: { ...fileOpts, filename: resolvedPath }, args: argValues }, babel); } function asTag(path, fileOpts) { const code = path.get('quasi').evaluate().value; if (!code) { throw path.buildCodeFrameError('Unable to determine the value of your codegen string', Error); } (0, _helpers.replace)({ path, code, fileOpts }, babel); } function asFunction(path, fileOpts) { const argumentsPaths = path.get('arguments'); const code = argumentsPaths[0].evaluate().value; (0, _helpers.replace)({ path: argumentsPaths[0].parentPath, code, fileOpts }, babel); } function asJSX(path, fileOpts) { const children = path.get('children'); const container = children[0]; const expression = container.node.expression; // @ts-expect-error value isn't on all nodes, but we will assume nobody // uses this for anything but the right kind of nodes... let code = expression.value; if (expression.type === 'TemplateLiteral') { code = container.get('expression').evaluate().value; } (0, _helpers.replace)({ path: container.parentPath, code, fileOpts }, babel); } return { asTag, asJSX, asFunction, asProgram, asImportCall, asImportDeclaration, asIdentifier }; } /* eslint @typescript-eslint/no-explicit-any: "off", complexity: ["error", 8], max-lines-per-function: ["error", 250], */