@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.
Files changed (277) hide show
  1. package/262.ts +372 -0
  2. package/BUILD +97 -0
  3. package/CHANGELOG.md +709 -0
  4. package/CanonicalizeLocaleList.ts +8 -0
  5. package/CanonicalizeTimeZoneName.ts +29 -0
  6. package/CoerceOptionsToObject.ts +13 -0
  7. package/DefaultNumberOption.ts +28 -0
  8. package/GetNumberOption.ts +29 -0
  9. package/GetOption.ts +38 -0
  10. package/GetOptionsObject.ts +14 -0
  11. package/IsSanctionedSimpleUnitIdentifier.ts +66 -0
  12. package/IsValidTimeZoneName.ts +27 -0
  13. package/IsWellFormedCurrencyCode.ts +23 -0
  14. package/IsWellFormedUnitIdentifier.ts +32 -0
  15. package/LICENSE.md +0 -0
  16. package/NumberFormat/ComputeExponent.ts +49 -0
  17. package/NumberFormat/ComputeExponentForMagnitude.ts +71 -0
  18. package/NumberFormat/CurrencyDigits.ts +13 -0
  19. package/NumberFormat/FormatNumericToParts.ts +22 -0
  20. package/NumberFormat/FormatNumericToString.ts +71 -0
  21. package/NumberFormat/InitializeNumberFormat.ts +147 -0
  22. package/NumberFormat/PartitionNumberPattern.ts +86 -0
  23. package/NumberFormat/SetNumberFormatDigitOptions.ts +45 -0
  24. package/NumberFormat/SetNumberFormatUnitOptions.ts +77 -0
  25. package/NumberFormat/ToRawFixed.ts +56 -0
  26. package/NumberFormat/ToRawPrecision.ts +86 -0
  27. package/NumberFormat/digit-mapping.generated.ts +1 -0
  28. package/NumberFormat/format_to_parts.ts +571 -0
  29. package/PartitionPattern.ts +38 -0
  30. package/README.md +0 -0
  31. package/SupportedLocales.ts +31 -0
  32. package/data.ts +9 -0
  33. package/index.ts +45 -0
  34. package/package.json +3 -3
  35. package/regex.generated.ts +2 -0
  36. package/scripts/digit-mapping.ts +109 -0
  37. package/scripts/regex-gen.ts +19 -0
  38. package/tests/PartitionPattern.test.ts +38 -0
  39. package/tests/ToRawFixed.test.tsx +41 -0
  40. package/tests/ToRawPrecision.test.tsx +65 -0
  41. package/tsconfig.json +5 -0
  42. package/types/core.ts +11 -0
  43. package/types/date-time.ts +199 -0
  44. package/types/displaynames.ts +48 -0
  45. package/types/list.ts +22 -0
  46. package/types/number.ts +240 -0
  47. package/types/plural-rules.ts +18 -0
  48. package/types/relative-time.ts +74 -0
  49. package/utils.ts +128 -0
  50. package/262.d.ts +0 -92
  51. package/262.d.ts.map +0 -1
  52. package/262.js +0 -362
  53. package/CanonicalizeLocaleList.d.ts +0 -6
  54. package/CanonicalizeLocaleList.d.ts.map +0 -1
  55. package/CanonicalizeLocaleList.js +0 -12
  56. package/CanonicalizeTimeZoneName.d.ts +0 -9
  57. package/CanonicalizeTimeZoneName.d.ts.map +0 -1
  58. package/CanonicalizeTimeZoneName.js +0 -21
  59. package/CoerceOptionsToObject.d.ts +0 -7
  60. package/CoerceOptionsToObject.d.ts.map +0 -1
  61. package/CoerceOptionsToObject.js +0 -16
  62. package/DefaultNumberOption.d.ts +0 -9
  63. package/DefaultNumberOption.d.ts.map +0 -1
  64. package/DefaultNumberOption.js +0 -14
  65. package/GetNumberOption.d.ts +0 -10
  66. package/GetNumberOption.d.ts.map +0 -1
  67. package/GetNumberOption.js +0 -18
  68. package/GetOption.d.ts +0 -10
  69. package/GetOption.d.ts.map +0 -1
  70. package/GetOption.js +0 -35
  71. package/GetOptionsObject.d.ts +0 -7
  72. package/GetOptionsObject.d.ts.map +0 -1
  73. package/GetOptionsObject.js +0 -18
  74. package/IsSanctionedSimpleUnitIdentifier.d.ts +0 -14
  75. package/IsSanctionedSimpleUnitIdentifier.d.ts.map +0 -1
  76. package/IsSanctionedSimpleUnitIdentifier.js +0 -68
  77. package/IsValidTimeZoneName.d.ts +0 -10
  78. package/IsValidTimeZoneName.d.ts.map +0 -1
  79. package/IsValidTimeZoneName.js +0 -23
  80. package/IsWellFormedCurrencyCode.d.ts +0 -5
  81. package/IsWellFormedCurrencyCode.d.ts.map +0 -1
  82. package/IsWellFormedCurrencyCode.js +0 -25
  83. package/IsWellFormedUnitIdentifier.d.ts +0 -6
  84. package/IsWellFormedUnitIdentifier.d.ts.map +0 -1
  85. package/IsWellFormedUnitIdentifier.js +0 -32
  86. package/NumberFormat/ComputeExponent.d.ts +0 -12
  87. package/NumberFormat/ComputeExponent.d.ts.map +0 -1
  88. package/NumberFormat/ComputeExponent.js +0 -43
  89. package/NumberFormat/ComputeExponentForMagnitude.d.ts +0 -10
  90. package/NumberFormat/ComputeExponentForMagnitude.d.ts.map +0 -1
  91. package/NumberFormat/ComputeExponentForMagnitude.js +0 -64
  92. package/NumberFormat/CurrencyDigits.d.ts +0 -7
  93. package/NumberFormat/CurrencyDigits.d.ts.map +0 -1
  94. package/NumberFormat/CurrencyDigits.js +0 -14
  95. package/NumberFormat/FormatNumericToParts.d.ts +0 -5
  96. package/NumberFormat/FormatNumericToParts.d.ts.map +0 -1
  97. package/NumberFormat/FormatNumericToParts.js +0 -18
  98. package/NumberFormat/FormatNumericToString.d.ts +0 -9
  99. package/NumberFormat/FormatNumericToString.d.ts.map +0 -1
  100. package/NumberFormat/FormatNumericToString.js +0 -45
  101. package/NumberFormat/InitializeNumberFormat.d.ts +0 -13
  102. package/NumberFormat/InitializeNumberFormat.d.ts.map +0 -1
  103. package/NumberFormat/InitializeNumberFormat.js +0 -68
  104. package/NumberFormat/PartitionNumberPattern.d.ts +0 -8
  105. package/NumberFormat/PartitionNumberPattern.d.ts.map +0 -1
  106. package/NumberFormat/PartitionNumberPattern.js +0 -80
  107. package/NumberFormat/SetNumberFormatDigitOptions.d.ts +0 -6
  108. package/NumberFormat/SetNumberFormatDigitOptions.d.ts.map +0 -1
  109. package/NumberFormat/SetNumberFormatDigitOptions.js +0 -40
  110. package/NumberFormat/SetNumberFormatUnitOptions.d.ts +0 -8
  111. package/NumberFormat/SetNumberFormatUnitOptions.d.ts.map +0 -1
  112. package/NumberFormat/SetNumberFormatUnitOptions.js +0 -43
  113. package/NumberFormat/ToRawFixed.d.ts +0 -10
  114. package/NumberFormat/ToRawFixed.d.ts.map +0 -1
  115. package/NumberFormat/ToRawFixed.js +0 -55
  116. package/NumberFormat/ToRawPrecision.d.ts +0 -3
  117. package/NumberFormat/ToRawPrecision.d.ts.map +0 -1
  118. package/NumberFormat/ToRawPrecision.js +0 -78
  119. package/NumberFormat/digit-mapping.generated.d.ts +0 -2
  120. package/NumberFormat/digit-mapping.generated.d.ts.map +0 -1
  121. package/NumberFormat/digit-mapping.generated.js +0 -4
  122. package/NumberFormat/format_to_parts.d.ts +0 -22
  123. package/NumberFormat/format_to_parts.d.ts.map +0 -1
  124. package/NumberFormat/format_to_parts.js +0 -424
  125. package/PartitionPattern.d.ts +0 -9
  126. package/PartitionPattern.d.ts.map +0 -1
  127. package/PartitionPattern.js +0 -39
  128. package/SupportedLocales.d.ts +0 -10
  129. package/SupportedLocales.d.ts.map +0 -1
  130. package/SupportedLocales.js +0 -24
  131. package/data.d.ts +0 -6
  132. package/data.d.ts.map +0 -1
  133. package/data.js +0 -17
  134. package/index.d.ts +0 -37
  135. package/index.d.ts.map +0 -1
  136. package/index.js +0 -48
  137. package/lib/262.d.ts +0 -92
  138. package/lib/262.d.ts.map +0 -1
  139. package/lib/262.js +0 -336
  140. package/lib/CanonicalizeLocaleList.d.ts +0 -6
  141. package/lib/CanonicalizeLocaleList.d.ts.map +0 -1
  142. package/lib/CanonicalizeLocaleList.js +0 -8
  143. package/lib/CanonicalizeTimeZoneName.d.ts +0 -9
  144. package/lib/CanonicalizeTimeZoneName.d.ts.map +0 -1
  145. package/lib/CanonicalizeTimeZoneName.js +0 -17
  146. package/lib/CoerceOptionsToObject.d.ts +0 -7
  147. package/lib/CoerceOptionsToObject.d.ts.map +0 -1
  148. package/lib/CoerceOptionsToObject.js +0 -12
  149. package/lib/DefaultNumberOption.d.ts +0 -9
  150. package/lib/DefaultNumberOption.d.ts.map +0 -1
  151. package/lib/DefaultNumberOption.js +0 -10
  152. package/lib/GetNumberOption.d.ts +0 -10
  153. package/lib/GetNumberOption.d.ts.map +0 -1
  154. package/lib/GetNumberOption.js +0 -14
  155. package/lib/GetOption.d.ts +0 -10
  156. package/lib/GetOption.d.ts.map +0 -1
  157. package/lib/GetOption.js +0 -31
  158. package/lib/GetOptionsObject.d.ts +0 -7
  159. package/lib/GetOptionsObject.d.ts.map +0 -1
  160. package/lib/GetOptionsObject.js +0 -14
  161. package/lib/IsSanctionedSimpleUnitIdentifier.d.ts +0 -14
  162. package/lib/IsSanctionedSimpleUnitIdentifier.d.ts.map +0 -1
  163. package/lib/IsSanctionedSimpleUnitIdentifier.js +0 -63
  164. package/lib/IsValidTimeZoneName.d.ts +0 -10
  165. package/lib/IsValidTimeZoneName.d.ts.map +0 -1
  166. package/lib/IsValidTimeZoneName.js +0 -19
  167. package/lib/IsWellFormedCurrencyCode.d.ts +0 -5
  168. package/lib/IsWellFormedCurrencyCode.d.ts.map +0 -1
  169. package/lib/IsWellFormedCurrencyCode.js +0 -21
  170. package/lib/IsWellFormedUnitIdentifier.d.ts +0 -6
  171. package/lib/IsWellFormedUnitIdentifier.d.ts.map +0 -1
  172. package/lib/IsWellFormedUnitIdentifier.js +0 -28
  173. package/lib/NumberFormat/ComputeExponent.d.ts +0 -12
  174. package/lib/NumberFormat/ComputeExponent.d.ts.map +0 -1
  175. package/lib/NumberFormat/ComputeExponent.js +0 -39
  176. package/lib/NumberFormat/ComputeExponentForMagnitude.d.ts +0 -10
  177. package/lib/NumberFormat/ComputeExponentForMagnitude.d.ts.map +0 -1
  178. package/lib/NumberFormat/ComputeExponentForMagnitude.js +0 -60
  179. package/lib/NumberFormat/CurrencyDigits.d.ts +0 -7
  180. package/lib/NumberFormat/CurrencyDigits.d.ts.map +0 -1
  181. package/lib/NumberFormat/CurrencyDigits.js +0 -10
  182. package/lib/NumberFormat/FormatNumericToParts.d.ts +0 -5
  183. package/lib/NumberFormat/FormatNumericToParts.d.ts.map +0 -1
  184. package/lib/NumberFormat/FormatNumericToParts.js +0 -14
  185. package/lib/NumberFormat/FormatNumericToString.d.ts +0 -9
  186. package/lib/NumberFormat/FormatNumericToString.d.ts.map +0 -1
  187. package/lib/NumberFormat/FormatNumericToString.js +0 -41
  188. package/lib/NumberFormat/InitializeNumberFormat.d.ts +0 -13
  189. package/lib/NumberFormat/InitializeNumberFormat.d.ts.map +0 -1
  190. package/lib/NumberFormat/InitializeNumberFormat.js +0 -64
  191. package/lib/NumberFormat/PartitionNumberPattern.d.ts +0 -8
  192. package/lib/NumberFormat/PartitionNumberPattern.d.ts.map +0 -1
  193. package/lib/NumberFormat/PartitionNumberPattern.js +0 -75
  194. package/lib/NumberFormat/SetNumberFormatDigitOptions.d.ts +0 -6
  195. package/lib/NumberFormat/SetNumberFormatDigitOptions.d.ts.map +0 -1
  196. package/lib/NumberFormat/SetNumberFormatDigitOptions.js +0 -36
  197. package/lib/NumberFormat/SetNumberFormatUnitOptions.d.ts +0 -8
  198. package/lib/NumberFormat/SetNumberFormatUnitOptions.d.ts.map +0 -1
  199. package/lib/NumberFormat/SetNumberFormatUnitOptions.js +0 -39
  200. package/lib/NumberFormat/ToRawFixed.d.ts +0 -10
  201. package/lib/NumberFormat/ToRawFixed.d.ts.map +0 -1
  202. package/lib/NumberFormat/ToRawFixed.js +0 -51
  203. package/lib/NumberFormat/ToRawPrecision.d.ts +0 -3
  204. package/lib/NumberFormat/ToRawPrecision.d.ts.map +0 -1
  205. package/lib/NumberFormat/ToRawPrecision.js +0 -74
  206. package/lib/NumberFormat/digit-mapping.generated.d.ts +0 -2
  207. package/lib/NumberFormat/digit-mapping.generated.d.ts.map +0 -1
  208. package/lib/NumberFormat/digit-mapping.generated.js +0 -1
  209. package/lib/NumberFormat/format_to_parts.d.ts +0 -22
  210. package/lib/NumberFormat/format_to_parts.d.ts.map +0 -1
  211. package/lib/NumberFormat/format_to_parts.js +0 -421
  212. package/lib/PartitionPattern.d.ts +0 -9
  213. package/lib/PartitionPattern.d.ts.map +0 -1
  214. package/lib/PartitionPattern.js +0 -35
  215. package/lib/SupportedLocales.d.ts +0 -10
  216. package/lib/SupportedLocales.d.ts.map +0 -1
  217. package/lib/SupportedLocales.js +0 -20
  218. package/lib/data.d.ts +0 -6
  219. package/lib/data.d.ts.map +0 -1
  220. package/lib/data.js +0 -13
  221. package/lib/index.d.ts +0 -37
  222. package/lib/index.d.ts.map +0 -1
  223. package/lib/index.js +0 -34
  224. package/lib/regex.generated.d.ts +0 -2
  225. package/lib/regex.generated.d.ts.map +0 -1
  226. package/lib/regex.generated.js +0 -2
  227. package/lib/types/core.d.ts +0 -11
  228. package/lib/types/core.d.ts.map +0 -1
  229. package/lib/types/core.js +0 -1
  230. package/lib/types/date-time.d.ts +0 -135
  231. package/lib/types/date-time.d.ts.map +0 -1
  232. package/lib/types/date-time.js +0 -6
  233. package/lib/types/displaynames.d.ts +0 -47
  234. package/lib/types/displaynames.d.ts.map +0 -1
  235. package/lib/types/displaynames.js +0 -1
  236. package/lib/types/list.d.ts +0 -19
  237. package/lib/types/list.d.ts.map +0 -1
  238. package/lib/types/list.js +0 -1
  239. package/lib/types/number.d.ts +0 -147
  240. package/lib/types/number.d.ts.map +0 -1
  241. package/lib/types/number.js +0 -1
  242. package/lib/types/plural-rules.d.ts +0 -17
  243. package/lib/types/plural-rules.d.ts.map +0 -1
  244. package/lib/types/plural-rules.js +0 -1
  245. package/lib/types/relative-time.d.ts +0 -41
  246. package/lib/types/relative-time.d.ts.map +0 -1
  247. package/lib/types/relative-time.js +0 -1
  248. package/lib/utils.d.ts +0 -24
  249. package/lib/utils.d.ts.map +0 -1
  250. package/lib/utils.js +0 -78
  251. package/regex.generated.d.ts +0 -2
  252. package/regex.generated.d.ts.map +0 -1
  253. package/regex.generated.js +0 -5
  254. package/types/core.d.ts +0 -11
  255. package/types/core.d.ts.map +0 -1
  256. package/types/core.js +0 -2
  257. package/types/date-time.d.ts +0 -135
  258. package/types/date-time.d.ts.map +0 -1
  259. package/types/date-time.js +0 -9
  260. package/types/displaynames.d.ts +0 -47
  261. package/types/displaynames.d.ts.map +0 -1
  262. package/types/displaynames.js +0 -2
  263. package/types/list.d.ts +0 -19
  264. package/types/list.d.ts.map +0 -1
  265. package/types/list.js +0 -2
  266. package/types/number.d.ts +0 -147
  267. package/types/number.d.ts.map +0 -1
  268. package/types/number.js +0 -2
  269. package/types/plural-rules.d.ts +0 -17
  270. package/types/plural-rules.d.ts.map +0 -1
  271. package/types/plural-rules.js +0 -2
  272. package/types/relative-time.d.ts +0 -41
  273. package/types/relative-time.d.ts.map +0 -1
  274. package/types/relative-time.js +0 -2
  275. package/utils.d.ts +0 -24
  276. package/utils.d.ts.map +0 -1
  277. package/utils.js +0 -90
@@ -0,0 +1,147 @@
1
+ import {
2
+ NumberFormatInternal,
3
+ NumberFormatOptions,
4
+ NumberFormatLocaleInternalData,
5
+ } from '../types/number'
6
+ import {CanonicalizeLocaleList} from '../CanonicalizeLocaleList'
7
+ import {GetOption} from '../GetOption'
8
+ import {ResolveLocale} from '@formatjs/intl-localematcher'
9
+ import {SetNumberFormatUnitOptions} from './SetNumberFormatUnitOptions'
10
+ import {CurrencyDigits} from './CurrencyDigits'
11
+ import {SetNumberFormatDigitOptions} from './SetNumberFormatDigitOptions'
12
+ import {invariant} from '../utils'
13
+ import {CoerceOptionsToObject} from '../CoerceOptionsToObject'
14
+
15
+ /**
16
+ * https://tc39.es/ecma402/#sec-initializenumberformat
17
+ */
18
+ export function InitializeNumberFormat(
19
+ nf: Intl.NumberFormat,
20
+ locales: string | ReadonlyArray<string> | undefined,
21
+ opts: NumberFormatOptions | undefined,
22
+ {
23
+ getInternalSlots,
24
+ localeData,
25
+ availableLocales,
26
+ numberingSystemNames,
27
+ getDefaultLocale,
28
+ currencyDigitsData,
29
+ }: {
30
+ getInternalSlots(nf: Intl.NumberFormat): NumberFormatInternal
31
+ localeData: Record<string, NumberFormatLocaleInternalData | undefined>
32
+ availableLocales: Set<string>
33
+ numberingSystemNames: ReadonlyArray<string>
34
+ getDefaultLocale(): string
35
+ currencyDigitsData: Record<string, number>
36
+ }
37
+ ) {
38
+ // @ts-ignore
39
+ const requestedLocales: string[] = CanonicalizeLocaleList(locales)
40
+ const options = CoerceOptionsToObject<NumberFormatOptions>(opts)
41
+ const opt = Object.create(null)
42
+ const matcher = GetOption(
43
+ options,
44
+ 'localeMatcher',
45
+ 'string',
46
+ ['lookup', 'best fit'],
47
+ 'best fit'
48
+ )
49
+ opt.localeMatcher = matcher
50
+
51
+ const numberingSystem = GetOption(
52
+ options,
53
+ 'numberingSystem',
54
+ 'string',
55
+ undefined,
56
+ undefined
57
+ )
58
+ if (
59
+ numberingSystem !== undefined &&
60
+ numberingSystemNames.indexOf(numberingSystem) < 0
61
+ ) {
62
+ // 8.a. If numberingSystem does not match the Unicode Locale Identifier type nonterminal,
63
+ // throw a RangeError exception.
64
+ throw RangeError(`Invalid numberingSystems: ${numberingSystem}`)
65
+ }
66
+ opt.nu = numberingSystem
67
+
68
+ const r = ResolveLocale(
69
+ availableLocales,
70
+ requestedLocales,
71
+ opt,
72
+ // [[RelevantExtensionKeys]] slot, which is a constant
73
+ ['nu'],
74
+ localeData,
75
+ getDefaultLocale
76
+ )
77
+ const dataLocaleData = localeData[r.dataLocale]
78
+ invariant(!!dataLocaleData, `Missing locale data for ${r.dataLocale}`)
79
+ const internalSlots = getInternalSlots(nf)
80
+ internalSlots.locale = r.locale
81
+ internalSlots.dataLocale = r.dataLocale
82
+ internalSlots.numberingSystem = r.nu
83
+ internalSlots.dataLocaleData = dataLocaleData
84
+
85
+ SetNumberFormatUnitOptions(nf, options, {getInternalSlots})
86
+ const style = internalSlots.style
87
+
88
+ let mnfdDefault: number
89
+ let mxfdDefault: number
90
+ if (style === 'currency') {
91
+ const currency = internalSlots.currency
92
+ const cDigits = CurrencyDigits(currency!, {currencyDigitsData})
93
+ mnfdDefault = cDigits
94
+ mxfdDefault = cDigits
95
+ } else {
96
+ mnfdDefault = 0
97
+ mxfdDefault = style === 'percent' ? 0 : 3
98
+ }
99
+
100
+ const notation = GetOption(
101
+ options,
102
+ 'notation',
103
+ 'string',
104
+ ['standard', 'scientific', 'engineering', 'compact'],
105
+ 'standard'
106
+ )
107
+ internalSlots.notation = notation
108
+
109
+ SetNumberFormatDigitOptions(
110
+ internalSlots,
111
+ options,
112
+ mnfdDefault,
113
+ mxfdDefault,
114
+ notation
115
+ )
116
+
117
+ const compactDisplay = GetOption(
118
+ options,
119
+ 'compactDisplay',
120
+ 'string',
121
+ ['short', 'long'],
122
+ 'short'
123
+ )
124
+ if (notation === 'compact') {
125
+ internalSlots.compactDisplay = compactDisplay
126
+ }
127
+
128
+ const useGrouping = GetOption(
129
+ options,
130
+ 'useGrouping',
131
+ 'boolean',
132
+ undefined,
133
+ true
134
+ )
135
+ internalSlots.useGrouping = useGrouping
136
+
137
+ const signDisplay = GetOption(
138
+ options,
139
+ 'signDisplay',
140
+ 'string',
141
+ ['auto', 'never', 'always', 'exceptZero'],
142
+ 'auto'
143
+ )
144
+ internalSlots.signDisplay = signDisplay
145
+
146
+ return nf
147
+ }
@@ -0,0 +1,86 @@
1
+ import {NumberFormatInternal} from '../types/number'
2
+ import {FormatNumericToString} from './FormatNumericToString'
3
+ import {SameValue} from '../262'
4
+ import {ComputeExponent} from './ComputeExponent'
5
+ import formatToParts from './format_to_parts'
6
+
7
+ /**
8
+ * https://tc39.es/ecma402/#sec-formatnumberstring
9
+ */
10
+ export function PartitionNumberPattern(
11
+ numberFormat: Intl.NumberFormat,
12
+ x: number,
13
+ {
14
+ getInternalSlots,
15
+ }: {
16
+ getInternalSlots(nf: Intl.NumberFormat): NumberFormatInternal
17
+ }
18
+ ) {
19
+ const internalSlots = getInternalSlots(numberFormat)
20
+ const {pl, dataLocaleData, numberingSystem} = internalSlots
21
+ const symbols =
22
+ dataLocaleData.numbers.symbols[numberingSystem] ||
23
+ dataLocaleData.numbers.symbols[dataLocaleData.numbers.nu[0]]
24
+
25
+ let magnitude = 0
26
+ let exponent = 0
27
+ let n: string
28
+
29
+ if (isNaN(x)) {
30
+ n = symbols.nan
31
+ } else if (!isFinite(x)) {
32
+ n = symbols.infinity
33
+ } else {
34
+ if (internalSlots.style === 'percent') {
35
+ x *= 100
36
+ }
37
+ ;[exponent, magnitude] = ComputeExponent(numberFormat, x, {
38
+ getInternalSlots,
39
+ })
40
+ // Preserve more precision by doing multiplication when exponent is negative.
41
+ x = exponent < 0 ? x * 10 ** -exponent : x / 10 ** exponent
42
+ const formatNumberResult = FormatNumericToString(internalSlots, x)
43
+ n = formatNumberResult.formattedString
44
+ x = formatNumberResult.roundedNumber
45
+ }
46
+
47
+ // Based on https://tc39.es/ecma402/#sec-getnumberformatpattern
48
+ // We need to do this before `x` is rounded.
49
+ let sign: -1 | 0 | 1
50
+ const signDisplay = internalSlots.signDisplay
51
+ switch (signDisplay) {
52
+ case 'never':
53
+ sign = 0
54
+ break
55
+ case 'auto':
56
+ if (SameValue(x, 0) || x > 0 || isNaN(x)) {
57
+ sign = 0
58
+ } else {
59
+ sign = -1
60
+ }
61
+ break
62
+ case 'always':
63
+ if (SameValue(x, 0) || x > 0 || isNaN(x)) {
64
+ sign = 1
65
+ } else {
66
+ sign = -1
67
+ }
68
+ break
69
+ default:
70
+ // x === 0 -> x is 0 or x is -0
71
+ if (x === 0 || isNaN(x)) {
72
+ sign = 0
73
+ } else if (x > 0) {
74
+ sign = 1
75
+ } else {
76
+ sign = -1
77
+ }
78
+ }
79
+
80
+ return formatToParts(
81
+ {roundedNumber: x, formattedString: n, exponent, magnitude, sign},
82
+ internalSlots.dataLocaleData,
83
+ pl,
84
+ internalSlots
85
+ )
86
+ }
@@ -0,0 +1,45 @@
1
+ import {
2
+ NumberFormatDigitOptions,
3
+ NumberFormatNotation,
4
+ NumberFormatDigitInternalSlots,
5
+ } from '../types/number'
6
+ import {GetNumberOption} from '../GetNumberOption'
7
+ import {DefaultNumberOption} from '../DefaultNumberOption'
8
+
9
+ /**
10
+ * https://tc39.es/ecma402/#sec-setnfdigitoptions
11
+ */
12
+ export function SetNumberFormatDigitOptions(
13
+ internalSlots: NumberFormatDigitInternalSlots,
14
+ opts: NumberFormatDigitOptions,
15
+ mnfdDefault: number,
16
+ mxfdDefault: number,
17
+ notation: NumberFormatNotation
18
+ ) {
19
+ const mnid = GetNumberOption(opts, 'minimumIntegerDigits', 1, 21, 1)
20
+ let mnfd = opts.minimumFractionDigits
21
+ let mxfd = opts.maximumFractionDigits
22
+ let mnsd = opts.minimumSignificantDigits
23
+ let mxsd = opts.maximumSignificantDigits
24
+ internalSlots.minimumIntegerDigits = mnid
25
+ if (mnsd !== undefined || mxsd !== undefined) {
26
+ internalSlots.roundingType = 'significantDigits'
27
+ mnsd = DefaultNumberOption(mnsd, 1, 21, 1)
28
+ mxsd = DefaultNumberOption(mxsd, mnsd, 21, 21)
29
+ internalSlots.minimumSignificantDigits = mnsd
30
+ internalSlots.maximumSignificantDigits = mxsd
31
+ } else if (mnfd !== undefined || mxfd !== undefined) {
32
+ internalSlots.roundingType = 'fractionDigits'
33
+ mnfd = DefaultNumberOption(mnfd, 0, 20, mnfdDefault)
34
+ const mxfdActualDefault = Math.max(mnfd, mxfdDefault)
35
+ mxfd = DefaultNumberOption(mxfd, mnfd, 20, mxfdActualDefault)
36
+ internalSlots.minimumFractionDigits = mnfd
37
+ internalSlots.maximumFractionDigits = mxfd
38
+ } else if (notation === 'compact') {
39
+ internalSlots.roundingType = 'compactRounding'
40
+ } else {
41
+ internalSlots.roundingType = 'fractionDigits'
42
+ internalSlots.minimumFractionDigits = mnfdDefault
43
+ internalSlots.maximumFractionDigits = mxfdDefault
44
+ }
45
+ }
@@ -0,0 +1,77 @@
1
+ import {NumberFormatInternal, NumberFormatOptions} from '../types/number'
2
+ import {GetOption} from '../GetOption'
3
+ import {IsWellFormedCurrencyCode} from '../IsWellFormedCurrencyCode'
4
+ import {IsWellFormedUnitIdentifier} from '../IsWellFormedUnitIdentifier'
5
+
6
+ /**
7
+ * https://tc39.es/ecma402/#sec-setnumberformatunitoptions
8
+ */
9
+ export function SetNumberFormatUnitOptions(
10
+ nf: Intl.NumberFormat,
11
+ options: NumberFormatOptions = Object.create(null),
12
+ {
13
+ getInternalSlots,
14
+ }: {getInternalSlots(nf: Intl.NumberFormat): NumberFormatInternal}
15
+ ) {
16
+ const internalSlots = getInternalSlots(nf)
17
+ const style = GetOption(
18
+ options,
19
+ 'style',
20
+ 'string',
21
+ ['decimal', 'percent', 'currency', 'unit'],
22
+ 'decimal'
23
+ )
24
+ internalSlots.style = style
25
+ const currency = GetOption(
26
+ options,
27
+ 'currency',
28
+ 'string',
29
+ undefined,
30
+ undefined
31
+ )
32
+ if (currency !== undefined && !IsWellFormedCurrencyCode(currency)) {
33
+ throw RangeError('Malformed currency code')
34
+ }
35
+ if (style === 'currency' && currency === undefined) {
36
+ throw TypeError('currency cannot be undefined')
37
+ }
38
+ const currencyDisplay = GetOption(
39
+ options,
40
+ 'currencyDisplay',
41
+ 'string',
42
+ ['code', 'symbol', 'narrowSymbol', 'name'],
43
+ 'symbol'
44
+ )
45
+ const currencySign = GetOption(
46
+ options,
47
+ 'currencySign',
48
+ 'string',
49
+ ['standard', 'accounting'],
50
+ 'standard'
51
+ )
52
+
53
+ const unit = GetOption(options, 'unit', 'string', undefined, undefined)
54
+ if (unit !== undefined && !IsWellFormedUnitIdentifier(unit)) {
55
+ throw RangeError('Invalid unit argument for Intl.NumberFormat()')
56
+ }
57
+ if (style === 'unit' && unit === undefined) {
58
+ throw TypeError('unit cannot be undefined')
59
+ }
60
+ const unitDisplay = GetOption(
61
+ options,
62
+ 'unitDisplay',
63
+ 'string',
64
+ ['short', 'narrow', 'long'],
65
+ 'short'
66
+ )
67
+
68
+ if (style === 'currency') {
69
+ internalSlots.currency = currency!.toUpperCase()
70
+ internalSlots.currencyDisplay = currencyDisplay
71
+ internalSlots.currencySign = currencySign
72
+ }
73
+ if (style === 'unit') {
74
+ internalSlots.unit = unit
75
+ internalSlots.unitDisplay = unitDisplay
76
+ }
77
+ }
@@ -0,0 +1,56 @@
1
+ import {RawNumberFormatResult} from '../types/number'
2
+ import {repeat} from '../utils'
3
+
4
+ /**
5
+ * TODO: dedup with intl-pluralrules and support BigInt
6
+ * https://tc39.es/ecma402/#sec-torawfixed
7
+ * @param x a finite non-negative Number or BigInt
8
+ * @param minFraction and integer between 0 and 20
9
+ * @param maxFraction and integer between 0 and 20
10
+ */
11
+ export function ToRawFixed(
12
+ x: number,
13
+ minFraction: number,
14
+ maxFraction: number
15
+ ): RawNumberFormatResult {
16
+ const f = maxFraction
17
+ const n = Math.round(x * 10 ** f)
18
+ const xFinal = n / 10 ** f
19
+
20
+ // n is a positive integer, but it is possible to be greater than 1e21.
21
+ // In such case we will go the slow path.
22
+ // See also: https://tc39.es/ecma262/#sec-numeric-types-number-tostring
23
+ let m: string
24
+ if (n < 1e21) {
25
+ m = n.toString()
26
+ } else {
27
+ m = n.toString()
28
+ const [mantissa, exponent] = m.split('e')
29
+ m = mantissa.replace('.', '')
30
+ m = m + repeat('0', Math.max(+exponent - m.length + 1, 0))
31
+ }
32
+ let int: number
33
+ if (f !== 0) {
34
+ let k = m.length
35
+ if (k <= f) {
36
+ const z = repeat('0', f + 1 - k)
37
+ m = z + m
38
+ k = f + 1
39
+ }
40
+ const a = m.slice(0, k - f)
41
+ const b = m.slice(k - f)
42
+ m = `${a}.${b}`
43
+ int = a.length
44
+ } else {
45
+ int = m.length
46
+ }
47
+ let cut = maxFraction - minFraction
48
+ while (cut > 0 && m[m.length - 1] === '0') {
49
+ m = m.slice(0, -1)
50
+ cut--
51
+ }
52
+ if (m[m.length - 1] === '.') {
53
+ m = m.slice(0, -1)
54
+ }
55
+ return {formattedString: m, roundedNumber: xFinal, integerDigitsCount: int}
56
+ }
@@ -0,0 +1,86 @@
1
+ import {RawNumberFormatResult} from '../types/number'
2
+ import {repeat, getMagnitude} from '../utils'
3
+
4
+ export function ToRawPrecision(
5
+ x: number,
6
+ minPrecision: number,
7
+ maxPrecision: number
8
+ ): RawNumberFormatResult {
9
+ const p = maxPrecision
10
+ let m: string
11
+ let e: number
12
+ let xFinal: number
13
+ if (x === 0) {
14
+ m = repeat('0', p)
15
+ e = 0
16
+ xFinal = 0
17
+ } else {
18
+ const xToString = x.toString()
19
+ // If xToString is formatted as scientific notation, the number is either very small or very
20
+ // large. If the precision of the formatted string is lower that requested max precision, we
21
+ // should still infer them from the formatted string, otherwise the formatted result might have
22
+ // precision loss (e.g. 1e41 will not have 0 in every trailing digits).
23
+ const xToStringExponentIndex = xToString.indexOf('e')
24
+ const [xToStringMantissa, xToStringExponent] = xToString.split('e')
25
+ const xToStringMantissaWithoutDecimalPoint = xToStringMantissa.replace(
26
+ '.',
27
+ ''
28
+ )
29
+
30
+ if (
31
+ xToStringExponentIndex >= 0 &&
32
+ xToStringMantissaWithoutDecimalPoint.length <= p
33
+ ) {
34
+ e = +xToStringExponent
35
+ m =
36
+ xToStringMantissaWithoutDecimalPoint +
37
+ repeat('0', p - xToStringMantissaWithoutDecimalPoint.length)
38
+ xFinal = x
39
+ } else {
40
+ e = getMagnitude(x)
41
+
42
+ const decimalPlaceOffset = e - p + 1
43
+ // n is the integer containing the required precision digits. To derive the formatted string,
44
+ // we will adjust its decimal place in the logic below.
45
+ let n = Math.round(adjustDecimalPlace(x, decimalPlaceOffset))
46
+
47
+ // The rounding caused the change of magnitude, so we should increment `e` by 1.
48
+ if (adjustDecimalPlace(n, p - 1) >= 10) {
49
+ e = e + 1
50
+ // Divide n by 10 to swallow one precision.
51
+ n = Math.floor(n / 10)
52
+ }
53
+
54
+ m = n.toString()
55
+ // Equivalent of n * 10 ** (e - p + 1)
56
+ xFinal = adjustDecimalPlace(n, p - 1 - e)
57
+ }
58
+ }
59
+ let int: number
60
+ if (e >= p - 1) {
61
+ m = m + repeat('0', e - p + 1)
62
+ int = e + 1
63
+ } else if (e >= 0) {
64
+ m = `${m.slice(0, e + 1)}.${m.slice(e + 1)}`
65
+ int = e + 1
66
+ } else {
67
+ m = `0.${repeat('0', -e - 1)}${m}`
68
+ int = 1
69
+ }
70
+ if (m.indexOf('.') >= 0 && maxPrecision > minPrecision) {
71
+ let cut = maxPrecision - minPrecision
72
+ while (cut > 0 && m[m.length - 1] === '0') {
73
+ m = m.slice(0, -1)
74
+ cut--
75
+ }
76
+ if (m[m.length - 1] === '.') {
77
+ m = m.slice(0, -1)
78
+ }
79
+ }
80
+ return {formattedString: m, roundedNumber: xFinal, integerDigitsCount: int}
81
+
82
+ // x / (10 ** magnitude), but try to preserve as much floating point precision as possible.
83
+ function adjustDecimalPlace(x: number, magnitude: number): number {
84
+ return magnitude < 0 ? x * 10 ** -magnitude : x / 10 ** magnitude
85
+ }
86
+ }
@@ -0,0 +1 @@
1
+ export const digitMapping: Record<string, ReadonlyArray<string>> = {"adlm":["𞥐","𞥑","𞥒","𞥓","𞥔","𞥕","𞥖","𞥗","𞥘","𞥙"],"ahom":["𑜰","𑜱","𑜲","𑜳","𑜴","𑜵","𑜶","𑜷","𑜸","𑜹"],"arab":["٠","١","٢","٣","٤","٥","٦","٧","٨","٩"],"arabext":["۰","۱","۲","۳","۴","۵","۶","۷","۸","۹"],"bali":["᭐","᭑","᭒","᭓","᭔","᭕","᭖","᭗","᭘","᭙"],"beng":["০","১","২","৩","৪","৫","৬","৭","৮","৯"],"bhks":["𑱐","𑱑","𑱒","𑱓","𑱔","𑱕","𑱖","𑱗","𑱘","𑱙"],"brah":["𑁦","𑁧","𑁨","𑁩","𑁪","𑁫","𑁬","𑁭","𑁮","𑁯"],"cakm":["𑄶","𑄷","𑄸","𑄹","𑄺","𑄻","𑄼","𑄽","𑄾","𑄿"],"cham":["꩐","꩑","꩒","꩓","꩔","꩕","꩖","꩗","꩘","꩙"],"deva":["०","१","२","३","४","५","६","७","८","९"],"diak":["𑥐","𑥑","𑥒","𑥓","𑥔","𑥕","𑥖","𑥗","𑥘","𑥙"],"fullwide":["0","1","2","3","4","5","6","7","8","9"],"gong":["𑶠","𑶡","𑶢","𑶣","𑶤","𑶥","𑶦","𑶧","𑶨","𑶩"],"gonm":["𑵐","𑵑","𑵒","𑵓","𑵔","𑵕","𑵖","𑵗","𑵘","𑵙"],"gujr":["૦","૧","૨","૩","૪","૫","૬","૭","૮","૯"],"guru":["੦","੧","੨","੩","੪","੫","੬","੭","੮","੯"],"hanidec":["〇","一","二","三","四","五","六","七","八","九"],"hmng":["𖭐","𖭑","𖭒","𖭓","𖭔","𖭕","𖭖","𖭗","𖭘","𖭙"],"hmnp":["𞅀","𞅁","𞅂","𞅃","𞅄","𞅅","𞅆","𞅇","𞅈","𞅉"],"java":["꧐","꧑","꧒","꧓","꧔","꧕","꧖","꧗","꧘","꧙"],"kali":["꤀","꤁","꤂","꤃","꤄","꤅","꤆","꤇","꤈","꤉"],"khmr":["០","១","២","៣","៤","៥","៦","៧","៨","៩"],"knda":["೦","೧","೨","೩","೪","೫","೬","೭","೮","೯"],"lana":["᪀","᪁","᪂","᪃","᪄","᪅","᪆","᪇","᪈","᪉"],"lanatham":["᪐","᪑","᪒","᪓","᪔","᪕","᪖","᪗","᪘","᪙"],"laoo":["໐","໑","໒","໓","໔","໕","໖","໗","໘","໙"],"lepc":["᪐","᪑","᪒","᪓","᪔","᪕","᪖","᪗","᪘","᪙"],"limb":["᥆","᥇","᥈","᥉","᥊","᥋","᥌","᥍","᥎","᥏"],"mathbold":["𝟎","𝟏","𝟐","𝟑","𝟒","𝟓","𝟔","𝟕","𝟖","𝟗"],"mathdbl":["𝟘","𝟙","𝟚","𝟛","𝟜","𝟝","𝟞","𝟟","𝟠","𝟡"],"mathmono":["𝟶","𝟷","𝟸","𝟹","𝟺","𝟻","𝟼","𝟽","𝟾","𝟿"],"mathsanb":["𝟬","𝟭","𝟮","𝟯","𝟰","𝟱","𝟲","𝟳","𝟴","𝟵"],"mathsans":["𝟢","𝟣","𝟤","𝟥","𝟦","𝟧","𝟨","𝟩","𝟪","𝟫"],"mlym":["൦","൧","൨","൩","൪","൫","൬","൭","൮","൯"],"modi":["𑙐","𑙑","𑙒","𑙓","𑙔","𑙕","𑙖","𑙗","𑙘","𑙙"],"mong":["᠐","᠑","᠒","᠓","᠔","᠕","᠖","᠗","᠘","᠙"],"mroo":["𖩠","𖩡","𖩢","𖩣","𖩤","𖩥","𖩦","𖩧","𖩨","𖩩"],"mtei":["꯰","꯱","꯲","꯳","꯴","꯵","꯶","꯷","꯸","꯹"],"mymr":["၀","၁","၂","၃","၄","၅","၆","၇","၈","၉"],"mymrshan":["႐","႑","႒","႓","႔","႕","႖","႗","႘","႙"],"mymrtlng":["꧰","꧱","꧲","꧳","꧴","꧵","꧶","꧷","꧸","꧹"],"newa":["𑑐","𑑑","𑑒","𑑓","𑑔","𑑕","𑑖","𑑗","𑑘","𑑙"],"nkoo":["߀","߁","߂","߃","߄","߅","߆","߇","߈","߉"],"olck":["᱐","᱑","᱒","᱓","᱔","᱕","᱖","᱗","᱘","᱙"],"orya":["୦","୧","୨","୩","୪","୫","୬","୭","୮","୯"],"osma":["𐒠","𐒡","𐒢","𐒣","𐒤","𐒥","𐒦","𐒧","𐒨","𐒩"],"rohg":["𐴰","𐴱","𐴲","𐴳","𐴴","𐴵","𐴶","𐴷","𐴸","𐴹"],"saur":["꣐","꣑","꣒","꣓","꣔","꣕","꣖","꣗","꣘","꣙"],"segment":["🯰","🯱","🯲","🯳","🯴","🯵","🯶","🯷","🯸","🯹"],"shrd":["𑇐","𑇑","𑇒","𑇓","𑇔","𑇕","𑇖","𑇗","𑇘","𑇙"],"sind":["𑋰","𑋱","𑋲","𑋳","𑋴","𑋵","𑋶","𑋷","𑋸","𑋹"],"sinh":["෦","෧","෨","෩","෪","෫","෬","෭","෮","෯"],"sora":["𑃰","𑃱","𑃲","𑃳","𑃴","𑃵","𑃶","𑃷","𑃸","𑃹"],"sund":["᮰","᮱","᮲","᮳","᮴","᮵","᮶","᮷","᮸","᮹"],"takr":["𑛀","𑛁","𑛂","𑛃","𑛄","𑛅","𑛆","𑛇","𑛈","𑛉"],"talu":["᧐","᧑","᧒","᧓","᧔","᧕","᧖","᧗","᧘","᧙"],"tamldec":["௦","௧","௨","௩","௪","௫","௬","௭","௮","௯"],"telu":["౦","౧","౨","౩","౪","౫","౬","౭","౮","౯"],"thai":["๐","๑","๒","๓","๔","๕","๖","๗","๘","๙"],"tibt":["༠","༡","༢","༣","༤","༥","༦","༧","༨","༩"],"tirh":["𑓐","𑓑","𑓒","𑓓","𑓔","𑓕","𑓖","𑓗","𑓘","𑓙"],"vaii":["ᘠ","ᘡ","ᘢ","ᘣ","ᘤ","ᘥ","ᘦ","ᘧ","ᘨ","ᘩ"],"wara":["𑣠","𑣡","𑣢","𑣣","𑣤","𑣥","𑣦","𑣧","𑣨","𑣩"],"wcho":["𞋰","𞋱","𞋲","𞋳","𞋴","𞋵","𞋶","𞋷","𞋸","𞋹"]};