Skip to content

Commit c223f9a

Browse files
ThomasRoestThomas Roest
and
Thomas Roest
authored
fix: prevent unnecessary wrapping of single line jsx elements (#2183)
When having a single line statement with an import statement everything works as expected. ```jsx import * as React from "react"; <ReactComponent />; ``` However if you remove the import statement, a semicolon `;` appears in the output. We no longer need the explicit import statements as this can be configured globally, and we have an eslint rule requiring us to close every js statement with a semicolon. ```jsx <ReactComponent />; ``` This happens because of the fix/changes done in this issue: #842, which causes every statement starting with JSX to be wrapped in a Fragment. This will cause the semicolon to be added inside the Fragment, and cause it to be rendered. This change causes the examples to only be wrapped in a Fragment if multiple jsx statements are returned on root level of the example by checking for the error before wrapping. Co-authored-by: Thomas Roest <[email protected]>
1 parent 3ae63b6 commit c223f9a

File tree

2 files changed

+26
-14
lines changed

2 files changed

+26
-14
lines changed

src/client/utils/__tests__/compileCode.spec.ts

+9-11
Original file line numberDiff line numberDiff line change
@@ -51,18 +51,16 @@ React.createElement( Button, null )"
5151
`);
5252
});
5353

54-
test('wrap JSX in Fragment', () => {
55-
const result = compileCode(
56-
`<div>
57-
<button>Click</button>
58-
</div>`,
59-
compilerConfig
54+
test('wrap JSX in Fragment if adjacent on line 1', () => {
55+
const result = compileCode(`<span /><span />`, compilerConfig);
56+
expect(result).toMatchInlineSnapshot(
57+
`"React.createElement( React.Fragment, null, React.createElement( 'span', null ), React.createElement( 'span', null ) );"`
6058
);
61-
expect(result).toMatchInlineSnapshot(`
62-
"React.createElement( React.Fragment, null, React.createElement( 'div', null,
63-
React.createElement( 'button', null, \\"Click\\" )
64-
) );"
65-
`);
59+
});
60+
61+
test('don’t wrap JSX in Fragment if there is only one statement', () => {
62+
const result = compileCode(`<Button />;`, compilerConfig);
63+
expect(result).toMatchInlineSnapshot(`"React.createElement( Button, null );"`);
6664
});
6765

6866
test('don’t wrap JSX in Fragment if it’s in the middle', () => {

src/client/utils/compileCode.ts

+17-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,23 @@ export default function compileCode(
1818
onError?: (err: Error) => void
1919
): string {
2020
try {
21-
const wrappedCode = startsWithJsx(code) ? wrapCodeInFragment(code) : code;
22-
const compiledCode = compile(wrappedCode, compilerConfig);
23-
return transpileImports(compiledCode);
21+
let compiledCode;
22+
23+
try {
24+
compiledCode = compile(code, compilerConfig);
25+
} catch (err) {
26+
if (
27+
err instanceof SyntaxError &&
28+
err.message.startsWith('Adjacent JSX elements must be wrapped in an enclosing tag')
29+
) {
30+
const wrappedCode = startsWithJsx(code) ? wrapCodeInFragment(code) : code;
31+
compiledCode = compile(wrappedCode, compilerConfig);
32+
} else if (onError && err instanceof Error) {
33+
onError(err);
34+
}
35+
}
36+
37+
return compiledCode ? transpileImports(compiledCode) : '';
2438
} catch (err) {
2539
if (onError && err instanceof Error) {
2640
onError(err);

0 commit comments

Comments
 (0)