Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: JSX attribute parsing issue when using html entities #1234

Merged
merged 2 commits into from
Jun 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 2 additions & 9 deletions packages/macro/src/macroJsx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,10 @@ export default class MacroJSX {
}

safeJsxAttribute = (name: string, value: string) => {
// Quoted JSX attributes use XML-style escapes instead of JavaScript-style escapes.
// This means that <Trans id="Say \"hi\"!" /> is invalid, but <Trans id={"Say \"hi\"!"} /> is valid.

// We could consider removing this condition and always wrap in a jsxExpressionContainer.
const attributeValue = value.includes('"')
? this.types.jsxExpressionContainer(this.types.stringLiteral(value))
: this.types.stringLiteral(value)

// This handles quoted JSX attributes and html entities.
return this.types.jsxAttribute(
this.types.jsxIdentifier(name),
attributeValue
this.types.jsxExpressionContainer(this.types.stringLiteral(value))
)
}

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 13 additions & 4 deletions packages/macro/test/jsx-plural.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="{count, plural, offset:1 =0 {Zero items} few {{count} items} other {<0>A lot of them</0>}}" values={{
<Trans id={
"{count, plural, offset:1 =0 {Zero items} few {{count} items} other {<0>A lot of them</0>}}"
}
values={{
count: count
}} components={{
0: <a href="/more" />
Expand All @@ -38,7 +41,10 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="{count, plural, one {<0>#</0> slot added} other {<1>#</1> slots added}}" values={{
<Trans id={
"{count, plural, one {<0>#</0> slot added} other {<1>#</1> slots added}}"
}
values={{
count: count
}} components={{
0: <strong />,
Expand All @@ -61,7 +67,7 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<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={{
<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={{
count: count
}} components={{
0: <a href="/more" />
Expand All @@ -84,7 +90,10 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<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={{
<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={{
0: items.length,
1: items.length,
2: 42
Expand Down
4 changes: 2 additions & 2 deletions packages/macro/test/jsx-select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="{count, select, male {He} female {She} other {<0>Other</0>}}" values={{
<Trans id={"{count, select, male {He} female {She} other {<0>Other</0>}}"} values={{
count: count
}} components={{
0: <strong />
Expand All @@ -32,7 +32,7 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans render="strong" id="msg.select" message="{0, select, male {He} female {She} other {<0>Other</0>}}" values={{
<Trans render="strong" id="msg.select" message={"{0, select, male {He} female {She} other {<0>Other</0>}}"} values={{
0: user.gender
}} components={{
0: <strong />
Expand Down
10 changes: 8 additions & 2 deletions packages/macro/test/jsx-selectOrdinal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="This is my {count, selectordinal, one {#st} two {#nd} other {<0>#rd</0>}} cat." values={{
<Trans id={
"This is my {count, selectordinal, one {#st} two {#nd} other {<0>#rd</0>}} cat."
}
values={{
count: count
}} components={{
0: <strong />
Expand All @@ -34,7 +37,10 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="This is my {0, selectordinal, one {#st} two {#nd} other {<0>#rd</0>}} cat." values={{
<Trans id={
"This is my {0, selectordinal, one {#st} two {#nd} other {<0>#rd</0>}} cat."
}
values={{
0: user.numCats
}} components={{
0: <strong />
Expand Down
59 changes: 38 additions & 21 deletions packages/macro/test/jsx-trans.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="Hello World" />;
<Trans id={"Hello World"} />;
`,
},
{
Expand All @@ -18,7 +18,7 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="Hello World" />;
<Trans id={"Hello World"} />;
`,
},
{
Expand All @@ -29,7 +29,7 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="msg.hello" message="Hello World" />;
<Trans id="msg.hello" message={"Hello World"} />;
`,
},
{
Expand All @@ -40,7 +40,7 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="msg.hello" message="Hello World" />;
<Trans id="msg.hello" message={"Hello World"} />;
`,
},
{
Expand All @@ -51,7 +51,7 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="msg.hello" message="Hello World" />;
<Trans id="msg.hello" message={"Hello World"} />;
`,
},
{
Expand All @@ -73,7 +73,7 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="Hi {yourName}, my name is {myName}" values={{
<Trans id={"Hi {yourName}, my name is {myName}"} values={{
yourName: yourName,
myName: myName,
}} />;
Expand All @@ -87,7 +87,7 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="{duplicate} variable {duplicate}" values={{
<Trans id={"{duplicate} variable {duplicate}"} values={{
duplicate: duplicate
}} />;
`,
Expand All @@ -105,6 +105,23 @@ export default [
<Trans id="custom-id" message={'Speak "friend"!'} />;
`,
},
{
name: "HTML attributes are handled",
input: `
import { Trans } from '@lingui/macro';
<Trans>
<Text>This should work &nbsp;</Text>
</Trans>;
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id={"<0>This should work \\xA0</0>"}
components={{
0: <Text />,
}}
/>;
`,
},
{
name: "Template literals as children",
input: `
Expand All @@ -113,7 +130,7 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="How much is {expression}? {count}" values={{
<Trans id={"How much is {expression}? {count}"} values={{
expression: expression,
count: count
}} />;
Expand All @@ -127,7 +144,7 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="hello {count, plural, one {world} other {worlds}}" />;
<Trans id={"hello {count, plural, one {world} other {worlds}}"} />;
`,
},
{
Expand All @@ -145,7 +162,7 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="Property {0}, function {1}, array {2}, constant {3}, object {4}, everything {5}" values={{
<Trans id={"Property {0}, function {1}, array {2}, constant {3}, object {4}, everything {5}"} values={{
0: props.name,
1: random(),
2: array[index],
Expand All @@ -169,7 +186,7 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="Hello <0>World!</0><1/><2>My name is <3> <4>{name}</4></3></2>" values={{
<Trans id={"Hello <0>World!</0><1/><2>My name is <3> <4>{name}</4></3></2>"} values={{
name: name
}} components={{
0: <strong />,
Expand All @@ -188,7 +205,7 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="<0>Component inside expression container</0>" components={{
<Trans id={"<0>Component inside expression container</0>"} components={{
0: <span />
}} />;
`,
Expand All @@ -201,7 +218,7 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="<0/>" components={{
<Trans id={"<0/>"} components={{
0: <br />
}} />;
`,
Expand All @@ -222,7 +239,7 @@ export default [
production: true,
input: `
import { Trans } from '@lingui/macro';
<Trans id="msg.hello" comment="Hello World">Hello World</Trans>
<Trans id="msg.hello" comment="Hello World">Hello World</Trans>
`,
expected: `
import { Trans } from "@lingui/react";
Expand Down Expand Up @@ -255,7 +272,7 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="Strip whitespace around arguments: '{name}'" values={{
<Trans id={"Strip whitespace around arguments: '{name}'"} values={{
name: name
}} />;
`,
Expand All @@ -272,7 +289,7 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="Strip whitespace around tags, but keep <0>forced spaces</0>!" components={{
<Trans id={"Strip whitespace around tags, but keep <0>forced spaces</0>!"} components={{
0: <strong />
}} />;
`,
Expand All @@ -288,7 +305,7 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="Keep forced\\n newlines!" />;
<Trans id={"Keep forced\\n newlines!"} />;
`,
},
{
Expand All @@ -303,7 +320,7 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="Keep multiple\\n forced\\n newlines!" />;
<Trans id={"Keep multiple\\n forced\\n newlines!"} />;
`,
},
{
Expand All @@ -314,7 +331,7 @@ export default [
expected: `
import { Trans } from "@lingui/react";
import { i18n } from "@lingui/core";
<Trans id="Read <0>more</0>" components={{
<Trans id={"Read <0>more</0>"} components={{
0: <a href="/more" title={
/*i18n*/
i18n._("Full content of {articleName}", {
Expand Down Expand Up @@ -350,7 +367,7 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="Hello World" />;
<Trans id={"Hello World"} />;
`,
},
{
Expand All @@ -361,7 +378,7 @@ export default [
`,
expected: `
import { Trans } from "@lingui/react";
<Trans id="&" />;
<Trans id={"&"} />;
`,
},
]