Skip to content
This repository was archived by the owner on May 4, 2020. It is now read-only.

Commit c052050

Browse files
author
Long Ho
committed
feat(intl-messageformat-parser): Fix number skeleton parser
Initially we didn't handle `.###` case. BREAKING CHANGE: Change precision wildcard token from `+` to `*` to conform with ICU67+
1 parent 40217b6 commit c052050

File tree

3 files changed

+48
-20
lines changed

3 files changed

+48
-20
lines changed

packages/intl-messageformat-parser/src/skeleton.ts

+19-15
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ function icuUnitToEcma(unit: string): UnifiedNumberFormatOptions['unit'] {
150150
return unit.replace(/^(.*?)-/, '') as UnifiedNumberFormatOptions['unit'];
151151
}
152152

153-
const FRACTION_PRECISION_REGEX = /^\.(?:(0+)(\+|#+)?)?$/g;
153+
const FRACTION_PRECISION_REGEX = /^\.(?:(0+)(\*)?|(#+)|(0+)(#+))$/g;
154154
const SIGNIFICANT_PRECISION_REGEX = /^(@+)?(\+|#+)?$/g;
155155

156156
function parseSignificantPrecision(str: string): UnifiedNumberFormatOptions {
@@ -248,6 +248,7 @@ export function convertNumberSkeletonToNumberFormatOptions(
248248
result.useGrouping = false;
249249
continue;
250250
case 'precision-integer':
251+
case '.':
251252
result.maximumFractionDigits = 0;
252253
continue;
253254
case 'measure-unit':
@@ -304,6 +305,7 @@ export function convertNumberSkeletonToNumberFormatOptions(
304305
}
305306
// Precision
306307
// https://github.com/unicode-org/icu/blob/master/docs/userguide/format_parse/numbers/skeletons.md#fraction-precision
308+
// precision-integer case
307309
if (FRACTION_PRECISION_REGEX.test(token.stem)) {
308310
if (token.options.length > 1) {
309311
throw new RangeError(
@@ -313,28 +315,30 @@ export function convertNumberSkeletonToNumberFormatOptions(
313315
token.stem.replace(FRACTION_PRECISION_REGEX, function(
314316
match: string,
315317
g1: string,
316-
g2: string | number
318+
g2: string | number,
319+
g3: string,
320+
g4: string,
321+
g5: string
317322
) {
318-
// precision-integer case
319-
if (match === '.') {
320-
result.maximumFractionDigits = 0;
321-
}
322-
// .000+ case
323-
else if (g2 === '+') {
324-
result.minimumFractionDigits = g2.length;
323+
// .000* case (before ICU67 it was .000+)
324+
if (g2 === '*') {
325+
result.minimumFractionDigits = g1.length;
325326
}
326327
// .### case
327-
else if (g1[0] === '#') {
328-
result.maximumFractionDigits = g1.length;
328+
else if (g3 && g3[0] === '#') {
329+
result.maximumFractionDigits = g3.length;
329330
}
330-
// .00## or .000 case
331-
else {
331+
// .00## case
332+
else if (g4 && g5) {
333+
result.minimumFractionDigits = g4.length;
334+
result.maximumFractionDigits = g4.length + g5.length;
335+
} else {
332336
result.minimumFractionDigits = g1.length;
333-
result.maximumFractionDigits =
334-
g1.length + (typeof g2 === 'string' ? g2.length : 0);
337+
result.maximumFractionDigits = g1.length;
335338
}
336339
return '';
337340
});
341+
338342
if (token.options.length) {
339343
result = {...result, ...parseSignificantPrecision(token.options[0])};
340344
}

packages/intl-messageformat-parser/test/__snapshots__/number_skeleton.test.ts.snap

+24-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Object {
2222
}
2323
`;
2424

25-
exports[`[convertNumberSkeletonToNumberFormatOptions] case: "currency/GBP .0+/@@@" 1`] = `
25+
exports[`[convertNumberSkeletonToNumberFormatOptions] case: "currency/GBP .0*/@@@" 1`] = `
2626
Object {
2727
"currency": "GBP",
2828
"maximumSignificantDigits": 3,
@@ -99,6 +99,21 @@ Object {
9999
}
100100
`;
101101

102+
exports[`[convertNumberSkeletonToNumberFormatOptions] case: "percent .##" 1`] = `
103+
Object {
104+
"maximumFractionDigits": 2,
105+
"style": "percent",
106+
}
107+
`;
108+
109+
exports[`[convertNumberSkeletonToNumberFormatOptions] case: "percent .0###" 1`] = `
110+
Object {
111+
"maximumFractionDigits": 4,
112+
"minimumFractionDigits": 1,
113+
"style": "percent",
114+
}
115+
`;
116+
102117
exports[`[convertNumberSkeletonToNumberFormatOptions] case: "percent .00/@##" 1`] = `
103118
Object {
104119
"maximumFractionDigits": 2,
@@ -119,11 +134,17 @@ Object {
119134
}
120135
`;
121136

122-
exports[`[convertNumberSkeletonToNumberFormatOptions] case: "percent .00/@@@@+" 1`] = `
137+
exports[`[convertNumberSkeletonToNumberFormatOptions] case: "percent .00/@@@@*" 1`] = `
123138
Object {
124139
"maximumFractionDigits": 2,
125140
"minimumFractionDigits": 2,
126-
"minimumSignificantDigits": 4,
141+
"style": "percent",
142+
}
143+
`;
144+
145+
exports[`[convertNumberSkeletonToNumberFormatOptions] case: "percent .000*" 1`] = `
146+
Object {
147+
"minimumFractionDigits": 3,
127148
"style": "percent",
128149
}
129150
`;

packages/intl-messageformat-parser/test/number_skeleton.test.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@ test.each([
1414
});
1515

1616
test.each([
17+
'percent .##',
18+
'percent .000*',
19+
'percent .0###',
1720
'percent .00/@##',
1821
'percent .00/@@@',
19-
'percent .00/@@@@+',
22+
'percent .00/@@@@*',
2023
'currency/CAD .',
21-
'currency/GBP .0+/@@@',
24+
'currency/GBP .0*/@@@',
2225
'currency/GBP .00##/@@@',
2326
'currency/GBP .00##/@@@ unit-width-full-name',
2427
'measure-unit/length-meter .00##/@@@',

0 commit comments

Comments
 (0)