mirror of
				https://github.com/vuejs/babel-plugin-jsx.git
				synced 2025-10-31 17:32:32 +08:00 
			
		
		
		
	refactor: support transformOn
This commit is contained in:
		
							
								
								
									
										8
									
								
								.babelrc
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								.babelrc
									
									
									
									
									
								
							| @@ -1,8 +0,0 @@ | ||||
| { | ||||
|   "presets": [ | ||||
|     "@babel/env" | ||||
|   ], | ||||
|   "plugins": [ | ||||
|     "./src/index.js" | ||||
|   ] | ||||
| } | ||||
							
								
								
									
										6
									
								
								lerna.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								lerna.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| { | ||||
|   "packages": [ | ||||
|     "packages/*" | ||||
|   ], | ||||
|   "version": "0.0.0" | ||||
| } | ||||
							
								
								
									
										36
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								package.json
									
									
									
									
									
								
							| @@ -1,49 +1,17 @@ | ||||
| { | ||||
|   "name": "@ant-design-vue/babel-plugin-jsx", | ||||
|   "version": "1.0.0-alpha.2", | ||||
|   "description": "Babel plugin for Vue 3.0 JSX", | ||||
|   "main": "src/index.js", | ||||
|   "scripts": { | ||||
|     "dev": "webpack-dev-server", | ||||
|     "lint": "eslint --ext .js src", | ||||
|     "test": "jest --config .jest.js" | ||||
|     "publish": "lerna publish" | ||||
|   }, | ||||
|   "repository": { | ||||
|     "type": "git", | ||||
|     "url": "git+https://github.com/vueComponent/jsx.git" | ||||
|   }, | ||||
|   "author": "", | ||||
|   "license": "MIT", | ||||
|   "bugs": { | ||||
|     "url": "https://github.com/vueComponent/jsx/issues" | ||||
|   }, | ||||
|   "homepage": "https://github.com/vueComponent/jsx#readme", | ||||
|   "keywords": [ | ||||
|     "vue", | ||||
|     "jsx" | ||||
|   ], | ||||
|   "dependencies": { | ||||
|     "@babel/helper-module-imports": "^7.0.0", | ||||
|     "@babel/plugin-syntax-jsx": "^7.0.0", | ||||
|     "camelcase": "^6.0.0", | ||||
|     "html-tags": "^3.1.0", | ||||
|     "svg-tags": "^1.0.0" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@babel/core": "^7.9.6", | ||||
|     "@babel/preset-env": "^7.9.6", | ||||
|     "@vue/test-utils": "^2.0.0-alpha.6", | ||||
|     "babel-eslint": "^10.1.0", | ||||
|     "babel-jest": "^26.0.1", | ||||
|     "babel-loader": "^8.1.0", | ||||
|     "eslint": "^7.0.0", | ||||
|     "eslint-config-airbnb": "^18.1.0", | ||||
|     "eslint-plugin-import": "^2.20.2", | ||||
|     "jest": "^26.0.1", | ||||
|     "regenerator-runtime": "^0.13.5", | ||||
|     "vue": "^3.0.0-beta.14", | ||||
|     "webpack": "^4.43.0", | ||||
|     "webpack-cli": "^3.3.11", | ||||
|     "webpack-dev-server": "^3.10.3" | ||||
|     "lerna": "^3.19.0" | ||||
|   } | ||||
| } | ||||
|   | ||||
							
								
								
									
										11
									
								
								packages/babel-helper-vue-transform-on/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								packages/babel-helper-vue-transform-on/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| # @ant-design-vue/babel-helper-vue-transform-on | ||||
|  | ||||
| A package used internally by vue jsx transformer to merge props spread. It is required to merge some prop trees like this: | ||||
|  | ||||
| ## Usage | ||||
|  | ||||
| ``` | ||||
| const babelHelperVueTransformOn = require('babel-helper-vue-transform-on'); | ||||
|  | ||||
| // TODO: DEMONSTRATE API | ||||
| ``` | ||||
							
								
								
									
										9
									
								
								packages/babel-helper-vue-transform-on/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								packages/babel-helper-vue-transform-on/index.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| const transformOn = (obj) => { | ||||
|   const result = {}; | ||||
|   Object.keys(obj).forEach((evt) => { | ||||
|     result[`on${evt[0].toUpperCase()}${evt.substr(1)}`] = obj[evt]; | ||||
|   }); | ||||
|   return result; | ||||
| }; | ||||
|  | ||||
| module.exports = transformOn; | ||||
							
								
								
									
										9
									
								
								packages/babel-helper-vue-transform-on/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								packages/babel-helper-vue-transform-on/package.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| { | ||||
|   "name": "@ant-design-vue/babel-helper-vue-transform-on", | ||||
|   "version": "1.0.0", | ||||
|   "description": "> TODO: description", | ||||
|   "author": "Amour1688 <lcz_1996@foxmail.com>", | ||||
|   "license": "MIT", | ||||
|   "main": "index.js", | ||||
|   "private": true | ||||
| } | ||||
							
								
								
									
										13
									
								
								packages/babel-plugin-jsx/.babelrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								packages/babel-plugin-jsx/.babelrc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| { | ||||
|   "presets": [ | ||||
|     [ | ||||
|       "@babel/env", | ||||
|       { | ||||
|         // "modules": "cjs" | ||||
|       } | ||||
|     ] | ||||
|   ], | ||||
|   "plugins": [ | ||||
|     ["./src/index.js", { "transformOn": true }] | ||||
|   ] | ||||
| } | ||||
							
								
								
									
										11
									
								
								packages/babel-plugin-jsx/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								packages/babel-plugin-jsx/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| # `babel-plugin-jsx` | ||||
|  | ||||
| > TODO: description | ||||
|  | ||||
| ## Usage | ||||
|  | ||||
| ``` | ||||
| const babelPluginJsx = require('babel-plugin-jsx'); | ||||
|  | ||||
| // TODO: DEMONSTRATE API | ||||
| ``` | ||||
| @@ -1,19 +1,26 @@ | ||||
| import { createApp, ref, defineComponent } from 'vue'; | ||||
| 
 | ||||
| const SuperButton = (props, context) => ( | ||||
|     <div class={props.class}> | ||||
|       Super | ||||
|       <button | ||||
|         on={{ | ||||
| const SuperButton = (props, context) => { | ||||
|   const obj = { | ||||
|     mouseover: () => { | ||||
|       context.emit('mouseover'); | ||||
|     }, | ||||
|     click: () => { | ||||
|       context.emit('click'); | ||||
|     }, | ||||
|         }} | ||||
|   }; | ||||
|   return ( | ||||
|     <div class={props.class}> | ||||
|       Super | ||||
|       <button | ||||
|         on={obj} | ||||
|       > | ||||
|         { props.buttonText } | ||||
|         {context.slots.default()} | ||||
|       </button> | ||||
|     </div> | ||||
|   ); | ||||
| }; | ||||
| 
 | ||||
| SuperButton.inheritAttrs = false; | ||||
| 
 | ||||
| @@ -23,17 +30,23 @@ const App = defineComponent(() => { | ||||
|     count.value++; | ||||
|   }; | ||||
| 
 | ||||
|   const obj = { | ||||
|     click: inc, | ||||
|     mouseover: inc, | ||||
|   }; | ||||
| 
 | ||||
|   return () => ( | ||||
|     <> | ||||
|     <div> | ||||
|       Foo {count.value} | ||||
|       <SuperButton | ||||
|         buttonText="VueComponent" | ||||
|         class="xxx" | ||||
|         on={{ | ||||
|           click: inc, | ||||
|         }} | ||||
|       /> | ||||
|     </> | ||||
|         vShow={true} | ||||
|         on={obj} | ||||
|       > | ||||
|         <button>1234</button> | ||||
|       </SuperButton> | ||||
|     </div> | ||||
|   ); | ||||
| }); | ||||
| 
 | ||||
							
								
								
									
										42
									
								
								packages/babel-plugin-jsx/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								packages/babel-plugin-jsx/package.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| { | ||||
|   "name": "@ant-design-vue/babel-plugin-jsx", | ||||
|   "version": "1.0.0", | ||||
|   "description": "Babel plugin for Vue 3.0 JSX", | ||||
|   "author": "Amour1688 <lcz_1996@foxmail.com>", | ||||
|   "homepage": "https://github.com/vueComponent/jsx/tree/master/packages/babel-plugin-jsx#readme", | ||||
|   "license": "MIT", | ||||
|   "main": "src/index.js", | ||||
|   "repository": { | ||||
|     "type": "git", | ||||
|     "url": "git+https://github.com/vueComponent/jsx.git" | ||||
|   }, | ||||
|   "scripts": { | ||||
|     "dev": "webpack-dev-server", | ||||
|     "lint": "eslint --ext .js src", | ||||
|     "test": "jest --config .jest.js" | ||||
|   }, | ||||
|   "bugs": { | ||||
|     "url": "https://github.com/vueComponent/jsx/issues" | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "@ant-design-vue/babel-helper-vue-transform-on": "^1.0.0", | ||||
|     "@babel/helper-module-imports": "^7.0.0", | ||||
|     "@babel/plugin-syntax-jsx": "^7.0.0", | ||||
|     "camelcase": "^6.0.0", | ||||
|     "html-tags": "^3.1.0", | ||||
|     "svg-tags": "^1.0.0" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@babel/core": "^7.9.6", | ||||
|     "@babel/preset-env": "^7.9.6", | ||||
|     "@vue/test-utils": "^2.0.0-alpha.6", | ||||
|     "babel-jest": "^26.0.1", | ||||
|     "babel-loader": "^8.1.0", | ||||
|     "jest": "^26.0.1", | ||||
|     "regenerator-runtime": "^0.13.5", | ||||
|     "vue": "^3.0.0-beta.14", | ||||
|     "webpack": "^4.43.0", | ||||
|     "webpack-cli": "^3.3.11", | ||||
|     "webpack-dev-server": "^3.10.3" | ||||
|   } | ||||
| } | ||||
| @@ -3,12 +3,12 @@ const tranformVueJSX = require('./transform-vue-jsx'); | ||||
| const sugarVModel = require('./sugar-v-model'); | ||||
| const sugarFragment = require('./sugar-fragment'); | ||||
| 
 | ||||
| module.exports = ({ types: t }) => ({ | ||||
| module.exports = ({ types: t }, opts = {}) => ({ | ||||
|   name: 'babel-plugin-jsx', | ||||
|   inherits: syntaxJsx, | ||||
|   visitor: { | ||||
|     ...sugarVModel(t), | ||||
|     ...tranformVueJSX(t), | ||||
|     ...tranformVueJSX(t, opts), | ||||
|     ...sugarFragment(t), | ||||
|   }, | ||||
| }); | ||||
| @@ -1,16 +1,11 @@ | ||||
| const htmlTags = require('html-tags'); | ||||
| const svgTags = require('svg-tags'); | ||||
| const { addNamed } = require('@babel/helper-module-imports'); | ||||
| const { addNamed, addDefault } = require('@babel/helper-module-imports'); | ||||
| 
 | ||||
| const xlinkRE = /^xlink([A-Z])/; | ||||
| const eventRE = /^on[A-Z][a-z]+$/; | ||||
| const rootAttributes = ['class', 'style']; | ||||
| 
 | ||||
| /** | ||||
|  * click --> onClick | ||||
|  */ | ||||
| 
 | ||||
| const transformOn = (event = '') => `on${event[0].toUpperCase()}${event.substr(1)}`; | ||||
| 
 | ||||
| /** | ||||
|  * Checks if string is describing a directive | ||||
| @@ -85,18 +80,15 @@ const getJSXAttributeValue = (t, path) => { | ||||
|   return null; | ||||
| }; | ||||
| 
 | ||||
| const transformJSXAttribute = (t, path, attributesToMerge, directives) => { | ||||
| const transformJSXAttribute = (t, path, state, attributesToMerge, directives) => { | ||||
|   let name = getJSXAttributeName(t, path); | ||||
|   if (name === 'on') { | ||||
|     const { properties = [] } = getJSXAttributeValue(t, path); | ||||
|     properties.forEach((property) => { | ||||
|       attributesToMerge.push(t.objectExpression([ | ||||
|         t.objectProperty( | ||||
|           t.identifier(transformOn(property.key.name)), | ||||
|           property.value, | ||||
|         ), | ||||
|       ])); | ||||
|     }); | ||||
|   const attributeValue = getJSXAttributeValue(t, path); | ||||
|   if (state.opts.transformOn && (name === 'on' || name === 'nativeOn')) { | ||||
|     const transformOn = addDefault(path, '@ant-design-vue/babel-helper-vue-transform-on', { nameHint: '_transformOn' }); | ||||
|     attributesToMerge.push(t.callExpression( | ||||
|       transformOn, | ||||
|       [attributeValue || t.booleanLiteral(true)], | ||||
|     )); | ||||
|     return null; | ||||
|   } | ||||
|   if (isDirective(name)) { | ||||
| @@ -104,18 +96,18 @@ const transformJSXAttribute = (t, path, attributesToMerge, directives) => { | ||||
|       ? name.replace('v-', '') | ||||
|       : name.replace(`v${name[1]}`, name[1].toLowerCase()); | ||||
|     if (directiveName === '_model') { | ||||
|       directives.push(getJSXAttributeValue(t, path)); | ||||
|       directives.push(attributeValue); | ||||
|     } else if (directiveName === 'show') { | ||||
|       directives.push(t.arrayExpression([ | ||||
|         path.vShow, | ||||
|         getJSXAttributeValue(t, path), | ||||
|         state.vShow, | ||||
|         attributeValue, | ||||
|       ])); | ||||
|     } else { | ||||
|       directives.push(t.arrayExpression([ | ||||
|         t.callExpression(path.resolveDirective, [ | ||||
|         t.callExpression(state.resolveDirective, [ | ||||
|           t.stringLiteral(directiveName), | ||||
|         ]), | ||||
|         getJSXAttributeValue(t, path), | ||||
|         attributeValue, | ||||
|       ])); | ||||
|     } | ||||
|     return null; | ||||
| @@ -127,7 +119,7 @@ const transformJSXAttribute = (t, path, attributesToMerge, directives) => { | ||||
|           t.stringLiteral( | ||||
|             name, | ||||
|           ), | ||||
|           getJSXAttributeValue(t, path), | ||||
|           attributeValue, | ||||
|         ), | ||||
|       ]), | ||||
|     ); | ||||
| @@ -141,7 +133,7 @@ const transformJSXAttribute = (t, path, attributesToMerge, directives) => { | ||||
|     t.stringLiteral( | ||||
|       name, | ||||
|     ), | ||||
|     getJSXAttributeValue(t, path) || t.booleanLiteral(true), | ||||
|     attributeValue || t.booleanLiteral(true), | ||||
|   ); | ||||
| }; | ||||
| 
 | ||||
| @@ -169,12 +161,12 @@ const transformJSXSpreadAttribute = (t, path, attributesToMerge) => { | ||||
|   }))); | ||||
| }; | ||||
| 
 | ||||
| const transformAttribute = (t, path, attributesToMerge, directives) => ( | ||||
| const transformAttribute = (t, path, state, attributesToMerge, directives) => ( | ||||
|   path.isJSXAttribute() | ||||
|     ? transformJSXAttribute(t, path, attributesToMerge, directives) | ||||
|     ? transformJSXAttribute(t, path, state, attributesToMerge, directives) | ||||
|     : transformJSXSpreadAttribute(t, path, attributesToMerge)); | ||||
| 
 | ||||
| const getAttributes = (t, path, directives) => { | ||||
| const getAttributes = (t, path, state, directives) => { | ||||
|   const attributes = path.get('openingElement').get('attributes'); | ||||
|   if (attributes.length === 0) { | ||||
|     return t.nullLiteral(); | ||||
| @@ -184,13 +176,13 @@ const getAttributes = (t, path, directives) => { | ||||
|   const attributeArray = []; | ||||
|   attributes | ||||
|     .forEach((attribute) => { | ||||
|       const attr = transformAttribute(t, attribute, attributesToMerge, directives); | ||||
|       const attr = transformAttribute(t, attribute, state, attributesToMerge, directives); | ||||
|       if (attr) { | ||||
|         attributeArray.push(attr); | ||||
|       } | ||||
|     }); | ||||
|   return t.callExpression( | ||||
|     path.mergeProps, | ||||
|     state.mergeProps, | ||||
|     [ | ||||
|       ...attributesToMerge, | ||||
|       t.objectExpression(attributeArray), | ||||
| @@ -295,18 +287,18 @@ const getChildren = (t, paths) => paths | ||||
|       && !t.isJSXEmptyExpression(value) | ||||
|   )); | ||||
| 
 | ||||
| const transformJSXElement = (t, path) => { | ||||
| const transformJSXElement = (t, path, state) => { | ||||
|   const directives = []; | ||||
|   const tag = getTag(t, path); | ||||
|   const children = t.arrayExpression(getChildren(t, path.get('children'))); | ||||
|   const h = t.callExpression(path.h, [ | ||||
|   const h = t.callExpression(state.h, [ | ||||
|     tag, | ||||
|     getAttributes(t, path, directives), | ||||
|     getAttributes(t, path, state, directives), | ||||
|     !t.isStringLiteral(tag) | ||||
|       ? t.objectExpression([ | ||||
|         t.objectProperty( | ||||
|           t.identifier('default'), | ||||
|           t.callExpression(path.withCtx, [ | ||||
|           t.callExpression(state.withCtx, [ | ||||
|             t.arrowFunctionExpression( | ||||
|               [], | ||||
|               children, | ||||
| @@ -319,7 +311,7 @@ const transformJSXElement = (t, path) => { | ||||
|   if (!directives.length) { | ||||
|     return h; | ||||
|   } | ||||
|   return t.callExpression(path.withDirectives, [ | ||||
|   return t.callExpression(state.withDirectives, [ | ||||
|     h, | ||||
|     t.arrayExpression(directives), | ||||
|   ]); | ||||
| @@ -332,14 +324,14 @@ const imports = [ | ||||
| 
 | ||||
| module.exports = (t) => ({ | ||||
|   JSXElement: { | ||||
|     exit(path) { | ||||
|     exit(path, state) { | ||||
|       imports.forEach((m) => { | ||||
|         if (!path[m]) { | ||||
|           path[m] = addNamed(path, m, 'vue'); | ||||
|         if (!state[m]) { | ||||
|           state[m] = addNamed(path, m, 'vue'); | ||||
|         } | ||||
|       }); | ||||
|       path.replaceWith( | ||||
|         transformJSXElement(t, path), | ||||
|         transformJSXElement(t, path, state), | ||||
|       ); | ||||
|     }, | ||||
|   }, | ||||
		Reference in New Issue
	
	Block a user