Add jsxPragmaFrag support to typescript transform (#11950)
This commit is contained in:
parent
94b5f92e39
commit
d0d1fdb921
@ -49,7 +49,8 @@ export default declare(
|
||||
(
|
||||
api,
|
||||
{
|
||||
jsxPragma = "React",
|
||||
jsxPragma = "React.createElement",
|
||||
jsxPragmaFrag = "React.Fragment",
|
||||
allowNamespaces = false,
|
||||
allowDeclareFields = false,
|
||||
onlyRemoveTypeImports = false,
|
||||
@ -57,7 +58,7 @@ export default declare(
|
||||
) => {
|
||||
api.assertVersion(7);
|
||||
|
||||
const JSX_ANNOTATION_REGEX = /\*?\s*@jsx\s+([^\s]+)/;
|
||||
const JSX_PRAGMA_REGEX = /\*?\s*@jsx((?:Frag)?)\s+([^\s]+)/;
|
||||
|
||||
const classMemberVisitors = {
|
||||
field(path) {
|
||||
@ -168,6 +169,7 @@ export default declare(
|
||||
Program(path, state) {
|
||||
const { file } = state;
|
||||
let fileJsxPragma = null;
|
||||
let fileJsxPragmaFrag = null;
|
||||
|
||||
if (!GLOBAL_TYPES.has(path.node)) {
|
||||
GLOBAL_TYPES.set(path.node, new Set());
|
||||
@ -175,9 +177,14 @@ export default declare(
|
||||
|
||||
if (file.ast.comments) {
|
||||
for (const comment of (file.ast.comments: Array<Object>)) {
|
||||
const jsxMatches = JSX_ANNOTATION_REGEX.exec(comment.value);
|
||||
const jsxMatches = JSX_PRAGMA_REGEX.exec(comment.value);
|
||||
if (jsxMatches) {
|
||||
fileJsxPragma = jsxMatches[1];
|
||||
if (jsxMatches[1]) {
|
||||
// isFragment
|
||||
fileJsxPragmaFrag = jsxMatches[2];
|
||||
} else {
|
||||
fileJsxPragma = jsxMatches[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -187,6 +194,11 @@ export default declare(
|
||||
[pragmaImportName] = pragmaImportName.split(".");
|
||||
}
|
||||
|
||||
let pragmaFragImportName = fileJsxPragmaFrag || jsxPragmaFrag;
|
||||
if (pragmaFragImportName) {
|
||||
[pragmaFragImportName] = pragmaFragImportName.split(".");
|
||||
}
|
||||
|
||||
// remove type imports
|
||||
for (let stmt of path.get("body")) {
|
||||
if (t.isImportDeclaration(stmt)) {
|
||||
@ -221,7 +233,8 @@ export default declare(
|
||||
isImportTypeOnly({
|
||||
binding,
|
||||
programPath: path,
|
||||
jsxPragma: pragmaImportName,
|
||||
pragmaImportName,
|
||||
pragmaFragImportName,
|
||||
})
|
||||
) {
|
||||
importsToRemove.push(binding.path);
|
||||
@ -456,25 +469,31 @@ export default declare(
|
||||
// 'access' and 'readonly' are only for parameter properties, so constructor visitor will handle them.
|
||||
}
|
||||
|
||||
function isImportTypeOnly({ binding, programPath, jsxPragma }) {
|
||||
function isImportTypeOnly({
|
||||
binding,
|
||||
programPath,
|
||||
pragmaImportName,
|
||||
pragmaFragImportName,
|
||||
}) {
|
||||
for (const path of binding.referencePaths) {
|
||||
if (!isInType(path)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (binding.identifier.name !== jsxPragma) {
|
||||
if (
|
||||
binding.identifier.name !== pragmaImportName &&
|
||||
binding.identifier.name !== pragmaFragImportName
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// "React" or the JSX pragma is referenced as a value if there are any JSX elements in the code.
|
||||
// "React" or the JSX pragma is referenced as a value if there are any JSX elements/fragments in the code.
|
||||
let sourceFileHasJsx = false;
|
||||
programPath.traverse({
|
||||
JSXElement() {
|
||||
sourceFileHasJsx = true;
|
||||
},
|
||||
JSXFragment() {
|
||||
"JSXElement|JSXFragment"(path) {
|
||||
sourceFileHasJsx = true;
|
||||
path.stop();
|
||||
},
|
||||
});
|
||||
return !sourceFileHasJsx;
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
/* @jsxFrag jsx.htm */
|
||||
// Don't elide htm if a JSX fragment appears somewhere.
|
||||
import * as jsx from "fake-jsx-package";
|
||||
<></>;
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"plugins": [["transform-typescript", { "isTSX": true }]]
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
/* @jsxFrag jsx.htm */
|
||||
// Don't elide htm if a JSX fragment appears somewhere.
|
||||
import * as jsx from "fake-jsx-package";
|
||||
<></>;
|
||||
@ -0,0 +1,4 @@
|
||||
/* @jsxFrag htm */
|
||||
// Don't elide htm if a JSX fragment appears somewhere.
|
||||
import { htm } from "fake-jsx-package";
|
||||
<></>;
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"plugins": [["transform-typescript", { "isTSX": true }]]
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
/* @jsxFrag htm */
|
||||
// Don't elide htm if a JSX fragment appears somewhere.
|
||||
import { htm } from "fake-jsx-package";
|
||||
<></>;
|
||||
3
packages/babel-plugin-transform-typescript/test/fixtures/imports/elide-preact-no-2/input.ts
vendored
Normal file
3
packages/babel-plugin-transform-typescript/test/fixtures/imports/elide-preact-no-2/input.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
// Don't elide Preact if a JSX fragment appears somewhere.
|
||||
import { Fragment, render } from "preact";
|
||||
<></>;
|
||||
@ -0,0 +1,8 @@
|
||||
{
|
||||
"plugins": [
|
||||
[
|
||||
"transform-typescript",
|
||||
{ "jsxPragma": "h", "jsxPragmaFrag": "Fragment", "isTSX": true }
|
||||
]
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
// Don't elide Preact if a JSX fragment appears somewhere.
|
||||
import { Fragment } from "preact";
|
||||
<></>;
|
||||
@ -1,3 +1,4 @@
|
||||
// Don't elide Preact if a JSX element appears somewhere.
|
||||
import { h, render } from "preact";
|
||||
import { h, Fragment, render } from "preact";
|
||||
<div></div>;
|
||||
<></>;
|
||||
|
||||
@ -1,3 +1,8 @@
|
||||
{
|
||||
"plugins": [["transform-typescript", { "jsxPragma": "h", "isTSX": true }]]
|
||||
"plugins": [
|
||||
[
|
||||
"transform-typescript",
|
||||
{ "jsxPragma": "h", "jsxPragmaFrag": "Fragment", "isTSX": true }
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
// Don't elide Preact if a JSX element appears somewhere.
|
||||
import { h } from "preact";
|
||||
import { h, Fragment } from "preact";
|
||||
<div></div>;
|
||||
<></>;
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
import { FooBar, h } from "preact";
|
||||
import { FooBar, h, Fragment } from "preact";
|
||||
const x: FooBar = 0;
|
||||
|
||||
@ -9,12 +9,17 @@ export default declare(
|
||||
allowDeclareFields,
|
||||
allowNamespaces,
|
||||
jsxPragma,
|
||||
jsxPragmaFrag = "React.Fragment",
|
||||
isTSX = false,
|
||||
onlyRemoveTypeImports,
|
||||
},
|
||||
) => {
|
||||
api.assertVersion(7);
|
||||
|
||||
if (typeof jsxPragmaFrag !== "string") {
|
||||
throw new Error(".jsxPragmaFrag must be a string, or undefined");
|
||||
}
|
||||
|
||||
if (typeof allExtensions !== "boolean") {
|
||||
throw new Error(".allExtensions must be a boolean, or undefined");
|
||||
}
|
||||
@ -32,6 +37,7 @@ export default declare(
|
||||
allowNamespaces,
|
||||
isTSX,
|
||||
jsxPragma,
|
||||
jsxPragmaFrag,
|
||||
onlyRemoveTypeImports,
|
||||
});
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user