Skip to content

Commit cf80593

Browse files
authored
Merge pull request #513 from stasm/fix-special-chars-start
* Port parser reference tests projectfluent/fluent#313 * Don't drop to newline when patterns start with special chars
2 parents f41d910 + 99d472b commit cf80593

File tree

5 files changed

+179
-9
lines changed

5 files changed

+179
-9
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"body": [
3+
{
4+
"id": "bracket-inline",
5+
"value": "[Value]",
6+
"attributes": {}
7+
},
8+
{
9+
"id": "dot-inline",
10+
"value": ".Value",
11+
"attributes": {}
12+
},
13+
{
14+
"id": "star-inline",
15+
"value": "*Value",
16+
"attributes": {}
17+
}
18+
]
19+
}

fluent-syntax/src/serializer.ts

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as AST from "./ast.js";
22

3-
function indent(content: string): string {
3+
function indentExceptFirstLine(content: string): string {
44
return content.split("\n").join("\n ");
55
}
66

@@ -13,6 +13,29 @@ function isSelectExpr(elem: AST.PatternElement): boolean {
1313
&& elem.expression instanceof AST.SelectExpression;
1414
}
1515

16+
function shouldStartOnNewLine(pattern: AST.Pattern): boolean {
17+
const isMultiline =
18+
pattern.elements.some(isSelectExpr) ||
19+
pattern.elements.some(includesNewLine);
20+
21+
if (isMultiline) {
22+
const firstElement = pattern.elements[0];
23+
if (firstElement instanceof AST.TextElement) {
24+
const firstChar = firstElement.value[0];
25+
// Due to the indentation requirement these text characters may not appear
26+
// as the first character on a new line.
27+
if (firstChar === "[" || firstChar === "." || firstChar === "*") {
28+
return false;
29+
}
30+
}
31+
32+
return true;
33+
}
34+
35+
return false;
36+
}
37+
38+
1639
// Bit masks representing the state of the serializer.
1740
export const HAS_ENTRIES = 1;
1841

@@ -136,22 +159,19 @@ function serializeTerm(term: AST.Term): string {
136159

137160

138161
function serializeAttribute(attribute: AST.Attribute): string {
139-
const value = indent(serializePattern(attribute.value));
162+
const value = indentExceptFirstLine(serializePattern(attribute.value));
140163
return `\n .${attribute.id.name} =${value}`;
141164
}
142165

143166

144167
function serializePattern(pattern: AST.Pattern): string {
145168
const content = pattern.elements.map(serializeElement).join("");
146-
const startOnNewLine =
147-
pattern.elements.some(isSelectExpr) ||
148-
pattern.elements.some(includesNewLine);
149169

150-
if (startOnNewLine) {
151-
return `\n ${indent(content)}`;
170+
if (shouldStartOnNewLine(pattern)) {
171+
return `\n ${indentExceptFirstLine(content)}`;
152172
}
153173

154-
return ` ${content}`;
174+
return ` ${indentExceptFirstLine(content)}`;
155175
}
156176

157177

@@ -228,7 +248,7 @@ export function serializeExpression(expr: AST.Expression): string {
228248

229249
function serializeVariant(variant: AST.Variant): string {
230250
const key = serializeVariantKey(variant.key);
231-
const value = indent(serializePattern(variant.value));
251+
const value = indentExceptFirstLine(serializePattern(variant.value));
232252

233253
if (variant.default) {
234254
return `\n *[${key}]${value}`;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
## OK
2+
3+
bracket-inline = [Value]
4+
dot-inline = .Value
5+
star-inline = *Value
6+
7+
## ERRORS
8+
9+
bracket-newline =
10+
[Value]
11+
dot-newline =
12+
.Value
13+
star-newline =
14+
*Value
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
{
2+
"type": "Resource",
3+
"body": [
4+
{
5+
"type": "GroupComment",
6+
"content": "OK"
7+
},
8+
{
9+
"type": "Message",
10+
"id": {
11+
"type": "Identifier",
12+
"name": "bracket-inline"
13+
},
14+
"value": {
15+
"type": "Pattern",
16+
"elements": [
17+
{
18+
"type": "TextElement",
19+
"value": "[Value]"
20+
}
21+
]
22+
},
23+
"attributes": [],
24+
"comment": null
25+
},
26+
{
27+
"type": "Message",
28+
"id": {
29+
"type": "Identifier",
30+
"name": "dot-inline"
31+
},
32+
"value": {
33+
"type": "Pattern",
34+
"elements": [
35+
{
36+
"type": "TextElement",
37+
"value": ".Value"
38+
}
39+
]
40+
},
41+
"attributes": [],
42+
"comment": null
43+
},
44+
{
45+
"type": "Message",
46+
"id": {
47+
"type": "Identifier",
48+
"name": "star-inline"
49+
},
50+
"value": {
51+
"type": "Pattern",
52+
"elements": [
53+
{
54+
"type": "TextElement",
55+
"value": "*Value"
56+
}
57+
]
58+
},
59+
"attributes": [],
60+
"comment": null
61+
},
62+
{
63+
"type": "GroupComment",
64+
"content": "ERRORS"
65+
},
66+
{
67+
"type": "Junk",
68+
"annotations": [],
69+
"content": "bracket-newline =\n [Value]\n"
70+
},
71+
{
72+
"type": "Junk",
73+
"annotations": [],
74+
"content": "dot-newline =\n .Value\n"
75+
},
76+
{
77+
"type": "Junk",
78+
"annotations": [],
79+
"content": "star-newline =\n *Value\n"
80+
}
81+
]
82+
}

fluent-syntax/test/serializer_test.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,30 @@ suite("Serialize resource", function() {
188188
assert.strictEqual(pretty(input), input);
189189
});
190190

191+
test("multiline starting inline", function() {
192+
const input = ftl`
193+
foo = Foo
194+
Bar
195+
196+
`;
197+
const output = ftl`
198+
foo =
199+
Foo
200+
Bar
201+
202+
`;
203+
assert.strictEqual(pretty(input), output);
204+
});
205+
206+
test("multiline starting inline with a special char", function() {
207+
const input = ftl`
208+
foo = *Foo
209+
Bar
210+
211+
`;
212+
assert.strictEqual(pretty(input), input);
213+
});
214+
191215
test("multiline with placeable", function() {
192216
const input = ftl`
193217
foo =
@@ -338,6 +362,17 @@ suite("Serialize resource", function() {
338362
assert.strictEqual(pretty(input), output);
339363
});
340364

365+
test("select expression in inline value starting with a special char", function() {
366+
const input = ftl`
367+
foo = .Foo { $sel ->
368+
*[a] A
369+
[b] B
370+
}
371+
372+
`;
373+
assert.strictEqual(pretty(input), input);
374+
});
375+
341376
test("select expression in multiline value", function() {
342377
const input = ftl`
343378
foo =

0 commit comments

Comments
 (0)