globalize-rpk 1.7.1 → 1.7.2
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/CONTRIBUTING.md +5 -0
- package/README.md +818 -0
- package/{globalize → dist/globalize}/currency.js +3 -3
- package/{globalize → dist/globalize}/date.js +3 -3
- package/{globalize → dist/globalize}/message.js +2 -2
- package/{globalize → dist/globalize}/number.js +3 -3
- package/{globalize → dist/globalize}/plural.js +3 -3
- package/{globalize → dist/globalize}/relative-time.js +3 -3
- package/{globalize → dist/globalize}/unit.js +0 -0
- package/dist/globalize-runtime/currency.js +183 -0
- package/dist/globalize-runtime/date.js +1657 -0
- package/dist/globalize-runtime/message.js +120 -0
- package/dist/globalize-runtime/number.js +919 -0
- package/dist/globalize-runtime/plural.js +90 -0
- package/dist/globalize-runtime/relative-time.js +120 -0
- package/dist/globalize-runtime/unit.js +132 -0
- package/{globalize → dist}/globalize-runtime.js +0 -0
- package/{globalize → dist}/globalize.js +2 -2
- package/{node-main.js → dist/node-main.js} +0 -0
- package/doc/api/core/constructor.md +28 -0
- package/doc/api/core/load.md +96 -0
- package/doc/api/core/locale.md +43 -0
- package/doc/api/currency/currency-formatter.md +196 -0
- package/doc/api/currency/currency-to-parts-formatter.md +117 -0
- package/doc/api/date/date-formatter.md +203 -0
- package/doc/api/date/date-parser.md +60 -0
- package/doc/api/date/date-to-parts-formatter.md +176 -0
- package/doc/api/date/load-iana-time-zone.md +29 -0
- package/doc/api/message/load-messages.md +105 -0
- package/doc/api/message/message-formatter.md +208 -0
- package/doc/api/number/number-formatter.md +202 -0
- package/doc/api/number/number-parser.md +130 -0
- package/doc/api/number/number-to-parts-formatter.md +140 -0
- package/doc/api/plural/plural-generator.md +84 -0
- package/doc/api/relative-time/relative-time-formatter.md +60 -0
- package/doc/api/unit/unit-formatter.md +72 -0
- package/doc/blog-post/2017-07-xx-1.3.0-announcement.md +177 -0
- package/doc/cldr.md +114 -0
- package/doc/error/e-default-locale-not-defined.md +9 -0
- package/doc/error/e-invalid-cldr.md +14 -0
- package/doc/error/e-invalid-par-type.md +12 -0
- package/doc/error/e-invalid-par-value.md +11 -0
- package/doc/error/e-missing-cldr.md +11 -0
- package/doc/error/e-missing-parameter.md +10 -0
- package/doc/error/e-missing-plural-module.md +9 -0
- package/doc/error/e-par-missing-key.md +11 -0
- package/doc/error/e-par-out-of-range.md +13 -0
- package/doc/error/e-unsupported.md +10 -0
- package/doc/migrating-from-0.x.md +64 -0
- package/examples/amd-bower/.bowerrc +7 -0
- package/examples/amd-bower/README.md +65 -0
- package/examples/amd-bower/bower.json +13 -0
- package/examples/amd-bower/index.html +46 -0
- package/examples/amd-bower/main.js +141 -0
- package/examples/amd-bower/messages/en.json +12 -0
- package/examples/amd-bower/package.json +14 -0
- package/examples/app-npm-webpack/README.md +74 -0
- package/examples/app-npm-webpack/app/index.js +89 -0
- package/examples/app-npm-webpack/index-template.html +71 -0
- package/examples/app-npm-webpack/messages/ar.json +25 -0
- package/examples/app-npm-webpack/messages/de.json +21 -0
- package/examples/app-npm-webpack/messages/en.json +21 -0
- package/examples/app-npm-webpack/messages/es.json +21 -0
- package/examples/app-npm-webpack/messages/pt.json +21 -0
- package/examples/app-npm-webpack/messages/ru.json +23 -0
- package/examples/app-npm-webpack/messages/zh.json +20 -0
- package/examples/app-npm-webpack/package.json +17 -0
- package/examples/app-npm-webpack/webpack-config.js +63 -0
- package/examples/globalize-compiler/README.md +45 -0
- package/examples/globalize-compiler/app.js +58 -0
- package/examples/globalize-compiler/development.html +121 -0
- package/examples/globalize-compiler/messages.json +12 -0
- package/examples/globalize-compiler/package.json +15 -0
- package/examples/globalize-compiler/production.html +75 -0
- package/examples/node-npm/README.md +57 -0
- package/examples/node-npm/main.js +65 -0
- package/examples/node-npm/messages/en.json +12 -0
- package/examples/node-npm/package.json +10 -0
- package/examples/plain-javascript/README.md +81 -0
- package/examples/plain-javascript/index.html +445 -0
- package/package.json +27 -4
@@ -0,0 +1,919 @@
|
|
1
|
+
/**
|
2
|
+
* Globalize Runtime v1.7.0
|
3
|
+
*
|
4
|
+
* https://github.com/globalizejs/globalize
|
5
|
+
*
|
6
|
+
* Copyright OpenJS Foundation and other contributors
|
7
|
+
* Released under the MIT license
|
8
|
+
* https://jquery.org/license
|
9
|
+
*
|
10
|
+
* Date: 2021-08-02T11:53Z
|
11
|
+
*/
|
12
|
+
/*!
|
13
|
+
* Globalize Runtime v1.7.0 2021-08-02T11:53Z Released under the MIT license
|
14
|
+
* http://git.io/TrdQbw
|
15
|
+
*/
|
16
|
+
(function( root, factory ) {
|
17
|
+
|
18
|
+
"use strict";
|
19
|
+
|
20
|
+
// UMD returnExports
|
21
|
+
if ( typeof define === "function" && define.amd ) {
|
22
|
+
|
23
|
+
// AMD
|
24
|
+
define([
|
25
|
+
"../globalize-runtime"
|
26
|
+
], factory );
|
27
|
+
} else if ( typeof exports === "object" ) {
|
28
|
+
|
29
|
+
// Node, CommonJS
|
30
|
+
module.exports = factory( require( "../globalize-runtime" ) );
|
31
|
+
} else {
|
32
|
+
|
33
|
+
// Extend global
|
34
|
+
factory( root.Globalize );
|
35
|
+
}
|
36
|
+
}(this, function( Globalize ) {
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
var createError = Globalize._createError,
|
41
|
+
partsJoin = Globalize._partsJoin,
|
42
|
+
partsPush = Globalize._partsPush,
|
43
|
+
regexpEscape = Globalize._regexpEscape,
|
44
|
+
runtimeKey = Globalize._runtimeKey,
|
45
|
+
stringPad = Globalize._stringPad,
|
46
|
+
validateParameterType = Globalize._validateParameterType,
|
47
|
+
validateParameterPresence = Globalize._validateParameterPresence,
|
48
|
+
validateParameterTypeString = Globalize._validateParameterTypeString;
|
49
|
+
|
50
|
+
|
51
|
+
var createErrorUnsupportedFeature = function( feature ) {
|
52
|
+
return createError( "E_UNSUPPORTED", "Unsupported {feature}.", {
|
53
|
+
feature: feature
|
54
|
+
});
|
55
|
+
};
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
var validateParameterTypeNumber = function( value, name ) {
|
61
|
+
validateParameterType(
|
62
|
+
value,
|
63
|
+
name,
|
64
|
+
value === undefined || typeof value === "number",
|
65
|
+
"Number"
|
66
|
+
);
|
67
|
+
};
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
/**
|
73
|
+
* EBNF representation:
|
74
|
+
*
|
75
|
+
* compact_pattern_re = prefix?
|
76
|
+
* number_pattern_re
|
77
|
+
* suffix?
|
78
|
+
*
|
79
|
+
* number_pattern_re = 0+
|
80
|
+
*
|
81
|
+
* Regexp groups:
|
82
|
+
*
|
83
|
+
* 0: compact_pattern_re
|
84
|
+
* 1: prefix
|
85
|
+
* 2: number_pattern_re (the number pattern to use in compact mode)
|
86
|
+
* 3: suffix
|
87
|
+
*/
|
88
|
+
var numberCompactPatternRe = ( /^([^0]*)(0+)([^0]*)$/ );
|
89
|
+
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
/**
|
94
|
+
* goupingSeparator( number, primaryGroupingSize, secondaryGroupingSize )
|
95
|
+
*
|
96
|
+
* @number [Number].
|
97
|
+
*
|
98
|
+
* @primaryGroupingSize [Number]
|
99
|
+
*
|
100
|
+
* @secondaryGroupingSize [Number]
|
101
|
+
*
|
102
|
+
* Return the formatted number with group separator.
|
103
|
+
*/
|
104
|
+
var numberFormatGroupingSeparator = function( number, primaryGroupingSize, secondaryGroupingSize ) {
|
105
|
+
var index,
|
106
|
+
currentGroupingSize = primaryGroupingSize,
|
107
|
+
ret = "",
|
108
|
+
sep = ",",
|
109
|
+
switchToSecondary = secondaryGroupingSize ? true : false;
|
110
|
+
|
111
|
+
number = String( number ).split( "." );
|
112
|
+
index = number[ 0 ].length;
|
113
|
+
|
114
|
+
while ( index > currentGroupingSize ) {
|
115
|
+
ret = number[ 0 ].slice( index - currentGroupingSize, index ) +
|
116
|
+
( ret.length ? sep : "" ) + ret;
|
117
|
+
index -= currentGroupingSize;
|
118
|
+
if ( switchToSecondary ) {
|
119
|
+
currentGroupingSize = secondaryGroupingSize;
|
120
|
+
switchToSecondary = false;
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
number[ 0 ] = number[ 0 ].slice( 0, index ) + ( ret.length ? sep : "" ) + ret;
|
125
|
+
return number.join( "." );
|
126
|
+
};
|
127
|
+
|
128
|
+
|
129
|
+
|
130
|
+
|
131
|
+
/**
|
132
|
+
* integerFractionDigits( number, minimumIntegerDigits, minimumFractionDigits,
|
133
|
+
* maximumFractionDigits, round, roundIncrement )
|
134
|
+
*
|
135
|
+
* @number [Number]
|
136
|
+
*
|
137
|
+
* @minimumIntegerDigits [Number]
|
138
|
+
*
|
139
|
+
* @minimumFractionDigits [Number]
|
140
|
+
*
|
141
|
+
* @maximumFractionDigits [Number]
|
142
|
+
*
|
143
|
+
* @round [Function]
|
144
|
+
*
|
145
|
+
* @roundIncrement [Function]
|
146
|
+
*
|
147
|
+
* Return the formatted integer and fraction digits.
|
148
|
+
*/
|
149
|
+
var numberFormatIntegerFractionDigits = function( number, minimumIntegerDigits, minimumFractionDigits, maximumFractionDigits, round,
|
150
|
+
roundIncrement ) {
|
151
|
+
|
152
|
+
// Fraction
|
153
|
+
if ( maximumFractionDigits ) {
|
154
|
+
|
155
|
+
// Rounding
|
156
|
+
if ( roundIncrement ) {
|
157
|
+
number = round( number, roundIncrement );
|
158
|
+
|
159
|
+
// Maximum fraction digits
|
160
|
+
} else {
|
161
|
+
number = round( number, { exponent: -maximumFractionDigits } );
|
162
|
+
}
|
163
|
+
|
164
|
+
} else {
|
165
|
+
number = round( number );
|
166
|
+
}
|
167
|
+
|
168
|
+
number = String( number );
|
169
|
+
|
170
|
+
// Maximum integer digits (post string phase)
|
171
|
+
if ( maximumFractionDigits && /e-/.test( number ) ) {
|
172
|
+
|
173
|
+
// Use toFixed( maximumFractionDigits ) to make sure small numbers like 1e-7 are
|
174
|
+
// displayed using plain digits instead of scientific notation.
|
175
|
+
// 1: Remove leading decimal zeros.
|
176
|
+
// 2: Remove leading decimal separator.
|
177
|
+
// Note: String() is still preferred so it doesn't mess up with a number precision
|
178
|
+
// unnecessarily, e.g., (123456789.123).toFixed(10) === "123456789.1229999959",
|
179
|
+
// String(123456789.123) === "123456789.123".
|
180
|
+
number = ( +number ).toFixed( maximumFractionDigits )
|
181
|
+
.replace( /0+$/, "" ) /* 1 */
|
182
|
+
.replace( /\.$/, "" ); /* 2 */
|
183
|
+
}
|
184
|
+
|
185
|
+
// Minimum fraction digits (post string phase)
|
186
|
+
if ( minimumFractionDigits ) {
|
187
|
+
number = number.split( "." );
|
188
|
+
number[ 1 ] = stringPad( number[ 1 ] || "", minimumFractionDigits, true );
|
189
|
+
number = number.join( "." );
|
190
|
+
}
|
191
|
+
|
192
|
+
// Minimum integer digits
|
193
|
+
if ( minimumIntegerDigits ) {
|
194
|
+
number = number.split( "." );
|
195
|
+
number[ 0 ] = stringPad( number[ 0 ], minimumIntegerDigits );
|
196
|
+
number = number.join( "." );
|
197
|
+
}
|
198
|
+
|
199
|
+
return number;
|
200
|
+
};
|
201
|
+
|
202
|
+
|
203
|
+
|
204
|
+
|
205
|
+
/**
|
206
|
+
* toPrecision( number, precision, round )
|
207
|
+
*
|
208
|
+
* @number (Number)
|
209
|
+
*
|
210
|
+
* @precision (Number) significant figures precision (not decimal precision).
|
211
|
+
*
|
212
|
+
* @round (Function)
|
213
|
+
*
|
214
|
+
* Return number.toPrecision( precision ) using the given round function.
|
215
|
+
*/
|
216
|
+
var numberToPrecision = function( number, precision, round ) {
|
217
|
+
var roundOrder;
|
218
|
+
|
219
|
+
if ( number === 0 ) { // Fix #706
|
220
|
+
return number;
|
221
|
+
}
|
222
|
+
|
223
|
+
roundOrder = Math.ceil( Math.log( Math.abs( number ) ) / Math.log( 10 ) );
|
224
|
+
roundOrder -= precision;
|
225
|
+
|
226
|
+
return round( number, { exponent: roundOrder } );
|
227
|
+
};
|
228
|
+
|
229
|
+
|
230
|
+
|
231
|
+
|
232
|
+
/**
|
233
|
+
* toPrecision( number, minimumSignificantDigits, maximumSignificantDigits, round )
|
234
|
+
*
|
235
|
+
* @number [Number]
|
236
|
+
*
|
237
|
+
* @minimumSignificantDigits [Number]
|
238
|
+
*
|
239
|
+
* @maximumSignificantDigits [Number]
|
240
|
+
*
|
241
|
+
* @round [Function]
|
242
|
+
*
|
243
|
+
* Return the formatted significant digits number.
|
244
|
+
*/
|
245
|
+
var numberFormatSignificantDigits = function( number, minimumSignificantDigits, maximumSignificantDigits, round ) {
|
246
|
+
var atMinimum, atMaximum;
|
247
|
+
|
248
|
+
// Sanity check.
|
249
|
+
if ( minimumSignificantDigits > maximumSignificantDigits ) {
|
250
|
+
maximumSignificantDigits = minimumSignificantDigits;
|
251
|
+
}
|
252
|
+
|
253
|
+
atMinimum = numberToPrecision( number, minimumSignificantDigits, round );
|
254
|
+
atMaximum = numberToPrecision( number, maximumSignificantDigits, round );
|
255
|
+
|
256
|
+
// Use atMaximum only if it has more significant digits than atMinimum.
|
257
|
+
number = +atMinimum === +atMaximum ? atMinimum : atMaximum;
|
258
|
+
|
259
|
+
// Expand integer numbers, eg. 123e5 to 12300.
|
260
|
+
number = ( +number ).toString( 10 );
|
261
|
+
|
262
|
+
if ( ( /e/ ).test( number ) ) {
|
263
|
+
throw createErrorUnsupportedFeature({
|
264
|
+
feature: "integers out of (1e21, 1e-7)"
|
265
|
+
});
|
266
|
+
}
|
267
|
+
|
268
|
+
// Add trailing zeros if necessary.
|
269
|
+
if ( minimumSignificantDigits - number.replace( /^0+|\./g, "" ).length > 0 ) {
|
270
|
+
number = number.split( "." );
|
271
|
+
number[ 1 ] = stringPad( number[ 1 ] || "", minimumSignificantDigits - number[ 0 ].replace( /^0+/, "" ).length, true );
|
272
|
+
number = number.join( "." );
|
273
|
+
}
|
274
|
+
|
275
|
+
return number;
|
276
|
+
};
|
277
|
+
|
278
|
+
|
279
|
+
|
280
|
+
|
281
|
+
var numberSymbolName = {
|
282
|
+
".": "decimal",
|
283
|
+
",": "group",
|
284
|
+
"%": "percentSign",
|
285
|
+
"+": "plusSign",
|
286
|
+
"-": "minusSign",
|
287
|
+
"E": "exponential",
|
288
|
+
"\u2030": "perMille"
|
289
|
+
};
|
290
|
+
|
291
|
+
|
292
|
+
|
293
|
+
|
294
|
+
/**
|
295
|
+
* removeLiteralQuotes( string )
|
296
|
+
*
|
297
|
+
* Return:
|
298
|
+
* - `'` if input string is `''`.
|
299
|
+
* - `o'clock` if input string is `'o''clock'`.
|
300
|
+
* - `foo` if input string is `foo`, i.e., return the same value in case it isn't a single-quoted
|
301
|
+
* string.
|
302
|
+
*/
|
303
|
+
var removeLiteralQuotes = function( string ) {
|
304
|
+
if ( string[ 0 ] + string[ string.length - 1 ] !== "''" ) {
|
305
|
+
return string;
|
306
|
+
}
|
307
|
+
if ( string === "''" ) {
|
308
|
+
return "'";
|
309
|
+
}
|
310
|
+
return string.replace( /''/g, "'" ).slice( 1, -1 );
|
311
|
+
};
|
312
|
+
|
313
|
+
|
314
|
+
|
315
|
+
|
316
|
+
/**
|
317
|
+
* format( number, properties )
|
318
|
+
*
|
319
|
+
* @number [Number].
|
320
|
+
*
|
321
|
+
* @properties [Object] Output of number/format-properties.
|
322
|
+
*
|
323
|
+
* Return the formatted number.
|
324
|
+
* ref: http://www.unicode.org/reports/tr35/tr35-numbers.html
|
325
|
+
*/
|
326
|
+
var numberFormat = function( number, properties, pluralGenerator ) {
|
327
|
+
var aux, compactMap, infinitySymbol, maximumFractionDigits, maximumSignificantDigits,
|
328
|
+
minimumFractionDigits, minimumIntegerDigits, minimumSignificantDigits, nanSymbol,
|
329
|
+
nuDigitsMap, prefix, primaryGroupingSize, pattern, round, roundIncrement,
|
330
|
+
secondaryGroupingSize, stringToParts, suffix, symbolMap;
|
331
|
+
|
332
|
+
minimumIntegerDigits = properties[ 2 ];
|
333
|
+
minimumFractionDigits = properties[ 3 ];
|
334
|
+
maximumFractionDigits = properties[ 4 ];
|
335
|
+
minimumSignificantDigits = properties[ 5 ];
|
336
|
+
maximumSignificantDigits = properties[ 6 ];
|
337
|
+
roundIncrement = properties[ 7 ];
|
338
|
+
primaryGroupingSize = properties[ 8 ];
|
339
|
+
secondaryGroupingSize = properties[ 9 ];
|
340
|
+
round = properties[ 15 ];
|
341
|
+
infinitySymbol = properties[ 16 ];
|
342
|
+
nanSymbol = properties[ 17 ];
|
343
|
+
symbolMap = properties[ 18 ];
|
344
|
+
nuDigitsMap = properties[ 19 ];
|
345
|
+
compactMap = properties[ 20 ];
|
346
|
+
|
347
|
+
// NaN
|
348
|
+
if ( isNaN( number ) ) {
|
349
|
+
return [ { type: "nan", value: nanSymbol } ];
|
350
|
+
}
|
351
|
+
|
352
|
+
if ( number < 0 ) {
|
353
|
+
pattern = properties[ 12 ];
|
354
|
+
prefix = properties[ 13 ];
|
355
|
+
suffix = properties[ 14 ];
|
356
|
+
} else {
|
357
|
+
pattern = properties[ 11 ];
|
358
|
+
prefix = properties[ 0 ];
|
359
|
+
suffix = properties[ 10 ];
|
360
|
+
}
|
361
|
+
|
362
|
+
// For prefix, suffix, and number parts.
|
363
|
+
stringToParts = function( string ) {
|
364
|
+
var numberType = "integer",
|
365
|
+
parts = [];
|
366
|
+
|
367
|
+
// TODO Move the tokenization of all parts that don't depend on number into
|
368
|
+
// format-properties.
|
369
|
+
string.replace( /('([^']|'')+'|'')|./g, function( character, literal ) {
|
370
|
+
|
371
|
+
// Literals
|
372
|
+
if ( literal ) {
|
373
|
+
partsPush( parts, "literal", removeLiteralQuotes( literal ) );
|
374
|
+
return;
|
375
|
+
}
|
376
|
+
|
377
|
+
// Currency symbol
|
378
|
+
if ( character === "\u00A4" ) {
|
379
|
+
partsPush( parts, "currency", character );
|
380
|
+
return;
|
381
|
+
}
|
382
|
+
|
383
|
+
// Symbols
|
384
|
+
character = character.replace( /[.,\-+E%\u2030]/, function( symbol ) {
|
385
|
+
if ( symbol === "." ) {
|
386
|
+
numberType = "fraction";
|
387
|
+
}
|
388
|
+
partsPush( parts, numberSymbolName[ symbol ], symbolMap[ symbol ] );
|
389
|
+
|
390
|
+
// "Erase" handled character.
|
391
|
+
return "";
|
392
|
+
});
|
393
|
+
|
394
|
+
// Number
|
395
|
+
character = character.replace( /[0-9]/, function( digit ) {
|
396
|
+
|
397
|
+
// Numbering system
|
398
|
+
if ( nuDigitsMap ) {
|
399
|
+
digit = nuDigitsMap[ +digit ];
|
400
|
+
}
|
401
|
+
partsPush( parts, numberType, digit );
|
402
|
+
|
403
|
+
// "Erase" handled character.
|
404
|
+
return "";
|
405
|
+
});
|
406
|
+
|
407
|
+
// Etc
|
408
|
+
character.replace( /./, function( etc ) {
|
409
|
+
partsPush( parts, "literal", etc );
|
410
|
+
});
|
411
|
+
});
|
412
|
+
return parts;
|
413
|
+
};
|
414
|
+
|
415
|
+
prefix = stringToParts( prefix );
|
416
|
+
suffix = stringToParts( suffix );
|
417
|
+
|
418
|
+
// Infinity
|
419
|
+
if ( !isFinite( number ) ) {
|
420
|
+
return prefix.concat(
|
421
|
+
{ type: "infinity", value: infinitySymbol },
|
422
|
+
suffix
|
423
|
+
);
|
424
|
+
}
|
425
|
+
|
426
|
+
// Percent
|
427
|
+
if ( pattern.indexOf( "%" ) !== -1 ) {
|
428
|
+
number *= 100;
|
429
|
+
|
430
|
+
// Per mille
|
431
|
+
} else if ( pattern.indexOf( "\u2030" ) !== -1 ) {
|
432
|
+
number *= 1000;
|
433
|
+
}
|
434
|
+
|
435
|
+
var compactPattern, compactDigits, compactProperties, divisor, numberExponent, pluralForm;
|
436
|
+
|
437
|
+
// Compact mode: initial number digit processing
|
438
|
+
if ( compactMap ) {
|
439
|
+
numberExponent = Math.abs( Math.floor( number ) ).toString().length - 1;
|
440
|
+
numberExponent = Math.min( numberExponent, compactMap.maxExponent );
|
441
|
+
|
442
|
+
// Use default plural form to perform initial decimal shift
|
443
|
+
if ( numberExponent >= 3 ) {
|
444
|
+
compactPattern = compactMap[ numberExponent ] && compactMap[ numberExponent ].other;
|
445
|
+
}
|
446
|
+
|
447
|
+
if ( compactPattern === "0" ) {
|
448
|
+
compactPattern = null;
|
449
|
+
} else if ( compactPattern ) {
|
450
|
+
compactDigits = compactPattern.split( "0" ).length - 1;
|
451
|
+
divisor = numberExponent - ( compactDigits - 1 );
|
452
|
+
number = number / Math.pow( 10, divisor );
|
453
|
+
}
|
454
|
+
}
|
455
|
+
|
456
|
+
// Significant digit format
|
457
|
+
if ( !isNaN( minimumSignificantDigits * maximumSignificantDigits ) ) {
|
458
|
+
number = numberFormatSignificantDigits( number, minimumSignificantDigits,
|
459
|
+
maximumSignificantDigits, round );
|
460
|
+
|
461
|
+
// Integer and fractional format
|
462
|
+
} else {
|
463
|
+
number = numberFormatIntegerFractionDigits( number, minimumIntegerDigits,
|
464
|
+
minimumFractionDigits, maximumFractionDigits, round, roundIncrement );
|
465
|
+
}
|
466
|
+
|
467
|
+
// Compact mode: apply formatting
|
468
|
+
if ( compactMap && compactPattern ) {
|
469
|
+
|
470
|
+
// Get plural form after possible roundings
|
471
|
+
pluralForm = pluralGenerator ? pluralGenerator( +number ) : "other";
|
472
|
+
|
473
|
+
compactPattern = compactMap[ numberExponent ][ pluralForm ] || compactPattern;
|
474
|
+
compactProperties = compactPattern.match( numberCompactPatternRe );
|
475
|
+
|
476
|
+
// TODO Move the tokenization of all parts that don't depend on number into
|
477
|
+
// format-properties.
|
478
|
+
aux = function( string ) {
|
479
|
+
var parts = [];
|
480
|
+
string.replace( /(\s+)|([^\s0]+)/g, function( _garbage, space, compact ) {
|
481
|
+
|
482
|
+
// Literals
|
483
|
+
if ( space ) {
|
484
|
+
partsPush( parts, "literal", space );
|
485
|
+
return;
|
486
|
+
}
|
487
|
+
|
488
|
+
// Compact value
|
489
|
+
if ( compact ) {
|
490
|
+
partsPush( parts, "compact", compact );
|
491
|
+
return;
|
492
|
+
}
|
493
|
+
});
|
494
|
+
return parts;
|
495
|
+
};
|
496
|
+
|
497
|
+
// update prefix/suffix with compact prefix/suffix
|
498
|
+
prefix = prefix.concat( aux( compactProperties[ 1 ] ) );
|
499
|
+
suffix = aux( compactProperties[ 3 ] ).concat( suffix );
|
500
|
+
}
|
501
|
+
|
502
|
+
// Remove the possible number minus sign
|
503
|
+
number = number.replace( /^-/, "" );
|
504
|
+
|
505
|
+
// Grouping separators
|
506
|
+
if ( primaryGroupingSize ) {
|
507
|
+
number = numberFormatGroupingSeparator( number, primaryGroupingSize,
|
508
|
+
secondaryGroupingSize );
|
509
|
+
}
|
510
|
+
|
511
|
+
// Scientific notation
|
512
|
+
// TODO implement here
|
513
|
+
|
514
|
+
// Padding/'([^']|'')+'|''|[.,\-+E%\u2030]/g
|
515
|
+
// TODO implement here
|
516
|
+
|
517
|
+
return prefix.concat(
|
518
|
+
stringToParts( number ),
|
519
|
+
suffix
|
520
|
+
);
|
521
|
+
};
|
522
|
+
|
523
|
+
|
524
|
+
|
525
|
+
|
526
|
+
var numberFormatterFn = function( numberToPartsFormatter ) {
|
527
|
+
return function numberFormatter( value ) {
|
528
|
+
return partsJoin( numberToPartsFormatter( value ));
|
529
|
+
};
|
530
|
+
};
|
531
|
+
|
532
|
+
|
533
|
+
|
534
|
+
|
535
|
+
/**
|
536
|
+
* Generated by:
|
537
|
+
*
|
538
|
+
* var regenerate = require( "regenerate" );
|
539
|
+
* var formatSymbols = require( "@unicode/unicode-13.0.0/General_Category/Format/symbols" );
|
540
|
+
* regenerate().add( formatSymbols ).toString();
|
541
|
+
*
|
542
|
+
* https://github.com/mathiasbynens/regenerate
|
543
|
+
* https://github.com/node-unicode/unicode-13.0.0
|
544
|
+
*/
|
545
|
+
var regexpCfG = /[\xAD\u0600-\u0605\u061C\u06DD\u070F\u08E2\u180E\u200B-\u200F\u202A-\u202E\u2060-\u2064\u2066-\u206F\uFEFF\uFFF9-\uFFFB]|\uD804[\uDCBD\uDCCD]|\uD80D[\uDC30-\uDC38]|\uD82F[\uDCA0-\uDCA3]|\uD834[\uDD73-\uDD7A]|\uDB40[\uDC01\uDC20-\uDC7F]/g;
|
546
|
+
|
547
|
+
|
548
|
+
|
549
|
+
|
550
|
+
/**
|
551
|
+
* Generated by:
|
552
|
+
*
|
553
|
+
* var regenerate = require( "regenerate" );
|
554
|
+
* var dashSymbols = require( "https://github.com/node-unicode/unicode-13.0.0/General_Category/Dash_Punctuation/symbols" );
|
555
|
+
* regenerate().add( dashSymbols ).toString();
|
556
|
+
*
|
557
|
+
* https://github.com/mathiasbynens/regenerate
|
558
|
+
* https://github.com/node-unicode/unicode-13.0.0
|
559
|
+
*
|
560
|
+
* NOTE: In addition to [:dash:], the below includes MINUS SIGN U+2212.
|
561
|
+
*/
|
562
|
+
var regexpDashG = /[\x2D\u058A\u05BE\u1400\u1806\u2010-\u2015\u2E17\u2E1A\u2E3A\u2E3B\u2E40\u301C\u3030\u30A0\uFE31\uFE32\uFE58\uFE63\uFF0D\u2212]|\uD803\uDEAD/g;
|
563
|
+
|
564
|
+
|
565
|
+
|
566
|
+
|
567
|
+
/**
|
568
|
+
* Generated by:
|
569
|
+
*
|
570
|
+
* var regenerate = require( "regenerate" );
|
571
|
+
* var spaceSeparatorSymbols = require( "@unicode/unicode-13.0.0/General_Category/Space_Separator/symbols" );
|
572
|
+
* regenerate().add( spaceSeparatorSymbols ).toString();
|
573
|
+
*
|
574
|
+
* https://github.com/mathiasbynens/regenerate
|
575
|
+
* https://github.com/node-unicode/unicode-13.0.0
|
576
|
+
*/
|
577
|
+
var regexpZsG = /[ \xA0\u1680\u2000-\u200A\u202F\u205F\u3000]/g;
|
578
|
+
|
579
|
+
|
580
|
+
|
581
|
+
|
582
|
+
/**
|
583
|
+
* Loose Matching:
|
584
|
+
* - Ignore all format characters, which includes RLM, LRM or ALM used to control BIDI
|
585
|
+
* formatting.
|
586
|
+
* - Map all characters in [:Zs:] to U+0020 SPACE;
|
587
|
+
* - Map all characters in [:Dash:] to U+002D HYPHEN-MINUS;
|
588
|
+
*/
|
589
|
+
var looseMatching = function( value ) {
|
590
|
+
return value
|
591
|
+
.replace( regexpCfG, "" )
|
592
|
+
.replace( regexpDashG, "-" )
|
593
|
+
.replace( regexpZsG, " " );
|
594
|
+
};
|
595
|
+
|
596
|
+
|
597
|
+
|
598
|
+
|
599
|
+
/**
|
600
|
+
* parse( value, properties )
|
601
|
+
*
|
602
|
+
* @value [String].
|
603
|
+
*
|
604
|
+
* @properties [Object] Parser properties is a reduced pre-processed cldr
|
605
|
+
* data set returned by numberParserProperties().
|
606
|
+
*
|
607
|
+
* Return the parsed Number (including Infinity) or NaN when value is invalid.
|
608
|
+
* ref: http://www.unicode.org/reports/tr35/tr35-numbers.html
|
609
|
+
*/
|
610
|
+
var numberParse = function( value, properties ) {
|
611
|
+
var grammar, invertedNuDigitsMap, invertedSymbolMap, negative, number, prefix, prefixNSuffix,
|
612
|
+
suffix, tokenizer, valid;
|
613
|
+
|
614
|
+
// Grammar:
|
615
|
+
// - Value <= NaN | PositiveNumber | NegativeNumber
|
616
|
+
// - PositiveNumber <= PositivePrefix NumberOrInf PositiveSufix
|
617
|
+
// - NegativeNumber <= NegativePrefix NumberOrInf
|
618
|
+
// - NumberOrInf <= Number | Inf
|
619
|
+
grammar = [
|
620
|
+
[ "nan" ],
|
621
|
+
[ "prefix", "infinity", "suffix" ],
|
622
|
+
[ "prefix", "number", "suffix" ],
|
623
|
+
[ "negativePrefix", "infinity", "negativeSuffix" ],
|
624
|
+
[ "negativePrefix", "number", "negativeSuffix" ]
|
625
|
+
];
|
626
|
+
|
627
|
+
invertedSymbolMap = properties[ 0 ];
|
628
|
+
invertedNuDigitsMap = properties[ 1 ] || {};
|
629
|
+
tokenizer = properties[ 2 ];
|
630
|
+
|
631
|
+
value = looseMatching( value );
|
632
|
+
|
633
|
+
function parse( type ) {
|
634
|
+
return function( lexeme ) {
|
635
|
+
|
636
|
+
// Reverse localized symbols and numbering system.
|
637
|
+
lexeme = lexeme.split( "" ).map(function( character ) {
|
638
|
+
return invertedSymbolMap[ character ] ||
|
639
|
+
invertedNuDigitsMap[ character ] ||
|
640
|
+
character;
|
641
|
+
}).join( "" );
|
642
|
+
|
643
|
+
switch ( type ) {
|
644
|
+
case "infinity":
|
645
|
+
number = Infinity;
|
646
|
+
break;
|
647
|
+
|
648
|
+
case "nan":
|
649
|
+
number = NaN;
|
650
|
+
break;
|
651
|
+
|
652
|
+
case "number":
|
653
|
+
|
654
|
+
// Remove grouping separators.
|
655
|
+
lexeme = lexeme.replace( /,/g, "" );
|
656
|
+
|
657
|
+
number = +lexeme;
|
658
|
+
break;
|
659
|
+
|
660
|
+
case "prefix":
|
661
|
+
case "negativePrefix":
|
662
|
+
prefix = lexeme;
|
663
|
+
break;
|
664
|
+
|
665
|
+
case "suffix":
|
666
|
+
suffix = lexeme;
|
667
|
+
break;
|
668
|
+
|
669
|
+
case "negativeSuffix":
|
670
|
+
suffix = lexeme;
|
671
|
+
negative = true;
|
672
|
+
break;
|
673
|
+
|
674
|
+
// This should never be reached.
|
675
|
+
default:
|
676
|
+
throw new Error( "Internal error" );
|
677
|
+
}
|
678
|
+
return "";
|
679
|
+
};
|
680
|
+
}
|
681
|
+
|
682
|
+
function tokenizeNParse( _value, grammar ) {
|
683
|
+
return grammar.some(function( statement ) {
|
684
|
+
var value = _value;
|
685
|
+
|
686
|
+
// The whole grammar statement should be used (i.e., .every() return true) and value be
|
687
|
+
// entirely consumed (i.e., !value.length).
|
688
|
+
return statement.every(function( type ) {
|
689
|
+
if ( value.match( tokenizer[ type ] ) === null ) {
|
690
|
+
return false;
|
691
|
+
}
|
692
|
+
|
693
|
+
// Consume and parse it.
|
694
|
+
value = value.replace( tokenizer[ type ], parse( type ) );
|
695
|
+
return true;
|
696
|
+
}) && !value.length;
|
697
|
+
});
|
698
|
+
}
|
699
|
+
|
700
|
+
valid = tokenizeNParse( value, grammar );
|
701
|
+
|
702
|
+
// NaN
|
703
|
+
if ( !valid || isNaN( number ) ) {
|
704
|
+
return NaN;
|
705
|
+
}
|
706
|
+
|
707
|
+
prefixNSuffix = "" + prefix + suffix;
|
708
|
+
|
709
|
+
// Percent
|
710
|
+
if ( prefixNSuffix.indexOf( "%" ) !== -1 ) {
|
711
|
+
number /= 100;
|
712
|
+
|
713
|
+
// Per mille
|
714
|
+
} else if ( prefixNSuffix.indexOf( "\u2030" ) !== -1 ) {
|
715
|
+
number /= 1000;
|
716
|
+
}
|
717
|
+
|
718
|
+
// Negative number
|
719
|
+
if ( negative ) {
|
720
|
+
number *= -1;
|
721
|
+
}
|
722
|
+
|
723
|
+
return number;
|
724
|
+
};
|
725
|
+
|
726
|
+
|
727
|
+
|
728
|
+
|
729
|
+
var numberParserFn = function( properties ) {
|
730
|
+
return function numberParser( value ) {
|
731
|
+
validateParameterPresence( value, "value" );
|
732
|
+
validateParameterTypeString( value, "value" );
|
733
|
+
|
734
|
+
return numberParse( value, properties );
|
735
|
+
};
|
736
|
+
|
737
|
+
};
|
738
|
+
|
739
|
+
|
740
|
+
|
741
|
+
|
742
|
+
var numberToPartsFormatterFn = function( properties, pluralGenerator ) {
|
743
|
+
return function numberToPartsFormatter( value ) {
|
744
|
+
validateParameterPresence( value, "value" );
|
745
|
+
validateParameterTypeNumber( value, "value" );
|
746
|
+
|
747
|
+
return numberFormat( value, properties, pluralGenerator );
|
748
|
+
};
|
749
|
+
};
|
750
|
+
|
751
|
+
|
752
|
+
|
753
|
+
|
754
|
+
var numberTruncate = function( value ) {
|
755
|
+
if ( isNaN( value ) ) {
|
756
|
+
return NaN;
|
757
|
+
}
|
758
|
+
return Math[ value < 0 ? "ceil" : "floor" ]( value );
|
759
|
+
};
|
760
|
+
|
761
|
+
|
762
|
+
|
763
|
+
|
764
|
+
/**
|
765
|
+
* round( method )
|
766
|
+
*
|
767
|
+
* @method [String] with either "round", "ceil", "floor", or "truncate".
|
768
|
+
*
|
769
|
+
* Return function( value, incrementOrExp ):
|
770
|
+
*
|
771
|
+
* @value [Number] eg. 123.45.
|
772
|
+
*
|
773
|
+
* @incrementOrExp [Number] optional, eg. 0.1; or
|
774
|
+
* [Object] Either { increment: <value> } or { exponent: <value> }
|
775
|
+
*
|
776
|
+
* Return the rounded number, eg:
|
777
|
+
* - round( "round" )( 123.45 ): 123;
|
778
|
+
* - round( "ceil" )( 123.45 ): 124;
|
779
|
+
* - round( "floor" )( 123.45 ): 123;
|
780
|
+
* - round( "truncate" )( 123.45 ): 123;
|
781
|
+
* - round( "round" )( 123.45, 0.1 ): 123.5;
|
782
|
+
* - round( "round" )( 123.45, 10 ): 120;
|
783
|
+
*
|
784
|
+
* Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
|
785
|
+
* Ref: #376
|
786
|
+
*/
|
787
|
+
var numberRound = function( method ) {
|
788
|
+
method = method || "round";
|
789
|
+
method = method === "truncate" ? numberTruncate : Math[ method ];
|
790
|
+
|
791
|
+
return function( value, incrementOrExp ) {
|
792
|
+
var exp, increment;
|
793
|
+
|
794
|
+
value = +value;
|
795
|
+
|
796
|
+
// If the value is not a number, return NaN.
|
797
|
+
if ( isNaN( value ) ) {
|
798
|
+
return NaN;
|
799
|
+
}
|
800
|
+
|
801
|
+
// Exponent given.
|
802
|
+
if ( typeof incrementOrExp === "object" && incrementOrExp.exponent ) {
|
803
|
+
exp = +incrementOrExp.exponent;
|
804
|
+
increment = 1;
|
805
|
+
|
806
|
+
if ( exp === 0 ) {
|
807
|
+
return method( value );
|
808
|
+
}
|
809
|
+
|
810
|
+
// If the exp is not an integer, return NaN.
|
811
|
+
if ( !( typeof exp === "number" && exp % 1 === 0 ) ) {
|
812
|
+
return NaN;
|
813
|
+
}
|
814
|
+
|
815
|
+
// Increment given.
|
816
|
+
} else {
|
817
|
+
increment = +incrementOrExp || 1;
|
818
|
+
|
819
|
+
if ( increment === 1 ) {
|
820
|
+
return method( value );
|
821
|
+
}
|
822
|
+
|
823
|
+
// If the increment is not a number, return NaN.
|
824
|
+
if ( isNaN( increment ) ) {
|
825
|
+
return NaN;
|
826
|
+
}
|
827
|
+
|
828
|
+
increment = increment.toExponential().split( "e" );
|
829
|
+
exp = +increment[ 1 ];
|
830
|
+
increment = +increment[ 0 ];
|
831
|
+
}
|
832
|
+
|
833
|
+
// Shift & Round
|
834
|
+
value = value.toString().split( "e" );
|
835
|
+
value[ 0 ] = +value[ 0 ] / increment;
|
836
|
+
value[ 1 ] = value[ 1 ] ? ( +value[ 1 ] - exp ) : -exp;
|
837
|
+
value = method( +( value[ 0 ] + "e" + value[ 1 ] ) );
|
838
|
+
|
839
|
+
// Shift back
|
840
|
+
value = value.toString().split( "e" );
|
841
|
+
value[ 0 ] = +value[ 0 ] * increment;
|
842
|
+
value[ 1 ] = value[ 1 ] ? ( +value[ 1 ] + exp ) : exp;
|
843
|
+
return +( value[ 0 ] + "e" + value[ 1 ] );
|
844
|
+
};
|
845
|
+
};
|
846
|
+
|
847
|
+
|
848
|
+
|
849
|
+
|
850
|
+
Globalize._createErrorUnsupportedFeature = createErrorUnsupportedFeature;
|
851
|
+
Globalize._looseMatching = looseMatching;
|
852
|
+
Globalize._numberFormat = numberFormat;
|
853
|
+
Globalize._numberFormatterFn = numberFormatterFn;
|
854
|
+
Globalize._numberParse = numberParse;
|
855
|
+
Globalize._numberParserFn = numberParserFn;
|
856
|
+
Globalize._numberRound = numberRound;
|
857
|
+
Globalize._numberToPartsFormatterFn = numberToPartsFormatterFn;
|
858
|
+
Globalize._removeLiteralQuotes = removeLiteralQuotes;
|
859
|
+
Globalize._validateParameterPresence = validateParameterPresence;
|
860
|
+
Globalize._validateParameterTypeNumber = validateParameterTypeNumber;
|
861
|
+
Globalize._validateParameterTypeString = validateParameterTypeString;
|
862
|
+
|
863
|
+
// Stamp runtimeKey and return cached fn.
|
864
|
+
// Note, this function isn't made common to all formatters and parsers, because in practice this is
|
865
|
+
// only used (at the moment) for numberFormatter used by unitFormatter.
|
866
|
+
// TODO: Move this function into a common place when this is used by different formatters.
|
867
|
+
function cached( runtimeKey ) {
|
868
|
+
Globalize[ runtimeKey ].runtimeKey = runtimeKey;
|
869
|
+
return Globalize[ runtimeKey ];
|
870
|
+
}
|
871
|
+
|
872
|
+
Globalize.numberFormatter =
|
873
|
+
Globalize.prototype.numberFormatter = function( options ) {
|
874
|
+
options = options || {};
|
875
|
+
return cached( runtimeKey( "numberFormatter", this._locale, [ options ] ) );
|
876
|
+
};
|
877
|
+
|
878
|
+
Globalize.numberToPartsFormatter =
|
879
|
+
Globalize.prototype.numberToPartsFormatter = function( options ) {
|
880
|
+
options = options || {};
|
881
|
+
return cached( runtimeKey( "numberToPartsFormatter", this._locale, [ options ] ) );
|
882
|
+
};
|
883
|
+
|
884
|
+
Globalize.numberParser =
|
885
|
+
Globalize.prototype.numberParser = function( options ) {
|
886
|
+
options = options || {};
|
887
|
+
return Globalize[ runtimeKey( "numberParser", this._locale, [ options ] ) ];
|
888
|
+
};
|
889
|
+
|
890
|
+
Globalize.formatNumber =
|
891
|
+
Globalize.prototype.formatNumber = function( value, options ) {
|
892
|
+
validateParameterPresence( value, "value" );
|
893
|
+
validateParameterTypeNumber( value, "value" );
|
894
|
+
|
895
|
+
return this.numberFormatter( options )( value );
|
896
|
+
};
|
897
|
+
|
898
|
+
Globalize.formatNumberToParts =
|
899
|
+
Globalize.prototype.formatNumberToParts = function( value, options ) {
|
900
|
+
validateParameterPresence( value, "value" );
|
901
|
+
validateParameterTypeNumber( value, "value" );
|
902
|
+
|
903
|
+
return this.numberFormatter( options )( value );
|
904
|
+
};
|
905
|
+
|
906
|
+
Globalize.parseNumber =
|
907
|
+
Globalize.prototype.parseNumber = function( value, options ) {
|
908
|
+
validateParameterPresence( value, "value" );
|
909
|
+
validateParameterTypeString( value, "value" );
|
910
|
+
|
911
|
+
return this.numberParser( options )( value );
|
912
|
+
};
|
913
|
+
|
914
|
+
return Globalize;
|
915
|
+
|
916
|
+
|
917
|
+
|
918
|
+
|
919
|
+
}));
|