Skip to content

Commit 583dd05

Browse files
feat(babel-plugin-lingui-macro): allow to configure macro packages (#2196)
1 parent 9e5f044 commit 583dd05

File tree

17 files changed

+417
-91
lines changed

17 files changed

+417
-91
lines changed

packages/babel-plugin-lingui-macro/src/constants.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
export const EXTRACT_MARK = "i18n"
2-
export const MACRO_LEGACY_PACKAGE = "@lingui/macro"
3-
export const MACRO_CORE_PACKAGE = "@lingui/core/macro"
4-
export const MACRO_REACT_PACKAGE = "@lingui/react/macro"
52

63
export enum MsgDescriptorPropKey {
74
id = "id",

packages/babel-plugin-lingui-macro/src/index.ts

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,7 @@ import { Program, Identifier } from "@babel/types"
44
import { MacroJSX } from "./macroJsx"
55
import type { NodePath } from "@babel/traverse"
66
import { MacroJs } from "./macroJs"
7-
import {
8-
MACRO_CORE_PACKAGE,
9-
MACRO_REACT_PACKAGE,
10-
MACRO_LEGACY_PACKAGE,
11-
JsMacroName,
12-
} from "./constants"
7+
import { JsMacroName } from "./constants"
138
import {
149
type LinguiConfigNormalized,
1510
getConfig as loadConfig,
@@ -18,9 +13,24 @@ import {
1813
let config: LinguiConfigNormalized
1914

2015
export type LinguiPluginOpts = {
21-
// explicitly set by CLI when running extraction process
16+
/*
17+
* When set `true` all auxiliary data such as `comment`, `context`,
18+
* and default message would be kept regardless of the current environment
19+
*
20+
* This flag explicitly set by Lingui CLI when running extraction process
21+
*/
2222
extract?: boolean
23+
/**
24+
* Setting `stripMessageField` to `true` will strip messages and comments from both development and production bundles.
25+
* Alternatively, set it to `false` to keep the original messages in both environments.
26+
*
27+
* If not set value would be determined based on `process.env.NODE_ENV === "production"`
28+
*/
2329
stripMessageField?: boolean
30+
31+
/**
32+
* Resolved and normalized Lingui Configuration
33+
*/
2434
linguiConfig?: LinguiConfigNormalized
2535
}
2636

@@ -61,14 +71,17 @@ type LinguiSymbol = "Trans" | "useLingui" | "i18n"
6171
const getIdentifierPath = ((path: NodePath, node: Identifier) => {
6272
let foundPath: NodePath
6373

64-
path.traverse({
65-
Identifier: (path) => {
66-
if (path.node === node) {
67-
foundPath = path
68-
path.stop()
69-
}
74+
path.traverse(
75+
{
76+
Identifier: (path) => {
77+
if (path.node === node) {
78+
foundPath = path
79+
path.stop()
80+
}
81+
},
7082
},
71-
})
83+
path.state
84+
)
7285

7386
return foundPath
7487
}) as any
@@ -110,14 +123,15 @@ export default function ({
110123
}
111124

112125
function getMacroImports(path: NodePath<Program>) {
126+
const linguiPackages = new Set([
127+
...config.macro.corePackage,
128+
...config.macro.jsxPackage,
129+
])
130+
113131
return path.get("body").filter((statement) => {
114132
return (
115133
statement.isImportDeclaration() &&
116-
[
117-
MACRO_CORE_PACKAGE,
118-
MACRO_REACT_PACKAGE,
119-
MACRO_LEGACY_PACKAGE,
120-
].includes(statement.get("source").node.value)
134+
linguiPackages.has(statement.get("source").node.value)
121135
)
122136
})
123137
}
@@ -138,11 +152,9 @@ export default function ({
138152

139153
if (macro === JsMacroName.useLingui) {
140154
if (
141-
identPath.referencesImport(
142-
MACRO_REACT_PACKAGE,
143-
JsMacroName.useLingui
144-
) ||
145-
identPath.referencesImport(MACRO_LEGACY_PACKAGE, JsMacroName.useLingui)
155+
config.macro.jsxPackage.some((moduleSource) =>
156+
identPath.referencesImport(moduleSource, JsMacroName.useLingui)
157+
)
146158
) {
147159
return true
148160
}
@@ -151,8 +163,9 @@ export default function ({
151163
identPath = identPath || getIdentifierPath(path.getFunctionParent(), node)
152164

153165
if (
154-
identPath.referencesImport(MACRO_CORE_PACKAGE, macro) ||
155-
identPath.referencesImport(MACRO_LEGACY_PACKAGE, macro)
166+
config.macro.corePackage.some((moduleSource) =>
167+
identPath.referencesImport(moduleSource, macro)
168+
)
156169
) {
157170
return true
158171
}
@@ -164,6 +177,11 @@ export default function ({
164177
visitor: {
165178
Program: {
166179
enter(path, state) {
180+
state.set(
181+
"linguiConfig",
182+
getConfig((state.opts as LinguiPluginOpts).linguiConfig)
183+
)
184+
167185
const macroImports = getMacroImports(path)
168186

169187
if (!macroImports.length) {
@@ -172,11 +190,6 @@ export default function ({
172190

173191
state.set("macroImport", macroImports[0])
174192

175-
state.set(
176-
"linguiConfig",
177-
getConfig((state.opts as LinguiPluginOpts).linguiConfig)
178-
)
179-
180193
state.set("linguiIdentifiers", {
181194
i18n: path.scope.generateUidIdentifier("i18n"),
182195
Trans: path.scope.generateUidIdentifier("Trans"),

packages/babel-plugin-lingui-macro/src/macroJsx.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { MacroJSX } from "./macroJsx"
44
import { transformSync } from "@babel/core"
55
import type { NodePath } from "@babel/traverse"
66
import { JsxMacroName } from "./constants"
7+
import { makeConfig } from "@lingui/conf"
78

89
const parseExpression = (expression: string) => {
910
let path: NodePath<JSXElement>
@@ -18,8 +19,11 @@ const parseExpression = (expression: string) => {
1819
"@babel/plugin-syntax-jsx",
1920
{
2021
visitor: {
21-
JSXElement: (d) => {
22+
JSXElement: (d, state) => {
23+
state.set("linguiConfig", makeConfig({}, { skipValidation: true }))
24+
2225
path = d
26+
path.context.state = state
2327
d.stop()
2428
},
2529
},

packages/babel-plugin-lingui-macro/src/macroJsx.ts

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,16 @@ import type { NodePath } from "@babel/traverse"
1818

1919
import { ArgToken, ElementToken, TextToken, Token } from "./icu"
2020
import { makeCounter } from "./utils"
21-
import {
22-
JsxMacroName,
23-
MACRO_REACT_PACKAGE,
24-
MACRO_LEGACY_PACKAGE,
25-
MsgDescriptorPropKey,
26-
JsMacroName,
27-
} from "./constants"
21+
import { JsxMacroName, MsgDescriptorPropKey, JsMacroName } from "./constants"
2822
import cleanJSXElementLiteralChild from "./utils/cleanJSXElementLiteralChild"
2923
import { createMessageDescriptorFromTokens } from "./messageDescriptorUtils"
3024
import {
3125
createMacroJsContext,
3226
MacroJsContext,
3327
tokenizeExpression,
3428
} from "./macroJsAst"
29+
import { LinguiConfigNormalized } from "@lingui/conf"
30+
import { PluginPass } from "@babel/core"
3531

3632
const pluralRuleRe = /(_[\d\w]+|zero|one|two|few|many|other)/
3733
const jsx2icuExactChoice = (value: string) =>
@@ -387,14 +383,17 @@ export class MacroJSX {
387383
tokenizeConditionalExpression = (
388384
exp: NodePath<ConditionalExpression>
389385
): ArgToken => {
390-
exp.traverse({
391-
JSXElement: (el) => {
392-
if (this.isTransComponent(el) || this.isChoiceComponent(el)) {
393-
this.replacePath(el)
394-
el.skip()
395-
}
386+
exp.traverse(
387+
{
388+
JSXElement: (el) => {
389+
if (this.isTransComponent(el) || this.isChoiceComponent(el)) {
390+
this.replacePath(el)
391+
el.skip()
392+
}
393+
},
396394
},
397-
})
395+
exp.state
396+
)
398397

399398
return this.tokenizeExpression(exp)
400399
}
@@ -414,11 +413,13 @@ export class MacroJSX {
414413
return false
415414
}
416415

416+
const config = (path.context.state as PluginPass).get(
417+
"linguiConfig"
418+
) as LinguiConfigNormalized
417419
const identifier = path.get("openingElement").get("name")
418420

419-
return (
420-
identifier.referencesImport(MACRO_REACT_PACKAGE, name) ||
421-
identifier.referencesImport(MACRO_LEGACY_PACKAGE, name)
421+
return config.macro.jsxPackage.some((moduleSource) =>
422+
identifier.referencesImport(moduleSource, name)
422423
)
423424
}
424425

packages/babel-plugin-lingui-macro/test/__snapshots__/js-t.test.ts.snap

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,23 @@ _i18n._(
664664
665665
`;
666666
667+
exports[`should detects macro imported from config.macro.corePackage 1`] = `
668+
import { t } from "@my-lingui/macro";
669+
const msg = t\`Message\`;
670+
671+
↓ ↓ ↓ ↓ ↓ ↓
672+
673+
import { i18n as _i18n } from "@lingui/core";
674+
const msg = _i18n._(
675+
/*i18n*/
676+
{
677+
id: "xDAtGP",
678+
message: "Message",
679+
}
680+
);
681+
682+
`;
683+
667684
exports[`should not crash when no params passed 1`] = `
668685
import { t } from "@lingui/core/macro";
669686
const msg = t();
@@ -675,6 +692,23 @@ const msg = _i18n._();
675692
676693
`;
677694
695+
exports[`should respect runtimeConfigModule 1`] = `
696+
import { t } from "@lingui/macro";
697+
const msg = t\`Message\`;
698+
699+
↓ ↓ ↓ ↓ ↓ ↓
700+
701+
import { myI18n as _i18n } from "@my/lingui";
702+
const msg = _i18n._(
703+
/*i18n*/
704+
{
705+
id: "xDAtGP",
706+
message: "Message",
707+
}
708+
);
709+
710+
`;
711+
678712
exports[`stripMessageField option - message prop is removed if stripMessageField: true 1`] = `
679713
import { t } from "@lingui/macro";
680714
const msg = t\`Message\`;

packages/babel-plugin-lingui-macro/test/__snapshots__/jsx-trans.test.ts.snap

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,44 @@ import { Trans as _Trans } from "@lingui/react";
891891
892892
`;
893893
894+
exports[`should detects macro imported from config.macro.jsxPackage 1`] = `
895+
import { Trans } from "@my-lingui/macro";
896+
<Trans>Hello World</Trans>;
897+
898+
↓ ↓ ↓ ↓ ↓ ↓
899+
900+
import { Trans as _Trans } from "@lingui/react";
901+
<_Trans
902+
{
903+
/*i18n*/
904+
...{
905+
id: "mY42CM",
906+
message: "Hello World",
907+
}
908+
}
909+
/>;
910+
911+
`;
912+
913+
exports[`should respect runtimeConfigModule 1`] = `
914+
import { Trans } from "@lingui/react/macro";
915+
<Trans>Hello World</Trans>;
916+
917+
↓ ↓ ↓ ↓ ↓ ↓
918+
919+
import { myTrans as _Trans } from "@my/lingui";
920+
<_Trans
921+
{
922+
/*i18n*/
923+
...{
924+
id: "mY42CM",
925+
message: "Hello World",
926+
}
927+
}
928+
/>;
929+
930+
`;
931+
894932
exports[`stripMessageField option - message prop is removed if stripMessageField: true 1`] = `
895933
import { Trans } from "@lingui/macro";
896934
<Trans id="msg.hello">Hello World</Trans>;

packages/babel-plugin-lingui-macro/test/js-t.test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { macroTester } from "./macroTester"
2+
import { makeConfig } from "@lingui/conf"
23

34
describe.skip("", () => {})
45

@@ -310,5 +311,40 @@ macroTester({
310311
t2\`Ola! \${plural1(count, {one: "1 user", many: "# users"})} Ola!\`
311312
`,
312313
},
314+
{
315+
name: "should respect runtimeConfigModule",
316+
macroOpts: {
317+
linguiConfig: makeConfig(
318+
{
319+
runtimeConfigModule: {
320+
i18n: ["@my/lingui", "myI18n"],
321+
},
322+
},
323+
{ skipValidation: true }
324+
),
325+
},
326+
code: `
327+
import { t } from '@lingui/macro'
328+
const msg = t\`Message\`
329+
`,
330+
},
331+
{
332+
name: "should detects macro imported from config.macro.corePackage",
333+
macroOpts: {
334+
linguiConfig: makeConfig(
335+
{
336+
macro: {
337+
corePackage: ["@my-lingui/macro"],
338+
},
339+
},
340+
{ skipValidation: true }
341+
),
342+
},
343+
skipBabelMacroTest: true,
344+
code: `
345+
import { t } from '@my-lingui/macro'
346+
const msg = t\`Message\`
347+
`,
348+
},
313349
],
314350
})

0 commit comments

Comments
 (0)