1- import syntaxJsx from '@babel/plugin-syntax-jsx' ;
21import * as t from '@babel/types' ;
2+ import * as BabelCore from '@babel/core' ;
3+ import syntaxJsx from '@babel/plugin-syntax-jsx' ;
4+ import { addNamed , isModule , addNamespace } from '@babel/helper-module-imports' ;
35import { NodePath } from '@babel/traverse' ;
46import tranformVueJSX from './transform-vue-jsx' ;
57import sugarFragment from './sugar-fragment' ;
6- import { JSX_HELPER_KEY } from './utils' ;
78
89export type State = {
910 get : ( name : string ) => any ;
@@ -20,59 +21,88 @@ export interface Opts {
2021
2122export type ExcludesBoolean = < T > ( x : T | false | true ) => x is T ;
2223
23- export default ( ) => ( {
24+ const hasJSX = ( parentPath : NodePath ) => {
25+ let fileHasJSX = false ;
26+
27+ parentPath . traverse ( {
28+ JSXElement ( path ) { // skip ts error
29+ fileHasJSX = true ;
30+ path . stop ( ) ;
31+ } ,
32+ JSXFragment ( path ) {
33+ fileHasJSX = true ;
34+ path . stop ( ) ;
35+ } ,
36+ } ) ;
37+
38+ return fileHasJSX ;
39+ } ;
40+
41+ export default ( { types } : typeof BabelCore ) => ( {
2442 name : 'babel-plugin-jsx' ,
2543 inherits : syntaxJsx ,
2644 visitor : {
45+ ...tranformVueJSX ,
46+ ...sugarFragment ,
2747 Program : {
28- exit ( path : NodePath < t . Program > , state : State ) {
29- const helpers : Set < string > = state . get ( JSX_HELPER_KEY ) ;
30- if ( ! helpers ) {
31- return ;
32- }
33-
34- const body = path . get ( 'body' ) ;
35- const specifierNames = new Set < string > ( ) ;
36- body
37- . filter ( ( nodePath ) => t . isImportDeclaration ( nodePath . node )
38- && nodePath . node . source . value === 'vue' )
39- . forEach ( ( nodePath ) => {
40- let shouldKeep = false ;
41- const newSpecifiers = ( nodePath . node as t . ImportDeclaration ) . specifiers
42- . filter ( ( specifier ) => {
43- if ( t . isImportSpecifier ( specifier ) ) {
44- const { imported, local } = specifier ;
45- if ( local . name === imported . name ) {
46- specifierNames . add ( imported . name ) ;
47- return false ;
48- }
49- return true ;
48+ enter ( path : NodePath , state : State ) {
49+ if ( hasJSX ( path ) ) {
50+ const importNames = [
51+ 'createVNode' ,
52+ 'Fragment' ,
53+ 'resolveComponent' ,
54+ 'withDirectives' ,
55+ 'vShow' ,
56+ 'vModelSelect' ,
57+ 'vModelText' ,
58+ 'vModelCheckbox' ,
59+ 'vModelRadio' ,
60+ 'vModelText' ,
61+ 'vModelDynamic' ,
62+ 'resolveDirective' ,
63+ 'mergeProps' ,
64+ 'createTextVNode' ,
65+ ] ;
66+ if ( isModule ( path ) ) {
67+ // import { createVNode } from "vue";
68+ const importMap : Record < string , t . Identifier > = { } ;
69+ importNames . forEach ( ( name ) => {
70+ state . set ( name , ( ) => {
71+ if ( importMap [ name ] ) {
72+ return types . cloneDeep ( importMap [ name ] ) ;
5073 }
51- if ( t . isImportNamespaceSpecifier ( specifier ) ) {
52- // should keep when `import * as Vue from 'vue'`
53- shouldKeep = true ;
74+ const identifier = addNamed (
75+ path ,
76+ name ,
77+ 'vue' ,
78+ {
79+ ensureLiveReference : true ,
80+ } ,
81+ ) ;
82+ importMap [ name ] = identifier ;
83+ return identifier ;
84+ } ) ;
85+ } ) ;
86+ } else {
87+ // var _vue = require('vue');
88+ let sourceName = '' ;
89+ importNames . forEach ( ( name ) => {
90+ state . set ( name , ( ) => {
91+ if ( ! sourceName ) {
92+ sourceName = addNamespace (
93+ path ,
94+ 'vue' ,
95+ {
96+ ensureLiveReference : true ,
97+ } ,
98+ ) . name ;
5499 }
55- return false ;
100+ return t . memberExpression ( t . identifier ( sourceName ) , t . identifier ( name ) ) ;
56101 } ) ;
57-
58- if ( newSpecifiers . length ) {
59- nodePath . replaceWith ( t . importDeclaration ( newSpecifiers , t . stringLiteral ( 'vue' ) ) ) ;
60- } else if ( ! shouldKeep ) {
61- nodePath . remove ( ) ;
62- }
63- } ) ;
64-
65- const importedHelperKeys = new Set ( [ ...specifierNames , ...helpers ] ) ;
66- const specifiers : t . ImportSpecifier [ ] = [ ...importedHelperKeys ] . map (
67- ( imported ) => t . importSpecifier (
68- t . identifier ( imported ) , t . identifier ( imported ) ,
69- ) ,
70- ) ;
71- const expression = t . importDeclaration ( specifiers , t . stringLiteral ( 'vue' ) ) ;
72- path . unshiftContainer ( 'body' , expression ) ;
102+ } ) ;
103+ }
104+ }
73105 } ,
74106 } ,
75- ...tranformVueJSX ( ) ,
76- ...sugarFragment ( ) ,
77107 } ,
78108} ) ;
0 commit comments