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
@@ -1,116 +1,243 @@
1
1
  /**
2
- * Converts numbers to their word representation in Greek (Ελληνικά).
3
- * @module languages/el
2
+ * Greek language converter - Functional Implementation
3
+ *
4
+ * A performance-optimized number-to-words converter using precomputed lookup tables.
5
+ *
6
+ * Key features:
7
+ * - Space-separated number composition
8
+ * - Implicit "one" (ένα) omission before scale words
9
+ * - Irregular hundreds (διακόσια, τριακόσια, etc.)
10
+ * - Per-digit decimal reading
4
11
  */
5
12
 
6
- import GreedyScaleLanguage from '../classes/greedy-scale-language.js'
13
+ import { parseNumericValue } from '../utils/parse-numeric.js'
14
+
15
+ // ============================================================================
16
+ // Vocabulary (module-level constants)
17
+ // ============================================================================
18
+
19
+ const ONES = ['', 'ένα', 'δύο', 'τρία', 'τέσσερα', 'πέντε', 'έξι', 'επτά', 'οκτώ', 'εννέα']
20
+
21
+ const TEENS = ['δέκα', 'έντεκα', 'δώδεκα', 'δεκατρία', 'δεκατέσσερα', 'δεκαπέντε', 'δεκαέξι', 'δεκαεπτά', 'δεκαοκτώ', 'δεκαεννέα']
22
+
23
+ const TENS = ['', '', 'είκοσι', 'τριάντα', 'σαράντα', 'πενήντα', 'εξήντα', 'εβδομήντα', 'ογδόντα', 'ενενήντα']
24
+
25
+ // Greek has irregular hundreds
26
+ const HUNDREDS = ['', 'εκατό', 'διακόσια', 'τριακόσια', 'τετρακόσια', 'πεντακόσια', 'εξακόσια', 'επτακόσια', 'οκτακόσια', 'εννιακόσια']
27
+
28
+ const THOUSAND = 'χίλια'
29
+
30
+ const ZERO = 'μηδέν'
31
+ const NEGATIVE = 'μείον'
32
+ const DECIMAL_SEP = 'κόμμα'
33
+
34
+ // Short scale
35
+ const SCALES = ['εκατομμύριο', 'δισεκατομμύριο', 'τρισεκατομμύριο']
36
+
37
+ // ============================================================================
38
+ // Precomputed Lookup Tables (built once at module load)
39
+ // ============================================================================
7
40
 
8
41
  /**
9
- * Greek language implementation using scale-based number conversion.
10
- * @extends GreedyScaleLanguage
42
+ * Builds segment word for 0-999.
11
43
  */
12
- class GreekLanguage extends GreedyScaleLanguage {
13
- negativeWord = 'μείον'
14
- decimalSeparatorWord = 'κόμμα'
15
- zeroWord = 'μηδέν'
16
- convertDecimalsPerDigit = true
17
-
18
- scaleWordPairs = [
19
- // Large numbers (limited set for now)
20
- [1_000_000_000n, 'δισεκατομμύριο'],
21
- [1_000_000n, 'εκατομμύριο'],
22
- [1000n, 'χίλια'],
23
-
24
- // Hundreds
25
- [900n, 'εννιακόσια'],
26
- [800n, 'οκτακόσια'],
27
- [700n, 'επτακόσια'],
28
- [600n, 'εξακόσια'],
29
- [500n, 'πεντακόσια'],
30
- [400n, 'τετρακόσια'],
31
- [300n, 'τριακόσια'],
32
- [200n, 'διακόσια'],
33
- [100n, 'εκατό'],
34
-
35
- // Tens
36
- [90n, 'ενενήντα'],
37
- [80n, 'ογδόντα'],
38
- [70n, 'εβδομήντα'],
39
- [60n, 'εξήντα'],
40
- [50n, 'πενήντα'],
41
- [40n, 'σαράντα'],
42
- [30n, 'τριάντα'],
43
- [20n, 'είκοσι'],
44
- [19n, 'δεκαεννέα'],
45
- [18n, 'δεκαοκτώ'],
46
- [17n, 'δεκαεπτά'],
47
- [16n, 'δεκαέξι'],
48
- [15n, 'δεκαπέντε'],
49
- [14n, 'δεκατέσσερα'],
50
- [13n, 'δεκατρία'],
51
- [12n, 'δώδεκα'],
52
- [11n, 'έντεκα'],
53
- [10n, 'δέκα'],
54
-
55
- // Singles
56
- [9n, 'εννέα'],
57
- [8n, 'οκτώ'],
58
- [7n, 'επτά'],
59
- [6n, 'έξι'],
60
- [5n, 'πέντε'],
61
- [4n, 'τέσσερα'],
62
- [3n, 'τρία'],
63
- [2n, 'δύο'],
64
- [1n, 'ένα'],
65
- [0n, 'μηδέν']
66
- ]
67
-
68
- /**
69
- * Merges two adjacent word-number pairs according to Greek grammar rules.
70
- *
71
- * Greek-specific rules:
72
- * - Implicit "one": χίλια (thousand), not ένα χίλια
73
- * - Space-separated composites
74
- * - Multiplication for scales (e.g., δύο χίλια = two thousand)
75
- *
76
- * @param {Object} leftPair - Left word-number pair (e.g., { 'δύο': 2n })
77
- * @param {Object} rightPair - Right word-number pair (e.g., { 'χίλια': 1000n })
78
- * @returns {Object} Merged word-number pair
79
- */
80
- mergeScales (leftPair, rightPair) {
81
- const leftWord = Object.keys(leftPair)[0]
82
- const leftNumber = Object.values(leftPair)[0]
83
- const rightWord = Object.keys(rightPair)[0]
84
- const rightNumber = Object.values(rightPair)[0]
85
-
86
- // Implicit one: omit "ένα" before any following value (> 0)
87
- if (leftNumber === 1n) {
88
- return rightPair
44
+ function buildSegment (n) {
45
+ if (n === 0) return ''
46
+
47
+ const ones = n % 10
48
+ const tens = Math.floor(n / 10) % 10
49
+ const hundreds = Math.floor(n / 100)
50
+
51
+ const parts = []
52
+
53
+ // Hundreds (irregular forms)
54
+ if (hundreds > 0) {
55
+ parts.push(HUNDREDS[hundreds])
56
+ }
57
+
58
+ // Tens and ones
59
+ const tensOnes = n % 100
60
+
61
+ if (tensOnes === 0) {
62
+ // Just hundreds
63
+ } else if (tensOnes < 10) {
64
+ parts.push(ONES[ones])
65
+ } else if (tensOnes < 20) {
66
+ parts.push(TEENS[ones])
67
+ } else if (ones === 0) {
68
+ parts.push(TENS[tens])
69
+ } else {
70
+ parts.push(TENS[tens] + ' ' + ONES[ones])
71
+ }
72
+
73
+ return parts.join(' ')
74
+ }
75
+
76
+ // Precompute all 1000 segment words (0-999)
77
+ const SEGMENTS = new Array(1000)
78
+
79
+ for (let i = 0; i < 1000; i++) {
80
+ SEGMENTS[i] = buildSegment(i)
81
+ }
82
+
83
+ // ============================================================================
84
+ // Conversion Functions
85
+ // ============================================================================
86
+
87
+ /**
88
+ * Converts a non-negative integer to Greek words.
89
+ *
90
+ * @param {bigint} n - Non-negative integer to convert
91
+ * @returns {string} Greek words
92
+ */
93
+ function integerToWords (n) {
94
+ if (n === 0n) return ZERO
95
+
96
+ // Fast path: numbers < 1000 (direct lookup)
97
+ if (n < 1000n) {
98
+ return SEGMENTS[Number(n)]
99
+ }
100
+
101
+ // Fast path: numbers < 1,000,000 (thousands)
102
+ if (n < 1_000_000n) {
103
+ const thousands = Number(n / 1000n)
104
+ const remainder = Number(n % 1000n)
105
+
106
+ // Omit "ένα" before χίλια
107
+ let result
108
+ if (thousands === 1) {
109
+ result = THOUSAND
110
+ } else {
111
+ result = SEGMENTS[thousands] + ' ' + THOUSAND
112
+ }
113
+
114
+ if (remainder > 0) {
115
+ result += ' ' + SEGMENTS[remainder]
89
116
  }
90
117
 
91
- // No special handling needed for trailing 'ένα';
92
- // nested merge will first collapse {1, 'ένα'} -> 'ένα'.
118
+ return result
119
+ }
120
+
121
+ // For numbers >= 1,000,000, use scale decomposition
122
+ return buildLargeNumberWords(n)
123
+ }
124
+
125
+ /**
126
+ * Builds words for numbers >= 1,000,000.
127
+ *
128
+ * @param {bigint} n - Number >= 1,000,000
129
+ * @returns {string} Greek words
130
+ */
131
+ function buildLargeNumberWords (n) {
132
+ const numStr = n.toString()
133
+ const len = numStr.length
134
+
135
+ // Build segments of 3 digits from right to left
136
+ const segments = []
137
+ const segmentSize = 3
138
+
139
+ const remainderLen = len % segmentSize
140
+ let pos = 0
141
+ if (remainderLen > 0) {
142
+ segments.push(Number(numStr.slice(0, remainderLen)))
143
+ pos = remainderLen
144
+ }
145
+ while (pos < len) {
146
+ segments.push(Number(numStr.slice(pos, pos + segmentSize)))
147
+ pos += segmentSize
148
+ }
149
+
150
+ // Convert segments to words
151
+ const parts = []
152
+ let scaleIndex = segments.length - 1
153
+
154
+ for (let i = 0; i < segments.length; i++) {
155
+ const segment = segments[i]
93
156
 
94
- // Multiplication: larger right scale multiplied by left number
95
- if (rightNumber > leftNumber) {
96
- return { [`${leftWord} ${rightWord}`]: leftNumber * rightNumber }
157
+ if (segment !== 0) {
158
+ const segmentWord = SEGMENTS[segment]
159
+
160
+ if (scaleIndex === 0) {
161
+ // Units segment
162
+ parts.push(segmentWord)
163
+ } else if (scaleIndex === 1) {
164
+ // Thousands - omit "ένα" before χίλια
165
+ if (segment === 1) {
166
+ parts.push(THOUSAND)
167
+ } else {
168
+ parts.push(segmentWord + ' ' + THOUSAND)
169
+ }
170
+ } else {
171
+ // Millions+ - omit "ένα" before scale words
172
+ const scaleWord = SCALES[scaleIndex - 2]
173
+ if (segment === 1) {
174
+ parts.push(scaleWord)
175
+ } else {
176
+ parts.push(segmentWord + ' ' + scaleWord)
177
+ }
178
+ }
97
179
  }
98
180
 
99
- // Addition: smaller numbers added together
100
- return { [`${leftWord} ${rightWord}`]: leftNumber + rightNumber }
181
+ scaleIndex--
101
182
  }
183
+
184
+ return parts.join(' ')
102
185
  }
103
186
 
104
187
  /**
105
- * Converts a number to its word representation in Greek.
106
- * @param {number|string|bigint} value - The number to convert
107
- * @param {Object} [options={}] - Conversion options
108
- * @returns {string} The word representation of the number
188
+ * Converts decimal digits to Greek words (per-digit).
189
+ *
190
+ * @param {string} decimalPart - Decimal digits (without the point)
191
+ * @returns {string} Greek words for decimal part
192
+ */
193
+ function decimalPartToWords (decimalPart) {
194
+ const parts = []
195
+
196
+ for (const digit of decimalPart) {
197
+ const d = parseInt(digit, 10)
198
+ if (d === 0) {
199
+ parts.push(ZERO)
200
+ } else {
201
+ parts.push(ONES[d])
202
+ }
203
+ }
204
+
205
+ return parts.join(' ')
206
+ }
207
+
208
+ /**
209
+ * Converts a numeric value to Greek words.
210
+ *
211
+ * @param {number | string | bigint} value - The numeric value to convert
212
+ * @returns {string} The number in Greek words
213
+ * @throws {TypeError} If value is not a valid numeric type
214
+ * @throws {Error} If value is not a valid number format
215
+ *
109
216
  * @example
110
- * convertToWords(42) // 'σαράντα δύο'
111
- * convertToWords(1000) // 'χίλια'
112
- * convertToWords(2000) // 'δύο χίλια'
217
+ * toWords(21) // 'είκοσι ένα'
218
+ * toWords(1000) // 'χίλια'
219
+ * toWords('3.14') // 'τρία κόμμα ένα τέσσερα'
113
220
  */
114
- export default function convertToWords (value, options = {}) {
115
- return new GreekLanguage(options).convertToWords(value)
221
+ function toWords (value) {
222
+ const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
223
+
224
+ let result = ''
225
+
226
+ if (isNegative) {
227
+ result = NEGATIVE + ' '
228
+ }
229
+
230
+ result += integerToWords(integerPart)
231
+
232
+ if (decimalPart) {
233
+ result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart)
234
+ }
235
+
236
+ return result
116
237
  }
238
+
239
+ // ============================================================================
240
+ // Public API
241
+ // ============================================================================
242
+
243
+ export { toWords }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Converts a numeric value to English words.
3
+ *
4
+ * This is the main public API. It accepts any valid numeric input
5
+ * (number, string, or bigint) and handles parsing internally.
6
+ *
7
+ * @param {number | string | bigint} value - The numeric value to convert
8
+ * @returns {string} The number in English words
9
+ * @throws {TypeError} If value is not a valid numeric type
10
+ * @throws {Error} If value is not a valid number format
11
+ *
12
+ * @example
13
+ * toWords(42) // 'forty-two'
14
+ * toWords(-3.14) // 'minus three point one four'
15
+ * toWords('1000000') // 'one million'
16
+ */
17
+ export function toWords(value: number | string | bigint): string;