vite-plugin-vue-wizard
Version:
Wrapper for automatic add toNative() for vue-facing-decorator
98 lines (87 loc) • 3.18 kB
text/typescript
import { transformSync } from '@babel/core';
const myBabelPlugin = function () {
return {
visitor: {
ImportDeclaration(a: any) {
if (a.node.source.value === 'vue-facing-decorator') {
const specifiers = a.node.specifiers;
const hasToNative = specifiers.map((v: any) => v.imported.name).includes('toNative');
if (!hasToNative) {
specifiers.push({
type: 'ImportSpecifier',
importKind: 'value',
imported: {
type: 'Identifier',
name: 'toNative'
},
local: {
type: 'Identifier',
name: 'toNative'
}
});
}
}
},
ExportDefaultDeclaration(a: any) {
const declaration = a.node.declaration;
if (declaration.type !== 'ClassDeclaration') {
console.log('Skip class transform!', declaration.type);
return;
}
a.node.declaration = {
type: 'CallExpression',
callee: {
type: 'Identifier',
name: 'toNative',
},
arguments: [
{
type: 'Identifier',
name: declaration.id.name,
}
]
};
const parent = a.parent;
const index = parent.body.map((v: any) => v.type).indexOf('ExportDefaultDeclaration');
parent.body.splice(index, 0, declaration);
}
}
};
};
function convertTsCode(oldCode: string) {
if (!oldCode.includes('vue-facing-decorator')) {
return '';
}
const transformResult = transformSync(oldCode, {
parserOpts: {
sourceType: 'module',
plugins: ['typescript', 'decorators-legacy']
},
plugins: [myBabelPlugin]
});
if (transformResult) {
return transformResult.code;
}
}
const vueWizard = () => ({
name: 'vite-plugin-vue-wizard',
transform(content: string, path: string) {
if (path.includes('node_modules')) {
return;
}
let flag = false;
function replacer(...matches: string[]): string {
const result = convertTsCode(matches[2]);
if (result) {
flag = true;
}
return matches[1] + result + matches[3];
}
const replaced = content.replace(/(<script[^>]*>\s*)([^]+?)(\s*<\/script>)/g, replacer);
if (flag) {
// console.log(replaced);
return { code: replaced };
}
}
});
export default vueWizard;