Skip to content

Commit 13710cc

Browse files
authored
fix(bundle): Only accept space, CRLF & LF as syntactical whitespace (#651)
1 parent 3f523cc commit 13710cc

File tree

7 files changed

+68
-57
lines changed

7 files changed

+68
-57
lines changed

fluent-bundle/src/resource.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ import {
1919

2020
// This regex is used to iterate through the beginnings of messages and terms.
2121
// With the /m flag, the ^ matches at the beginning of every line.
22-
const RE_MESSAGE_START = /^(-?[a-zA-Z][\w-]*) *= */gm;
22+
const RE_MESSAGE_START = /^(?<!\r)(-?[a-zA-Z][\w-]*) *= */gm;
2323

2424
// Both Attributes and Variants are parsed in while loops. These regexes are
2525
// used to break out of them.
26-
const RE_ATTRIBUTE_START = /\.([a-zA-Z][\w-]*) *= */y;
26+
const RE_ATTRIBUTE_START = /(?<=\n *)\.([a-zA-Z][\w-]*) *= */y;
2727
const RE_VARIANT_START = /\*?\[/y;
2828

2929
const RE_NUMBER_LITERAL = /(-?[0-9]+(?:\.([0-9]+))?)/y;
@@ -37,8 +37,8 @@ const RE_FUNCTION_NAME = /^[A-Z][A-Z0-9_-]*$/;
3737
// if the next line is indented. For StringLiterals they are: \ (starts an
3838
// escape sequence), " (ends the literal), and line breaks which are not allowed
3939
// in StringLiterals. Note that string runs may be empty; text runs may not.
40-
const RE_TEXT_RUN = /([^{}\n\r]+)/y;
41-
const RE_STRING_RUN = /([^\\"\n\r]*)/y;
40+
const RE_TEXT_RUN = /((?:[^{}\n\r]|\r(?!\n))+)/y;
41+
const RE_STRING_RUN = /((?:[^\\"\n\r]|\r(?!\n))*)/y;
4242

4343
// Escape sequences.
4444
const RE_STRING_ESCAPE = /\\([\\"])/y;
@@ -53,17 +53,17 @@ const RE_BLANK_LINES = / *\r?\n/g;
5353
const RE_INDENT = /( *)$/;
5454

5555
// Common tokens.
56-
const TOKEN_BRACE_OPEN = /{\s*/y;
57-
const TOKEN_BRACE_CLOSE = /\s*}/y;
58-
const TOKEN_BRACKET_OPEN = /\[\s*/y;
59-
const TOKEN_BRACKET_CLOSE = /\s*] */y;
60-
const TOKEN_PAREN_OPEN = /\s*\(\s*/y;
61-
const TOKEN_ARROW = /\s*->\s*/y;
62-
const TOKEN_COLON = /\s*:\s*/y;
56+
const TOKEN_BRACE_OPEN = /{(?: |\r?\n)*/y;
57+
const TOKEN_BRACE_CLOSE = /(?: |\r?\n)*}/y;
58+
const TOKEN_BRACKET_OPEN = /\[(?: |\r?\n)*/y;
59+
const TOKEN_BRACKET_CLOSE = /(?: |\r?\n)*] */y;
60+
const TOKEN_PAREN_OPEN = /(?: |\r?\n)*\((?: |\r?\n)*/y;
61+
const TOKEN_ARROW = /(?: |\r?\n)*->(?: |\r?\n)*/y;
62+
const TOKEN_COLON = /(?: |\r?\n)*:(?: |\r?\n)*/y;
6363
// Note the optional comma. As a deviation from the Fluent EBNF, the parser
6464
// doesn't enforce commas between call arguments.
65-
const TOKEN_COMMA = /\s*,?\s*/y;
66-
const TOKEN_BLANK = /\s+/y;
65+
const TOKEN_COMMA = /(?: |\r?\n)*,?(?: |\r?\n)*/y;
66+
const TOKEN_BLANK = /(?: |\r?\n)+/y;
6767

6868
/**
6969
* Fluent Resource is a structure storing parsed localization entries.
Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,3 @@
11
{
2-
"body": [
3-
{
4-
"id": "err01",
5-
"value": "Value 01",
6-
"attributes": {}
7-
},
8-
{
9-
"id": "err02",
10-
"value": "Value 02",
11-
"attributes": {}
12-
},
13-
{
14-
"id": "err03",
15-
"value": [
16-
"\r\r",
17-
"Value 03",
18-
"\r",
19-
"Continued"
20-
],
21-
"attributes": {
22-
"title": "Title"
23-
}
24-
},
25-
{
26-
"id": "err05",
27-
"value": [
28-
{
29-
"type": "select",
30-
"selector": {
31-
"type": "var",
32-
"name": "sel"
33-
}
34-
}
35-
],
36-
"attributes": {}
37-
}
38-
]
2+
"body": []
393
}

fluent-bundle/test/fixtures_reference/tab.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@
2323
"attributes": {
2424
"attr": "\t\t"
2525
}
26+
},
27+
{
28+
"id": "key07",
29+
"value": null,
30+
"attributes": {
31+
"good": "Spaces as indent"
32+
}
2633
}
2734
]
2835
}

fluent-react/test/use_localization.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ describe("useLocalization", () => {
2727
const bundle = new FluentBundle("en");
2828
bundle.addResource(
2929
new FluentResource(
30-
"foo = FOO\nbar = BAR<elem>BAZ</elem>\n\t.title = QUX\n"
30+
"foo = FOO\nbar = BAR<elem>BAZ</elem>\n .title = QUX\n"
3131
)
3232
);
3333
return bundle;

fluent-syntax/makefile

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ export SHELL := /bin/bash
22

33
OK := \033[32;01m✓\033[0m
44

5-
STRUCTURE_FTL := $(wildcard test/fixtures_structure/*.ftl)
6-
STRUCTURE_AST := $(STRUCTURE_FTL:.ftl=.json)
5+
FIXTURES_FTL := $(wildcard test/fixtures_structure/*.ftl) $(wildcard test/fixtures_reference/*.ftl)
6+
FIXTURES_AST := $(FIXTURES_FTL:.ftl=.json)
77

88
.PHONY: fixtures
9-
fixtures: $(STRUCTURE_AST)
9+
fixtures: $(FIXTURES_AST)
1010

11-
.PHONY: $(STRUCTURE_AST)
12-
$(STRUCTURE_AST): test/fixtures_structure/%.json: test/fixtures_structure/%.ftl
13-
@../tools/parse.js --silent --with-spans $< > $@
11+
.PHONY: $(FIXTURES_AST)
12+
$(FIXTURES_AST): test/fixtures_%.json: test/fixtures_%.ftl
13+
@../tools/parse.mjs --silent --with-spans $< > $@
1414
@echo -e " $(OK) $@"

fluent-syntax/test/fixtures_reference/tab.ftl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,8 @@ key05 =
1919
# OK (attribute value is two tabs)
2020
key06 =
2121
.attr =
22+
23+
# Partial Error (tab is not a valid indent)
24+
key07 =
25+
.good = Spaces as indent
26+
.bad = Tab as indent

fluent-syntax/test/fixtures_reference/tab.json

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,41 @@
116116
"type": "Comment",
117117
"content": "OK (attribute value is two tabs)"
118118
}
119+
},
120+
{
121+
"type": "Message",
122+
"id": {
123+
"type": "Identifier",
124+
"name": "key07"
125+
},
126+
"value": null,
127+
"attributes": [
128+
{
129+
"type": "Attribute",
130+
"id": {
131+
"type": "Identifier",
132+
"name": "good"
133+
},
134+
"value": {
135+
"type": "Pattern",
136+
"elements": [
137+
{
138+
"type": "TextElement",
139+
"value": "Spaces as indent"
140+
}
141+
]
142+
}
143+
}
144+
],
145+
"comment": {
146+
"type": "Comment",
147+
"content": "Partial Error (tab is not a valid indent)"
148+
}
149+
},
150+
{
151+
"type": "Junk",
152+
"annotations": [],
153+
"content": "\t.bad = Tab as indent\n"
119154
}
120155
]
121156
}

0 commit comments

Comments
 (0)