mirror of
https://github.com/vuejs/babel-plugin-jsx.git
synced 2024-11-10 17:49:16 +08:00
feat: add pragma option and support @jsx annotation (#322)
* add pragma option and support @jsx annotation * update syntax and remove useless eslint rule * use BabelCore.BabelFile as type definition of state.file * update chinese doc
This commit is contained in:
parent
57f670711d
commit
ec50fddc8a
@ -22,6 +22,7 @@ module.exports = {
|
|||||||
'no-nested-ternary': [0],
|
'no-nested-ternary': [0],
|
||||||
'no-param-reassign': [0],
|
'no-param-reassign': [0],
|
||||||
'no-use-before-define': [0],
|
'no-use-before-define': [0],
|
||||||
|
'no-restricted-syntax': [0],
|
||||||
'no-plusplus': [0],
|
'no-plusplus': [0],
|
||||||
'import/no-extraneous-dependencies': [0],
|
'import/no-extraneous-dependencies': [0],
|
||||||
'consistent-return': [0],
|
'consistent-return': [0],
|
||||||
|
@ -62,6 +62,14 @@ Default: `true`
|
|||||||
|
|
||||||
使用 `enableObjectSlots` (文档下面会提到)。虽然在 JSX 中比较好使,但是会增加一些 `_isSlot` 的运行时条件判断,这会增加你的项目体积。即使你关闭了 `enableObjectSlots`,`v-slots` 还是可以使用
|
使用 `enableObjectSlots` (文档下面会提到)。虽然在 JSX 中比较好使,但是会增加一些 `_isSlot` 的运行时条件判断,这会增加你的项目体积。即使你关闭了 `enableObjectSlots`,`v-slots` 还是可以使用
|
||||||
|
|
||||||
|
#### pragma
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Default: `createVNode`
|
||||||
|
|
||||||
|
替换编译JSX表达式的时候使用的函数
|
||||||
|
|
||||||
## 表达式
|
## 表达式
|
||||||
|
|
||||||
### 内容
|
### 内容
|
||||||
|
@ -66,6 +66,14 @@ Default: `true`
|
|||||||
|
|
||||||
Whether to enable `object slots` (mentioned below the document) syntax". It might be useful in JSX, but it will add a lot of `_isSlot` condition expressions which increase your bundle size. And `v-slots` is still available even if `enableObjectSlots` is turned off.
|
Whether to enable `object slots` (mentioned below the document) syntax". It might be useful in JSX, but it will add a lot of `_isSlot` condition expressions which increase your bundle size. And `v-slots` is still available even if `enableObjectSlots` is turned off.
|
||||||
|
|
||||||
|
#### pragma
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Default: `createVNode`
|
||||||
|
|
||||||
|
Replace the function used when compiling JSX expressions.
|
||||||
|
|
||||||
## Syntax
|
## Syntax
|
||||||
|
|
||||||
### Content
|
### Content
|
||||||
|
@ -11,6 +11,7 @@ export type State = {
|
|||||||
get: (name: string) => any;
|
get: (name: string) => any;
|
||||||
set: (name: string, value: any) => any;
|
set: (name: string, value: any) => any;
|
||||||
opts: VueJSXPluginOptions;
|
opts: VueJSXPluginOptions;
|
||||||
|
file: BabelCore.BabelFile
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface VueJSXPluginOptions {
|
export interface VueJSXPluginOptions {
|
||||||
@ -24,6 +25,8 @@ export interface VueJSXPluginOptions {
|
|||||||
isCustomElement?: (tag: string) => boolean;
|
isCustomElement?: (tag: string) => boolean;
|
||||||
/** enable object slots syntax */
|
/** enable object slots syntax */
|
||||||
enableObjectSlots?: boolean;
|
enableObjectSlots?: boolean;
|
||||||
|
/** Replace the function used when compiling JSX expressions */
|
||||||
|
pragma?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ExcludesBoolean = <T>(x: T | false | true) => x is T;
|
export type ExcludesBoolean = <T>(x: T | false | true) => x is T;
|
||||||
@ -44,6 +47,8 @@ const hasJSX = (parentPath: NodePath<t.Program>) => {
|
|||||||
return fileHasJSX;
|
return fileHasJSX;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const JSX_ANNOTATION_REGEX = /\*?\s*@jsx\s+([^\s]+)/;
|
||||||
|
|
||||||
export default ({ types }: typeof BabelCore) => ({
|
export default ({ types }: typeof BabelCore) => ({
|
||||||
name: 'babel-plugin-jsx',
|
name: 'babel-plugin-jsx',
|
||||||
inherits: syntaxJsx,
|
inherits: syntaxJsx,
|
||||||
@ -129,6 +134,21 @@ export default ({ types }: typeof BabelCore) => ({
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { opts: { pragma = '' }, file } = state;
|
||||||
|
|
||||||
|
if (pragma) {
|
||||||
|
state.set('createVNode', () => t.identifier(pragma));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file.ast.comments) {
|
||||||
|
for (const comment of file.ast.comments) {
|
||||||
|
const jsxMatches = JSX_ANNOTATION_REGEX.exec(comment.value);
|
||||||
|
if (jsxMatches) {
|
||||||
|
state.set('createVNode', () => t.identifier(jsxMatches[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
exit(path: NodePath<t.Program>) {
|
exit(path: NodePath<t.Program>) {
|
||||||
|
@ -210,6 +210,11 @@ _withDirectives(_createVNode(\\"select\\", {
|
|||||||
}, [_createTextVNode(\\"c\\")])], 8, [\\"onUpdate:modelValue\\"]), [[_vModelSelect, test]]);"
|
}, [_createTextVNode(\\"c\\")])], 8, [\\"onUpdate:modelValue\\"]), [[_vModelSelect, test]]);"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`set pragma to custom: custom 1`] = `
|
||||||
|
"import { createTextVNode as _createTextVNode } from \\"vue\\";
|
||||||
|
custom(\\"div\\", null, [_createTextVNode(\\"pragma\\")]);"
|
||||||
|
`;
|
||||||
|
|
||||||
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, createTextVNode as _createTextVNode } from \\"vue\\";
|
"import { createVNode as _createVNode, createTextVNode as _createTextVNode } from \\"vue\\";
|
||||||
import * as Vue from 'vue';
|
import * as Vue from 'vue';
|
||||||
@ -239,6 +244,15 @@ _withDirectives(_createVNode(\\"textarea\\", {
|
|||||||
}, null, 8, [\\"onUpdate:modelValue\\"]), [[_vModelText, test]]);"
|
}, null, 8, [\\"onUpdate:modelValue\\"]), [[_vModelText, test]]);"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`use "@jsx" comment specify pragma: use "@jsx" comment specify pragma 1`] = `
|
||||||
|
"import { createTextVNode as _createTextVNode } from \\"vue\\";
|
||||||
|
|
||||||
|
/* @jsx custom */
|
||||||
|
custom(\\"div\\", {
|
||||||
|
\\"id\\": \\"custom\\"
|
||||||
|
}, [_createTextVNode(\\"Hello\\")]);"
|
||||||
|
`;
|
||||||
|
|
||||||
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, resolveComponent as _resolveComponent } from \\"vue\\";
|
"import { createVNode as _createVNode, resolveComponent as _resolveComponent } from \\"vue\\";
|
||||||
|
|
||||||
|
@ -163,6 +163,13 @@ const tests: Test[] = [
|
|||||||
<Vue.KeepAlive>123</Vue.KeepAlive>
|
<Vue.KeepAlive>123</Vue.KeepAlive>
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'use "@jsx" comment specify pragma',
|
||||||
|
from: `
|
||||||
|
/* @jsx custom */
|
||||||
|
<div id="custom">Hello</div>
|
||||||
|
`,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
tests.forEach((
|
tests.forEach((
|
||||||
@ -244,3 +251,22 @@ objectSlotsTests.forEach(({
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const pragmaTests = [
|
||||||
|
{
|
||||||
|
name: 'custom',
|
||||||
|
from: '<div>pragma</div>',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
pragmaTests.forEach(({
|
||||||
|
name, from,
|
||||||
|
}) => {
|
||||||
|
test(
|
||||||
|
`set pragma to ${name}`,
|
||||||
|
async () => {
|
||||||
|
expect(await transpile(from, { pragma: 'custom' }))
|
||||||
|
.toMatchSnapshot(name);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user