@formatjs/ecma402-abstract 1.11.8 → 1.11.9
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/262.ts +372 -0
- package/BUILD +97 -0
- package/CHANGELOG.md +709 -0
- package/CanonicalizeLocaleList.ts +8 -0
- package/CanonicalizeTimeZoneName.ts +29 -0
- package/CoerceOptionsToObject.ts +13 -0
- package/DefaultNumberOption.ts +28 -0
- package/GetNumberOption.ts +29 -0
- package/GetOption.ts +38 -0
- package/GetOptionsObject.ts +14 -0
- package/IsSanctionedSimpleUnitIdentifier.ts +66 -0
- package/IsValidTimeZoneName.ts +27 -0
- package/IsWellFormedCurrencyCode.ts +23 -0
- package/IsWellFormedUnitIdentifier.ts +32 -0
- package/LICENSE.md +0 -0
- package/NumberFormat/ComputeExponent.ts +49 -0
- package/NumberFormat/ComputeExponentForMagnitude.ts +71 -0
- package/NumberFormat/CurrencyDigits.ts +13 -0
- package/NumberFormat/FormatNumericToParts.ts +22 -0
- package/NumberFormat/FormatNumericToString.ts +71 -0
- package/NumberFormat/InitializeNumberFormat.ts +147 -0
- package/NumberFormat/PartitionNumberPattern.ts +86 -0
- package/NumberFormat/SetNumberFormatDigitOptions.ts +45 -0
- package/NumberFormat/SetNumberFormatUnitOptions.ts +77 -0
- package/NumberFormat/ToRawFixed.ts +56 -0
- package/NumberFormat/ToRawPrecision.ts +86 -0
- package/NumberFormat/digit-mapping.generated.ts +1 -0
- package/NumberFormat/format_to_parts.ts +571 -0
- package/PartitionPattern.ts +38 -0
- package/README.md +0 -0
- package/SupportedLocales.ts +31 -0
- package/data.ts +9 -0
- package/index.ts +45 -0
- package/package.json +3 -3
- package/regex.generated.ts +2 -0
- package/scripts/digit-mapping.ts +109 -0
- package/scripts/regex-gen.ts +19 -0
- package/tests/PartitionPattern.test.ts +38 -0
- package/tests/ToRawFixed.test.tsx +41 -0
- package/tests/ToRawPrecision.test.tsx +65 -0
- package/tsconfig.json +5 -0
- package/types/core.ts +11 -0
- package/types/date-time.ts +199 -0
- package/types/displaynames.ts +48 -0
- package/types/list.ts +22 -0
- package/types/number.ts +240 -0
- package/types/plural-rules.ts +18 -0
- package/types/relative-time.ts +74 -0
- package/utils.ts +128 -0
- package/262.d.ts +0 -92
- package/262.d.ts.map +0 -1
- package/262.js +0 -362
- package/CanonicalizeLocaleList.d.ts +0 -6
- package/CanonicalizeLocaleList.d.ts.map +0 -1
- package/CanonicalizeLocaleList.js +0 -12
- package/CanonicalizeTimeZoneName.d.ts +0 -9
- package/CanonicalizeTimeZoneName.d.ts.map +0 -1
- package/CanonicalizeTimeZoneName.js +0 -21
- package/CoerceOptionsToObject.d.ts +0 -7
- package/CoerceOptionsToObject.d.ts.map +0 -1
- package/CoerceOptionsToObject.js +0 -16
- package/DefaultNumberOption.d.ts +0 -9
- package/DefaultNumberOption.d.ts.map +0 -1
- package/DefaultNumberOption.js +0 -14
- package/GetNumberOption.d.ts +0 -10
- package/GetNumberOption.d.ts.map +0 -1
- package/GetNumberOption.js +0 -18
- package/GetOption.d.ts +0 -10
- package/GetOption.d.ts.map +0 -1
- package/GetOption.js +0 -35
- package/GetOptionsObject.d.ts +0 -7
- package/GetOptionsObject.d.ts.map +0 -1
- package/GetOptionsObject.js +0 -18
- package/IsSanctionedSimpleUnitIdentifier.d.ts +0 -14
- package/IsSanctionedSimpleUnitIdentifier.d.ts.map +0 -1
- package/IsSanctionedSimpleUnitIdentifier.js +0 -68
- package/IsValidTimeZoneName.d.ts +0 -10
- package/IsValidTimeZoneName.d.ts.map +0 -1
- package/IsValidTimeZoneName.js +0 -23
- package/IsWellFormedCurrencyCode.d.ts +0 -5
- package/IsWellFormedCurrencyCode.d.ts.map +0 -1
- package/IsWellFormedCurrencyCode.js +0 -25
- package/IsWellFormedUnitIdentifier.d.ts +0 -6
- package/IsWellFormedUnitIdentifier.d.ts.map +0 -1
- package/IsWellFormedUnitIdentifier.js +0 -32
- package/NumberFormat/ComputeExponent.d.ts +0 -12
- package/NumberFormat/ComputeExponent.d.ts.map +0 -1
- package/NumberFormat/ComputeExponent.js +0 -43
- package/NumberFormat/ComputeExponentForMagnitude.d.ts +0 -10
- package/NumberFormat/ComputeExponentForMagnitude.d.ts.map +0 -1
- package/NumberFormat/ComputeExponentForMagnitude.js +0 -64
- package/NumberFormat/CurrencyDigits.d.ts +0 -7
- package/NumberFormat/CurrencyDigits.d.ts.map +0 -1
- package/NumberFormat/CurrencyDigits.js +0 -14
- package/NumberFormat/FormatNumericToParts.d.ts +0 -5
- package/NumberFormat/FormatNumericToParts.d.ts.map +0 -1
- package/NumberFormat/FormatNumericToParts.js +0 -18
- package/NumberFormat/FormatNumericToString.d.ts +0 -9
- package/NumberFormat/FormatNumericToString.d.ts.map +0 -1
- package/NumberFormat/FormatNumericToString.js +0 -45
- package/NumberFormat/InitializeNumberFormat.d.ts +0 -13
- package/NumberFormat/InitializeNumberFormat.d.ts.map +0 -1
- package/NumberFormat/InitializeNumberFormat.js +0 -68
- package/NumberFormat/PartitionNumberPattern.d.ts +0 -8
- package/NumberFormat/PartitionNumberPattern.d.ts.map +0 -1
- package/NumberFormat/PartitionNumberPattern.js +0 -80
- package/NumberFormat/SetNumberFormatDigitOptions.d.ts +0 -6
- package/NumberFormat/SetNumberFormatDigitOptions.d.ts.map +0 -1
- package/NumberFormat/SetNumberFormatDigitOptions.js +0 -40
- package/NumberFormat/SetNumberFormatUnitOptions.d.ts +0 -8
- package/NumberFormat/SetNumberFormatUnitOptions.d.ts.map +0 -1
- package/NumberFormat/SetNumberFormatUnitOptions.js +0 -43
- package/NumberFormat/ToRawFixed.d.ts +0 -10
- package/NumberFormat/ToRawFixed.d.ts.map +0 -1
- package/NumberFormat/ToRawFixed.js +0 -55
- package/NumberFormat/ToRawPrecision.d.ts +0 -3
- package/NumberFormat/ToRawPrecision.d.ts.map +0 -1
- package/NumberFormat/ToRawPrecision.js +0 -78
- package/NumberFormat/digit-mapping.generated.d.ts +0 -2
- package/NumberFormat/digit-mapping.generated.d.ts.map +0 -1
- package/NumberFormat/digit-mapping.generated.js +0 -4
- package/NumberFormat/format_to_parts.d.ts +0 -22
- package/NumberFormat/format_to_parts.d.ts.map +0 -1
- package/NumberFormat/format_to_parts.js +0 -424
- package/PartitionPattern.d.ts +0 -9
- package/PartitionPattern.d.ts.map +0 -1
- package/PartitionPattern.js +0 -39
- package/SupportedLocales.d.ts +0 -10
- package/SupportedLocales.d.ts.map +0 -1
- package/SupportedLocales.js +0 -24
- package/data.d.ts +0 -6
- package/data.d.ts.map +0 -1
- package/data.js +0 -17
- package/index.d.ts +0 -37
- package/index.d.ts.map +0 -1
- package/index.js +0 -48
- package/lib/262.d.ts +0 -92
- package/lib/262.d.ts.map +0 -1
- package/lib/262.js +0 -336
- package/lib/CanonicalizeLocaleList.d.ts +0 -6
- package/lib/CanonicalizeLocaleList.d.ts.map +0 -1
- package/lib/CanonicalizeLocaleList.js +0 -8
- package/lib/CanonicalizeTimeZoneName.d.ts +0 -9
- package/lib/CanonicalizeTimeZoneName.d.ts.map +0 -1
- package/lib/CanonicalizeTimeZoneName.js +0 -17
- package/lib/CoerceOptionsToObject.d.ts +0 -7
- package/lib/CoerceOptionsToObject.d.ts.map +0 -1
- package/lib/CoerceOptionsToObject.js +0 -12
- package/lib/DefaultNumberOption.d.ts +0 -9
- package/lib/DefaultNumberOption.d.ts.map +0 -1
- package/lib/DefaultNumberOption.js +0 -10
- package/lib/GetNumberOption.d.ts +0 -10
- package/lib/GetNumberOption.d.ts.map +0 -1
- package/lib/GetNumberOption.js +0 -14
- package/lib/GetOption.d.ts +0 -10
- package/lib/GetOption.d.ts.map +0 -1
- package/lib/GetOption.js +0 -31
- package/lib/GetOptionsObject.d.ts +0 -7
- package/lib/GetOptionsObject.d.ts.map +0 -1
- package/lib/GetOptionsObject.js +0 -14
- package/lib/IsSanctionedSimpleUnitIdentifier.d.ts +0 -14
- package/lib/IsSanctionedSimpleUnitIdentifier.d.ts.map +0 -1
- package/lib/IsSanctionedSimpleUnitIdentifier.js +0 -63
- package/lib/IsValidTimeZoneName.d.ts +0 -10
- package/lib/IsValidTimeZoneName.d.ts.map +0 -1
- package/lib/IsValidTimeZoneName.js +0 -19
- package/lib/IsWellFormedCurrencyCode.d.ts +0 -5
- package/lib/IsWellFormedCurrencyCode.d.ts.map +0 -1
- package/lib/IsWellFormedCurrencyCode.js +0 -21
- package/lib/IsWellFormedUnitIdentifier.d.ts +0 -6
- package/lib/IsWellFormedUnitIdentifier.d.ts.map +0 -1
- package/lib/IsWellFormedUnitIdentifier.js +0 -28
- package/lib/NumberFormat/ComputeExponent.d.ts +0 -12
- package/lib/NumberFormat/ComputeExponent.d.ts.map +0 -1
- package/lib/NumberFormat/ComputeExponent.js +0 -39
- package/lib/NumberFormat/ComputeExponentForMagnitude.d.ts +0 -10
- package/lib/NumberFormat/ComputeExponentForMagnitude.d.ts.map +0 -1
- package/lib/NumberFormat/ComputeExponentForMagnitude.js +0 -60
- package/lib/NumberFormat/CurrencyDigits.d.ts +0 -7
- package/lib/NumberFormat/CurrencyDigits.d.ts.map +0 -1
- package/lib/NumberFormat/CurrencyDigits.js +0 -10
- package/lib/NumberFormat/FormatNumericToParts.d.ts +0 -5
- package/lib/NumberFormat/FormatNumericToParts.d.ts.map +0 -1
- package/lib/NumberFormat/FormatNumericToParts.js +0 -14
- package/lib/NumberFormat/FormatNumericToString.d.ts +0 -9
- package/lib/NumberFormat/FormatNumericToString.d.ts.map +0 -1
- package/lib/NumberFormat/FormatNumericToString.js +0 -41
- package/lib/NumberFormat/InitializeNumberFormat.d.ts +0 -13
- package/lib/NumberFormat/InitializeNumberFormat.d.ts.map +0 -1
- package/lib/NumberFormat/InitializeNumberFormat.js +0 -64
- package/lib/NumberFormat/PartitionNumberPattern.d.ts +0 -8
- package/lib/NumberFormat/PartitionNumberPattern.d.ts.map +0 -1
- package/lib/NumberFormat/PartitionNumberPattern.js +0 -75
- package/lib/NumberFormat/SetNumberFormatDigitOptions.d.ts +0 -6
- package/lib/NumberFormat/SetNumberFormatDigitOptions.d.ts.map +0 -1
- package/lib/NumberFormat/SetNumberFormatDigitOptions.js +0 -36
- package/lib/NumberFormat/SetNumberFormatUnitOptions.d.ts +0 -8
- package/lib/NumberFormat/SetNumberFormatUnitOptions.d.ts.map +0 -1
- package/lib/NumberFormat/SetNumberFormatUnitOptions.js +0 -39
- package/lib/NumberFormat/ToRawFixed.d.ts +0 -10
- package/lib/NumberFormat/ToRawFixed.d.ts.map +0 -1
- package/lib/NumberFormat/ToRawFixed.js +0 -51
- package/lib/NumberFormat/ToRawPrecision.d.ts +0 -3
- package/lib/NumberFormat/ToRawPrecision.d.ts.map +0 -1
- package/lib/NumberFormat/ToRawPrecision.js +0 -74
- package/lib/NumberFormat/digit-mapping.generated.d.ts +0 -2
- package/lib/NumberFormat/digit-mapping.generated.d.ts.map +0 -1
- package/lib/NumberFormat/digit-mapping.generated.js +0 -1
- package/lib/NumberFormat/format_to_parts.d.ts +0 -22
- package/lib/NumberFormat/format_to_parts.d.ts.map +0 -1
- package/lib/NumberFormat/format_to_parts.js +0 -421
- package/lib/PartitionPattern.d.ts +0 -9
- package/lib/PartitionPattern.d.ts.map +0 -1
- package/lib/PartitionPattern.js +0 -35
- package/lib/SupportedLocales.d.ts +0 -10
- package/lib/SupportedLocales.d.ts.map +0 -1
- package/lib/SupportedLocales.js +0 -20
- package/lib/data.d.ts +0 -6
- package/lib/data.d.ts.map +0 -1
- package/lib/data.js +0 -13
- package/lib/index.d.ts +0 -37
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js +0 -34
- package/lib/regex.generated.d.ts +0 -2
- package/lib/regex.generated.d.ts.map +0 -1
- package/lib/regex.generated.js +0 -2
- package/lib/types/core.d.ts +0 -11
- package/lib/types/core.d.ts.map +0 -1
- package/lib/types/core.js +0 -1
- package/lib/types/date-time.d.ts +0 -135
- package/lib/types/date-time.d.ts.map +0 -1
- package/lib/types/date-time.js +0 -6
- package/lib/types/displaynames.d.ts +0 -47
- package/lib/types/displaynames.d.ts.map +0 -1
- package/lib/types/displaynames.js +0 -1
- package/lib/types/list.d.ts +0 -19
- package/lib/types/list.d.ts.map +0 -1
- package/lib/types/list.js +0 -1
- package/lib/types/number.d.ts +0 -147
- package/lib/types/number.d.ts.map +0 -1
- package/lib/types/number.js +0 -1
- package/lib/types/plural-rules.d.ts +0 -17
- package/lib/types/plural-rules.d.ts.map +0 -1
- package/lib/types/plural-rules.js +0 -1
- package/lib/types/relative-time.d.ts +0 -41
- package/lib/types/relative-time.d.ts.map +0 -1
- package/lib/types/relative-time.js +0 -1
- package/lib/utils.d.ts +0 -24
- package/lib/utils.d.ts.map +0 -1
- package/lib/utils.js +0 -78
- package/regex.generated.d.ts +0 -2
- package/regex.generated.d.ts.map +0 -1
- package/regex.generated.js +0 -5
- package/types/core.d.ts +0 -11
- package/types/core.d.ts.map +0 -1
- package/types/core.js +0 -2
- package/types/date-time.d.ts +0 -135
- package/types/date-time.d.ts.map +0 -1
- package/types/date-time.js +0 -9
- package/types/displaynames.d.ts +0 -47
- package/types/displaynames.d.ts.map +0 -1
- package/types/displaynames.js +0 -2
- package/types/list.d.ts +0 -19
- package/types/list.d.ts.map +0 -1
- package/types/list.js +0 -2
- package/types/number.d.ts +0 -147
- package/types/number.d.ts.map +0 -1
- package/types/number.js +0 -2
- package/types/plural-rules.d.ts +0 -17
- package/types/plural-rules.d.ts.map +0 -1
- package/types/plural-rules.js +0 -2
- package/types/relative-time.d.ts +0 -41
- package/types/relative-time.d.ts.map +0 -1
- package/types/relative-time.js +0 -2
- package/utils.d.ts +0 -24
- package/utils.d.ts.map +0 -1
- package/utils.js +0 -90
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* http://ecma-international.org/ecma-402/7.0/index.html#sec-canonicalizelocalelist
|
|
3
|
+
* @param locales
|
|
4
|
+
*/
|
|
5
|
+
export function CanonicalizeLocaleList(locales?: string | string[]): string[] {
|
|
6
|
+
// TODO
|
|
7
|
+
return ((Intl as any).getCanonicalLocales as any)(locales)
|
|
8
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* https://tc39.es/ecma402/#sec-canonicalizetimezonename
|
|
3
|
+
* @param tz
|
|
4
|
+
*/
|
|
5
|
+
export function CanonicalizeTimeZoneName(
|
|
6
|
+
tz: string,
|
|
7
|
+
{
|
|
8
|
+
tzData,
|
|
9
|
+
uppercaseLinks,
|
|
10
|
+
}: {
|
|
11
|
+
tzData: Record<string, unknown>
|
|
12
|
+
uppercaseLinks: Record<string, string>
|
|
13
|
+
}
|
|
14
|
+
) {
|
|
15
|
+
const uppercasedTz = tz.toUpperCase()
|
|
16
|
+
const uppercasedZones = Object.keys(tzData).reduce(
|
|
17
|
+
(all: Record<string, string>, z) => {
|
|
18
|
+
all[z.toUpperCase()] = z
|
|
19
|
+
return all
|
|
20
|
+
},
|
|
21
|
+
{}
|
|
22
|
+
)
|
|
23
|
+
const ianaTimeZone =
|
|
24
|
+
uppercaseLinks[uppercasedTz] || uppercasedZones[uppercasedTz]
|
|
25
|
+
if (ianaTimeZone === 'Etc/UTC' || ianaTimeZone === 'Etc/GMT') {
|
|
26
|
+
return 'UTC'
|
|
27
|
+
}
|
|
28
|
+
return ianaTimeZone
|
|
29
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import {ToObject} from './262'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* https://tc39.es/ecma402/#sec-coerceoptionstoobject
|
|
5
|
+
* @param options
|
|
6
|
+
* @returns
|
|
7
|
+
*/
|
|
8
|
+
export function CoerceOptionsToObject<T>(options?: T): T {
|
|
9
|
+
if (typeof options === 'undefined') {
|
|
10
|
+
return Object.create(null)
|
|
11
|
+
}
|
|
12
|
+
return ToObject(options)
|
|
13
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* https://tc39.es/ecma402/#sec-defaultnumberoption
|
|
3
|
+
* @param val
|
|
4
|
+
* @param min
|
|
5
|
+
* @param max
|
|
6
|
+
* @param fallback
|
|
7
|
+
*/
|
|
8
|
+
export function DefaultNumberOption(
|
|
9
|
+
val: any,
|
|
10
|
+
min: number,
|
|
11
|
+
max: number,
|
|
12
|
+
fallback: number
|
|
13
|
+
): number
|
|
14
|
+
export function DefaultNumberOption(
|
|
15
|
+
val: any,
|
|
16
|
+
min: number,
|
|
17
|
+
max: number,
|
|
18
|
+
fallback: number | undefined
|
|
19
|
+
): number | undefined {
|
|
20
|
+
if (val !== undefined) {
|
|
21
|
+
val = Number(val)
|
|
22
|
+
if (isNaN(val) || val < min || val > max) {
|
|
23
|
+
throw new RangeError(`${val} is outside of range [${min}, ${max}]`)
|
|
24
|
+
}
|
|
25
|
+
return Math.floor(val)
|
|
26
|
+
}
|
|
27
|
+
return fallback
|
|
28
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* https://tc39.es/ecma402/#sec-getnumberoption
|
|
3
|
+
* @param options
|
|
4
|
+
* @param property
|
|
5
|
+
* @param min
|
|
6
|
+
* @param max
|
|
7
|
+
* @param fallback
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {DefaultNumberOption} from './DefaultNumberOption'
|
|
11
|
+
|
|
12
|
+
export function GetNumberOption<T extends object, K extends keyof T>(
|
|
13
|
+
options: T,
|
|
14
|
+
property: K,
|
|
15
|
+
minimum: number,
|
|
16
|
+
maximum: number,
|
|
17
|
+
fallback: number
|
|
18
|
+
): number
|
|
19
|
+
export function GetNumberOption<T extends object, K extends keyof T>(
|
|
20
|
+
options: T,
|
|
21
|
+
property: K,
|
|
22
|
+
minimum: number,
|
|
23
|
+
maximum: number,
|
|
24
|
+
fallback: number | undefined
|
|
25
|
+
): number | undefined {
|
|
26
|
+
const val = options[property]
|
|
27
|
+
// @ts-expect-error
|
|
28
|
+
return DefaultNumberOption(val, minimum, maximum, fallback)
|
|
29
|
+
}
|
package/GetOption.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {ToString} from './262'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* https://tc39.es/ecma402/#sec-getoption
|
|
5
|
+
* @param opts
|
|
6
|
+
* @param prop
|
|
7
|
+
* @param type
|
|
8
|
+
* @param values
|
|
9
|
+
* @param fallback
|
|
10
|
+
*/
|
|
11
|
+
export function GetOption<T extends object, K extends keyof T, F>(
|
|
12
|
+
opts: T,
|
|
13
|
+
prop: K,
|
|
14
|
+
type: 'string' | 'boolean',
|
|
15
|
+
values: T[K][] | undefined,
|
|
16
|
+
fallback: F
|
|
17
|
+
): Exclude<T[K], undefined> | F {
|
|
18
|
+
if (typeof opts !== 'object') {
|
|
19
|
+
throw new TypeError('Options must be an object')
|
|
20
|
+
}
|
|
21
|
+
let value: any = opts[prop]
|
|
22
|
+
if (value !== undefined) {
|
|
23
|
+
if (type !== 'boolean' && type !== 'string') {
|
|
24
|
+
throw new TypeError('invalid type')
|
|
25
|
+
}
|
|
26
|
+
if (type === 'boolean') {
|
|
27
|
+
value = Boolean(value)
|
|
28
|
+
}
|
|
29
|
+
if (type === 'string') {
|
|
30
|
+
value = ToString(value)
|
|
31
|
+
}
|
|
32
|
+
if (values !== undefined && !values.filter(val => val == value).length) {
|
|
33
|
+
throw new RangeError(`${value} is not within ${values.join(', ')}`)
|
|
34
|
+
}
|
|
35
|
+
return value
|
|
36
|
+
}
|
|
37
|
+
return fallback
|
|
38
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* https://tc39.es/ecma402/#sec-getoptionsobject
|
|
3
|
+
* @param options
|
|
4
|
+
* @returns
|
|
5
|
+
*/
|
|
6
|
+
export function GetOptionsObject<T extends object>(options?: T): T {
|
|
7
|
+
if (typeof options === 'undefined') {
|
|
8
|
+
return Object.create(null)
|
|
9
|
+
}
|
|
10
|
+
if (typeof options === 'object') {
|
|
11
|
+
return options
|
|
12
|
+
}
|
|
13
|
+
throw new TypeError('Options must be an object')
|
|
14
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* https://tc39.es/ecma402/#table-sanctioned-simple-unit-identifiers
|
|
3
|
+
*/
|
|
4
|
+
export const SANCTIONED_UNITS = [
|
|
5
|
+
'angle-degree',
|
|
6
|
+
'area-acre',
|
|
7
|
+
'area-hectare',
|
|
8
|
+
'concentr-percent',
|
|
9
|
+
'digital-bit',
|
|
10
|
+
'digital-byte',
|
|
11
|
+
'digital-gigabit',
|
|
12
|
+
'digital-gigabyte',
|
|
13
|
+
'digital-kilobit',
|
|
14
|
+
'digital-kilobyte',
|
|
15
|
+
'digital-megabit',
|
|
16
|
+
'digital-megabyte',
|
|
17
|
+
'digital-petabyte',
|
|
18
|
+
'digital-terabit',
|
|
19
|
+
'digital-terabyte',
|
|
20
|
+
'duration-day',
|
|
21
|
+
'duration-hour',
|
|
22
|
+
'duration-millisecond',
|
|
23
|
+
'duration-minute',
|
|
24
|
+
'duration-month',
|
|
25
|
+
'duration-second',
|
|
26
|
+
'duration-week',
|
|
27
|
+
'duration-year',
|
|
28
|
+
'length-centimeter',
|
|
29
|
+
'length-foot',
|
|
30
|
+
'length-inch',
|
|
31
|
+
'length-kilometer',
|
|
32
|
+
'length-meter',
|
|
33
|
+
'length-mile-scandinavian',
|
|
34
|
+
'length-mile',
|
|
35
|
+
'length-millimeter',
|
|
36
|
+
'length-yard',
|
|
37
|
+
'mass-gram',
|
|
38
|
+
'mass-kilogram',
|
|
39
|
+
'mass-ounce',
|
|
40
|
+
'mass-pound',
|
|
41
|
+
'mass-stone',
|
|
42
|
+
'temperature-celsius',
|
|
43
|
+
'temperature-fahrenheit',
|
|
44
|
+
'volume-fluid-ounce',
|
|
45
|
+
'volume-gallon',
|
|
46
|
+
'volume-liter',
|
|
47
|
+
'volume-milliliter',
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
// In CLDR, the unit name always follows the form `namespace-unit` pattern.
|
|
51
|
+
// For example: `digital-bit` instead of `bit`. This function removes the namespace prefix.
|
|
52
|
+
export function removeUnitNamespace(unit: string) {
|
|
53
|
+
return unit.slice(unit.indexOf('-') + 1)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* https://tc39.es/ecma402/#table-sanctioned-simple-unit-identifiers
|
|
58
|
+
*/
|
|
59
|
+
export const SIMPLE_UNITS = SANCTIONED_UNITS.map(removeUnitNamespace)
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* https://tc39.es/ecma402/#sec-issanctionedsimpleunitidentifier
|
|
63
|
+
*/
|
|
64
|
+
export function IsSanctionedSimpleUnitIdentifier(unitIdentifier: string) {
|
|
65
|
+
return SIMPLE_UNITS.indexOf(unitIdentifier) > -1
|
|
66
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* https://tc39.es/ecma402/#sec-isvalidtimezonename
|
|
3
|
+
* @param tz
|
|
4
|
+
* @param implDetails implementation details
|
|
5
|
+
*/
|
|
6
|
+
export function IsValidTimeZoneName(
|
|
7
|
+
tz: string,
|
|
8
|
+
{
|
|
9
|
+
tzData,
|
|
10
|
+
uppercaseLinks,
|
|
11
|
+
}: {
|
|
12
|
+
tzData: Record<string, unknown>
|
|
13
|
+
uppercaseLinks: Record<string, string>
|
|
14
|
+
}
|
|
15
|
+
): boolean {
|
|
16
|
+
const uppercasedTz = tz.toUpperCase()
|
|
17
|
+
const zoneNames = new Set()
|
|
18
|
+
const linkNames = new Set()
|
|
19
|
+
Object.keys(tzData)
|
|
20
|
+
.map(z => z.toUpperCase())
|
|
21
|
+
.forEach(z => zoneNames.add(z))
|
|
22
|
+
Object.keys(uppercaseLinks).forEach(linkName => {
|
|
23
|
+
linkNames.add(linkName.toUpperCase())
|
|
24
|
+
zoneNames.add(uppercaseLinks[linkName].toUpperCase())
|
|
25
|
+
})
|
|
26
|
+
return zoneNames.has(uppercasedTz) || linkNames.has(uppercasedTz)
|
|
27
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This follows https://tc39.es/ecma402/#sec-case-sensitivity-and-case-mapping
|
|
3
|
+
* @param str string to convert
|
|
4
|
+
*/
|
|
5
|
+
function toUpperCase(str: string): string {
|
|
6
|
+
return str.replace(/([a-z])/g, (_, c) => c.toUpperCase())
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const NOT_A_Z_REGEX = /[^A-Z]/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* https://tc39.es/ecma402/#sec-iswellformedcurrencycode
|
|
13
|
+
*/
|
|
14
|
+
export function IsWellFormedCurrencyCode(currency: string): boolean {
|
|
15
|
+
currency = toUpperCase(currency)
|
|
16
|
+
if (currency.length !== 3) {
|
|
17
|
+
return false
|
|
18
|
+
}
|
|
19
|
+
if (NOT_A_Z_REGEX.test(currency)) {
|
|
20
|
+
return false
|
|
21
|
+
}
|
|
22
|
+
return true
|
|
23
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {IsSanctionedSimpleUnitIdentifier} from './IsSanctionedSimpleUnitIdentifier'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This follows https://tc39.es/ecma402/#sec-case-sensitivity-and-case-mapping
|
|
5
|
+
* @param str string to convert
|
|
6
|
+
*/
|
|
7
|
+
function toLowerCase(str: string): string {
|
|
8
|
+
return str.replace(/([A-Z])/g, (_, c) => c.toLowerCase())
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* https://tc39.es/ecma402/#sec-iswellformedunitidentifier
|
|
13
|
+
* @param unit
|
|
14
|
+
*/
|
|
15
|
+
export function IsWellFormedUnitIdentifier(unit: string) {
|
|
16
|
+
unit = toLowerCase(unit)
|
|
17
|
+
if (IsSanctionedSimpleUnitIdentifier(unit)) {
|
|
18
|
+
return true
|
|
19
|
+
}
|
|
20
|
+
const units = unit.split('-per-')
|
|
21
|
+
if (units.length !== 2) {
|
|
22
|
+
return false
|
|
23
|
+
}
|
|
24
|
+
const [numerator, denominator] = units
|
|
25
|
+
if (
|
|
26
|
+
!IsSanctionedSimpleUnitIdentifier(numerator) ||
|
|
27
|
+
!IsSanctionedSimpleUnitIdentifier(denominator)
|
|
28
|
+
) {
|
|
29
|
+
return false
|
|
30
|
+
}
|
|
31
|
+
return true
|
|
32
|
+
}
|
package/LICENSE.md
CHANGED
|
File without changes
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {getMagnitude} from '../utils'
|
|
2
|
+
import {ComputeExponentForMagnitude} from './ComputeExponentForMagnitude'
|
|
3
|
+
import {FormatNumericToString} from './FormatNumericToString'
|
|
4
|
+
import {NumberFormatInternal} from '../types/number'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The abstract operation ComputeExponent computes an exponent (power of ten) by which to scale x
|
|
8
|
+
* according to the number formatting settings. It handles cases such as 999 rounding up to 1000,
|
|
9
|
+
* requiring a different exponent.
|
|
10
|
+
*
|
|
11
|
+
* NOT IN SPEC: it returns [exponent, magnitude].
|
|
12
|
+
*/
|
|
13
|
+
export function ComputeExponent(
|
|
14
|
+
numberFormat: Intl.NumberFormat,
|
|
15
|
+
x: number,
|
|
16
|
+
{
|
|
17
|
+
getInternalSlots,
|
|
18
|
+
}: {getInternalSlots(nf: Intl.NumberFormat): NumberFormatInternal}
|
|
19
|
+
): [number, number] {
|
|
20
|
+
if (x === 0) {
|
|
21
|
+
return [0, 0]
|
|
22
|
+
}
|
|
23
|
+
if (x < 0) {
|
|
24
|
+
x = -x
|
|
25
|
+
}
|
|
26
|
+
const magnitude = getMagnitude(x)
|
|
27
|
+
const exponent = ComputeExponentForMagnitude(numberFormat, magnitude, {
|
|
28
|
+
getInternalSlots,
|
|
29
|
+
})
|
|
30
|
+
// Preserve more precision by doing multiplication when exponent is negative.
|
|
31
|
+
x = exponent < 0 ? x * 10 ** -exponent : x / 10 ** exponent
|
|
32
|
+
const formatNumberResult = FormatNumericToString(
|
|
33
|
+
getInternalSlots(numberFormat),
|
|
34
|
+
x
|
|
35
|
+
)
|
|
36
|
+
if (formatNumberResult.roundedNumber === 0) {
|
|
37
|
+
return [exponent, magnitude]
|
|
38
|
+
}
|
|
39
|
+
const newMagnitude = getMagnitude(formatNumberResult.roundedNumber)
|
|
40
|
+
if (newMagnitude === magnitude - exponent) {
|
|
41
|
+
return [exponent, magnitude]
|
|
42
|
+
}
|
|
43
|
+
return [
|
|
44
|
+
ComputeExponentForMagnitude(numberFormat, magnitude + 1, {
|
|
45
|
+
getInternalSlots,
|
|
46
|
+
}),
|
|
47
|
+
magnitude + 1,
|
|
48
|
+
]
|
|
49
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import {NumberFormatInternal, DecimalFormatNum} from '../types/number'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The abstract operation ComputeExponentForMagnitude computes an exponent by which to scale a
|
|
5
|
+
* number of the given magnitude (power of ten of the most significant digit) according to the
|
|
6
|
+
* locale and the desired notation (scientific, engineering, or compact).
|
|
7
|
+
*/
|
|
8
|
+
export function ComputeExponentForMagnitude(
|
|
9
|
+
numberFormat: Intl.NumberFormat,
|
|
10
|
+
magnitude: number,
|
|
11
|
+
{
|
|
12
|
+
getInternalSlots,
|
|
13
|
+
}: {getInternalSlots(nf: Intl.NumberFormat): NumberFormatInternal}
|
|
14
|
+
): number {
|
|
15
|
+
const internalSlots = getInternalSlots(numberFormat)
|
|
16
|
+
const {notation, dataLocaleData, numberingSystem} = internalSlots
|
|
17
|
+
|
|
18
|
+
switch (notation) {
|
|
19
|
+
case 'standard':
|
|
20
|
+
return 0
|
|
21
|
+
case 'scientific':
|
|
22
|
+
return magnitude
|
|
23
|
+
case 'engineering':
|
|
24
|
+
return Math.floor(magnitude / 3) * 3
|
|
25
|
+
default: {
|
|
26
|
+
// Let exponent be an implementation- and locale-dependent (ILD) integer by which to scale a
|
|
27
|
+
// number of the given magnitude in compact notation for the current locale.
|
|
28
|
+
const {compactDisplay, style, currencyDisplay} = internalSlots
|
|
29
|
+
let thresholdMap
|
|
30
|
+
if (style === 'currency' && currencyDisplay !== 'name') {
|
|
31
|
+
const currency =
|
|
32
|
+
dataLocaleData.numbers.currency[numberingSystem] ||
|
|
33
|
+
dataLocaleData.numbers.currency[dataLocaleData.numbers.nu[0]]
|
|
34
|
+
thresholdMap = currency.short
|
|
35
|
+
} else {
|
|
36
|
+
const decimal =
|
|
37
|
+
dataLocaleData.numbers.decimal[numberingSystem] ||
|
|
38
|
+
dataLocaleData.numbers.decimal[dataLocaleData.numbers.nu[0]]
|
|
39
|
+
thresholdMap = compactDisplay === 'long' ? decimal.long : decimal.short
|
|
40
|
+
}
|
|
41
|
+
if (!thresholdMap) {
|
|
42
|
+
return 0
|
|
43
|
+
}
|
|
44
|
+
const num = String(10 ** magnitude) as DecimalFormatNum
|
|
45
|
+
const thresholds = Object.keys(thresholdMap) as DecimalFormatNum[] // TODO: this can be pre-processed
|
|
46
|
+
if (num < thresholds[0]) {
|
|
47
|
+
return 0
|
|
48
|
+
}
|
|
49
|
+
if (num > thresholds[thresholds.length - 1]) {
|
|
50
|
+
return thresholds[thresholds.length - 1].length - 1
|
|
51
|
+
}
|
|
52
|
+
const i = thresholds.indexOf(num)
|
|
53
|
+
if (i === -1) {
|
|
54
|
+
return 0
|
|
55
|
+
}
|
|
56
|
+
// See https://unicode.org/reports/tr35/tr35-numbers.html#Compact_Number_Formats
|
|
57
|
+
// Special handling if the pattern is precisely `0`.
|
|
58
|
+
const magnitudeKey = thresholds[i]
|
|
59
|
+
// TODO: do we need to handle plural here?
|
|
60
|
+
const compactPattern = thresholdMap[magnitudeKey].other
|
|
61
|
+
if (compactPattern === '0') {
|
|
62
|
+
return 0
|
|
63
|
+
}
|
|
64
|
+
// Example: in zh-TW, `10000000` maps to `0000萬`. So we need to return 8 - 4 = 4 here.
|
|
65
|
+
return (
|
|
66
|
+
magnitudeKey.length -
|
|
67
|
+
thresholdMap[magnitudeKey].other.match(/0+/)![0].length
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import {HasOwnProperty} from '../262'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* https://tc39.es/ecma402/#sec-currencydigits
|
|
5
|
+
*/
|
|
6
|
+
export function CurrencyDigits(
|
|
7
|
+
c: string,
|
|
8
|
+
{currencyDigitsData}: {currencyDigitsData: Record<string, number>}
|
|
9
|
+
): number {
|
|
10
|
+
return HasOwnProperty(currencyDigitsData, c)
|
|
11
|
+
? (currencyDigitsData as Record<string, number>)[c]
|
|
12
|
+
: 2
|
|
13
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {PartitionNumberPattern} from './PartitionNumberPattern'
|
|
2
|
+
import {ArrayCreate} from '../262'
|
|
3
|
+
import {NumberFormatInternal, NumberFormatPart} from '../types/number'
|
|
4
|
+
|
|
5
|
+
export function FormatNumericToParts(
|
|
6
|
+
nf: Intl.NumberFormat,
|
|
7
|
+
x: number,
|
|
8
|
+
implDetails: {
|
|
9
|
+
getInternalSlots(nf: Intl.NumberFormat): NumberFormatInternal
|
|
10
|
+
}
|
|
11
|
+
): NumberFormatPart[] {
|
|
12
|
+
const parts = PartitionNumberPattern(nf, x, implDetails)
|
|
13
|
+
const result = ArrayCreate(0) as NumberFormatPart[]
|
|
14
|
+
|
|
15
|
+
for (const part of parts) {
|
|
16
|
+
result.push({
|
|
17
|
+
type: part.type,
|
|
18
|
+
value: part.value,
|
|
19
|
+
})
|
|
20
|
+
}
|
|
21
|
+
return result
|
|
22
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import {SameValue} from '../262'
|
|
2
|
+
import {ToRawPrecision} from './ToRawPrecision'
|
|
3
|
+
import {repeat} from '../utils'
|
|
4
|
+
import {
|
|
5
|
+
NumberFormatDigitInternalSlots,
|
|
6
|
+
RawNumberFormatResult,
|
|
7
|
+
} from '../types/number'
|
|
8
|
+
import {ToRawFixed} from './ToRawFixed'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* https://tc39.es/ecma402/#sec-formatnumberstring
|
|
12
|
+
*/
|
|
13
|
+
export function FormatNumericToString(
|
|
14
|
+
intlObject: Pick<
|
|
15
|
+
NumberFormatDigitInternalSlots,
|
|
16
|
+
| 'roundingType'
|
|
17
|
+
| 'minimumSignificantDigits'
|
|
18
|
+
| 'maximumSignificantDigits'
|
|
19
|
+
| 'minimumIntegerDigits'
|
|
20
|
+
| 'minimumFractionDigits'
|
|
21
|
+
| 'maximumFractionDigits'
|
|
22
|
+
>,
|
|
23
|
+
x: number
|
|
24
|
+
) {
|
|
25
|
+
const isNegative = x < 0 || SameValue(x, -0)
|
|
26
|
+
if (isNegative) {
|
|
27
|
+
x = -x
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let result: RawNumberFormatResult
|
|
31
|
+
|
|
32
|
+
const rourndingType = intlObject.roundingType
|
|
33
|
+
|
|
34
|
+
switch (rourndingType) {
|
|
35
|
+
case 'significantDigits':
|
|
36
|
+
result = ToRawPrecision(
|
|
37
|
+
x,
|
|
38
|
+
intlObject.minimumSignificantDigits!,
|
|
39
|
+
intlObject.maximumSignificantDigits!
|
|
40
|
+
)
|
|
41
|
+
break
|
|
42
|
+
case 'fractionDigits':
|
|
43
|
+
result = ToRawFixed(
|
|
44
|
+
x,
|
|
45
|
+
intlObject.minimumFractionDigits!,
|
|
46
|
+
intlObject.maximumFractionDigits!
|
|
47
|
+
)
|
|
48
|
+
break
|
|
49
|
+
default:
|
|
50
|
+
result = ToRawPrecision(x, 1, 2)
|
|
51
|
+
if (result.integerDigitsCount > 1) {
|
|
52
|
+
result = ToRawFixed(x, 0, 0)
|
|
53
|
+
}
|
|
54
|
+
break
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
x = result.roundedNumber
|
|
58
|
+
let string = result.formattedString
|
|
59
|
+
const int = result.integerDigitsCount
|
|
60
|
+
const minInteger = intlObject.minimumIntegerDigits
|
|
61
|
+
|
|
62
|
+
if (int < minInteger) {
|
|
63
|
+
const forwardZeros = repeat('0', minInteger - int)
|
|
64
|
+
string = forwardZeros + string
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (isNegative) {
|
|
68
|
+
x = -x
|
|
69
|
+
}
|
|
70
|
+
return {roundedNumber: x, formattedString: string}
|
|
71
|
+
}
|