mirror of
https://github.com/vuejs/babel-plugin-jsx.git
synced 2024-11-10 09:39:14 +08:00
refactor: support transformOn
This commit is contained in:
parent
402568dc52
commit
7a1a39a4cb
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),
|
||||
);
|
||||
},
|
||||
},
|
Loading…
Reference in New Issue
Block a user