packages/build-plugin-alt/src/babelPluginMeta.ts (86 lines of code) (raw):
import { Visitor } from '@babel/traverse';
import * as BabelTypes from "@babel/types";
import template from '@babel/template';
interface IMeta {
pluginName: string;
meta: any;
};
interface IVisitorPass {
opts?: {
filename: string;
meta?: IMeta;
}
filename?: string;
}
interface IInjectVisitorPass extends IVisitorPass {
declarationName: string;
meta?: IMeta;
cache: {
pluginNameAssignmentExists: boolean;
metaAssignmentExists: boolean;
}
}
const addInfoComment = (node) => {
BabelTypes.addComment(node, 'leading', ' Generated By Ali Lowcode Tools ');
}
const injectMetaVisitor: Visitor<IInjectVisitorPass> = {
AssignmentExpression(path, pass) {
const left = path.node.left;
if (BabelTypes.isMemberExpression(left) && BabelTypes.isIdentifier(left.object) && left.object.name === pass.declarationName) {
const property = left.property;
if (
(BabelTypes.isIdentifier(property) && property.name === 'pluginName') ||
(BabelTypes.isStringLiteral(property) && property.value === 'pluginName')
) {
const meta = pass.meta;
pass.cache.pluginNameAssignmentExists = true;
if (meta?.pluginName) {
path.node.right = BabelTypes.stringLiteral(meta.pluginName);
addInfoComment(path.node);
}
}
if (
(BabelTypes.isIdentifier(property) && property.name === 'meta') ||
(BabelTypes.isStringLiteral(property) && property.value === 'meta')
) {
const meta = pass.meta;
pass.cache.metaAssignmentExists = true;
if (meta?.meta) {
const generateAst = template(`const a = ${JSON.stringify(meta.meta)}`)() as BabelTypes.VariableDeclaration;
path.node.right = generateAst.declarations[0].init;
addInfoComment(path.node);
}
}
}
}
}
export default function (babel: { types: typeof BabelTypes }): {
visitor: Visitor<IVisitorPass>
} {
const { types: t } = babel;
const cache = {
pluginNameAssignmentExists: false,
metaAssignmentExists: false,
};
return {
visitor: {
ExportDefaultDeclaration(path, state) {
// 如果不是入口文件,则不做任何处理
if (state.opts.filename !== state.filename) return;
if (t.isIdentifier(path.node.declaration)) {
const declarationName = path.node.declaration.name;
path.parentPath.traverse(injectMetaVisitor, { ...state.opts, declarationName, cache })
if (!cache.pluginNameAssignmentExists && state.opts?.meta?.pluginName) {
const generatedNode = template(`${declarationName}.pluginName = "${state.opts?.meta?.pluginName}"`)();
addInfoComment(generatedNode);
path.insertBefore(generatedNode);
}
if (!cache.metaAssignmentExists && state.opts?.meta?.meta) {
const generatedNode = template(`${declarationName}.meta = ${JSON.stringify(state.opts?.meta?.meta)}`)();
addInfoComment(generatedNode);
path.insertBefore(generatedNode);
}
}
},
}
};
}