@formatjs/icu-skeleton-parser 2.1.2 → 2.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -1,2 +1,68 @@
1
- export * from "./date-time.js";
2
- export * from "./number.js";
1
+ //#region packages/icu-skeleton-parser/date-time.d.ts
2
+ /**
3
+ * Parse Date time skeleton into Intl.DateTimeFormatOptions
4
+ * Ref: https://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
5
+ * @public
6
+ * @param skeleton skeleton string
7
+ */
8
+ declare function parseDateTimeSkeleton(skeleton: string): Intl.DateTimeFormatOptions;
9
+ //#endregion
10
+ //#region packages/ecma402-abstract/types/number.d.ts
11
+ type NumberFormatNotation = "standard" | "scientific" | "engineering" | "compact";
12
+ type RoundingPriorityType = "auto" | "morePrecision" | "lessPrecision";
13
+ type RoundingModeType = "ceil" | "floor" | "expand" | "trunc" | "halfCeil" | "halfFloor" | "halfExpand" | "halfTrunc" | "halfEven";
14
+ type UseGroupingType = "min2" | "auto" | "always" | boolean;
15
+ interface NumberFormatDigitOptions {
16
+ minimumIntegerDigits?: number;
17
+ minimumSignificantDigits?: number;
18
+ maximumSignificantDigits?: number;
19
+ minimumFractionDigits?: number;
20
+ maximumFractionDigits?: number;
21
+ roundingPriority?: RoundingPriorityType;
22
+ roundingIncrement?: number;
23
+ roundingMode?: RoundingModeType;
24
+ trailingZeroDisplay?: TrailingZeroDisplay;
25
+ }
26
+ type NumberFormatOptionsLocaleMatcher = "lookup" | "best fit";
27
+ type NumberFormatOptionsStyle = "decimal" | "percent" | "currency" | "unit";
28
+ type NumberFormatOptionsCompactDisplay = "short" | "long";
29
+ type NumberFormatOptionsCurrencyDisplay = "symbol" | "code" | "name" | "narrowSymbol";
30
+ type NumberFormatOptionsCurrencySign = "standard" | "accounting";
31
+ type NumberFormatOptionsNotation = NumberFormatNotation;
32
+ type NumberFormatOptionsSignDisplay = "auto" | "always" | "never" | "exceptZero" | "negative";
33
+ type NumberFormatOptionsUnitDisplay = "long" | "short" | "narrow";
34
+ type TrailingZeroDisplay = "auto" | "stripIfInteger";
35
+ type NumberFormatOptions = Omit<Intl.NumberFormatOptions, "signDisplay" | "useGrouping"> & NumberFormatDigitOptions & {
36
+ localeMatcher?: NumberFormatOptionsLocaleMatcher;
37
+ style?: NumberFormatOptionsStyle;
38
+ compactDisplay?: NumberFormatOptionsCompactDisplay;
39
+ currencyDisplay?: NumberFormatOptionsCurrencyDisplay;
40
+ currencySign?: NumberFormatOptionsCurrencySign;
41
+ notation?: NumberFormatOptionsNotation;
42
+ signDisplay?: NumberFormatOptionsSignDisplay;
43
+ unit?: string;
44
+ unitDisplay?: NumberFormatOptionsUnitDisplay;
45
+ numberingSystem?: string;
46
+ trailingZeroDisplay?: TrailingZeroDisplay;
47
+ roundingPriority?: RoundingPriorityType;
48
+ roundingIncrement?: number;
49
+ roundingMode?: RoundingModeType;
50
+ useGrouping?: UseGroupingType;
51
+ };
52
+ //#endregion
53
+ //#region packages/icu-skeleton-parser/number.d.ts
54
+ interface ExtendedNumberFormatOptions extends NumberFormatOptions {
55
+ scale?: number;
56
+ }
57
+ interface NumberSkeletonToken {
58
+ stem: string;
59
+ options: string[];
60
+ }
61
+ declare function parseNumberSkeletonFromString(skeleton: string): NumberSkeletonToken[];
62
+ /**
63
+ * https://github.com/unicode-org/icu/blob/master/docs/userguide/format_parse/numbers/skeletons.md#skeleton-stems-and-options
64
+ */
65
+ declare function parseNumberSkeleton(tokens: NumberSkeletonToken[]): ExtendedNumberFormatOptions;
66
+ //#endregion
67
+ export { ExtendedNumberFormatOptions, NumberSkeletonToken, parseDateTimeSkeleton, parseNumberSkeleton, parseNumberSkeletonFromString };
68
+ //# sourceMappingURL=index.d.ts.map
package/index.js CHANGED
@@ -1,2 +1,380 @@
1
- export * from "./date-time.js";
2
- export * from "./number.js";
1
+ //#region packages/icu-skeleton-parser/date-time.ts
2
+ /**
3
+ * https://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
4
+ * Credit: https://github.com/caridy/intl-datetimeformat-pattern/blob/master/index.js
5
+ * with some tweaks
6
+ */
7
+ const DATE_TIME_REGEX = /(?:[Eec]{1,6}|G{1,5}|[Qq]{1,5}|(?:[yYur]+|U{1,5})|[ML]{1,5}|d{1,2}|D{1,3}|F{1}|[abB]{1,5}|[hkHK]{1,2}|w{1,2}|W{1}|m{1,2}|s{1,2}|[zZOvVxX]{1,4})(?=([^']*'[^']*')*[^']*$)/g;
8
+ /**
9
+ * Parse Date time skeleton into Intl.DateTimeFormatOptions
10
+ * Ref: https://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
11
+ * @public
12
+ * @param skeleton skeleton string
13
+ */
14
+ function parseDateTimeSkeleton(skeleton) {
15
+ const result = {};
16
+ skeleton.replace(DATE_TIME_REGEX, (match) => {
17
+ const len = match.length;
18
+ switch (match[0]) {
19
+ case "G":
20
+ result.era = len === 4 ? "long" : len === 5 ? "narrow" : "short";
21
+ break;
22
+ case "y":
23
+ result.year = len === 2 ? "2-digit" : "numeric";
24
+ break;
25
+ case "Y":
26
+ case "u":
27
+ case "U":
28
+ case "r": throw new RangeError("`Y/u/U/r` (year) patterns are not supported, use `y` instead");
29
+ case "q":
30
+ case "Q": throw new RangeError("`q/Q` (quarter) patterns are not supported");
31
+ case "M":
32
+ case "L":
33
+ result.month = [
34
+ "numeric",
35
+ "2-digit",
36
+ "short",
37
+ "long",
38
+ "narrow"
39
+ ][len - 1];
40
+ break;
41
+ case "w":
42
+ case "W": throw new RangeError("`w/W` (week) patterns are not supported");
43
+ case "d":
44
+ result.day = ["numeric", "2-digit"][len - 1];
45
+ break;
46
+ case "D":
47
+ case "F":
48
+ case "g": throw new RangeError("`D/F/g` (day) patterns are not supported, use `d` instead");
49
+ case "E":
50
+ result.weekday = len === 4 ? "long" : len === 5 ? "narrow" : "short";
51
+ break;
52
+ case "e":
53
+ if (len < 4) throw new RangeError("`e..eee` (weekday) patterns are not supported");
54
+ result.weekday = [
55
+ "short",
56
+ "long",
57
+ "narrow",
58
+ "short"
59
+ ][len - 4];
60
+ break;
61
+ case "c":
62
+ if (len < 4) throw new RangeError("`c..ccc` (weekday) patterns are not supported");
63
+ result.weekday = [
64
+ "short",
65
+ "long",
66
+ "narrow",
67
+ "short"
68
+ ][len - 4];
69
+ break;
70
+ case "a":
71
+ result.hour12 = true;
72
+ break;
73
+ case "b":
74
+ case "B": throw new RangeError("`b/B` (period) patterns are not supported, use `a` instead");
75
+ case "h":
76
+ result.hourCycle = "h12";
77
+ result.hour = ["numeric", "2-digit"][len - 1];
78
+ break;
79
+ case "H":
80
+ result.hourCycle = "h23";
81
+ result.hour = ["numeric", "2-digit"][len - 1];
82
+ break;
83
+ case "K":
84
+ result.hourCycle = "h11";
85
+ result.hour = ["numeric", "2-digit"][len - 1];
86
+ break;
87
+ case "k":
88
+ result.hourCycle = "h24";
89
+ result.hour = ["numeric", "2-digit"][len - 1];
90
+ break;
91
+ case "j":
92
+ case "J":
93
+ case "C": throw new RangeError("`j/J/C` (hour) patterns are not supported, use `h/H/K/k` instead");
94
+ case "m":
95
+ result.minute = ["numeric", "2-digit"][len - 1];
96
+ break;
97
+ case "s":
98
+ result.second = ["numeric", "2-digit"][len - 1];
99
+ break;
100
+ case "S":
101
+ case "A": throw new RangeError("`S/A` (second) patterns are not supported, use `s` instead");
102
+ case "z":
103
+ result.timeZoneName = len < 4 ? "short" : "long";
104
+ break;
105
+ case "Z":
106
+ case "O":
107
+ case "v":
108
+ case "V":
109
+ case "X":
110
+ case "x": throw new RangeError("`Z/O/v/V/X/x` (timeZone) patterns are not supported, use `z` instead");
111
+ }
112
+ return "";
113
+ });
114
+ return result;
115
+ }
116
+ //#endregion
117
+ //#region packages/icu-skeleton-parser/regex.generated.ts
118
+ const WHITE_SPACE_REGEX = /[\t-\r \x85\u200E\u200F\u2028\u2029]/i;
119
+ //#endregion
120
+ //#region packages/icu-skeleton-parser/number.ts
121
+ function parseNumberSkeletonFromString(skeleton) {
122
+ if (skeleton.length === 0) throw new Error("Number skeleton cannot be empty");
123
+ const stringTokens = skeleton.split(WHITE_SPACE_REGEX).filter((x) => x.length > 0);
124
+ const tokens = [];
125
+ for (const stringToken of stringTokens) {
126
+ let stemAndOptions = stringToken.split("/");
127
+ if (stemAndOptions.length === 0) throw new Error("Invalid number skeleton");
128
+ const [stem, ...options] = stemAndOptions;
129
+ for (const option of options) if (option.length === 0) throw new Error("Invalid number skeleton");
130
+ tokens.push({
131
+ stem,
132
+ options
133
+ });
134
+ }
135
+ return tokens;
136
+ }
137
+ function icuUnitToEcma(unit) {
138
+ return unit.replace(/^(.*?)-/, "");
139
+ }
140
+ const FRACTION_PRECISION_REGEX = /^\.(?:(0+)(\*)?|(#+)|(0+)(#+))$/g;
141
+ const SIGNIFICANT_PRECISION_REGEX = /^(@+)?(\+|#+)?[rs]?$/g;
142
+ const INTEGER_WIDTH_REGEX = /(\*)(0+)|(#+)(0+)|(0+)/g;
143
+ const CONCISE_INTEGER_WIDTH_REGEX = /^(0+)$/;
144
+ function parseSignificantPrecision(str) {
145
+ const result = {};
146
+ if (str[str.length - 1] === "r") result.roundingPriority = "morePrecision";
147
+ else if (str[str.length - 1] === "s") result.roundingPriority = "lessPrecision";
148
+ str.replace(SIGNIFICANT_PRECISION_REGEX, function(_, g1, g2) {
149
+ if (typeof g2 !== "string") {
150
+ result.minimumSignificantDigits = g1.length;
151
+ result.maximumSignificantDigits = g1.length;
152
+ } else if (g2 === "+") result.minimumSignificantDigits = g1.length;
153
+ else if (g1[0] === "#") result.maximumSignificantDigits = g1.length;
154
+ else {
155
+ result.minimumSignificantDigits = g1.length;
156
+ result.maximumSignificantDigits = g1.length + (typeof g2 === "string" ? g2.length : 0);
157
+ }
158
+ return "";
159
+ });
160
+ return result;
161
+ }
162
+ function parseSign(str) {
163
+ switch (str) {
164
+ case "sign-auto": return { signDisplay: "auto" };
165
+ case "sign-accounting":
166
+ case "()": return { currencySign: "accounting" };
167
+ case "sign-always":
168
+ case "+!": return { signDisplay: "always" };
169
+ case "sign-accounting-always":
170
+ case "()!": return {
171
+ signDisplay: "always",
172
+ currencySign: "accounting"
173
+ };
174
+ case "sign-except-zero":
175
+ case "+?": return { signDisplay: "exceptZero" };
176
+ case "sign-accounting-except-zero":
177
+ case "()?": return {
178
+ signDisplay: "exceptZero",
179
+ currencySign: "accounting"
180
+ };
181
+ case "sign-never":
182
+ case "+_": return { signDisplay: "never" };
183
+ }
184
+ }
185
+ function parseConciseScientificAndEngineeringStem(stem) {
186
+ let result;
187
+ if (stem[0] === "E" && stem[1] === "E") {
188
+ result = { notation: "engineering" };
189
+ stem = stem.slice(2);
190
+ } else if (stem[0] === "E") {
191
+ result = { notation: "scientific" };
192
+ stem = stem.slice(1);
193
+ }
194
+ if (result) {
195
+ const signDisplay = stem.slice(0, 2);
196
+ if (signDisplay === "+!") {
197
+ result.signDisplay = "always";
198
+ stem = stem.slice(2);
199
+ } else if (signDisplay === "+?") {
200
+ result.signDisplay = "exceptZero";
201
+ stem = stem.slice(2);
202
+ }
203
+ if (!CONCISE_INTEGER_WIDTH_REGEX.test(stem)) throw new Error("Malformed concise eng/scientific notation");
204
+ result.minimumIntegerDigits = stem.length;
205
+ }
206
+ return result;
207
+ }
208
+ function parseNotationOptions(opt) {
209
+ const result = {};
210
+ const signOpts = parseSign(opt);
211
+ if (signOpts) return signOpts;
212
+ return result;
213
+ }
214
+ /**
215
+ * https://github.com/unicode-org/icu/blob/master/docs/userguide/format_parse/numbers/skeletons.md#skeleton-stems-and-options
216
+ */
217
+ function parseNumberSkeleton(tokens) {
218
+ let result = {};
219
+ for (const token of tokens) {
220
+ switch (token.stem) {
221
+ case "percent":
222
+ case "%":
223
+ result.style = "percent";
224
+ continue;
225
+ case "%x100":
226
+ result.style = "percent";
227
+ result.scale = 100;
228
+ continue;
229
+ case "currency":
230
+ result.style = "currency";
231
+ result.currency = token.options[0];
232
+ continue;
233
+ case "group-off":
234
+ case ",_":
235
+ result.useGrouping = false;
236
+ continue;
237
+ case "precision-integer":
238
+ case ".":
239
+ result.maximumFractionDigits = 0;
240
+ continue;
241
+ case "measure-unit":
242
+ case "unit":
243
+ result.style = "unit";
244
+ result.unit = icuUnitToEcma(token.options[0]);
245
+ continue;
246
+ case "compact-short":
247
+ case "K":
248
+ result.notation = "compact";
249
+ result.compactDisplay = "short";
250
+ continue;
251
+ case "compact-long":
252
+ case "KK":
253
+ result.notation = "compact";
254
+ result.compactDisplay = "long";
255
+ continue;
256
+ case "scientific":
257
+ result = {
258
+ ...result,
259
+ notation: "scientific",
260
+ ...token.options.reduce((all, opt) => ({
261
+ ...all,
262
+ ...parseNotationOptions(opt)
263
+ }), {})
264
+ };
265
+ continue;
266
+ case "engineering":
267
+ result = {
268
+ ...result,
269
+ notation: "engineering",
270
+ ...token.options.reduce((all, opt) => ({
271
+ ...all,
272
+ ...parseNotationOptions(opt)
273
+ }), {})
274
+ };
275
+ continue;
276
+ case "notation-simple":
277
+ result.notation = "standard";
278
+ continue;
279
+ case "unit-width-narrow":
280
+ result.currencyDisplay = "narrowSymbol";
281
+ result.unitDisplay = "narrow";
282
+ continue;
283
+ case "unit-width-short":
284
+ result.currencyDisplay = "code";
285
+ result.unitDisplay = "short";
286
+ continue;
287
+ case "unit-width-full-name":
288
+ result.currencyDisplay = "name";
289
+ result.unitDisplay = "long";
290
+ continue;
291
+ case "unit-width-iso-code":
292
+ result.currencyDisplay = "symbol";
293
+ continue;
294
+ case "scale":
295
+ result.scale = parseFloat(token.options[0]);
296
+ continue;
297
+ case "rounding-mode-floor":
298
+ result.roundingMode = "floor";
299
+ continue;
300
+ case "rounding-mode-ceiling":
301
+ result.roundingMode = "ceil";
302
+ continue;
303
+ case "rounding-mode-down":
304
+ result.roundingMode = "trunc";
305
+ continue;
306
+ case "rounding-mode-up":
307
+ result.roundingMode = "expand";
308
+ continue;
309
+ case "rounding-mode-half-even":
310
+ result.roundingMode = "halfEven";
311
+ continue;
312
+ case "rounding-mode-half-down":
313
+ result.roundingMode = "halfTrunc";
314
+ continue;
315
+ case "rounding-mode-half-up":
316
+ result.roundingMode = "halfExpand";
317
+ continue;
318
+ case "integer-width":
319
+ if (token.options.length > 1) throw new RangeError("integer-width stems only accept a single optional option");
320
+ token.options[0].replace(INTEGER_WIDTH_REGEX, function(_, g1, g2, g3, g4, g5) {
321
+ if (g1) result.minimumIntegerDigits = g2.length;
322
+ else if (g3 && g4) throw new Error("We currently do not support maximum integer digits");
323
+ else if (g5) throw new Error("We currently do not support exact integer digits");
324
+ return "";
325
+ });
326
+ continue;
327
+ }
328
+ if (CONCISE_INTEGER_WIDTH_REGEX.test(token.stem)) {
329
+ result.minimumIntegerDigits = token.stem.length;
330
+ continue;
331
+ }
332
+ if (FRACTION_PRECISION_REGEX.test(token.stem)) {
333
+ if (token.options.length > 1) throw new RangeError("Fraction-precision stems only accept a single optional option");
334
+ token.stem.replace(FRACTION_PRECISION_REGEX, function(_, g1, g2, g3, g4, g5) {
335
+ if (g2 === "*") result.minimumFractionDigits = g1.length;
336
+ else if (g3 && g3[0] === "#") result.maximumFractionDigits = g3.length;
337
+ else if (g4 && g5) {
338
+ result.minimumFractionDigits = g4.length;
339
+ result.maximumFractionDigits = g4.length + g5.length;
340
+ } else {
341
+ result.minimumFractionDigits = g1.length;
342
+ result.maximumFractionDigits = g1.length;
343
+ }
344
+ return "";
345
+ });
346
+ const opt = token.options[0];
347
+ if (opt === "w") result = {
348
+ ...result,
349
+ trailingZeroDisplay: "stripIfInteger"
350
+ };
351
+ else if (opt) result = {
352
+ ...result,
353
+ ...parseSignificantPrecision(opt)
354
+ };
355
+ continue;
356
+ }
357
+ if (SIGNIFICANT_PRECISION_REGEX.test(token.stem)) {
358
+ result = {
359
+ ...result,
360
+ ...parseSignificantPrecision(token.stem)
361
+ };
362
+ continue;
363
+ }
364
+ const signOpts = parseSign(token.stem);
365
+ if (signOpts) result = {
366
+ ...result,
367
+ ...signOpts
368
+ };
369
+ const conciseScientificAndEngineeringOpts = parseConciseScientificAndEngineeringStem(token.stem);
370
+ if (conciseScientificAndEngineeringOpts) result = {
371
+ ...result,
372
+ ...conciseScientificAndEngineeringOpts
373
+ };
374
+ }
375
+ return result;
376
+ }
377
+ //#endregion
378
+ export { parseDateTimeSkeleton, parseNumberSkeleton, parseNumberSkeletonFromString };
379
+
380
+ //# sourceMappingURL=index.js.map
package/index.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../date-time.ts","../regex.generated.ts","../number.ts"],"sourcesContent":["/**\n * https://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table\n * Credit: https://github.com/caridy/intl-datetimeformat-pattern/blob/master/index.js\n * with some tweaks\n */\nconst DATE_TIME_REGEX =\n /(?:[Eec]{1,6}|G{1,5}|[Qq]{1,5}|(?:[yYur]+|U{1,5})|[ML]{1,5}|d{1,2}|D{1,3}|F{1}|[abB]{1,5}|[hkHK]{1,2}|w{1,2}|W{1}|m{1,2}|s{1,2}|[zZOvVxX]{1,4})(?=([^']*'[^']*')*[^']*$)/g\n\n/**\n * Parse Date time skeleton into Intl.DateTimeFormatOptions\n * Ref: https://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table\n * @public\n * @param skeleton skeleton string\n */\nexport function parseDateTimeSkeleton(\n skeleton: string\n): Intl.DateTimeFormatOptions {\n const result: Intl.DateTimeFormatOptions = {}\n skeleton.replace(DATE_TIME_REGEX, match => {\n const len = match.length\n switch (match[0]) {\n // Era\n case 'G':\n result.era = len === 4 ? 'long' : len === 5 ? 'narrow' : 'short'\n break\n // Year\n case 'y':\n result.year = len === 2 ? '2-digit' : 'numeric'\n break\n case 'Y':\n case 'u':\n case 'U':\n case 'r':\n throw new RangeError(\n '`Y/u/U/r` (year) patterns are not supported, use `y` instead'\n )\n // Quarter\n case 'q':\n case 'Q':\n throw new RangeError('`q/Q` (quarter) patterns are not supported')\n // Month\n case 'M':\n case 'L':\n result.month = ['numeric', '2-digit', 'short', 'long', 'narrow'][\n len - 1\n ] as 'numeric'\n break\n // Week\n case 'w':\n case 'W':\n throw new RangeError('`w/W` (week) patterns are not supported')\n case 'd':\n result.day = ['numeric', '2-digit'][len - 1] as 'numeric'\n break\n case 'D':\n case 'F':\n case 'g':\n throw new RangeError(\n '`D/F/g` (day) patterns are not supported, use `d` instead'\n )\n // Weekday\n case 'E':\n result.weekday = len === 4 ? 'long' : len === 5 ? 'narrow' : 'short'\n break\n case 'e':\n if (len < 4) {\n throw new RangeError('`e..eee` (weekday) patterns are not supported')\n }\n result.weekday = ['short', 'long', 'narrow', 'short'][\n len - 4\n ] as 'short'\n break\n case 'c':\n if (len < 4) {\n throw new RangeError('`c..ccc` (weekday) patterns are not supported')\n }\n result.weekday = ['short', 'long', 'narrow', 'short'][\n len - 4\n ] as 'short'\n break\n\n // Period\n case 'a': // AM, PM\n result.hour12 = true\n break\n case 'b': // am, pm, noon, midnight\n case 'B': // flexible day periods\n throw new RangeError(\n '`b/B` (period) patterns are not supported, use `a` instead'\n )\n // Hour\n case 'h':\n result.hourCycle = 'h12'\n result.hour = ['numeric', '2-digit'][len - 1] as 'numeric'\n break\n case 'H':\n result.hourCycle = 'h23'\n result.hour = ['numeric', '2-digit'][len - 1] as 'numeric'\n break\n case 'K':\n result.hourCycle = 'h11'\n result.hour = ['numeric', '2-digit'][len - 1] as 'numeric'\n break\n case 'k':\n result.hourCycle = 'h24'\n result.hour = ['numeric', '2-digit'][len - 1] as 'numeric'\n break\n case 'j':\n case 'J':\n case 'C':\n throw new RangeError(\n '`j/J/C` (hour) patterns are not supported, use `h/H/K/k` instead'\n )\n // Minute\n case 'm':\n result.minute = ['numeric', '2-digit'][len - 1] as 'numeric'\n break\n // Second\n case 's':\n result.second = ['numeric', '2-digit'][len - 1] as 'numeric'\n break\n case 'S':\n case 'A':\n throw new RangeError(\n '`S/A` (second) patterns are not supported, use `s` instead'\n )\n // Zone\n case 'z': // 1..3, 4: specific non-location format\n result.timeZoneName = len < 4 ? 'short' : 'long'\n break\n case 'Z': // 1..3, 4, 5: The ISO8601 varios formats\n case 'O': // 1, 4: milliseconds in day short, long\n case 'v': // 1, 4: generic non-location format\n case 'V': // 1, 2, 3, 4: time zone ID or city\n case 'X': // 1, 2, 3, 4: The ISO8601 varios formats\n case 'x': // 1, 2, 3, 4: The ISO8601 varios formats\n throw new RangeError(\n '`Z/O/v/V/X/x` (timeZone) patterns are not supported, use `z` instead'\n )\n }\n return ''\n })\n return result\n}\n","// @generated from regex-gen.ts\nexport const WHITE_SPACE_REGEX: RegExp = /[\\t-\\r \\x85\\u200E\\u200F\\u2028\\u2029]/i\n","import type {NumberFormatOptions} from '#packages/ecma402-abstract/types/number.js'\nimport {WHITE_SPACE_REGEX} from '#packages/icu-skeleton-parser/regex.generated.js'\n\nexport interface ExtendedNumberFormatOptions extends NumberFormatOptions {\n scale?: number\n}\nexport interface NumberSkeletonToken {\n stem: string\n options: string[]\n}\n\nexport function parseNumberSkeletonFromString(\n skeleton: string\n): NumberSkeletonToken[] {\n if (skeleton.length === 0) {\n throw new Error('Number skeleton cannot be empty')\n }\n // Parse the skeleton\n const stringTokens = skeleton\n .split(WHITE_SPACE_REGEX)\n .filter(x => x.length > 0)\n\n const tokens: NumberSkeletonToken[] = []\n for (const stringToken of stringTokens) {\n let stemAndOptions = stringToken.split('/')\n if (stemAndOptions.length === 0) {\n throw new Error('Invalid number skeleton')\n }\n\n const [stem, ...options] = stemAndOptions\n for (const option of options) {\n if (option.length === 0) {\n throw new Error('Invalid number skeleton')\n }\n }\n\n tokens.push({stem, options})\n }\n return tokens\n}\n\nfunction icuUnitToEcma(unit: string): ExtendedNumberFormatOptions['unit'] {\n return unit.replace(/^(.*?)-/, '') as ExtendedNumberFormatOptions['unit']\n}\n\nconst FRACTION_PRECISION_REGEX = /^\\.(?:(0+)(\\*)?|(#+)|(0+)(#+))$/g\nconst SIGNIFICANT_PRECISION_REGEX = /^(@+)?(\\+|#+)?[rs]?$/g\nconst INTEGER_WIDTH_REGEX = /(\\*)(0+)|(#+)(0+)|(0+)/g\nconst CONCISE_INTEGER_WIDTH_REGEX = /^(0+)$/\n\nfunction parseSignificantPrecision(str: string): ExtendedNumberFormatOptions {\n const result: ExtendedNumberFormatOptions = {}\n if (str[str.length - 1] === 'r') {\n result.roundingPriority = 'morePrecision'\n } else if (str[str.length - 1] === 's') {\n result.roundingPriority = 'lessPrecision'\n }\n str.replace(\n SIGNIFICANT_PRECISION_REGEX,\n function (_: string, g1: string, g2: string | number) {\n // @@@ case\n if (typeof g2 !== 'string') {\n result.minimumSignificantDigits = g1.length\n result.maximumSignificantDigits = g1.length\n }\n // @@@+ case\n else if (g2 === '+') {\n result.minimumSignificantDigits = g1.length\n }\n // .### case\n else if (g1[0] === '#') {\n result.maximumSignificantDigits = g1.length\n }\n // .@@## or .@@@ case\n else {\n result.minimumSignificantDigits = g1.length\n result.maximumSignificantDigits =\n g1.length + (typeof g2 === 'string' ? g2.length : 0)\n }\n return ''\n }\n )\n return result\n}\n\nfunction parseSign(str: string): ExtendedNumberFormatOptions | undefined {\n switch (str) {\n case 'sign-auto':\n return {\n signDisplay: 'auto',\n }\n case 'sign-accounting':\n case '()':\n return {\n currencySign: 'accounting',\n }\n case 'sign-always':\n case '+!':\n return {\n signDisplay: 'always',\n }\n case 'sign-accounting-always':\n case '()!':\n return {\n signDisplay: 'always',\n currencySign: 'accounting',\n }\n case 'sign-except-zero':\n case '+?':\n return {\n signDisplay: 'exceptZero',\n }\n case 'sign-accounting-except-zero':\n case '()?':\n return {\n signDisplay: 'exceptZero',\n currencySign: 'accounting',\n }\n case 'sign-never':\n case '+_':\n return {\n signDisplay: 'never',\n }\n }\n}\n\nfunction parseConciseScientificAndEngineeringStem(\n stem: string\n): ExtendedNumberFormatOptions | undefined {\n // Engineering\n let result: ExtendedNumberFormatOptions | undefined\n if (stem[0] === 'E' && stem[1] === 'E') {\n result = {\n notation: 'engineering',\n }\n stem = stem.slice(2)\n } else if (stem[0] === 'E') {\n result = {\n notation: 'scientific',\n }\n stem = stem.slice(1)\n }\n if (result) {\n const signDisplay = stem.slice(0, 2)\n if (signDisplay === '+!') {\n result.signDisplay = 'always'\n stem = stem.slice(2)\n } else if (signDisplay === '+?') {\n result.signDisplay = 'exceptZero'\n stem = stem.slice(2)\n }\n if (!CONCISE_INTEGER_WIDTH_REGEX.test(stem)) {\n throw new Error('Malformed concise eng/scientific notation')\n }\n result.minimumIntegerDigits = stem.length\n }\n return result\n}\n\nfunction parseNotationOptions(opt: string): ExtendedNumberFormatOptions {\n const result: ExtendedNumberFormatOptions = {}\n const signOpts = parseSign(opt)\n if (signOpts) {\n return signOpts\n }\n return result\n}\n\n/**\n * https://github.com/unicode-org/icu/blob/master/docs/userguide/format_parse/numbers/skeletons.md#skeleton-stems-and-options\n */\nexport function parseNumberSkeleton(\n tokens: NumberSkeletonToken[]\n): ExtendedNumberFormatOptions {\n let result: ExtendedNumberFormatOptions = {}\n for (const token of tokens) {\n switch (token.stem) {\n case 'percent':\n case '%':\n result.style = 'percent'\n continue\n case '%x100':\n result.style = 'percent'\n result.scale = 100\n continue\n case 'currency':\n result.style = 'currency'\n result.currency = token.options[0]\n continue\n case 'group-off':\n case ',_':\n result.useGrouping = false\n continue\n case 'precision-integer':\n case '.':\n result.maximumFractionDigits = 0\n continue\n case 'measure-unit':\n case 'unit':\n result.style = 'unit'\n result.unit = icuUnitToEcma(token.options[0])\n continue\n case 'compact-short':\n case 'K':\n result.notation = 'compact'\n result.compactDisplay = 'short'\n continue\n case 'compact-long':\n case 'KK':\n result.notation = 'compact'\n result.compactDisplay = 'long'\n continue\n case 'scientific':\n result = {\n ...result,\n notation: 'scientific',\n ...token.options.reduce(\n (all, opt) => ({...all, ...parseNotationOptions(opt)}),\n {}\n ),\n }\n continue\n case 'engineering':\n result = {\n ...result,\n notation: 'engineering',\n ...token.options.reduce(\n (all, opt) => ({...all, ...parseNotationOptions(opt)}),\n {}\n ),\n }\n continue\n case 'notation-simple':\n result.notation = 'standard'\n continue\n // https://github.com/unicode-org/icu/blob/master/icu4c/source/i18n/unicode/unumberformatter.h\n case 'unit-width-narrow':\n result.currencyDisplay = 'narrowSymbol'\n result.unitDisplay = 'narrow'\n continue\n case 'unit-width-short':\n result.currencyDisplay = 'code'\n result.unitDisplay = 'short'\n continue\n case 'unit-width-full-name':\n result.currencyDisplay = 'name'\n result.unitDisplay = 'long'\n continue\n case 'unit-width-iso-code':\n result.currencyDisplay = 'symbol'\n continue\n case 'scale':\n result.scale = parseFloat(token.options[0])\n continue\n case 'rounding-mode-floor':\n result.roundingMode = 'floor'\n continue\n case 'rounding-mode-ceiling':\n result.roundingMode = 'ceil'\n continue\n case 'rounding-mode-down':\n result.roundingMode = 'trunc'\n continue\n case 'rounding-mode-up':\n result.roundingMode = 'expand'\n continue\n case 'rounding-mode-half-even':\n result.roundingMode = 'halfEven'\n continue\n case 'rounding-mode-half-down':\n result.roundingMode = 'halfTrunc'\n continue\n case 'rounding-mode-half-up':\n result.roundingMode = 'halfExpand'\n continue\n // https://unicode-org.github.io/icu/userguide/format_parse/numbers/skeletons.html#integer-width\n case 'integer-width':\n if (token.options.length > 1) {\n throw new RangeError(\n 'integer-width stems only accept a single optional option'\n )\n }\n token.options[0].replace(\n INTEGER_WIDTH_REGEX,\n function (\n _: string,\n g1: string,\n g2: string,\n g3: string,\n g4: string,\n g5: string\n ) {\n if (g1) {\n result.minimumIntegerDigits = g2.length\n } else if (g3 && g4) {\n throw new Error(\n 'We currently do not support maximum integer digits'\n )\n } else if (g5) {\n throw new Error(\n 'We currently do not support exact integer digits'\n )\n }\n return ''\n }\n )\n continue\n }\n // https://unicode-org.github.io/icu/userguide/format_parse/numbers/skeletons.html#integer-width\n if (CONCISE_INTEGER_WIDTH_REGEX.test(token.stem)) {\n result.minimumIntegerDigits = token.stem.length\n continue\n }\n if (FRACTION_PRECISION_REGEX.test(token.stem)) {\n // Precision\n // https://unicode-org.github.io/icu/userguide/format_parse/numbers/skeletons.html#fraction-precision\n // precision-integer case\n if (token.options.length > 1) {\n throw new RangeError(\n 'Fraction-precision stems only accept a single optional option'\n )\n }\n token.stem.replace(\n FRACTION_PRECISION_REGEX,\n function (\n _: string,\n g1: string,\n g2: string | number,\n g3: string,\n g4: string,\n g5: string\n ) {\n // .000* case (before ICU67 it was .000+)\n if (g2 === '*') {\n result.minimumFractionDigits = g1.length\n }\n // .### case\n else if (g3 && g3[0] === '#') {\n result.maximumFractionDigits = g3.length\n }\n // .00## case\n else if (g4 && g5) {\n result.minimumFractionDigits = g4.length\n result.maximumFractionDigits = g4.length + g5.length\n } else {\n result.minimumFractionDigits = g1.length\n result.maximumFractionDigits = g1.length\n }\n return ''\n }\n )\n\n const opt = token.options[0]\n // https://unicode-org.github.io/icu/userguide/format_parse/numbers/skeletons.html#trailing-zero-display\n if (opt === 'w') {\n result = {...result, trailingZeroDisplay: 'stripIfInteger'}\n } else if (opt) {\n result = {...result, ...parseSignificantPrecision(opt)}\n }\n continue\n }\n // https://unicode-org.github.io/icu/userguide/format_parse/numbers/skeletons.html#significant-digits-precision\n if (SIGNIFICANT_PRECISION_REGEX.test(token.stem)) {\n result = {...result, ...parseSignificantPrecision(token.stem)}\n continue\n }\n const signOpts = parseSign(token.stem)\n if (signOpts) {\n result = {...result, ...signOpts}\n }\n const conciseScientificAndEngineeringOpts =\n parseConciseScientificAndEngineeringStem(token.stem)\n if (conciseScientificAndEngineeringOpts) {\n result = {...result, ...conciseScientificAndEngineeringOpts}\n }\n }\n return result\n}\n"],"mappings":";;;;;;AAKA,MAAM,kBACJ;;;;;;;AAQF,SAAgB,sBACd,UAC4B;CAC5B,MAAM,SAAqC,EAAE;AAC7C,UAAS,QAAQ,kBAAiB,UAAS;EACzC,MAAM,MAAM,MAAM;AAClB,UAAQ,MAAM,IAAd;GAEE,KAAK;AACH,WAAO,MAAM,QAAQ,IAAI,SAAS,QAAQ,IAAI,WAAW;AACzD;GAEF,KAAK;AACH,WAAO,OAAO,QAAQ,IAAI,YAAY;AACtC;GACF,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK,IACH,OAAM,IAAI,WACR,+DACD;GAEH,KAAK;GACL,KAAK,IACH,OAAM,IAAI,WAAW,6CAA6C;GAEpE,KAAK;GACL,KAAK;AACH,WAAO,QAAQ;KAAC;KAAW;KAAW;KAAS;KAAQ;KAAS,CAC9D,MAAM;AAER;GAEF,KAAK;GACL,KAAK,IACH,OAAM,IAAI,WAAW,0CAA0C;GACjE,KAAK;AACH,WAAO,MAAM,CAAC,WAAW,UAAU,CAAC,MAAM;AAC1C;GACF,KAAK;GACL,KAAK;GACL,KAAK,IACH,OAAM,IAAI,WACR,4DACD;GAEH,KAAK;AACH,WAAO,UAAU,QAAQ,IAAI,SAAS,QAAQ,IAAI,WAAW;AAC7D;GACF,KAAK;AACH,QAAI,MAAM,EACR,OAAM,IAAI,WAAW,gDAAgD;AAEvE,WAAO,UAAU;KAAC;KAAS;KAAQ;KAAU;KAAQ,CACnD,MAAM;AAER;GACF,KAAK;AACH,QAAI,MAAM,EACR,OAAM,IAAI,WAAW,gDAAgD;AAEvE,WAAO,UAAU;KAAC;KAAS;KAAQ;KAAU;KAAQ,CACnD,MAAM;AAER;GAGF,KAAK;AACH,WAAO,SAAS;AAChB;GACF,KAAK;GACL,KAAK,IACH,OAAM,IAAI,WACR,6DACD;GAEH,KAAK;AACH,WAAO,YAAY;AACnB,WAAO,OAAO,CAAC,WAAW,UAAU,CAAC,MAAM;AAC3C;GACF,KAAK;AACH,WAAO,YAAY;AACnB,WAAO,OAAO,CAAC,WAAW,UAAU,CAAC,MAAM;AAC3C;GACF,KAAK;AACH,WAAO,YAAY;AACnB,WAAO,OAAO,CAAC,WAAW,UAAU,CAAC,MAAM;AAC3C;GACF,KAAK;AACH,WAAO,YAAY;AACnB,WAAO,OAAO,CAAC,WAAW,UAAU,CAAC,MAAM;AAC3C;GACF,KAAK;GACL,KAAK;GACL,KAAK,IACH,OAAM,IAAI,WACR,mEACD;GAEH,KAAK;AACH,WAAO,SAAS,CAAC,WAAW,UAAU,CAAC,MAAM;AAC7C;GAEF,KAAK;AACH,WAAO,SAAS,CAAC,WAAW,UAAU,CAAC,MAAM;AAC7C;GACF,KAAK;GACL,KAAK,IACH,OAAM,IAAI,WACR,6DACD;GAEH,KAAK;AACH,WAAO,eAAe,MAAM,IAAI,UAAU;AAC1C;GACF,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK,IACH,OAAM,IAAI,WACR,uEACD;;AAEL,SAAO;GACP;AACF,QAAO;;;;AC7IT,MAAa,oBAA4B;;;ACUzC,SAAgB,8BACd,UACuB;AACvB,KAAI,SAAS,WAAW,EACtB,OAAM,IAAI,MAAM,kCAAkC;CAGpD,MAAM,eAAe,SAClB,MAAM,kBAAkB,CACxB,QAAO,MAAK,EAAE,SAAS,EAAE;CAE5B,MAAM,SAAgC,EAAE;AACxC,MAAK,MAAM,eAAe,cAAc;EACtC,IAAI,iBAAiB,YAAY,MAAM,IAAI;AAC3C,MAAI,eAAe,WAAW,EAC5B,OAAM,IAAI,MAAM,0BAA0B;EAG5C,MAAM,CAAC,MAAM,GAAG,WAAW;AAC3B,OAAK,MAAM,UAAU,QACnB,KAAI,OAAO,WAAW,EACpB,OAAM,IAAI,MAAM,0BAA0B;AAI9C,SAAO,KAAK;GAAC;GAAM;GAAQ,CAAC;;AAE9B,QAAO;;AAGT,SAAS,cAAc,MAAmD;AACxE,QAAO,KAAK,QAAQ,WAAW,GAAG;;AAGpC,MAAM,2BAA2B;AACjC,MAAM,8BAA8B;AACpC,MAAM,sBAAsB;AAC5B,MAAM,8BAA8B;AAEpC,SAAS,0BAA0B,KAA0C;CAC3E,MAAM,SAAsC,EAAE;AAC9C,KAAI,IAAI,IAAI,SAAS,OAAO,IAC1B,QAAO,mBAAmB;UACjB,IAAI,IAAI,SAAS,OAAO,IACjC,QAAO,mBAAmB;AAE5B,KAAI,QACF,6BACA,SAAU,GAAW,IAAY,IAAqB;AAEpD,MAAI,OAAO,OAAO,UAAU;AAC1B,UAAO,2BAA2B,GAAG;AACrC,UAAO,2BAA2B,GAAG;aAG9B,OAAO,IACd,QAAO,2BAA2B,GAAG;WAG9B,GAAG,OAAO,IACjB,QAAO,2BAA2B,GAAG;OAGlC;AACH,UAAO,2BAA2B,GAAG;AACrC,UAAO,2BACL,GAAG,UAAU,OAAO,OAAO,WAAW,GAAG,SAAS;;AAEtD,SAAO;GAEV;AACD,QAAO;;AAGT,SAAS,UAAU,KAAsD;AACvE,SAAQ,KAAR;EACE,KAAK,YACH,QAAO,EACL,aAAa,QACd;EACH,KAAK;EACL,KAAK,KACH,QAAO,EACL,cAAc,cACf;EACH,KAAK;EACL,KAAK,KACH,QAAO,EACL,aAAa,UACd;EACH,KAAK;EACL,KAAK,MACH,QAAO;GACL,aAAa;GACb,cAAc;GACf;EACH,KAAK;EACL,KAAK,KACH,QAAO,EACL,aAAa,cACd;EACH,KAAK;EACL,KAAK,MACH,QAAO;GACL,aAAa;GACb,cAAc;GACf;EACH,KAAK;EACL,KAAK,KACH,QAAO,EACL,aAAa,SACd;;;AAIP,SAAS,yCACP,MACyC;CAEzC,IAAI;AACJ,KAAI,KAAK,OAAO,OAAO,KAAK,OAAO,KAAK;AACtC,WAAS,EACP,UAAU,eACX;AACD,SAAO,KAAK,MAAM,EAAE;YACX,KAAK,OAAO,KAAK;AAC1B,WAAS,EACP,UAAU,cACX;AACD,SAAO,KAAK,MAAM,EAAE;;AAEtB,KAAI,QAAQ;EACV,MAAM,cAAc,KAAK,MAAM,GAAG,EAAE;AACpC,MAAI,gBAAgB,MAAM;AACxB,UAAO,cAAc;AACrB,UAAO,KAAK,MAAM,EAAE;aACX,gBAAgB,MAAM;AAC/B,UAAO,cAAc;AACrB,UAAO,KAAK,MAAM,EAAE;;AAEtB,MAAI,CAAC,4BAA4B,KAAK,KAAK,CACzC,OAAM,IAAI,MAAM,4CAA4C;AAE9D,SAAO,uBAAuB,KAAK;;AAErC,QAAO;;AAGT,SAAS,qBAAqB,KAA0C;CACtE,MAAM,SAAsC,EAAE;CAC9C,MAAM,WAAW,UAAU,IAAI;AAC/B,KAAI,SACF,QAAO;AAET,QAAO;;;;;AAMT,SAAgB,oBACd,QAC6B;CAC7B,IAAI,SAAsC,EAAE;AAC5C,MAAK,MAAM,SAAS,QAAQ;AAC1B,UAAQ,MAAM,MAAd;GACE,KAAK;GACL,KAAK;AACH,WAAO,QAAQ;AACf;GACF,KAAK;AACH,WAAO,QAAQ;AACf,WAAO,QAAQ;AACf;GACF,KAAK;AACH,WAAO,QAAQ;AACf,WAAO,WAAW,MAAM,QAAQ;AAChC;GACF,KAAK;GACL,KAAK;AACH,WAAO,cAAc;AACrB;GACF,KAAK;GACL,KAAK;AACH,WAAO,wBAAwB;AAC/B;GACF,KAAK;GACL,KAAK;AACH,WAAO,QAAQ;AACf,WAAO,OAAO,cAAc,MAAM,QAAQ,GAAG;AAC7C;GACF,KAAK;GACL,KAAK;AACH,WAAO,WAAW;AAClB,WAAO,iBAAiB;AACxB;GACF,KAAK;GACL,KAAK;AACH,WAAO,WAAW;AAClB,WAAO,iBAAiB;AACxB;GACF,KAAK;AACH,aAAS;KACP,GAAG;KACH,UAAU;KACV,GAAG,MAAM,QAAQ,QACd,KAAK,SAAS;MAAC,GAAG;MAAK,GAAG,qBAAqB,IAAI;MAAC,GACrD,EAAE,CACH;KACF;AACD;GACF,KAAK;AACH,aAAS;KACP,GAAG;KACH,UAAU;KACV,GAAG,MAAM,QAAQ,QACd,KAAK,SAAS;MAAC,GAAG;MAAK,GAAG,qBAAqB,IAAI;MAAC,GACrD,EAAE,CACH;KACF;AACD;GACF,KAAK;AACH,WAAO,WAAW;AAClB;GAEF,KAAK;AACH,WAAO,kBAAkB;AACzB,WAAO,cAAc;AACrB;GACF,KAAK;AACH,WAAO,kBAAkB;AACzB,WAAO,cAAc;AACrB;GACF,KAAK;AACH,WAAO,kBAAkB;AACzB,WAAO,cAAc;AACrB;GACF,KAAK;AACH,WAAO,kBAAkB;AACzB;GACF,KAAK;AACH,WAAO,QAAQ,WAAW,MAAM,QAAQ,GAAG;AAC3C;GACF,KAAK;AACH,WAAO,eAAe;AACtB;GACF,KAAK;AACH,WAAO,eAAe;AACtB;GACF,KAAK;AACH,WAAO,eAAe;AACtB;GACF,KAAK;AACH,WAAO,eAAe;AACtB;GACF,KAAK;AACH,WAAO,eAAe;AACtB;GACF,KAAK;AACH,WAAO,eAAe;AACtB;GACF,KAAK;AACH,WAAO,eAAe;AACtB;GAEF,KAAK;AACH,QAAI,MAAM,QAAQ,SAAS,EACzB,OAAM,IAAI,WACR,2DACD;AAEH,UAAM,QAAQ,GAAG,QACf,qBACA,SACE,GACA,IACA,IACA,IACA,IACA,IACA;AACA,SAAI,GACF,QAAO,uBAAuB,GAAG;cACxB,MAAM,GACf,OAAM,IAAI,MACR,qDACD;cACQ,GACT,OAAM,IAAI,MACR,mDACD;AAEH,YAAO;MAEV;AACD;;AAGJ,MAAI,4BAA4B,KAAK,MAAM,KAAK,EAAE;AAChD,UAAO,uBAAuB,MAAM,KAAK;AACzC;;AAEF,MAAI,yBAAyB,KAAK,MAAM,KAAK,EAAE;AAI7C,OAAI,MAAM,QAAQ,SAAS,EACzB,OAAM,IAAI,WACR,gEACD;AAEH,SAAM,KAAK,QACT,0BACA,SACE,GACA,IACA,IACA,IACA,IACA,IACA;AAEA,QAAI,OAAO,IACT,QAAO,wBAAwB,GAAG;aAG3B,MAAM,GAAG,OAAO,IACvB,QAAO,wBAAwB,GAAG;aAG3B,MAAM,IAAI;AACjB,YAAO,wBAAwB,GAAG;AAClC,YAAO,wBAAwB,GAAG,SAAS,GAAG;WACzC;AACL,YAAO,wBAAwB,GAAG;AAClC,YAAO,wBAAwB,GAAG;;AAEpC,WAAO;KAEV;GAED,MAAM,MAAM,MAAM,QAAQ;AAE1B,OAAI,QAAQ,IACV,UAAS;IAAC,GAAG;IAAQ,qBAAqB;IAAiB;YAClD,IACT,UAAS;IAAC,GAAG;IAAQ,GAAG,0BAA0B,IAAI;IAAC;AAEzD;;AAGF,MAAI,4BAA4B,KAAK,MAAM,KAAK,EAAE;AAChD,YAAS;IAAC,GAAG;IAAQ,GAAG,0BAA0B,MAAM,KAAK;IAAC;AAC9D;;EAEF,MAAM,WAAW,UAAU,MAAM,KAAK;AACtC,MAAI,SACF,UAAS;GAAC,GAAG;GAAQ,GAAG;GAAS;EAEnC,MAAM,sCACJ,yCAAyC,MAAM,KAAK;AACtD,MAAI,oCACF,UAAS;GAAC,GAAG;GAAQ,GAAG;GAAoC;;AAGhE,QAAO"}
package/package.json CHANGED
@@ -1,15 +1,13 @@
1
1
  {
2
2
  "name": "@formatjs/icu-skeleton-parser",
3
- "version": "2.1.2",
3
+ "version": "2.1.4",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "types": "index.d.ts",
7
7
  "exports": {
8
8
  ".": "./index.js"
9
9
  },
10
- "dependencies": {
11
- "@formatjs/ecma402-abstract": "3.1.2"
12
- },
10
+ "dependencies": {},
13
11
  "repository": {
14
12
  "type": "git",
15
13
  "url": "https://github.com/formatjs/formatjs.git",
package/date-time.d.ts DELETED
@@ -1,7 +0,0 @@
1
- /**
2
- * Parse Date time skeleton into Intl.DateTimeFormatOptions
3
- * Ref: https://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
4
- * @public
5
- * @param skeleton skeleton string
6
- */
7
- export declare function parseDateTimeSkeleton(skeleton: string): Intl.DateTimeFormatOptions;
package/date-time.js DELETED
@@ -1,118 +0,0 @@
1
- /**
2
- * https://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
3
- * Credit: https://github.com/caridy/intl-datetimeformat-pattern/blob/master/index.js
4
- * with some tweaks
5
- */
6
- const DATE_TIME_REGEX = /(?:[Eec]{1,6}|G{1,5}|[Qq]{1,5}|(?:[yYur]+|U{1,5})|[ML]{1,5}|d{1,2}|D{1,3}|F{1}|[abB]{1,5}|[hkHK]{1,2}|w{1,2}|W{1}|m{1,2}|s{1,2}|[zZOvVxX]{1,4})(?=([^']*'[^']*')*[^']*$)/g;
7
- /**
8
- * Parse Date time skeleton into Intl.DateTimeFormatOptions
9
- * Ref: https://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
10
- * @public
11
- * @param skeleton skeleton string
12
- */
13
- export function parseDateTimeSkeleton(skeleton) {
14
- const result = {};
15
- skeleton.replace(DATE_TIME_REGEX, (match) => {
16
- const len = match.length;
17
- switch (match[0]) {
18
- case "G":
19
- result.era = len === 4 ? "long" : len === 5 ? "narrow" : "short";
20
- break;
21
- case "y":
22
- result.year = len === 2 ? "2-digit" : "numeric";
23
- break;
24
- case "Y":
25
- case "u":
26
- case "U":
27
- case "r": throw new RangeError("`Y/u/U/r` (year) patterns are not supported, use `y` instead");
28
- case "q":
29
- case "Q": throw new RangeError("`q/Q` (quarter) patterns are not supported");
30
- case "M":
31
- case "L":
32
- result.month = [
33
- "numeric",
34
- "2-digit",
35
- "short",
36
- "long",
37
- "narrow"
38
- ][len - 1];
39
- break;
40
- case "w":
41
- case "W": throw new RangeError("`w/W` (week) patterns are not supported");
42
- case "d":
43
- result.day = ["numeric", "2-digit"][len - 1];
44
- break;
45
- case "D":
46
- case "F":
47
- case "g": throw new RangeError("`D/F/g` (day) patterns are not supported, use `d` instead");
48
- case "E":
49
- result.weekday = len === 4 ? "long" : len === 5 ? "narrow" : "short";
50
- break;
51
- case "e":
52
- if (len < 4) {
53
- throw new RangeError("`e..eee` (weekday) patterns are not supported");
54
- }
55
- result.weekday = [
56
- "short",
57
- "long",
58
- "narrow",
59
- "short"
60
- ][len - 4];
61
- break;
62
- case "c":
63
- if (len < 4) {
64
- throw new RangeError("`c..ccc` (weekday) patterns are not supported");
65
- }
66
- result.weekday = [
67
- "short",
68
- "long",
69
- "narrow",
70
- "short"
71
- ][len - 4];
72
- break;
73
- case "a":
74
- result.hour12 = true;
75
- break;
76
- case "b":
77
- case "B": throw new RangeError("`b/B` (period) patterns are not supported, use `a` instead");
78
- case "h":
79
- result.hourCycle = "h12";
80
- result.hour = ["numeric", "2-digit"][len - 1];
81
- break;
82
- case "H":
83
- result.hourCycle = "h23";
84
- result.hour = ["numeric", "2-digit"][len - 1];
85
- break;
86
- case "K":
87
- result.hourCycle = "h11";
88
- result.hour = ["numeric", "2-digit"][len - 1];
89
- break;
90
- case "k":
91
- result.hourCycle = "h24";
92
- result.hour = ["numeric", "2-digit"][len - 1];
93
- break;
94
- case "j":
95
- case "J":
96
- case "C": throw new RangeError("`j/J/C` (hour) patterns are not supported, use `h/H/K/k` instead");
97
- case "m":
98
- result.minute = ["numeric", "2-digit"][len - 1];
99
- break;
100
- case "s":
101
- result.second = ["numeric", "2-digit"][len - 1];
102
- break;
103
- case "S":
104
- case "A": throw new RangeError("`S/A` (second) patterns are not supported, use `s` instead");
105
- case "z":
106
- result.timeZoneName = len < 4 ? "short" : "long";
107
- break;
108
- case "Z":
109
- case "O":
110
- case "v":
111
- case "V":
112
- case "X":
113
- case "x": throw new RangeError("`Z/O/v/V/X/x` (timeZone) patterns are not supported, use `z` instead");
114
- }
115
- return "";
116
- });
117
- return result;
118
- }
package/number.d.ts DELETED
@@ -1,13 +0,0 @@
1
- import type { NumberFormatOptions } from "@formatjs/ecma402-abstract";
2
- export interface ExtendedNumberFormatOptions extends NumberFormatOptions {
3
- scale?: number;
4
- }
5
- export interface NumberSkeletonToken {
6
- stem: string;
7
- options: string[];
8
- }
9
- export declare function parseNumberSkeletonFromString(skeleton: string): NumberSkeletonToken[];
10
- /**
11
- * https://github.com/unicode-org/icu/blob/master/docs/userguide/format_parse/numbers/skeletons.md#skeleton-stems-and-options
12
- */
13
- export declare function parseNumberSkeleton(tokens: NumberSkeletonToken[]): ExtendedNumberFormatOptions;
package/number.js DELETED
@@ -1,301 +0,0 @@
1
- import { WHITE_SPACE_REGEX } from "./regex.generated.js";
2
- export function parseNumberSkeletonFromString(skeleton) {
3
- if (skeleton.length === 0) {
4
- throw new Error("Number skeleton cannot be empty");
5
- }
6
- // Parse the skeleton
7
- const stringTokens = skeleton.split(WHITE_SPACE_REGEX).filter((x) => x.length > 0);
8
- const tokens = [];
9
- for (const stringToken of stringTokens) {
10
- let stemAndOptions = stringToken.split("/");
11
- if (stemAndOptions.length === 0) {
12
- throw new Error("Invalid number skeleton");
13
- }
14
- const [stem, ...options] = stemAndOptions;
15
- for (const option of options) {
16
- if (option.length === 0) {
17
- throw new Error("Invalid number skeleton");
18
- }
19
- }
20
- tokens.push({
21
- stem,
22
- options
23
- });
24
- }
25
- return tokens;
26
- }
27
- function icuUnitToEcma(unit) {
28
- return unit.replace(/^(.*?)-/, "");
29
- }
30
- const FRACTION_PRECISION_REGEX = /^\.(?:(0+)(\*)?|(#+)|(0+)(#+))$/g;
31
- const SIGNIFICANT_PRECISION_REGEX = /^(@+)?(\+|#+)?[rs]?$/g;
32
- const INTEGER_WIDTH_REGEX = /(\*)(0+)|(#+)(0+)|(0+)/g;
33
- const CONCISE_INTEGER_WIDTH_REGEX = /^(0+)$/;
34
- function parseSignificantPrecision(str) {
35
- const result = {};
36
- if (str[str.length - 1] === "r") {
37
- result.roundingPriority = "morePrecision";
38
- } else if (str[str.length - 1] === "s") {
39
- result.roundingPriority = "lessPrecision";
40
- }
41
- str.replace(SIGNIFICANT_PRECISION_REGEX, function(_, g1, g2) {
42
- // @@@ case
43
- if (typeof g2 !== "string") {
44
- result.minimumSignificantDigits = g1.length;
45
- result.maximumSignificantDigits = g1.length;
46
- } else if (g2 === "+") {
47
- result.minimumSignificantDigits = g1.length;
48
- } else if (g1[0] === "#") {
49
- result.maximumSignificantDigits = g1.length;
50
- } else {
51
- result.minimumSignificantDigits = g1.length;
52
- result.maximumSignificantDigits = g1.length + (typeof g2 === "string" ? g2.length : 0);
53
- }
54
- return "";
55
- });
56
- return result;
57
- }
58
- function parseSign(str) {
59
- switch (str) {
60
- case "sign-auto": return { signDisplay: "auto" };
61
- case "sign-accounting":
62
- case "()": return { currencySign: "accounting" };
63
- case "sign-always":
64
- case "+!": return { signDisplay: "always" };
65
- case "sign-accounting-always":
66
- case "()!": return {
67
- signDisplay: "always",
68
- currencySign: "accounting"
69
- };
70
- case "sign-except-zero":
71
- case "+?": return { signDisplay: "exceptZero" };
72
- case "sign-accounting-except-zero":
73
- case "()?": return {
74
- signDisplay: "exceptZero",
75
- currencySign: "accounting"
76
- };
77
- case "sign-never":
78
- case "+_": return { signDisplay: "never" };
79
- }
80
- }
81
- function parseConciseScientificAndEngineeringStem(stem) {
82
- // Engineering
83
- let result;
84
- if (stem[0] === "E" && stem[1] === "E") {
85
- result = { notation: "engineering" };
86
- stem = stem.slice(2);
87
- } else if (stem[0] === "E") {
88
- result = { notation: "scientific" };
89
- stem = stem.slice(1);
90
- }
91
- if (result) {
92
- const signDisplay = stem.slice(0, 2);
93
- if (signDisplay === "+!") {
94
- result.signDisplay = "always";
95
- stem = stem.slice(2);
96
- } else if (signDisplay === "+?") {
97
- result.signDisplay = "exceptZero";
98
- stem = stem.slice(2);
99
- }
100
- if (!CONCISE_INTEGER_WIDTH_REGEX.test(stem)) {
101
- throw new Error("Malformed concise eng/scientific notation");
102
- }
103
- result.minimumIntegerDigits = stem.length;
104
- }
105
- return result;
106
- }
107
- function parseNotationOptions(opt) {
108
- const result = {};
109
- const signOpts = parseSign(opt);
110
- if (signOpts) {
111
- return signOpts;
112
- }
113
- return result;
114
- }
115
- /**
116
- * https://github.com/unicode-org/icu/blob/master/docs/userguide/format_parse/numbers/skeletons.md#skeleton-stems-and-options
117
- */
118
- export function parseNumberSkeleton(tokens) {
119
- let result = {};
120
- for (const token of tokens) {
121
- switch (token.stem) {
122
- case "percent":
123
- case "%":
124
- result.style = "percent";
125
- continue;
126
- case "%x100":
127
- result.style = "percent";
128
- result.scale = 100;
129
- continue;
130
- case "currency":
131
- result.style = "currency";
132
- result.currency = token.options[0];
133
- continue;
134
- case "group-off":
135
- case ",_":
136
- result.useGrouping = false;
137
- continue;
138
- case "precision-integer":
139
- case ".":
140
- result.maximumFractionDigits = 0;
141
- continue;
142
- case "measure-unit":
143
- case "unit":
144
- result.style = "unit";
145
- result.unit = icuUnitToEcma(token.options[0]);
146
- continue;
147
- case "compact-short":
148
- case "K":
149
- result.notation = "compact";
150
- result.compactDisplay = "short";
151
- continue;
152
- case "compact-long":
153
- case "KK":
154
- result.notation = "compact";
155
- result.compactDisplay = "long";
156
- continue;
157
- case "scientific":
158
- result = {
159
- ...result,
160
- notation: "scientific",
161
- ...token.options.reduce((all, opt) => ({
162
- ...all,
163
- ...parseNotationOptions(opt)
164
- }), {})
165
- };
166
- continue;
167
- case "engineering":
168
- result = {
169
- ...result,
170
- notation: "engineering",
171
- ...token.options.reduce((all, opt) => ({
172
- ...all,
173
- ...parseNotationOptions(opt)
174
- }), {})
175
- };
176
- continue;
177
- case "notation-simple":
178
- result.notation = "standard";
179
- continue;
180
- case "unit-width-narrow":
181
- result.currencyDisplay = "narrowSymbol";
182
- result.unitDisplay = "narrow";
183
- continue;
184
- case "unit-width-short":
185
- result.currencyDisplay = "code";
186
- result.unitDisplay = "short";
187
- continue;
188
- case "unit-width-full-name":
189
- result.currencyDisplay = "name";
190
- result.unitDisplay = "long";
191
- continue;
192
- case "unit-width-iso-code":
193
- result.currencyDisplay = "symbol";
194
- continue;
195
- case "scale":
196
- result.scale = parseFloat(token.options[0]);
197
- continue;
198
- case "rounding-mode-floor":
199
- result.roundingMode = "floor";
200
- continue;
201
- case "rounding-mode-ceiling":
202
- result.roundingMode = "ceil";
203
- continue;
204
- case "rounding-mode-down":
205
- result.roundingMode = "trunc";
206
- continue;
207
- case "rounding-mode-up":
208
- result.roundingMode = "expand";
209
- continue;
210
- case "rounding-mode-half-even":
211
- result.roundingMode = "halfEven";
212
- continue;
213
- case "rounding-mode-half-down":
214
- result.roundingMode = "halfTrunc";
215
- continue;
216
- case "rounding-mode-half-up":
217
- result.roundingMode = "halfExpand";
218
- continue;
219
- case "integer-width":
220
- if (token.options.length > 1) {
221
- throw new RangeError("integer-width stems only accept a single optional option");
222
- }
223
- token.options[0].replace(INTEGER_WIDTH_REGEX, function(_, g1, g2, g3, g4, g5) {
224
- if (g1) {
225
- result.minimumIntegerDigits = g2.length;
226
- } else if (g3 && g4) {
227
- throw new Error("We currently do not support maximum integer digits");
228
- } else if (g5) {
229
- throw new Error("We currently do not support exact integer digits");
230
- }
231
- return "";
232
- });
233
- continue;
234
- }
235
- // https://unicode-org.github.io/icu/userguide/format_parse/numbers/skeletons.html#integer-width
236
- if (CONCISE_INTEGER_WIDTH_REGEX.test(token.stem)) {
237
- result.minimumIntegerDigits = token.stem.length;
238
- continue;
239
- }
240
- if (FRACTION_PRECISION_REGEX.test(token.stem)) {
241
- // Precision
242
- // https://unicode-org.github.io/icu/userguide/format_parse/numbers/skeletons.html#fraction-precision
243
- // precision-integer case
244
- if (token.options.length > 1) {
245
- throw new RangeError("Fraction-precision stems only accept a single optional option");
246
- }
247
- token.stem.replace(FRACTION_PRECISION_REGEX, function(_, g1, g2, g3, g4, g5) {
248
- // .000* case (before ICU67 it was .000+)
249
- if (g2 === "*") {
250
- result.minimumFractionDigits = g1.length;
251
- } else if (g3 && g3[0] === "#") {
252
- result.maximumFractionDigits = g3.length;
253
- } else if (g4 && g5) {
254
- result.minimumFractionDigits = g4.length;
255
- result.maximumFractionDigits = g4.length + g5.length;
256
- } else {
257
- result.minimumFractionDigits = g1.length;
258
- result.maximumFractionDigits = g1.length;
259
- }
260
- return "";
261
- });
262
- const opt = token.options[0];
263
- // https://unicode-org.github.io/icu/userguide/format_parse/numbers/skeletons.html#trailing-zero-display
264
- if (opt === "w") {
265
- result = {
266
- ...result,
267
- trailingZeroDisplay: "stripIfInteger"
268
- };
269
- } else if (opt) {
270
- result = {
271
- ...result,
272
- ...parseSignificantPrecision(opt)
273
- };
274
- }
275
- continue;
276
- }
277
- // https://unicode-org.github.io/icu/userguide/format_parse/numbers/skeletons.html#significant-digits-precision
278
- if (SIGNIFICANT_PRECISION_REGEX.test(token.stem)) {
279
- result = {
280
- ...result,
281
- ...parseSignificantPrecision(token.stem)
282
- };
283
- continue;
284
- }
285
- const signOpts = parseSign(token.stem);
286
- if (signOpts) {
287
- result = {
288
- ...result,
289
- ...signOpts
290
- };
291
- }
292
- const conciseScientificAndEngineeringOpts = parseConciseScientificAndEngineeringStem(token.stem);
293
- if (conciseScientificAndEngineeringOpts) {
294
- result = {
295
- ...result,
296
- ...conciseScientificAndEngineeringOpts
297
- };
298
- }
299
- }
300
- return result;
301
- }
@@ -1 +0,0 @@
1
- export declare const WHITE_SPACE_REGEX: RegExp;
@@ -1,2 +0,0 @@
1
- // @generated from regex-gen.ts
2
- export const WHITE_SPACE_REGEX = /[\t-\r \x85\u200E\u200F\u2028\u2029]/i;