mirror of
				https://github.com/vuejs/babel-plugin-jsx.git
				synced 2025-10-31 09:22:19 +08:00 
			
		
		
		
	feat: should merge generated imports (#274)
This commit is contained in:
		| @@ -32,6 +32,7 @@ module.exports = { | |||||||
|     '@typescript-eslint/explicit-module-boundary-types': [0], |     '@typescript-eslint/explicit-module-boundary-types': [0], | ||||||
|     '@typescript-eslint/no-explicit-any': [0], |     '@typescript-eslint/no-explicit-any': [0], | ||||||
|     '@typescript-eslint/no-non-null-assertion': [0], |     '@typescript-eslint/no-non-null-assertion': [0], | ||||||
|  |     'max-len': [0], | ||||||
|   }, |   }, | ||||||
|   settings: { |   settings: { | ||||||
|     'import/resolver': { |     'import/resolver': { | ||||||
|   | |||||||
| @@ -28,7 +28,7 @@ export interface VueJSXPluginOptions { | |||||||
|  |  | ||||||
| export type ExcludesBoolean = <T>(x: T | false | true) => x is T; | export type ExcludesBoolean = <T>(x: T | false | true) => x is T; | ||||||
|  |  | ||||||
| const hasJSX = (parentPath: NodePath) => { | const hasJSX = (parentPath: NodePath<t.Program>) => { | ||||||
|   let fileHasJSX = false; |   let fileHasJSX = false; | ||||||
|   parentPath.traverse({ |   parentPath.traverse({ | ||||||
|     JSXElement(path) { // skip ts error |     JSXElement(path) { // skip ts error | ||||||
| @@ -51,7 +51,7 @@ export default ({ types }: typeof BabelCore) => ({ | |||||||
|     ...tranformVueJSX, |     ...tranformVueJSX, | ||||||
|     ...sugarFragment, |     ...sugarFragment, | ||||||
|     Program: { |     Program: { | ||||||
|       enter(path: NodePath, state: State) { |       enter(path: NodePath<t.Program>, state: State) { | ||||||
|         if (hasJSX(path)) { |         if (hasJSX(path)) { | ||||||
|           const importNames = [ |           const importNames = [ | ||||||
|             'createVNode', |             'createVNode', | ||||||
| @@ -131,6 +131,33 @@ export default ({ types }: typeof BabelCore) => ({ | |||||||
|           } |           } | ||||||
|         } |         } | ||||||
|       }, |       }, | ||||||
|  |       exit(path: NodePath<t.Program>) { | ||||||
|  |         const body = path.get('body') as NodePath[]; | ||||||
|  |         const specifiersMap = new Map<string, t.ImportSpecifier>(); | ||||||
|  |  | ||||||
|  |         body.filter((nodePath) => t.isImportDeclaration(nodePath.node) | ||||||
|  |           && nodePath.node.source.value === 'vue') | ||||||
|  |           .forEach((nodePath) => { | ||||||
|  |             const { specifiers } = nodePath.node as t.ImportDeclaration; | ||||||
|  |             let shouldRemove = false; | ||||||
|  |             specifiers.forEach((specifier) => { | ||||||
|  |               if (!specifier.loc && t.isImportSpecifier(specifier) && t.isIdentifier(specifier.imported)) { | ||||||
|  |                 specifiersMap.set(specifier.imported.name, specifier); | ||||||
|  |                 shouldRemove = true; | ||||||
|  |               } | ||||||
|  |             }); | ||||||
|  |             if (shouldRemove) { | ||||||
|  |               nodePath.remove(); | ||||||
|  |             } | ||||||
|  |           }); | ||||||
|  |  | ||||||
|  |         const specifiers = [...specifiersMap.keys()].map( | ||||||
|  |           (imported) => specifiersMap.get(imported)!, | ||||||
|  |         ); | ||||||
|  |         if (specifiers.length) { | ||||||
|  |           path.unshiftContainer('body', t.importDeclaration(specifiers, t.stringLiteral('vue'))); | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|     }, |     }, | ||||||
|   }, |   }, | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -1,9 +1,7 @@ | |||||||
| // Jest Snapshot v1, https://goo.gl/fbAQLP | // Jest Snapshot v1, https://goo.gl/fbAQLP | ||||||
|  |  | ||||||
| exports[`MereProps Order: MereProps Order 1`] = ` | exports[`MereProps Order: MereProps Order 1`] = ` | ||||||
| "import { createVNode as _createVNode } from \\"vue\\"; | "import { createVNode as _createVNode, mergeProps as _mergeProps, createTextVNode as _createTextVNode } from \\"vue\\"; | ||||||
| import { mergeProps as _mergeProps } from \\"vue\\"; |  | ||||||
| import { createTextVNode as _createTextVNode } from \\"vue\\"; |  | ||||||
|  |  | ||||||
| _createVNode(\\"button\\", _mergeProps({ | _createVNode(\\"button\\", _mergeProps({ | ||||||
|   \\"loading\\": true |   \\"loading\\": true | ||||||
| @@ -27,24 +25,19 @@ createVNode('div', null, ['Without JSX should work']);" | |||||||
| `; | `; | ||||||
|  |  | ||||||
| exports[`Without props: Without props 1`] = ` | exports[`Without props: Without props 1`] = ` | ||||||
| "import { createVNode as _createVNode } from \\"vue\\"; | "import { createVNode as _createVNode, createTextVNode as _createTextVNode } from \\"vue\\"; | ||||||
| import { createTextVNode as _createTextVNode } from \\"vue\\"; |  | ||||||
|  |  | ||||||
| _createVNode(\\"a\\", null, [_createTextVNode(\\"a\\")]);" | _createVNode(\\"a\\", null, [_createTextVNode(\\"a\\")]);" | ||||||
| `; | `; | ||||||
|  |  | ||||||
| exports[`custom directive: custom directive 1`] = ` | exports[`custom directive: custom directive 1`] = ` | ||||||
| "import { withDirectives as _withDirectives } from \\"vue\\"; | "import { withDirectives as _withDirectives, createVNode as _createVNode, resolveDirective as _resolveDirective, resolveComponent as _resolveComponent } from \\"vue\\"; | ||||||
| import { createVNode as _createVNode } from \\"vue\\"; |  | ||||||
| import { resolveDirective as _resolveDirective } from \\"vue\\"; |  | ||||||
| import { resolveComponent as _resolveComponent } from \\"vue\\"; |  | ||||||
|  |  | ||||||
| _withDirectives(_createVNode(_resolveComponent(\\"A\\"), null, null, 512), [[_resolveDirective(\\"cus\\"), x]]);" | _withDirectives(_createVNode(_resolveComponent(\\"A\\"), null, null, 512), [[_resolveDirective(\\"cus\\"), x]]);" | ||||||
| `; | `; | ||||||
|  |  | ||||||
| exports[`disable object slot syntax with defaultSlot: defaultSlot 1`] = ` | exports[`disable object slot syntax with defaultSlot: defaultSlot 1`] = ` | ||||||
| "import { createVNode as _createVNode } from \\"vue\\"; | "import { createVNode as _createVNode, resolveComponent as _resolveComponent } from \\"vue\\"; | ||||||
| import { resolveComponent as _resolveComponent } from \\"vue\\"; |  | ||||||
|  |  | ||||||
| _createVNode(_resolveComponent(\\"Badge\\"), null, { | _createVNode(_resolveComponent(\\"Badge\\"), null, { | ||||||
|   default: () => [slots.default()], |   default: () => [slots.default()], | ||||||
| @@ -53,9 +46,7 @@ _createVNode(_resolveComponent(\\"Badge\\"), null, { | |||||||
| `; | `; | ||||||
|  |  | ||||||
| exports[`dynamic type in input: dynamic type in input 1`] = ` | exports[`dynamic type in input: dynamic type in input 1`] = ` | ||||||
| "import { withDirectives as _withDirectives } from \\"vue\\"; | "import { withDirectives as _withDirectives, createVNode as _createVNode, vModelDynamic as _vModelDynamic } from \\"vue\\"; | ||||||
| import { createVNode as _createVNode } from \\"vue\\"; |  | ||||||
| import { vModelDynamic as _vModelDynamic } from \\"vue\\"; |  | ||||||
|  |  | ||||||
| _withDirectives(_createVNode(\\"input\\", { | _withDirectives(_createVNode(\\"input\\", { | ||||||
|   \\"type\\": type, |   \\"type\\": type, | ||||||
| @@ -64,9 +55,7 @@ _withDirectives(_createVNode(\\"input\\", { | |||||||
| `; | `; | ||||||
|  |  | ||||||
| exports[`input[type="checkbox"]: input[type="checkbox"] 1`] = ` | exports[`input[type="checkbox"]: input[type="checkbox"] 1`] = ` | ||||||
| "import { withDirectives as _withDirectives } from \\"vue\\"; | "import { withDirectives as _withDirectives, createVNode as _createVNode, vModelCheckbox as _vModelCheckbox } from \\"vue\\"; | ||||||
| import { createVNode as _createVNode } from \\"vue\\"; |  | ||||||
| import { vModelCheckbox as _vModelCheckbox } from \\"vue\\"; |  | ||||||
|  |  | ||||||
| _withDirectives(_createVNode(\\"input\\", { | _withDirectives(_createVNode(\\"input\\", { | ||||||
|   \\"type\\": \\"checkbox\\", |   \\"type\\": \\"checkbox\\", | ||||||
| @@ -75,10 +64,7 @@ _withDirectives(_createVNode(\\"input\\", { | |||||||
| `; | `; | ||||||
|  |  | ||||||
| exports[`input[type="radio"]: input[type="radio"] 1`] = ` | exports[`input[type="radio"]: input[type="radio"] 1`] = ` | ||||||
| "import { withDirectives as _withDirectives } from \\"vue\\"; | "import { withDirectives as _withDirectives, createVNode as _createVNode, vModelRadio as _vModelRadio, Fragment as _Fragment } from \\"vue\\"; | ||||||
| import { createVNode as _createVNode } from \\"vue\\"; |  | ||||||
| import { vModelRadio as _vModelRadio } from \\"vue\\"; |  | ||||||
| import { Fragment as _Fragment } from \\"vue\\"; |  | ||||||
|  |  | ||||||
| _createVNode(_Fragment, null, [_withDirectives(_createVNode(\\"input\\", { | _createVNode(_Fragment, null, [_withDirectives(_createVNode(\\"input\\", { | ||||||
|   \\"type\\": \\"radio\\", |   \\"type\\": \\"radio\\", | ||||||
| @@ -94,9 +80,7 @@ _createVNode(_Fragment, null, [_withDirectives(_createVNode(\\"input\\", { | |||||||
| `; | `; | ||||||
|  |  | ||||||
| exports[`input[type="text"] .lazy modifier: input[type="text"] .lazy modifier 1`] = ` | exports[`input[type="text"] .lazy modifier: input[type="text"] .lazy modifier 1`] = ` | ||||||
| "import { withDirectives as _withDirectives } from \\"vue\\"; | "import { withDirectives as _withDirectives, createVNode as _createVNode, vModelText as _vModelText } from \\"vue\\"; | ||||||
| import { createVNode as _createVNode } from \\"vue\\"; |  | ||||||
| import { vModelText as _vModelText } from \\"vue\\"; |  | ||||||
|  |  | ||||||
| _withDirectives(_createVNode(\\"input\\", { | _withDirectives(_createVNode(\\"input\\", { | ||||||
|   \\"onUpdate:modelValue\\": $event => test = $event |   \\"onUpdate:modelValue\\": $event => test = $event | ||||||
| @@ -106,9 +90,7 @@ _withDirectives(_createVNode(\\"input\\", { | |||||||
| `; | `; | ||||||
|  |  | ||||||
| exports[`input[type="text"]: input[type="text"] 1`] = ` | exports[`input[type="text"]: input[type="text"] 1`] = ` | ||||||
| "import { withDirectives as _withDirectives } from \\"vue\\"; | "import { withDirectives as _withDirectives, createVNode as _createVNode, vModelText as _vModelText } from \\"vue\\"; | ||||||
| import { createVNode as _createVNode } from \\"vue\\"; |  | ||||||
| import { vModelText as _vModelText } from \\"vue\\"; |  | ||||||
|  |  | ||||||
| _withDirectives(_createVNode(\\"input\\", { | _withDirectives(_createVNode(\\"input\\", { | ||||||
|   \\"onUpdate:modelValue\\": $event => test = $event |   \\"onUpdate:modelValue\\": $event => test = $event | ||||||
| @@ -116,8 +98,7 @@ _withDirectives(_createVNode(\\"input\\", { | |||||||
| `; | `; | ||||||
|  |  | ||||||
| exports[`override props multiple: multiple 1`] = ` | exports[`override props multiple: multiple 1`] = ` | ||||||
| "import { createVNode as _createVNode } from \\"vue\\"; | "import { createVNode as _createVNode, resolveComponent as _resolveComponent } from \\"vue\\"; | ||||||
| import { resolveComponent as _resolveComponent } from \\"vue\\"; |  | ||||||
|  |  | ||||||
| _createVNode(_resolveComponent(\\"A\\"), { | _createVNode(_resolveComponent(\\"A\\"), { | ||||||
|   \\"loading\\": true, |   \\"loading\\": true, | ||||||
| @@ -138,8 +119,7 @@ _createVNode(\\"div\\", a, null);" | |||||||
| `; | `; | ||||||
|  |  | ||||||
| exports[`passing object slots via JSX children multiple expressions: multiple expressions 1`] = ` | exports[`passing object slots via JSX children multiple expressions: multiple expressions 1`] = ` | ||||||
| "import { createVNode as _createVNode } from \\"vue\\"; | "import { createVNode as _createVNode, resolveComponent as _resolveComponent } from \\"vue\\"; | ||||||
| import { resolveComponent as _resolveComponent } from \\"vue\\"; |  | ||||||
|  |  | ||||||
| _createVNode(_resolveComponent(\\"A\\"), null, { | _createVNode(_resolveComponent(\\"A\\"), null, { | ||||||
|   default: () => [foo, bar], |   default: () => [foo, bar], | ||||||
| @@ -148,8 +128,7 @@ _createVNode(_resolveComponent(\\"A\\"), null, { | |||||||
| `; | `; | ||||||
|  |  | ||||||
| exports[`passing object slots via JSX children single expression, function expression: single expression, function expression 1`] = ` | exports[`passing object slots via JSX children single expression, function expression: single expression, function expression 1`] = ` | ||||||
| "import { createVNode as _createVNode } from \\"vue\\"; | "import { createVNode as _createVNode, resolveComponent as _resolveComponent } from \\"vue\\"; | ||||||
| import { resolveComponent as _resolveComponent } from \\"vue\\"; |  | ||||||
|  |  | ||||||
| _createVNode(_resolveComponent(\\"A\\"), null, { | _createVNode(_resolveComponent(\\"A\\"), null, { | ||||||
|   default: () => \\"foo\\" |   default: () => \\"foo\\" | ||||||
| @@ -157,11 +136,9 @@ _createVNode(_resolveComponent(\\"A\\"), null, { | |||||||
| `; | `; | ||||||
|  |  | ||||||
| exports[`passing object slots via JSX children single expression, non-literal value: runtime check: single expression, non-literal value: runtime check 1`] = ` | exports[`passing object slots via JSX children single expression, non-literal value: runtime check: single expression, non-literal value: runtime check 1`] = ` | ||||||
| "import { createVNode as _createVNode } from \\"vue\\"; | "let _slot; | ||||||
| import { isVNode as _isVNode } from \\"vue\\"; |  | ||||||
| import { resolveComponent as _resolveComponent } from \\"vue\\"; |  | ||||||
|  |  | ||||||
| let _slot; | import { createVNode as _createVNode, isVNode as _isVNode, resolveComponent as _resolveComponent } from \\"vue\\"; | ||||||
|  |  | ||||||
| function _isSlot(s) { | function _isSlot(s) { | ||||||
|   return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !_isVNode(s); |   return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !_isVNode(s); | ||||||
| @@ -176,8 +153,7 @@ _createVNode(_resolveComponent(\\"A\\"), null, _isSlot(_slot = foo()) ? _slot : | |||||||
| `; | `; | ||||||
|  |  | ||||||
| exports[`reassign variable as component: reassign variable as component 1`] = ` | exports[`reassign variable as component: reassign variable as component 1`] = ` | ||||||
| "import { isVNode as _isVNode } from \\"vue\\"; | "import { isVNode as _isVNode, createVNode as _createVNode } from \\"vue\\"; | ||||||
| import { createVNode as _createVNode } from \\"vue\\"; |  | ||||||
| import { defineComponent } from 'vue'; | import { defineComponent } from 'vue'; | ||||||
|  |  | ||||||
| function _isSlot(s) { | function _isSlot(s) { | ||||||
| @@ -207,10 +183,7 @@ a = _createVNode(A, null, _isSlot(a) ? a : { | |||||||
| `; | `; | ||||||
|  |  | ||||||
| exports[`select: select 1`] = ` | exports[`select: select 1`] = ` | ||||||
| "import { withDirectives as _withDirectives } from \\"vue\\"; | "import { withDirectives as _withDirectives, vModelSelect as _vModelSelect, createVNode as _createVNode, createTextVNode as _createTextVNode } from \\"vue\\"; | ||||||
| import { vModelSelect as _vModelSelect } from \\"vue\\"; |  | ||||||
| import { createVNode as _createVNode } from \\"vue\\"; |  | ||||||
| import { createTextVNode as _createTextVNode } from \\"vue\\"; |  | ||||||
|  |  | ||||||
| _withDirectives(_createVNode(\\"select\\", { | _withDirectives(_createVNode(\\"select\\", { | ||||||
|   \\"onUpdate:modelValue\\": $event => test = $event |   \\"onUpdate:modelValue\\": $event => test = $event | ||||||
| @@ -224,16 +197,14 @@ _withDirectives(_createVNode(\\"select\\", { | |||||||
| `; | `; | ||||||
|  |  | ||||||
| exports[`should keep \`import * as Vue from "vue"\`: should keep \`import * as Vue from "vue"\` 1`] = ` | exports[`should keep \`import * as Vue from "vue"\`: should keep \`import * as Vue from "vue"\` 1`] = ` | ||||||
| "import { createVNode as _createVNode } from \\"vue\\"; | "import { createVNode as _createVNode, createTextVNode as _createTextVNode } from \\"vue\\"; | ||||||
| import { createTextVNode as _createTextVNode } from \\"vue\\"; |  | ||||||
| import * as Vue from 'vue'; | import * as Vue from 'vue'; | ||||||
|  |  | ||||||
| _createVNode(\\"div\\", null, [_createTextVNode(\\"Vue\\")]);" | _createVNode(\\"div\\", null, [_createTextVNode(\\"Vue\\")]);" | ||||||
| `; | `; | ||||||
|  |  | ||||||
| exports[`single no need for a mergeProps call: single no need for a mergeProps call 1`] = ` | exports[`single no need for a mergeProps call: single no need for a mergeProps call 1`] = ` | ||||||
| "import { createVNode as _createVNode } from \\"vue\\"; | "import { createVNode as _createVNode, createTextVNode as _createTextVNode } from \\"vue\\"; | ||||||
| import { createTextVNode as _createTextVNode } from \\"vue\\"; |  | ||||||
|  |  | ||||||
| _createVNode(\\"div\\", x, [_createTextVNode(\\"single\\")], 16);" | _createVNode(\\"div\\", x, [_createTextVNode(\\"single\\")], 16);" | ||||||
| `; | `; | ||||||
| @@ -247,9 +218,7 @@ _createVNode(_Fragment, null, null);" | |||||||
| `; | `; | ||||||
|  |  | ||||||
| exports[`textarea: textarea 1`] = ` | exports[`textarea: textarea 1`] = ` | ||||||
| "import { withDirectives as _withDirectives } from \\"vue\\"; | "import { withDirectives as _withDirectives, createVNode as _createVNode, vModelText as _vModelText } from \\"vue\\"; | ||||||
| import { createVNode as _createVNode } from \\"vue\\"; |  | ||||||
| import { vModelText as _vModelText } from \\"vue\\"; |  | ||||||
|  |  | ||||||
| _withDirectives(_createVNode(\\"textarea\\", { | _withDirectives(_createVNode(\\"textarea\\", { | ||||||
|   \\"onUpdate:modelValue\\": $event => test = $event |   \\"onUpdate:modelValue\\": $event => test = $event | ||||||
| @@ -257,8 +226,7 @@ _withDirectives(_createVNode(\\"textarea\\", { | |||||||
| `; | `; | ||||||
|  |  | ||||||
| exports[`use "model" as the prop name: use "model" as the prop name 1`] = ` | exports[`use "model" as the prop name: use "model" as the prop name 1`] = ` | ||||||
| "import { createVNode as _createVNode } from \\"vue\\"; | "import { createVNode as _createVNode, resolveComponent as _resolveComponent } from \\"vue\\"; | ||||||
| import { resolveComponent as _resolveComponent } from \\"vue\\"; |  | ||||||
|  |  | ||||||
| _createVNode(_resolveComponent(\\"C\\"), { | _createVNode(_resolveComponent(\\"C\\"), { | ||||||
|   \\"model\\": foo, |   \\"model\\": foo, | ||||||
| @@ -267,10 +235,7 @@ _createVNode(_resolveComponent(\\"C\\"), { | |||||||
| `; | `; | ||||||
|  |  | ||||||
| exports[`v-show: v-show 1`] = ` | exports[`v-show: v-show 1`] = ` | ||||||
| "import { withDirectives as _withDirectives } from \\"vue\\"; | "import { withDirectives as _withDirectives, createVNode as _createVNode, vShow as _vShow, createTextVNode as _createTextVNode } from \\"vue\\"; | ||||||
| import { createVNode as _createVNode } from \\"vue\\"; |  | ||||||
| import { vShow as _vShow } from \\"vue\\"; |  | ||||||
| import { createTextVNode as _createTextVNode } from \\"vue\\"; |  | ||||||
|  |  | ||||||
| _withDirectives(_createVNode(\\"div\\", null, [_createTextVNode(\\"vShow\\")], 512), [[_vShow, x]]);" | _withDirectives(_createVNode(\\"div\\", null, [_createTextVNode(\\"vShow\\")], 512), [[_vShow, x]]);" | ||||||
| `; | `; | ||||||
| @@ -284,8 +249,7 @@ _createVNode(\\"h1\\", { | |||||||
| `; | `; | ||||||
|  |  | ||||||
| exports[`vModels: vModels 1`] = ` | exports[`vModels: vModels 1`] = ` | ||||||
| "import { createVNode as _createVNode } from \\"vue\\"; | "import { createVNode as _createVNode, resolveComponent as _resolveComponent } from \\"vue\\"; | ||||||
| import { resolveComponent as _resolveComponent } from \\"vue\\"; |  | ||||||
|  |  | ||||||
| _createVNode(_resolveComponent(\\"C\\"), { | _createVNode(_resolveComponent(\\"C\\"), { | ||||||
|   \\"modelValue\\": foo, |   \\"modelValue\\": foo, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user