@ultraq/icu-message-formatter 0.14.2 → 0.15.0-beta.1

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.
@@ -1,44 +1,9 @@
1
- import { memoize } from '@ultraq/function-utils';
2
-
3
- /*
4
- * Copyright 2019, Emanuel Rabina (http://www.ultraq.net.nz/)
5
- *
6
- * Licensed under the Apache License, Version 2.0 (the "License");
7
- * you may not use this file except in compliance with the License.
8
- * You may obtain a copy of the License at
9
- *
10
- * http://www.apache.org/licenses/LICENSE-2.0
11
- *
12
- * Unless required by applicable law or agreed to in writing, software
13
- * distributed under the License is distributed on an "AS IS" BASIS,
14
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- * See the License for the specific language governing permissions and
16
- * limitations under the License.
17
- */
18
-
19
- /**
20
- * @typedef ParseCasesResult
21
- * @property {string[]} args
22
- * A list of prepended arguments.
23
- * @property {Record<string,string>} cases
24
- * A map of all cases.
25
- */
26
-
27
- /**
28
- * Most branch-based type handlers are based around "cases". For example,
29
- * `select` and `plural` compare compare a value to "case keys" to choose a
30
- * subtranslation.
31
- *
32
- * This util splits "matches" portions provided to the aforementioned handlers
33
- * into case strings, and extracts any prepended arguments (for example,
34
- * `plural` supports an `offset:n` argument used for populating the magic `#`
35
- * variable).
36
- *
37
- * @param {string} string
38
- * @return {ParseCasesResult}
39
- */
40
- function parseCases(string = '') {
41
- const isWhitespace = ch => /\s/.test(ch);
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ import { memoize } from "@ultraq/function-utils";
5
+ function parseCases(string = "") {
6
+ const isWhitespace = (ch) => /\s/.test(ch);
42
7
  const args = [];
43
8
  const cases = {};
44
9
  let currTermStart = 0;
@@ -46,31 +11,21 @@ function parseCases(string = '') {
46
11
  let inTerm = false;
47
12
  let i = 0;
48
13
  while (i < string.length) {
49
- // Term ended
50
- if (inTerm && (isWhitespace(string[i]) || string[i] === '{')) {
14
+ if (inTerm && (isWhitespace(string[i]) || string[i] === "{")) {
51
15
  inTerm = false;
52
16
  latestTerm = string.slice(currTermStart, i);
53
-
54
- // We want to process the opening char again so the case will be properly registered.
55
- if (string[i] === '{') {
17
+ if (string[i] === "{") {
56
18
  i--;
57
19
  }
58
- }
59
-
60
- // New term
61
- else if (!inTerm && !isWhitespace(string[i])) {
62
- const caseBody = string[i] === '{';
63
-
64
- // If there's a previous term, we can either handle a whole
65
- // case, or add that as an argument.
20
+ } else if (!inTerm && !isWhitespace(string[i])) {
21
+ const caseBody = string[i] === "{";
66
22
  if (latestTerm && caseBody) {
67
23
  const branchEndIndex = findClosingBracket(string, i);
68
24
  if (branchEndIndex === -1) {
69
25
  throw new Error(`Unbalanced curly braces in string: "${string}"`);
70
26
  }
71
- cases[latestTerm] = string.slice(i + 1, branchEndIndex); // Don't include the braces
72
-
73
- i = branchEndIndex; // Will be moved up where needed at end of loop.
27
+ cases[latestTerm] = string.slice(i + 1, branchEndIndex);
28
+ i = branchEndIndex;
74
29
  latestTerm = null;
75
30
  } else {
76
31
  if (latestTerm) {
@@ -94,57 +49,24 @@ function parseCases(string = '') {
94
49
  cases
95
50
  };
96
51
  }
97
-
98
- /**
99
- * Finds the index of the matching closing curly bracket, including through
100
- * strings that could have nested brackets.
101
- *
102
- * @param {string} string
103
- * @param {number} fromIndex
104
- * @return {number}
105
- * The index of the matching closing bracket, or -1 if no closing bracket
106
- * could be found.
107
- */
108
52
  function findClosingBracket(string, fromIndex) {
109
53
  let depth = 0;
110
54
  for (let i = fromIndex + 1; i < string.length; i++) {
111
55
  let char = string.charAt(i);
112
- if (char === '}') {
56
+ if (char === "}") {
113
57
  if (depth === 0) {
114
58
  return i;
115
59
  }
116
60
  depth--;
117
- } else if (char === '{') {
61
+ } else if (char === "{") {
118
62
  depth++;
119
63
  }
120
64
  }
121
65
  return -1;
122
66
  }
123
-
124
- /**
125
- * Split a `{key, type, format}` block into those 3 parts, taking into account
126
- * nested message syntax that can exist in the `format` part.
127
- *
128
- * @param {string} block
129
- * @return {string[]}
130
- * An array with `key`, `type`, and `format` items in that order, if present
131
- * in the formatted argument block.
132
- */
133
67
  function splitFormattedArgument(block) {
134
- return split(block.slice(1, -1), ',', 3);
68
+ return split(block.slice(1, -1), ",", 3);
135
69
  }
136
-
137
- /**
138
- * Like `String.prototype.split()` but where the limit parameter causes the
139
- * remainder of the string to be grouped together in a final entry.
140
- *
141
- * @private
142
- * @param {string} string
143
- * @param {string} separator
144
- * @param {number} limit
145
- * @param {string[]} accumulator
146
- * @return {string[]}
147
- */
148
70
  function split(string, separator, limit, accumulator = []) {
149
71
  if (!string) {
150
72
  return accumulator;
@@ -163,57 +85,6 @@ function split(string, separator, limit, accumulator = []) {
163
85
  accumulator.push(head);
164
86
  return split(tail, separator, limit - 1, accumulator);
165
87
  }
166
-
167
- /*
168
- * Copyright 2019, Emanuel Rabina (http://www.ultraq.net.nz/)
169
- *
170
- * Licensed under the Apache License, Version 2.0 (the "License");
171
- * you may not use this file except in compliance with the License.
172
- * You may obtain a copy of the License at
173
- *
174
- * http://www.apache.org/licenses/LICENSE-2.0
175
- *
176
- * Unless required by applicable law or agreed to in writing, software
177
- * distributed under the License is distributed on an "AS IS" BASIS,
178
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
179
- * See the License for the specific language governing permissions and
180
- * limitations under the License.
181
- */
182
-
183
-
184
- /**
185
- * @typedef {Record<string,any>} FormatValues
186
- */
187
-
188
- /**
189
- * @callback ProcessFunction
190
- * @param {string} message
191
- * @param {FormatValues} [values={}]
192
- * @return {any[]}
193
- */
194
-
195
- /**
196
- * @callback TypeHandler
197
- * @param {any} value
198
- * The object which matched the key of the block being processed.
199
- * @param {string} matches
200
- * Any format options associated with the block being processed.
201
- * @param {string} locale
202
- * The locale to use for formatting.
203
- * @param {FormatValues} values
204
- * The object of placeholder data given to the original `format`/`process`
205
- * call.
206
- * @param {ProcessFunction} process
207
- * The `process` function itself so that sub-messages can be processed by type
208
- * handlers.
209
- * @return {any | any[]}
210
- */
211
-
212
- /**
213
- * The main class for formatting messages.
214
- *
215
- * @author Emanuel Rabina
216
- */
217
88
  class MessageFormatter {
218
89
  /**
219
90
  * Creates a new formatter that can work using any of the custom type handlers
@@ -226,20 +97,18 @@ class MessageFormatter {
226
97
  * string for the data and locale they are given.
227
98
  */
228
99
  constructor(locale, typeHandlers = {}) {
100
+ /**
101
+ * Formats an ICU message syntax string using `values` for placeholder data
102
+ * and any currently-registered type handlers.
103
+ *
104
+ * @type {(message: string, values?: FormatValues) => string}
105
+ */
106
+ __publicField(this, "format", memoize((message, values = {}) => {
107
+ return this.process(message, values).flat(Infinity).join("");
108
+ }));
229
109
  this.locale = locale;
230
110
  this.typeHandlers = typeHandlers;
231
111
  }
232
-
233
- /**
234
- * Formats an ICU message syntax string using `values` for placeholder data
235
- * and any currently-registered type handlers.
236
- *
237
- * @type {(message: string, values?: FormatValues) => string}
238
- */
239
- format = memoize((message, values = {}) => {
240
- return this.process(message, values).flat(Infinity).join('');
241
- });
242
-
243
112
  /**
244
113
  * Process an ICU message syntax string using `values` for placeholder data
245
114
  * and any currently-registered type handlers. The result of this method is
@@ -259,7 +128,7 @@ class MessageFormatter {
259
128
  if (!message) {
260
129
  return [];
261
130
  }
262
- let blockStartIndex = message.indexOf('{');
131
+ let blockStartIndex = message.indexOf("{");
263
132
  if (blockStartIndex !== -1) {
264
133
  let blockEndIndex = findClosingBracket(message, blockStartIndex);
265
134
  if (blockEndIndex !== -1) {
@@ -272,8 +141,8 @@ class MessageFormatter {
272
141
  }
273
142
  let [key, type, format] = splitFormattedArgument(block);
274
143
  let body = values[key];
275
- if (body === null || body === undefined) {
276
- body = '';
144
+ if (body === null || body === void 0) {
145
+ body = "";
277
146
  }
278
147
  let typeHandler = type && this.typeHandlers[type];
279
148
  result.push(typeHandler ? typeHandler(body, format, this.locale, values, this.process.bind(this)) : body);
@@ -290,52 +159,26 @@ class MessageFormatter {
290
159
  return [message];
291
160
  }
292
161
  }
293
-
294
- /*
295
- * Copyright 2019, Emanuel Rabina (http://www.ultraq.net.nz/)
296
- *
297
- * Licensed under the Apache License, Version 2.0 (the "License");
298
- * you may not use this file except in compliance with the License.
299
- * You may obtain a copy of the License at
300
- *
301
- * http://www.apache.org/licenses/LICENSE-2.0
302
- *
303
- * Unless required by applicable law or agreed to in writing, software
304
- * distributed under the License is distributed on an "AS IS" BASIS,
305
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
306
- * See the License for the specific language governing permissions and
307
- * limitations under the License.
308
- */
309
-
310
162
  let pluralFormatter;
311
163
  let keyCounter = 0;
312
-
313
- // All the special keywords that can be used in `plural` blocks for the various branches
314
- const ONE = 'one';
315
- const OTHER$1 = 'other';
316
-
317
- /**
318
- * @private
319
- * @param {string} caseBody
320
- * @param {number} value
321
- * @return {{caseBody: string, numberValues: object}}
322
- */
164
+ const ONE = "one";
165
+ const OTHER$1 = "other";
323
166
  function replaceNumberSign(caseBody, value) {
324
167
  let i = 0;
325
- let output = '';
168
+ let output = "";
326
169
  let numBraces = 0;
327
170
  const numberValues = {};
328
171
  while (i < caseBody.length) {
329
- if (caseBody[i] === '#' && !numBraces) {
172
+ if (caseBody[i] === "#" && !numBraces) {
330
173
  let keyParam = `__hashToken${keyCounter++}`;
331
174
  output += `{${keyParam}, number}`;
332
175
  numberValues[keyParam] = value;
333
176
  } else {
334
177
  output += caseBody[i];
335
178
  }
336
- if (caseBody[i] === '{') {
179
+ if (caseBody[i] === "{") {
337
180
  numBraces++;
338
- } else if (caseBody[i] === '}') {
181
+ } else if (caseBody[i] === "}") {
339
182
  numBraces--;
340
183
  }
341
184
  i++;
@@ -345,41 +188,20 @@ function replaceNumberSign(caseBody, value) {
345
188
  numberValues
346
189
  };
347
190
  }
348
-
349
- /**
350
- * Handler for `plural` statements within ICU message syntax strings. Returns
351
- * a formatted string for the branch that closely matches the current value.
352
- *
353
- * See https://formatjs.io/docs/core-concepts/icu-syntax#plural-format for more
354
- * details on how the `plural` statement works.
355
- *
356
- * @param {string} value
357
- * @param {string} matches
358
- * @param {string} locale
359
- * @param {import('./MessageFormatter.js').FormatValues} values
360
- * @param {import('./MessageFormatter.js').ProcessFunction} process
361
- * @return {any | any[]}
362
- */
363
191
  function pluralTypeHandler(value, matches, locale, values, process) {
364
- const {
365
- args,
366
- cases
367
- } = parseCases(matches);
192
+ const { args, cases } = parseCases(matches);
368
193
  let intValue = parseInt(value);
369
- args.forEach(arg => {
370
- if (arg.startsWith('offset:')) {
371
- intValue -= parseInt(arg.slice('offset:'.length));
194
+ args.forEach((arg) => {
195
+ if (arg.startsWith("offset:")) {
196
+ intValue -= parseInt(arg.slice("offset:".length));
372
197
  }
373
198
  });
374
199
  const keywordPossibilities = [];
375
- if ('PluralRules' in Intl) {
376
- // Effectively memoize because instantiation of `Int.*` objects is expensive.
377
- if (pluralFormatter === undefined || pluralFormatter.resolvedOptions().locale !== locale) {
200
+ if ("PluralRules" in Intl) {
201
+ if (pluralFormatter === void 0 || pluralFormatter.resolvedOptions().locale !== locale) {
378
202
  pluralFormatter = new Intl.PluralRules(locale);
379
203
  }
380
204
  const pluralKeyword = pluralFormatter.select(intValue);
381
-
382
- // Other is always added last with least priority, so we don't want to add it here.
383
205
  if (pluralKeyword !== OTHER$1) {
384
206
  keywordPossibilities.push(pluralKeyword);
385
207
  }
@@ -391,10 +213,7 @@ function pluralTypeHandler(value, matches, locale, values, process) {
391
213
  for (let i = 0; i < keywordPossibilities.length; i++) {
392
214
  const keyword = keywordPossibilities[i];
393
215
  if (keyword in cases) {
394
- const {
395
- caseBody,
396
- numberValues
397
- } = replaceNumberSign(cases[keyword], intValue);
216
+ const { caseBody, numberValues } = replaceNumberSign(cases[keyword], intValue);
398
217
  return process(caseBody, {
399
218
  ...values,
400
219
  ...numberValues
@@ -403,43 +222,9 @@ function pluralTypeHandler(value, matches, locale, values, process) {
403
222
  }
404
223
  return value;
405
224
  }
406
-
407
- /*
408
- * Copyright 2019, Emanuel Rabina (http://www.ultraq.net.nz/)
409
- *
410
- * Licensed under the Apache License, Version 2.0 (the "License");
411
- * you may not use this file except in compliance with the License.
412
- * You may obtain a copy of the License at
413
- *
414
- * http://www.apache.org/licenses/LICENSE-2.0
415
- *
416
- * Unless required by applicable law or agreed to in writing, software
417
- * distributed under the License is distributed on an "AS IS" BASIS,
418
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
419
- * See the License for the specific language governing permissions and
420
- * limitations under the License.
421
- */
422
-
423
- const OTHER = 'other';
424
-
425
- /**
426
- * Handler for `select` statements within ICU message syntax strings. Returns
427
- * a formatted string for the branch that closely matches the current value.
428
- *
429
- * See https://formatjs.io/docs/core-concepts/icu-syntax#select-format for more
430
- * details on how the `select` statement works.
431
- *
432
- * @param {string} value
433
- * @param {string} matches
434
- * @param {string} locale
435
- * @param {import('./MessageFormatter.js').FormatValues} values
436
- * @param {import('./MessageFormatter.js').ProcessFunction} process
437
- * @return {any | any[]}
438
- */
225
+ const OTHER = "other";
439
226
  function selectTypeHandler(value, matches, locale, values, process) {
440
- const {
441
- cases
442
- } = parseCases(matches);
227
+ const { cases } = parseCases(matches);
443
228
  if (value in cases) {
444
229
  return process(cases[value], values);
445
230
  } else if (OTHER in cases) {
@@ -447,6 +232,12 @@ function selectTypeHandler(value, matches, locale, values, process) {
447
232
  }
448
233
  return value;
449
234
  }
450
-
451
- export { MessageFormatter, findClosingBracket, parseCases, pluralTypeHandler, selectTypeHandler, splitFormattedArgument };
235
+ export {
236
+ MessageFormatter,
237
+ findClosingBracket,
238
+ parseCases,
239
+ pluralTypeHandler,
240
+ selectTypeHandler,
241
+ splitFormattedArgument
242
+ };
452
243
  //# sourceMappingURL=icu-message-formatter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"icu-message-formatter.js","sources":["../source/utilities.js","../source/MessageFormatter.js","../source/pluralTypeHandler.js","../source/selectTypeHandler.js"],"sourcesContent":["/*\n * Copyright 2019, Emanuel Rabina (http://www.ultraq.net.nz/)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @typedef ParseCasesResult\n * @property {string[]} args\n * A list of prepended arguments.\n * @property {Record<string,string>} cases\n * A map of all cases.\n */\n\n/**\n * Most branch-based type handlers are based around \"cases\". For example,\n * `select` and `plural` compare compare a value to \"case keys\" to choose a\n * subtranslation.\n *\n * This util splits \"matches\" portions provided to the aforementioned handlers\n * into case strings, and extracts any prepended arguments (for example,\n * `plural` supports an `offset:n` argument used for populating the magic `#`\n * variable).\n *\n * @param {string} string\n * @return {ParseCasesResult}\n */\nexport function parseCases(string = '') {\n\tconst isWhitespace = ch => /\\s/.test(ch);\n\n\tconst args = [];\n\tconst cases = {};\n\n\tlet currTermStart = 0;\n\tlet latestTerm = null;\n\tlet inTerm = false;\n\n\tlet i = 0;\n\twhile (i < string.length) {\n\t\t// Term ended\n\t\tif (inTerm && (isWhitespace(string[i]) || string[i] === '{')) {\n\t\t\tinTerm = false;\n\t\t\tlatestTerm = string.slice(currTermStart, i);\n\n\t\t\t// We want to process the opening char again so the case will be properly registered.\n\t\t\tif (string[i] === '{') {\n\t\t\t\ti--;\n\t\t\t}\n\t\t}\n\n\t\t// New term\n\t\telse if (!inTerm && !isWhitespace(string[i])) {\n\t\t\tconst caseBody = string[i] === '{';\n\n\t\t\t// If there's a previous term, we can either handle a whole\n\t\t\t// case, or add that as an argument.\n\t\t\tif (latestTerm && caseBody) {\n\t\t\t\tconst branchEndIndex = findClosingBracket(string, i);\n\n\t\t\t\tif (branchEndIndex === -1) {\n\t\t\t\t\tthrow new Error(`Unbalanced curly braces in string: \"${string}\"`);\n\t\t\t\t}\n\n\t\t\t\tcases[latestTerm] = string.slice(i + 1, branchEndIndex); // Don't include the braces\n\n\t\t\t\ti = branchEndIndex; // Will be moved up where needed at end of loop.\n\t\t\t\tlatestTerm = null;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (latestTerm) {\n\t\t\t\t\targs.push(latestTerm);\n\t\t\t\t\tlatestTerm = null;\n\t\t\t\t}\n\n\t\t\t\tinTerm = true;\n\t\t\t\tcurrTermStart = i;\n\t\t\t}\n\t\t}\n\t\ti++;\n\t}\n\n\tif (inTerm) {\n\t\tlatestTerm = string.slice(currTermStart);\n\t}\n\n\tif (latestTerm) {\n\t\targs.push(latestTerm);\n\t}\n\n\treturn {\n\t\targs,\n\t\tcases\n\t};\n}\n\n/**\n * Finds the index of the matching closing curly bracket, including through\n * strings that could have nested brackets.\n *\n * @param {string} string\n * @param {number} fromIndex\n * @return {number}\n * The index of the matching closing bracket, or -1 if no closing bracket\n * could be found.\n */\nexport function findClosingBracket(string, fromIndex) {\n\tlet depth = 0;\n\tfor (let i = fromIndex + 1; i < string.length; i++) {\n\t\tlet char = string.charAt(i);\n\t\tif (char === '}') {\n\t\t\tif (depth === 0) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t\tdepth--;\n\t\t}\n\t\telse if (char === '{') {\n\t\t\tdepth++;\n\t\t}\n\t}\n\treturn -1;\n}\n\n/**\n * Split a `{key, type, format}` block into those 3 parts, taking into account\n * nested message syntax that can exist in the `format` part.\n *\n * @param {string} block\n * @return {string[]}\n * An array with `key`, `type`, and `format` items in that order, if present\n * in the formatted argument block.\n */\nexport function splitFormattedArgument(block) {\n\treturn split(block.slice(1, -1), ',', 3);\n}\n\n/**\n * Like `String.prototype.split()` but where the limit parameter causes the\n * remainder of the string to be grouped together in a final entry.\n *\n * @private\n * @param {string} string\n * @param {string} separator\n * @param {number} limit\n * @param {string[]} accumulator\n * @return {string[]}\n */\nfunction split(string, separator, limit, accumulator = []) {\n\tif (!string) {\n\t\treturn accumulator;\n\t}\n\tif (limit === 1) {\n\t\taccumulator.push(string);\n\t\treturn accumulator;\n\t}\n\tlet indexOfDelimiter = string.indexOf(separator);\n\tif (indexOfDelimiter === -1) {\n\t\taccumulator.push(string);\n\t\treturn accumulator;\n\t}\n\tlet head = string.substring(0, indexOfDelimiter).trim();\n\tlet tail = string.substring(indexOfDelimiter + separator.length + 1).trim();\n\taccumulator.push(head);\n\treturn split(tail, separator, limit - 1, accumulator);\n}\n","/*\n * Copyright 2019, Emanuel Rabina (http://www.ultraq.net.nz/)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {findClosingBracket, splitFormattedArgument} from './utilities.js';\n\nimport {memoize} from '@ultraq/function-utils';\n\n/**\n * @typedef {Record<string,any>} FormatValues\n */\n\n/**\n * @callback ProcessFunction\n * @param {string} message\n * @param {FormatValues} [values={}]\n * @return {any[]}\n */\n\n/**\n * @callback TypeHandler\n * @param {any} value\n * The object which matched the key of the block being processed.\n * @param {string} matches\n * Any format options associated with the block being processed.\n * @param {string} locale\n * The locale to use for formatting.\n * @param {FormatValues} values\n * The object of placeholder data given to the original `format`/`process`\n * call.\n * @param {ProcessFunction} process\n * The `process` function itself so that sub-messages can be processed by type\n * handlers.\n * @return {any | any[]}\n */\n\n/**\n * The main class for formatting messages.\n *\n * @author Emanuel Rabina\n */\nexport default class MessageFormatter {\n\n\t/**\n\t * Creates a new formatter that can work using any of the custom type handlers\n\t * you register.\n\t *\n\t * @param {string} locale\n\t * @param {Record<string,TypeHandler>} [typeHandlers]\n\t * Optional object where the keys are the names of the types to register,\n\t * their values being the functions that will return a nicely formatted\n\t * string for the data and locale they are given.\n\t */\n\tconstructor(locale, typeHandlers = {}) {\n\n\t\tthis.locale = locale;\n\t\tthis.typeHandlers = typeHandlers;\n\t}\n\n\t/**\n\t * Formats an ICU message syntax string using `values` for placeholder data\n\t * and any currently-registered type handlers.\n\t *\n\t * @type {(message: string, values?: FormatValues) => string}\n\t */\n\tformat = memoize((message, values = {}) => {\n\n\t\treturn this.process(message, values).flat(Infinity).join('');\n\t});\n\n\t/**\n\t * Process an ICU message syntax string using `values` for placeholder data\n\t * and any currently-registered type handlers. The result of this method is\n\t * an array of the component parts after they have been processed in turn by\n\t * their own type handlers. This raw output is useful for other renderers,\n\t * eg: React where components can be used instead of being forced to return\n\t * raw strings.\n\t *\n\t * This method is used by {@link MessageFormatter#format} where it acts as a\n\t * string renderer.\n\t *\n\t * @param {string} message\n\t * @param {FormatValues} [values]\n\t * @return {any[]}\n\t */\n\tprocess(message, values = {}) {\n\n\t\tif (!message) {\n\t\t\treturn [];\n\t\t}\n\n\t\tlet blockStartIndex = message.indexOf('{');\n\t\tif (blockStartIndex !== -1) {\n\t\t\tlet blockEndIndex = findClosingBracket(message, blockStartIndex);\n\t\t\tif (blockEndIndex !== -1) {\n\t\t\t\tlet block = message.substring(blockStartIndex, blockEndIndex + 1);\n\t\t\t\tif (block) {\n\t\t\t\t\tlet result = [];\n\t\t\t\t\tlet head = message.substring(0, blockStartIndex);\n\t\t\t\t\tif (head) {\n\t\t\t\t\t\tresult.push(head);\n\t\t\t\t\t}\n\t\t\t\t\tlet [key, type, format] = splitFormattedArgument(block);\n\t\t\t\t\tlet body = values[key];\n\t\t\t\t\tif (body === null || body === undefined) {\n\t\t\t\t\t\tbody = '';\n\t\t\t\t\t}\n\t\t\t\t\tlet typeHandler = type && this.typeHandlers[type];\n\t\t\t\t\tresult.push(typeHandler ?\n\t\t\t\t\t\ttypeHandler(body, format, this.locale, values, this.process.bind(this)) :\n\t\t\t\t\t\tbody);\n\t\t\t\t\tlet tail = message.substring(blockEndIndex + 1);\n\t\t\t\t\tif (tail) {\n\t\t\t\t\t\tresult.push(this.process(tail, values));\n\t\t\t\t\t}\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new Error(`Unbalanced curly braces in string: \"${message}\"`);\n\t\t\t}\n\t\t}\n\t\treturn [message];\n\t}\n}\n","/*\n * Copyright 2019, Emanuel Rabina (http://www.ultraq.net.nz/)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {parseCases} from './utilities.js';\n\nlet pluralFormatter;\n\nlet keyCounter = 0;\n\n// All the special keywords that can be used in `plural` blocks for the various branches\nconst ONE = 'one';\nconst OTHER = 'other';\n\n/**\n * @private\n * @param {string} caseBody\n * @param {number} value\n * @return {{caseBody: string, numberValues: object}}\n */\nfunction replaceNumberSign(caseBody, value) {\n\tlet i = 0;\n\tlet output = '';\n\tlet numBraces = 0;\n\tconst numberValues = {};\n\n\twhile (i < caseBody.length) {\n\t\tif (caseBody[i] === '#' && !numBraces) {\n\t\t\tlet keyParam = `__hashToken${keyCounter++}`;\n\t\t\toutput += `{${keyParam}, number}`;\n\t\t\tnumberValues[keyParam] = value;\n\t\t}\n\t\telse {\n\t\t\toutput += caseBody[i];\n\t\t}\n\n\t\tif (caseBody[i] === '{') {\n\t\t\tnumBraces++;\n\t\t}\n\t\telse if (caseBody[i] === '}') {\n\t\t\tnumBraces--;\n\t\t}\n\n\t\ti++;\n\t}\n\n\treturn {\n\t\tcaseBody: output,\n\t\tnumberValues\n\t};\n}\n\n/**\n * Handler for `plural` statements within ICU message syntax strings. Returns\n * a formatted string for the branch that closely matches the current value.\n *\n * See https://formatjs.io/docs/core-concepts/icu-syntax#plural-format for more\n * details on how the `plural` statement works.\n *\n * @param {string} value\n * @param {string} matches\n * @param {string} locale\n * @param {import('./MessageFormatter.js').FormatValues} values\n * @param {import('./MessageFormatter.js').ProcessFunction} process\n * @return {any | any[]}\n */\nexport default function pluralTypeHandler(value, matches, locale, values, process) {\n\tconst {args, cases} = parseCases(matches);\n\n\tlet intValue = parseInt(value);\n\n\targs.forEach((arg) => {\n\t\tif (arg.startsWith('offset:')) {\n\t\t\tintValue -= parseInt(arg.slice('offset:'.length));\n\t\t}\n\t});\n\n\tconst keywordPossibilities = [];\n\n\tif ('PluralRules' in Intl) {\n\t\t// Effectively memoize because instantiation of `Int.*` objects is expensive.\n\t\tif (pluralFormatter === undefined || pluralFormatter.resolvedOptions().locale !== locale) {\n\t\t\tpluralFormatter = new Intl.PluralRules(locale);\n\t\t}\n\n\t\tconst pluralKeyword = pluralFormatter.select(intValue);\n\n\t\t// Other is always added last with least priority, so we don't want to add it here.\n\t\tif (pluralKeyword !== OTHER) {\n\t\t\tkeywordPossibilities.push(pluralKeyword);\n\t\t}\n\t}\n\tif (intValue === 1) {\n\t\tkeywordPossibilities.push(ONE);\n\t}\n\tkeywordPossibilities.push(`=${intValue}`, OTHER);\n\n\tfor (let i = 0; i < keywordPossibilities.length; i++) {\n\t\tconst keyword = keywordPossibilities[i];\n\t\tif (keyword in cases) {\n\t\t\tconst {caseBody, numberValues} = replaceNumberSign(cases[keyword], intValue);\n\t\t\treturn process(caseBody, {\n\t\t\t\t...values,\n\t\t\t\t...numberValues\n\t\t\t});\n\t\t}\n\t}\n\n\treturn value;\n}\n","/*\n * Copyright 2019, Emanuel Rabina (http://www.ultraq.net.nz/)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {parseCases} from './utilities.js';\n\nconst OTHER = 'other';\n\n/**\n * Handler for `select` statements within ICU message syntax strings. Returns\n * a formatted string for the branch that closely matches the current value.\n *\n * See https://formatjs.io/docs/core-concepts/icu-syntax#select-format for more\n * details on how the `select` statement works.\n *\n * @param {string} value\n * @param {string} matches\n * @param {string} locale\n * @param {import('./MessageFormatter.js').FormatValues} values\n * @param {import('./MessageFormatter.js').ProcessFunction} process\n * @return {any | any[]}\n */\nexport default function selectTypeHandler(value, matches, locale, values, process) {\n\tconst {cases} = parseCases(matches);\n\n\tif (value in cases) {\n\t\treturn process(cases[value], values);\n\t}\n\telse if (OTHER in cases) {\n\t\treturn process(cases[OTHER], values);\n\t}\n\n\treturn value;\n}\n"],"names":["parseCases","string","isWhitespace","ch","test","args","cases","currTermStart","latestTerm","inTerm","i","length","slice","caseBody","branchEndIndex","findClosingBracket","Error","push","fromIndex","depth","char","charAt","splitFormattedArgument","block","split","separator","limit","accumulator","indexOfDelimiter","indexOf","head","substring","trim","tail","MessageFormatter","constructor","locale","typeHandlers","format","memoize","message","values","process","flat","Infinity","join","blockStartIndex","blockEndIndex","result","key","type","body","undefined","typeHandler","bind","pluralFormatter","keyCounter","ONE","OTHER","replaceNumberSign","value","output","numBraces","numberValues","keyParam","pluralTypeHandler","matches","intValue","parseInt","forEach","arg","startsWith","keywordPossibilities","Intl","resolvedOptions","PluralRules","pluralKeyword","select","keyword","selectTypeHandler"],"mappings":"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"}
1
+ {"version":3,"file":"icu-message-formatter.js","sources":["../source/utilities.js","../source/MessageFormatter.js","../source/pluralTypeHandler.js","../source/selectTypeHandler.js"],"sourcesContent":["/*\n * Copyright 2019, Emanuel Rabina (http://www.ultraq.net.nz/)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @typedef ParseCasesResult\n * @property {string[]} args\n * A list of prepended arguments.\n * @property {Record<string,string>} cases\n * A map of all cases.\n */\n\n/**\n * Most branch-based type handlers are based around \"cases\". For example,\n * `select` and `plural` compare compare a value to \"case keys\" to choose a\n * subtranslation.\n *\n * This util splits \"matches\" portions provided to the aforementioned handlers\n * into case strings, and extracts any prepended arguments (for example,\n * `plural` supports an `offset:n` argument used for populating the magic `#`\n * variable).\n *\n * @param {string} string\n * @return {ParseCasesResult}\n */\nexport function parseCases(string = '') {\n\tconst isWhitespace = ch => /\\s/.test(ch);\n\n\tconst args = [];\n\tconst cases = {};\n\n\tlet currTermStart = 0;\n\tlet latestTerm = null;\n\tlet inTerm = false;\n\n\tlet i = 0;\n\twhile (i < string.length) {\n\t\t// Term ended\n\t\tif (inTerm && (isWhitespace(string[i]) || string[i] === '{')) {\n\t\t\tinTerm = false;\n\t\t\tlatestTerm = string.slice(currTermStart, i);\n\n\t\t\t// We want to process the opening char again so the case will be properly registered.\n\t\t\tif (string[i] === '{') {\n\t\t\t\ti--;\n\t\t\t}\n\t\t}\n\n\t\t// New term\n\t\telse if (!inTerm && !isWhitespace(string[i])) {\n\t\t\tconst caseBody = string[i] === '{';\n\n\t\t\t// If there's a previous term, we can either handle a whole\n\t\t\t// case, or add that as an argument.\n\t\t\tif (latestTerm && caseBody) {\n\t\t\t\tconst branchEndIndex = findClosingBracket(string, i);\n\n\t\t\t\tif (branchEndIndex === -1) {\n\t\t\t\t\tthrow new Error(`Unbalanced curly braces in string: \"${string}\"`);\n\t\t\t\t}\n\n\t\t\t\tcases[latestTerm] = string.slice(i + 1, branchEndIndex); // Don't include the braces\n\n\t\t\t\ti = branchEndIndex; // Will be moved up where needed at end of loop.\n\t\t\t\tlatestTerm = null;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (latestTerm) {\n\t\t\t\t\targs.push(latestTerm);\n\t\t\t\t\tlatestTerm = null;\n\t\t\t\t}\n\n\t\t\t\tinTerm = true;\n\t\t\t\tcurrTermStart = i;\n\t\t\t}\n\t\t}\n\t\ti++;\n\t}\n\n\tif (inTerm) {\n\t\tlatestTerm = string.slice(currTermStart);\n\t}\n\n\tif (latestTerm) {\n\t\targs.push(latestTerm);\n\t}\n\n\treturn {\n\t\targs,\n\t\tcases\n\t};\n}\n\n/**\n * Finds the index of the matching closing curly bracket, including through\n * strings that could have nested brackets.\n *\n * @param {string} string\n * @param {number} fromIndex\n * @return {number}\n * The index of the matching closing bracket, or -1 if no closing bracket\n * could be found.\n */\nexport function findClosingBracket(string, fromIndex) {\n\tlet depth = 0;\n\tfor (let i = fromIndex + 1; i < string.length; i++) {\n\t\tlet char = string.charAt(i);\n\t\tif (char === '}') {\n\t\t\tif (depth === 0) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t\tdepth--;\n\t\t}\n\t\telse if (char === '{') {\n\t\t\tdepth++;\n\t\t}\n\t}\n\treturn -1;\n}\n\n/**\n * Split a `{key, type, format}` block into those 3 parts, taking into account\n * nested message syntax that can exist in the `format` part.\n *\n * @param {string} block\n * @return {string[]}\n * An array with `key`, `type`, and `format` items in that order, if present\n * in the formatted argument block.\n */\nexport function splitFormattedArgument(block) {\n\treturn split(block.slice(1, -1), ',', 3);\n}\n\n/**\n * Like `String.prototype.split()` but where the limit parameter causes the\n * remainder of the string to be grouped together in a final entry.\n *\n * @private\n * @param {string} string\n * @param {string} separator\n * @param {number} limit\n * @param {string[]} accumulator\n * @return {string[]}\n */\nfunction split(string, separator, limit, accumulator = []) {\n\tif (!string) {\n\t\treturn accumulator;\n\t}\n\tif (limit === 1) {\n\t\taccumulator.push(string);\n\t\treturn accumulator;\n\t}\n\tlet indexOfDelimiter = string.indexOf(separator);\n\tif (indexOfDelimiter === -1) {\n\t\taccumulator.push(string);\n\t\treturn accumulator;\n\t}\n\tlet head = string.substring(0, indexOfDelimiter).trim();\n\tlet tail = string.substring(indexOfDelimiter + separator.length + 1).trim();\n\taccumulator.push(head);\n\treturn split(tail, separator, limit - 1, accumulator);\n}\n","/*\n * Copyright 2019, Emanuel Rabina (http://www.ultraq.net.nz/)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {findClosingBracket, splitFormattedArgument} from './utilities.js';\n\nimport {memoize} from '@ultraq/function-utils';\n\n/**\n * @typedef {Record<string,any>} FormatValues\n */\n\n/**\n * @callback ProcessFunction\n * @param {string} message\n * @param {FormatValues} [values={}]\n * @return {any[]}\n */\n\n/**\n * @callback TypeHandler\n * @param {any} value\n * The object which matched the key of the block being processed.\n * @param {string} matches\n * Any format options associated with the block being processed.\n * @param {string} locale\n * The locale to use for formatting.\n * @param {FormatValues} values\n * The object of placeholder data given to the original `format`/`process`\n * call.\n * @param {ProcessFunction} process\n * The `process` function itself so that sub-messages can be processed by type\n * handlers.\n * @return {any | any[]}\n */\n\n/**\n * The main class for formatting messages.\n *\n * @author Emanuel Rabina\n */\nexport default class MessageFormatter {\n\n\t/**\n\t * Creates a new formatter that can work using any of the custom type handlers\n\t * you register.\n\t *\n\t * @param {string} locale\n\t * @param {Record<string,TypeHandler>} [typeHandlers]\n\t * Optional object where the keys are the names of the types to register,\n\t * their values being the functions that will return a nicely formatted\n\t * string for the data and locale they are given.\n\t */\n\tconstructor(locale, typeHandlers = {}) {\n\n\t\tthis.locale = locale;\n\t\tthis.typeHandlers = typeHandlers;\n\t}\n\n\t/**\n\t * Formats an ICU message syntax string using `values` for placeholder data\n\t * and any currently-registered type handlers.\n\t *\n\t * @type {(message: string, values?: FormatValues) => string}\n\t */\n\tformat = memoize((message, values = {}) => {\n\n\t\treturn this.process(message, values).flat(Infinity).join('');\n\t});\n\n\t/**\n\t * Process an ICU message syntax string using `values` for placeholder data\n\t * and any currently-registered type handlers. The result of this method is\n\t * an array of the component parts after they have been processed in turn by\n\t * their own type handlers. This raw output is useful for other renderers,\n\t * eg: React where components can be used instead of being forced to return\n\t * raw strings.\n\t *\n\t * This method is used by {@link MessageFormatter#format} where it acts as a\n\t * string renderer.\n\t *\n\t * @param {string} message\n\t * @param {FormatValues} [values]\n\t * @return {any[]}\n\t */\n\tprocess(message, values = {}) {\n\n\t\tif (!message) {\n\t\t\treturn [];\n\t\t}\n\n\t\tlet blockStartIndex = message.indexOf('{');\n\t\tif (blockStartIndex !== -1) {\n\t\t\tlet blockEndIndex = findClosingBracket(message, blockStartIndex);\n\t\t\tif (blockEndIndex !== -1) {\n\t\t\t\tlet block = message.substring(blockStartIndex, blockEndIndex + 1);\n\t\t\t\tif (block) {\n\t\t\t\t\tlet result = [];\n\t\t\t\t\tlet head = message.substring(0, blockStartIndex);\n\t\t\t\t\tif (head) {\n\t\t\t\t\t\tresult.push(head);\n\t\t\t\t\t}\n\t\t\t\t\tlet [key, type, format] = splitFormattedArgument(block);\n\t\t\t\t\tlet body = values[key];\n\t\t\t\t\tif (body === null || body === undefined) {\n\t\t\t\t\t\tbody = '';\n\t\t\t\t\t}\n\t\t\t\t\tlet typeHandler = type && this.typeHandlers[type];\n\t\t\t\t\tresult.push(typeHandler ?\n\t\t\t\t\t\ttypeHandler(body, format, this.locale, values, this.process.bind(this)) :\n\t\t\t\t\t\tbody);\n\t\t\t\t\tlet tail = message.substring(blockEndIndex + 1);\n\t\t\t\t\tif (tail) {\n\t\t\t\t\t\tresult.push(this.process(tail, values));\n\t\t\t\t\t}\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new Error(`Unbalanced curly braces in string: \"${message}\"`);\n\t\t\t}\n\t\t}\n\t\treturn [message];\n\t}\n}\n","/*\n * Copyright 2019, Emanuel Rabina (http://www.ultraq.net.nz/)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {parseCases} from './utilities.js';\n\nlet pluralFormatter;\n\nlet keyCounter = 0;\n\n// All the special keywords that can be used in `plural` blocks for the various branches\nconst ONE = 'one';\nconst OTHER = 'other';\n\n/**\n * @private\n * @param {string} caseBody\n * @param {number} value\n * @return {{caseBody: string, numberValues: object}}\n */\nfunction replaceNumberSign(caseBody, value) {\n\tlet i = 0;\n\tlet output = '';\n\tlet numBraces = 0;\n\tconst numberValues = {};\n\n\twhile (i < caseBody.length) {\n\t\tif (caseBody[i] === '#' && !numBraces) {\n\t\t\tlet keyParam = `__hashToken${keyCounter++}`;\n\t\t\toutput += `{${keyParam}, number}`;\n\t\t\tnumberValues[keyParam] = value;\n\t\t}\n\t\telse {\n\t\t\toutput += caseBody[i];\n\t\t}\n\n\t\tif (caseBody[i] === '{') {\n\t\t\tnumBraces++;\n\t\t}\n\t\telse if (caseBody[i] === '}') {\n\t\t\tnumBraces--;\n\t\t}\n\n\t\ti++;\n\t}\n\n\treturn {\n\t\tcaseBody: output,\n\t\tnumberValues\n\t};\n}\n\n/**\n * Handler for `plural` statements within ICU message syntax strings. Returns\n * a formatted string for the branch that closely matches the current value.\n *\n * See https://formatjs.io/docs/core-concepts/icu-syntax#plural-format for more\n * details on how the `plural` statement works.\n *\n * @param {string} value\n * @param {string} matches\n * @param {string} locale\n * @param {import('./MessageFormatter.js').FormatValues} values\n * @param {import('./MessageFormatter.js').ProcessFunction} process\n * @return {any | any[]}\n */\nexport default function pluralTypeHandler(value, matches, locale, values, process) {\n\tconst {args, cases} = parseCases(matches);\n\n\tlet intValue = parseInt(value);\n\n\targs.forEach((arg) => {\n\t\tif (arg.startsWith('offset:')) {\n\t\t\tintValue -= parseInt(arg.slice('offset:'.length));\n\t\t}\n\t});\n\n\tconst keywordPossibilities = [];\n\n\tif ('PluralRules' in Intl) {\n\t\t// Effectively memoize because instantiation of `Int.*` objects is expensive.\n\t\tif (pluralFormatter === undefined || pluralFormatter.resolvedOptions().locale !== locale) {\n\t\t\tpluralFormatter = new Intl.PluralRules(locale);\n\t\t}\n\n\t\tconst pluralKeyword = pluralFormatter.select(intValue);\n\n\t\t// Other is always added last with least priority, so we don't want to add it here.\n\t\tif (pluralKeyword !== OTHER) {\n\t\t\tkeywordPossibilities.push(pluralKeyword);\n\t\t}\n\t}\n\tif (intValue === 1) {\n\t\tkeywordPossibilities.push(ONE);\n\t}\n\tkeywordPossibilities.push(`=${intValue}`, OTHER);\n\n\tfor (let i = 0; i < keywordPossibilities.length; i++) {\n\t\tconst keyword = keywordPossibilities[i];\n\t\tif (keyword in cases) {\n\t\t\tconst {caseBody, numberValues} = replaceNumberSign(cases[keyword], intValue);\n\t\t\treturn process(caseBody, {\n\t\t\t\t...values,\n\t\t\t\t...numberValues\n\t\t\t});\n\t\t}\n\t}\n\n\treturn value;\n}\n","/*\n * Copyright 2019, Emanuel Rabina (http://www.ultraq.net.nz/)\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {parseCases} from './utilities.js';\n\nconst OTHER = 'other';\n\n/**\n * Handler for `select` statements within ICU message syntax strings. Returns\n * a formatted string for the branch that closely matches the current value.\n *\n * See https://formatjs.io/docs/core-concepts/icu-syntax#select-format for more\n * details on how the `select` statement works.\n *\n * @param {string} value\n * @param {string} matches\n * @param {string} locale\n * @param {import('./MessageFormatter.js').FormatValues} values\n * @param {import('./MessageFormatter.js').ProcessFunction} process\n * @return {any | any[]}\n */\nexport default function selectTypeHandler(value, matches, locale, values, process) {\n\tconst {cases} = parseCases(matches);\n\n\tif (value in cases) {\n\t\treturn process(cases[value], values);\n\t}\n\telse if (OTHER in cases) {\n\t\treturn process(cases[OTHER], values);\n\t}\n\n\treturn value;\n}\n"],"names":["OTHER"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultraq/icu-message-formatter",
3
- "version": "0.14.2",
3
+ "version": "0.15.0-beta.1",
4
4
  "description": "Format ICU message syntax strings from supplied parameters and your own configurable types",
5
5
  "author": "Emanuel Rabina <emanuelrabina@gmail.com> (http://www.ultraq.net.nz/)",
6
6
  "license": "Apache-2.0",
@@ -21,12 +21,12 @@
21
21
  "types": "dist/icu-message-formatter.d.ts",
22
22
  "exports": {
23
23
  "import": {
24
- "default": "./dist/icu-message-formatter.js",
25
- "types": "./dist/icu-message-formatter.d.ts"
24
+ "types": "./dist/icu-message-formatter.d.ts",
25
+ "default": "./dist/icu-message-formatter.js"
26
26
  },
27
27
  "require": {
28
- "default": "./dist/icu-message-formatter.cjs",
29
- "types": "./dist/icu-message-formatter.d.cts"
28
+ "types": "./dist/icu-message-formatter.d.ts",
29
+ "default": "./dist/icu-message-formatter.cjs"
30
30
  }
31
31
  },
32
32
  "files": [
@@ -36,37 +36,29 @@
36
36
  "sideEffects": false,
37
37
  "scripts": {
38
38
  "lint": "eslint \"**/*.js\"",
39
- "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest",
39
+ "test": "vitest run",
40
40
  "build": "npm run build:dist && npm run build:browser && npm run build:dts",
41
- "build:dist": "rollup --config",
42
- "build:browser": "rollup --config rollup.config.browser.js",
43
- "build:dts": "tsc --allowJs --declaration --emitDeclarationOnly dist/icu-message-formatter.js dist/icu-message-formatter.cjs",
41
+ "build:dist": "vite build",
42
+ "build:browser": "vite build --config vite.config.browser.js",
43
+ "build:dts": "tsup source/IcuMessageFormatter.js --dts-only && mv dist/IcuMessageFormatter.d.cts dist/icu-message-formatter.d.ts",
44
44
  "prepublishOnly": "npm run build"
45
45
  },
46
46
  "dependencies": {
47
- "@babel/runtime": "^7.22.15",
48
- "@ultraq/function-utils": "^0.5.1"
47
+ "@ultraq/function-utils": "^0.5.2"
49
48
  },
50
49
  "devDependencies": {
51
- "@babel/core": "^7.22.15",
52
- "@babel/plugin-transform-runtime": "^7.22.15",
53
- "@babel/preset-env": "^7.22.15",
54
50
  "@formatjs/intl-locale": "^3.3.2",
55
51
  "@formatjs/intl-numberformat": "^8.7.0",
56
- "@jest/globals": "^29.7.0",
57
- "@rollup/plugin-babel": "^6.0.3",
58
- "@rollup/plugin-commonjs": "^25.0.4",
59
- "@rollup/plugin-node-resolve": "^15.2.1",
60
- "@rollup/plugin-terser": "^0.4.3",
61
- "@types/jest": "^29.5.4",
52
+ "@vitest/coverage-v8": "^2.1.8",
62
53
  "cross-env": "^7.0.3",
63
- "eslint": "^8.48.0",
64
- "eslint-config-ultraq": "^3.1.0",
65
- "eslint-plugin-import": "^2.28.1",
66
- "eslint-plugin-jsdoc": "^46.5.1",
67
- "jest": "^29.6.4",
68
- "rollup": "^4.9.1",
69
- "typescript": "^5.2.2"
54
+ "eslint": "^9.17.0",
55
+ "eslint-config-ultraq": "^4.0.0",
56
+ "globals": "^15.14.0",
57
+ "jsdom": "^25.0.1",
58
+ "tsup": "^8.3.5",
59
+ "typescript": "^5.2.2",
60
+ "vite": "^6.0.6",
61
+ "vitest": "^2.1.8"
70
62
  },
71
63
  "engines": {
72
64
  "node": ">=18"