Skip to content

Commit

Permalink
fix(@formatjs/icu-messageformat-parser): fix unescaping in parser pri…
Browse files Browse the repository at this point in the history
…nter, fix #3870
  • Loading branch information
longlho committed Oct 16, 2022
1 parent 9cfeecc commit 3887aa4
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ Object {
\\"description\\": \\"Counts kittens\\"
},
\\"escaped.apostrophe\\": {
\\"defaultMessage\\": \\"A quoted value '{value}'\\",
\\"defaultMessage\\": \\"A quoted value ''{value}''\\",
\\"description\\": \\"Escaped apostrophe\\"
},
\\"foo.bar.baz\\": {
Expand Down
23 changes: 19 additions & 4 deletions packages/icu-messageformat-parser/printer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ export function doPrintAST(
ast: MessageFormatElement[],
isInPlural: boolean
): string {
const printedNodes = ast.map(el => {
const printedNodes = ast.map((el, i) => {
if (isLiteralElement(el)) {
return printLiteralElement(el, isInPlural)
return printLiteralElement(el, isInPlural, i === 0, i === ast.length - 1)
}

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

function printLiteralElement({value}: LiteralElement, isInPlural: boolean) {
const escaped = printEscapedMessage(value)
function printLiteralElement(
{value}: LiteralElement,
isInPlural: boolean,
isFirstEl: boolean,
isLastEl: boolean
) {
let escaped = value
// If this literal starts with a ' and its not the 1st node, this means the node before it is non-literal
// and the `'` needs to be unescaped
if (!isFirstEl && escaped[0] === `'`) {
escaped = `''${escaped.slice(1)}`
}
// Same logic but for last el
if (!isLastEl && escaped[escaped.length - 1] === `'`) {
escaped = `${escaped.slice(0, escaped.length - 1)}''`
}
escaped = printEscapedMessage(escaped)
return isInPlural ? escaped.replace('#', "'#'") : escaped
}

Expand Down
16 changes: 16 additions & 0 deletions packages/icu-messageformat-parser/tests/printer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {parse} from '..'
import {printAST} from '../printer'

test('should escape things properly', function () {
expect(printAST(parse("Name: ''{name}''."))).toBe("Name: ''{name}''.")
expect(printAST(parse("'just some {name} thing'"))).toBe(
"'just some {name} thing'"
)
expect(
printAST(
parse(
"Peter's brother {name1} is taller than {name} who is Peter's friend."
)
)
).toBe("Peter's brother {name1} is taller than {name} who is Peter's friend.")
})

0 comments on commit 3887aa4

Please sign in to comment.