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": {
|
"scripts": {
|
||||||
"dev": "webpack-dev-server",
|
"publish": "lerna publish"
|
||||||
"lint": "eslint --ext .js src",
|
|
||||||
"test": "jest --config .jest.js"
|
|
||||||
},
|
},
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git+https://github.com/vueComponent/jsx.git"
|
|
||||||
},
|
|
||||||
"author": "",
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/vueComponent/jsx/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/vueComponent/jsx#readme",
|
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"vue",
|
"vue",
|
||||||
"jsx"
|
"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": {
|
"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-eslint": "^10.1.0",
|
||||||
"babel-jest": "^26.0.1",
|
|
||||||
"babel-loader": "^8.1.0",
|
|
||||||
"eslint": "^7.0.0",
|
"eslint": "^7.0.0",
|
||||||
"eslint-config-airbnb": "^18.1.0",
|
"eslint-config-airbnb": "^18.1.0",
|
||||||
"eslint-plugin-import": "^2.20.2",
|
"eslint-plugin-import": "^2.20.2",
|
||||||
"jest": "^26.0.1",
|
"lerna": "^3.19.0"
|
||||||
"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"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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';
|
import { createApp, ref, defineComponent } from 'vue';
|
||||||
|
|
||||||
const SuperButton = (props, context) => (
|
const SuperButton = (props, context) => {
|
||||||
<div class={props.class}>
|
const obj = {
|
||||||
Super
|
mouseover: () => {
|
||||||
<button
|
context.emit('mouseover');
|
||||||
on={{
|
},
|
||||||
click: () => {
|
click: () => {
|
||||||
context.emit('click');
|
context.emit('click');
|
||||||
},
|
},
|
||||||
}}
|
};
|
||||||
|
return (
|
||||||
|
<div class={props.class}>
|
||||||
|
Super
|
||||||
|
<button
|
||||||
|
on={obj}
|
||||||
>
|
>
|
||||||
{ props.buttonText }
|
{ props.buttonText }
|
||||||
|
{context.slots.default()}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
SuperButton.inheritAttrs = false;
|
SuperButton.inheritAttrs = false;
|
||||||
|
|
||||||
@ -23,17 +30,23 @@ const App = defineComponent(() => {
|
|||||||
count.value++;
|
count.value++;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const obj = {
|
||||||
|
click: inc,
|
||||||
|
mouseover: inc,
|
||||||
|
};
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
<>
|
<div>
|
||||||
Foo {count.value}
|
Foo {count.value}
|
||||||
<SuperButton
|
<SuperButton
|
||||||
buttonText="VueComponent"
|
buttonText="VueComponent"
|
||||||
class="xxx"
|
class="xxx"
|
||||||
on={{
|
vShow={true}
|
||||||
click: inc,
|
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 sugarVModel = require('./sugar-v-model');
|
||||||
const sugarFragment = require('./sugar-fragment');
|
const sugarFragment = require('./sugar-fragment');
|
||||||
|
|
||||||
module.exports = ({ types: t }) => ({
|
module.exports = ({ types: t }, opts = {}) => ({
|
||||||
name: 'babel-plugin-jsx',
|
name: 'babel-plugin-jsx',
|
||||||
inherits: syntaxJsx,
|
inherits: syntaxJsx,
|
||||||
visitor: {
|
visitor: {
|
||||||
...sugarVModel(t),
|
...sugarVModel(t),
|
||||||
...tranformVueJSX(t),
|
...tranformVueJSX(t, opts),
|
||||||
...sugarFragment(t),
|
...sugarFragment(t),
|
||||||
},
|
},
|
||||||
});
|
});
|
@ -1,16 +1,11 @@
|
|||||||
const htmlTags = require('html-tags');
|
const htmlTags = require('html-tags');
|
||||||
const svgTags = require('svg-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 xlinkRE = /^xlink([A-Z])/;
|
||||||
const eventRE = /^on[A-Z][a-z]+$/;
|
const eventRE = /^on[A-Z][a-z]+$/;
|
||||||
const rootAttributes = ['class', 'style'];
|
const rootAttributes = ['class', 'style'];
|
||||||
|
|
||||||
/**
|
|
||||||
* click --> onClick
|
|
||||||
*/
|
|
||||||
|
|
||||||
const transformOn = (event = '') => `on${event[0].toUpperCase()}${event.substr(1)}`;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if string is describing a directive
|
* Checks if string is describing a directive
|
||||||
@ -85,18 +80,15 @@ const getJSXAttributeValue = (t, path) => {
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const transformJSXAttribute = (t, path, attributesToMerge, directives) => {
|
const transformJSXAttribute = (t, path, state, attributesToMerge, directives) => {
|
||||||
let name = getJSXAttributeName(t, path);
|
let name = getJSXAttributeName(t, path);
|
||||||
if (name === 'on') {
|
const attributeValue = getJSXAttributeValue(t, path);
|
||||||
const { properties = [] } = getJSXAttributeValue(t, path);
|
if (state.opts.transformOn && (name === 'on' || name === 'nativeOn')) {
|
||||||
properties.forEach((property) => {
|
const transformOn = addDefault(path, '@ant-design-vue/babel-helper-vue-transform-on', { nameHint: '_transformOn' });
|
||||||
attributesToMerge.push(t.objectExpression([
|
attributesToMerge.push(t.callExpression(
|
||||||
t.objectProperty(
|
transformOn,
|
||||||
t.identifier(transformOn(property.key.name)),
|
[attributeValue || t.booleanLiteral(true)],
|
||||||
property.value,
|
));
|
||||||
),
|
|
||||||
]));
|
|
||||||
});
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (isDirective(name)) {
|
if (isDirective(name)) {
|
||||||
@ -104,18 +96,18 @@ const transformJSXAttribute = (t, path, attributesToMerge, directives) => {
|
|||||||
? name.replace('v-', '')
|
? name.replace('v-', '')
|
||||||
: name.replace(`v${name[1]}`, name[1].toLowerCase());
|
: name.replace(`v${name[1]}`, name[1].toLowerCase());
|
||||||
if (directiveName === '_model') {
|
if (directiveName === '_model') {
|
||||||
directives.push(getJSXAttributeValue(t, path));
|
directives.push(attributeValue);
|
||||||
} else if (directiveName === 'show') {
|
} else if (directiveName === 'show') {
|
||||||
directives.push(t.arrayExpression([
|
directives.push(t.arrayExpression([
|
||||||
path.vShow,
|
state.vShow,
|
||||||
getJSXAttributeValue(t, path),
|
attributeValue,
|
||||||
]));
|
]));
|
||||||
} else {
|
} else {
|
||||||
directives.push(t.arrayExpression([
|
directives.push(t.arrayExpression([
|
||||||
t.callExpression(path.resolveDirective, [
|
t.callExpression(state.resolveDirective, [
|
||||||
t.stringLiteral(directiveName),
|
t.stringLiteral(directiveName),
|
||||||
]),
|
]),
|
||||||
getJSXAttributeValue(t, path),
|
attributeValue,
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -127,7 +119,7 @@ const transformJSXAttribute = (t, path, attributesToMerge, directives) => {
|
|||||||
t.stringLiteral(
|
t.stringLiteral(
|
||||||
name,
|
name,
|
||||||
),
|
),
|
||||||
getJSXAttributeValue(t, path),
|
attributeValue,
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
@ -141,7 +133,7 @@ const transformJSXAttribute = (t, path, attributesToMerge, directives) => {
|
|||||||
t.stringLiteral(
|
t.stringLiteral(
|
||||||
name,
|
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()
|
path.isJSXAttribute()
|
||||||
? transformJSXAttribute(t, path, attributesToMerge, directives)
|
? transformJSXAttribute(t, path, state, attributesToMerge, directives)
|
||||||
: transformJSXSpreadAttribute(t, path, attributesToMerge));
|
: transformJSXSpreadAttribute(t, path, attributesToMerge));
|
||||||
|
|
||||||
const getAttributes = (t, path, directives) => {
|
const getAttributes = (t, path, state, directives) => {
|
||||||
const attributes = path.get('openingElement').get('attributes');
|
const attributes = path.get('openingElement').get('attributes');
|
||||||
if (attributes.length === 0) {
|
if (attributes.length === 0) {
|
||||||
return t.nullLiteral();
|
return t.nullLiteral();
|
||||||
@ -184,13 +176,13 @@ const getAttributes = (t, path, directives) => {
|
|||||||
const attributeArray = [];
|
const attributeArray = [];
|
||||||
attributes
|
attributes
|
||||||
.forEach((attribute) => {
|
.forEach((attribute) => {
|
||||||
const attr = transformAttribute(t, attribute, attributesToMerge, directives);
|
const attr = transformAttribute(t, attribute, state, attributesToMerge, directives);
|
||||||
if (attr) {
|
if (attr) {
|
||||||
attributeArray.push(attr);
|
attributeArray.push(attr);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return t.callExpression(
|
return t.callExpression(
|
||||||
path.mergeProps,
|
state.mergeProps,
|
||||||
[
|
[
|
||||||
...attributesToMerge,
|
...attributesToMerge,
|
||||||
t.objectExpression(attributeArray),
|
t.objectExpression(attributeArray),
|
||||||
@ -295,18 +287,18 @@ const getChildren = (t, paths) => paths
|
|||||||
&& !t.isJSXEmptyExpression(value)
|
&& !t.isJSXEmptyExpression(value)
|
||||||
));
|
));
|
||||||
|
|
||||||
const transformJSXElement = (t, path) => {
|
const transformJSXElement = (t, path, state) => {
|
||||||
const directives = [];
|
const directives = [];
|
||||||
const tag = getTag(t, path);
|
const tag = getTag(t, path);
|
||||||
const children = t.arrayExpression(getChildren(t, path.get('children')));
|
const children = t.arrayExpression(getChildren(t, path.get('children')));
|
||||||
const h = t.callExpression(path.h, [
|
const h = t.callExpression(state.h, [
|
||||||
tag,
|
tag,
|
||||||
getAttributes(t, path, directives),
|
getAttributes(t, path, state, directives),
|
||||||
!t.isStringLiteral(tag)
|
!t.isStringLiteral(tag)
|
||||||
? t.objectExpression([
|
? t.objectExpression([
|
||||||
t.objectProperty(
|
t.objectProperty(
|
||||||
t.identifier('default'),
|
t.identifier('default'),
|
||||||
t.callExpression(path.withCtx, [
|
t.callExpression(state.withCtx, [
|
||||||
t.arrowFunctionExpression(
|
t.arrowFunctionExpression(
|
||||||
[],
|
[],
|
||||||
children,
|
children,
|
||||||
@ -319,7 +311,7 @@ const transformJSXElement = (t, path) => {
|
|||||||
if (!directives.length) {
|
if (!directives.length) {
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
return t.callExpression(path.withDirectives, [
|
return t.callExpression(state.withDirectives, [
|
||||||
h,
|
h,
|
||||||
t.arrayExpression(directives),
|
t.arrayExpression(directives),
|
||||||
]);
|
]);
|
||||||
@ -332,14 +324,14 @@ const imports = [
|
|||||||
|
|
||||||
module.exports = (t) => ({
|
module.exports = (t) => ({
|
||||||
JSXElement: {
|
JSXElement: {
|
||||||
exit(path) {
|
exit(path, state) {
|
||||||
imports.forEach((m) => {
|
imports.forEach((m) => {
|
||||||
if (!path[m]) {
|
if (!state[m]) {
|
||||||
path[m] = addNamed(path, m, 'vue');
|
state[m] = addNamed(path, m, 'vue');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
path.replaceWith(
|
path.replaceWith(
|
||||||
transformJSXElement(t, path),
|
transformJSXElement(t, path, state),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
Loading…
Reference in New Issue
Block a user