Skip to content

Commit df91c60

Browse files
authored
Fix @compiled/babel-plugin handling of classic JSX pragma (#1603)
* Fix @compiled/babel-plugin handling of classic JSX pragma * Remove `/** @jsx jsx */` and `/** @jsxImportSource @compiled/react */` comments through Compiled babel plugin * Throw error when jsx classic pragma is set in Babel config, or if Compiled APIs and Emotion JSX pragma were mixed in the same file (this would otherwise cause invalid output) * Refactor `@compiled/babel-plugin-strip-runtime` tests
1 parent 190fd06 commit df91c60

File tree

12 files changed

+742
-513
lines changed

12 files changed

+742
-513
lines changed

.changeset/famous-dots-jump.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
'@compiled/babel-plugin-strip-runtime': minor
3+
'@compiled/babel-plugin': minor
4+
---
5+
6+
\[BREAKING\] Fix @compiled/babel-plugin handling of classic JSX pragma. Involves several breaking changes.
7+
8+
- Move the below @compiled/babel-plugin-strip-runtime behaviour to @compiled/babel-plugin
9+
- Classic JSX pragma will no longer affect the Babel output: instead of seeing `jsx` function calls in the output, you will see `React.createElement` calls again. (Added to @compiled/babel-plugin-strip-runtime in v0.27.0)
10+
- @compiled/babel-plugin: Due to the above behaviour change, a classic JSX pragma (`/** @jsx jsx */`) is used, React will always be imported regardless of the value of `importReact`.
11+
- @compiled/babel-plugin: We don't support specifying the `pragma` option through `@babel/preset-react` or `@babel/plugin-transform-react-jsx` - we will now throw an error if this happens.
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
import { writeFileSync } from 'fs';
2+
3+
import { transform } from './transform';
4+
5+
// Mock out FS to avoid writing to disk
6+
// We aren't processing the result anyway, so no need for specifying the response
7+
jest.mock('fs');
8+
9+
describe('babel-plugin-strip-runtime with stylesheet extraction (extractStylesToDirectory)', () => {
10+
describe('with the classic runtime', () => {
11+
const runtime = 'classic';
12+
13+
describe('without JSX pragma', () => {
14+
const code = `
15+
import '@compiled/react';
16+
17+
const Component = () => (
18+
<div css={{ fontSize: 12, color: 'blue' }}>
19+
hello world
20+
</div>
21+
);
22+
`;
23+
24+
it('adds styles to directory', () => {
25+
const actual = transform(code, {
26+
run: 'both',
27+
runtime,
28+
extractStylesToDirectory: { source: 'src/', dest: 'dist/' },
29+
});
30+
31+
expect(actual).toMatchInlineSnapshot(`
32+
"/* app.tsx generated by @compiled/babel-plugin v0.0.0 */
33+
import './app.compiled.css';
34+
import * as React from 'react';
35+
import { ax, ix } from '@compiled/react/runtime';
36+
const Component = () =>
37+
/*#__PURE__*/ React.createElement(
38+
'div',
39+
{
40+
className: ax(['_1wyb1fwx _syaz13q2']),
41+
},
42+
'hello world'
43+
);
44+
"
45+
`);
46+
47+
expect(writeFileSync).toBeCalledWith(
48+
expect.stringContaining('app.compiled.css'),
49+
'._1wyb1fwx{font-size:12px}\n._syaz13q2{color:blue}'
50+
);
51+
});
52+
53+
it('error when source directory is not found', () => {
54+
expect(() =>
55+
transform(code, {
56+
run: 'both',
57+
runtime,
58+
extractStylesToDirectory: { source: 'not-existing-src/', dest: 'dist/' },
59+
})
60+
).toThrowWithMessage(
61+
Error,
62+
`/base/src/app.tsx: Source directory 'not-existing-src/' was not found relative to source file ('../src/app.tsx')`
63+
);
64+
});
65+
});
66+
67+
describe('with JSX pragma', () => {
68+
it('extracts styles into app.compiled.css', () => {
69+
const codeWithPragma = `
70+
/** @jsx myJsx */
71+
import { css, jsx as myJsx } from '@compiled/react';
72+
73+
const Component = () => (
74+
<div css={{ fontSize: 12, color: 'blue' }}>
75+
hello world 2
76+
</div>
77+
);
78+
79+
const Component2 = () => (
80+
<div css={css({ fontSize: 12, color: 'pink' })}>
81+
hello world 2
82+
</div>
83+
);
84+
`;
85+
86+
const actual = transform(codeWithPragma, {
87+
run: 'both',
88+
runtime: 'classic',
89+
extractStylesToDirectory: { source: 'src/', dest: 'dist/' },
90+
});
91+
92+
expect(actual).toMatchInlineSnapshot(`
93+
"/* app.tsx generated by @compiled/babel-plugin v0.0.0 */
94+
import './app.compiled.css';
95+
import * as React from 'react';
96+
import { ax, ix } from '@compiled/react/runtime';
97+
const Component = () =>
98+
/*#__PURE__*/ React.createElement(
99+
'div',
100+
{
101+
className: ax(['_1wyb1fwx _syaz13q2']),
102+
},
103+
'hello world 2'
104+
);
105+
const Component2 = () =>
106+
/*#__PURE__*/ React.createElement(
107+
'div',
108+
{
109+
className: ax(['_1wyb1fwx _syaz32ev']),
110+
},
111+
'hello world 2'
112+
);
113+
"
114+
`);
115+
});
116+
});
117+
});
118+
119+
describe('with the automatic runtime', () => {
120+
describe('with JSX pragma', () => {
121+
it('extracts styles into app.compiled.css', () => {
122+
const codeWithPragma = `
123+
/** @jsxImportSource @compiled/react */
124+
import { css } from '@compiled/react';
125+
126+
const Component = () => (
127+
<div css={{ fontSize: 12, color: 'blue' }}>
128+
hello world 2
129+
</div>
130+
);
131+
132+
const Component2 = () => (
133+
<div css={css({ fontSize: 12, color: 'pink' })}>
134+
hello world 2
135+
</div>
136+
);
137+
`;
138+
139+
const actual = transform(codeWithPragma, {
140+
run: 'both',
141+
runtime: 'automatic',
142+
extractStylesToDirectory: { source: 'src/', dest: 'dist/' },
143+
});
144+
145+
expect(actual).toMatchInlineSnapshot(`
146+
"/* app.tsx generated by @compiled/babel-plugin v0.0.0 */
147+
import './app.compiled.css';
148+
import { ax, ix } from '@compiled/react/runtime';
149+
import { jsxs as _jsxs } from 'react/jsx-runtime';
150+
import { jsx as _jsx } from 'react/jsx-runtime';
151+
const Component = () =>
152+
/*#__PURE__*/ _jsx('div', {
153+
className: ax(['_1wyb1fwx _syaz13q2']),
154+
children: 'hello world 2',
155+
});
156+
const Component2 = () =>
157+
/*#__PURE__*/ _jsx('div', {
158+
className: ax(['_1wyb1fwx _syaz32ev']),
159+
children: 'hello world 2',
160+
});
161+
"
162+
`);
163+
});
164+
});
165+
});
166+
});

0 commit comments

Comments
 (0)