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
package/CHANGELOG.md ADDED
@@ -0,0 +1,49 @@
1
+ ## 3.0.0 - Functional Architecture
2
+
3
+ Complete rewrite from class-based to functional architecture with major performance improvements.
4
+
5
+ ### ⚠ BREAKING CHANGES
6
+
7
+ **Migration required** - API has changed:
8
+
9
+ #### From v1.x (default export)
10
+
11
+ > **Note:** v1 bundled all languages into a single wrapper function with runtime language selection via `{ lang: 'es' }`. v3 requires explicit language imports for tree-shaking—only the languages you import are included in your bundle.
12
+
13
+ | Context | v1 | v3 |
14
+ |---------|----|----|
15
+ | **Import (all)** | `import n2words from 'n2words'` | `import { en, es } from 'n2words'` |
16
+ | **Import (single)** | `import es from 'n2words/languages/es'` | `import { toWords } from 'n2words/es'` |
17
+ | **Usage** | `n2words(42, { lang: 'es' })` | `es(42)` or `toWords(42)` |
18
+ | **Browser** | `n2words(42, { lang: 'es' })` | `n2words.es(42)` |
19
+ | **CDN (single)** | `.../dist/languages/es.js` | `.../dist/languages/es.js` (unchanged) |
20
+
21
+ #### From v2.x (class-based)
22
+
23
+ | Context | v2 | v3 |
24
+ |---------|----|----|
25
+ | **Import (all)** | `import { EnglishConverter } from 'n2words'` | `import { en } from 'n2words'` |
26
+ | **Import (single)** | `import { EnglishConverter } from 'n2words/en'` | `import { toWords } from 'n2words/en'` |
27
+ | **Usage** | `EnglishConverter(42)` | `en(42)` or `toWords(42)` |
28
+ | **Browser** | `n2words.EnglishConverter(42)` | `n2words.en(42)` |
29
+ | **CDN (single)** | `.../dist/EnglishConverter.js` | `.../dist/languages/en.js` |
30
+
31
+ ### Highlights
32
+
33
+ - **3x-85x faster** conversion across languages
34
+ - **70-96% less memory** per conversion
35
+ - **75-92% smaller** per-language bundles
36
+ - **52 languages** - all self-contained, tree-shakeable modules
37
+
38
+ ### New Languages
39
+
40
+ `am` (Amharic), `am-Latn` (Amharic Latin), `fi` (Finnish), `ha` (Hausa), `hbo` (Biblical Hebrew), `sr-Cyrl` (Serbian Cyrillic), `zh-Hant` (Traditional Chinese)
41
+
42
+ ### Performance Improvements
43
+
44
+ - Precomputed lookup tables (en, pt, he, hbo)
45
+ - BigInt modulo instead of string slicing (ja, sw)
46
+ - Eliminated class instantiation overhead
47
+
48
+ ---
49
+ See [#206](https://github.com/forzagreen/n2words/pull/206) for full details.
package/README.md CHANGED
@@ -1,223 +1,250 @@
1
1
  # n2words
2
2
 
3
- [![CI](https://github.com/forzagreen/n2words/actions/workflows/test.yml/badge.svg)](https://github.com/forzagreen/n2words/actions/workflows/test.yml)
4
- [![Coverage Status](https://coveralls.io/repos/github/forzagreen/n2words/badge.svg)](https://coveralls.io/github/forzagreen/n2words)
5
- [![npm](https://img.shields.io/npm/v/n2words.svg)](https://npmjs.com/package/n2words)
6
- [![npm](https://img.shields.io/npm/dw/n2words)](https://npmjs.com/package/n2words)
7
- [![jsDelivr](https://data.jsdelivr.com/v1/package/npm/n2words/badge)](https://www.jsdelivr.com/package/npm/n2words)
3
+ [![CI](https://github.com/forzagreen/n2words/actions/workflows/ci.yml/badge.svg)](https://github.com/forzagreen/n2words/actions/workflows/ci.yml)
4
+ [![Coverage](https://img.shields.io/coveralls/github/forzagreen/n2words)](https://coveralls.io/github/forzagreen/n2words)
5
+ [![npm version](https://img.shields.io/npm/v/n2words)](https://npmjs.com/package/n2words)
6
+ [![npm provenance](https://img.shields.io/badge/npm-provenance-blue)](https://www.npmjs.com/package/n2words)
7
+ [![Bundle size](https://img.shields.io/bundlephobia/minzip/n2words)](https://bundlephobia.com/package/n2words)
8
+ [![npm downloads](https://img.shields.io/npm/dw/n2words)](https://npmjs.com/package/n2words)
9
+ [![jsDelivr](https://img.shields.io/jsdelivr/npm/hm/n2words)](https://www.jsdelivr.com/package/npm/n2words)
8
10
 
9
- **n2words** converts numerical numbers into written ones. Supports **45 languages** with **zero dependencies**.
11
+ **Convert numbers to words in 52 languages with zero dependencies.**
10
12
 
11
- - 🌍 **45 languages** - Comprehensive international language support
12
- - 📦 **Zero dependencies** - Lightweight and fast
13
- - 🚀 **Performance optimized** - Highly tuned for speed
14
- - 📱 **Universal** - Works in browsers, Node.js, and TypeScript
15
- - 🧩 **Modular** - Import only the languages you need, keeping your bundle size minimal
16
- - 🔒 **Type-safe** - Full TypeScript support with language code literals and language-specific options
13
+ ## Why n2words?
17
14
 
18
- ## Quick Start
19
-
20
- ```js
21
- import n2words from 'n2words';
22
-
23
- n2words(123); // 'one hundred and twenty-three'
24
- n2words(-1.5); // 'minus one point five'
25
- n2words(123, { lang: 'zh-Hans' }); // '壹佰贰拾叁'
26
- n2words(123, { lang: 'hi' }); // 'एक सौ तेईस'
27
- n2words(123, { lang: 'es' }); // 'ciento veintitrés'
28
- n2words(123, { lang: 'ar' }); // 'مائة وثلاثة وعشرون'
29
- n2words(10000n, { lang: 'zh-Hans' }); // '壹万' (BigInt support!)
30
- ```
15
+ - **52 Languages** — European, Asian, Middle Eastern, and regional variants
16
+ - **Zero Dependencies** — Pure JavaScript, works everywhere (Node.js, browsers, bundlers)
17
+ - **Type-Safe** — Full TypeScript support with generated `.d.ts` declarations
18
+ - **BigInt Support** — Handle arbitrarily large numbers without precision loss
19
+ - **High Performance** — 1M+ ops/sec, ~1.4 KB gzipped per language
31
20
 
32
- ## Installation
21
+ ## Quick Start
33
22
 
34
- ```sh
23
+ ```bash
35
24
  npm install n2words
36
25
  ```
37
26
 
38
- ## Usage
39
-
40
- ### Node.js / ESM
41
-
42
27
  ```js
43
- import n2words from 'n2words';
28
+ import { en, es, ar } from 'n2words'
44
29
 
45
- console.log(n2words(42)); // 'forty-two'
46
- console.log(n2words(3.14)); // 'three point one four'
30
+ en(123) // 'one hundred and twenty-three'
31
+ es(123) // 'ciento veintitrés'
32
+ ar(1, { gender: 'feminine' }) // 'واحدة' (with options)
47
33
  ```
48
34
 
49
- ### TypeScript
50
-
51
- **Full type safety with language-specific options:**
52
-
53
- ```ts
54
- import n2words, { type N2WordsOptions, type LanguageCode } from 'n2words';
35
+ ## Usage
55
36
 
56
- // Language code autocomplete (45+ languages)
57
- const lang: LanguageCode = 'zh-Hans'; // Full IntelliSense support
37
+ **ESM (Node.js, modern bundlers):**
58
38
 
59
- // Type-safe language-specific options
60
- const result1 = n2words(123, { lang: 'zh-Hans', formal: true }); // Chinese financial numerals
61
- const result2 = n2words(42, { lang: 'ar', feminine: true }); // Arabic feminine forms
62
- const result3 = n2words(91, { lang: 'fr', withHyphenSeparator: true }); // French with hyphens
39
+ ```js
40
+ // Named imports (tree-shakable)
41
+ import { en, es } from 'n2words'
63
42
 
64
- // Comprehensive type safety
65
- const options: N2WordsOptions = {
66
- lang: 'es',
67
- genderStem: 'a' // TypeScript validates this option for Spanish
68
- };
43
+ // Subpath imports (smallest bundle, recommended for single language)
44
+ import { toWords } from 'n2words/en'
45
+ import { toWords as esWords } from 'n2words/es'
69
46
  ```
70
47
 
71
- See [TYPESCRIPT_GUIDE.md](guides/TYPESCRIPT_GUIDE.md) for comprehensive TypeScript documentation.
48
+ **CommonJS (Node.js):**
72
49
 
73
- ### CommonJS
50
+ n2words is an ES module. For CommonJS environments, use dynamic import:
74
51
 
75
52
  ```js
76
- import('n2words').then(({ default: n2words }) => {
77
- console.log(n2words(100)); // 'one hundred'
78
- });
53
+ // Promise-based
54
+ import('n2words').then(({ en }) => {
55
+ console.log(en(42)) // 'forty-two'
56
+ })
57
+
58
+ // Subpath import (smallest bundle)
59
+ import('n2words/en').then(({ toWords }) => {
60
+ console.log(toWords(42)) // 'forty-two'
61
+ })
79
62
  ```
80
63
 
81
- ### Browser (UMD)
64
+ **Browser (UMD via CDN):**
82
65
 
83
66
  ```html
67
+ <!-- All languages -->
84
68
  <script src="https://cdn.jsdelivr.net/npm/n2words/dist/n2words.js"></script>
85
69
  <script>
86
- console.log(n2words(100)); // 'one hundred'
70
+ n2words.en(42) // 'forty-two'
71
+ n2words.es(123) // 'ciento veintitrés'
87
72
  </script>
88
- ```
89
73
 
90
- Or import specific languages:
74
+ <!-- Single language (smallest, ~1.4 KB gzipped) -->
75
+ <script src="https://cdn.jsdelivr.net/npm/n2words/dist/languages/en.js"></script>
76
+ <script>
77
+ n2words.en(42) // 'forty-two'
78
+ </script>
91
79
 
92
- ```html
93
- <script src="https://cdn.jsdelivr.net/npm/n2words/dist/languages/fr.js"></script>
80
+ <!-- Multiple single-language bundles (no conflicts) -->
81
+ <script src="https://cdn.jsdelivr.net/npm/n2words/dist/languages/en.js"></script>
82
+ <script src="https://cdn.jsdelivr.net/npm/n2words/dist/languages/es.js"></script>
94
83
  <script>
95
- console.log(n2words(100, { lang: 'fr' })); // 'cent'
84
+ n2words.en(42) // 'forty-two'
85
+ n2words.es(42) // 'cuarenta y dos'
96
86
  </script>
97
87
  ```
98
88
 
99
- ## Supported Languages
100
-
101
- | Code | Language | Code | Language |
102
- | --------- | -------------------- | --------- | ---------------- |
103
- | `ar` | Arabic | `az` | Azerbaijani |
104
- | `bn` | Bengali | `cs` | Czech |
105
- | `de` | German | `da` | Danish |
106
- | `el` | Greek | `en` | English |
107
- | `es` | Spanish | `fa` | Farsi/Persian |
108
- | `fr` | French | `fr-BE` | French (Belgium) |
109
- | `gu` | Gujarati | `he` | Hebrew |
110
- | `hi` | Hindi | `hr` | Croatian |
111
- | `hu` | Hungarian | `id` | Indonesian |
112
- | `it` | Italian | `ja` | Japanese |
113
- | `kn` | Kannada | `ko` | Korean |
114
- | `lt` | Lithuanian | `lv` | Latvian |
115
- | `mr` | Marathi | `ms` | Malay |
116
- | `nl` | Dutch | `nb` | Norwegian |
117
- | `pa-Guru` | Punjabi (Gurmukhi) | `pl` | Polish |
118
- | `pt` | Portuguese | `ro` | Romanian |
119
- | `ru` | Russian | `sr-Latn` | Serbian (Latin) |
120
- | `sv` | Swedish | `sw` | Swahili |
121
- | `ta` | Tamil | `te` | Telugu |
122
- | `th` | Thai | `fil` | Filipino/Tagalog |
123
- | `tr` | Turkish | `uk` | Ukrainian |
124
- | `ur` | Urdu | `vi` | Vietnamese |
125
- | `zh-Hans` | Chinese (Simplified) | `gu` | Gujarati |
126
-
127
- ## Performance
128
-
129
- Performance benchmarks (ops/sec) on latest hardware:
130
-
131
- | Language | Performance |
132
- | --------------- | ------------- |
133
- | Arabic (ar) | ~180k ops/sec |
134
- | Indonesian (id) | ~160k ops/sec |
135
- | Vietnamese (vi) | ~165k ops/sec |
136
- | Persian (fa) | ~125k ops/sec |
137
- | Hebrew (he) | ~115k ops/sec |
138
-
139
- All languages are highly optimized. Run `npm run bench:perf` to benchmark on your system.
89
+ ## Supported Languages (52)
140
90
 
141
- ## Examples
91
+ Language codes follow [IETF BCP 47](https://tools.ietf.org/html/bcp47) standards.
142
92
 
143
- ### Basic Usage
93
+ | Code | Language | Options | Code | Language | Options |
94
+ | --------- | ------------------- | ------- | --------- | ------------------- | ------- |
95
+ | `am` | Amharic | | `am-Latn` | Amharic Latin | |
96
+ | `ar` | Arabic | ✓ | `az` | Azerbaijani | |
97
+ | `bn` | Bengali | | `cs` | Czech | |
98
+ | `da` | Danish | | `de` | German | |
99
+ | `el` | Greek | | `en` | English | |
100
+ | `es` | Spanish | ✓ | `fa` | Persian | |
101
+ | `fi` | Finnish | | `fil` | Filipino | |
102
+ | `fr` | French | ✓ | `fr-BE` | Belgian French | ✓ |
103
+ | `gu` | Gujarati | | `ha` | Hausa | |
104
+ | `hbo` | Biblical Hebrew | ✓ | `he` | Modern Hebrew | ✓ |
105
+ | `hi` | Hindi | | `hr` | Croatian | ✓ |
106
+ | `hu` | Hungarian | | `id` | Indonesian | |
107
+ | `it` | Italian | | `ja` | Japanese | |
108
+ | `kn` | Kannada | | `ko` | Korean | |
109
+ | `lt` | Lithuanian | ✓ | `lv` | Latvian | ✓ |
110
+ | `mr` | Marathi | | `ms` | Malay | |
111
+ | `nb` | Norwegian Bokmål | | `nl` | Dutch | ✓ |
112
+ | `pa` | Punjabi | | `pl` | Polish | ✓ |
113
+ | `pt` | Portuguese | | `ro` | Romanian | ✓ |
114
+ | `ru` | Russian | ✓ | `sr-Cyrl` | Serbian Cyrillic | ✓ |
115
+ | `sr-Latn` | Serbian Latin | ✓ | `sv` | Swedish | |
116
+ | `sw` | Swahili | | `ta` | Tamil | |
117
+ | `te` | Telugu | | `th` | Thai | |
118
+ | `tr` | Turkish | ✓ | `uk` | Ukrainian | ✓ |
119
+ | `ur` | Urdu | | `vi` | Vietnamese | |
120
+ | `zh-Hans` | Chinese Simplified | ✓ | `zh-Hant` | Chinese Traditional | ✓ |
144
121
 
145
- ```js
146
- n2words(0); // 'zero'
147
- n2words(1); // 'one'
148
- n2words(10); // 'ten'
149
- n2words(100); // 'one hundred'
150
- n2words(1000); // 'one thousand'
151
- n2words(1000000); // 'one million'
152
- ```
122
+ ### Language Options
153
123
 
154
- ### Decimal Numbers
124
+ 19 languages support additional options. Common options include:
155
125
 
156
- ```js
157
- n2words(3.14); // 'three point one four'
158
- n2words(10.5); // 'ten point five'
159
- n2words(0.007); // 'zero point zero zero seven'
126
+ **`gender`** (`'masculine'` | `'feminine'`) - 12 languages
127
+ Arabic, Biblical Hebrew, Croatian, Latvian, Lithuanian, Polish, Romanian, Russian, Serbian (both scripts), Spanish, Ukrainian
160
128
 
161
- // Some languages read decimals digit-by-digit
162
- n2words(3.14, { lang: 'ja' }); // '三点一四' (Japanese: san-ten-ichi-yon)
163
- n2words(2.05, { lang: 'th' }); // 'สามจุดหนึ่งสี่' (Thai: each digit spoken)
164
- ```
129
+ **`formal`** (`boolean`) - 2 languages
130
+ Simplified Chinese, Traditional Chinese - Toggle between formal/financial and common numerals
131
+
132
+ **Other options:**
165
133
 
166
- ### Negative Numbers
134
+ - Dutch: `includeOptionalAnd`, `accentOne`, `noHundredPairing`
135
+ - French/Belgian French: `withHyphenSeparator`
136
+ - Hebrew (Modern & Biblical): `andWord`
137
+ - Turkish: `dropSpaces`
138
+ - Arabic: `negativeWord` (custom negative word)
139
+
140
+ ## Browser Compatibility
141
+
142
+ **Minimum Requirements** (due to BigInt):
143
+
144
+ - **Node.js**: 20 or above
145
+ - **Browsers**: Chrome 67+, Firefox 68+, Safari 14+, Edge 79+ (desktop + mobile)
146
+ - **Global Coverage**: ~86% of all users worldwide
147
+
148
+ **Note**: BigInt is a hard requirement and cannot be polyfilled. Older browsers are not supported.
149
+
150
+ **Build options:**
151
+
152
+ - **Browser CDN**: Use `dist/n2words.js` (pre-built UMD, tested in real browsers)
153
+ - **Node.js/Bundlers**: Use `lib/` source (ES modules, tree-shakable)
154
+
155
+ [See detailed compatibility guide →](COMPATIBILITY.md)
156
+
157
+ ## Performance & Bundle Size
158
+
159
+ ### Bundle Size Comparison
160
+
161
+ | Import Strategy | Bundle Size | Gzipped | Languages |
162
+ | ------------------------------ | ----------- | --------- | --------- |
163
+ | All languages (UMD) | ~116 KB | ~28 KB | All 52 |
164
+ | Single language (UMD) | ~3-5 KB | ~1.4-2 KB | 1 |
165
+ | **Subpath import (ESM)** ⭐ | ~3 KB | ~1.4 KB | 1 |
166
+ | Named imports (ESM, 1 lang) | ~3-5 KB | ~1.4-2 KB | 1 |
167
+ | Named imports (ESM, 3 langs) | ~9-15 KB | ~4-6 KB | 3 |
168
+ | Named imports (ESM, 10 langs) | ~30-50 KB | ~10-15 KB | 10 |
169
+
170
+ ### Performance Characteristics
171
+
172
+ - **1M+ ops/sec**: Most languages exceed 1 million conversions per second
173
+ - **Sub-millisecond**: Typical conversion takes < 1 microsecond
174
+ - **Low memory**: ~500-800 bytes per conversion (no allocations for small numbers)
175
+ - **BigInt optimized**: Uses BigInt modulo instead of string manipulation
176
+ - **Precomputed tables**: Common segments (0-999) precomputed at module load
177
+
178
+ **Subpath imports (recommended for single language):**
167
179
 
168
180
  ```js
169
- n2words(-42); // 'minus forty-two'
170
- n2words(-3.14); // 'minus three point one four'
181
+ // Smallest possible bundle - no barrel file overhead
182
+ import { toWords } from 'n2words/en'
183
+ toWords(42) // 'forty-two'
184
+ // Final bundle: ~1.4 KB gzipped
171
185
  ```
172
186
 
173
- ### Large Numbers
187
+ **Named imports (for multiple languages):**
174
188
 
175
189
  ```js
176
- n2words(1000000000); // 'one billion'
177
- n2words(1234567890); // 'one billion two hundred and thirty-four million five hundred and sixty-seven thousand eight hundred and ninety'
190
+ // Bundler tree-shakes unused languages
191
+ import { en, es } from 'n2words'
192
+ // Final bundle: ~3-4 KB gzipped (English + Spanish)
193
+ ```
194
+
195
+ **Run benchmarks:**
196
+
197
+ ```bash
198
+ npm run bench:perf # Performance benchmarks (ops/sec)
199
+ npm run bench:memory # Memory usage benchmarks
178
200
  ```
179
201
 
180
- ### BigInt Support
202
+ ## Examples
181
203
 
182
204
  ```js
183
- n2words(123456789012345n); // Works with arbitrarily large integers
205
+ import { en, es, ar, zhHans } from 'n2words'
206
+
207
+ // Basic conversions
208
+ en(42) // 'forty-two'
209
+ en(3.14) // 'three point one four'
210
+ en(-1000000) // 'minus one million'
211
+
212
+ // Input types: number, string, or BigInt
213
+ en('42') // 'forty-two'
214
+ en(42n) // 'forty-two'
215
+ en(999999999999999999999999n) // Works with arbitrarily large integers
216
+
217
+ // Gender agreement (12 languages)
218
+ es(1) // 'uno' (masculine, default)
219
+ es(1, { gender: 'feminine' }) // 'una'
220
+ ar(1, { gender: 'feminine' }) // 'واحدة'
221
+
222
+ // Chinese: formal (financial) vs common numerals
223
+ zhHans(123) // '壹佰贰拾叁' (formal, default)
224
+ zhHans(123, { formal: false }) // '一百二十三' (common)
184
225
  ```
185
226
 
186
227
  ## Documentation
187
228
 
188
- - [TYPESCRIPT_GUIDE.md](./guides/TYPESCRIPT_GUIDE.md) - **Comprehensive TypeScript guide** with enhanced type safety
189
- - [LANGUAGE_OPTIONS.md](./guides/LANGUAGE_OPTIONS.md) - Language-specific options and examples
190
- - [LANGUAGE_GUIDE.md](./guides/LANGUAGE_GUIDE.md) - Comprehensive guide for adding new languages
191
- - [BIGINT-GUIDE.md](./guides/BIGINT-GUIDE.md) - BigInt usage guide for language developers
192
- - [CONTRIBUTING.md](./CONTRIBUTING.md) - Contribution guidelines
193
- - [Wiki](https://github.com/forzagreen/n2words/wiki) - Detailed examples and guides
229
+ - **[Compatibility Guide](COMPATIBILITY.md)** - Browser and Node.js compatibility
230
+ - **[Contributing Guide](CONTRIBUTING.md)** - How to contribute and add languages
231
+ - **[Code of Conduct](CODE_OF_CONDUCT.md)** - Community standards
194
232
 
195
233
  ## Contributing
196
234
 
197
- This library is actively maintained and welcomes contributions!
198
-
199
- - 🐛 **Bug reports** - Help us fix issues
200
- - ✨ **Feature requests** - Suggest improvements
201
- - 🌐 **New languages** - Add support for more languages (use `npm run lang:add` to get started!)
202
- - 📝 **Documentation** - Improve guides and examples
203
-
204
- ### Adding a New Language
205
-
206
- We provide automated tools to streamline language implementation:
235
+ We welcome contributions! Add a new language or improve existing ones:
207
236
 
208
237
  ```bash
209
- # Generate boilerplate for a new language
210
- npm run lang:add
238
+ npm run lang:add <code> # Scaffold a new language (BCP 47 code)
239
+ npm test # Run full test suite
240
+ ```
211
241
 
212
- # Validate your implementation
213
- npm run lang:validate <language-code>
242
+ Also welcome: bug reports, feature requests, documentation improvements, and language enhancements.
214
243
 
215
- # Validate all languages
216
- npm run lang:validate
217
- ```
244
+ Please read our [Code of Conduct](CODE_OF_CONDUCT.md) before contributing.
218
245
 
219
- See [CONTRIBUTING.md](./CONTRIBUTING.md) and [LANGUAGE_GUIDE.md](./guides/LANGUAGE_GUIDE.md) for detailed guidance.
246
+ **[See full contributing guide →](CONTRIBUTING.md)**
220
247
 
221
248
  ## License
222
249
 
223
- [MIT](./LICENSE) © 2025
250
+ [MIT](./LICENSE) © Wael TELLAT, Tyler Vigario & contributors
@@ -0,0 +1,3 @@
1
+ /*! n2words/am-Latn v3.0.0 | MIT License | github.com/forzagreen/n2words */
2
+ var e,t;e=this,t=function(e){"use strict";function t(e){const t="-"===e[0];t&&(e=e.slice(1));const n=e.indexOf(".");if(-1===n)return{isNegative:t,integerPart:BigInt(e)};const i=e.slice(0,n)||"0",r=e.slice(n+1);return{isNegative:t,integerPart:BigInt(i),decimalPart:r}}function n(e){const[t,n]=e.toLowerCase().split("e"),i=parseInt(n,10),r=t.indexOf("."),s=-1===r?t:t.slice(0,r)+t.slice(r+1),a=(-1===r?t.length:r)+i;return a>=s.length?s+"0".repeat(a-s.length):a<=0?"0."+"0".repeat(-a)+s:s.slice(0,a)+"."+s.slice(a)}const i=["","and","hulet","sost","arat","amist","siddist","sebat","siment","zeteny"],r=["asir","asra and","asra hulet","asra sost","asra arat","asra amist","asra siddist","asra sebat","asra siment","asra zeteny"],s=["","","haya","selasa","arba","hamsa","silsa","seba","semanya","zetena"],a="zero",o=["","shi","miliyon","billiyon"];function u(e){if(0===e)return"";const t=e%10,n=Math.floor(e/10)%10,a=Math.floor(e/100),o=[];return a>0&&o.push(i[a]+" meto"),1===n?o.push(r[t]):(n>1&&o.push(s[n]),t>0&&o.push(i[t])),o.join(" ")}const c=new Array(1e3);for(let e=0;e<1e3;e++)c[e]=u(e);e.amLatn=function(e){const{isNegative:r,integerPart:s,decimalPart:u}=function(e){const i=typeof e;if("bigint"===i)return e<0n?{isNegative:!0,integerPart:-e}:{isNegative:!1,integerPart:e};if("number"===i){if(!Number.isFinite(e))throw new Error("Number must be finite (NaN and Infinity are not supported)");return Number.isSafeInteger(e)?e<0?{isNegative:!0,integerPart:BigInt(-e)}:{isNegative:!1,integerPart:BigInt(e)}:t(function(e){const t=e.toString();return t.includes("e")||t.includes("E")?n(t):t}(e))}if("string"===i)return t(function(e){const t=e.trim();if(0===t.length||Number.isNaN(Number(t)))throw new Error(`Invalid number format: "${e}"`);return t.includes("e")||t.includes("E")?n(t):t}(e));throw new TypeError(`Invalid value type: expected number, string, or bigint, received ${i}`)}(e);let l="";return r&&(l="asitegna "),l+=0n===(f=s)?a:f<1000n?c[Number(f)]:function(e){const t=e.toString(),n=t.length,i=[],r=n%3;let s=0;for(r>0&&(i.push(Number(t.slice(0,r))),s=r);s<n;)i.push(Number(t.slice(s,s+3))),s+=3;const a=[];let u=i.length-1;for(let e=0;e<i.length;e++){const t=i[e];0!==t&&a.push(0===u?c[t]:c[t]+" "+(o[u]||"")),u--}return a.join(" ")}(f),u&&(l+=" netib "+function(e){const t=[];for(const n of e){const e=parseInt(n,10);t.push(0===e?a:i[e])}return t.join(" ")}(u)),l;var f}},"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).n2words=e.n2words||{});
3
+ //# sourceMappingURL=am-Latn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"am-Latn.js","sources":["../../lib/utils/parse-numeric.js","../../lib/languages/am-Latn.js"],"sourcesContent":["/**\n * Numeric value parsing utility.\n * Transforms user input (number, string, or bigint) into normalized components.\n * @module parse-numeric\n */\n\n/**\n * Parses a numeric value into its components.\n * @param {number|string|bigint} value\n * @returns {{isNegative: boolean, integerPart: bigint, decimalPart?: string}}\n * @throws {TypeError} If value is not number, string, or bigint\n * @throws {Error} If value is not a valid number format\n */\nexport function parseNumericValue (value) {\n const type = typeof value\n\n // BigInt: simplest case\n if (type === 'bigint') {\n return value < 0n\n ? { isNegative: true, integerPart: -value }\n : { isNegative: false, integerPart: value }\n }\n\n // Number: fast path for safe integers\n if (type === 'number') {\n if (!Number.isFinite(value)) {\n throw new Error('Number must be finite (NaN and Infinity are not supported)')\n }\n if (Number.isSafeInteger(value)) {\n return value < 0\n ? { isNegative: true, integerPart: BigInt(-value) }\n : { isNegative: false, integerPart: BigInt(value) }\n }\n return parseNumericString(numberToString(value))\n }\n\n // String input\n if (type === 'string') {\n return parseNumericString(normalizeString(value))\n }\n\n throw new TypeError(\n `Invalid value type: expected number, string, or bigint, received ${type}`\n )\n}\n\n/**\n * Converts a number to decimal string, expanding scientific notation if needed.\n */\nfunction numberToString (value) {\n const str = value.toString()\n return (str.includes('e') || str.includes('E'))\n ? expandScientificNotation(str)\n : str\n}\n\n/**\n * Validates and normalizes a string numeric input.\n */\nfunction normalizeString (value) {\n const trimmed = value.trim()\n if (trimmed.length === 0 || Number.isNaN(Number(trimmed))) {\n throw new Error(`Invalid number format: \"${value}\"`)\n }\n return (trimmed.includes('e') || trimmed.includes('E'))\n ? expandScientificNotation(trimmed)\n : trimmed\n}\n\n/**\n * Parses a normalized numeric string into components.\n */\nfunction parseNumericString (str) {\n const isNegative = str[0] === '-'\n if (isNegative) str = str.slice(1)\n\n const dotIndex = str.indexOf('.')\n if (dotIndex === -1) {\n return { isNegative, integerPart: BigInt(str) }\n }\n\n const integerStr = str.slice(0, dotIndex) || '0'\n const decimalPart = str.slice(dotIndex + 1)\n return { isNegative, integerPart: BigInt(integerStr), decimalPart }\n}\n\n/**\n * Expands scientific notation to decimal form (e.g., \"1e21\" → \"1000...\").\n */\nfunction expandScientificNotation (str) {\n const [mantissa, expStr] = str.toLowerCase().split('e')\n const exp = parseInt(expStr, 10)\n\n const dotIndex = mantissa.indexOf('.')\n const digits = dotIndex === -1\n ? mantissa\n : mantissa.slice(0, dotIndex) + mantissa.slice(dotIndex + 1)\n const integerLength = dotIndex === -1 ? mantissa.length : dotIndex\n const newDotPosition = integerLength + exp\n\n if (newDotPosition >= digits.length) {\n return digits + '0'.repeat(newDotPosition - digits.length)\n }\n if (newDotPosition <= 0) {\n return '0.' + '0'.repeat(-newDotPosition) + digits\n }\n return digits.slice(0, newDotPosition) + '.' + digits.slice(newDotPosition)\n}\n","/**\n * Amharic Latin language converter - Functional Implementation\n *\n * Self-contained converter with precomputed lookup tables.\n * Latin/ASCII romanization of Amharic numerals.\n *\n * Key features:\n * - Romanized numerals (and, hulet, sost)\n * - Teens formed with \"asra\" prefix\n * - Keeps \"one\" before hundred: \"and meto\" (100)\n * - Short scale naming\n * - Per-digit decimal reading\n */\n\nimport { parseNumericValue } from '../utils/parse-numeric.js'\n\n// ============================================================================\n// Vocabulary\n// ============================================================================\n\nconst ONES = ['', 'and', 'hulet', 'sost', 'arat', 'amist', 'siddist', 'sebat', 'siment', 'zeteny']\nconst TEENS = ['asir', 'asra and', 'asra hulet', 'asra sost', 'asra arat', 'asra amist', 'asra siddist', 'asra sebat', 'asra siment', 'asra zeteny']\nconst TENS = ['', '', 'haya', 'selasa', 'arba', 'hamsa', 'silsa', 'seba', 'semanya', 'zetena']\n\nconst HUNDRED = 'meto'\nconst THOUSAND = 'shi'\n\nconst ZERO = 'zero'\nconst NEGATIVE = 'asitegna'\nconst DECIMAL_SEP = 'netib'\n\n// Short scale\nconst SCALE_WORDS = ['', THOUSAND, 'miliyon', 'billiyon']\n\n// ============================================================================\n// Precomputed Lookup Table\n// ============================================================================\n\nfunction buildSegment (n) {\n if (n === 0) return ''\n\n const ones = n % 10\n const tensDigit = Math.floor(n / 10) % 10\n const hundredsDigit = Math.floor(n / 100)\n\n const parts = []\n\n // Amharic keeps \"one\" before hundred: \"and meto\" (100)\n if (hundredsDigit > 0) {\n parts.push(ONES[hundredsDigit] + ' ' + HUNDRED)\n }\n\n if (tensDigit === 1) {\n parts.push(TEENS[ones])\n } else {\n if (tensDigit > 1) {\n parts.push(TENS[tensDigit])\n }\n if (ones > 0) {\n parts.push(ONES[ones])\n }\n }\n\n return parts.join(' ')\n}\n\nconst SEGMENTS = new Array(1000)\nfor (let i = 0; i < 1000; i++) {\n SEGMENTS[i] = buildSegment(i)\n}\n\n// ============================================================================\n// Conversion Functions\n// ============================================================================\n\nfunction integerToWords (n) {\n if (n === 0n) return ZERO\n\n if (n < 1000n) {\n return SEGMENTS[Number(n)]\n }\n\n return buildLargeNumberWords(n)\n}\n\nfunction buildLargeNumberWords (n) {\n const numStr = n.toString()\n const len = numStr.length\n\n const segments = []\n const segmentSize = 3\n\n const remainderLen = len % segmentSize\n let pos = 0\n if (remainderLen > 0) {\n segments.push(Number(numStr.slice(0, remainderLen)))\n pos = remainderLen\n }\n while (pos < len) {\n segments.push(Number(numStr.slice(pos, pos + segmentSize)))\n pos += segmentSize\n }\n\n const parts = []\n let scaleIndex = segments.length - 1\n\n for (let i = 0; i < segments.length; i++) {\n const segment = segments[i]\n\n if (segment !== 0) {\n const scaleWord = SCALE_WORDS[scaleIndex] || ''\n\n if (scaleIndex === 0) {\n parts.push(SEGMENTS[segment])\n } else {\n parts.push(SEGMENTS[segment] + ' ' + scaleWord)\n }\n }\n\n scaleIndex--\n }\n\n return parts.join(' ')\n}\n\nfunction decimalPartToWords (decimalPart) {\n // Per-digit decimal reading\n const digits = []\n for (const char of decimalPart) {\n const d = parseInt(char, 10)\n digits.push(d === 0 ? ZERO : ONES[d])\n }\n return digits.join(' ')\n}\n\n/**\n * Converts a numeric value to Amharic (Latin script) words.\n *\n * @param {number | string | bigint} value - The numeric value to convert\n * @returns {string} The number in Amharic Latin words\n */\nfunction toWords (value) {\n const { isNegative, integerPart, decimalPart } = parseNumericValue(value)\n\n let result = ''\n\n if (isNegative) {\n result = NEGATIVE + ' '\n }\n\n result += integerToWords(integerPart)\n\n if (decimalPart) {\n result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart)\n }\n\n return result\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport { toWords }\n"],"names":["parseNumericString","str","isNegative","slice","dotIndex","indexOf","integerPart","BigInt","integerStr","decimalPart","expandScientificNotation","mantissa","expStr","toLowerCase","split","exp","parseInt","digits","newDotPosition","length","repeat","ONES","TEENS","TENS","ZERO","SCALE_WORDS","buildSegment","n","ones","tensDigit","Math","floor","hundredsDigit","parts","push","join","SEGMENTS","Array","i","value","type","Number","isFinite","Error","isSafeInteger","toString","includes","numberToString","trimmed","trim","isNaN","normalizeString","TypeError","parseNumericValue","result","NEGATIVE","numStr","len","segments","remainderLen","pos","scaleIndex","segment","buildLargeNumberWords","char","d","decimalPartToWords"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /*! n2words/am v3.0.0 | MIT License | github.com/forzagreen/n2words */
2
+ var e,t;e=this,t=function(e){"use strict";function t(e){const t="-"===e[0];t&&(e=e.slice(1));const n=e.indexOf(".");if(-1===n)return{isNegative:t,integerPart:BigInt(e)};const r=e.slice(0,n)||"0",i=e.slice(n+1);return{isNegative:t,integerPart:BigInt(r),decimalPart:i}}function n(e){const[t,n]=e.toLowerCase().split("e"),r=parseInt(n,10),i=t.indexOf("."),o=-1===i?t:t.slice(0,i)+t.slice(i+1),s=(-1===i?t.length:i)+r;return s>=o.length?o+"0".repeat(s-o.length):s<=0?"0."+"0".repeat(-s)+o:o.slice(0,s)+"."+o.slice(s)}const r=["","አንድ","ሁለት","ሶስት","አራት","አምስት","ስድስት","ሰባት","ስምንት","ዘጠኝ"],i=["አስር","አስራ አንድ","አስራ ሁለት","አስራ ሶስት","አስራ አራት","አስራ አምስት","አስራ ስድስት","አስራ ሰባት","አስራ ስምንት","አስራ ዘጠኝ"],o=["","","ሃያ","ሰላሳ","አርባ","ሃምሳ","ስልሳ","ሰባ","ሰማንያ","ዘጠና"],s=["","ሺ","ሚሊዮን","ቢሊዮን"];function u(e){if(0===e)return"";const t=e%10,n=Math.floor(e/10)%10,s=Math.floor(e/100),u=[];return s>0&&u.push(r[s]+" መቶ"),1===n?u.push(i[t]):(n>1&&u.push(o[n]),t>0&&u.push(r[t])),u.join(" ")}const c=new Array(1e3);for(let e=0;e<1e3;e++)c[e]=u(e);e.am=function(e){const{isNegative:i,integerPart:o,decimalPart:u}=function(e){const r=typeof e;if("bigint"===r)return e<0n?{isNegative:!0,integerPart:-e}:{isNegative:!1,integerPart:e};if("number"===r){if(!Number.isFinite(e))throw new Error("Number must be finite (NaN and Infinity are not supported)");return Number.isSafeInteger(e)?e<0?{isNegative:!0,integerPart:BigInt(-e)}:{isNegative:!1,integerPart:BigInt(e)}:t(function(e){const t=e.toString();return t.includes("e")||t.includes("E")?n(t):t}(e))}if("string"===r)return t(function(e){const t=e.trim();if(0===t.length||Number.isNaN(Number(t)))throw new Error(`Invalid number format: "${e}"`);return t.includes("e")||t.includes("E")?n(t):t}(e));throw new TypeError(`Invalid value type: expected number, string, or bigint, received ${r}`)}(e);let f="";return i&&(f="አሉታዊ "),f+=0n===(a=o)?"ዜሮ":a<1000n?c[Number(a)]:function(e){const t=e.toString(),n=t.length,r=[],i=n%3;let o=0;for(i>0&&(r.push(Number(t.slice(0,i))),o=i);o<n;)r.push(Number(t.slice(o,o+3))),o+=3;const u=[];let f=r.length-1;for(let e=0;e<r.length;e++){const t=r[e];0!==t&&u.push(0===f?c[t]:c[t]+" "+(s[f]||"")),f--}return u.join(" ")}(a),u&&(f+=" ነጥብ "+function(e){const t=[];for(const n of e){const e=parseInt(n,10);t.push(0===e?"ዜሮ":r[e])}return t.join(" ")}(u)),f;var a}},"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).n2words=e.n2words||{});
3
+ //# sourceMappingURL=am.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"am.js","sources":["../../lib/utils/parse-numeric.js","../../lib/languages/am.js"],"sourcesContent":["/**\n * Numeric value parsing utility.\n * Transforms user input (number, string, or bigint) into normalized components.\n * @module parse-numeric\n */\n\n/**\n * Parses a numeric value into its components.\n * @param {number|string|bigint} value\n * @returns {{isNegative: boolean, integerPart: bigint, decimalPart?: string}}\n * @throws {TypeError} If value is not number, string, or bigint\n * @throws {Error} If value is not a valid number format\n */\nexport function parseNumericValue (value) {\n const type = typeof value\n\n // BigInt: simplest case\n if (type === 'bigint') {\n return value < 0n\n ? { isNegative: true, integerPart: -value }\n : { isNegative: false, integerPart: value }\n }\n\n // Number: fast path for safe integers\n if (type === 'number') {\n if (!Number.isFinite(value)) {\n throw new Error('Number must be finite (NaN and Infinity are not supported)')\n }\n if (Number.isSafeInteger(value)) {\n return value < 0\n ? { isNegative: true, integerPart: BigInt(-value) }\n : { isNegative: false, integerPart: BigInt(value) }\n }\n return parseNumericString(numberToString(value))\n }\n\n // String input\n if (type === 'string') {\n return parseNumericString(normalizeString(value))\n }\n\n throw new TypeError(\n `Invalid value type: expected number, string, or bigint, received ${type}`\n )\n}\n\n/**\n * Converts a number to decimal string, expanding scientific notation if needed.\n */\nfunction numberToString (value) {\n const str = value.toString()\n return (str.includes('e') || str.includes('E'))\n ? expandScientificNotation(str)\n : str\n}\n\n/**\n * Validates and normalizes a string numeric input.\n */\nfunction normalizeString (value) {\n const trimmed = value.trim()\n if (trimmed.length === 0 || Number.isNaN(Number(trimmed))) {\n throw new Error(`Invalid number format: \"${value}\"`)\n }\n return (trimmed.includes('e') || trimmed.includes('E'))\n ? expandScientificNotation(trimmed)\n : trimmed\n}\n\n/**\n * Parses a normalized numeric string into components.\n */\nfunction parseNumericString (str) {\n const isNegative = str[0] === '-'\n if (isNegative) str = str.slice(1)\n\n const dotIndex = str.indexOf('.')\n if (dotIndex === -1) {\n return { isNegative, integerPart: BigInt(str) }\n }\n\n const integerStr = str.slice(0, dotIndex) || '0'\n const decimalPart = str.slice(dotIndex + 1)\n return { isNegative, integerPart: BigInt(integerStr), decimalPart }\n}\n\n/**\n * Expands scientific notation to decimal form (e.g., \"1e21\" → \"1000...\").\n */\nfunction expandScientificNotation (str) {\n const [mantissa, expStr] = str.toLowerCase().split('e')\n const exp = parseInt(expStr, 10)\n\n const dotIndex = mantissa.indexOf('.')\n const digits = dotIndex === -1\n ? mantissa\n : mantissa.slice(0, dotIndex) + mantissa.slice(dotIndex + 1)\n const integerLength = dotIndex === -1 ? mantissa.length : dotIndex\n const newDotPosition = integerLength + exp\n\n if (newDotPosition >= digits.length) {\n return digits + '0'.repeat(newDotPosition - digits.length)\n }\n if (newDotPosition <= 0) {\n return '0.' + '0'.repeat(-newDotPosition) + digits\n }\n return digits.slice(0, newDotPosition) + '.' + digits.slice(newDotPosition)\n}\n","/**\n * Amharic language converter - Functional Implementation\n *\n * Self-contained converter with precomputed lookup tables.\n * Native Ge'ez script (ግዕዝ) output.\n *\n * Key features:\n * - Ge'ez/Ethiopic script numerals\n * - Teens formed with \"አስራ\" prefix\n * - Keeps \"one\" before hundred: \"አንድ መቶ\" (100)\n * - Short scale naming\n * - Per-digit decimal reading\n */\n\nimport { parseNumericValue } from '../utils/parse-numeric.js'\n\n// ============================================================================\n// Vocabulary\n// ============================================================================\n\nconst ONES = ['', 'አንድ', 'ሁለት', 'ሶስት', 'አራት', 'አምስት', 'ስድስት', 'ሰባት', 'ስምንት', 'ዘጠኝ']\nconst TEENS = ['አስር', 'አስራ አንድ', 'አስራ ሁለት', 'አስራ ሶስት', 'አስራ አራት', 'አስራ አምስት', 'አስራ ስድስት', 'አስራ ሰባት', 'አስራ ስምንት', 'አስራ ዘጠኝ']\nconst TENS = ['', '', 'ሃያ', 'ሰላሳ', 'አርባ', 'ሃምሳ', 'ስልሳ', 'ሰባ', 'ሰማንያ', 'ዘጠና']\n\nconst HUNDRED = 'መቶ'\nconst THOUSAND = 'ሺ'\n\nconst ZERO = 'ዜሮ'\nconst NEGATIVE = 'አሉታዊ'\nconst DECIMAL_SEP = 'ነጥብ'\n\n// Short scale\nconst SCALE_WORDS = ['', THOUSAND, 'ሚሊዮን', 'ቢሊዮን']\n\n// ============================================================================\n// Precomputed Lookup Table\n// ============================================================================\n\nfunction buildSegment (n) {\n if (n === 0) return ''\n\n const ones = n % 10\n const tensDigit = Math.floor(n / 10) % 10\n const hundredsDigit = Math.floor(n / 100)\n\n const parts = []\n\n // Amharic keeps \"one\" before hundred: \"አንድ መቶ\" (100)\n if (hundredsDigit > 0) {\n parts.push(ONES[hundredsDigit] + ' ' + HUNDRED)\n }\n\n if (tensDigit === 1) {\n parts.push(TEENS[ones])\n } else {\n if (tensDigit > 1) {\n parts.push(TENS[tensDigit])\n }\n if (ones > 0) {\n parts.push(ONES[ones])\n }\n }\n\n return parts.join(' ')\n}\n\nconst SEGMENTS = new Array(1000)\nfor (let i = 0; i < 1000; i++) {\n SEGMENTS[i] = buildSegment(i)\n}\n\n// ============================================================================\n// Conversion Functions\n// ============================================================================\n\nfunction integerToWords (n) {\n if (n === 0n) return ZERO\n\n if (n < 1000n) {\n return SEGMENTS[Number(n)]\n }\n\n return buildLargeNumberWords(n)\n}\n\nfunction buildLargeNumberWords (n) {\n const numStr = n.toString()\n const len = numStr.length\n\n const segments = []\n const segmentSize = 3\n\n const remainderLen = len % segmentSize\n let pos = 0\n if (remainderLen > 0) {\n segments.push(Number(numStr.slice(0, remainderLen)))\n pos = remainderLen\n }\n while (pos < len) {\n segments.push(Number(numStr.slice(pos, pos + segmentSize)))\n pos += segmentSize\n }\n\n const parts = []\n let scaleIndex = segments.length - 1\n\n for (let i = 0; i < segments.length; i++) {\n const segment = segments[i]\n\n if (segment !== 0) {\n const scaleWord = SCALE_WORDS[scaleIndex] || ''\n\n if (scaleIndex === 0) {\n parts.push(SEGMENTS[segment])\n } else {\n parts.push(SEGMENTS[segment] + ' ' + scaleWord)\n }\n }\n\n scaleIndex--\n }\n\n return parts.join(' ')\n}\n\nfunction decimalPartToWords (decimalPart) {\n // Per-digit decimal reading\n const digits = []\n for (const char of decimalPart) {\n const d = parseInt(char, 10)\n digits.push(d === 0 ? ZERO : ONES[d])\n }\n return digits.join(' ')\n}\n\n/**\n * Converts a numeric value to Amharic words.\n *\n * @param {number | string | bigint} value - The numeric value to convert\n * @returns {string} The number in Amharic words\n */\nfunction toWords (value) {\n const { isNegative, integerPart, decimalPart } = parseNumericValue(value)\n\n let result = ''\n\n if (isNegative) {\n result = NEGATIVE + ' '\n }\n\n result += integerToWords(integerPart)\n\n if (decimalPart) {\n result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart)\n }\n\n return result\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport { toWords }\n"],"names":["parseNumericString","str","isNegative","slice","dotIndex","indexOf","integerPart","BigInt","integerStr","decimalPart","expandScientificNotation","mantissa","expStr","toLowerCase","split","exp","parseInt","digits","newDotPosition","length","repeat","ONES","TEENS","TENS","SCALE_WORDS","buildSegment","n","ones","tensDigit","Math","floor","hundredsDigit","parts","push","join","SEGMENTS","Array","i","value","type","Number","isFinite","Error","isSafeInteger","toString","includes","numberToString","trimmed","trim","isNaN","normalizeString","TypeError","parseNumericValue","result","NEGATIVE","numStr","len","segments","remainderLen","pos","scaleIndex","segment","buildLargeNumberWords","char","d","decimalPartToWords"],"mappings":"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"}
@@ -1,2 +1,3 @@
1
- !function(r,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.n2words=t():r.n2words=t()}(globalThis,()=>(()=>{"use strict";var r={34(r,t,e){var n=e(4901);r.exports=function(r){return"object"==typeof r?null!==r:n(r)}},283(r,t,e){var n=e(9504),o=e(9039),i=e(4901),a=e(9297),s=e(3724),u=e(350).CONFIGURABLE,c=e(3706),p=e(1181),f=p.enforce,l=p.get,h=String,v=Object.defineProperty,b=n("".slice),d=n("".replace),g=n([].join),y=s&&!o(function(){return 8!==v(function(){},"length",{value:8}).length}),m=String(String).split("String"),x=r.exports=function(r,t,e){"Symbol("===b(h(t),0,7)&&(t="["+d(h(t),/^Symbol\(([^)]*)\).*$/,"$1")+"]"),e&&e.getter&&(t="get "+t),e&&e.setter&&(t="set "+t),(!a(r,"name")||u&&r.name!==t)&&(s?v(r,"name",{value:t,configurable:!0}):r.name=t),y&&e&&a(e,"arity")&&r.length!==e.arity&&v(r,"length",{value:e.arity});try{e&&a(e,"constructor")&&e.constructor?s&&v(r,"prototype",{writable:!1}):r.prototype&&(r.prototype=void 0)}catch(r){}var n=f(r);return a(n,"source")||(n.source=g(m,"string"==typeof t?t:"")),r};Function.prototype.toString=x(function(){return i(this)&&l(this).source||c(this)},"toString")},350(r,t,e){var n=e(3724),o=e(9297),i=Function.prototype,a=n&&Object.getOwnPropertyDescriptor,s=o(i,"name"),u=s&&"something"===function(){}.name,c=s&&(!n||n&&a(i,"name").configurable);r.exports={EXISTS:s,PROPER:u,CONFIGURABLE:c}},421(r){r.exports={}},616(r,t,e){var n=e(9039);r.exports=!n(function(){var r=function(){}.bind();return"function"!=typeof r||r.hasOwnProperty("prototype")})},741(r){var t=Math.ceil,e=Math.floor;r.exports=Math.trunc||function(r){var n=+r;return(n>0?e:t)(n)}},757(r,t,e){var n=e(7751),o=e(4901),i=e(1625),a=e(7040),s=Object;r.exports=a?function(r){return"symbol"==typeof r}:function(r){var t=n("Symbol");return o(t)&&i(t.prototype,s(r))}},1181(r,t,e){var n,o,i,a=e(8622),s=e(4576),u=e(34),c=e(6699),p=e(9297),f=e(7629),l=e(6119),h=e(421),v="Object already initialized",b=s.TypeError,d=s.WeakMap;if(a||f.state){var g=f.state||(f.state=new d);g.get=g.get,g.has=g.has,g.set=g.set,n=function(r,t){if(g.has(r))throw new b(v);return t.facade=r,g.set(r,t),t},o=function(r){return g.get(r)||{}},i=function(r){return g.has(r)}}else{var y=l("state");h[y]=!0,n=function(r,t){if(p(r,y))throw new b(v);return t.facade=r,c(r,y,t),t},o=function(r){return p(r,y)?r[y]:{}},i=function(r){return p(r,y)}}r.exports={set:n,get:o,has:i,enforce:function(r){return i(r)?o(r):n(r,{})},getterFor:function(r){return function(t){var e;if(!u(t)||(e=o(t)).type!==r)throw new b("Incompatible receiver, "+r+" required");return e}}}},1291(r,t,e){var n=e(741);r.exports=function(r){var t=+r;return t!=t||0===t?0:n(t)}},1625(r,t,e){var n=e(9504);r.exports=n({}.isPrototypeOf)},1828(r,t,e){var n=e(9504),o=e(9297),i=e(5397),a=e(9617).indexOf,s=e(421),u=n([].push);r.exports=function(r,t){var e,n=i(r),c=0,p=[];for(e in n)!o(s,e)&&o(n,e)&&u(p,e);for(;t.length>c;)o(n,e=t[c++])&&(~a(p,e)||u(p,e));return p}},2195(r,t,e){var n=e(9504),o=n({}.toString),i=n("".slice);r.exports=function(r){return i(o(r),8,-1)}},2777(r,t,e){var n=e(9565),o=e(34),i=e(757),a=e(5966),s=e(4270),u=e(8227),c=TypeError,p=u("toPrimitive");r.exports=function(r,t){if(!o(r)||i(r))return r;var e,u=a(r,p);if(u){if(void 0===t&&(t="default"),e=n(u,r,t),!o(e)||i(e))return e;throw new c("Can't convert object to primitive value")}return void 0===t&&(t="number"),s(r,t)}},2796(r,t,e){var n=e(9039),o=e(4901),i=/#|\.prototype\./,a=function(r,t){var e=u[s(r)];return e===p||e!==c&&(o(t)?n(t):!!t)},s=a.normalize=function(r){return String(r).replace(i,".").toLowerCase()},u=a.data={},c=a.NATIVE="N",p=a.POLYFILL="P";r.exports=a},2839(r,t,e){var n=e(4576).navigator,o=n&&n.userAgent;r.exports=o?String(o):""},3392(r,t,e){var n=e(9504),o=0,i=Math.random(),a=n(1.1.toString);r.exports=function(r){return"Symbol("+(void 0===r?"":r)+")_"+a(++o+i,36)}},3706(r,t,e){var n=e(9504),o=e(4901),i=e(7629),a=n(Function.toString);o(i.inspectSource)||(i.inspectSource=function(r){return a(r)}),r.exports=i.inspectSource},3717(r,t){t.f=Object.getOwnPropertySymbols},3724(r,t,e){var n=e(9039);r.exports=!n(function(){return 7!==Object.defineProperty({},1,{get:function(){return 7}})[1]})},4055(r,t,e){var n=e(4576),o=e(34),i=n.document,a=o(i)&&o(i.createElement);r.exports=function(r){return a?i.createElement(r):{}}},4114(r,t,e){var n=e(6518),o=e(8981),i=e(6198),a=e(4527),s=e(6837);n({target:"Array",proto:!0,arity:1,forced:e(9039)(function(){return 4294967297!==[].push.call({length:4294967296},1)})||!function(){try{Object.defineProperty([],"length",{writable:!1}).push()}catch(r){return r instanceof TypeError}}()},{push:function(r){var t=o(this),e=i(t),n=arguments.length;s(e+n);for(var u=0;u<n;u++)t[e]=arguments[u],e++;return a(t,e),e}})},4117(r){r.exports=function(r){return null==r}},4270(r,t,e){var n=e(9565),o=e(4901),i=e(34),a=TypeError;r.exports=function(r,t){var e,s;if("string"===t&&o(e=r.toString)&&!i(s=n(e,r)))return s;if(o(e=r.valueOf)&&!i(s=n(e,r)))return s;if("string"!==t&&o(e=r.toString)&&!i(s=n(e,r)))return s;throw new a("Can't convert object to primitive value")}},4376(r,t,e){var n=e(2195);r.exports=Array.isArray||function(r){return"Array"===n(r)}},4495(r,t,e){var n=e(9519),o=e(9039),i=e(4576).String;r.exports=!!Object.getOwnPropertySymbols&&!o(function(){var r=Symbol("symbol detection");return!i(r)||!(Object(r)instanceof Symbol)||!Symbol.sham&&n&&n<41})},4527(r,t,e){var n=e(3724),o=e(4376),i=TypeError,a=Object.getOwnPropertyDescriptor,s=n&&!function(){if(void 0!==this)return!0;try{Object.defineProperty([],"length",{writable:!1}).length=1}catch(r){return r instanceof TypeError}}();r.exports=s?function(r,t){if(o(r)&&!a(r,"length").writable)throw new i("Cannot set read only .length");return r.length=t}:function(r,t){return r.length=t}},4576(r){var t=function(r){return r&&r.Math===Math&&r};r.exports=t("object"==typeof globalThis&&globalThis)||t("object"==typeof window&&window)||t("object"==typeof self&&self)||t("object"==typeof global&&global)||t("object"==typeof this&&this)||function(){return this}()||Function("return this")()},4901(r){var t="object"==typeof document&&document.all;r.exports=void 0===t&&void 0!==t?function(r){return"function"==typeof r||r===t}:function(r){return"function"==typeof r}},4913(r,t,e){var n=e(3724),o=e(5917),i=e(8686),a=e(8551),s=e(6969),u=TypeError,c=Object.defineProperty,p=Object.getOwnPropertyDescriptor,f="enumerable",l="configurable",h="writable";t.f=n?i?function(r,t,e){if(a(r),t=s(t),a(e),"function"==typeof r&&"prototype"===t&&"value"in e&&h in e&&!e[h]){var n=p(r,t);n&&n[h]&&(r[t]=e.value,e={configurable:l in e?e[l]:n[l],enumerable:f in e?e[f]:n[f],writable:!1})}return c(r,t,e)}:c:function(r,t,e){if(a(r),t=s(t),a(e),o)try{return c(r,t,e)}catch(r){}if("get"in e||"set"in e)throw new u("Accessors not supported");return"value"in e&&(r[t]=e.value),r}},5031(r,t,e){var n=e(7751),o=e(9504),i=e(8480),a=e(3717),s=e(8551),u=o([].concat);r.exports=n("Reflect","ownKeys")||function(r){var t=i.f(s(r)),e=a.f;return e?u(t,e(r)):t}},5397(r,t,e){var n=e(7055),o=e(7750);r.exports=function(r){return n(o(r))}},5610(r,t,e){var n=e(1291),o=Math.max,i=Math.min;r.exports=function(r,t){var e=n(r);return e<0?o(e+t,0):i(e,t)}},5745(r,t,e){var n=e(7629);r.exports=function(r,t){return n[r]||(n[r]=t||{})}},5917(r,t,e){var n=e(3724),o=e(9039),i=e(4055);r.exports=!n&&!o(function(){return 7!==Object.defineProperty(i("div"),"a",{get:function(){return 7}}).a})},5966(r,t,e){var n=e(9306),o=e(4117);r.exports=function(r,t){var e=r[t];return o(e)?void 0:n(e)}},6119(r,t,e){var n=e(5745),o=e(3392),i=n("keys");r.exports=function(r){return i[r]||(i[r]=o(r))}},6198(r,t,e){var n=e(8014);r.exports=function(r){return n(r.length)}},6298(r,t,e){e.d(t,{A:()=>n}),e(4114);const n=class{negativeWord="";decimalSeparatorWord="";zeroWord="";wordSeparator=" ";cachedWholeNumber=0n;convertDecimalsPerDigit=!1;digits=null;convertDigitToWord(r){const t=Number(r);if(0===t)return this.zeroWord;if(Array.isArray(this.digits)){if(10===this.digits.length)return this.digits[t]??this.zeroWord;if(9===this.digits.length)return this.digits[t-1]??this.zeroWord}return this.convertWholePart(r)}decimalDigitsToWords(r){const t=[],e=r.length;if(this.convertDecimalsPerDigit){for(let n=0;n<e;n++){const e=BigInt(r[n]);t.push(this.convertDigitToWord(e))}return t}let n=0;for(;n<e&&"0"===r[n];)t.push(this.zeroWord),n++;if(n===e)return t;const o=r.slice(n);return t.push(this.convertWholePart(BigInt(o))),t}convertToWords(r){const t=typeof r;if("number"===t){if(Number.isNaN(r))throw new TypeError("NaN is not an accepted number.");r=r.toString()}else if("string"===t){if(0===(r=r.trim()).length||Number.isNaN(Number(r)))throw new Error('Invalid number format: "'+r+'"')}else if("bigint"!==t)throw new TypeError("Invalid variable type, expected number|string|bigint, received: "+t);const e=[];let n,o,i=!1;if("bigint"===t?r<0n&&(i=!0,r=-r):"-"===r[0]&&(i=!0,r=r.slice(1)),"bigint"===t)n=r;else{const t=r.indexOf(".");if(-1===t)n=BigInt(r);else{const e=r.slice(0,t)||"0";n=BigInt(e),o=r.slice(t+1)}}return this.cachedWholeNumber=n,i&&e.push(this.negativeWord),e.push(this.convertWholePart(n)),o&&(e.push(this.decimalSeparatorWord),e.push(...this.decimalDigitsToWords(o))),e.join(this.wordSeparator)}convertWholePart(r){throw new Error("convertWholePart() must be implemented by subclass")}}},6395(r){r.exports=!1},6518(r,t,e){var n=e(4576),o=e(7347).f,i=e(6699),a=e(6840),s=e(9433),u=e(7740),c=e(2796);r.exports=function(r,t){var e,p,f,l,h,v=r.target,b=r.global,d=r.stat;if(e=b?n:d?n[v]||s(v,{}):n[v]&&n[v].prototype)for(p in t){if(l=t[p],f=r.dontCallGetSet?(h=o(e,p))&&h.value:e[p],!c(b?p:v+(d?".":"#")+p,r.forced)&&void 0!==f){if(typeof l==typeof f)continue;u(l,f)}(r.sham||f&&f.sham)&&i(l,"sham",!0),a(e,p,l,r)}}},6699(r,t,e){var n=e(3724),o=e(4913),i=e(6980);r.exports=n?function(r,t,e){return o.f(r,t,i(1,e))}:function(r,t,e){return r[t]=e,r}},6823(r){var t=String;r.exports=function(r){try{return t(r)}catch(r){return"Object"}}},6837(r){var t=TypeError;r.exports=function(r){if(r>9007199254740991)throw t("Maximum allowed index exceeded");return r}},6840(r,t,e){var n=e(4901),o=e(4913),i=e(283),a=e(9433);r.exports=function(r,t,e,s){s||(s={});var u=s.enumerable,c=void 0!==s.name?s.name:t;if(n(e)&&i(e,c,s),s.global)u?r[t]=e:a(t,e);else{try{s.unsafe?r[t]&&(u=!0):delete r[t]}catch(r){}u?r[t]=e:o.f(r,t,{value:e,enumerable:!1,configurable:!s.nonConfigurable,writable:!s.nonWritable})}return r}},6969(r,t,e){var n=e(2777),o=e(757);r.exports=function(r){var t=n(r,"string");return o(t)?t:t+""}},6980(r){r.exports=function(r,t){return{enumerable:!(1&r),configurable:!(2&r),writable:!(4&r),value:t}}},7040(r,t,e){var n=e(4495);r.exports=n&&!Symbol.sham&&"symbol"==typeof Symbol.iterator},7055(r,t,e){var n=e(9504),o=e(9039),i=e(2195),a=Object,s=n("".split);r.exports=o(function(){return!a("z").propertyIsEnumerable(0)})?function(r){return"String"===i(r)?s(r,""):a(r)}:a},7347(r,t,e){var n=e(3724),o=e(9565),i=e(8773),a=e(6980),s=e(5397),u=e(6969),c=e(9297),p=e(5917),f=Object.getOwnPropertyDescriptor;t.f=n?f:function(r,t){if(r=s(r),t=u(t),p)try{return f(r,t)}catch(r){}if(c(r,t))return a(!o(i.f,r,t),r[t])}},7629(r,t,e){var n=e(6395),o=e(4576),i=e(9433),a="__core-js_shared__",s=r.exports=o[a]||i(a,{});(s.versions||(s.versions=[])).push({version:"3.47.0",mode:n?"pure":"global",copyright:"© 2014-2025 Denis Pushkarev (zloirock.ru), 2025 CoreJS Company (core-js.io)",license:"https://github.com/zloirock/core-js/blob/v3.47.0/LICENSE",source:"https://github.com/zloirock/core-js"})},7740(r,t,e){var n=e(9297),o=e(5031),i=e(7347),a=e(4913);r.exports=function(r,t,e){for(var s=o(t),u=a.f,c=i.f,p=0;p<s.length;p++){var f=s[p];n(r,f)||e&&n(e,f)||u(r,f,c(t,f))}}},7750(r,t,e){var n=e(4117),o=TypeError;r.exports=function(r){if(n(r))throw new o("Can't call method on "+r);return r}},7751(r,t,e){var n=e(4576),o=e(4901);r.exports=function(r,t){return arguments.length<2?(e=n[r],o(e)?e:void 0):n[r]&&n[r][t];var e}},8014(r,t,e){var n=e(1291),o=Math.min;r.exports=function(r){var t=n(r);return t>0?o(t,9007199254740991):0}},8227(r,t,e){var n=e(4576),o=e(5745),i=e(9297),a=e(3392),s=e(4495),u=e(7040),c=n.Symbol,p=o("wks"),f=u?c.for||c:c&&c.withoutSetter||a;r.exports=function(r){return i(p,r)||(p[r]=s&&i(c,r)?c[r]:f("Symbol."+r)),p[r]}},8480(r,t,e){var n=e(1828),o=e(8727).concat("length","prototype");t.f=Object.getOwnPropertyNames||function(r){return n(r,o)}},8551(r,t,e){var n=e(34),o=String,i=TypeError;r.exports=function(r){if(n(r))return r;throw new i(o(r)+" is not an object")}},8622(r,t,e){var n=e(4576),o=e(4901),i=n.WeakMap;r.exports=o(i)&&/native code/.test(String(i))},8686(r,t,e){var n=e(3724),o=e(9039);r.exports=n&&o(function(){return 42!==Object.defineProperty(function(){},"prototype",{value:42,writable:!1}).prototype})},8727(r){r.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},8773(r,t){var e={}.propertyIsEnumerable,n=Object.getOwnPropertyDescriptor,o=n&&!e.call({1:2},1);t.f=o?function(r){var t=n(this,r);return!!t&&t.enumerable}:e},8981(r,t,e){var n=e(7750),o=Object;r.exports=function(r){return o(n(r))}},9039(r){r.exports=function(r){try{return!!r()}catch(r){return!0}}},9297(r,t,e){var n=e(9504),o=e(8981),i=n({}.hasOwnProperty);r.exports=Object.hasOwn||function(r,t){return i(o(r),t)}},9306(r,t,e){var n=e(4901),o=e(6823),i=TypeError;r.exports=function(r){if(n(r))return r;throw new i(o(r)+" is not a function")}},9433(r,t,e){var n=e(4576),o=Object.defineProperty;r.exports=function(r,t){try{o(n,r,{value:t,configurable:!0,writable:!0})}catch(e){n[r]=t}return t}},9504(r,t,e){var n=e(616),o=Function.prototype,i=o.call,a=n&&o.bind.bind(i,i);r.exports=n?a:function(r){return function(){return i.apply(r,arguments)}}},9519(r,t,e){var n,o,i=e(4576),a=e(2839),s=i.process,u=i.Deno,c=s&&s.versions||u&&u.version,p=c&&c.v8;p&&(o=(n=p.split("."))[0]>0&&n[0]<4?1:+(n[0]+n[1])),!o&&a&&(!(n=a.match(/Edge\/(\d+)/))||n[1]>=74)&&(n=a.match(/Chrome\/(\d+)/))&&(o=+n[1]),r.exports=o},9565(r,t,e){var n=e(616),o=Function.prototype.call;r.exports=n?o.bind(o):function(){return o.apply(o,arguments)}},9617(r,t,e){var n=e(5397),o=e(5610),i=e(6198),a=function(r){return function(t,e,a){var s=n(t),u=i(s);if(0===u)return!r&&-1;var c,p=o(a,u);if(r&&e!=e){for(;u>p;)if((c=s[p++])!=c)return!0}else for(;u>p;p++)if((r||p in s)&&s[p]===e)return r||p||0;return!r&&-1}};r.exports={includes:a(!0),indexOf:a(!1)}}},t={};function e(n){var o=t[n];if(void 0!==o)return o.exports;var i=t[n]={exports:{}};return r[n].call(i.exports,i,i.exports,e),i.exports}e.d=(r,t)=>{for(var n in t)e.o(t,n)&&!e.o(r,n)&&Object.defineProperty(r,n,{enumerable:!0,get:t[n]})},e.o=(r,t)=>Object.prototype.hasOwnProperty.call(r,t);var n={};e.d(n,{default:()=>a});var o=e(6298);class i extends o.A{decimalSeparatorWord="فاصلة";zeroWord="صفر";arabicTens=["عشرون","ثلاثون","أربعون","خمسون","ستون","سبعون","ثمانون","تسعون"];arabicHundreds=["","مائة","مئتان","ثلاثمائة","أربعمائة","خمسمائة","ستمائة","سبعمائة","ثمانمائة","تسعمائة"];arabicAppendedTwos=["مئتا","ألفا","مليونا","مليارا","تريليونا","كوادريليونا","كوينتليونا","سكستيليونا"];arabicTwos=["مئتان","ألفان","مليونان","ملياران","تريليونان","كوادريليونان","كوينتليونان","سكستيليونان"];arabicGroup=["مائة","ألف","مليون","مليار","تريليون","كوادريليون","كوينتليون","سكستيليون"];arabicAppendedGroup=["","ألفاً","مليوناً","ملياراً","تريليوناً","كوادريليوناً","كوينتليوناً","سكستيليوناً"];arabicPluralGroups=["","آلاف","ملايين","مليارات","تريليونات","كوادريليونات","كوينتليونات","سكستيليونات"];ones={masculine:["واحد","اثنان","ثلاثة","أربعة","خمسة","ستة","سبعة","ثمانية","تسعة","عشرة","أحد عشر","اثنا عشر","ثلاثة عشر","أربعة عشر","خمسة عشر","ستة عشر","سبعة عشر","ثمانية عشر","تسعة عشر"],feminine:["واحدة","اثنتان","ثلاث","أربع","خمس","ست","سبع","ثمان","تسع","عشر","إحدى عشرة","اثنتا عشرة","ثلاث عشرة","أربع عشرة","خمس عشرة","ست عشرة","سبع عشرة","ثماني عشرة","تسع عشرة"]};constructor({negativeWord:r="ناقص",feminine:t=!1}={}){super(),this.feminine=t,this.negativeWord=r,this.selectedOnes=this.ones[this.feminine?"feminine":"masculine"]}digitFeminineStatus(r){return this.selectedOnes[r-1]}processArabicGroup(r,t,e){const n=r%100,o=r/100,i=Math.trunc(o);let a="";if(i>0)if(0===n&&2===i)a=this.arabicTwos[0];else{const r=this.arabicHundreds[i];r&&(a=r,0!==n&&(a+=" و"))}if(n>0)if(n<20)if(2===n&&0===i&&t>0){const n=Number(e),o=Math.trunc(Math.log10(n));a=o%3==0&&e===BigInt(2*Math.pow(10,o))?2===r?this.arabicTwos[t]:this.arabicAppendedTwos[t]:this.arabicTwos[t]}else a+=1===n&&t>0?this.arabicGroup[t]:this.selectedOnes[n-1];else{const r=n%10,t=Math.trunc(n/10)-2;r>0&&(a+=this.selectedOnes[r-1],a+=" و"),a+=this.arabicTens[t]}return a}convertWholePart(r){if(0n===r)return this.zeroWord;let t=r,e=0,n="";for(;t>0n;){const o=Number(t%1000n);if(t/=1000n,o>0){const t=this.processArabicGroup(o,e,r);t&&(e>0&&(n&&(n=" و"+n),o>2)&&(n=1==o%100?this.arabicGroup[e]+" "+n:o>=3&&o<=10?this.arabicPluralGroups[e]+" "+n:(n?this.arabicAppendedGroup[e]:this.arabicGroup[e])+" "+n),n=t+" "+n)}e++}return n.replace(/\s+/g," ").trim()}}function a(r,t={}){return new i(t).convertToWords(r)}return n.default})());
2
- //# sourceMappingURL=ar.js.map
1
+ /*! n2words/ar v3.0.0 | MIT License | github.com/forzagreen/n2words */
2
+ var e,t;e=this,t=function(e){"use strict";function t(e){const t="-"===e[0];t&&(e=e.slice(1));const n=e.indexOf(".");if(-1===n)return{isNegative:t,integerPart:BigInt(e)};const i=e.slice(0,n)||"0",r=e.slice(n+1);return{isNegative:t,integerPart:BigInt(i),decimalPart:r}}function n(e){const[t,n]=e.toLowerCase().split("e"),i=parseInt(n,10),r=t.indexOf("."),o=-1===r?t:t.slice(0,r)+t.slice(r+1),s=(-1===r?t.length:r)+i;return s>=o.length?o+"0".repeat(s-o.length):s<=0?"0."+"0".repeat(-s)+o:o.slice(0,s)+"."+o.slice(s)}const i=["عشرون","ثلاثون","أربعون","خمسون","ستون","سبعون","ثمانون","تسعون"],r=["","مائة","مئتان","ثلاثمائة","أربعمائة","خمسمائة","ستمائة","سبعمائة","ثمانمائة","تسعمائة"],o=["مائة","ألف","مليون","مليار","تريليون","كوادريليون","كوينتليون","سكستيليون"],s=["","ألفاً","مليوناً","ملياراً","تريليوناً","كوادريليوناً","كوينتليوناً","سكستيليوناً"],u=["","آلاف","ملايين","مليارات","تريليونات","كوادريليونات","كوينتليونات","سكستيليونات"],c=["مئتان","ألفان","مليونان","ملياران","تريليونان","كوادريليونان","كوينتليونان","سكستيليونان"],f=["مئتا","ألفا","مليونا","مليارا","تريليونا","كوادريليونا","كوينتليونا","سكستيليونا"],l=["واحد","اثنان","ثلاثة","أربعة","خمسة","ستة","سبعة","ثمانية","تسعة","عشرة","أحد عشر","اثنا عشر","ثلاثة عشر","أربعة عشر","خمسة عشر","ستة عشر","سبعة عشر","ثمانية عشر","تسعة عشر"],a=["واحدة","اثنتان","ثلاث","أربع","خمس","ست","سبع","ثمان","تسع","عشر","إحدى عشرة","اثنتا عشرة","ثلاث عشرة","أربع عشرة","خمس عشرة","ست عشرة","سبع عشرة","ثماني عشرة","تسع عشرة"];function g(e,t,n,s){const u=e%100,l=Math.trunc(e/100);let a="";if(l>0)if(0===u&&2===l)a=c[0];else{const e=r[l];e&&(a=e,0!==u&&(a+=" و"))}if(u>0)if(u<20)if(2===u&&0===l&&t>0){const i=Number(n),r=Math.trunc(Math.log10(i));r%3==0&&n===BigInt(2*Math.pow(10,r))?a+=2===e?c[t]:f[t]:a+=c[t]}else a+=1===u&&t>0?o[t]:s[u-1];else{const e=u%10,t=Math.trunc(u/10)-2;e>0&&(a+=s[e-1]+" و"),a+=i[t]}return a}function p(e,t){if(0n===e)return"صفر";const n="feminine"===(t.gender||"masculine")?a:l;let i=e,r=0;const c=[];for(;i>0n;){const t=Number(i%1000n);if(i/=1000n,t>0){const i=g(t,r,e,n);if(i){let e=i;r>0&&t>2&&(e+=1==t%100?" "+o[r]:t>=3&&t<=10?" "+u[r]:" "+(c.length>0?s[r]:o[r])),c.unshift(e)}}r++}if(1===c.length)return c[0];let f=c[0];for(let e=1;e<c.length;e++)f+=" و"+c[e];return f}e.ar=function(e,i){i=function(e){if(void 0===e)return{};if(function(e){if(null===e||"object"!=typeof e)return!1;const t=Object.getPrototypeOf(e);return null===t||t===Object.prototype}(e))return e;throw new TypeError("Invalid options: expected plain object or undefined, got "+typeof e)}(i);const{isNegative:r,integerPart:o,decimalPart:s}=function(e){const i=typeof e;if("bigint"===i)return e<0n?{isNegative:!0,integerPart:-e}:{isNegative:!1,integerPart:e};if("number"===i){if(!Number.isFinite(e))throw new Error("Number must be finite (NaN and Infinity are not supported)");return Number.isSafeInteger(e)?e<0?{isNegative:!0,integerPart:BigInt(-e)}:{isNegative:!1,integerPart:BigInt(e)}:t(function(e){const t=e.toString();return t.includes("e")||t.includes("E")?n(t):t}(e))}if("string"===i)return t(function(e){const t=e.trim();if(0===t.length||Number.isNaN(Number(t)))throw new Error(`Invalid number format: "${e}"`);return t.includes("e")||t.includes("E")?n(t):t}(e));throw new TypeError(`Invalid value type: expected number, string, or bigint, received ${i}`)}(e),u=[];return r&&u.push(i.negativeWord||"ناقص"),u.push(p(o,i)),s&&(u.push("فاصلة"),u.push(function(e,t){const n=[];let i=0;for(;i<e.length&&"0"===e[i];)n.push("صفر"),i++;const r=e.slice(i);return r&&n.push(p(BigInt(r),t)),n.join(" ")}(s,i))),u.join(" ")}},"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).n2words=e.n2words||{});
3
+ //# sourceMappingURL=ar.js.map