Skip to content

Commit

Permalink
fixed inline constant tag name in JSX transformation
Browse files Browse the repository at this point in the history
  • Loading branch information
AhmadFaraz-crypto authored and pionxzh committed May 1, 2024
1 parent 8546f81 commit b07e977
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 10 deletions.
66 changes: 61 additions & 5 deletions packages/unminify/src/transformations/__tests__/un-jsx.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ function fn() {
`
function fn() {
const Component = r ? "a" : "div";
return <Component>Hello</Component>;
return <div>Hello</div>;
}
`,
)
Expand All @@ -172,16 +172,15 @@ inlineTest('jsx with dynamic Component tag #2',
`
function fn() {
return React.createElement(
components[0],
Components,
null,
"Hello",
);
}
`,
`
function fn() {
const Component = components[0];
return <Component>Hello</Component>;
return <Components>Hello</Components>;
}
`,
)
Expand All @@ -201,11 +200,68 @@ const Foo = () => {
const Foo = () => {
const Component = g ? "p" : "div";
const Component_1 = r ? "a" : "div";
return <div><Component_1 key="b">bar</Component_1><Component key={c}>baz</Component></div>;
return <div><div key="b">bar</div><div key={c}>baz</div></div>;
};
`,
)

inlineTest('jsx with dynamic Component tag #4',
`
function fn() {
const value = "wakaru"
return React.createElement(
value ? "a" : "div",
null,
"Hello",
);
}
`,
`
function fn() {
const value = "wakaru"
const Component = value ? "a" : "div";
return <a>Hello</a>;
}
`,
)

inlineTest('jsx with dynamic Component tag #5',
`
function fn() {
const value = ""
return React.createElement(
value ? "a" : "div",
null,
"Hello",
);
}
`,
`
function fn() {
const value = ""
const Component = value ? "a" : "div";
return <div>Hello</div>;
}
`,
)

inlineTest('jsx with dynamic Component tag #6',
`
function fn() {
const Name = "div";
const attrs = {id: "x"};
return React.createElement(Name, attrs);
}
`,
`
function fn() {
const Name = "div";
const attrs = {id: "x"};
return <div {...attrs} />;
}
`,
)

inlineTest('jsx with child text that should be wrapped',
`
function fn() {
Expand Down
47 changes: 42 additions & 5 deletions packages/unminify/src/transformations/un-jsx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,17 +102,16 @@ export const transformAST: ASTTransformation<typeof Schema> = (context, params)
// bottom-up transformation
.reverse()
.forEach((path) => {
const jsxElement = toJSX(j, path, pragmas, pragmaFrags)
const jsxElement = toJSX(j, path, pragmas, pragmaFrags, root)
if (jsxElement) {
const parentWithComments = j.ExpressionStatement.check(path.parent.node) ? path.parent : path
removePureAnnotation(j, parentWithComments.node)

path.replace(jsxElement)
}
})
}

function toJSX(j: JSCodeshift, path: ASTPath<CallExpression>, pragmas: string[], pragmaFrags: string[]): JSXElement | JSXFragment | null {
function toJSX(j: JSCodeshift, path: ASTPath<CallExpression>, pragmas: string[], pragmaFrags: string[], root: Collection): JSXElement | JSXFragment | null {
const scope = path.scope
assertScopeExists(scope)

Expand All @@ -130,13 +129,51 @@ function toJSX(j: JSCodeshift, path: ASTPath<CallExpression>, pragmas: string[],

if (isCapitalizationInvalid(j, type)) return null

let tag = toJsxTag(j, type)
let tag = toJsxTag(j, type) as JSXIdentifier

// constant tag name will convert into JSX tag
if (tag?.name) {
root.find(j.VariableDeclarator, {
id: {
type: 'Identifier',
name: tag.name,
},
}).forEach((path: any) => {
const { id: { loc: { identifierName } } } = path.node
if (tag.name === identifierName) {
tag = { ...tag, name: path.node?.init?.value }
}
})
}

// If a tag cannot be converted to JSX tag, convert it to a variable
if (!tag && !j.SpreadElement.check(type)) {
const name = generateName('Component', scope)
tag = j.jsxIdentifier(name)

const variableDeclaration = j.variableDeclaration('const', [j.variableDeclarator(j.identifier(name), type)])
const isVariableDeclaration = root.find(j.VariableDeclarator, {
id: {
type: 'Identifier',
name: variableDeclaration.declarations[0].init.test.name,
},
})
// if ternary operator variable value exist
if (isVariableDeclaration.length) {
isVariableDeclaration.forEach((path: any) => {
if (path.node.init.value) {
tag = { ...tag, name: variableDeclaration.declarations[0].init.consequent.value }
}
else {
tag = { ...tag, name: variableDeclaration.declarations[0].init.alternate.value }
}
})
}
else {
if (variableDeclaration.declarations[0].init.alternate.value) {
tag = { ...tag, name: variableDeclaration.declarations[0].init.alternate.value }
}
}
insertBefore(j, path, variableDeclaration)
scope.markAsStale()
}
Expand Down Expand Up @@ -191,7 +228,7 @@ function toJSX(j: JSCodeshift, path: ASTPath<CallExpression>, pragmas: string[],

if (attributes.length === 0) {
const isFrag1 = j.JSXIdentifier.check(tag) && pragmaFrags.includes(tag.name)
const isFrag2 = j.JSXMemberExpression.check(tag) && pragmaFrags.includes(tag.property.name)
const isFrag2 = j.JSXMemberExpression.check(tag) && pragmaFrags.includes((tag as JSXMemberExpression).property.name)
if (isFrag1 || isFrag2) {
return j.jsxFragment(j.jsxOpeningFragment(), j.jsxClosingFragment(), children)
}
Expand Down

0 comments on commit b07e977

Please sign in to comment.