Skip to content

Commit 96e9bae

Browse files
authored
fix: escape defaultMessage properly, fixes #1158 (#1345)
1 parent 493d6dd commit 96e9bae

File tree

4 files changed

+31
-3
lines changed

4 files changed

+31
-3
lines changed

package-lock.json

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

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@
138138
"watchify": "^3.7.0"
139139
},
140140
"scripts": {
141-
"benchmark": "TS_NODE_PROJECT='test/perf/tsconfig.json' ts-node test/perf/index.tsx",
141+
"benchmark": "NODE_ENV=production TS_NODE_PROJECT='test/perf/tsconfig.json' ts-node test/perf/index.tsx",
142142
"build:dist:dev": "cross-env NODE_ENV=development rollup -c rollup.config.dist.js",
143143
"build:dist:prod": "cross-env NODE_ENV=production rollup -c rollup.config.dist.js",
144144
"build:dist": "npm run build:dist:dev && npm run build:dist:prod",

src/format.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,19 @@ function getNamedFormat<T extends keyof CustomFormats>(
8787
onError(createError(`No ${type} format named: ${name}`));
8888
}
8989

90+
/**
91+
* Escape a raw msg when we run in prod mode
92+
* https://github.com/formatjs/formatjs/blob/master/packages/intl-messageformat-parser/src/parser.pegjs#L155
93+
*/
94+
function escapeUnformattedMessage(msg: string): string {
95+
return msg
96+
.replace(/\\u([\da-fA-F]{4})/g, (_, digits) =>
97+
String.fromCharCode(parseInt(digits, 16))
98+
)
99+
.replace(/\\\{/g, '\u007B')
100+
.replace(/\\\}/g, '\u007D');
101+
}
102+
90103
export function formatDate(
91104
{
92105
locale,
@@ -266,7 +279,7 @@ export function formatMessage(
266279
if (!hasValues && process.env.NODE_ENV === 'production') {
267280
const val = message || defaultMessage || id;
268281
if (typeof val === 'string') {
269-
return val;
282+
return escapeUnformattedMessage(val);
270283
}
271284
invariant(
272285
val.elements.length === 1 &&

test/unit/format.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,21 @@ RangeError: Invalid unit argument`
672672
formatMessage = f.formatMessage.bind(null, config, state);
673673
});
674674

675+
['Hello, World!\\{foo\\}', '\\ud83d\\udc04'].forEach(msg =>
676+
it(`should render escaped msg ${msg} properly in production`, () => {
677+
process.env.NODE_ENV = 'production';
678+
679+
const descriptor = {
680+
id: 'hello',
681+
defaultMessage: msg,
682+
};
683+
684+
const mf = new IntlMessageFormat(msg, 'en');
685+
686+
expect(formatMessage(descriptor)).toBe(mf.format());
687+
})
688+
);
689+
675690
it('throws when no Message Descriptor is provided', () => {
676691
expect(() => formatMessage()).toThrow(
677692
'[React Intl] An `id` must be provided to format a message.'

0 commit comments

Comments
 (0)