Skip to content

Commit 98e9332

Browse files
authored
fix: JSX attribute parsing issue when using html entities (#1234)
* Handle html entities in macro * Update test expectations
1 parent 71ffc32 commit 98e9332

6 files changed

Lines changed: 64 additions & 39 deletions

File tree

packages/macro/src/macroJsx.ts

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,10 @@ export default class MacroJSX {
5252
}
5353

5454
safeJsxAttribute = (name: string, value: string) => {
55-
// Quoted JSX attributes use XML-style escapes instead of JavaScript-style escapes.
56-
// This means that <Trans id="Say \"hi\"!" /> is invalid, but <Trans id={"Say \"hi\"!"} /> is valid.
57-
58-
// We could consider removing this condition and always wrap in a jsxExpressionContainer.
59-
const attributeValue = value.includes('"')
60-
? this.types.jsxExpressionContainer(this.types.stringLiteral(value))
61-
: this.types.stringLiteral(value)
62-
55+
// This handles quoted JSX attributes and html entities.
6356
return this.types.jsxAttribute(
6457
this.types.jsxIdentifier(name),
65-
attributeValue
58+
this.types.jsxExpressionContainer(this.types.stringLiteral(value))
6659
)
6760
}
6861

packages/macro/test/fixtures/jsx-plural-select-nested.expected.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/macro/test/jsx-plural.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ export default [
1212
`,
1313
expected: `
1414
import { Trans } from "@lingui/react";
15-
<Trans id="{count, plural, offset:1 =0 {Zero items} few {{count} items} other {<0>A lot of them</0>}}" values={{
15+
<Trans id={
16+
"{count, plural, offset:1 =0 {Zero items} few {{count} items} other {<0>A lot of them</0>}}"
17+
}
18+
values={{
1619
count: count
1720
}} components={{
1821
0: <a href="/more" />
@@ -38,7 +41,10 @@ export default [
3841
`,
3942
expected: `
4043
import { Trans } from "@lingui/react";
41-
<Trans id="{count, plural, one {<0>#</0> slot added} other {<1>#</1> slots added}}" values={{
44+
<Trans id={
45+
"{count, plural, one {<0>#</0> slot added} other {<1>#</1> slots added}}"
46+
}
47+
values={{
4248
count: count
4349
}} components={{
4450
0: <strong />,
@@ -61,7 +67,7 @@ export default [
6167
`,
6268
expected: `
6369
import { Trans } from "@lingui/react";
64-
<Trans render="strong" id="msg.plural" message="{count, plural, offset:1 =0 {Zero items} few {{count} items} other {<0>A lot of them</0>}}" values={{
70+
<Trans render="strong" id="msg.plural" message={"{count, plural, offset:1 =0 {Zero items} few {{count} items} other {<0>A lot of them</0>}}"} values={{
6571
count: count
6672
}} components={{
6773
0: <a href="/more" />
@@ -84,7 +90,10 @@ export default [
8490
`,
8591
expected: `
8692
import { Trans } from "@lingui/react";
87-
<Trans id="inner-id-removed" message="Looking for {0, plural, offset:1 =0 {zero items} few {{1} items {2}} other {<0>a lot of them</0>}}" values={{
93+
<Trans id="inner-id-removed" message={
94+
"Looking for {0, plural, offset:1 =0 {zero items} few {{1} items {2}} other {<0>a lot of them</0>}}"
95+
}
96+
values={{
8897
0: items.length,
8998
1: items.length,
9099
2: 42

packages/macro/test/jsx-select.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export default [
1111
`,
1212
expected: `
1313
import { Trans } from "@lingui/react";
14-
<Trans id="{count, select, male {He} female {She} other {<0>Other</0>}}" values={{
14+
<Trans id={"{count, select, male {He} female {She} other {<0>Other</0>}}"} values={{
1515
count: count
1616
}} components={{
1717
0: <strong />
@@ -32,7 +32,7 @@ export default [
3232
`,
3333
expected: `
3434
import { Trans } from "@lingui/react";
35-
<Trans render="strong" id="msg.select" message="{0, select, male {He} female {She} other {<0>Other</0>}}" values={{
35+
<Trans render="strong" id="msg.select" message={"{0, select, male {He} female {She} other {<0>Other</0>}}"} values={{
3636
0: user.gender
3737
}} components={{
3838
0: <strong />

packages/macro/test/jsx-selectOrdinal.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ export default [
1313
`,
1414
expected: `
1515
import { Trans } from "@lingui/react";
16-
<Trans id="This is my {count, selectordinal, one {#st} two {#nd} other {<0>#rd</0>}} cat." values={{
16+
<Trans id={
17+
"This is my {count, selectordinal, one {#st} two {#nd} other {<0>#rd</0>}} cat."
18+
}
19+
values={{
1720
count: count
1821
}} components={{
1922
0: <strong />
@@ -34,7 +37,10 @@ export default [
3437
`,
3538
expected: `
3639
import { Trans } from "@lingui/react";
37-
<Trans id="This is my {0, selectordinal, one {#st} two {#nd} other {<0>#rd</0>}} cat." values={{
40+
<Trans id={
41+
"This is my {0, selectordinal, one {#st} two {#nd} other {<0>#rd</0>}} cat."
42+
}
43+
values={{
3844
0: user.numCats
3945
}} components={{
4046
0: <strong />

packages/macro/test/jsx-trans.ts

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export default [
77
`,
88
expected: `
99
import { Trans } from "@lingui/react";
10-
<Trans id="Hello World" />;
10+
<Trans id={"Hello World"} />;
1111
`,
1212
},
1313
{
@@ -18,7 +18,7 @@ export default [
1818
`,
1919
expected: `
2020
import { Trans } from "@lingui/react";
21-
<Trans id="Hello World" />;
21+
<Trans id={"Hello World"} />;
2222
`,
2323
},
2424
{
@@ -29,7 +29,7 @@ export default [
2929
`,
3030
expected: `
3131
import { Trans } from "@lingui/react";
32-
<Trans id="msg.hello" message="Hello World" />;
32+
<Trans id="msg.hello" message={"Hello World"} />;
3333
`,
3434
},
3535
{
@@ -40,7 +40,7 @@ export default [
4040
`,
4141
expected: `
4242
import { Trans } from "@lingui/react";
43-
<Trans id="msg.hello" message="Hello World" />;
43+
<Trans id="msg.hello" message={"Hello World"} />;
4444
`,
4545
},
4646
{
@@ -51,7 +51,7 @@ export default [
5151
`,
5252
expected: `
5353
import { Trans } from "@lingui/react";
54-
<Trans id="msg.hello" message="Hello World" />;
54+
<Trans id="msg.hello" message={"Hello World"} />;
5555
`,
5656
},
5757
{
@@ -73,7 +73,7 @@ export default [
7373
`,
7474
expected: `
7575
import { Trans } from "@lingui/react";
76-
<Trans id="Hi {yourName}, my name is {myName}" values={{
76+
<Trans id={"Hi {yourName}, my name is {myName}"} values={{
7777
yourName: yourName,
7878
myName: myName,
7979
}} />;
@@ -87,7 +87,7 @@ export default [
8787
`,
8888
expected: `
8989
import { Trans } from "@lingui/react";
90-
<Trans id="{duplicate} variable {duplicate}" values={{
90+
<Trans id={"{duplicate} variable {duplicate}"} values={{
9191
duplicate: duplicate
9292
}} />;
9393
`,
@@ -105,6 +105,23 @@ export default [
105105
<Trans id="custom-id" message={'Speak "friend"!'} />;
106106
`,
107107
},
108+
{
109+
name: "HTML attributes are handled",
110+
input: `
111+
import { Trans } from '@lingui/macro';
112+
<Trans>
113+
<Text>This should work &nbsp;</Text>
114+
</Trans>;
115+
`,
116+
expected: `
117+
import { Trans } from "@lingui/react";
118+
<Trans id={"<0>This should work \\xA0</0>"}
119+
components={{
120+
0: <Text />,
121+
}}
122+
/>;
123+
`,
124+
},
108125
{
109126
name: "Template literals as children",
110127
input: `
@@ -113,7 +130,7 @@ export default [
113130
`,
114131
expected: `
115132
import { Trans } from "@lingui/react";
116-
<Trans id="How much is {expression}? {count}" values={{
133+
<Trans id={"How much is {expression}? {count}"} values={{
117134
expression: expression,
118135
count: count
119136
}} />;
@@ -127,7 +144,7 @@ export default [
127144
`,
128145
expected: `
129146
import { Trans } from "@lingui/react";
130-
<Trans id="hello {count, plural, one {world} other {worlds}}" />;
147+
<Trans id={"hello {count, plural, one {world} other {worlds}}"} />;
131148
`,
132149
},
133150
{
@@ -145,7 +162,7 @@ export default [
145162
`,
146163
expected: `
147164
import { Trans } from "@lingui/react";
148-
<Trans id="Property {0}, function {1}, array {2}, constant {3}, object {4}, everything {5}" values={{
165+
<Trans id={"Property {0}, function {1}, array {2}, constant {3}, object {4}, everything {5}"} values={{
149166
0: props.name,
150167
1: random(),
151168
2: array[index],
@@ -169,7 +186,7 @@ export default [
169186
`,
170187
expected: `
171188
import { Trans } from "@lingui/react";
172-
<Trans id="Hello <0>World!</0><1/><2>My name is <3> <4>{name}</4></3></2>" values={{
189+
<Trans id={"Hello <0>World!</0><1/><2>My name is <3> <4>{name}</4></3></2>"} values={{
173190
name: name
174191
}} components={{
175192
0: <strong />,
@@ -188,7 +205,7 @@ export default [
188205
`,
189206
expected: `
190207
import { Trans } from "@lingui/react";
191-
<Trans id="<0>Component inside expression container</0>" components={{
208+
<Trans id={"<0>Component inside expression container</0>"} components={{
192209
0: <span />
193210
}} />;
194211
`,
@@ -201,7 +218,7 @@ export default [
201218
`,
202219
expected: `
203220
import { Trans } from "@lingui/react";
204-
<Trans id="<0/>" components={{
221+
<Trans id={"<0/>"} components={{
205222
0: <br />
206223
}} />;
207224
`,
@@ -222,7 +239,7 @@ export default [
222239
production: true,
223240
input: `
224241
import { Trans } from '@lingui/macro';
225-
<Trans id="msg.hello" comment="Hello World">Hello World</Trans>
242+
<Trans id="msg.hello" comment="Hello World">Hello World</Trans>
226243
`,
227244
expected: `
228245
import { Trans } from "@lingui/react";
@@ -255,7 +272,7 @@ export default [
255272
`,
256273
expected: `
257274
import { Trans } from "@lingui/react";
258-
<Trans id="Strip whitespace around arguments: '{name}'" values={{
275+
<Trans id={"Strip whitespace around arguments: '{name}'"} values={{
259276
name: name
260277
}} />;
261278
`,
@@ -272,7 +289,7 @@ export default [
272289
`,
273290
expected: `
274291
import { Trans } from "@lingui/react";
275-
<Trans id="Strip whitespace around tags, but keep <0>forced spaces</0>!" components={{
292+
<Trans id={"Strip whitespace around tags, but keep <0>forced spaces</0>!"} components={{
276293
0: <strong />
277294
}} />;
278295
`,
@@ -288,7 +305,7 @@ export default [
288305
`,
289306
expected: `
290307
import { Trans } from "@lingui/react";
291-
<Trans id="Keep forced\\n newlines!" />;
308+
<Trans id={"Keep forced\\n newlines!"} />;
292309
`,
293310
},
294311
{
@@ -303,7 +320,7 @@ export default [
303320
`,
304321
expected: `
305322
import { Trans } from "@lingui/react";
306-
<Trans id="Keep multiple\\n forced\\n newlines!" />;
323+
<Trans id={"Keep multiple\\n forced\\n newlines!"} />;
307324
`,
308325
},
309326
{
@@ -314,7 +331,7 @@ export default [
314331
expected: `
315332
import { Trans } from "@lingui/react";
316333
import { i18n } from "@lingui/core";
317-
<Trans id="Read <0>more</0>" components={{
334+
<Trans id={"Read <0>more</0>"} components={{
318335
0: <a href="/more" title={
319336
/*i18n*/
320337
i18n._("Full content of {articleName}", {
@@ -350,7 +367,7 @@ export default [
350367
`,
351368
expected: `
352369
import { Trans } from "@lingui/react";
353-
<Trans id="Hello World" />;
370+
<Trans id={"Hello World"} />;
354371
`,
355372
},
356373
{
@@ -361,7 +378,7 @@ export default [
361378
`,
362379
expected: `
363380
import { Trans } from "@lingui/react";
364-
<Trans id="&" />;
381+
<Trans id={"&"} />;
365382
`,
366383
},
367384
]

0 commit comments

Comments
 (0)