Skip to content

Commit be7ff8f

Browse files
committed
Expose FluentSerializer.serializeExpression
1 parent 0b8ba5f commit be7ff8f

File tree

2 files changed

+133
-9
lines changed

2 files changed

+133
-9
lines changed

fluent-syntax/src/serializer.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ export default class FluentSerializer {
1818
}
1919

2020
serialize(resource) {
21+
if (resource.type !== 'Resource') {
22+
throw new Error(`Unknown resource type: ${resource.type}`);
23+
}
24+
2125
const parts = [];
2226

2327
if (resource.comment) {
@@ -66,6 +70,10 @@ export default class FluentSerializer {
6670
throw new Error(`Unknown entry type: ${entry.type}`);
6771
}
6872
}
73+
74+
serializeExpression(expr) {
75+
return serializeExpression(expr);
76+
}
6977
}
7078

7179

@@ -176,7 +184,15 @@ function serializePlaceable(placeable) {
176184
case 'Placeable':
177185
return `{${serializePlaceable(expr)}}`;
178186
case 'SelectExpression':
179-
return `{${serializeSelectExpression(expr)}}`;
187+
// Special-case select expression to control the whitespace around the
188+
// opening and the closing brace.
189+
if (expr.expression) {
190+
// A select expression with a selector.
191+
return `{ ${serializeSelectExpression(expr)}}`;
192+
} else {
193+
// A variant list without a selector.
194+
return `{${serializeSelectExpression(expr)}}`;
195+
}
180196
default:
181197
return `{ ${serializeExpression(expr)} }`;
182198
}
@@ -199,6 +215,8 @@ function serializeExpression(expr) {
199215
return serializeVariantExpression(expr);
200216
case 'CallExpression':
201217
return serializeCallExpression(expr);
218+
case 'SelectExpression':
219+
return serializeSelectExpression(expr);
202220
default:
203221
throw new Error(`Unknown expression type: ${expr.type}`);
204222
}
@@ -229,7 +247,7 @@ function serializeSelectExpression(expr) {
229247
const parts = [];
230248

231249
if (expr.expression) {
232-
const selector = ` ${serializeExpression(expr.expression)} ->`;
250+
const selector = `${serializeExpression(expr.expression)} ->`;
233251
parts.push(selector);
234252
}
235253

fluent-syntax/test/serializer_test.js

Lines changed: 113 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,36 @@
11
import assert from 'assert';
22
import { ftl } from './util';
33

4-
import { parse, serialize } from '../src';
4+
import { FluentParser, FluentSerializer } from '../src';
55

66

7-
function pretty(text) {
8-
const res = parse(text);
9-
return serialize(res, {
10-
withJunk: false
7+
suite('Serialize resource', function() {
8+
let pretty;
9+
10+
setup(function() {
11+
const parser = new FluentParser();
12+
const serializer = new FluentSerializer({
13+
withJunk: false
14+
});
15+
16+
pretty = function pretty(text) {
17+
const res = parser.parse(text);
18+
return serializer.serialize(res);
19+
}
20+
});
21+
22+
test('invalid resource', function() {
23+
const serializer = new FluentSerializer();
24+
assert.throws(
25+
() => serializer.serialize(null),
26+
/Cannot read property 'type'/
27+
);
28+
assert.throws(
29+
() => serializer.serialize({}),
30+
/Unknown resource type/
31+
);
1132
});
12-
}
1333

14-
suite('Serializer', function() {
1534
test('simple message', function() {
1635
const input = ftl`
1736
foo = Foo
@@ -400,3 +419,90 @@ suite('Serializer', function() {
400419
assert.equal(pretty(input), input);
401420
});
402421
});
422+
423+
suite('Serialize expression', function() {
424+
let pretty;
425+
426+
setup(function() {
427+
const parser = new FluentParser();
428+
const serializer = new FluentSerializer({
429+
withJunk: false
430+
});
431+
432+
pretty = function pretty(text) {
433+
const {value: {elements: [placeable]}} = parser.parseEntry(text);
434+
return serializer.serializeExpression(placeable.expression);
435+
}
436+
});
437+
438+
test('invalid expression', function() {
439+
const serializer = new FluentSerializer();
440+
assert.throws(
441+
() => serializer.serializeExpression(null),
442+
/Cannot read property 'type'/
443+
);
444+
assert.throws(
445+
() => serializer.serializeExpression({}),
446+
/Unknown expression type/
447+
);
448+
});
449+
450+
test('string expression', function() {
451+
const input = ftl`
452+
foo = { "str" }
453+
`;
454+
assert.equal(pretty(input), '"str"');
455+
});
456+
457+
test('number expression', function() {
458+
const input = ftl`
459+
foo = { 3 }
460+
`;
461+
assert.equal(pretty(input), '3');
462+
});
463+
464+
test('message reference', function() {
465+
const input = ftl`
466+
foo = { msg }
467+
`;
468+
assert.equal(pretty(input), 'msg');
469+
});
470+
471+
test('external argument', function() {
472+
const input = ftl`
473+
foo = { $ext }
474+
`;
475+
assert.equal(pretty(input), '$ext');
476+
});
477+
478+
test('attribute expression', function() {
479+
const input = ftl`
480+
foo = { msg.attr }
481+
`;
482+
assert.equal(pretty(input), 'msg.attr');
483+
});
484+
485+
test('variant expression', function() {
486+
const input = ftl`
487+
foo = { -msg[variant] }
488+
`;
489+
assert.equal(pretty(input), '-msg[variant]');
490+
});
491+
492+
test('call expression', function() {
493+
const input = ftl`
494+
foo = { BUILTIN(3.14, kwarg: "value") }
495+
`;
496+
assert.equal(pretty(input), 'BUILTIN(3.14, kwarg: "value")');
497+
});
498+
499+
test('select expression', function() {
500+
const input = ftl`
501+
foo =
502+
{ $num ->
503+
*[one] One
504+
}
505+
`;
506+
assert.equal(pretty(input), '$num ->\n *[one] One\n');
507+
});
508+
});

0 commit comments

Comments
 (0)