Skip to content

Commit be019f1

Browse files
authoredNov 7, 2023
Extend jsx-pragma eslint rule: detect mixing Compiled with Emotion, and only run if importing Compiled (#1551)
* Extend jsx-pragma to support onlyRunIfImportingCompiled and detectConflictWithOtherLibraries * Raise linting error when Compiled styled API is mixed with Emotion * Add changeset * Restore xcss tests
1 parent 2395a10 commit be019f1

File tree

7 files changed

+442
-27
lines changed

7 files changed

+442
-27
lines changed
 

‎.changeset/smooth-shirts-guess.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
'@compiled/eslint-plugin': minor
3+
'@compiled/babel-plugin': patch
4+
'@compiled/react': patch
5+
---
6+
7+
Add detectConflictWithOtherLibraries and onlyRunIfImportingCompiled config options to jsx-pragma ESLint rule. Both are set to true by default, hence the breaking change.
8+
9+
`detectConflictWithOtherLibraries` raises a linting error if `css` or `jsx` is imported from `@emotion/react` (or `@emotion/core`) in the same file
10+
as a Compiled import. Set to true by default.
11+
12+
`onlyRunIfImportingCompiled` sets this rule to only suggest adding the JSX pragma if the `css` or `cssMap` functions are imported from `@compiled/react`, as opposed to whenever the `css` attribute is detected at all. Set to false by default.

‎packages/eslint-plugin/src/rules/jsx-pragma/README.md

+72-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
11
# `jsx-pragma`
22

3-
Enforce a jsx pragma is set when using the `css` prop.
3+
Ensure that the Compiled JSX pragma is set when using the `css` or `xcss` prop.
4+
5+
A JSX pragma is a comment that declares where to import the JSX namespace from. It looks
6+
like one of the following:
7+
8+
```js
9+
/** @jsx jsx */
10+
import { jsx } from '@compiled/react';
11+
```
12+
13+
```js
14+
/** @jsxImportSource @compiled/react */
15+
import { jsx } from '@compiled/react';
16+
```
17+
18+
For all Compiled usages, one of these should be used. See the
19+
[Emotion documentation](https://emotion.sh/docs/css-prop#jsx-pragma) for more details
20+
on how JSX pragmas work.
421

522
---
623

@@ -35,6 +52,26 @@ import '@compiled/react';
3552
^^^ missing pragma
3653
```
3754

55+
```js
56+
// [{ "pragma": "jsxImportSource" }]
57+
58+
import { Box } from '@atlaskit/primitives';
59+
60+
<Box xcss={{ borderStyle: 'solid' }} />;
61+
^^^ missing pragma
62+
```
63+
64+
```js
65+
// [{ "detectConflictWithOtherLibraries": true }]
66+
67+
/** @jsx jsx */
68+
import { css } from '@compiled/react';
69+
import { jsx } from '@emotion/react';
70+
71+
<div css={css({ display: 'block' })} />;
72+
^^^ cannot mix Compiled and Emotion
73+
```
74+
3875
👍 Examples of **correct** code for this rule:
3976

4077
```js
@@ -52,6 +89,19 @@ import { jsx } from '@compiled/react';
5289
<div css={{ display: 'block' }} />
5390
```
5491

92+
```js
93+
// [{ "onlyRunIfImportingCompiled": true }]
94+
95+
import { css } from '@emotion/react';
96+
<div css={css({ display: 'block' })} />;
97+
```
98+
99+
```js
100+
// [{ "onlyRunIfImportingCompiled": true }]
101+
102+
<div css={{ display: 'block' }} />
103+
```
104+
55105
## Options
56106

57107
This rule supports the following options:
@@ -60,3 +110,24 @@ This rule supports the following options:
60110

61111
What [JSX runtime](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html) to adhere to,
62112
defaults to automatic.
113+
114+
### `detectConflictWithOtherLibraries: boolean`
115+
116+
Raises a linting error if `css` or `jsx` is imported from `@emotion/react` (or `@emotion/core`) in the same file
117+
as a Compiled import.
118+
119+
This is important as Emotion can't be used with Compiled in the same file, and ignoring this linting error will
120+
result in a confusing runtime error.
121+
122+
This defaults to `true`.
123+
124+
### `onlyRunIfImportingCompiled: boolean`
125+
126+
By default, the `jsx-pragma` rule suggests adding the Compiled JSX pragma whenever the `css` attribute is being
127+
used. This may not be ideal if your codebase uses a mix of Compiled and other libraries (e.g. Emotion,
128+
styled-components). Setting `onlyRunIfImportingCompiled` to true turns off this rule unless `css` or `cssMap`
129+
are imported from `@compiled/react`.
130+
131+
Note that this option does not affect `xcss`.
132+
133+
This option defaults to `false`.

‎packages/eslint-plugin/src/rules/jsx-pragma/__tests__/rule.test.ts

+202-7
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,70 @@ tester.run('jsx-pragma', jsxPragmaRule, {
2323
`,
2424
{
2525
code: `
26-
/** @jsxImportSource @compiled/react */
27-
<div css={{ display: 'block' }} />
28-
`,
26+
/** @jsxImportSource @compiled/react */
27+
<div css={{ display: 'block' }} />
28+
`,
2929
options: [{ runtime: 'automatic' }],
3030
},
3131
{
3232
code: `
33-
/** @jsx jsx */
34-
import { jsx } from '@compiled/react';
35-
<div css={{ display: 'block' }} />
36-
`,
33+
/** @jsx jsx */
34+
import { jsx } from '@compiled/react';
35+
<div css={{ display: 'block' }} />
36+
`,
37+
options: [{ runtime: 'classic' }],
38+
},
39+
{
40+
name: "don't error when @jsxImportSource and Compiled css API are being used",
41+
code: `
42+
/** @jsxImportSource @compiled/react */
43+
import { css } from '@compiled/react';
44+
<div css={css({ display: 'block' })} />
45+
`,
46+
options: [{ runtime: 'automatic' }],
47+
},
48+
{
49+
code: `
50+
/** @jsx jsx */
51+
import { css, jsx } from '@compiled/react';
52+
<div css={css({ display: 'block' })} />
53+
`,
3754
options: [{ runtime: 'classic' }],
3855
},
56+
{
57+
name: "when onlyRunIfImportingCompiled is true and Compiled is not imported, don't override with Compiled",
58+
code: `<div css={{ display: 'block' }} />`,
59+
options: [{ onlyRunIfImportingCompiled: true }],
60+
},
61+
{
62+
name: "when onlyRunIfImportingCompiled is true and Emotion jsx is used, don't override with Compiled",
63+
code: `
64+
/** @jsx jsx */
65+
import { jsx } from '@emotion/react';
66+
<>
67+
<div css={{ display: 'block' }} />
68+
<div css={[ someStyles ]} />
69+
</>
70+
`,
71+
options: [{ onlyRunIfImportingCompiled: true }],
72+
},
73+
{
74+
name: "when onlyRunIfImportingCompiled is true and Emotion css is used, don't override with Compiled (with Emotion css function)",
75+
code: `
76+
import { css } from '@emotion/react';
77+
<div css={css({ display: 'block' })} />
78+
`,
79+
options: [{ onlyRunIfImportingCompiled: true }],
80+
},
81+
{
82+
name: "when onlyRunIfImportingCompiled is true and Emotion css is used, don't override with Compiled (with Emotion css and jsx)",
83+
code: `
84+
/** @jsx jsx */
85+
import { css, jsx } from '@emotion/react';
86+
<div css={css({ display: 'block' })} />
87+
`,
88+
options: [{ onlyRunIfImportingCompiled: true }],
89+
},
3990
],
4091
invalid: [
4192
{
@@ -340,5 +391,149 @@ import * as React from 'react';
340391
},
341392
],
342393
},
394+
{
395+
name: 'should error if Emotion css and Compiled styled are used',
396+
code: `
397+
import { css } from '@emotion/react';
398+
import { styled } from '@compiled/react';
399+
<div css={css({ display: 'block' })} />
400+
`,
401+
errors: [
402+
{
403+
messageId: 'emotionAndCompiledConflict',
404+
},
405+
],
406+
},
407+
{
408+
name: 'should error if Emotion css and Compiled styled are used (onlyRunIfImportingCompiled = true)',
409+
code: `
410+
import { css } from '@emotion/react';
411+
import { styled } from '@compiled/react';
412+
<div css={css({ display: 'block' })} />
413+
`,
414+
options: [{ onlyRunIfImportingCompiled: true }],
415+
errors: [
416+
{
417+
messageId: 'emotionAndCompiledConflict',
418+
},
419+
],
420+
},
421+
{
422+
name: 'should error when both Emotion and Compiled css APIs are being used',
423+
code: `
424+
/** @jsx jsx */
425+
import * as React from 'react';
426+
import { css, jsx } from '@emotion/react';
427+
import { css as cssCompiled } from '@compiled/react';
428+
429+
<div css={css({ display: 'block' })} />
430+
`,
431+
options: [{ onlyRunIfImportingCompiled: true }],
432+
errors: [
433+
{
434+
messageId: 'emotionAndCompiledConflict',
435+
},
436+
],
437+
},
438+
{
439+
name: 'should error when both Emotion and Compiled css APIs are being used (alt)',
440+
code: `
441+
/** @jsx jsxEmotion */
442+
import * as React from 'react';
443+
import { css, jsx as jsxEmotion } from '@emotion/react';
444+
import { css as cssCompiled } from '@compiled/react';
445+
446+
<div css={css({ display: 'block' })} />
447+
`,
448+
options: [{ onlyRunIfImportingCompiled: true }],
449+
errors: [
450+
{
451+
messageId: 'emotionAndCompiledConflict',
452+
},
453+
],
454+
},
455+
{
456+
name: 'should error when both Emotion jsx API and Compiled css API are being used',
457+
code: `
458+
import * as React from 'react';
459+
import { jsx } from '@emotion/react';
460+
import { css } from '@compiled/react';
461+
462+
<div css={css({ display: 'block' })} />
463+
`,
464+
options: [{ onlyRunIfImportingCompiled: true }],
465+
errors: [
466+
{
467+
messageId: 'emotionAndCompiledConflict',
468+
},
469+
],
470+
},
471+
{
472+
name: 'should error when both Emotion jsx API and Compiled css API are being used (with JSX pragma)',
473+
code: `
474+
/** @jsx jsx */
475+
import * as React from 'react';
476+
import { jsx } from '@emotion/react';
477+
import { css } from '@compiled/react';
478+
479+
<div css={css({ display: 'block' })} />
480+
`,
481+
options: [{ onlyRunIfImportingCompiled: true }],
482+
errors: [
483+
{
484+
messageId: 'emotionAndCompiledConflict',
485+
},
486+
],
487+
},
488+
{
489+
name: 'should error when both Emotion css API and Compiled jsx API are being used (with JSX pragma)',
490+
code: `
491+
/** @jsx jsx */
492+
import * as React from 'react';
493+
import { jsx } from '@compiled/react';
494+
import { css } from '@emotion/react';
495+
496+
<div css={css({ display: 'block' })} />
497+
`,
498+
options: [{ onlyRunIfImportingCompiled: true, runtime: 'classic' }],
499+
errors: [
500+
{
501+
messageId: 'emotionAndCompiledConflict',
502+
},
503+
],
504+
},
505+
{
506+
name: 'should error when both Emotion and Compiled css APIs are being used (with @emotion/core)',
507+
code: `
508+
/** @jsx jsxEmotion */
509+
import * as React from 'react';
510+
import { jsx } from '@emotion/core';
511+
import { css as cssCompiled } from '@compiled/react';
512+
513+
<div css={{ display: 'block' }} />
514+
`,
515+
options: [{ onlyRunIfImportingCompiled: true }],
516+
errors: [
517+
{
518+
messageId: 'emotionAndCompiledConflict',
519+
},
520+
],
521+
},
522+
{
523+
name: 'should error when both Emotion and Compiled css APIs are being used (onlyRunIfImportingCompiled = true)',
524+
code: `
525+
import * as React from 'react';
526+
import { css } from '@emotion/react';
527+
import { css as cssCompiled } from '@compiled/react';
528+
529+
<div css={css({ display: 'block' })} />
530+
`,
531+
options: [{ onlyRunIfImportingCompiled: true }],
532+
errors: [
533+
{
534+
messageId: 'emotionAndCompiledConflict',
535+
},
536+
],
537+
},
343538
],
344539
});

‎packages/eslint-plugin/src/rules/jsx-pragma/index.ts

+73-13
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,45 @@
11
import type { Rule, SourceCode } from 'eslint';
22
import type { ImportDeclaration, ImportDefaultSpecifier, ImportNamespaceSpecifier } from 'estree';
33

4-
import { findCompiledImportDeclarations, findDeclarationWithImport } from '../../utils/ast';
4+
import {
5+
findDeclarationWithImport,
6+
findLibraryImportDeclarations,
7+
usesCompiledAPI,
8+
} from '../../utils/ast';
59
import { addImportToDeclaration, removeImportFromDeclaration } from '../../utils/ast-to-string';
10+
import { findJsxImportSourcePragma, findJsxPragma } from '../../utils/jsx';
611

712
type Options = {
13+
detectConflictWithOtherLibraries: boolean;
14+
onlyRunIfImportingCompiled: boolean;
815
runtime: 'classic' | 'automatic';
916
};
1017

18+
const getOtherLibraryImports = (context: Rule.RuleContext): ImportDeclaration[] => {
19+
const PROBLEMATIC_IMPORT_SPECIFIERS: readonly string[] = ['css', 'jsx'];
20+
21+
const PROBLEMATIC_LIBRARIES = ['@emotion/core', '@emotion/react'];
22+
const otherLibraryImports = findLibraryImportDeclarations(context, PROBLEMATIC_LIBRARIES);
23+
24+
const detectedLibraries: ImportDeclaration[] = [];
25+
26+
for (const importDecl of otherLibraryImports) {
27+
for (const specifier of importDecl.specifiers) {
28+
if (
29+
specifier.type === 'ImportSpecifier' &&
30+
PROBLEMATIC_IMPORT_SPECIFIERS.includes(specifier.imported.name)
31+
) {
32+
const sourceLibrary = importDecl.source.value;
33+
if (typeof sourceLibrary === 'string' && PROBLEMATIC_LIBRARIES.includes(sourceLibrary)) {
34+
detectedLibraries.push(importDecl);
35+
}
36+
}
37+
}
38+
}
39+
40+
return detectedLibraries;
41+
};
42+
1143
const findReactDeclarationWithDefaultImport = (
1244
source: SourceCode
1345
): [ImportDeclaration, ImportDefaultSpecifier | ImportNamespaceSpecifier] | undefined => {
@@ -28,6 +60,8 @@ const findReactDeclarationWithDefaultImport = (
2860
};
2961

3062
function createFixer(context: Rule.RuleContext, source: SourceCode, options: Options) {
63+
const compiledImports = findLibraryImportDeclarations(context);
64+
3165
return function* fix(fixer: Rule.RuleFixer) {
3266
const pragma = options.runtime === 'classic' ? '@jsx jsx' : '@jsxImportSource @compiled/react';
3367
const reactImport = findReactDeclarationWithDefaultImport(source);
@@ -48,8 +82,6 @@ function createFixer(context: Rule.RuleContext, source: SourceCode, options: Opt
4882

4983
yield fixer.insertTextBefore(source.ast.body[0], `/** ${pragma} */\n`);
5084

51-
const compiledImports = findCompiledImportDeclarations(context);
52-
5385
if (options.runtime === 'classic' && !findDeclarationWithImport(compiledImports, 'jsx')) {
5486
// jsx import is missing time to add one
5587
if (compiledImports.length === 0) {
@@ -84,6 +116,8 @@ export const jsxPragmaRule: Rule.RuleModule = {
84116
'Use of the jsxImportSource pragma (automatic runtime) is preferred over the jsx pragma (classic runtime).',
85117
preferJsx:
86118
'Use of the jsx pragma (classic runtime) is preferred over the jsx pragma (automatic runtime).',
119+
emotionAndCompiledConflict:
120+
"You can't have css/styled/jsx be imported from both Emotion and Compiled in the same file - this will cause type-checking and runtime errors. Consider changing all of your Emotion imports from `@emotion/react` to `@compiled/react`.",
87121
},
88122
schema: [
89123
{
@@ -93,20 +127,34 @@ export const jsxPragmaRule: Rule.RuleModule = {
93127
type: 'string',
94128
pattern: '^(classic|automatic)$',
95129
},
130+
detectConflictWithOtherLibraries: {
131+
type: 'boolean',
132+
},
133+
onlyRunIfImportingCompiled: {
134+
type: 'boolean',
135+
},
96136
},
97137
additionalProperties: false,
98138
},
99139
],
100140
type: 'problem',
101141
},
142+
102143
create(context) {
103-
const options: Options = context.options[0] || { runtime: 'automatic' };
144+
const optionsRaw = context.options[0] || {};
145+
const options: Options = {
146+
detectConflictWithOtherLibraries: optionsRaw.detectConflictWithOtherLibraries ?? true,
147+
onlyRunIfImportingCompiled: optionsRaw.onlyRunIfImportingCompiled ?? false,
148+
runtime: optionsRaw.runtime ?? 'automatic',
149+
};
150+
104151
const source = context.getSourceCode();
105152
const comments = source.getAllComments();
106-
const jsxPragma = comments.find((n) => n.value.indexOf('@jsx jsx') > -1);
107-
const jsxImportSourcePragma = comments.find(
108-
(n) => n.value.indexOf('@jsxImportSource @compiled/react') > -1
109-
);
153+
154+
const compiledImports = findLibraryImportDeclarations(context);
155+
const otherLibraryImports = getOtherLibraryImports(context);
156+
const jsxPragma = findJsxPragma(comments, compiledImports);
157+
const jsxImportSourcePragma = findJsxImportSourcePragma(comments);
110158

111159
return {
112160
Program() {
@@ -117,7 +165,6 @@ export const jsxPragmaRule: Rule.RuleModule = {
117165
*fix(fixer) {
118166
yield fixer.replaceText(jsxPragma as any, '/** @jsxImportSource @compiled/react */');
119167

120-
const compiledImports = findCompiledImportDeclarations(context);
121168
const jsxImport = findDeclarationWithImport(compiledImports, 'jsx');
122169
if (!jsxImport) {
123170
return;
@@ -144,7 +191,7 @@ export const jsxPragmaRule: Rule.RuleModule = {
144191
*fix(fixer) {
145192
yield fixer.replaceText(jsxImportSourcePragma as any, '/** @jsx jsx */');
146193

147-
const compiledImports = findCompiledImportDeclarations(context);
194+
const compiledImports = findLibraryImportDeclarations(context);
148195
const jsxImport = findDeclarationWithImport(compiledImports, 'jsx');
149196
if (jsxImport) {
150197
return;
@@ -186,17 +233,30 @@ export const jsxPragmaRule: Rule.RuleModule = {
186233
}
187234
},
188235

189-
JSXAttribute(node: any) {
190-
if (jsxPragma || jsxImportSourcePragma || node.name.name !== 'css') {
236+
'JSXAttribute[name.name=/^css$/]': (node: Rule.Node) => {
237+
if (options.onlyRunIfImportingCompiled && !usesCompiledAPI(compiledImports)) {
238+
return;
239+
}
240+
241+
if (options.detectConflictWithOtherLibraries && otherLibraryImports.length) {
242+
context.report({
243+
node: otherLibraryImports[0],
244+
messageId: 'emotionAndCompiledConflict',
245+
});
246+
247+
return;
248+
}
249+
250+
if (node.type !== 'JSXAttribute' || jsxPragma || jsxImportSourcePragma) {
191251
return;
192252
}
193253

194254
context.report({
255+
node,
195256
messageId: 'missingPragma',
196257
data: {
197258
pragma: options.runtime === 'classic' ? 'jsx' : 'jsxImportSource',
198259
},
199-
node,
200260
fix: createFixer(context, source, options),
201261
});
202262
},

‎packages/eslint-plugin/src/utils/ast.ts

+38-4
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,27 @@ import type { ImportDeclaration, ImportSpecifier } from 'estree';
55
import { COMPILED_IMPORT } from './constants';
66

77
/**
8-
* Given a rule, return any `@compiled/react` nodes in the source being parsed.
8+
* Given a rule, return all imports from the libraries defined in `source`
9+
* in the file. If `source` is not specified, return all import statements
10+
* from `@compiled/react`.
911
*
1012
* @param context Rule context
11-
* @returns {Rule.Node} The `@compiled/react` node or undefined
13+
* @param sources An array containing all the libraries for which we want to
14+
* find import statements
15+
* @returns {Rule.Node} All import statements from `source` (or from
16+
* `@compiled/react` by default)
1217
*/
13-
export const findCompiledImportDeclarations = (context: Rule.RuleContext): ImportDeclaration[] => {
18+
export const findLibraryImportDeclarations = (
19+
context: Rule.RuleContext,
20+
sources = [COMPILED_IMPORT]
21+
): ImportDeclaration[] => {
1422
return context
1523
.getSourceCode()
1624
.ast.body.filter(
1725
(node): node is ImportDeclaration =>
18-
node.type === 'ImportDeclaration' && node.source.value === COMPILED_IMPORT
26+
node.type === 'ImportDeclaration' &&
27+
typeof node.source.value === 'string' &&
28+
sources.includes(node.source.value)
1929
);
2030
};
2131

@@ -85,3 +95,27 @@ export const findDeclarationWithImport = (
8595
)
8696
);
8797
};
98+
99+
const COMPILED_IMPORTS: readonly string[] = ['css', 'cssMap', 'styled', 'jsx'];
100+
101+
/**
102+
* Given an array of import statements, return whether there are any Compiled imports
103+
* from `@compiled/react`.
104+
*
105+
* @param source an array of import declarations
106+
* @returns whether any Compiled APIs are being imported from @compiled/react
107+
*/
108+
export const usesCompiledAPI = (imports: ImportDeclaration[]): boolean => {
109+
for (const importDeclaration of imports) {
110+
for (const specifier of importDeclaration.specifiers) {
111+
if (
112+
specifier.type === 'ImportSpecifier' &&
113+
COMPILED_IMPORTS.includes(specifier.imported.name)
114+
) {
115+
return true;
116+
}
117+
}
118+
}
119+
120+
return false;
121+
};

‎packages/eslint-plugin/src/utils/create-no-exported-rule/is-styled-component.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { Rule } from 'eslint';
22
import type { MemberExpression, Identifier } from 'estree';
33

4-
import { findCompiledImportDeclarations } from '../ast';
4+
import { findLibraryImportDeclarations } from '../ast';
55

66
type Node = Rule.Node;
77
type RuleContext = Rule.RuleContext;
@@ -48,7 +48,7 @@ const findNode = (nodes: Node[]): MemberExpression | Identifier | undefined => {
4848
* @returns
4949
*/
5050
const getStyledImportSpecifierName = (context: RuleContext): string | undefined => {
51-
const compiledImports = findCompiledImportDeclarations(context);
51+
const compiledImports = findLibraryImportDeclarations(context);
5252

5353
return compiledImports[0].specifiers.find(
5454
(spec) => spec.type === 'ImportSpecifier' && spec.imported.name === 'styled'
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import type { Comment, ImportDeclaration } from 'estree';
2+
3+
/**
4+
* Return the "@ jsx jsx" JSX pragma (i.e. a comment that has special
5+
* meaning to the TypeScript compiler), if it exists AND if jsx is
6+
* imported from "@compiled/react".
7+
*/
8+
export const findJsxPragma = (
9+
comments: Comment[],
10+
compiledImports: ImportDeclaration[]
11+
): Comment | undefined => {
12+
let jsxPragma: Comment | undefined = undefined;
13+
// It is surprisingly possible to specify the JSX pragma with a
14+
// value other than "jsx", e.g. "@ jsx myCustomJsxFunction", as long
15+
// as that is imported somehow (e.g. import { myCustomJsxFunction } from 'xyz').
16+
let jsxPragmaName = '';
17+
18+
for (const comment of comments) {
19+
const match = /@jsx (\w+)/.exec(comment.value);
20+
if (match) {
21+
jsxPragma = comment;
22+
jsxPragmaName = match[1];
23+
}
24+
}
25+
26+
if (!jsxPragma) return undefined;
27+
28+
for (const importDecl of compiledImports) {
29+
for (const specifier of importDecl.specifiers) {
30+
const jsxPragmaUsesCompiled =
31+
specifier.type === 'ImportSpecifier' &&
32+
specifier.imported.name === 'jsx' &&
33+
specifier.local.name === jsxPragmaName;
34+
35+
if (jsxPragmaUsesCompiled) return jsxPragma;
36+
}
37+
}
38+
39+
return undefined;
40+
};
41+
42+
export const findJsxImportSourcePragma = (comments: Comment[]): Comment | undefined =>
43+
comments.find((n) => n.value.indexOf('@jsxImportSource @compiled/react') > -1);

0 commit comments

Comments
 (0)
Please sign in to comment.