Skip to content

Commit 3887aa4

Browse files
committed
fix(@formatjs/icu-messageformat-parser): fix unescaping in parser printer, fix #3870
1 parent 9cfeecc commit 3887aa4

File tree

3 files changed

+36
-5
lines changed

3 files changed

+36
-5
lines changed

packages/cli/integration-tests/extract/__snapshots__/integration.test.ts.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ Object {
298298
\\"description\\": \\"Counts kittens\\"
299299
},
300300
\\"escaped.apostrophe\\": {
301-
\\"defaultMessage\\": \\"A quoted value '{value}'\\",
301+
\\"defaultMessage\\": \\"A quoted value ''{value}''\\",
302302
\\"description\\": \\"Escaped apostrophe\\"
303303
},
304304
\\"foo.bar.baz\\": {

packages/icu-messageformat-parser/printer.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ export function doPrintAST(
3232
ast: MessageFormatElement[],
3333
isInPlural: boolean
3434
): string {
35-
const printedNodes = ast.map(el => {
35+
const printedNodes = ast.map((el, i) => {
3636
if (isLiteralElement(el)) {
37-
return printLiteralElement(el, isInPlural)
37+
return printLiteralElement(el, isInPlural, i === 0, i === ast.length - 1)
3838
}
3939

4040
if (isArgumentElement(el)) {
@@ -71,8 +71,23 @@ function printEscapedMessage(message: string): string {
7171
return message.replace(/([{}](?:.*[{}])?)/su, `'$1'`)
7272
}
7373

74-
function printLiteralElement({value}: LiteralElement, isInPlural: boolean) {
75-
const escaped = printEscapedMessage(value)
74+
function printLiteralElement(
75+
{value}: LiteralElement,
76+
isInPlural: boolean,
77+
isFirstEl: boolean,
78+
isLastEl: boolean
79+
) {
80+
let escaped = value
81+
// If this literal starts with a ' and its not the 1st node, this means the node before it is non-literal
82+
// and the `'` needs to be unescaped
83+
if (!isFirstEl && escaped[0] === `'`) {
84+
escaped = `''${escaped.slice(1)}`
85+
}
86+
// Same logic but for last el
87+
if (!isLastEl && escaped[escaped.length - 1] === `'`) {
88+
escaped = `${escaped.slice(0, escaped.length - 1)}''`
89+
}
90+
escaped = printEscapedMessage(escaped)
7691
return isInPlural ? escaped.replace('#', "'#'") : escaped
7792
}
7893

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import {parse} from '..'
2+
import {printAST} from '../printer'
3+
4+
test('should escape things properly', function () {
5+
expect(printAST(parse("Name: ''{name}''."))).toBe("Name: ''{name}''.")
6+
expect(printAST(parse("'just some {name} thing'"))).toBe(
7+
"'just some {name} thing'"
8+
)
9+
expect(
10+
printAST(
11+
parse(
12+
"Peter's brother {name1} is taller than {name} who is Peter's friend."
13+
)
14+
)
15+
).toBe("Peter's brother {name1} is taller than {name} who is Peter's friend.")
16+
})

0 commit comments

Comments
 (0)