n2words 1.24.0 → 3.0.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.
Files changed (280) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +183 -156
  3. package/dist/languages/am-Latn.js +3 -0
  4. package/dist/languages/am-Latn.js.map +1 -0
  5. package/dist/languages/am.js +3 -0
  6. package/dist/languages/am.js.map +1 -0
  7. package/dist/languages/ar.js +3 -2
  8. package/dist/languages/ar.js.map +1 -1
  9. package/dist/languages/az.js +3 -2
  10. package/dist/languages/az.js.map +1 -1
  11. package/dist/languages/bn.js +3 -2
  12. package/dist/languages/bn.js.map +1 -1
  13. package/dist/languages/cs.js +3 -2
  14. package/dist/languages/cs.js.map +1 -1
  15. package/dist/languages/da.js +3 -2
  16. package/dist/languages/da.js.map +1 -1
  17. package/dist/languages/de.js +3 -2
  18. package/dist/languages/de.js.map +1 -1
  19. package/dist/languages/el.js +3 -2
  20. package/dist/languages/el.js.map +1 -1
  21. package/dist/languages/en.js +3 -2
  22. package/dist/languages/en.js.map +1 -1
  23. package/dist/languages/es.js +3 -2
  24. package/dist/languages/es.js.map +1 -1
  25. package/dist/languages/fa.js +3 -2
  26. package/dist/languages/fa.js.map +1 -1
  27. package/dist/languages/fi.js +3 -0
  28. package/dist/languages/fi.js.map +1 -0
  29. package/dist/languages/fil.js +3 -2
  30. package/dist/languages/fil.js.map +1 -1
  31. package/dist/languages/fr-BE.js +3 -2
  32. package/dist/languages/fr-BE.js.map +1 -1
  33. package/dist/languages/fr.js +3 -2
  34. package/dist/languages/fr.js.map +1 -1
  35. package/dist/languages/gu.js +3 -2
  36. package/dist/languages/gu.js.map +1 -1
  37. package/dist/languages/ha.js +3 -0
  38. package/dist/languages/ha.js.map +1 -0
  39. package/dist/languages/hbo.js +3 -0
  40. package/dist/languages/hbo.js.map +1 -0
  41. package/dist/languages/he.js +3 -2
  42. package/dist/languages/he.js.map +1 -1
  43. package/dist/languages/hi.js +3 -2
  44. package/dist/languages/hi.js.map +1 -1
  45. package/dist/languages/hr.js +3 -2
  46. package/dist/languages/hr.js.map +1 -1
  47. package/dist/languages/hu.js +3 -2
  48. package/dist/languages/hu.js.map +1 -1
  49. package/dist/languages/id.js +3 -2
  50. package/dist/languages/id.js.map +1 -1
  51. package/dist/languages/it.js +3 -2
  52. package/dist/languages/it.js.map +1 -1
  53. package/dist/languages/ja.js +3 -2
  54. package/dist/languages/ja.js.map +1 -1
  55. package/dist/languages/kn.js +3 -2
  56. package/dist/languages/kn.js.map +1 -1
  57. package/dist/languages/ko.js +3 -2
  58. package/dist/languages/ko.js.map +1 -1
  59. package/dist/languages/lt.js +3 -2
  60. package/dist/languages/lt.js.map +1 -1
  61. package/dist/languages/lv.js +3 -2
  62. package/dist/languages/lv.js.map +1 -1
  63. package/dist/languages/mr.js +3 -2
  64. package/dist/languages/mr.js.map +1 -1
  65. package/dist/languages/ms.js +3 -2
  66. package/dist/languages/ms.js.map +1 -1
  67. package/dist/languages/nb.js +3 -2
  68. package/dist/languages/nb.js.map +1 -1
  69. package/dist/languages/nl.js +3 -2
  70. package/dist/languages/nl.js.map +1 -1
  71. package/dist/languages/pa.js +3 -0
  72. package/dist/languages/pa.js.map +1 -0
  73. package/dist/languages/pl.js +3 -2
  74. package/dist/languages/pl.js.map +1 -1
  75. package/dist/languages/pt.js +3 -2
  76. package/dist/languages/pt.js.map +1 -1
  77. package/dist/languages/ro.js +3 -2
  78. package/dist/languages/ro.js.map +1 -1
  79. package/dist/languages/ru.js +3 -2
  80. package/dist/languages/ru.js.map +1 -1
  81. package/dist/languages/sr-Cyrl.js +3 -0
  82. package/dist/languages/sr-Cyrl.js.map +1 -0
  83. package/dist/languages/sr-Latn.js +3 -2
  84. package/dist/languages/sr-Latn.js.map +1 -1
  85. package/dist/languages/sv.js +3 -2
  86. package/dist/languages/sv.js.map +1 -1
  87. package/dist/languages/sw.js +3 -2
  88. package/dist/languages/sw.js.map +1 -1
  89. package/dist/languages/ta.js +3 -2
  90. package/dist/languages/ta.js.map +1 -1
  91. package/dist/languages/te.js +3 -2
  92. package/dist/languages/te.js.map +1 -1
  93. package/dist/languages/th.js +3 -2
  94. package/dist/languages/th.js.map +1 -1
  95. package/dist/languages/tr.js +3 -2
  96. package/dist/languages/tr.js.map +1 -1
  97. package/dist/languages/uk.js +3 -2
  98. package/dist/languages/uk.js.map +1 -1
  99. package/dist/languages/ur.js +3 -2
  100. package/dist/languages/ur.js.map +1 -1
  101. package/dist/languages/vi.js +3 -2
  102. package/dist/languages/vi.js.map +1 -1
  103. package/dist/languages/zh-Hans.js +3 -2
  104. package/dist/languages/zh-Hans.js.map +1 -1
  105. package/dist/languages/zh-Hant.js +3 -0
  106. package/dist/languages/zh-Hant.js.map +1 -0
  107. package/dist/n2words.js +3 -2
  108. package/dist/n2words.js.map +1 -1
  109. package/lib/languages/am-Latn.d.ts +7 -0
  110. package/lib/languages/am-Latn.js +164 -0
  111. package/lib/languages/am.d.ts +7 -0
  112. package/lib/languages/am.js +164 -0
  113. package/lib/languages/ar.d.ts +17 -0
  114. package/lib/languages/ar.js +171 -209
  115. package/lib/languages/az.d.ts +7 -0
  116. package/lib/languages/az.js +167 -49
  117. package/lib/languages/bn.d.ts +7 -0
  118. package/lib/languages/bn.js +142 -123
  119. package/lib/languages/cs.d.ts +18 -0
  120. package/lib/languages/cs.js +303 -176
  121. package/lib/languages/da.d.ts +14 -0
  122. package/lib/languages/da.js +267 -139
  123. package/lib/languages/de.d.ts +17 -0
  124. package/lib/languages/de.js +310 -113
  125. package/lib/languages/el.d.ts +14 -0
  126. package/lib/languages/el.js +225 -98
  127. package/lib/languages/en.d.ts +17 -0
  128. package/lib/languages/en.js +235 -102
  129. package/lib/languages/es.d.ts +21 -0
  130. package/lib/languages/es.js +307 -125
  131. package/lib/languages/fa.d.ts +7 -0
  132. package/lib/languages/fa.js +115 -108
  133. package/lib/languages/fi.d.ts +14 -0
  134. package/lib/languages/fi.js +245 -0
  135. package/lib/languages/fil.d.ts +7 -0
  136. package/lib/languages/fil.js +199 -139
  137. package/lib/languages/fr-BE.d.ts +11 -0
  138. package/lib/languages/fr-BE.js +287 -48
  139. package/lib/languages/fr.d.ts +21 -0
  140. package/lib/languages/fr.js +343 -119
  141. package/lib/languages/gu.d.ts +7 -0
  142. package/lib/languages/gu.js +125 -144
  143. package/lib/languages/ha.d.ts +7 -0
  144. package/lib/languages/ha.js +230 -0
  145. package/lib/languages/hbo.d.ts +13 -0
  146. package/lib/languages/hbo.js +300 -0
  147. package/lib/languages/he.d.ts +13 -0
  148. package/lib/languages/he.js +230 -283
  149. package/lib/languages/hi.d.ts +7 -0
  150. package/lib/languages/hi.js +142 -123
  151. package/lib/languages/hr.d.ts +11 -0
  152. package/lib/languages/hr.js +190 -129
  153. package/lib/languages/hu.d.ts +7 -0
  154. package/lib/languages/hu.js +194 -133
  155. package/lib/languages/id.d.ts +7 -0
  156. package/lib/languages/id.js +167 -140
  157. package/lib/languages/it.d.ts +19 -0
  158. package/lib/languages/it.js +337 -108
  159. package/lib/languages/ja.d.ts +17 -0
  160. package/lib/languages/ja.js +224 -155
  161. package/lib/languages/kn.d.ts +7 -0
  162. package/lib/languages/kn.js +128 -62
  163. package/lib/languages/ko.d.ts +14 -0
  164. package/lib/languages/ko.js +250 -70
  165. package/lib/languages/lt.d.ts +18 -0
  166. package/lib/languages/lt.js +287 -148
  167. package/lib/languages/lv.d.ts +18 -0
  168. package/lib/languages/lv.js +291 -123
  169. package/lib/languages/mr.d.ts +7 -0
  170. package/lib/languages/mr.js +125 -144
  171. package/lib/languages/ms.d.ts +7 -0
  172. package/lib/languages/ms.js +171 -112
  173. package/lib/languages/nb.d.ts +14 -0
  174. package/lib/languages/nb.js +275 -100
  175. package/lib/languages/nl.d.ts +26 -0
  176. package/lib/languages/nl.js +307 -174
  177. package/lib/languages/pa.d.ts +7 -0
  178. package/lib/languages/pa.js +163 -0
  179. package/lib/languages/pl.d.ts +22 -0
  180. package/lib/languages/pl.js +299 -158
  181. package/lib/languages/pt.d.ts +17 -0
  182. package/lib/languages/pt.js +279 -120
  183. package/lib/languages/ro.d.ts +18 -0
  184. package/lib/languages/ro.js +214 -337
  185. package/lib/languages/ru.d.ts +11 -0
  186. package/lib/languages/ru.js +219 -95
  187. package/lib/languages/sr-Cyrl.d.ts +11 -0
  188. package/lib/languages/sr-Cyrl.js +215 -0
  189. package/lib/languages/sr-Latn.d.ts +11 -0
  190. package/lib/languages/sr-Latn.js +190 -132
  191. package/lib/languages/sv.d.ts +14 -0
  192. package/lib/languages/sv.js +280 -103
  193. package/lib/languages/sw.d.ts +7 -0
  194. package/lib/languages/sw.js +135 -103
  195. package/lib/languages/ta.d.ts +7 -0
  196. package/lib/languages/ta.js +133 -205
  197. package/lib/languages/te.d.ts +7 -0
  198. package/lib/languages/te.js +148 -213
  199. package/lib/languages/th.d.ts +7 -0
  200. package/lib/languages/th.js +139 -101
  201. package/lib/languages/tr.d.ts +18 -0
  202. package/lib/languages/tr.js +246 -66
  203. package/lib/languages/uk.d.ts +11 -0
  204. package/lib/languages/uk.js +197 -101
  205. package/lib/languages/ur.d.ts +7 -0
  206. package/lib/languages/ur.js +160 -123
  207. package/lib/languages/vi.d.ts +17 -0
  208. package/lib/languages/vi.js +287 -164
  209. package/lib/languages/zh-Hans.d.ts +11 -0
  210. package/lib/languages/zh-Hans.js +159 -142
  211. package/lib/languages/zh-Hant.d.ts +11 -0
  212. package/lib/languages/zh-Hant.js +202 -0
  213. package/lib/n2words.d.ts +53 -0
  214. package/lib/n2words.js +91 -227
  215. package/lib/utils/is-plain-object.d.ts +13 -0
  216. package/lib/utils/is-plain-object.js +17 -0
  217. package/lib/utils/parse-numeric.d.ts +17 -0
  218. package/lib/utils/parse-numeric.js +108 -0
  219. package/lib/utils/validate-options.d.ts +8 -0
  220. package/lib/utils/validate-options.js +16 -0
  221. package/package.json +118 -67
  222. package/dist/languages/pa-Guru.js +0 -2
  223. package/dist/languages/pa-Guru.js.map +0 -1
  224. package/lib/classes/abstract-language.js +0 -261
  225. package/lib/classes/greedy-scale-language.js +0 -195
  226. package/lib/classes/slavic-language.js +0 -251
  227. package/lib/classes/south-asian-language.js +0 -161
  228. package/lib/classes/turkic-language.js +0 -63
  229. package/lib/languages/pa-Guru.js +0 -126
  230. package/typings/classes/abstract-language.d.ts +0 -144
  231. package/typings/classes/greedy-scale-language.d.ts +0 -148
  232. package/typings/classes/slavic-language.d.ts +0 -145
  233. package/typings/classes/south-asian-language.d.ts +0 -101
  234. package/typings/classes/turkic-language.d.ts +0 -42
  235. package/typings/languages/ar.d.ts +0 -93
  236. package/typings/languages/az.d.ts +0 -25
  237. package/typings/languages/bn.d.ts +0 -1
  238. package/typings/languages/cs.d.ts +0 -120
  239. package/typings/languages/da.d.ts +0 -53
  240. package/typings/languages/de.d.ts +0 -26
  241. package/typings/languages/el.d.ts +0 -11
  242. package/typings/languages/en.d.ts +0 -30
  243. package/typings/languages/es.d.ts +0 -43
  244. package/typings/languages/fa.d.ts +0 -81
  245. package/typings/languages/fil.d.ts +0 -12
  246. package/typings/languages/fr-BE.d.ts +0 -41
  247. package/typings/languages/fr.d.ts +0 -43
  248. package/typings/languages/gu.d.ts +0 -12
  249. package/typings/languages/he.d.ts +0 -197
  250. package/typings/languages/hi.d.ts +0 -1
  251. package/typings/languages/hr.d.ts +0 -110
  252. package/typings/languages/hu.d.ts +0 -37
  253. package/typings/languages/id.d.ts +0 -69
  254. package/typings/languages/it.d.ts +0 -51
  255. package/typings/languages/ja.d.ts +0 -58
  256. package/typings/languages/kn.d.ts +0 -11
  257. package/typings/languages/ko.d.ts +0 -25
  258. package/typings/languages/lt.d.ts +0 -110
  259. package/typings/languages/lv.d.ts +0 -99
  260. package/typings/languages/mr.d.ts +0 -12
  261. package/typings/languages/ms.d.ts +0 -37
  262. package/typings/languages/nb.d.ts +0 -27
  263. package/typings/languages/nl.d.ts +0 -65
  264. package/typings/languages/pa-Guru.d.ts +0 -1
  265. package/typings/languages/pl.d.ts +0 -116
  266. package/typings/languages/pt.d.ts +0 -39
  267. package/typings/languages/ro.d.ts +0 -229
  268. package/typings/languages/ru.d.ts +0 -108
  269. package/typings/languages/sr-Latn.d.ts +0 -98
  270. package/typings/languages/sv.d.ts +0 -30
  271. package/typings/languages/sw.d.ts +0 -1
  272. package/typings/languages/ta.d.ts +0 -1
  273. package/typings/languages/te.d.ts +0 -1
  274. package/typings/languages/th.d.ts +0 -1
  275. package/typings/languages/tr.d.ts +0 -46
  276. package/typings/languages/uk.d.ts +0 -117
  277. package/typings/languages/ur.d.ts +0 -1
  278. package/typings/languages/vi.d.ts +0 -116
  279. package/typings/languages/zh-Hans.d.ts +0 -57
  280. package/typings/n2words.d.ts +0 -177
@@ -0,0 +1,300 @@
1
+ /**
2
+ * Biblical Hebrew language converter - Functional Implementation
3
+ *
4
+ * Self-contained converter with segment-based decomposition.
5
+ *
6
+ * Key features:
7
+ * - Gender agreement (masculine default, feminine via option)
8
+ * - Dual forms for 2, 200, 2000
9
+ * - Special 1-9 thousands construct state
10
+ * - "ו" (ve) conjunction rules vary by position
11
+ * - Per-digit decimal reading
12
+ *
13
+ * Optimization: Precomputed segment lookup tables for both genders.
14
+ */
15
+
16
+ import { parseNumericValue } from '../utils/parse-numeric.js'
17
+ import { validateOptions } from '../utils/validate-options.js'
18
+
19
+ // ============================================================================
20
+ // Vocabulary (arrays for indexed access - faster than object property lookup)
21
+ // ============================================================================
22
+
23
+ // Masculine forms (default in Biblical Hebrew) - index 0 unused
24
+ const ONES_MASC = ['', 'אחד', 'שניים', 'שלשה', 'ארבעה', 'חמשה', 'ששה', 'שבעה', 'שמונה', 'תשעה']
25
+ const TEENS_MASC = ['עשרה', 'אחד עשר', 'שנים עשר', 'שלשה עשר', 'ארבעה עשר', 'חמשה עשר', 'ששה עשר', 'שבעה עשר', 'שמונה עשר', 'תשעה עשר']
26
+ const THOUSANDS_MASC = ['', 'אלף', 'אלפיים', 'שלשה אלפים', 'ארבעה אלפים', 'חמשה אלפים', 'ששה אלפים', 'שבעה אלפים', 'שמונה אלפים', 'תשעה אלפים']
27
+
28
+ // Feminine forms - index 0 unused
29
+ const ONES_FEM = ['', 'אחת', 'שתים', 'שלש', 'ארבע', 'חמש', 'שש', 'שבע', 'שמונה', 'תשע']
30
+ const TEENS_FEM = ['עשר', 'אחת עשרה', 'שתים עשרה', 'שלש עשרה', 'ארבע עשרה', 'חמש עשרה', 'שש עשרה', 'שבע עשרה', 'שמונה עשרה', 'תשע עשרה']
31
+ const THOUSANDS_FEM = ['', 'אלף', 'אלפיים', 'שלשת אלפים', 'ארבעת אלפים', 'חמשת אלפים', 'ששת אלפים', 'שבעת אלפים', 'שמונת אלפים', 'תשעת אלפים']
32
+
33
+ // Shared vocabulary
34
+ const TENS = ['', '', 'עשרים', 'שלשים', 'ארבעים', 'חמישים', 'ששים', 'שבעים', 'שמונים', 'תשעים']
35
+ const HUNDREDS = ['', 'מאה', 'מאתיים', 'שלשה מאות', 'ארבעה מאות', 'חמשה מאות', 'ששה מאות', 'שבעה מאות', 'שמונה מאות', 'תשעה מאות']
36
+ const HUNDREDS_FEM = ['', 'מאה', 'מאתיים', 'שלש מאות', 'ארבע מאות', 'חמש מאות', 'שש מאות', 'שבע מאות', 'שמונה מאות', 'תשע מאות']
37
+
38
+ // Scale words (index 1 = thousands, 2 = millions, etc.)
39
+ const SCALE = ['', 'אלף', 'מיליון', 'מיליארד', 'טריליון', 'קוודרליון', 'קווינטיליון']
40
+ const SCALE_PLURAL = ['', 'אלפים', 'מיליונים', 'מיליארדים', 'טריליונים', 'קוודרליונים', 'קווינטיליונים']
41
+
42
+ const ZERO = 'אפס'
43
+ const NEGATIVE = 'מינוס'
44
+ const DECIMAL_SEP = 'נקודה'
45
+
46
+ // ============================================================================
47
+ // Precomputed Lookup Tables (built once at module load)
48
+ // ============================================================================
49
+
50
+ /**
51
+ * Builds segment word for scale segments (thousands, millions, etc.).
52
+ * "ו" is added before tens and ones when following hundreds.
53
+ */
54
+ function buildScaleSegment (n, andWord, ONES, TEENS, HUNDREDS_ARR) {
55
+ if (n === 0) return ''
56
+
57
+ const ones = n % 10
58
+ const tens = Math.floor(n / 10) % 10
59
+ const hundreds = Math.floor(n / 100)
60
+
61
+ let result = ''
62
+
63
+ // Hundreds
64
+ if (hundreds > 0) {
65
+ result = HUNDREDS_ARR[hundreds]
66
+ }
67
+
68
+ // Tens and ones
69
+ if (tens === 1) {
70
+ // Teens (10-19)
71
+ const teenWord = TEENS[ones]
72
+ if (result) {
73
+ result += ' ' + andWord + teenWord
74
+ } else {
75
+ result = teenWord
76
+ }
77
+ } else {
78
+ // Tens (20-90)
79
+ if (tens >= 2) {
80
+ if (result) {
81
+ result += ' ' + andWord + TENS[tens]
82
+ } else {
83
+ result = TENS[tens]
84
+ }
85
+ }
86
+
87
+ // Ones
88
+ if (ones > 0) {
89
+ if (result) {
90
+ result += ' ' + andWord + ONES[ones]
91
+ } else {
92
+ result = ONES[ones]
93
+ }
94
+ }
95
+ }
96
+
97
+ return result
98
+ }
99
+
100
+ /**
101
+ * Builds segment word for units segment (no scale word).
102
+ * "ו" is only added before the final ones digit.
103
+ */
104
+ function buildUnitsSegment (n, andWord, ONES, TEENS, HUNDREDS_ARR) {
105
+ if (n === 0) return ''
106
+
107
+ const ones = n % 10
108
+ const tens = Math.floor(n / 10) % 10
109
+ const hundreds = Math.floor(n / 100)
110
+
111
+ let result = ''
112
+
113
+ // Hundreds
114
+ if (hundreds > 0) {
115
+ result = HUNDREDS_ARR[hundreds]
116
+ }
117
+
118
+ // Tens (no conjunction)
119
+ if (tens === 1) {
120
+ // Teens (10-19)
121
+ if (result) {
122
+ result += ' ' + TEENS[ones]
123
+ } else {
124
+ result = TEENS[ones]
125
+ }
126
+ } else {
127
+ if (tens >= 2) {
128
+ if (result) {
129
+ result += ' ' + TENS[tens]
130
+ } else {
131
+ result = TENS[tens]
132
+ }
133
+ }
134
+
135
+ // Ones - conjunction only here
136
+ if (ones > 0) {
137
+ if (result) {
138
+ result += ' ' + andWord + ONES[ones]
139
+ } else {
140
+ result = ONES[ones]
141
+ }
142
+ }
143
+ }
144
+
145
+ return result
146
+ }
147
+
148
+ // Precompute all 1000 segment words for masculine (default) with default conjunction
149
+ const SCALE_SEGMENTS_MASC = new Array(1000)
150
+ const UNITS_SEGMENTS_MASC = new Array(1000)
151
+ const SCALE_SEGMENTS_FEM = new Array(1000)
152
+ const UNITS_SEGMENTS_FEM = new Array(1000)
153
+
154
+ for (let i = 0; i < 1000; i++) {
155
+ SCALE_SEGMENTS_MASC[i] = buildScaleSegment(i, 'ו', ONES_MASC, TEENS_MASC, HUNDREDS)
156
+ UNITS_SEGMENTS_MASC[i] = buildUnitsSegment(i, 'ו', ONES_MASC, TEENS_MASC, HUNDREDS)
157
+ SCALE_SEGMENTS_FEM[i] = buildScaleSegment(i, 'ו', ONES_FEM, TEENS_FEM, HUNDREDS_FEM)
158
+ UNITS_SEGMENTS_FEM[i] = buildUnitsSegment(i, 'ו', ONES_FEM, TEENS_FEM, HUNDREDS_FEM)
159
+ }
160
+
161
+ // ============================================================================
162
+ // Conversion Functions
163
+ // ============================================================================
164
+
165
+ /**
166
+ * Converts a non-negative integer to Biblical Hebrew words.
167
+ *
168
+ * @param {bigint} n - Non-negative integer to convert
169
+ * @param {Object} options - Conversion options
170
+ * @returns {string} Biblical Hebrew words
171
+ */
172
+ function integerToWords (n, options) {
173
+ if (n === 0n) return ZERO
174
+
175
+ const andWord = options.andWord ?? 'ו'
176
+ const gender = options.gender || 'masculine'
177
+ const isFeminine = gender === 'feminine'
178
+ const usePrecomputed = andWord === 'ו'
179
+
180
+ // Select vocabulary based on gender
181
+ const ONES = isFeminine ? ONES_FEM : ONES_MASC
182
+ const TEENS = isFeminine ? TEENS_FEM : TEENS_MASC
183
+ const THOUSANDS_SPECIAL = isFeminine ? THOUSANDS_FEM : THOUSANDS_MASC
184
+ const HUNDREDS_ARR = isFeminine ? HUNDREDS_FEM : HUNDREDS
185
+ const SCALE_SEGS = isFeminine ? SCALE_SEGMENTS_FEM : SCALE_SEGMENTS_MASC
186
+ const UNITS_SEGS = isFeminine ? UNITS_SEGMENTS_FEM : UNITS_SEGMENTS_MASC
187
+
188
+ // Fast path: numbers < 1000 (direct lookup)
189
+ if (n < 1000n) {
190
+ return usePrecomputed ? UNITS_SEGS[Number(n)] : buildUnitsSegment(Number(n), andWord, ONES, TEENS, HUNDREDS_ARR)
191
+ }
192
+
193
+ // Extract segments using BigInt modulo
194
+ const segments = []
195
+ let temp = n
196
+ while (temp > 0n) {
197
+ segments.push(Number(temp % 1000n))
198
+ temp = temp / 1000n
199
+ }
200
+
201
+ // Build result string directly
202
+ let result = ''
203
+
204
+ for (let i = segments.length - 1; i >= 0; i--) {
205
+ const segment = segments[i]
206
+ if (segment === 0) continue
207
+
208
+ if (i === 0) {
209
+ // Units segment (no scale word)
210
+ const segmentWord = usePrecomputed ? UNITS_SEGS[segment] : buildUnitsSegment(segment, andWord, ONES, TEENS, HUNDREDS_ARR)
211
+ if (result) {
212
+ // Add "ו" before single-digit units when following scale words
213
+ if (segment <= 9) {
214
+ result += ' ' + andWord + segmentWord
215
+ } else {
216
+ result += ' ' + segmentWord
217
+ }
218
+ } else {
219
+ result = segmentWord
220
+ }
221
+ } else if (i === 1) {
222
+ // Thousands - special handling for 1-9
223
+ if (segment <= 9) {
224
+ if (result) result += ' '
225
+ result += THOUSANDS_SPECIAL[segment]
226
+ } else {
227
+ const segmentWord = usePrecomputed ? SCALE_SEGS[segment] : buildScaleSegment(segment, andWord, ONES, TEENS, HUNDREDS_ARR)
228
+ if (result) result += ' '
229
+ result += segmentWord + ' ' + SCALE[1]
230
+ }
231
+ } else {
232
+ // Millions and above
233
+ if (segment === 1) {
234
+ if (result) result += ' '
235
+ result += SCALE[i]
236
+ } else {
237
+ const segmentWord = usePrecomputed ? SCALE_SEGS[segment] : buildScaleSegment(segment, andWord, ONES, TEENS, HUNDREDS_ARR)
238
+ if (result) result += ' '
239
+ result += segmentWord + ' ' + SCALE_PLURAL[i]
240
+ }
241
+ }
242
+ }
243
+
244
+ return result
245
+ }
246
+
247
+ /**
248
+ * Converts decimal digits to Biblical Hebrew words (digit by digit).
249
+ *
250
+ * @param {string} decimalPart - Decimal digits (without the point)
251
+ * @param {Object} options - Conversion options
252
+ * @returns {string} Biblical Hebrew words for decimal part
253
+ */
254
+ function decimalPartToWords (decimalPart, options) {
255
+ const gender = options.gender || 'masculine'
256
+ const ONES = gender === 'feminine' ? ONES_FEM : ONES_MASC
257
+
258
+ let result = ''
259
+ for (let i = 0; i < decimalPart.length; i++) {
260
+ const d = parseInt(decimalPart[i], 10)
261
+ if (result) result += ' '
262
+ result += d === 0 ? ZERO : ONES[d]
263
+ }
264
+
265
+ return result
266
+ }
267
+
268
+ /**
269
+ * Converts a numeric value to Biblical Hebrew words.
270
+ *
271
+ * @param {number | string | bigint} value - The numeric value to convert
272
+ * @param {Object} [options] - Optional configuration
273
+ * @param {('masculine'|'feminine')} [options.gender='masculine'] - Grammatical gender
274
+ * @param {string} [options.andWord] - Custom conjunction word
275
+ * @returns {string} The number in Biblical Hebrew words
276
+ */
277
+ function toWords (value, options) {
278
+ options = validateOptions(options)
279
+ const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
280
+
281
+ let result = ''
282
+
283
+ if (isNegative) {
284
+ result = NEGATIVE + ' '
285
+ }
286
+
287
+ result += integerToWords(integerPart, options)
288
+
289
+ if (decimalPart) {
290
+ result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart, options)
291
+ }
292
+
293
+ return result
294
+ }
295
+
296
+ // ============================================================================
297
+ // Exports
298
+ // ============================================================================
299
+
300
+ export { toWords }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Converts a numeric value to Modern Hebrew words.
3
+ *
4
+ * @param {number | string | bigint} value - The numeric value to convert
5
+ * @param {Object} [options] - Optional configuration
6
+ * @param {('masculine'|'feminine')} [options.gender='masculine'] - Grammatical gender
7
+ * @param {string} [options.andWord] - Custom conjunction word
8
+ * @returns {string} The number in Modern Hebrew words
9
+ */
10
+ export function toWords(value: number | string | bigint, options?: {
11
+ gender?: "masculine" | "feminine" | undefined;
12
+ andWord?: string | undefined;
13
+ }): string;