Skip to content

Commit

Permalink
feat(macro): make message stripping configurable via Babel options
Browse files Browse the repository at this point in the history
  • Loading branch information
toblu committed Oct 17, 2024
1 parent b8b4b19 commit 02e24ee
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 10 deletions.
21 changes: 20 additions & 1 deletion packages/macro/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export type LinguiMacroOpts = {
// explicitly set by CLI when running extraction process
extract?: boolean
linguiConfig?: LinguiConfigNormalized
stripMessageField?: boolean
}

const jsMacroTags = new Set([
Expand Down Expand Up @@ -83,12 +84,26 @@ function macro({ references, state, babel, config }: MacroParams) {
const stripNonEssentialProps =
process.env.NODE_ENV == "production" && !opts.extract

const stripMessageProp = (() => {
if (opts.extract) {
// never strip message during extraction process
return false
}
if (typeof opts.stripMessageField === "boolean") {
// if explicitly set in options, use it
return opts.stripMessageField
}
// default to strip message in production if no explicit option is set
return process.env.NODE_ENV === "production"
})()

const jsNodesArray = Array.from(jsNodes)

jsNodesArray.filter(isRootPath(jsNodesArray)).forEach((path) => {
const macro = new MacroJS(babel, {
i18nImportName,
stripNonEssentialProps,
stripMessageProp,
nameMap,
})
try {
Expand All @@ -101,7 +116,11 @@ function macro({ references, state, babel, config }: MacroParams) {
const jsxNodesArray = Array.from(jsxNodes)

jsxNodesArray.filter(isRootPath(jsxNodesArray)).forEach((path) => {
const macro = new MacroJSX(babel, { stripNonEssentialProps, nameMap })
const macro = new MacroJSX(babel, {
stripNonEssentialProps,
stripMessageProp,
nameMap,
})

try {
macro.replacePath(path)
Expand Down
1 change: 1 addition & 0 deletions packages/macro/src/macroJs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ function createMacro() {
{
i18nImportName: "i18n",
stripNonEssentialProps: false,
stripMessageProp: false,
nameMap: new Map<string, string>(),
}
)
Expand Down
7 changes: 5 additions & 2 deletions packages/macro/src/macroJs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ function buildICUFromTokens(tokens: Tokens) {
export type MacroJsOpts = {
i18nImportName: string
stripNonEssentialProps: boolean
stripMessageProp: boolean
nameMap: Map<string, string>
}

Expand All @@ -51,6 +52,7 @@ export default class MacroJs {
// Identifier of i18n object
i18nImportName: string
stripNonEssentialProps: boolean
stripMessageProp: boolean
nameMap: Map<string, string>
nameMapReversed: Map<string, string>

Expand All @@ -61,6 +63,7 @@ export default class MacroJs {
this.types = types
this.i18nImportName = opts.i18nImportName
this.stripNonEssentialProps = opts.stripNonEssentialProps
this.stripMessageProp = opts.stripMessageProp
this.nameMap = opts.nameMap
this.nameMapReversed = Array.from(opts.nameMap.entries()).reduce(
(map, [key, value]) => map.set(value, key),
Expand Down Expand Up @@ -218,7 +221,7 @@ export default class MacroJs {
properties.push(this.createValuesProperty(values))
}

if (!this.stripNonEssentialProps) {
if (!this.stripMessageProp) {
properties.push(
this.createObjectProperty(MESSAGE, messageNode as Expression)
)
Expand Down Expand Up @@ -404,7 +407,7 @@ export default class MacroJs {
const properties: ObjectProperty[] = [
this.createIdProperty(message),

!this.stripNonEssentialProps
!this.stripMessageProp
? this.createObjectProperty(MESSAGE, this.types.stringLiteral(message))
: null,

Expand Down
6 changes: 5 additions & 1 deletion packages/macro/src/macroJsx.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ const parseExpression = (expression: string) => {
function createMacro() {
return new MacroJSX(
{ types },
{ stripNonEssentialProps: false, nameMap: new Map() }
{
stripNonEssentialProps: false,
stripMessageProp: false,
nameMap: new Map(),
}
)
}

Expand Down
7 changes: 6 additions & 1 deletion packages/macro/src/macroJsx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export function normalizeWhitespace(text: string): string {

export type MacroJsxOpts = {
stripNonEssentialProps: boolean
stripMessageProp: boolean
nameMap: Map<string, string>
}

Expand All @@ -73,12 +74,14 @@ export default class MacroJSX {
expressionIndex = makeCounter()
elementIndex = makeCounter()
stripNonEssentialProps: boolean
stripMessageProp: boolean
nameMap: Map<string, string>
nameMapReversed: Map<string, string>

constructor({ types }: { types: typeof babelTypes }, opts: MacroJsxOpts) {
this.types = types
this.stripNonEssentialProps = opts.stripNonEssentialProps
this.stripMessageProp = opts.stripMessageProp
this.nameMap = opts.nameMap
this.nameMapReversed = Array.from(opts.nameMap.entries()).reduce(
(map, [key, value]) => map.set(value, key),
Expand Down Expand Up @@ -130,11 +133,13 @@ export default class MacroJSX {
)
}

if (!this.stripNonEssentialProps) {
if (!this.stripMessageProp) {
if (message) {
attributes.push(this.createStringJsxAttribute(MESSAGE, message))
}
}

if (!this.stripNonEssentialProps) {
if (comment) {
attributes.push(
this.types.jsxAttribute(
Expand Down
69 changes: 64 additions & 5 deletions packages/macro/test/js-t.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,44 @@ const cases: TestCase[] = [
});
`,
},
{
name: "stripMessageField option - message prop is removed if stripMessageField: true",
macroOpts: {
stripMessageField: true,
},
input: `
import { t } from '@lingui/macro'
const msg = t\`Message\`
`,
expected: `
import { i18n } from "@lingui/core";
const msg =
i18n._(/*i18n*/
{
id: "xDAtGP"
});
`,
},
{
name: "stripMessageField option - Message prop is kept during extraction process if extract: true and stripMessageField: true",
macroOpts: {
extract: true,
stripMessageField: true,
},
input: `
import { t } from '@lingui/macro'
const msg = t\`Message\`
`,
expected: `
import { i18n } from "@lingui/core";
const msg =
i18n._(/*i18n*/
{
id: "xDAtGP",
message: "Message"
});
`,
},
{
name: "Production - only essential props are kept",
production: true,
Expand Down Expand Up @@ -486,11 +524,32 @@ const cases: TestCase[] = [
`,
},
{
name: "Newlines after continuation character are removed",
filename: "js-t-continuation-character.js",
},
{
filename: "js-t-var/js-t-var.js",
name: "Production - message prop is kept if stripMessageField: false",
production: true,
macroOpts: {
stripMessageField: false,
},
input: `
import { t } from '@lingui/macro';
const msg = t({
message: \`Hello $\{name\}\`,
id: 'msgId',
comment: 'description for translators',
context: 'My Context',
})
`,
expected: `
import { i18n } from "@lingui/core";
const msg =
i18n._(/*i18n*/
{
id: 'msgId',
values: {
name: name,
},
message: "Hello {name}",
});
`,
},
]

Expand Down
44 changes: 44 additions & 0 deletions packages/macro/test/jsx-trans.ts
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,35 @@ const cases: TestCase[] = [
<Trans>{...spread}</Trans>
`,
},
{
name: "stripMessageField option - message prop is removed if stripMessageField: true",
macroOpts: {
stripMessageField: true,
},
input: `
import { Trans } from '@lingui/macro';
<Trans id="msg.hello">Hello World</Trans>
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="msg.hello"/>;
`,
},
{
name: "stripMessageField option - Message prop is kept during extraction process if extract: true and stripMessageField: true",
macroOpts: {
extract: true,
stripMessageField: true,
},
input: `
import { Trans } from '@lingui/macro';
<Trans id="msg.hello">Hello World</Trans>
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="msg.hello" message={"Hello World"}/>;
`,
},
{
name: "Production - only essential props are kept",
production: true,
Expand Down Expand Up @@ -386,6 +415,21 @@ const cases: TestCase[] = [
<Trans id="msg.hello" message={"Hello World"} comment="Hello World"/>;
`,
},
{
name: "Production - message prop is kept if stripMessageField: false",
production: true,
macroOpts: {
stripMessageField: false,
},
input: `
import { Trans } from '@lingui/macro';
<Trans id="msg.hello" comment="Hello World">Hello World</Trans>
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="msg.hello" message={"Hello World"}/>;
`,
},
{
name: "Production - import type doesn't interference on normal import",
production: true,
Expand Down

0 comments on commit 02e24ee

Please sign in to comment.