Skip to content

Commit 856667c

Browse files
feat(mf2): Support leading whitespace for complex messages (unicode-org/message-format-wg#854)
1 parent dfe5438 commit 856667c

File tree

4 files changed

+17
-9
lines changed

4 files changed

+17
-9
lines changed

packages/mf2-messageformat/src/cst/declarations.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@ import type * as CST from './types.js';
55
import { whitespaces } from './util.js';
66
import { parseVariable } from './values.js';
77

8-
export function parseDeclarations(ctx: ParseContext): {
8+
export function parseDeclarations(
9+
ctx: ParseContext,
10+
start: number
11+
): {
912
declarations: CST.Declaration[];
1013
end: number;
1114
} {
1215
const { source } = ctx;
13-
let pos = whitespaces(source, 0);
16+
let pos = start;
1417
const declarations: CST.Declaration[] = [];
1518
loop: while (source[pos] === '.') {
1619
const keyword = parseNameValue(source, pos + 1);

packages/mf2-messageformat/src/cst/parse-cst.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,16 @@ export function parseCST(
5252
): CST.Message {
5353
const ctx = new ParseContext(source, opt);
5454

55-
if (source.startsWith('.')) {
56-
const { declarations, end: pos } = parseDeclarations(ctx);
57-
return source.startsWith('.match', pos)
58-
? parseSelectMessage(ctx, pos, declarations)
59-
: parsePatternMessage(ctx, pos, declarations, true);
55+
const pos = whitespaces(source, 0);
56+
if (source.startsWith('.', pos)) {
57+
const { declarations, end } = parseDeclarations(ctx, pos);
58+
return source.startsWith('.match', end)
59+
? parseSelectMessage(ctx, end, declarations)
60+
: parsePatternMessage(ctx, end, declarations, true);
6061
} else {
61-
return parsePatternMessage(ctx, 0, [], source.startsWith('{{'));
62+
return source.startsWith('{{', pos)
63+
? parsePatternMessage(ctx, pos, [], true)
64+
: parsePatternMessage(ctx, 0, [], false);
6265
}
6366
}
6467

packages/mf2-messageformat/src/data-model/parse.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ export function parseMessage(
7272
if (source.startsWith('.match', pos)) return selectMessage(decl);
7373

7474
const quoted = decl.length > 0 || source.startsWith('{{', pos);
75+
if (!quoted && pos > 0) pos = 0;
7576
const pattern_ = pattern(quoted);
7677
if (quoted) {
7778
ws();
@@ -149,6 +150,7 @@ function pattern(quoted: boolean): Model.Pattern {
149150

150151
function declarations(): Model.Declaration[] {
151152
const declarations: Model.Declaration[] = [];
153+
ws();
152154
loop: while (source[pos] === '.') {
153155
const keyword = parseNameValue(source, pos + 1);
154156
switch (keyword) {

packages/mf2-messageformat/src/data-model/stringify.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ function stringifyAttribute({ name, value }: Attribute) {
105105

106106
function stringifyPattern(pattern: Pattern, quoted: boolean) {
107107
let res = '';
108-
if (!quoted && typeof pattern[0] === 'string' && pattern[0][0] === '.') {
108+
if (!quoted && typeof pattern[0] === 'string' && /^\s*\./.test(pattern[0])) {
109109
quoted = true;
110110
}
111111
for (const el of pattern) {

0 commit comments

Comments
 (0)