From b51f57300d5a371c979dca7d321acdcfd184fefc Mon Sep 17 00:00:00 2001 From: Long Ho Date: Fri, 8 May 2020 17:33:54 -0400 Subject: [PATCH] fix(@formatjs/ts-transformer): preserve other attr in the component --- packages/ts-transformer/src/transform.ts | 35 +++++++++++++------ .../tests/__snapshots__/index.test.ts.snap | 27 +++++++------- .../tests/fixtures/FormattedMessage.tsx | 5 ++- .../tests/fixtures/overrideIdFn.tsx | 3 +- 4 files changed, 42 insertions(+), 28 deletions(-) diff --git a/packages/ts-transformer/src/transform.ts b/packages/ts-transformer/src/transform.ts index a4bf16690e..731d0a999a 100644 --- a/packages/ts-transformer/src/transform.ts +++ b/packages/ts-transformer/src/transform.ts @@ -10,6 +10,8 @@ export type InterpolateNameFn = ( description?: string ) => string; +const MESSAGE_DESC_KEYS = new Set(['id', 'defaultMessage', 'description']); + export interface Opts { /** * Whether the metadata about the location of the message in the source file @@ -215,19 +217,30 @@ function setAttributesInObject( msg: MessageDescriptor ) { const newNode = ts.getMutableClone(node); - newNode.properties = ts.createNodeArray( - (['id', 'description', 'defaultMessage'] as Array) - .filter(k => !!msg[k]) - .map(k => { + const newProps = []; + for (const prop of node.properties) { + if ( + (ts.isJsxAttribute(prop) || ts.isPropertyAssignment(prop)) && + ts.isIdentifier(prop.name) + ) { + const k = prop.name.text as keyof MessageDescriptor; + if (MESSAGE_DESC_KEYS.has(k)) { const val = msg[k]; - const keyNode = ts.createIdentifier(k); - const valNode = ts.createStringLiteral(val + ''); - if (ts.isJsxAttributes(node)) { - return ts.createJsxAttribute(keyNode, valNode); + if (val) { + const keyNode = ts.createIdentifier(k); + const valNode = ts.createStringLiteral(val + ''); + if (ts.isJsxAttributes(node)) { + newProps.push(ts.createJsxAttribute(keyNode, valNode)); + } else if (ts.isObjectLiteralExpression(node)) { + newProps.push(ts.createPropertyAssignment(k, valNode)); + } } - return ts.createPropertyAssignment(keyNode, valNode); - }) - ) as ts.NodeArray; + continue; + } + } + newProps.push(prop); + } + newNode.properties = ts.createNodeArray(newProps) as any; return newNode; } diff --git a/packages/ts-transformer/tests/__snapshots__/index.test.ts.snap b/packages/ts-transformer/tests/__snapshots__/index.test.ts.snap index 347f0fb5a3..132d6f225f 100644 --- a/packages/ts-transformer/tests/__snapshots__/index.test.ts.snap +++ b/packages/ts-transformer/tests/__snapshots__/index.test.ts.snap @@ -32,14 +32,16 @@ const react_1 = require(\\"react\\"); const react_intl_1 = require(\\"react-intl\\"); class Foo extends react_1.Component { render() { - return (react_1.default.createElement(react_intl_1.FormattedMessage, { id: 'foo.bar.baz', defaultMessage: 'Hello World!' })); + return (react_1.default.createElement(react_intl_1.FormattedMessage, { id: 'foo.bar.baz', defaultMessage: 'Hello World! {foo, number}', values: { + foo: 1 + } })); } } exports.default = Foo; ", "msgs": Array [ Object { - "defaultMessage": "Hello World!", + "defaultMessage": "Hello World! {foo, number}", "description": "The default message.", "id": "foo.bar.baz", }, @@ -183,12 +185,16 @@ class Foo extends react_1.Component { defaultMessage: \\"Hello Nurse!\\" }), invalid: this.props.intl.formatMessage(objectPointer), - invalid2: this.props.intl.formatMessage({ id, defaultMessage, description: 'asd' }) + invalid2: this.props.intl.formatMessage({ + id, + defaultMessage, + description: 'asd', + }), }; return (react_1.default.createElement(\\"div\\", null, react_1.default.createElement(\\"h1\\", null, msgs.header), react_1.default.createElement(\\"p\\", null, msgs.content), - react_1.default.createElement(\\"input\\", { placeholder: intl.formatMessage({ id: \\"1_ZyCapCsn\\", defaultMessage: \\"inline\\" }) }), + react_1.default.createElement(\\"input\\", { placeholder: intl.formatMessage({ defaultMessage: \\"inline\\" }) }), react_1.default.createElement(\\"span\\", null, react_1.default.createElement(react_intl_1.FormattedMessage, { id: 'foo', defaultMessage: 'bar' })))); } @@ -370,11 +376,9 @@ exports.default = Foo; exports[`emit asserts for nested 1`] = ` Object { "code": "intl.formatMessage({ - id: \\"HELLO.undefined.13.undefined\\", defaultMessage: \\"layer1 {name}\\" }, { name: intl.formatMessage({ - id: \\"HELLO.undefined.6.undefined\\", defaultMessage: \\"layer2\\" }), }); @@ -398,15 +402,12 @@ Object { Object.defineProperty(exports, \\"__esModule\\", { value: true }); function foo() { props.intl.formatMessage({ - id: \\"2AgGp\\", defaultMessage: \\"props {intl}\\" }, { bar: 'bar' }); this.props.intl.formatMessage({ - id: \\"STVHS\\", defaultMessage: \\"this props {intl}\\" }, { bar: 'bar' }); return intl.formatMessage({ - id: \\"1aog4\\", defaultMessage: \\"foo {bar}\\" }, { bar: 'bar' }); } @@ -449,7 +450,6 @@ const msgs = react_intl_1.defineMessages({ } }); react_intl_1.defineMessage({ - id: \\"HELLO.undefined.13.string\\", defaultMessage: \\"defineMessage\\" }); class Foo extends react_1.Component { @@ -457,15 +457,12 @@ class Foo extends react_1.Component { const { intl } = this.props; const { formatMessage } = intl; this.props.intl.formatMessage({ - id: \\"HELLO.undefined.5.string\\", defaultMessage: \\"no-id\\" }); intl.formatMessage({ - id: \\"HELLO.undefined.18.string\\", defaultMessage: \\"intl.formatMessage\\" }); formatMessage({ - id: \\"HELLO.undefined.13.string\\", defaultMessage: \\"formatMessage\\" }); return (react_1.default.createElement(\\"div\\", null, @@ -473,7 +470,7 @@ class Foo extends react_1.Component { react_1.default.createElement(react_intl_1.FormattedMessage, Object.assign({}, msgs.header))), react_1.default.createElement(\\"p\\", null, react_1.default.createElement(react_intl_1.FormattedMessage, Object.assign({}, msgs.content))), - react_1.default.createElement(react_intl_1.FormattedMessage, { id: 'foo.bar.zoo', defaultMessage: 'Hello World!' }))); + react_1.default.createElement(react_intl_1.FormattedMessage, { id: 'foo.bar.zoo', defaultMessage: 'Hello World! {abc}', values: { abc: 2 } }))); } } exports.default = Foo; @@ -509,7 +506,7 @@ exports.default = Foo; "id": "HELLO.undefined.13.string", }, Object { - "defaultMessage": "Hello World!", + "defaultMessage": "Hello World! {abc}", "id": "foo.bar.zoo", }, ], diff --git a/packages/ts-transformer/tests/fixtures/FormattedMessage.tsx b/packages/ts-transformer/tests/fixtures/FormattedMessage.tsx index a25f03f055..6d3fef655e 100644 --- a/packages/ts-transformer/tests/fixtures/FormattedMessage.tsx +++ b/packages/ts-transformer/tests/fixtures/FormattedMessage.tsx @@ -6,8 +6,11 @@ export default class Foo extends Component { return ( ); } diff --git a/packages/ts-transformer/tests/fixtures/overrideIdFn.tsx b/packages/ts-transformer/tests/fixtures/overrideIdFn.tsx index 2a396996f7..984e6e8e0b 100644 --- a/packages/ts-transformer/tests/fixtures/overrideIdFn.tsx +++ b/packages/ts-transformer/tests/fixtures/overrideIdFn.tsx @@ -49,11 +49,12 @@ export default class Foo extends Component {

);