Skip to content

Commit 3cb1ebe

Browse files
feat(compiler): fix import * as React from "react" edge cases in compiler (#1072)
* fix: handle default and namespace imports in compiler * chore: pnpm changeset
1 parent ae31b1c commit 3cb1ebe

File tree

3 files changed

+120
-0
lines changed

3 files changed

+120
-0
lines changed

.changeset/young-bees-glow.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@lingo.dev/_compiler": patch
3+
---
4+
5+
Fixed compiler handling of namespace imports (import \* as React from "react") and default imports.

packages/compiler/src/jsx-fragment.spec.ts

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,101 @@ function Component() {
136136
const result = runMutation(input);
137137
expect(result).toBe(input);
138138
});
139+
140+
it("should handle default import React and use React.Fragment", () => {
141+
const input = `
142+
import React from "react";
143+
144+
function Component() {
145+
return <></>;
146+
}
147+
`.trim();
148+
149+
const expected = `
150+
import React from "react";
151+
function Component() {
152+
return <React.Fragment></React.Fragment>;
153+
}
154+
`.trim();
155+
const result = runMutation(input);
156+
expect(result).toBe(expected);
157+
});
158+
159+
it("should handle import * as React and use React.Fragment", () => {
160+
const input = `
161+
import * as React from "react";
162+
163+
function Component() {
164+
return <></>;
165+
}
166+
`.trim();
167+
168+
const expected = `
169+
import * as React from "react";
170+
function Component() {
171+
return <React.Fragment></React.Fragment>;
172+
}
173+
`.trim();
174+
const result = runMutation(input);
175+
expect(result).toBe(expected);
176+
});
177+
178+
it("should handle mixed default and named imports", () => {
179+
const input = `
180+
import React, { useState } from "react";
181+
182+
function Component() {
183+
return <></>;
184+
}
185+
`.trim();
186+
187+
const expected = `
188+
import React, { useState } from "react";
189+
function Component() {
190+
return <React.Fragment></React.Fragment>;
191+
}
192+
`.trim();
193+
const result = runMutation(input);
194+
expect(result).toBe(expected);
195+
});
196+
197+
it("should handle separate namespace and named imports", () => {
198+
const input = `
199+
import * as React from "react";
200+
import { Fragment } from "react";
201+
202+
function Component() {
203+
return <></>;
204+
}
205+
`.trim();
206+
207+
const expected = `
208+
import * as React from "react";
209+
import { Fragment } from "react";
210+
function Component() {
211+
return <Fragment></Fragment>;
212+
}
213+
`.trim();
214+
const result = runMutation(input);
215+
expect(result).toBe(expected);
216+
});
217+
218+
it("should handle import * as SomeOtherName from react", () => {
219+
const input = `
220+
import * as SomeOtherName from "react";
221+
222+
function Component() {
223+
return <></>;
224+
}
225+
`.trim();
226+
227+
const expected = `
228+
import * as SomeOtherName from "react";
229+
function Component() {
230+
return <SomeOtherName.Fragment></SomeOtherName.Fragment>;
231+
}
232+
`.trim();
233+
const result = runMutation(input);
234+
expect(result).toBe(expected);
235+
});
139236
});

packages/compiler/src/utils/index.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,24 @@ function findExistingImport(
9090
path.stop();
9191
return;
9292
}
93+
94+
// Handle default imports (import React from "react")
95+
if (t.isImportDefaultSpecifier(specifier)) {
96+
// For default imports, we can access the exported name via the default import
97+
// e.g., React.Fragment when we have "import React from 'react'"
98+
result = `${specifier.local.name}.${exportedName}`;
99+
path.stop();
100+
return;
101+
}
102+
103+
// Handle namespace imports (import * as React from "react")
104+
if (t.isImportNamespaceSpecifier(specifier)) {
105+
// For namespace imports, we can access the exported name via the namespace
106+
// e.g., React.Fragment when we have "import * as React from 'react'"
107+
result = `${specifier.local.name}.${exportedName}`;
108+
path.stop();
109+
return;
110+
}
93111
}
94112
},
95113
});

0 commit comments

Comments
 (0)