Skip to content

Instantly share code, notes, and snippets.

@kejun
Last active April 4, 2019 05:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kejun/44c1411433c59d763968270fedcf2b66 to your computer and use it in GitHub Desktop.
Save kejun/44c1411433c59d763968270fedcf2b66 to your computer and use it in GitHub Desktop.
test babel plugin
const babel = require('@babel/core');
const t = require('@babel/types');
const sampleCode = `\
import {uniq, extend, flatten, cloneDeep } from "lodash";
export default function Test() {
return (
<Sky.Card>
Test
<Wind.Button type="primary" loading>{intl('sas.baseline.inDetection')}</Wind.Button>
</Sky.Card>
);
}\
`;
const babelOptions = {
plugins: ["@babel/plugin-transform-react-jsx"]
};
const mapCommonComponents = {
'intl': '@ali/wind-intl',
};
const importComponents = {
Sky: [],
Wind: [],
common: [],
};
const visitor = {
ImportDeclaration(path, options={opts:{}}){
const { specifiers, source } = path.node;
if (!t.isImportDefaultSpecifier(specifiers[0]) ) {
const declarations = [];
specifiers.forEach(specifier => {
declarations.push(`import ${ specifier.local.name } from "${ source.value }/${ specifier.local.name}";`)
});
path.replaceWithMultiple(
babel.parse(declarations.join(''), babelOptions).program.body.map(c => ({
type: c.type,
specifiers: c.specifiers,
source: {
type: c.source.type,
value: c.source.value,
}
}))
);
}
},
JSXElement(path, { file }) {
const { node } = path;
const {object, property} = node.openingElement.name;
file.set('hasJSX', true);
if (object && ['Sky', 'Wind'].indexOf(object.name) + 1) {
let name = {
type: 'JSXIdentifier',
name: `${ object.name }${ property.name }`,
};
node.openingElement.name = name;
if (node.closingElement) {
node.closingElement.name = name;
}
importComponents[object.name].push(property.name);
path.replaceWith(node);
}
},
CallExpression({ node, scope }) {
if (node.callee.name in mapCommonComponents && !scope.hasBinding(node.callee.name)) {
importComponents.common.push(node.callee.name);
}
},
Program: {
enter (_, { file }) {
file.set('hasJSX', false);
},
exit({ node, scope }, { file }) {
let declaration;
if (importComponents.Sky.length) {
declaration = babel.parse(`import {${ importComponents.Sky.map(c => `${c} as Sky${c}`).join(',')}} from '@ali/sky'`);
node.body.unshift(declaration.program.body[0]);
}
if (importComponents.Wind.length) {
declaration = babel.parse(`import {${ importComponents.Wind.map(c => `${c} as Wind${c}`).join(',')}} from '@ali/wind'`);
node.body.unshift(declaration.program.body[0]);
}
[...new Set(importComponents.common)].forEach(name => {
node.body.unshift(babel.parse(`import ${ name } from '${ mapCommonComponents[name] }'`).program.body[0]);
});
if (file.get('hasJSX') && !scope.hasBinding('React')) {
declaration = babel.parse(`import React from 'react'`);
node.body.unshift(declaration.program.body[0]);
}
}
}
};
const result = babel.transform(sampleCode, {
plugins: babelOptions.plugins.concat([{
visitor
}])
});
console.log('\n\ninput:');
console.log(sampleCode);
console.log('\n\n\nout:');
console.log(result.code, '\n\n');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment