n2words 4.0.0 → 5.1.0
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/CHANGELOG.md +53 -0
- package/README.md +14 -12
- package/dist/am-ET.js +2 -2
- package/dist/am-ET.umd.js +2 -2
- package/dist/am-Latn-ET.js +2 -2
- package/dist/am-Latn-ET.umd.js +2 -2
- package/dist/ar-SA.js +2 -2
- package/dist/ar-SA.umd.js +2 -2
- package/dist/az-AZ.js +2 -2
- package/dist/az-AZ.umd.js +2 -2
- package/dist/bn-BD.js +2 -2
- package/dist/bn-BD.umd.js +2 -2
- package/dist/cs-CZ.js +2 -2
- package/dist/cs-CZ.umd.js +2 -2
- package/dist/da-DK.js +2 -2
- package/dist/da-DK.umd.js +2 -2
- package/dist/de-DE.js +2 -2
- package/dist/de-DE.umd.js +2 -2
- package/dist/el-GR.js +2 -2
- package/dist/el-GR.umd.js +2 -2
- package/dist/en-AU.js +2 -2
- package/dist/en-AU.umd.js +2 -2
- package/dist/en-BD.js +2 -2
- package/dist/en-BD.umd.js +2 -2
- package/dist/en-CA.js +2 -2
- package/dist/en-CA.umd.js +2 -2
- package/dist/en-GB.js +2 -2
- package/dist/en-GB.umd.js +2 -2
- package/dist/en-GH.js +2 -2
- package/dist/en-GH.umd.js +2 -2
- package/dist/en-IE.js +2 -2
- package/dist/en-IE.umd.js +2 -2
- package/dist/en-IN.js +2 -2
- package/dist/en-IN.umd.js +2 -2
- package/dist/en-KE.js +2 -2
- package/dist/en-KE.umd.js +2 -2
- package/dist/en-MY.js +2 -2
- package/dist/en-MY.umd.js +2 -2
- package/dist/en-NG.js +2 -2
- package/dist/en-NG.umd.js +2 -2
- package/dist/en-NZ.js +2 -2
- package/dist/en-NZ.umd.js +2 -2
- package/dist/en-PH.js +2 -2
- package/dist/en-PH.umd.js +2 -2
- package/dist/en-PK.js +2 -2
- package/dist/en-PK.umd.js +2 -2
- package/dist/en-SG.js +2 -2
- package/dist/en-SG.umd.js +2 -2
- package/dist/en-US.js +2 -2
- package/dist/en-US.umd.js +2 -2
- package/dist/en-ZA.js +2 -2
- package/dist/en-ZA.umd.js +2 -2
- package/dist/es-ES.js +2 -2
- package/dist/es-ES.umd.js +2 -2
- package/dist/es-MX.js +2 -2
- package/dist/es-MX.umd.js +2 -2
- package/dist/es-US.js +2 -2
- package/dist/es-US.umd.js +2 -2
- package/dist/fa-IR.js +2 -2
- package/dist/fa-IR.umd.js +2 -2
- package/dist/fi-FI.js +2 -2
- package/dist/fi-FI.umd.js +2 -2
- package/dist/fil-PH.js +2 -2
- package/dist/fil-PH.umd.js +2 -2
- package/dist/fr-BE.js +2 -2
- package/dist/fr-BE.umd.js +2 -2
- package/dist/fr-FR.js +2 -2
- package/dist/fr-FR.umd.js +2 -2
- package/dist/gu-IN.js +2 -2
- package/dist/gu-IN.umd.js +2 -2
- package/dist/ha-NG.js +2 -2
- package/dist/ha-NG.umd.js +2 -2
- package/dist/hbo-IL.js +2 -2
- package/dist/hbo-IL.umd.js +2 -2
- package/dist/he-IL.js +2 -2
- package/dist/he-IL.umd.js +2 -2
- package/dist/hi-IN.js +2 -2
- package/dist/hi-IN.umd.js +2 -2
- package/dist/hr-HR.js +2 -2
- package/dist/hr-HR.umd.js +2 -2
- package/dist/hu-HU.js +2 -2
- package/dist/hu-HU.umd.js +2 -2
- package/dist/id-ID.js +2 -2
- package/dist/id-ID.umd.js +2 -2
- package/dist/it-IT.js +2 -2
- package/dist/it-IT.umd.js +2 -2
- package/dist/ja-JP.js +2 -2
- package/dist/ja-JP.umd.js +2 -2
- package/dist/ka-GE.js +2 -2
- package/dist/ka-GE.umd.js +2 -2
- package/dist/kn-IN.js +2 -2
- package/dist/kn-IN.umd.js +2 -2
- package/dist/ko-KR.js +2 -2
- package/dist/ko-KR.umd.js +2 -2
- package/dist/lt-LT.js +2 -2
- package/dist/lt-LT.umd.js +2 -2
- package/dist/lv-LV.js +2 -2
- package/dist/lv-LV.umd.js +2 -2
- package/dist/mr-IN.js +2 -2
- package/dist/mr-IN.umd.js +2 -2
- package/dist/ms-MY.js +2 -2
- package/dist/ms-MY.umd.js +2 -2
- package/dist/nb-NO.js +2 -2
- package/dist/nb-NO.umd.js +2 -2
- package/dist/nl-NL.js +2 -2
- package/dist/nl-NL.umd.js +2 -2
- package/dist/pa-IN.js +2 -2
- package/dist/pa-IN.umd.js +2 -2
- package/dist/pl-PL.js +2 -2
- package/dist/pl-PL.umd.js +2 -2
- package/dist/pt-BR.js +2 -0
- package/dist/pt-BR.umd.js +2 -0
- package/dist/pt-PT.js +2 -2
- package/dist/pt-PT.umd.js +2 -2
- package/dist/ro-RO.js +2 -2
- package/dist/ro-RO.umd.js +2 -2
- package/dist/ru-RU.js +2 -2
- package/dist/ru-RU.umd.js +2 -2
- package/dist/sr-Cyrl-RS.js +2 -2
- package/dist/sr-Cyrl-RS.umd.js +2 -2
- package/dist/sr-Latn-RS.js +2 -2
- package/dist/sr-Latn-RS.umd.js +2 -2
- package/dist/sv-SE.js +2 -2
- package/dist/sv-SE.umd.js +2 -2
- package/dist/sw-KE.js +2 -2
- package/dist/sw-KE.umd.js +2 -2
- package/dist/ta-IN.js +2 -2
- package/dist/ta-IN.umd.js +2 -2
- package/dist/te-IN.js +2 -2
- package/dist/te-IN.umd.js +2 -2
- package/dist/th-TH.js +2 -2
- package/dist/th-TH.umd.js +2 -2
- package/dist/tr-TR.js +2 -2
- package/dist/tr-TR.umd.js +2 -2
- package/dist/uk-UA.js +2 -2
- package/dist/uk-UA.umd.js +2 -2
- package/dist/ur-PK.js +2 -2
- package/dist/ur-PK.umd.js +2 -2
- package/dist/vi-VN.js +2 -2
- package/dist/vi-VN.umd.js +2 -2
- package/dist/yo-NG.js +2 -2
- package/dist/yo-NG.umd.js +2 -2
- package/dist/zh-Hans-CN.js +2 -2
- package/dist/zh-Hans-CN.umd.js +2 -2
- package/dist/zh-Hant-TW.js +2 -2
- package/dist/zh-Hant-TW.umd.js +2 -2
- package/package.json +53 -36
- package/src/am-ET.d.ts +3 -5
- package/src/am-ET.js +41 -16
- package/src/am-Latn-ET.d.ts +3 -5
- package/src/am-Latn-ET.js +45 -16
- package/src/ar-SA.d.ts +44 -18
- package/src/ar-SA.js +93 -40
- package/src/az-AZ.d.ts +3 -5
- package/src/az-AZ.js +58 -20
- package/src/bn-BD.d.ts +3 -5
- package/src/bn-BD.js +32 -16
- package/src/cs-CZ.d.ts +3 -6
- package/src/cs-CZ.js +66 -42
- package/src/da-DK.d.ts +3 -6
- package/src/da-DK.js +53 -48
- package/src/de-DE.d.ts +17 -11
- package/src/de-DE.js +88 -57
- package/src/el-GR.d.ts +3 -6
- package/src/el-GR.js +45 -32
- package/src/en-AU.d.ts +17 -11
- package/src/en-AU.js +56 -41
- package/src/en-BD.d.ts +17 -11
- package/src/en-BD.js +60 -41
- package/src/en-CA.d.ts +36 -18
- package/src/en-CA.js +67 -46
- package/src/en-GB.d.ts +17 -11
- package/src/en-GB.js +56 -41
- package/src/en-GH.d.ts +32 -3
- package/src/en-GH.js +104 -26
- package/src/en-IE.d.ts +17 -11
- package/src/en-IE.js +56 -41
- package/src/en-IN.d.ts +17 -11
- package/src/en-IN.js +60 -41
- package/src/en-KE.d.ts +28 -3
- package/src/en-KE.js +93 -26
- package/src/en-MY.d.ts +26 -3
- package/src/en-MY.js +91 -26
- package/src/en-NG.d.ts +17 -11
- package/src/en-NG.js +56 -41
- package/src/en-NZ.d.ts +32 -3
- package/src/en-NZ.js +85 -31
- package/src/en-PH.d.ts +32 -3
- package/src/en-PH.js +97 -26
- package/src/en-PK.d.ts +17 -11
- package/src/en-PK.js +60 -41
- package/src/en-SG.d.ts +28 -3
- package/src/en-SG.js +93 -26
- package/src/en-US.d.ts +36 -18
- package/src/en-US.js +70 -47
- package/src/en-ZA.d.ts +17 -11
- package/src/en-ZA.js +56 -41
- package/src/es-ES.d.ts +53 -21
- package/src/es-ES.js +104 -56
- package/src/es-MX.d.ts +53 -21
- package/src/es-MX.js +104 -56
- package/src/es-US.d.ts +53 -21
- package/src/es-US.js +92 -51
- package/src/fa-IR.d.ts +3 -5
- package/src/fa-IR.js +28 -13
- package/src/fi-FI.d.ts +3 -6
- package/src/fi-FI.js +47 -29
- package/src/fil-PH.d.ts +3 -5
- package/src/fil-PH.js +61 -28
- package/src/fr-BE.d.ts +31 -15
- package/src/fr-BE.js +128 -57
- package/src/fr-FR.d.ts +31 -16
- package/src/fr-FR.js +97 -60
- package/src/gu-IN.d.ts +3 -5
- package/src/gu-IN.js +31 -16
- package/src/ha-NG.d.ts +3 -5
- package/src/ha-NG.js +55 -27
- package/src/hbo-IL.d.ts +26 -12
- package/src/hbo-IL.js +92 -51
- package/src/he-IL.d.ts +17 -10
- package/src/he-IL.js +92 -50
- package/src/hi-IN.d.ts +3 -5
- package/src/hi-IN.js +30 -17
- package/src/hr-HR.d.ts +21 -10
- package/src/hr-HR.js +89 -33
- package/src/hu-HU.d.ts +3 -5
- package/src/hu-HU.js +57 -23
- package/src/id-ID.d.ts +3 -5
- package/src/id-ID.js +56 -23
- package/src/it-IT.d.ts +17 -11
- package/src/it-IT.js +74 -43
- package/src/ja-JP.d.ts +3 -6
- package/src/ja-JP.js +39 -26
- package/src/ka-GE.d.ts +3 -6
- package/src/ka-GE.js +38 -26
- package/src/kn-IN.d.ts +3 -5
- package/src/kn-IN.js +31 -16
- package/src/ko-KR.d.ts +3 -6
- package/src/ko-KR.js +34 -26
- package/src/lt-LT.d.ts +21 -11
- package/src/lt-LT.js +64 -42
- package/src/lv-LV.d.ts +21 -11
- package/src/lv-LV.js +79 -51
- package/src/mr-IN.d.ts +3 -5
- package/src/mr-IN.js +31 -16
- package/src/ms-MY.d.ts +3 -5
- package/src/ms-MY.js +58 -24
- package/src/nb-NO.d.ts +3 -6
- package/src/nb-NO.js +54 -34
- package/src/nl-NL.d.ts +41 -20
- package/src/nl-NL.js +111 -69
- package/src/pa-IN.d.ts +3 -5
- package/src/pa-IN.js +32 -16
- package/src/pl-PL.d.ts +21 -11
- package/src/pl-PL.js +69 -45
- package/src/pt-BR.d.ts +42 -0
- package/src/pt-BR.js +574 -0
- package/src/pt-PT.d.ts +17 -11
- package/src/pt-PT.js +80 -48
- package/src/ro-RO.d.ts +21 -11
- package/src/ro-RO.js +77 -39
- package/src/ru-RU.d.ts +35 -15
- package/src/ru-RU.js +100 -38
- package/src/sr-Cyrl-RS.d.ts +35 -15
- package/src/sr-Cyrl-RS.js +100 -38
- package/src/sr-Latn-RS.d.ts +35 -15
- package/src/sr-Latn-RS.js +100 -38
- package/src/sv-SE.d.ts +3 -6
- package/src/sv-SE.js +53 -34
- package/src/sw-KE.d.ts +3 -5
- package/src/sw-KE.js +50 -20
- package/src/ta-IN.d.ts +3 -5
- package/src/ta-IN.js +29 -17
- package/src/te-IN.d.ts +3 -5
- package/src/te-IN.js +31 -16
- package/src/th-TH.d.ts +3 -5
- package/src/th-TH.js +42 -19
- package/src/tr-TR.d.ts +17 -11
- package/src/tr-TR.js +63 -37
- package/src/uk-UA.d.ts +21 -10
- package/src/uk-UA.js +89 -33
- package/src/ur-PK.d.ts +3 -5
- package/src/ur-PK.js +32 -16
- package/src/utils/check-max.d.ts +26 -0
- package/src/utils/check-max.js +33 -0
- package/src/utils/expand-scientific.d.ts +0 -4
- package/src/utils/expand-scientific.js +7 -9
- package/src/utils/is-plain-object.d.ts +3 -4
- package/src/utils/is-plain-object.js +3 -4
- package/src/utils/parse-cardinal.d.ts +1 -2
- package/src/utils/parse-cardinal.js +12 -9
- package/src/utils/parse-currency.d.ts +1 -2
- package/src/utils/parse-currency.js +9 -11
- package/src/utils/parse-ordinal.d.ts +0 -1
- package/src/utils/parse-ordinal.js +9 -10
- package/src/utils/resolve-options.d.ts +17 -0
- package/src/utils/resolve-options.js +56 -0
- package/src/utils/scale.d.ts +49 -0
- package/src/utils/scale.js +65 -0
- package/src/vi-VN.d.ts +3 -6
- package/src/vi-VN.js +41 -28
- package/src/yo-NG.d.ts +3 -5
- package/src/yo-NG.js +49 -33
- package/src/zh-Hans-CN.d.ts +45 -20
- package/src/zh-Hans-CN.js +84 -31
- package/src/zh-Hant-TW.d.ts +45 -20
- package/src/zh-Hant-TW.js +85 -34
- package/src/utils/validate-options.d.ts +0 -8
- package/src/utils/validate-options.js +0 -16
package/src/en-AU.d.ts
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
|
+
export const cardinalMax: bigint;
|
|
2
|
+
export const ordinalMax: bigint;
|
|
3
|
+
export const currencyMax: bigint;
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {object} CurrencyOptions
|
|
6
|
+
* @property {boolean} [and] - Use "and" between dollars and cents
|
|
7
|
+
*/
|
|
8
|
+
/** @type {Required<CurrencyOptions>} */
|
|
9
|
+
export const currencyDefaults: Required<CurrencyOptions>;
|
|
10
|
+
export type CurrencyOptions = {
|
|
11
|
+
/**
|
|
12
|
+
* - Use "and" between dollars and cents
|
|
13
|
+
*/
|
|
14
|
+
and?: boolean | undefined;
|
|
15
|
+
};
|
|
1
16
|
/**
|
|
2
17
|
* Converts a numeric value to Australian English words.
|
|
3
|
-
*
|
|
4
18
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
19
|
* @returns {string} The number in English words
|
|
6
20
|
* @throws {TypeError} If value is not a valid numeric type
|
|
7
21
|
* @throws {Error} If value is not a valid number format
|
|
8
|
-
*
|
|
9
22
|
* @example
|
|
10
23
|
* toCardinal(42) // 'forty-two'
|
|
11
24
|
* toCardinal(101) // 'one hundred and one'
|
|
@@ -14,12 +27,10 @@
|
|
|
14
27
|
export function toCardinal(value: number | string | bigint): string;
|
|
15
28
|
/**
|
|
16
29
|
* Converts a numeric value to Australian English ordinal words.
|
|
17
|
-
*
|
|
18
30
|
* @param {number | string | bigint} value - The numeric value to convert (must be a positive integer)
|
|
19
31
|
* @returns {string} The number as ordinal words
|
|
20
32
|
* @throws {TypeError} If value is not a valid numeric type
|
|
21
33
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
22
|
-
*
|
|
23
34
|
* @example
|
|
24
35
|
* toOrdinal(1) // 'first'
|
|
25
36
|
* toOrdinal(42) // 'forty-second'
|
|
@@ -28,20 +39,15 @@ export function toCardinal(value: number | string | bigint): string;
|
|
|
28
39
|
export function toOrdinal(value: number | string | bigint): string;
|
|
29
40
|
/**
|
|
30
41
|
* Converts a numeric value to Australian English currency words.
|
|
31
|
-
*
|
|
32
42
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
33
|
-
* @param {
|
|
34
|
-
* @param {boolean} [options.and=true] - Use "and" between dollars and cents
|
|
43
|
+
* @param {CurrencyOptions} [options] - Optional configuration
|
|
35
44
|
* @returns {string} The amount in Australian English currency words
|
|
36
45
|
* @throws {TypeError} If value is not a valid numeric type
|
|
37
46
|
* @throws {Error} If value is not a valid number format
|
|
38
|
-
*
|
|
39
47
|
* @example
|
|
40
48
|
* toCurrency(42.50) // 'forty-two dollars and fifty cents'
|
|
41
49
|
* toCurrency(1) // 'one dollar'
|
|
42
50
|
* toCurrency(0.99) // 'ninety-nine cents'
|
|
43
51
|
* toCurrency(42.50, { and: false }) // 'forty-two dollars fifty cents'
|
|
44
52
|
*/
|
|
45
|
-
export function toCurrency(value: number | string | bigint, options?:
|
|
46
|
-
and?: boolean | undefined;
|
|
47
|
-
}): string;
|
|
53
|
+
export function toCurrency(value: number | string | bigint, options?: CurrencyOptions): string;
|
package/src/en-AU.js
CHANGED
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
import { parseCardinalValue } from './utils/parse-cardinal.js'
|
|
13
13
|
import { parseCurrencyValue } from './utils/parse-currency.js'
|
|
14
14
|
import { parseOrdinalValue } from './utils/parse-ordinal.js'
|
|
15
|
-
import {
|
|
15
|
+
import { checkMax } from './utils/check-max.js'
|
|
16
|
+
import { western } from './utils/scale.js'
|
|
17
|
+
import { resolveOptions } from './utils/resolve-options.js'
|
|
16
18
|
|
|
17
19
|
// ============================================================================
|
|
18
20
|
// Vocabulary (module-level constants)
|
|
@@ -27,9 +29,13 @@ const SCALES = [
|
|
|
27
29
|
'quintillion', 'sextillion', 'septillion', 'octillion', 'nonillion',
|
|
28
30
|
'decillion', 'undecillion', 'duodecillion', 'tredecillion', 'quattuordecillion',
|
|
29
31
|
'quindecillion', 'sexdecillion', 'septendecillion', 'octodecillion', 'novemdecillion',
|
|
30
|
-
'vigintillion'
|
|
32
|
+
'vigintillion',
|
|
31
33
|
]
|
|
32
34
|
|
|
35
|
+
export const cardinalMax = western(SCALES.length)
|
|
36
|
+
export const ordinalMax = western(SCALES.length)
|
|
37
|
+
export const currencyMax = western(SCALES.length)
|
|
38
|
+
|
|
33
39
|
const HUNDRED = 'hundred'
|
|
34
40
|
const ZERO = 'zero'
|
|
35
41
|
const NEGATIVE = 'minus'
|
|
@@ -55,11 +61,10 @@ const segmentResult = { word: '', hasHundred: false }
|
|
|
55
61
|
|
|
56
62
|
/**
|
|
57
63
|
* Builds words for a 0-999 segment (British-style with "and" after hundreds).
|
|
58
|
-
*
|
|
59
64
|
* @param {number} n - Number 0-999
|
|
60
|
-
* @returns {{ word: string, hasHundred: boolean }}
|
|
65
|
+
* @returns {{ word: string, hasHundred: boolean }} The segment words and whether a hundreds place was present
|
|
61
66
|
*/
|
|
62
|
-
function buildSegment
|
|
67
|
+
function buildSegment(n) {
|
|
63
68
|
if (n === 0) {
|
|
64
69
|
segmentResult.word = ''
|
|
65
70
|
segmentResult.hasHundred = false
|
|
@@ -74,9 +79,11 @@ function buildSegment (n) {
|
|
|
74
79
|
let tensOnes = ''
|
|
75
80
|
if (tens === 1) {
|
|
76
81
|
tensOnes = TEENS[ones]
|
|
77
|
-
}
|
|
82
|
+
}
|
|
83
|
+
else if (tens >= 2) {
|
|
78
84
|
tensOnes = ones > 0 ? TENS[tens] + '-' + ONES[ones] : TENS[tens]
|
|
79
|
-
}
|
|
85
|
+
}
|
|
86
|
+
else if (ones > 0) {
|
|
80
87
|
tensOnes = ONES[ones]
|
|
81
88
|
}
|
|
82
89
|
|
|
@@ -84,11 +91,13 @@ function buildSegment (n) {
|
|
|
84
91
|
if (hundreds > 0) {
|
|
85
92
|
if (tensOnes) {
|
|
86
93
|
segmentResult.word = ONES[hundreds] + ' ' + HUNDRED + ' and ' + tensOnes
|
|
87
|
-
}
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
88
96
|
segmentResult.word = ONES[hundreds] + ' ' + HUNDRED
|
|
89
97
|
}
|
|
90
98
|
segmentResult.hasHundred = true
|
|
91
|
-
}
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
92
101
|
segmentResult.word = tensOnes
|
|
93
102
|
segmentResult.hasHundred = false
|
|
94
103
|
}
|
|
@@ -102,11 +111,10 @@ function buildSegment (n) {
|
|
|
102
111
|
|
|
103
112
|
/**
|
|
104
113
|
* Converts a non-negative integer to English words.
|
|
105
|
-
*
|
|
106
114
|
* @param {bigint} n - Non-negative integer to convert
|
|
107
115
|
* @returns {string} English words
|
|
108
116
|
*/
|
|
109
|
-
function integerToWords
|
|
117
|
+
function integerToWords(n) {
|
|
110
118
|
if (n === 0n) return ZERO
|
|
111
119
|
|
|
112
120
|
// Fast path: numbers < 1000
|
|
@@ -136,11 +144,10 @@ function integerToWords (n) {
|
|
|
136
144
|
|
|
137
145
|
/**
|
|
138
146
|
* Builds words for numbers >= 1,000,000.
|
|
139
|
-
*
|
|
140
147
|
* @param {bigint} n - Number >= 1,000,000
|
|
141
148
|
* @returns {string} English words
|
|
142
149
|
*/
|
|
143
|
-
function buildLargeNumberWords
|
|
150
|
+
function buildLargeNumberWords(n) {
|
|
144
151
|
const segments = []
|
|
145
152
|
let temp = n
|
|
146
153
|
while (temp > 0n) {
|
|
@@ -176,7 +183,8 @@ function buildLargeNumberWords (n) {
|
|
|
176
183
|
if (i > 0) {
|
|
177
184
|
result += ' ' + SCALES[i - 1]
|
|
178
185
|
prevWasScale = true
|
|
179
|
-
}
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
180
188
|
prevWasScale = false
|
|
181
189
|
}
|
|
182
190
|
}
|
|
@@ -186,11 +194,10 @@ function buildLargeNumberWords (n) {
|
|
|
186
194
|
|
|
187
195
|
/**
|
|
188
196
|
* Converts decimal digits to English words.
|
|
189
|
-
*
|
|
190
197
|
* @param {string} decimalPart - Decimal digits (without the point)
|
|
191
198
|
* @returns {string} English words for decimal part
|
|
192
199
|
*/
|
|
193
|
-
function decimalPartToWords
|
|
200
|
+
function decimalPartToWords(decimalPart) {
|
|
194
201
|
let result = ''
|
|
195
202
|
|
|
196
203
|
let i = 0
|
|
@@ -211,19 +218,20 @@ function decimalPartToWords (decimalPart) {
|
|
|
211
218
|
|
|
212
219
|
/**
|
|
213
220
|
* Converts a numeric value to Australian English words.
|
|
214
|
-
*
|
|
215
221
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
216
222
|
* @returns {string} The number in English words
|
|
217
223
|
* @throws {TypeError} If value is not a valid numeric type
|
|
218
224
|
* @throws {Error} If value is not a valid number format
|
|
219
|
-
*
|
|
220
225
|
* @example
|
|
221
226
|
* toCardinal(42) // 'forty-two'
|
|
222
227
|
* toCardinal(101) // 'one hundred and one'
|
|
223
228
|
* toCardinal(1000000) // 'one million'
|
|
224
229
|
*/
|
|
225
|
-
function toCardinal
|
|
230
|
+
function toCardinal(value) {
|
|
226
231
|
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
232
|
+
// Both the integer part and the decimal's significant digits are spelled via
|
|
233
|
+
// the scale builder, so both must clear the ceiling.
|
|
234
|
+
checkMax(integerPart, cardinalMax, decimalPart)
|
|
227
235
|
|
|
228
236
|
let result = ''
|
|
229
237
|
|
|
@@ -246,11 +254,10 @@ function toCardinal (value) {
|
|
|
246
254
|
|
|
247
255
|
/**
|
|
248
256
|
* Builds ordinal words for a 0-999 segment.
|
|
249
|
-
*
|
|
250
257
|
* @param {number} n - Number 0-999
|
|
251
258
|
* @returns {string} Ordinal words for this segment
|
|
252
259
|
*/
|
|
253
|
-
function buildOrdinalSegment
|
|
260
|
+
function buildOrdinalSegment(n) {
|
|
254
261
|
const ones = n % 10
|
|
255
262
|
const tens = Math.trunc(n / 10) % 10
|
|
256
263
|
const hundreds = Math.trunc(n / 100)
|
|
@@ -258,20 +265,24 @@ function buildOrdinalSegment (n) {
|
|
|
258
265
|
let tensOnesOrdinal = ''
|
|
259
266
|
if (tens === 1) {
|
|
260
267
|
tensOnesOrdinal = ORDINAL_TEENS[ones]
|
|
261
|
-
}
|
|
268
|
+
}
|
|
269
|
+
else if (tens >= 2) {
|
|
262
270
|
if (ones > 0) {
|
|
263
271
|
tensOnesOrdinal = TENS[tens] + '-' + ORDINAL_ONES[ones]
|
|
264
|
-
}
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
265
274
|
tensOnesOrdinal = ORDINAL_TENS[tens]
|
|
266
275
|
}
|
|
267
|
-
}
|
|
276
|
+
}
|
|
277
|
+
else if (ones > 0) {
|
|
268
278
|
tensOnesOrdinal = ORDINAL_ONES[ones]
|
|
269
279
|
}
|
|
270
280
|
|
|
271
281
|
if (hundreds > 0) {
|
|
272
282
|
if (tensOnesOrdinal) {
|
|
273
283
|
return ONES[hundreds] + ' ' + HUNDRED + ' ' + tensOnesOrdinal
|
|
274
|
-
}
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
275
286
|
return ONES[hundreds] + ' hundredth'
|
|
276
287
|
}
|
|
277
288
|
}
|
|
@@ -281,11 +292,10 @@ function buildOrdinalSegment (n) {
|
|
|
281
292
|
|
|
282
293
|
/**
|
|
283
294
|
* Converts a positive integer to ordinal words.
|
|
284
|
-
*
|
|
285
295
|
* @param {bigint} n - Positive integer to convert
|
|
286
296
|
* @returns {string} Ordinal English words
|
|
287
297
|
*/
|
|
288
|
-
function integerToOrdinal
|
|
298
|
+
function integerToOrdinal(n) {
|
|
289
299
|
if (n < 1000n) {
|
|
290
300
|
return buildOrdinalSegment(Number(n))
|
|
291
301
|
}
|
|
@@ -307,11 +317,10 @@ function integerToOrdinal (n) {
|
|
|
307
317
|
|
|
308
318
|
/**
|
|
309
319
|
* Builds ordinal words for numbers >= 1,000,000.
|
|
310
|
-
*
|
|
311
320
|
* @param {bigint} n - Number >= 1,000,000
|
|
312
321
|
* @returns {string} Ordinal English words
|
|
313
322
|
*/
|
|
314
|
-
function buildLargeOrdinal
|
|
323
|
+
function buildLargeOrdinal(n) {
|
|
315
324
|
const segments = []
|
|
316
325
|
let temp = n
|
|
317
326
|
while (temp > 0n) {
|
|
@@ -340,10 +349,12 @@ function buildLargeOrdinal (n) {
|
|
|
340
349
|
if (isLowestSegment) {
|
|
341
350
|
if (i === 0) {
|
|
342
351
|
result += buildOrdinalSegment(segment)
|
|
343
|
-
}
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
344
354
|
result += buildSegment(segment).word + ' ' + SCALES[i - 1] + 'th'
|
|
345
355
|
}
|
|
346
|
-
}
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
347
358
|
result += buildSegment(segment).word
|
|
348
359
|
if (i > 0) {
|
|
349
360
|
result += ' ' + SCALES[i - 1]
|
|
@@ -356,19 +367,18 @@ function buildLargeOrdinal (n) {
|
|
|
356
367
|
|
|
357
368
|
/**
|
|
358
369
|
* Converts a numeric value to Australian English ordinal words.
|
|
359
|
-
*
|
|
360
370
|
* @param {number | string | bigint} value - The numeric value to convert (must be a positive integer)
|
|
361
371
|
* @returns {string} The number as ordinal words
|
|
362
372
|
* @throws {TypeError} If value is not a valid numeric type
|
|
363
373
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
364
|
-
*
|
|
365
374
|
* @example
|
|
366
375
|
* toOrdinal(1) // 'first'
|
|
367
376
|
* toOrdinal(42) // 'forty-second'
|
|
368
377
|
* toOrdinal(100) // 'one hundredth'
|
|
369
378
|
*/
|
|
370
|
-
function toOrdinal
|
|
379
|
+
function toOrdinal(value) {
|
|
371
380
|
const integerPart = parseOrdinalValue(value)
|
|
381
|
+
checkMax(integerPart, ordinalMax)
|
|
372
382
|
return integerToOrdinal(integerPart)
|
|
373
383
|
}
|
|
374
384
|
|
|
@@ -376,26 +386,31 @@ function toOrdinal (value) {
|
|
|
376
386
|
// CURRENCY: toCurrency(value, options?)
|
|
377
387
|
// ============================================================================
|
|
378
388
|
|
|
389
|
+
/**
|
|
390
|
+
* @typedef {object} CurrencyOptions
|
|
391
|
+
* @property {boolean} [and] - Use "and" between dollars and cents
|
|
392
|
+
*/
|
|
393
|
+
|
|
394
|
+
/** @type {Required<CurrencyOptions>} */
|
|
395
|
+
export const currencyDefaults = { and: true }
|
|
396
|
+
|
|
379
397
|
/**
|
|
380
398
|
* Converts a numeric value to Australian English currency words.
|
|
381
|
-
*
|
|
382
399
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
383
|
-
* @param {
|
|
384
|
-
* @param {boolean} [options.and=true] - Use "and" between dollars and cents
|
|
400
|
+
* @param {CurrencyOptions} [options] - Optional configuration
|
|
385
401
|
* @returns {string} The amount in Australian English currency words
|
|
386
402
|
* @throws {TypeError} If value is not a valid numeric type
|
|
387
403
|
* @throws {Error} If value is not a valid number format
|
|
388
|
-
*
|
|
389
404
|
* @example
|
|
390
405
|
* toCurrency(42.50) // 'forty-two dollars and fifty cents'
|
|
391
406
|
* toCurrency(1) // 'one dollar'
|
|
392
407
|
* toCurrency(0.99) // 'ninety-nine cents'
|
|
393
408
|
* toCurrency(42.50, { and: false }) // 'forty-two dollars fifty cents'
|
|
394
409
|
*/
|
|
395
|
-
function toCurrency
|
|
396
|
-
options = validateOptions(options)
|
|
410
|
+
function toCurrency(value, options) {
|
|
397
411
|
const { isNegative, dollars, cents } = parseCurrencyValue(value)
|
|
398
|
-
|
|
412
|
+
checkMax(dollars, currencyMax)
|
|
413
|
+
const { and: useAnd } = resolveOptions(options, currencyDefaults)
|
|
399
414
|
|
|
400
415
|
let result = ''
|
|
401
416
|
if (isNegative) result = NEGATIVE + ' '
|
package/src/en-BD.d.ts
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
|
+
export const cardinalMax: bigint;
|
|
2
|
+
export const ordinalMax: bigint;
|
|
3
|
+
export const currencyMax: bigint;
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {object} CurrencyOptions
|
|
6
|
+
* @property {boolean} [and] - Use "and" between taka and paise
|
|
7
|
+
*/
|
|
8
|
+
/** @type {Required<CurrencyOptions>} */
|
|
9
|
+
export const currencyDefaults: Required<CurrencyOptions>;
|
|
10
|
+
export type CurrencyOptions = {
|
|
11
|
+
/**
|
|
12
|
+
* - Use "and" between taka and paise
|
|
13
|
+
*/
|
|
14
|
+
and?: boolean | undefined;
|
|
15
|
+
};
|
|
1
16
|
/**
|
|
2
17
|
* Converts a numeric value to English words using Indian numbering.
|
|
3
|
-
*
|
|
4
18
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
19
|
* @returns {string} The number in English words
|
|
6
20
|
* @throws {TypeError} If value is not a valid numeric type
|
|
7
21
|
* @throws {Error} If value is not a valid number format
|
|
8
|
-
*
|
|
9
22
|
* @example
|
|
10
23
|
* toCardinal(42) // 'forty-two'
|
|
11
24
|
* toCardinal(100000) // 'one lakh'
|
|
@@ -15,12 +28,10 @@
|
|
|
15
28
|
export function toCardinal(value: number | string | bigint): string;
|
|
16
29
|
/**
|
|
17
30
|
* Converts a numeric value to English ordinal words using Indian numbering.
|
|
18
|
-
*
|
|
19
31
|
* @param {number | string | bigint} value - The numeric value to convert (must be a positive integer)
|
|
20
32
|
* @returns {string} The number as ordinal words
|
|
21
33
|
* @throws {TypeError} If value is not a valid numeric type
|
|
22
34
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
23
|
-
*
|
|
24
35
|
* @example
|
|
25
36
|
* toOrdinal(1) // 'first'
|
|
26
37
|
* toOrdinal(100000) // 'one lakhth'
|
|
@@ -29,14 +40,11 @@ export function toCardinal(value: number | string | bigint): string;
|
|
|
29
40
|
export function toOrdinal(value: number | string | bigint): string;
|
|
30
41
|
/**
|
|
31
42
|
* Converts a numeric value to Bangladeshi English currency words.
|
|
32
|
-
*
|
|
33
43
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
34
|
-
* @param {
|
|
35
|
-
* @param {boolean} [options.and=true] - Use "and" between taka and paise
|
|
44
|
+
* @param {CurrencyOptions} [options] - Optional configuration
|
|
36
45
|
* @returns {string} The amount in Bangladeshi English currency words
|
|
37
46
|
* @throws {TypeError} If value is not a valid numeric type
|
|
38
47
|
* @throws {Error} If value is not a valid number format
|
|
39
|
-
*
|
|
40
48
|
* @example
|
|
41
49
|
* toCurrency(42.50) // 'forty-two taka and fifty paise'
|
|
42
50
|
* toCurrency(100000) // 'one lakh taka'
|
|
@@ -44,6 +52,4 @@ export function toOrdinal(value: number | string | bigint): string;
|
|
|
44
52
|
* toCurrency(0.50) // 'fifty paise'
|
|
45
53
|
* toCurrency(42.50, { and: false }) // 'forty-two taka fifty paise'
|
|
46
54
|
*/
|
|
47
|
-
export function toCurrency(value: number | string | bigint, options?:
|
|
48
|
-
and?: boolean | undefined;
|
|
49
|
-
}): string;
|
|
55
|
+
export function toCurrency(value: number | string | bigint, options?: CurrencyOptions): string;
|
package/src/en-BD.js
CHANGED
|
@@ -13,7 +13,9 @@
|
|
|
13
13
|
import { parseCardinalValue } from './utils/parse-cardinal.js'
|
|
14
14
|
import { parseCurrencyValue } from './utils/parse-currency.js'
|
|
15
15
|
import { parseOrdinalValue } from './utils/parse-ordinal.js'
|
|
16
|
-
import {
|
|
16
|
+
import { checkMax } from './utils/check-max.js'
|
|
17
|
+
import { indian } from './utils/scale.js'
|
|
18
|
+
import { resolveOptions } from './utils/resolve-options.js'
|
|
17
19
|
|
|
18
20
|
// ============================================================================
|
|
19
21
|
// Vocabulary (module-level constants)
|
|
@@ -26,6 +28,11 @@ const TENS = ['', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy',
|
|
|
26
28
|
// Indian numbering scales: 10^3, 10^5, 10^7, 10^9, 10^11, 10^13, 10^15, 10^17
|
|
27
29
|
const SCALES = ['thousand', 'lakh', 'crore', 'arab', 'kharab', 'neel', 'padma', 'shankh']
|
|
28
30
|
|
|
31
|
+
// 3-2-2 grouping: a 3-digit base segment then 2 digits per Indian scale word.
|
|
32
|
+
export const cardinalMax = indian(SCALES.length + 1)
|
|
33
|
+
export const ordinalMax = indian(SCALES.length + 1)
|
|
34
|
+
export const currencyMax = indian(SCALES.length + 1)
|
|
35
|
+
|
|
29
36
|
const HUNDRED = 'hundred'
|
|
30
37
|
const ZERO = 'zero'
|
|
31
38
|
const NEGATIVE = 'minus'
|
|
@@ -50,11 +57,10 @@ const segmentResult = { word: '', hasHundred: false }
|
|
|
50
57
|
|
|
51
58
|
/**
|
|
52
59
|
* Builds words for a 0-999 segment (British-style with "and" after hundreds).
|
|
53
|
-
*
|
|
54
60
|
* @param {number} n - Number 0-999
|
|
55
|
-
* @returns {{ word: string, hasHundred: boolean }}
|
|
61
|
+
* @returns {{ word: string, hasHundred: boolean }} The segment words and whether a hundred was emitted
|
|
56
62
|
*/
|
|
57
|
-
function buildSegment
|
|
63
|
+
function buildSegment(n) {
|
|
58
64
|
if (n === 0) {
|
|
59
65
|
segmentResult.word = ''
|
|
60
66
|
segmentResult.hasHundred = false
|
|
@@ -69,9 +75,11 @@ function buildSegment (n) {
|
|
|
69
75
|
let tensOnes = ''
|
|
70
76
|
if (tens === 1) {
|
|
71
77
|
tensOnes = TEENS[ones]
|
|
72
|
-
}
|
|
78
|
+
}
|
|
79
|
+
else if (tens >= 2) {
|
|
73
80
|
tensOnes = ones > 0 ? TENS[tens] + '-' + ONES[ones] : TENS[tens]
|
|
74
|
-
}
|
|
81
|
+
}
|
|
82
|
+
else if (ones > 0) {
|
|
75
83
|
tensOnes = ONES[ones]
|
|
76
84
|
}
|
|
77
85
|
|
|
@@ -79,11 +87,13 @@ function buildSegment (n) {
|
|
|
79
87
|
if (hundreds > 0) {
|
|
80
88
|
if (tensOnes) {
|
|
81
89
|
segmentResult.word = ONES[hundreds] + ' ' + HUNDRED + ' and ' + tensOnes
|
|
82
|
-
}
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
83
92
|
segmentResult.word = ONES[hundreds] + ' ' + HUNDRED
|
|
84
93
|
}
|
|
85
94
|
segmentResult.hasHundred = true
|
|
86
|
-
}
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
87
97
|
segmentResult.word = tensOnes
|
|
88
98
|
segmentResult.hasHundred = false
|
|
89
99
|
}
|
|
@@ -93,11 +103,10 @@ function buildSegment (n) {
|
|
|
93
103
|
|
|
94
104
|
/**
|
|
95
105
|
* Builds words for a 0-99 segment (no hundreds).
|
|
96
|
-
*
|
|
97
106
|
* @param {number} n - Number 0-99
|
|
98
|
-
* @returns {string}
|
|
107
|
+
* @returns {string} The segment in words
|
|
99
108
|
*/
|
|
100
|
-
function buildSmallSegment
|
|
109
|
+
function buildSmallSegment(n) {
|
|
101
110
|
if (n === 0) return ''
|
|
102
111
|
|
|
103
112
|
const ones = n % 10
|
|
@@ -105,7 +114,8 @@ function buildSmallSegment (n) {
|
|
|
105
114
|
|
|
106
115
|
if (tens === 1) {
|
|
107
116
|
return TEENS[ones]
|
|
108
|
-
}
|
|
117
|
+
}
|
|
118
|
+
else if (tens >= 2) {
|
|
109
119
|
return ones > 0 ? TENS[tens] + '-' + ONES[ones] : TENS[tens]
|
|
110
120
|
}
|
|
111
121
|
return ONES[ones]
|
|
@@ -120,11 +130,10 @@ function buildSmallSegment (n) {
|
|
|
120
130
|
*
|
|
121
131
|
* Uses BigInt modulo for segment extraction.
|
|
122
132
|
* South Asian 3-2-2 grouping: first 3 digits, then groups of 2.
|
|
123
|
-
*
|
|
124
133
|
* @param {bigint} n - Non-negative integer to convert
|
|
125
134
|
* @returns {string} English words
|
|
126
135
|
*/
|
|
127
|
-
function integerToWords
|
|
136
|
+
function integerToWords(n) {
|
|
128
137
|
if (n === 0n) return ZERO
|
|
129
138
|
|
|
130
139
|
// Fast path: numbers < 1000
|
|
@@ -161,7 +170,8 @@ function integerToWords (n) {
|
|
|
161
170
|
words.push('and')
|
|
162
171
|
}
|
|
163
172
|
words.push(word)
|
|
164
|
-
}
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
165
175
|
// Other segments are 0-99
|
|
166
176
|
words.push(buildSmallSegment(segment))
|
|
167
177
|
// Add scale word
|
|
@@ -176,11 +186,10 @@ function integerToWords (n) {
|
|
|
176
186
|
|
|
177
187
|
/**
|
|
178
188
|
* Converts decimal digits to English words.
|
|
179
|
-
*
|
|
180
189
|
* @param {string} decimalPart - Decimal digits (without the point)
|
|
181
190
|
* @returns {string} English words for decimal part
|
|
182
191
|
*/
|
|
183
|
-
function decimalPartToWords
|
|
192
|
+
function decimalPartToWords(decimalPart) {
|
|
184
193
|
let result = ''
|
|
185
194
|
|
|
186
195
|
// Handle leading zeros
|
|
@@ -203,20 +212,21 @@ function decimalPartToWords (decimalPart) {
|
|
|
203
212
|
|
|
204
213
|
/**
|
|
205
214
|
* Converts a numeric value to English words using Indian numbering.
|
|
206
|
-
*
|
|
207
215
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
208
216
|
* @returns {string} The number in English words
|
|
209
217
|
* @throws {TypeError} If value is not a valid numeric type
|
|
210
218
|
* @throws {Error} If value is not a valid number format
|
|
211
|
-
*
|
|
212
219
|
* @example
|
|
213
220
|
* toCardinal(42) // 'forty-two'
|
|
214
221
|
* toCardinal(100000) // 'one lakh'
|
|
215
222
|
* toCardinal(10000000) // 'one crore'
|
|
216
223
|
* toCardinal(1234567) // 'twelve lakh thirty-four thousand five hundred and sixty-seven'
|
|
217
224
|
*/
|
|
218
|
-
function toCardinal
|
|
225
|
+
function toCardinal(value) {
|
|
219
226
|
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
227
|
+
// Both the integer part and the decimal's significant digits are spelled via
|
|
228
|
+
// the scale builder, so both must clear the ceiling.
|
|
229
|
+
checkMax(integerPart, cardinalMax, decimalPart)
|
|
220
230
|
|
|
221
231
|
let result = ''
|
|
222
232
|
|
|
@@ -239,11 +249,10 @@ function toCardinal (value) {
|
|
|
239
249
|
|
|
240
250
|
/**
|
|
241
251
|
* Builds ordinal words for a 0-999 segment (final segment only).
|
|
242
|
-
*
|
|
243
252
|
* @param {number} n - Number 0-999
|
|
244
253
|
* @returns {string} Ordinal words for this segment
|
|
245
254
|
*/
|
|
246
|
-
function buildOrdinalSegment
|
|
255
|
+
function buildOrdinalSegment(n) {
|
|
247
256
|
const ones = n % 10
|
|
248
257
|
const tens = Math.trunc(n / 10) % 10
|
|
249
258
|
const hundreds = Math.trunc(n / 100)
|
|
@@ -252,13 +261,16 @@ function buildOrdinalSegment (n) {
|
|
|
252
261
|
let tensOnesOrdinal = ''
|
|
253
262
|
if (tens === 1) {
|
|
254
263
|
tensOnesOrdinal = ORDINAL_TEENS[ones]
|
|
255
|
-
}
|
|
264
|
+
}
|
|
265
|
+
else if (tens >= 2) {
|
|
256
266
|
if (ones > 0) {
|
|
257
267
|
tensOnesOrdinal = TENS[tens] + '-' + ORDINAL_ONES[ones]
|
|
258
|
-
}
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
259
270
|
tensOnesOrdinal = ORDINAL_TENS[tens]
|
|
260
271
|
}
|
|
261
|
-
}
|
|
272
|
+
}
|
|
273
|
+
else if (ones > 0) {
|
|
262
274
|
tensOnesOrdinal = ORDINAL_ONES[ones]
|
|
263
275
|
}
|
|
264
276
|
|
|
@@ -266,7 +278,8 @@ function buildOrdinalSegment (n) {
|
|
|
266
278
|
if (hundreds > 0) {
|
|
267
279
|
if (tensOnesOrdinal) {
|
|
268
280
|
return ONES[hundreds] + ' ' + HUNDRED + ' ' + tensOnesOrdinal
|
|
269
|
-
}
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
270
283
|
return ONES[hundreds] + ' hundredth'
|
|
271
284
|
}
|
|
272
285
|
}
|
|
@@ -276,11 +289,10 @@ function buildOrdinalSegment (n) {
|
|
|
276
289
|
|
|
277
290
|
/**
|
|
278
291
|
* Converts a positive integer to ordinal words using Indian numbering.
|
|
279
|
-
*
|
|
280
292
|
* @param {bigint} n - Positive integer to convert
|
|
281
293
|
* @returns {string} Ordinal English words
|
|
282
294
|
*/
|
|
283
|
-
function integerToOrdinal
|
|
295
|
+
function integerToOrdinal(n) {
|
|
284
296
|
// Fast path: numbers < 1000
|
|
285
297
|
if (n < 1000n) {
|
|
286
298
|
return buildOrdinalSegment(Number(n))
|
|
@@ -322,16 +334,19 @@ function integerToOrdinal (n) {
|
|
|
322
334
|
if (i === 0) {
|
|
323
335
|
// Units position: use ordinal segment
|
|
324
336
|
words.push(buildOrdinalSegment(segment))
|
|
325
|
-
}
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
326
339
|
// Scale position with no remainder below: "one lakhth"
|
|
327
340
|
words.push(buildSmallSegment(segment))
|
|
328
341
|
words.push(SCALES[i - 1] + 'th')
|
|
329
342
|
}
|
|
330
|
-
}
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
331
345
|
// Non-final segments are cardinal
|
|
332
346
|
if (i === 0) {
|
|
333
347
|
words.push(buildSegment(segment).word)
|
|
334
|
-
}
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
335
350
|
words.push(buildSmallSegment(segment))
|
|
336
351
|
words.push(SCALES[i - 1])
|
|
337
352
|
}
|
|
@@ -343,19 +358,18 @@ function integerToOrdinal (n) {
|
|
|
343
358
|
|
|
344
359
|
/**
|
|
345
360
|
* Converts a numeric value to English ordinal words using Indian numbering.
|
|
346
|
-
*
|
|
347
361
|
* @param {number | string | bigint} value - The numeric value to convert (must be a positive integer)
|
|
348
362
|
* @returns {string} The number as ordinal words
|
|
349
363
|
* @throws {TypeError} If value is not a valid numeric type
|
|
350
364
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
351
|
-
*
|
|
352
365
|
* @example
|
|
353
366
|
* toOrdinal(1) // 'first'
|
|
354
367
|
* toOrdinal(100000) // 'one lakhth'
|
|
355
368
|
* toOrdinal(100001) // 'one lakh first'
|
|
356
369
|
*/
|
|
357
|
-
function toOrdinal
|
|
370
|
+
function toOrdinal(value) {
|
|
358
371
|
const integerPart = parseOrdinalValue(value)
|
|
372
|
+
checkMax(integerPart, ordinalMax)
|
|
359
373
|
return integerToOrdinal(integerPart)
|
|
360
374
|
}
|
|
361
375
|
|
|
@@ -363,16 +377,21 @@ function toOrdinal (value) {
|
|
|
363
377
|
// CURRENCY: toCurrency(value, options?)
|
|
364
378
|
// ============================================================================
|
|
365
379
|
|
|
380
|
+
/**
|
|
381
|
+
* @typedef {object} CurrencyOptions
|
|
382
|
+
* @property {boolean} [and] - Use "and" between taka and paise
|
|
383
|
+
*/
|
|
384
|
+
|
|
385
|
+
/** @type {Required<CurrencyOptions>} */
|
|
386
|
+
export const currencyDefaults = { and: true }
|
|
387
|
+
|
|
366
388
|
/**
|
|
367
389
|
* Converts a numeric value to Bangladeshi English currency words.
|
|
368
|
-
*
|
|
369
390
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
370
|
-
* @param {
|
|
371
|
-
* @param {boolean} [options.and=true] - Use "and" between taka and paise
|
|
391
|
+
* @param {CurrencyOptions} [options] - Optional configuration
|
|
372
392
|
* @returns {string} The amount in Bangladeshi English currency words
|
|
373
393
|
* @throws {TypeError} If value is not a valid numeric type
|
|
374
394
|
* @throws {Error} If value is not a valid number format
|
|
375
|
-
*
|
|
376
395
|
* @example
|
|
377
396
|
* toCurrency(42.50) // 'forty-two taka and fifty paise'
|
|
378
397
|
* toCurrency(100000) // 'one lakh taka'
|
|
@@ -380,10 +399,10 @@ function toOrdinal (value) {
|
|
|
380
399
|
* toCurrency(0.50) // 'fifty paise'
|
|
381
400
|
* toCurrency(42.50, { and: false }) // 'forty-two taka fifty paise'
|
|
382
401
|
*/
|
|
383
|
-
function toCurrency
|
|
384
|
-
options = validateOptions(options)
|
|
402
|
+
function toCurrency(value, options) {
|
|
385
403
|
const { isNegative, dollars: taka, cents: paise } = parseCurrencyValue(value)
|
|
386
|
-
|
|
404
|
+
checkMax(taka, currencyMax)
|
|
405
|
+
const { and: useAnd } = resolveOptions(options, currencyDefaults)
|
|
387
406
|
|
|
388
407
|
// Build result
|
|
389
408
|
let result = ''
|