n2words 3.1.0 → 5.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 (486) hide show
  1. package/CHANGELOG.md +51 -40
  2. package/LICENSE +1 -1
  3. package/README.md +64 -184
  4. package/dist/am-ET.js +2 -0
  5. package/dist/am-ET.umd.js +2 -0
  6. package/dist/am-Latn-ET.js +2 -0
  7. package/dist/am-Latn-ET.umd.js +2 -0
  8. package/dist/ar-SA.js +2 -0
  9. package/dist/ar-SA.umd.js +2 -0
  10. package/dist/az-AZ.js +2 -0
  11. package/dist/az-AZ.umd.js +2 -0
  12. package/dist/bn-BD.js +2 -0
  13. package/dist/bn-BD.umd.js +2 -0
  14. package/dist/cs-CZ.js +2 -0
  15. package/dist/cs-CZ.umd.js +2 -0
  16. package/dist/da-DK.js +2 -0
  17. package/dist/da-DK.umd.js +2 -0
  18. package/dist/de-DE.js +2 -0
  19. package/dist/de-DE.umd.js +2 -0
  20. package/dist/el-GR.js +2 -0
  21. package/dist/el-GR.umd.js +2 -0
  22. package/dist/en-AU.js +2 -0
  23. package/dist/en-AU.umd.js +2 -0
  24. package/dist/en-BD.js +2 -0
  25. package/dist/en-BD.umd.js +2 -0
  26. package/dist/en-CA.js +2 -0
  27. package/dist/en-CA.umd.js +2 -0
  28. package/dist/en-GB.js +2 -0
  29. package/dist/en-GB.umd.js +2 -0
  30. package/dist/en-GH.js +2 -0
  31. package/dist/en-GH.umd.js +2 -0
  32. package/dist/en-IE.js +2 -0
  33. package/dist/en-IE.umd.js +2 -0
  34. package/dist/en-IN.js +2 -0
  35. package/dist/en-IN.umd.js +2 -0
  36. package/dist/en-KE.js +2 -0
  37. package/dist/en-KE.umd.js +2 -0
  38. package/dist/en-MY.js +2 -0
  39. package/dist/en-MY.umd.js +2 -0
  40. package/dist/en-NG.js +2 -0
  41. package/dist/en-NG.umd.js +2 -0
  42. package/dist/en-NZ.js +2 -0
  43. package/dist/en-NZ.umd.js +2 -0
  44. package/dist/en-PH.js +2 -0
  45. package/dist/en-PH.umd.js +2 -0
  46. package/dist/en-PK.js +2 -0
  47. package/dist/en-PK.umd.js +2 -0
  48. package/dist/en-SG.js +2 -0
  49. package/dist/en-SG.umd.js +2 -0
  50. package/dist/en-US.js +2 -0
  51. package/dist/en-US.umd.js +2 -0
  52. package/dist/en-ZA.js +2 -0
  53. package/dist/en-ZA.umd.js +2 -0
  54. package/dist/es-ES.js +2 -0
  55. package/dist/es-ES.umd.js +2 -0
  56. package/dist/es-MX.js +2 -0
  57. package/dist/es-MX.umd.js +2 -0
  58. package/dist/es-US.js +2 -0
  59. package/dist/es-US.umd.js +2 -0
  60. package/dist/fa-IR.js +2 -0
  61. package/dist/fa-IR.umd.js +2 -0
  62. package/dist/fi-FI.js +2 -0
  63. package/dist/fi-FI.umd.js +2 -0
  64. package/dist/fil-PH.js +2 -0
  65. package/dist/fil-PH.umd.js +2 -0
  66. package/dist/fr-BE.js +2 -0
  67. package/dist/fr-BE.umd.js +2 -0
  68. package/dist/fr-FR.js +2 -0
  69. package/dist/fr-FR.umd.js +2 -0
  70. package/dist/gu-IN.js +2 -0
  71. package/dist/gu-IN.umd.js +2 -0
  72. package/dist/ha-NG.js +2 -0
  73. package/dist/ha-NG.umd.js +2 -0
  74. package/dist/hbo-IL.js +2 -0
  75. package/dist/hbo-IL.umd.js +2 -0
  76. package/dist/he-IL.js +2 -0
  77. package/dist/he-IL.umd.js +2 -0
  78. package/dist/hi-IN.js +2 -0
  79. package/dist/hi-IN.umd.js +2 -0
  80. package/dist/hr-HR.js +2 -0
  81. package/dist/hr-HR.umd.js +2 -0
  82. package/dist/hu-HU.js +2 -0
  83. package/dist/hu-HU.umd.js +2 -0
  84. package/dist/id-ID.js +2 -0
  85. package/dist/id-ID.umd.js +2 -0
  86. package/dist/it-IT.js +2 -0
  87. package/dist/it-IT.umd.js +2 -0
  88. package/dist/ja-JP.js +2 -0
  89. package/dist/ja-JP.umd.js +2 -0
  90. package/dist/ka-GE.js +2 -0
  91. package/dist/ka-GE.umd.js +2 -0
  92. package/dist/kn-IN.js +2 -0
  93. package/dist/kn-IN.umd.js +2 -0
  94. package/dist/ko-KR.js +2 -0
  95. package/dist/ko-KR.umd.js +2 -0
  96. package/dist/lt-LT.js +2 -0
  97. package/dist/lt-LT.umd.js +2 -0
  98. package/dist/lv-LV.js +2 -0
  99. package/dist/lv-LV.umd.js +2 -0
  100. package/dist/mr-IN.js +2 -0
  101. package/dist/mr-IN.umd.js +2 -0
  102. package/dist/ms-MY.js +2 -0
  103. package/dist/ms-MY.umd.js +2 -0
  104. package/dist/nb-NO.js +2 -0
  105. package/dist/nb-NO.umd.js +2 -0
  106. package/dist/nl-NL.js +2 -0
  107. package/dist/nl-NL.umd.js +2 -0
  108. package/dist/pa-IN.js +2 -0
  109. package/dist/pa-IN.umd.js +2 -0
  110. package/dist/pl-PL.js +2 -0
  111. package/dist/pl-PL.umd.js +2 -0
  112. package/dist/pt-BR.js +2 -0
  113. package/dist/pt-BR.umd.js +2 -0
  114. package/dist/pt-PT.js +2 -0
  115. package/dist/pt-PT.umd.js +2 -0
  116. package/dist/ro-RO.js +2 -0
  117. package/dist/ro-RO.umd.js +2 -0
  118. package/dist/ru-RU.js +2 -0
  119. package/dist/ru-RU.umd.js +2 -0
  120. package/dist/sr-Cyrl-RS.js +2 -0
  121. package/dist/sr-Cyrl-RS.umd.js +2 -0
  122. package/dist/sr-Latn-RS.js +2 -0
  123. package/dist/sr-Latn-RS.umd.js +2 -0
  124. package/dist/sv-SE.js +2 -0
  125. package/dist/sv-SE.umd.js +2 -0
  126. package/dist/sw-KE.js +2 -0
  127. package/dist/sw-KE.umd.js +2 -0
  128. package/dist/ta-IN.js +2 -0
  129. package/dist/ta-IN.umd.js +2 -0
  130. package/dist/te-IN.js +2 -0
  131. package/dist/te-IN.umd.js +2 -0
  132. package/dist/th-TH.js +2 -0
  133. package/dist/th-TH.umd.js +2 -0
  134. package/dist/tr-TR.js +2 -0
  135. package/dist/tr-TR.umd.js +2 -0
  136. package/dist/uk-UA.js +2 -0
  137. package/dist/uk-UA.umd.js +2 -0
  138. package/dist/ur-PK.js +2 -0
  139. package/dist/ur-PK.umd.js +2 -0
  140. package/dist/vi-VN.js +2 -0
  141. package/dist/vi-VN.umd.js +2 -0
  142. package/dist/yo-NG.js +2 -0
  143. package/dist/yo-NG.umd.js +2 -0
  144. package/dist/zh-Hans-CN.js +2 -0
  145. package/dist/zh-Hans-CN.umd.js +2 -0
  146. package/dist/zh-Hant-TW.js +2 -0
  147. package/dist/zh-Hant-TW.umd.js +2 -0
  148. package/package.json +61 -88
  149. package/src/am-ET.d.ts +40 -0
  150. package/src/am-ET.js +269 -0
  151. package/src/am-Latn-ET.d.ts +35 -0
  152. package/src/am-Latn-ET.js +264 -0
  153. package/src/ar-SA.d.ts +49 -0
  154. package/{lib/languages/ar.js → src/ar-SA.js} +177 -15
  155. package/src/az-AZ.d.ts +37 -0
  156. package/src/az-AZ.js +312 -0
  157. package/src/bn-BD.d.ts +36 -0
  158. package/{lib/languages/bn.js → src/bn-BD.js} +110 -6
  159. package/src/cs-CZ.d.ts +49 -0
  160. package/{lib/languages/cs.js → src/cs-CZ.js} +240 -14
  161. package/src/da-DK.d.ts +44 -0
  162. package/{lib/languages/da.js → src/da-DK.js} +131 -11
  163. package/src/de-DE.d.ts +57 -0
  164. package/src/de-DE.js +603 -0
  165. package/src/el-GR.d.ts +40 -0
  166. package/src/el-GR.js +418 -0
  167. package/src/en-AU.d.ts +47 -0
  168. package/src/en-AU.js +423 -0
  169. package/src/en-BD.d.ts +49 -0
  170. package/src/en-BD.js +415 -0
  171. package/src/en-CA.d.ts +63 -0
  172. package/src/en-CA.js +518 -0
  173. package/src/en-GB.d.ts +56 -0
  174. package/src/en-GB.js +469 -0
  175. package/src/en-GH.d.ts +11 -0
  176. package/src/en-GH.js +345 -0
  177. package/src/en-IE.d.ts +56 -0
  178. package/src/en-IE.js +479 -0
  179. package/src/en-IN.d.ts +49 -0
  180. package/src/en-IN.js +415 -0
  181. package/src/en-KE.d.ts +11 -0
  182. package/src/en-KE.js +345 -0
  183. package/src/en-MY.d.ts +11 -0
  184. package/src/en-MY.js +347 -0
  185. package/src/en-NG.d.ts +56 -0
  186. package/src/en-NG.js +479 -0
  187. package/src/en-NZ.d.ts +11 -0
  188. package/{lib/languages/en.js → src/en-NZ.js} +164 -31
  189. package/src/en-PH.d.ts +11 -0
  190. package/src/en-PH.js +345 -0
  191. package/src/en-PK.d.ts +49 -0
  192. package/src/en-PK.js +415 -0
  193. package/src/en-SG.d.ts +11 -0
  194. package/src/en-SG.js +345 -0
  195. package/src/en-US.d.ts +63 -0
  196. package/src/en-US.js +516 -0
  197. package/src/en-ZA.d.ts +56 -0
  198. package/src/en-ZA.js +478 -0
  199. package/src/es-ES.d.ts +65 -0
  200. package/src/es-ES.js +541 -0
  201. package/src/es-MX.d.ts +58 -0
  202. package/{lib/languages/es.js → src/es-MX.js} +228 -18
  203. package/src/es-US.d.ts +58 -0
  204. package/src/es-US.js +446 -0
  205. package/src/fa-IR.d.ts +38 -0
  206. package/src/fa-IR.js +246 -0
  207. package/src/fi-FI.d.ts +46 -0
  208. package/{lib/languages/fi.js → src/fi-FI.js} +152 -11
  209. package/src/fil-PH.d.ts +37 -0
  210. package/{lib/languages/fil.js → src/fil-PH.js} +144 -8
  211. package/src/fr-BE.d.ts +49 -0
  212. package/{lib/languages → src}/fr-BE.js +175 -13
  213. package/src/fr-FR.d.ts +63 -0
  214. package/{lib/languages/fr.js → src/fr-FR.js} +182 -16
  215. package/src/gu-IN.d.ts +35 -0
  216. package/{lib/languages/gu.js → src/gu-IN.js} +115 -6
  217. package/src/ha-NG.d.ts +37 -0
  218. package/{lib/languages/ha.js → src/ha-NG.js} +107 -8
  219. package/src/hbo-IL.d.ts +39 -0
  220. package/{lib/languages/hbo.js → src/hbo-IL.js} +211 -19
  221. package/src/he-IL.d.ts +37 -0
  222. package/src/he-IL.js +537 -0
  223. package/src/hi-IN.d.ts +36 -0
  224. package/{lib/languages/hi.js → src/hi-IN.js} +116 -6
  225. package/src/hr-HR.d.ts +42 -0
  226. package/src/hr-HR.js +463 -0
  227. package/src/hu-HU.d.ts +38 -0
  228. package/{lib/languages/hu.js → src/hu-HU.js} +164 -6
  229. package/src/id-ID.d.ts +38 -0
  230. package/{lib/languages/id.js → src/id-ID.js} +99 -8
  231. package/src/it-IT.d.ts +59 -0
  232. package/{lib/languages/it.js → src/it-IT.js} +179 -15
  233. package/src/ja-JP.d.ts +49 -0
  234. package/{lib/languages/ja.js → src/ja-JP.js} +111 -12
  235. package/src/ka-GE.d.ts +44 -0
  236. package/{lib/languages/ka.js → src/ka-GE.js} +113 -11
  237. package/src/kn-IN.d.ts +35 -0
  238. package/{lib/languages/kn.js → src/kn-IN.js} +115 -6
  239. package/src/ko-KR.d.ts +45 -0
  240. package/{lib/languages/ko.js → src/ko-KR.js} +94 -12
  241. package/src/lt-LT.d.ts +49 -0
  242. package/src/lt-LT.js +543 -0
  243. package/src/lv-LV.d.ts +49 -0
  244. package/src/lv-LV.js +595 -0
  245. package/src/mr-IN.d.ts +36 -0
  246. package/{lib/languages/mr.js → src/mr-IN.js} +116 -6
  247. package/src/ms-MY.d.ts +37 -0
  248. package/{lib/languages/ms.js → src/ms-MY.js} +111 -8
  249. package/src/nb-NO.d.ts +44 -0
  250. package/{lib/languages/nb.js → src/nb-NO.js} +153 -11
  251. package/src/nl-NL.d.ts +54 -0
  252. package/{lib/languages/nl.js → src/nl-NL.js} +260 -18
  253. package/src/pa-IN.d.ts +36 -0
  254. package/{lib/languages/pa.js → src/pa-IN.js} +116 -6
  255. package/src/pl-PL.d.ts +55 -0
  256. package/src/pl-PL.js +585 -0
  257. package/src/pt-BR.d.ts +31 -0
  258. package/src/pt-BR.js +534 -0
  259. package/src/pt-PT.d.ts +45 -0
  260. package/{lib/languages/pt.js → src/pt-PT.js} +234 -12
  261. package/src/ro-RO.d.ts +44 -0
  262. package/{lib/languages/ro.js → src/ro-RO.js} +212 -18
  263. package/src/ru-RU.d.ts +50 -0
  264. package/src/ru-RU.js +535 -0
  265. package/src/sr-Cyrl-RS.d.ts +49 -0
  266. package/src/sr-Cyrl-RS.js +503 -0
  267. package/src/sr-Latn-RS.d.ts +49 -0
  268. package/src/sr-Latn-RS.js +503 -0
  269. package/src/sv-SE.d.ts +44 -0
  270. package/{lib/languages/sv.js → src/sv-SE.js} +136 -11
  271. package/src/sw-KE.d.ts +37 -0
  272. package/{lib/languages/sw.js → src/sw-KE.js} +117 -6
  273. package/src/ta-IN.d.ts +35 -0
  274. package/{lib/languages/ta.js → src/ta-IN.js} +109 -6
  275. package/src/te-IN.d.ts +35 -0
  276. package/{lib/languages/te.js → src/te-IN.js} +115 -6
  277. package/src/th-TH.d.ts +38 -0
  278. package/{lib/languages/th.js → src/th-TH.js} +99 -6
  279. package/src/tr-TR.d.ts +48 -0
  280. package/{lib/languages/tr.js → src/tr-TR.js} +168 -23
  281. package/src/uk-UA.d.ts +42 -0
  282. package/src/uk-UA.js +463 -0
  283. package/src/ur-PK.d.ts +36 -0
  284. package/{lib/languages/ur.js → src/ur-PK.js} +116 -6
  285. package/src/utils/expand-scientific.d.ts +32 -0
  286. package/src/utils/expand-scientific.js +65 -0
  287. package/src/utils/parse-cardinal.d.ts +14 -0
  288. package/{lib/utils/parse-numeric.js → src/utils/parse-cardinal.js} +14 -44
  289. package/src/utils/parse-currency.d.ts +14 -0
  290. package/src/utils/parse-currency.js +91 -0
  291. package/src/utils/parse-ordinal.d.ts +10 -0
  292. package/src/utils/parse-ordinal.js +103 -0
  293. package/src/vi-VN.d.ts +48 -0
  294. package/{lib/languages/vi.js → src/vi-VN.js} +102 -11
  295. package/src/yo-NG.d.ts +37 -0
  296. package/{lib/languages/yo.js → src/yo-NG.js} +109 -9
  297. package/src/zh-Hans-CN.d.ts +48 -0
  298. package/{lib/languages/zh-Hans.js → src/zh-Hans-CN.js} +140 -8
  299. package/src/zh-Hant-TW.d.ts +50 -0
  300. package/{lib/languages/zh-Hant.js → src/zh-Hant-TW.js} +139 -8
  301. package/dist/languages/am-Latn.js +0 -3
  302. package/dist/languages/am-Latn.js.map +0 -1
  303. package/dist/languages/am.js +0 -3
  304. package/dist/languages/am.js.map +0 -1
  305. package/dist/languages/ar.js +0 -3
  306. package/dist/languages/ar.js.map +0 -1
  307. package/dist/languages/az.js +0 -3
  308. package/dist/languages/az.js.map +0 -1
  309. package/dist/languages/bn.js +0 -3
  310. package/dist/languages/bn.js.map +0 -1
  311. package/dist/languages/cs.js +0 -3
  312. package/dist/languages/cs.js.map +0 -1
  313. package/dist/languages/da.js +0 -3
  314. package/dist/languages/da.js.map +0 -1
  315. package/dist/languages/de.js +0 -3
  316. package/dist/languages/de.js.map +0 -1
  317. package/dist/languages/el.js +0 -3
  318. package/dist/languages/el.js.map +0 -1
  319. package/dist/languages/en.js +0 -3
  320. package/dist/languages/en.js.map +0 -1
  321. package/dist/languages/es.js +0 -3
  322. package/dist/languages/es.js.map +0 -1
  323. package/dist/languages/fa.js +0 -3
  324. package/dist/languages/fa.js.map +0 -1
  325. package/dist/languages/fi.js +0 -3
  326. package/dist/languages/fi.js.map +0 -1
  327. package/dist/languages/fil.js +0 -3
  328. package/dist/languages/fil.js.map +0 -1
  329. package/dist/languages/fr-BE.js +0 -3
  330. package/dist/languages/fr-BE.js.map +0 -1
  331. package/dist/languages/fr.js +0 -3
  332. package/dist/languages/fr.js.map +0 -1
  333. package/dist/languages/gu.js +0 -3
  334. package/dist/languages/gu.js.map +0 -1
  335. package/dist/languages/ha.js +0 -3
  336. package/dist/languages/ha.js.map +0 -1
  337. package/dist/languages/hbo.js +0 -3
  338. package/dist/languages/hbo.js.map +0 -1
  339. package/dist/languages/he.js +0 -3
  340. package/dist/languages/he.js.map +0 -1
  341. package/dist/languages/hi.js +0 -3
  342. package/dist/languages/hi.js.map +0 -1
  343. package/dist/languages/hr.js +0 -3
  344. package/dist/languages/hr.js.map +0 -1
  345. package/dist/languages/hu.js +0 -3
  346. package/dist/languages/hu.js.map +0 -1
  347. package/dist/languages/id.js +0 -3
  348. package/dist/languages/id.js.map +0 -1
  349. package/dist/languages/it.js +0 -3
  350. package/dist/languages/it.js.map +0 -1
  351. package/dist/languages/ja.js +0 -3
  352. package/dist/languages/ja.js.map +0 -1
  353. package/dist/languages/ka.js +0 -3
  354. package/dist/languages/ka.js.map +0 -1
  355. package/dist/languages/kn.js +0 -3
  356. package/dist/languages/kn.js.map +0 -1
  357. package/dist/languages/ko.js +0 -3
  358. package/dist/languages/ko.js.map +0 -1
  359. package/dist/languages/lt.js +0 -3
  360. package/dist/languages/lt.js.map +0 -1
  361. package/dist/languages/lv.js +0 -3
  362. package/dist/languages/lv.js.map +0 -1
  363. package/dist/languages/mr.js +0 -3
  364. package/dist/languages/mr.js.map +0 -1
  365. package/dist/languages/ms.js +0 -3
  366. package/dist/languages/ms.js.map +0 -1
  367. package/dist/languages/nb.js +0 -3
  368. package/dist/languages/nb.js.map +0 -1
  369. package/dist/languages/nl.js +0 -3
  370. package/dist/languages/nl.js.map +0 -1
  371. package/dist/languages/pa.js +0 -3
  372. package/dist/languages/pa.js.map +0 -1
  373. package/dist/languages/pl.js +0 -3
  374. package/dist/languages/pl.js.map +0 -1
  375. package/dist/languages/pt.js +0 -3
  376. package/dist/languages/pt.js.map +0 -1
  377. package/dist/languages/ro.js +0 -3
  378. package/dist/languages/ro.js.map +0 -1
  379. package/dist/languages/ru.js +0 -3
  380. package/dist/languages/ru.js.map +0 -1
  381. package/dist/languages/sr-Cyrl.js +0 -3
  382. package/dist/languages/sr-Cyrl.js.map +0 -1
  383. package/dist/languages/sr-Latn.js +0 -3
  384. package/dist/languages/sr-Latn.js.map +0 -1
  385. package/dist/languages/sv.js +0 -3
  386. package/dist/languages/sv.js.map +0 -1
  387. package/dist/languages/sw.js +0 -3
  388. package/dist/languages/sw.js.map +0 -1
  389. package/dist/languages/ta.js +0 -3
  390. package/dist/languages/ta.js.map +0 -1
  391. package/dist/languages/te.js +0 -3
  392. package/dist/languages/te.js.map +0 -1
  393. package/dist/languages/th.js +0 -3
  394. package/dist/languages/th.js.map +0 -1
  395. package/dist/languages/tr.js +0 -3
  396. package/dist/languages/tr.js.map +0 -1
  397. package/dist/languages/uk.js +0 -3
  398. package/dist/languages/uk.js.map +0 -1
  399. package/dist/languages/ur.js +0 -3
  400. package/dist/languages/ur.js.map +0 -1
  401. package/dist/languages/vi.js +0 -3
  402. package/dist/languages/vi.js.map +0 -1
  403. package/dist/languages/yo.js +0 -3
  404. package/dist/languages/yo.js.map +0 -1
  405. package/dist/languages/zh-Hans.js +0 -3
  406. package/dist/languages/zh-Hans.js.map +0 -1
  407. package/dist/languages/zh-Hant.js +0 -3
  408. package/dist/languages/zh-Hant.js.map +0 -1
  409. package/dist/n2words.js +0 -3
  410. package/dist/n2words.js.map +0 -1
  411. package/lib/languages/am-Latn.d.ts +0 -7
  412. package/lib/languages/am-Latn.js +0 -159
  413. package/lib/languages/am.d.ts +0 -7
  414. package/lib/languages/am.js +0 -159
  415. package/lib/languages/ar.d.ts +0 -17
  416. package/lib/languages/az.d.ts +0 -7
  417. package/lib/languages/az.js +0 -171
  418. package/lib/languages/bn.d.ts +0 -7
  419. package/lib/languages/cs.d.ts +0 -18
  420. package/lib/languages/da.d.ts +0 -14
  421. package/lib/languages/de.d.ts +0 -17
  422. package/lib/languages/de.js +0 -320
  423. package/lib/languages/el.d.ts +0 -14
  424. package/lib/languages/el.js +0 -236
  425. package/lib/languages/en.d.ts +0 -17
  426. package/lib/languages/es.d.ts +0 -21
  427. package/lib/languages/fa.d.ts +0 -7
  428. package/lib/languages/fa.js +0 -134
  429. package/lib/languages/fi.d.ts +0 -14
  430. package/lib/languages/fil.d.ts +0 -7
  431. package/lib/languages/fr-BE.d.ts +0 -11
  432. package/lib/languages/fr.d.ts +0 -21
  433. package/lib/languages/gu.d.ts +0 -7
  434. package/lib/languages/ha.d.ts +0 -7
  435. package/lib/languages/hbo.d.ts +0 -13
  436. package/lib/languages/he.d.ts +0 -13
  437. package/lib/languages/he.js +0 -265
  438. package/lib/languages/hi.d.ts +0 -7
  439. package/lib/languages/hr.d.ts +0 -11
  440. package/lib/languages/hr.js +0 -224
  441. package/lib/languages/hu.d.ts +0 -7
  442. package/lib/languages/id.d.ts +0 -7
  443. package/lib/languages/it.d.ts +0 -19
  444. package/lib/languages/ja.d.ts +0 -17
  445. package/lib/languages/ka.d.ts +0 -17
  446. package/lib/languages/kn.d.ts +0 -7
  447. package/lib/languages/ko.d.ts +0 -14
  448. package/lib/languages/lt.d.ts +0 -18
  449. package/lib/languages/lt.js +0 -301
  450. package/lib/languages/lv.d.ts +0 -18
  451. package/lib/languages/lv.js +0 -312
  452. package/lib/languages/mr.d.ts +0 -7
  453. package/lib/languages/ms.d.ts +0 -7
  454. package/lib/languages/nb.d.ts +0 -14
  455. package/lib/languages/nl.d.ts +0 -26
  456. package/lib/languages/pa.d.ts +0 -7
  457. package/lib/languages/pl.d.ts +0 -22
  458. package/lib/languages/pl.js +0 -317
  459. package/lib/languages/pt.d.ts +0 -17
  460. package/lib/languages/ro.d.ts +0 -18
  461. package/lib/languages/ru.d.ts +0 -11
  462. package/lib/languages/ru.js +0 -245
  463. package/lib/languages/sr-Cyrl.d.ts +0 -11
  464. package/lib/languages/sr-Cyrl.js +0 -221
  465. package/lib/languages/sr-Latn.d.ts +0 -11
  466. package/lib/languages/sr-Latn.js +0 -221
  467. package/lib/languages/sv.d.ts +0 -14
  468. package/lib/languages/sw.d.ts +0 -7
  469. package/lib/languages/ta.d.ts +0 -7
  470. package/lib/languages/te.d.ts +0 -7
  471. package/lib/languages/th.d.ts +0 -7
  472. package/lib/languages/tr.d.ts +0 -18
  473. package/lib/languages/uk.d.ts +0 -11
  474. package/lib/languages/uk.js +0 -224
  475. package/lib/languages/ur.d.ts +0 -7
  476. package/lib/languages/vi.d.ts +0 -17
  477. package/lib/languages/yo.d.ts +0 -7
  478. package/lib/languages/zh-Hans.d.ts +0 -11
  479. package/lib/languages/zh-Hant.d.ts +0 -11
  480. package/lib/n2words.d.ts +0 -55
  481. package/lib/n2words.js +0 -126
  482. package/lib/utils/parse-numeric.d.ts +0 -17
  483. /package/{lib → src}/utils/is-plain-object.d.ts +0 -0
  484. /package/{lib → src}/utils/is-plain-object.js +0 -0
  485. /package/{lib → src}/utils/validate-options.d.ts +0 -0
  486. /package/{lib → src}/utils/validate-options.js +0 -0
@@ -1,3 +0,0 @@
1
- /*! n2words/ro v3.1.0 | MIT License | github.com/forzagreen/n2words */
2
- var e,n;e=this,n=function(e){"use strict";function n(e){const n="-"===e[0];n&&(e=e.slice(1));const i=e.indexOf(".");if(-1===i)return{isNegative:n,integerPart:BigInt(e)};const t=e.slice(0,i)||"0",r=e.slice(i+1);return{isNegative:n,integerPart:BigInt(t),decimalPart:r}}function i(e){const[n,i]=e.toLowerCase().split("e"),t=parseInt(i,10),r=n.indexOf("."),u=-1===r?n:n.slice(0,r)+n.slice(r+1),o=(-1===r?n.length:r)+t;return o>=u.length?u+"0".repeat(o-u.length):o<=0?"0."+"0".repeat(-o)+u:u.slice(0,o)+"."+u.slice(o)}const t=["","unu","doi","trei","patru","cinci","șase","șapte","opt","nouă"],r=["","una","două","trei","patru","cinci","șase","șapte","opt","nouă"],u=["zece","unsprezece","douăsprezece","treisprezece","paisprezece","cincisprezece","șaisprezece","șaptesprezece","optsprezece","nouăsprezece"],o=["zece","unsprezece","doisprezece","treisprezece","paisprezece","cincisprezece","șaisprezece","șaptesprezece","optsprezece","nouăsprezece"],s=["","","douăzeci","treizeci","patruzeci","cincizeci","șaizeci","șaptezeci","optzeci","nouăzeci"],c=["","o sută","două sute","trei sute","patru sute","cinci sute","șase sute","șapte sute","opt sute","nouă sute"],l="zero",a=[{singular:"mie",plural:"mii",article:"o",feminine:!0,needsDe:!0},{singular:"milion",plural:"milioane",article:"un",feminine:!1,needsDe:!0},{singular:"miliard",plural:"miliarde",article:"un",feminine:!1,needsDe:!0},{singular:"trilion",plural:"trilioane",article:"un",feminine:!1,needsDe:!0},{singular:"cvadrilion",plural:"cvadrilioane",article:"un",feminine:!1,needsDe:!0},{singular:"cvintilion",plural:"cvintilioane",article:"un",feminine:!1,needsDe:!0},{singular:"sextilion",plural:"sextilioane",article:"un",feminine:!1,needsDe:!0},{singular:"septilion",plural:"septilioane",article:"un",feminine:!1,needsDe:!0},{singular:"octilion",plural:"octilioane",article:"un",feminine:!1,needsDe:!0}];function p(e,n=!1,i=!1){if(0===e)return"";if(e<10)return n?r[e]:t[e];if(e<20)return i?o[e-10]:u[e-10];const c=Math.floor(e/10),l=e%10;return 0===l?s[c]:s[c]+" și "+(n?r[l]:t[l])}function f(e,n=!1,i=!1){if(0===e)return"";if(e<100)return p(e,n,i);const t=Math.floor(e/100),r=e%100,u=c[t];return 0===r?u:u+" "+p(r,n,i)}function d(e,n){const i=a[n-1];return i?1===e?i.article+" "+i.singular:21===e&&i.needsDe?"douăzeci și una de "+i.plural:f(e,!0)+(i.needsDe&&e>=20?" de ":" ")+i.plural:f(e,!0)}function g(e,n={}){if(0n===e)return l;if(e<1000n){const i="feminine"===n.gender;return f(Number(e),i)}return function(e,n){const i=[];let t=e;for(;t>0n;)i.push(Number(t%1000n)),t/=1000n;let r="";for(let e=i.length-1;e>=0;e--){const t=i[e];if(0===t)continue;let u;u=0===e?f(t,"feminine"===n.gender):d(t,e),r&&u?r+=" "+u:u&&(r=u)}return r}(e,n)}e.ro=function(e,t){t=function(e){if(void 0===e)return{};if(function(e){if(null===e||"object"!=typeof e)return!1;const n=Object.getPrototypeOf(e);return null===n||n===Object.prototype}(e))return e;throw new TypeError("Invalid options: expected plain object or undefined, got "+typeof e)}(t);const{isNegative:r,integerPart:u,decimalPart:o}=function(e){const t=typeof e;if("bigint"===t)return e<0n?{isNegative:!0,integerPart:-e}:{isNegative:!1,integerPart:e};if("number"===t){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)}:n(function(e){const n=e.toString();return n.includes("e")||n.includes("E")?i(n):n}(e))}if("string"===t)return n(function(e){const n=e.trim();if(0===n.length||Number.isNaN(Number(n)))throw new Error(`Invalid number format: "${e}"`);return n.includes("e")||n.includes("E")?i(n):n}(e));throw new TypeError(`Invalid value type: expected number, string, or bigint, received ${t}`)}(e);let s="";return r&&(s="minus "),s+=g(u,t),o&&(s+=" virgulă "+function(e){let n="",i=0;for(;i<e.length&&"0"===e[i];)n&&(n+=" "),n+=l,i++;const t=e.slice(i);if(t){n&&(n+=" ");const e=BigInt(t);n+=e<1000n?f(Number(e),!1,!0):g(e,{gender:"masculine"})}return n}(o)),s}},"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).n2words=e.n2words||{});
3
- //# sourceMappingURL=ro.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ro.js","sources":["../../lib/utils/parse-numeric.js","../../lib/languages/ro.js","../../lib/utils/validate-options.js","../../lib/utils/is-plain-object.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 * Romanian language converter - Functional Implementation\n *\n * A performance-optimized number-to-words converter using precomputed lookup tables.\n *\n * Key features:\n * - Gender agreement (unu/una, doi/două)\n * - \"De\" preposition insertion for groups >= 20\n * - Complex scale word handling (mie/mii, milion/milioane)\n * - Feminine units for thousands\n */\n\nimport { parseNumericValue } from '../utils/parse-numeric.js'\nimport { validateOptions } from '../utils/validate-options.js'\n\n// ============================================================================\n// Vocabulary (module-level constants)\n// ============================================================================\n\nconst ONES_MASC = ['', 'unu', 'doi', 'trei', 'patru', 'cinci', 'șase', 'șapte', 'opt', 'nouă']\nconst ONES_FEM = ['', 'una', 'două', 'trei', 'patru', 'cinci', 'șase', 'șapte', 'opt', 'nouă']\n\nconst TEENS = ['zece', 'unsprezece', 'douăsprezece', 'treisprezece', 'paisprezece', 'cincisprezece', 'șaisprezece', 'șaptesprezece', 'optsprezece', 'nouăsprezece']\nconst TEENS_MASC = ['zece', 'unsprezece', 'doisprezece', 'treisprezece', 'paisprezece', 'cincisprezece', 'șaisprezece', 'șaptesprezece', 'optsprezece', 'nouăsprezece']\n\nconst TWENTIES = ['', '', 'douăzeci', 'treizeci', 'patruzeci', 'cincizeci', 'șaizeci', 'șaptezeci', 'optzeci', 'nouăzeci']\n\nconst HUNDREDS = ['', 'o sută', 'două sute', 'trei sute', 'patru sute', 'cinci sute', 'șase sute', 'șapte sute', 'opt sute', 'nouă sute']\n\nconst ZERO = 'zero'\nconst NEGATIVE = 'minus'\nconst DECIMAL_SEP = 'virgulă'\n\n// Scale metadata: [singular, plural, article, feminine, needsDe]\n// - singular: form for 1\n// - plural: form for 2+\n// - article: 'o' for feminine, 'un' for masculine\n// - feminine: whether units should be feminine\n// - needsDe: whether \"de\" is inserted for segment >= 20\nconst SCALE_META = [\n { singular: 'mie', plural: 'mii', article: 'o', feminine: true, needsDe: true },\n { singular: 'milion', plural: 'milioane', article: 'un', feminine: false, needsDe: true },\n { singular: 'miliard', plural: 'miliarde', article: 'un', feminine: false, needsDe: true },\n { singular: 'trilion', plural: 'trilioane', article: 'un', feminine: false, needsDe: true },\n { singular: 'cvadrilion', plural: 'cvadrilioane', article: 'un', feminine: false, needsDe: true },\n { singular: 'cvintilion', plural: 'cvintilioane', article: 'un', feminine: false, needsDe: true },\n { singular: 'sextilion', plural: 'sextilioane', article: 'un', feminine: false, needsDe: true },\n { singular: 'septilion', plural: 'septilioane', article: 'un', feminine: false, needsDe: true },\n { singular: 'octilion', plural: 'octilioane', article: 'un', feminine: false, needsDe: true }\n]\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Spells number under 100.\n */\nfunction spellUnder100 (n, feminine = false, masculineTeens = false) {\n if (n === 0) return ''\n if (n < 10) {\n return feminine ? ONES_FEM[n] : ONES_MASC[n]\n }\n if (n < 20) {\n return masculineTeens ? TEENS_MASC[n - 10] : TEENS[n - 10]\n }\n const t = Math.floor(n / 10)\n const u = n % 10\n if (u === 0) {\n return TWENTIES[t]\n }\n const onesWord = feminine ? ONES_FEM[u] : ONES_MASC[u]\n return TWENTIES[t] + ' și ' + onesWord\n}\n\n/**\n * Spells number under 1000.\n */\nfunction spellUnder1000 (n, feminine = false, masculineTeens = false) {\n if (n === 0) return ''\n if (n < 100) return spellUnder100(n, feminine, masculineTeens)\n\n const h = Math.floor(n / 100)\n const r = n % 100\n const hundredWord = HUNDREDS[h]\n\n if (r === 0) return hundredWord\n return hundredWord + ' ' + spellUnder100(r, feminine, masculineTeens)\n}\n\n/**\n * Builds scale word with proper pluralization and \"de\" insertion.\n * Romanian always uses feminine forms (două, not doi) when counting scale words.\n */\nfunction buildScalePhrase (segment, scaleIndex) {\n const meta = SCALE_META[scaleIndex - 1]\n if (!meta) return spellUnder1000(segment, true)\n\n if (segment === 1) {\n return meta.article + ' ' + meta.singular\n }\n\n // Special case: 21 with scale words uses feminine \"una\"\n if (segment === 21 && meta.needsDe) {\n return 'douăzeci și una de ' + meta.plural\n }\n\n // Romanian always uses feminine when counting scale words (două milioane, not doi milioane)\n const words = spellUnder1000(segment, true)\n\n // \"de\" after >= 20\n const needsDe = meta.needsDe && segment >= 20\n const separator = needsDe ? ' de ' : ' '\n\n return words + separator + meta.plural\n}\n\n// ============================================================================\n// Conversion Functions\n// ============================================================================\n\n/**\n * Converts a non-negative integer to Romanian words.\n *\n * @param {bigint} n - Non-negative integer to convert\n * @param {Object} options - Conversion options\n * @returns {string} Romanian words\n */\nfunction integerToWords (n, options = {}) {\n if (n === 0n) return ZERO\n\n // Fast path: numbers < 1000\n if (n < 1000n) {\n const feminine = options.gender === 'feminine'\n return spellUnder1000(Number(n), feminine)\n }\n\n return buildLargeNumberWords(n, options)\n}\n\n/**\n * Builds words for numbers >= 1000.\n * Uses BigInt division for faster segment extraction.\n *\n * @param {bigint} n - Number >= 1000\n * @param {Object} options - Conversion options\n * @returns {string} Romanian words\n */\nfunction buildLargeNumberWords (n, options) {\n // Extract segments using BigInt division (faster than string slicing)\n // Segments stored least-significant first (index 0 = ones, 1 = thousands, etc.)\n const segmentValues = []\n let temp = n\n while (temp > 0n) {\n segmentValues.push(Number(temp % 1000n))\n temp = temp / 1000n\n }\n\n // Build result string directly (avoid regex cleanup)\n let result = ''\n\n for (let i = segmentValues.length - 1; i >= 0; i--) {\n const segment = segmentValues[i]\n if (segment === 0) continue\n\n let segmentWords\n if (i === 0) {\n // Units segment - use gender from options\n const feminine = options.gender === 'feminine'\n segmentWords = spellUnder1000(segment, feminine)\n } else {\n // Scale segment\n segmentWords = buildScalePhrase(segment, i)\n }\n\n if (result && segmentWords) {\n result += ' ' + segmentWords\n } else if (segmentWords) {\n result = segmentWords\n }\n }\n\n return result\n}\n\n/**\n * Converts decimal digits to Romanian words.\n * Decimals always use masculine forms.\n *\n * @param {string} decimalPart - Decimal digits (without the point)\n * @returns {string} Romanian words for decimal part\n */\nfunction decimalPartToWords (decimalPart) {\n let result = ''\n let i = 0\n\n // Handle leading zeros\n while (i < decimalPart.length && decimalPart[i] === '0') {\n if (result) result += ' '\n result += ZERO\n i++\n }\n\n // Convert remainder as a single number (masculine, with masculine teens)\n const remainder = decimalPart.slice(i)\n if (remainder) {\n if (result) result += ' '\n const n = BigInt(remainder)\n if (n < 1000n) {\n result += spellUnder1000(Number(n), false, true)\n } else {\n result += integerToWords(n, { gender: 'masculine' })\n }\n }\n\n return result\n}\n\n/**\n * Converts a numeric value to Romanian words.\n *\n * @param {number | string | bigint} value - The numeric value to convert\n * @param {Object} [options] - Conversion options\n * @param {string} [options.gender='masculine'] - Gender for numbers\n * @returns {string} The number in Romanian words\n * @throws {TypeError} If value is not a valid numeric type\n * @throws {Error} If value is not a valid number format\n *\n * @example\n * toWords(21) // 'douăzeci și unu'\n * toWords(1, { gender: 'feminine' }) // 'una'\n * toWords(1000) // 'o mie'\n */\nfunction toWords (value, options) {\n options = validateOptions(options)\n const { isNegative, integerPart, decimalPart } = parseNumericValue(value)\n\n let result = ''\n\n if (isNegative) {\n result = NEGATIVE + ' '\n }\n\n result += integerToWords(integerPart, options)\n\n if (decimalPart) {\n result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart)\n }\n\n return result\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\nexport { toWords }\n","import { isPlainObject } from './is-plain-object.js'\n\n/**\n * Validates and normalizes the options parameter.\n *\n * @param {*} options The options value to validate\n * @returns {Object} A valid options object (empty object if undefined)\n * @throws {TypeError} If options is not undefined or a plain object\n */\nexport function validateOptions (options) {\n if (options === undefined) return {}\n if (isPlainObject(options)) return options\n throw new TypeError(\n `Invalid options: expected plain object or undefined, got ${typeof options}`\n )\n}\n","/**\n * Checks if a value is a plain object (not null, array, or other object types).\n *\n * A plain object is one created by:\n * - Object literal: `{}`\n * - Object.create(null): null-prototype object\n *\n * This excludes arrays, class instances, Map, Set, and other object types.\n *\n * @param {*} value Value to check\n * @returns {boolean} True if value is a plain object\n */\nexport function isPlainObject (value) {\n if (value === null || typeof value !== 'object') return false\n const proto = Object.getPrototypeOf(value)\n return proto === null || proto === Object.prototype\n}\n"],"names":["parseNumericString","str","isNegative","slice","dotIndex","indexOf","integerPart","BigInt","integerStr","decimalPart","expandScientificNotation","mantissa","expStr","toLowerCase","split","exp","parseInt","digits","newDotPosition","length","repeat","ONES_MASC","ONES_FEM","TEENS","TEENS_MASC","TWENTIES","HUNDREDS","ZERO","SCALE_META","singular","plural","article","feminine","needsDe","spellUnder100","n","masculineTeens","t","Math","floor","u","spellUnder1000","h","r","hundredWord","buildScalePhrase","segment","scaleIndex","meta","integerToWords","options","gender","Number","segmentValues","temp","push","result","i","segmentWords","buildLargeNumberWords","value","undefined","proto","Object","getPrototypeOf","prototype","isPlainObject","TypeError","validateOptions","type","isFinite","Error","isSafeInteger","toString","includes","numberToString","trimmed","trim","isNaN","normalizeString","parseNumericValue","NEGATIVE","remainder","decimalPartToWords"],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- /*! n2words/ru v3.1.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),u=(-1===i?t.length:i)+r;return u>=o.length?o+"0".repeat(u-o.length):u<=0?"0."+"0".repeat(-u)+o:o.slice(0,u)+"."+o.slice(u)}const r=["","один","два","три","четыре","пять","шесть","семь","восемь","девять"],i=["","одна","две","три","четыре","пять","шесть","семь","восемь","девять"],o=["десять","одиннадцать","двенадцать","тринадцать","четырнадцать","пятнадцать","шестнадцать","семнадцать","восемнадцать","девятнадцать"],u=["","","двадцать","тридцать","сорок","пятьдесят","шестьдесят","семьдесят","восемьдесят","девяносто"],s=["","сто","двести","триста","четыреста","пятьсот","шестьсот","семьсот","восемьсот","девятьсот"],f="ноль",c=[["тысяча","тысячи","тысяч"],["миллион","миллиона","миллионов"],["миллиард","миллиарда","миллиардов"],["триллион","триллиона","триллионов"],["квадриллион","квадриллиона","квадриллионов"],["квинтиллион","квинтиллиона","квинтиллионов"],["секстиллион","секстиллиона","секстиллионов"],["септиллион","септиллиона","септиллионов"],["октиллион","октиллиона","октиллионов"],["нониллион","нониллиона","нониллионов"]];function l(e,t){const n="bigint"==typeof e?Number(e):e,r=n%10,i=n%100;return i>=11&&i<=19?t[2]:1===r?t[0]:r>=2&&r<=4?t[1]:t[2]}function a(e){if(0===e)return"";const t=e%10,n=Math.floor(e/10)%10,i=Math.floor(e/100),f=[];return i>0&&f.push(s[i]),n>1&&f.push(u[n]),1===n?f.push(o[t]):t>0&&f.push(r[t]),f.join(" ")}function g(e){if(0===e)return"";const t=e%10,n=Math.floor(e/10)%10,r=Math.floor(e/100),f=[];return r>0&&f.push(s[r]),n>1&&f.push(u[n]),1===n?f.push(o[t]):t>0&&f.push(i[t]),f.join(" ")}function p(e,t={}){if(0n===e)return f;const n="feminine"===t.gender;if(e<1000n)return n?g(Number(e)):a(Number(e));if(e<1000000n){const t=Number(e/1000n),r=Number(e%1000n);let i=g(t)+" "+l(t,c[0]);return r>0&&(i+=" "+(n?g(r):a(r))),i}return function(e,t){const n="feminine"===t.gender,r=e.toString(),i=r.length,o=[],u=i%3;let s=0;for(u>0&&(o.push(Number(r.slice(0,u))),s=u);s<i;)o.push(Number(r.slice(s,s+3))),s+=3;const f=[];let p=o.length-1;for(let e=0;e<o.length;e++){const t=o[e];if(0!==t)if(0===p)f.push(n?g(t):a(t));else{const e=l(t,c[p-1]),n=1===p?g(t):a(t);f.push(n+" "+e)}p--}return f.join(" ")}(e,t)}e.ru=function(e,r){r=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)}(r);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 s="";return i&&(s="минус "),s+=p(o,r),u&&(s+=" запятая "+function(e,t){let n="",r=0;for(;r<e.length&&"0"===e[r];)n&&(n+=" "),n+=f,r++;const i=e.slice(r);return i&&(n&&(n+=" "),n+=p(BigInt(i),t)),n}(u,r)),s}},"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=ru.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ru.js","sources":["../../lib/utils/parse-numeric.js","../../lib/languages/ru.js","../../lib/utils/validate-options.js","../../lib/utils/is-plain-object.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 * Russian language converter - Functional Implementation\n *\n * Self-contained module with its own input validation, ready for subpath exports.\n *\n * Key features:\n * - Three-form pluralization (one/few/many)\n * - Gender: thousands are feminine, millions+ are masculine\n * - Irregular hundreds (двести, триста, etc.)\n * - Long scale naming\n */\n\nimport { parseNumericValue } from '../utils/parse-numeric.js'\nimport { validateOptions } from '../utils/validate-options.js'\n\n// ============================================================================\n// Vocabulary\n// ============================================================================\n\nconst ONES_MASC = ['', 'один', 'два', 'три', 'четыре', 'пять', 'шесть', 'семь', 'восемь', 'девять']\nconst ONES_FEM = ['', 'одна', 'две', 'три', 'четыре', 'пять', 'шесть', 'семь', 'восемь', 'девять']\n\nconst TEENS = ['десять', 'одиннадцать', 'двенадцать', 'тринадцать', 'четырнадцать', 'пятнадцать', 'шестнадцать', 'семнадцать', 'восемнадцать', 'девятнадцать']\nconst TENS = ['', '', 'двадцать', 'тридцать', 'сорок', 'пятьдесят', 'шестьдесят', 'семьдесят', 'восемьдесят', 'девяносто']\n\n// Irregular hundreds\nconst HUNDREDS = ['', 'сто', 'двести', 'триста', 'четыреста', 'пятьсот', 'шестьсот', 'семьсот', 'восемьсот', 'девятьсот']\n\nconst ZERO = 'ноль'\nconst NEGATIVE = 'минус'\nconst DECIMAL_SEP = 'запятая'\n\n// Scale words: [singular, few, many]\n// Thousands (index 0) are feminine, rest are masculine\nconst SCALE_FORMS = [\n ['тысяча', 'тысячи', 'тысяч'],\n ['миллион', 'миллиона', 'миллионов'],\n ['миллиард', 'миллиарда', 'миллиардов'],\n ['триллион', 'триллиона', 'триллионов'],\n ['квадриллион', 'квадриллиона', 'квадриллионов'],\n ['квинтиллион', 'квинтиллиона', 'квинтиллионов'],\n ['секстиллион', 'секстиллиона', 'секстиллионов'],\n ['септиллион', 'септиллиона', 'септиллионов'],\n ['октиллион', 'октиллиона', 'октиллионов'],\n ['нониллион', 'нониллиона', 'нониллионов']\n]\n\n// ============================================================================\n// Segment Building\n// ============================================================================\n\nfunction pluralize (n, forms) {\n const num = typeof n === 'bigint' ? Number(n) : n\n const lastDigit = num % 10\n const lastTwoDigits = num % 100\n\n if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {\n return forms[2]\n }\n\n if (lastDigit === 1) return forms[0]\n if (lastDigit >= 2 && lastDigit <= 4) return forms[1]\n return forms[2]\n}\n\nfunction buildSegmentMasc (n) {\n if (n === 0) return ''\n\n const onesDigit = n % 10\n const tensDigit = Math.floor(n / 10) % 10\n const hundredsDigit = Math.floor(n / 100)\n\n const parts = []\n\n if (hundredsDigit > 0) {\n parts.push(HUNDREDS[hundredsDigit])\n }\n\n if (tensDigit > 1) {\n parts.push(TENS[tensDigit])\n }\n\n if (tensDigit === 1) {\n parts.push(TEENS[onesDigit])\n } else if (onesDigit > 0) {\n parts.push(ONES_MASC[onesDigit])\n }\n\n return parts.join(' ')\n}\n\nfunction buildSegmentFem (n) {\n if (n === 0) return ''\n\n const onesDigit = n % 10\n const tensDigit = Math.floor(n / 10) % 10\n const hundredsDigit = Math.floor(n / 100)\n\n const parts = []\n\n if (hundredsDigit > 0) {\n parts.push(HUNDREDS[hundredsDigit])\n }\n\n if (tensDigit > 1) {\n parts.push(TENS[tensDigit])\n }\n\n if (tensDigit === 1) {\n parts.push(TEENS[onesDigit])\n } else if (onesDigit > 0) {\n parts.push(ONES_FEM[onesDigit])\n }\n\n return parts.join(' ')\n}\n\n// ============================================================================\n// Conversion Functions\n// ============================================================================\n\nfunction integerToWords (n, options = {}) {\n if (n === 0n) return ZERO\n\n const feminine = options.gender === 'feminine'\n\n if (n < 1000n) {\n return feminine ? buildSegmentFem(Number(n)) : buildSegmentMasc(Number(n))\n }\n\n if (n < 1_000_000n) {\n const thousands = Number(n / 1000n)\n const remainder = Number(n % 1000n)\n\n // Thousands are always feminine in Russian\n const thousandsWord = buildSegmentFem(thousands)\n const scaleWord = pluralize(thousands, SCALE_FORMS[0])\n\n let result = thousandsWord + ' ' + scaleWord\n\n if (remainder > 0) {\n result += ' ' + (feminine ? buildSegmentFem(remainder) : buildSegmentMasc(remainder))\n }\n\n return result\n }\n\n return buildLargeNumberWords(n, options)\n}\n\nfunction buildLargeNumberWords (n, options) {\n const feminine = options.gender === 'feminine'\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 if (scaleIndex === 0) {\n parts.push(feminine ? buildSegmentFem(segment) : buildSegmentMasc(segment))\n } else {\n const scaleForms = SCALE_FORMS[scaleIndex - 1]\n const scaleWord = pluralize(segment, scaleForms)\n // Thousands (scaleIndex=1) are feminine, others masculine\n const isFeminine = scaleIndex === 1\n const segmentWord = isFeminine ? buildSegmentFem(segment) : buildSegmentMasc(segment)\n parts.push(segmentWord + ' ' + scaleWord)\n }\n }\n\n scaleIndex--\n }\n\n return parts.join(' ')\n}\n\nfunction decimalPartToWords (decimalPart, options) {\n let result = ''\n let i = 0\n\n while (i < decimalPart.length && decimalPart[i] === '0') {\n if (result) result += ' '\n result += ZERO\n i++\n }\n\n const remainder = decimalPart.slice(i)\n if (remainder) {\n if (result) result += ' '\n result += integerToWords(BigInt(remainder), options)\n }\n\n return result\n}\n\n/**\n * Converts a numeric value to Russian words.\n *\n * @param {number | string | bigint} value - The numeric value to convert\n * @param {Object} [options] - Optional configuration\n * @param {('masculine'|'feminine')} [options.gender='masculine'] - Grammatical gender\n * @returns {string} The number in Russian words\n */\nfunction toWords (value, options) {\n options = validateOptions(options)\n const { isNegative, integerPart, decimalPart } = parseNumericValue(value)\n\n let result = ''\n\n if (isNegative) {\n result = NEGATIVE + ' '\n }\n\n result += integerToWords(integerPart, options)\n\n if (decimalPart) {\n result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart, options)\n }\n\n return result\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport { toWords }\n","import { isPlainObject } from './is-plain-object.js'\n\n/**\n * Validates and normalizes the options parameter.\n *\n * @param {*} options The options value to validate\n * @returns {Object} A valid options object (empty object if undefined)\n * @throws {TypeError} If options is not undefined or a plain object\n */\nexport function validateOptions (options) {\n if (options === undefined) return {}\n if (isPlainObject(options)) return options\n throw new TypeError(\n `Invalid options: expected plain object or undefined, got ${typeof options}`\n )\n}\n","/**\n * Checks if a value is a plain object (not null, array, or other object types).\n *\n * A plain object is one created by:\n * - Object literal: `{}`\n * - Object.create(null): null-prototype object\n *\n * This excludes arrays, class instances, Map, Set, and other object types.\n *\n * @param {*} value Value to check\n * @returns {boolean} True if value is a plain object\n */\nexport function isPlainObject (value) {\n if (value === null || typeof value !== 'object') return false\n const proto = Object.getPrototypeOf(value)\n return proto === null || proto === Object.prototype\n}\n"],"names":["parseNumericString","str","isNegative","slice","dotIndex","indexOf","integerPart","BigInt","integerStr","decimalPart","expandScientificNotation","mantissa","expStr","toLowerCase","split","exp","parseInt","digits","newDotPosition","length","repeat","ONES_MASC","ONES_FEM","TEENS","TENS","HUNDREDS","ZERO","SCALE_FORMS","pluralize","n","forms","num","Number","lastDigit","lastTwoDigits","buildSegmentMasc","onesDigit","tensDigit","Math","floor","hundredsDigit","parts","push","join","buildSegmentFem","integerToWords","options","feminine","gender","thousands","remainder","result","numStr","toString","len","segments","remainderLen","pos","scaleIndex","i","segment","scaleWord","segmentWord","buildLargeNumberWords","value","undefined","proto","Object","getPrototypeOf","prototype","isPlainObject","TypeError","validateOptions","type","isFinite","Error","isSafeInteger","includes","numberToString","trimmed","trim","isNaN","normalizeString","parseNumericValue","NEGATIVE","decimalPartToWords"],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- /*! n2words/sr-Cyrl v3.1.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),u=(-1===i?t.length:i)+r;return u>=o.length?o+"0".repeat(u-o.length):u<=0?"0."+"0".repeat(-u)+o:o.slice(0,u)+"."+o.slice(u)}const r=["","један","два","три","четири","пет","шест","седам","осам","девет"],i=["","једна","две","три","четири","пет","шест","седам","осам","девет"],o=["десет","једанаест","дванаест","тринаест","четрнаест","петнаест","шеснаест","седамнаест","осамнаест","деветнаест"],u=["","","двадесет","тридесет","четрдесет","педесет","шездесет","седамдесет","осамдесет","деведесет"],s=["","сто","двеста","триста","четиристо","петсто","шесто","седамсто","осамсто","девестo"],f="нула",c=[["хиљада","хиљаде","хиљада"],["милион","милиона","милиона"],["милијарда","милијарде","милијарда"],["билион","билиона","билиона"],["билијарда","билијарде","билијарда"],["трилион","трилиона","трилиона"],["трилијарда","трилијарде","трилијарда"],["квадрилион","квадрилиона","квадрилиона"],["квадрилијарда","квадрилијарде","квадрилијарда"]];function l(e,t){const n="bigint"==typeof e?Number(e):e,r=n%10,i=n%100;return i>=11&&i<=19?t[2]:1===r?t[0]:r>=2&&r<=4?t[1]:t[2]}function a(e){if(0===e)return"";const t=e%10,n=Math.floor(e/10)%10,i=Math.floor(e/100),f=[];return i>0&&f.push(s[i]),n>1&&f.push(u[n]),1===n?f.push(o[t]):t>0&&f.push(r[t]),f.join(" ")}function g(e){if(0===e)return"";const t=e%10,n=Math.floor(e/10)%10,r=Math.floor(e/100),f=[];return r>0&&f.push(s[r]),n>1&&f.push(u[n]),1===n?f.push(o[t]):t>0&&f.push(i[t]),f.join(" ")}function p(e,t={}){return 0n===e?f:e<1000n?"feminine"===t.gender?g(Number(e)):a(Number(e)):function(e,t){const n=e.toString(),r=n.length,i=[],o=r%3;let u=0;for(o>0&&(i.push(Number(n.slice(0,o))),u=o);u<r;)i.push(Number(n.slice(u,u+3))),u+=3;const s=[];let f=i.length-1;for(let e=0;e<i.length;e++){const n=i[e];if(0!==n)if(0===f)s.push("feminine"===t.gender?g(n):a(n));else{const e=l(n,c[f-1]),t=1===f?g(n):a(n);s.push(t+" "+e)}f--}return s.join(" ")}(e,t)}e.srCyrl=function(e,r){r=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)}(r);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 s="";return i&&(s="минус "),s+=p(o,r),u&&(s+=" запета "+function(e,t){let n="",r=0;for(;r<e.length&&"0"===e[r];)n&&(n+=" "),n+=f,r++;const i=e.slice(r);return i&&(n&&(n+=" "),n+=p(BigInt(i),t)),n}(u,r)),s}},"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=sr-Cyrl.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sr-Cyrl.js","sources":["../../lib/utils/parse-numeric.js","../../lib/languages/sr-Cyrl.js","../../lib/utils/validate-options.js","../../lib/utils/is-plain-object.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 * Serbian Cyrillic language converter - Functional Implementation\n *\n * Self-contained module with its own input validation, ready for subpath exports.\n *\n * Key features:\n * - Three-form pluralization (one/few/many)\n * - Gender: thousands are feminine, millions+ are masculine\n * - Irregular hundreds\n * - Long scale naming with -ard forms\n * - Cyrillic script\n */\n\nimport { parseNumericValue } from '../utils/parse-numeric.js'\nimport { validateOptions } from '../utils/validate-options.js'\n\n// ============================================================================\n// Vocabulary\n// ============================================================================\n\nconst ONES_MASC = ['', 'један', 'два', 'три', 'четири', 'пет', 'шест', 'седам', 'осам', 'девет']\nconst ONES_FEM = ['', 'једна', 'две', 'три', 'четири', 'пет', 'шест', 'седам', 'осам', 'девет']\nconst TEENS = ['десет', 'једанаест', 'дванаест', 'тринаест', 'четрнаест', 'петнаест', 'шеснаест', 'седамнаест', 'осамнаест', 'деветнаест']\nconst TENS = ['', '', 'двадесет', 'тридесет', 'четрдесет', 'педесет', 'шездесет', 'седамдесет', 'осамдесет', 'деведесет']\nconst HUNDREDS = ['', 'сто', 'двеста', 'триста', 'четиристо', 'петсто', 'шесто', 'седамсто', 'осамсто', 'девестo']\n\nconst ZERO = 'нула'\nconst NEGATIVE = 'минус'\nconst DECIMAL_SEP = 'запета'\n\n// Scale words: [singular, few, many]\nconst SCALE_FORMS = [\n ['хиљада', 'хиљаде', 'хиљада'],\n ['милион', 'милиона', 'милиона'],\n ['милијарда', 'милијарде', 'милијарда'],\n ['билион', 'билиона', 'билиона'],\n ['билијарда', 'билијарде', 'билијарда'],\n ['трилион', 'трилиона', 'трилиона'],\n ['трилијарда', 'трилијарде', 'трилијарда'],\n ['квадрилион', 'квадрилиона', 'квадрилиона'],\n ['квадрилијарда', 'квадрилијарде', 'квадрилијарда']\n]\n\n// ============================================================================\n// Segment Building\n// ============================================================================\n\nfunction pluralize (n, forms) {\n const num = typeof n === 'bigint' ? Number(n) : n\n const lastDigit = num % 10\n const lastTwoDigits = num % 100\n\n if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {\n return forms[2]\n }\n\n if (lastDigit === 1) return forms[0]\n if (lastDigit >= 2 && lastDigit <= 4) return forms[1]\n return forms[2]\n}\n\nfunction buildSegmentMasc (n) {\n if (n === 0) return ''\n\n const onesDigit = n % 10\n const tensDigit = Math.floor(n / 10) % 10\n const hundredsDigit = Math.floor(n / 100)\n\n const parts = []\n\n if (hundredsDigit > 0) {\n parts.push(HUNDREDS[hundredsDigit])\n }\n\n if (tensDigit > 1) {\n parts.push(TENS[tensDigit])\n }\n\n if (tensDigit === 1) {\n parts.push(TEENS[onesDigit])\n } else if (onesDigit > 0) {\n parts.push(ONES_MASC[onesDigit])\n }\n\n return parts.join(' ')\n}\n\nfunction buildSegmentFem (n) {\n if (n === 0) return ''\n\n const onesDigit = n % 10\n const tensDigit = Math.floor(n / 10) % 10\n const hundredsDigit = Math.floor(n / 100)\n\n const parts = []\n\n if (hundredsDigit > 0) {\n parts.push(HUNDREDS[hundredsDigit])\n }\n\n if (tensDigit > 1) {\n parts.push(TENS[tensDigit])\n }\n\n if (tensDigit === 1) {\n parts.push(TEENS[onesDigit])\n } else if (onesDigit > 0) {\n parts.push(ONES_FEM[onesDigit])\n }\n\n return parts.join(' ')\n}\n\n// ============================================================================\n// Conversion Functions\n// ============================================================================\n\nfunction integerToWords (n, options = {}) {\n if (n === 0n) return ZERO\n\n if (n < 1000n) {\n return options.gender === 'feminine' ? buildSegmentFem(Number(n)) : buildSegmentMasc(Number(n))\n }\n\n return buildLargeNumberWords(n, options)\n}\n\nfunction buildLargeNumberWords (n, options) {\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 if (scaleIndex === 0) {\n parts.push(options.gender === 'feminine' ? buildSegmentFem(segment) : buildSegmentMasc(segment))\n } else {\n const scaleForms = SCALE_FORMS[scaleIndex - 1]\n const scaleWord = pluralize(segment, scaleForms)\n // Thousands (scaleIndex=1) are feminine, others masculine\n const isFeminine = scaleIndex === 1\n const segmentWord = isFeminine ? buildSegmentFem(segment) : buildSegmentMasc(segment)\n parts.push(segmentWord + ' ' + scaleWord)\n }\n }\n\n scaleIndex--\n }\n\n return parts.join(' ')\n}\n\nfunction decimalPartToWords (decimalPart, options) {\n let result = ''\n let i = 0\n\n while (i < decimalPart.length && decimalPart[i] === '0') {\n if (result) result += ' '\n result += ZERO\n i++\n }\n\n const remainder = decimalPart.slice(i)\n if (remainder) {\n if (result) result += ' '\n result += integerToWords(BigInt(remainder), options)\n }\n\n return result\n}\n\n/**\n * Converts a numeric value to Serbian (Cyrillic) words.\n *\n * @param {number | string | bigint} value - The numeric value to convert\n * @param {Object} [options] - Optional configuration\n * @param {('masculine'|'feminine')} [options.gender='masculine'] - Grammatical gender\n * @returns {string} The number in Serbian Cyrillic words\n */\nfunction toWords (value, options) {\n options = validateOptions(options)\n const { isNegative, integerPart, decimalPart } = parseNumericValue(value)\n\n let result = ''\n\n if (isNegative) {\n result = NEGATIVE + ' '\n }\n\n result += integerToWords(integerPart, options)\n\n if (decimalPart) {\n result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart, options)\n }\n\n return result\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport { toWords }\n","import { isPlainObject } from './is-plain-object.js'\n\n/**\n * Validates and normalizes the options parameter.\n *\n * @param {*} options The options value to validate\n * @returns {Object} A valid options object (empty object if undefined)\n * @throws {TypeError} If options is not undefined or a plain object\n */\nexport function validateOptions (options) {\n if (options === undefined) return {}\n if (isPlainObject(options)) return options\n throw new TypeError(\n `Invalid options: expected plain object or undefined, got ${typeof options}`\n )\n}\n","/**\n * Checks if a value is a plain object (not null, array, or other object types).\n *\n * A plain object is one created by:\n * - Object literal: `{}`\n * - Object.create(null): null-prototype object\n *\n * This excludes arrays, class instances, Map, Set, and other object types.\n *\n * @param {*} value Value to check\n * @returns {boolean} True if value is a plain object\n */\nexport function isPlainObject (value) {\n if (value === null || typeof value !== 'object') return false\n const proto = Object.getPrototypeOf(value)\n return proto === null || proto === Object.prototype\n}\n"],"names":["parseNumericString","str","isNegative","slice","dotIndex","indexOf","integerPart","BigInt","integerStr","decimalPart","expandScientificNotation","mantissa","expStr","toLowerCase","split","exp","parseInt","digits","newDotPosition","length","repeat","ONES_MASC","ONES_FEM","TEENS","TENS","HUNDREDS","ZERO","SCALE_FORMS","pluralize","n","forms","num","Number","lastDigit","lastTwoDigits","buildSegmentMasc","onesDigit","tensDigit","Math","floor","hundredsDigit","parts","push","join","buildSegmentFem","integerToWords","options","gender","numStr","toString","len","segments","remainderLen","pos","scaleIndex","i","segment","scaleWord","segmentWord","buildLargeNumberWords","value","undefined","proto","Object","getPrototypeOf","prototype","isPlainObject","TypeError","validateOptions","type","isFinite","Error","isSafeInteger","includes","numberToString","trimmed","trim","isNaN","normalizeString","parseNumericValue","result","NEGATIVE","remainder","decimalPartToWords"],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- /*! n2words/sr-Latn v3.1.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 i=e.indexOf(".");if(-1===i)return{isNegative:t,integerPart:BigInt(e)};const n=e.slice(0,i)||"0",r=e.slice(i+1);return{isNegative:t,integerPart:BigInt(n),decimalPart:r}}function i(e){const[t,i]=e.toLowerCase().split("e"),n=parseInt(i,10),r=t.indexOf("."),o=-1===r?t:t.slice(0,r)+t.slice(r+1),s=(-1===r?t.length:r)+n;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 n=["","jedan","dva","tri","četiri","pet","šest","sedam","osam","devet"],r=["","jedna","dve","tri","četiri","pet","šest","sedam","osam","devet"],o=["deset","jedanaest","dvanaest","trinaest","četrnaest","petnaest","šesnaest","sedamnaest","osamnaest","devetnaest"],s=["","","dvadeset","trideset","četrdeset","pedeset","šezdeset","sedamdeset","osamdeset","devedeset"],a=["","sto","dvesta","trista","četiristo","petsto","šesto","sedamsto","osamsto","devetsto"],d="nula",l=[["hiljada","hiljade","hiljada"],["milion","miliona","miliona"],["milijarda","milijarde","milijarda"],["bilion","biliona","biliona"],["bilijarda","bilijarde","bilijarda"],["trilion","triliona","triliona"],["trilijarda","trilijarde","trilijarda"],["kvadrilion","kvadriliona","kvadriliona"],["kvadrilijarda","kvadrilijarde","kvadrilijarda"]];function u(e,t){const i="bigint"==typeof e?Number(e):e,n=i%10,r=i%100;return r>=11&&r<=19?t[2]:1===n?t[0]:n>=2&&n<=4?t[1]:t[2]}function f(e){if(0===e)return"";const t=e%10,i=Math.floor(e/10)%10,r=Math.floor(e/100),d=[];return r>0&&d.push(a[r]),i>1&&d.push(s[i]),1===i?d.push(o[t]):t>0&&d.push(n[t]),d.join(" ")}function c(e){if(0===e)return"";const t=e%10,i=Math.floor(e/10)%10,n=Math.floor(e/100),d=[];return n>0&&d.push(a[n]),i>1&&d.push(s[i]),1===i?d.push(o[t]):t>0&&d.push(r[t]),d.join(" ")}function p(e,t={}){return 0n===e?d:e<1000n?"feminine"===t.gender?c(Number(e)):f(Number(e)):function(e,t){const i=e.toString(),n=i.length,r=[],o=n%3;let s=0;for(o>0&&(r.push(Number(i.slice(0,o))),s=o);s<n;)r.push(Number(i.slice(s,s+3))),s+=3;const a=[];let d=r.length-1;for(let e=0;e<r.length;e++){const i=r[e];if(0!==i)if(0===d)a.push("feminine"===t.gender?c(i):f(i));else{const e=u(i,l[d-1]),t=1===d?c(i):f(i);a.push(t+" "+e)}d--}return a.join(" ")}(e,t)}e.srLatn=function(e,n){n=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)}(n);const{isNegative:r,integerPart:o,decimalPart:s}=function(e){const n=typeof e;if("bigint"===n)return e<0n?{isNegative:!0,integerPart:-e}:{isNegative:!1,integerPart:e};if("number"===n){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")?i(t):t}(e))}if("string"===n)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")?i(t):t}(e));throw new TypeError(`Invalid value type: expected number, string, or bigint, received ${n}`)}(e);let a="";return r&&(a="minus "),a+=p(o,n),s&&(a+=" zapeta "+function(e,t){let i="",n=0;for(;n<e.length&&"0"===e[n];)i&&(i+=" "),i+=d,n++;const r=e.slice(n);return r&&(i&&(i+=" "),i+=p(BigInt(r),t)),i}(s,n)),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=sr-Latn.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sr-Latn.js","sources":["../../lib/utils/parse-numeric.js","../../lib/languages/sr-Latn.js","../../lib/utils/validate-options.js","../../lib/utils/is-plain-object.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 * Serbian Latin language converter - Functional Implementation\n *\n * Self-contained module with its own input validation, ready for subpath exports.\n *\n * Key features:\n * - Three-form pluralization (one/few/many)\n * - Gender: thousands are feminine, millions+ are masculine\n * - Irregular hundreds (dvesta, trista, etc.)\n * - Long scale naming with -ard forms\n * - Latin script\n */\n\nimport { parseNumericValue } from '../utils/parse-numeric.js'\nimport { validateOptions } from '../utils/validate-options.js'\n\n// ============================================================================\n// Vocabulary\n// ============================================================================\n\nconst ONES_MASC = ['', 'jedan', 'dva', 'tri', 'četiri', 'pet', 'šest', 'sedam', 'osam', 'devet']\nconst ONES_FEM = ['', 'jedna', 'dve', 'tri', 'četiri', 'pet', 'šest', 'sedam', 'osam', 'devet']\nconst TEENS = ['deset', 'jedanaest', 'dvanaest', 'trinaest', 'četrnaest', 'petnaest', 'šesnaest', 'sedamnaest', 'osamnaest', 'devetnaest']\nconst TENS = ['', '', 'dvadeset', 'trideset', 'četrdeset', 'pedeset', 'šezdeset', 'sedamdeset', 'osamdeset', 'devedeset']\nconst HUNDREDS = ['', 'sto', 'dvesta', 'trista', 'četiristo', 'petsto', 'šesto', 'sedamsto', 'osamsto', 'devetsto']\n\nconst ZERO = 'nula'\nconst NEGATIVE = 'minus'\nconst DECIMAL_SEP = 'zapeta'\n\n// Scale words: [singular, few, many]\nconst SCALE_FORMS = [\n ['hiljada', 'hiljade', 'hiljada'],\n ['milion', 'miliona', 'miliona'],\n ['milijarda', 'milijarde', 'milijarda'],\n ['bilion', 'biliona', 'biliona'],\n ['bilijarda', 'bilijarde', 'bilijarda'],\n ['trilion', 'triliona', 'triliona'],\n ['trilijarda', 'trilijarde', 'trilijarda'],\n ['kvadrilion', 'kvadriliona', 'kvadriliona'],\n ['kvadrilijarda', 'kvadrilijarde', 'kvadrilijarda']\n]\n\n// ============================================================================\n// Segment Building\n// ============================================================================\n\nfunction pluralize (n, forms) {\n const num = typeof n === 'bigint' ? Number(n) : n\n const lastDigit = num % 10\n const lastTwoDigits = num % 100\n\n if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {\n return forms[2]\n }\n\n if (lastDigit === 1) return forms[0]\n if (lastDigit >= 2 && lastDigit <= 4) return forms[1]\n return forms[2]\n}\n\nfunction buildSegmentMasc (n) {\n if (n === 0) return ''\n\n const onesDigit = n % 10\n const tensDigit = Math.floor(n / 10) % 10\n const hundredsDigit = Math.floor(n / 100)\n\n const parts = []\n\n if (hundredsDigit > 0) {\n parts.push(HUNDREDS[hundredsDigit])\n }\n\n if (tensDigit > 1) {\n parts.push(TENS[tensDigit])\n }\n\n if (tensDigit === 1) {\n parts.push(TEENS[onesDigit])\n } else if (onesDigit > 0) {\n parts.push(ONES_MASC[onesDigit])\n }\n\n return parts.join(' ')\n}\n\nfunction buildSegmentFem (n) {\n if (n === 0) return ''\n\n const onesDigit = n % 10\n const tensDigit = Math.floor(n / 10) % 10\n const hundredsDigit = Math.floor(n / 100)\n\n const parts = []\n\n if (hundredsDigit > 0) {\n parts.push(HUNDREDS[hundredsDigit])\n }\n\n if (tensDigit > 1) {\n parts.push(TENS[tensDigit])\n }\n\n if (tensDigit === 1) {\n parts.push(TEENS[onesDigit])\n } else if (onesDigit > 0) {\n parts.push(ONES_FEM[onesDigit])\n }\n\n return parts.join(' ')\n}\n\n// ============================================================================\n// Conversion Functions\n// ============================================================================\n\nfunction integerToWords (n, options = {}) {\n if (n === 0n) return ZERO\n\n if (n < 1000n) {\n return options.gender === 'feminine' ? buildSegmentFem(Number(n)) : buildSegmentMasc(Number(n))\n }\n\n return buildLargeNumberWords(n, options)\n}\n\nfunction buildLargeNumberWords (n, options) {\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 if (scaleIndex === 0) {\n parts.push(options.gender === 'feminine' ? buildSegmentFem(segment) : buildSegmentMasc(segment))\n } else {\n const scaleForms = SCALE_FORMS[scaleIndex - 1]\n const scaleWord = pluralize(segment, scaleForms)\n // Thousands (scaleIndex=1) are feminine, others masculine\n const isFeminine = scaleIndex === 1\n const segmentWord = isFeminine ? buildSegmentFem(segment) : buildSegmentMasc(segment)\n parts.push(segmentWord + ' ' + scaleWord)\n }\n }\n\n scaleIndex--\n }\n\n return parts.join(' ')\n}\n\nfunction decimalPartToWords (decimalPart, options) {\n let result = ''\n let i = 0\n\n while (i < decimalPart.length && decimalPart[i] === '0') {\n if (result) result += ' '\n result += ZERO\n i++\n }\n\n const remainder = decimalPart.slice(i)\n if (remainder) {\n if (result) result += ' '\n result += integerToWords(BigInt(remainder), options)\n }\n\n return result\n}\n\n/**\n * Converts a numeric value to Serbian (Latin) words.\n *\n * @param {number | string | bigint} value - The numeric value to convert\n * @param {Object} [options] - Optional configuration\n * @param {('masculine'|'feminine')} [options.gender='masculine'] - Grammatical gender\n * @returns {string} The number in Serbian Latin words\n */\nfunction toWords (value, options) {\n options = validateOptions(options)\n const { isNegative, integerPart, decimalPart } = parseNumericValue(value)\n\n let result = ''\n\n if (isNegative) {\n result = NEGATIVE + ' '\n }\n\n result += integerToWords(integerPart, options)\n\n if (decimalPart) {\n result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart, options)\n }\n\n return result\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport { toWords }\n","import { isPlainObject } from './is-plain-object.js'\n\n/**\n * Validates and normalizes the options parameter.\n *\n * @param {*} options The options value to validate\n * @returns {Object} A valid options object (empty object if undefined)\n * @throws {TypeError} If options is not undefined or a plain object\n */\nexport function validateOptions (options) {\n if (options === undefined) return {}\n if (isPlainObject(options)) return options\n throw new TypeError(\n `Invalid options: expected plain object or undefined, got ${typeof options}`\n )\n}\n","/**\n * Checks if a value is a plain object (not null, array, or other object types).\n *\n * A plain object is one created by:\n * - Object literal: `{}`\n * - Object.create(null): null-prototype object\n *\n * This excludes arrays, class instances, Map, Set, and other object types.\n *\n * @param {*} value Value to check\n * @returns {boolean} True if value is a plain object\n */\nexport function isPlainObject (value) {\n if (value === null || typeof value !== 'object') return false\n const proto = Object.getPrototypeOf(value)\n return proto === null || proto === Object.prototype\n}\n"],"names":["parseNumericString","str","isNegative","slice","dotIndex","indexOf","integerPart","BigInt","integerStr","decimalPart","expandScientificNotation","mantissa","expStr","toLowerCase","split","exp","parseInt","digits","newDotPosition","length","repeat","ONES_MASC","ONES_FEM","TEENS","TENS","HUNDREDS","ZERO","SCALE_FORMS","pluralize","n","forms","num","Number","lastDigit","lastTwoDigits","buildSegmentMasc","onesDigit","tensDigit","Math","floor","hundredsDigit","parts","push","join","buildSegmentFem","integerToWords","options","gender","numStr","toString","len","segments","remainderLen","pos","scaleIndex","i","segment","scaleWord","segmentWord","buildLargeNumberWords","value","undefined","proto","Object","getPrototypeOf","prototype","isPlainObject","TypeError","validateOptions","type","isFinite","Error","isSafeInteger","includes","numberToString","trimmed","trim","isNaN","normalizeString","parseNumericValue","result","NEGATIVE","remainder","decimalPartToWords"],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- /*! n2words/sv v3.1.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=["","ett","två","tre","fyra","fem","sex","sju","åtta","nio"],i=["tio","elva","tolv","tretton","fjorton","femton","sexton","sjutton","arton","nitton"],o=["","","tjugo","trettio","fyrtio","femtio","sextio","sjuttio","åttio","nittio"],s="hundra",u="noll",l=["tusen","miljon","miljard","biljon","biljard","triljon","triljard","kvadriljon"];function a(e){if(0===e)return{word:"",hasHundred:!1,lessThan100:!1};const t=e%10,n=Math.floor(e/10)%10,u=Math.floor(e/100),l=[];let a=!1;u>0&&(a=!0,l.push(1===u?s:r[u]+" "+s));let d="";return 1===n?d=i[t]:n>=2?d=t>0?o[n]+"-"+r[t]:o[n]:t>0&&(d=r[t]),a&&d?{word:l[0]+" och "+d,hasHundred:!0,lessThan100:!1}:a?{word:l[0],hasHundred:!0,lessThan100:!1}:{word:d,hasHundred:!1,lessThan100:!0}}function d(e){if(0n===e)return u;if(e<1000n)return a(Number(e)).word;if(e<1000000n){const t=Number(e/1000n),n=Number(e%1000n);let r=1===t?l[0]:a(t).word+" "+l[0];if(n>0){const e=a(n);r+=e.lessThan100?" och "+e.word:" "+e.word}return r}return 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 s=[];let d=r.length-1;for(let e=0;e<r.length;e++){const t=r[e];if(0!==t){const e=a(t);if(0===d)s.push({word:e.word,hasHundred:e.hasHundred,isScale:!1});else{const n=l[d-1];let r;r=1===t?1===d?"":"en":e.word,r&&s.push({word:r,hasHundred:!1,isScale:!1}),s.push({word:n,hasHundred:!1,isScale:!0})}}d--}return function(e){if(0===e.length)return u;if(1===e.length)return e[0].word;const t=[];for(let n=0;n<e.length;n++){const r=e[n];n===e.length-1&&e.length>1&&e[n-1].isScale&&!r.hasHundred&&t.push("och"),t.push(r.word)}return t.join(" ")}(s)}(e)}e.sv=function(e){const{isNegative:r,integerPart:i,decimalPart:o}=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 s="";return r&&(s="minus "),s+=d(i),o&&(s+=" komma "+function(e){let t="",n=0;for(;n<e.length&&"0"===e[n];)t&&(t+=" "),t+=u,n++;const r=e.slice(n);return r&&(t&&(t+=" "),t+=d(BigInt(r))),t}(o)),s}},"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=sv.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sv.js","sources":["../../lib/utils/parse-numeric.js","../../lib/languages/sv.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 * Swedish language converter - Functional Implementation\n *\n * Self-contained module with its own input validation, ready for subpath exports.\n *\n * Key features:\n * - Hyphenation for tens-ones (tjugo-ett)\n * - \"och\" after hundreds before small numbers\n * - Omit \"ett\" before hundra and tusen\n * - Use \"en\" (not \"ett\") before million+ scales\n * - Long scale naming with -ard forms\n */\n\nimport { parseNumericValue } from '../utils/parse-numeric.js'\n\n// ============================================================================\n// Vocabulary (module-level constants)\n// ============================================================================\n\nconst ONES = ['', 'ett', 'två', 'tre', 'fyra', 'fem', 'sex', 'sju', 'åtta', 'nio']\n\nconst TEENS = ['tio', 'elva', 'tolv', 'tretton', 'fjorton', 'femton', 'sexton', 'sjutton', 'arton', 'nitton']\nconst TENS = ['', '', 'tjugo', 'trettio', 'fyrtio', 'femtio', 'sextio', 'sjuttio', 'åttio', 'nittio']\n\nconst HUNDRED = 'hundra'\n\nconst ZERO = 'noll'\nconst NEGATIVE = 'minus'\nconst DECIMAL_SEP = 'komma'\n\n// Scale words (long scale with -ard forms)\nconst SCALES = ['tusen', 'miljon', 'miljard', 'biljon', 'biljard', 'triljon', 'triljard', 'kvadriljon']\n\n// ============================================================================\n// Segment Building\n// ============================================================================\n\n/**\n * Builds segment word for 0-999.\n * Returns object with word and metadata for \"och\" logic.\n */\nfunction buildSegment (n) {\n if (n === 0) return { word: '', hasHundred: false, lessThan100: false }\n\n const ones = n % 10\n const tens = Math.floor(n / 10) % 10\n const hundreds = Math.floor(n / 100)\n\n const parts = []\n let hasHundred = false\n\n // Hundreds - omit \"ett\" before hundra\n if (hundreds > 0) {\n hasHundred = true\n if (hundreds === 1) {\n parts.push(HUNDRED)\n } else {\n parts.push(ONES[hundreds] + ' ' + HUNDRED)\n }\n }\n\n // Tens and ones with hyphenation\n let tensOnesWord = ''\n if (tens === 1) {\n tensOnesWord = TEENS[ones]\n } else if (tens >= 2) {\n if (ones > 0) {\n tensOnesWord = TENS[tens] + '-' + ONES[ones]\n } else {\n tensOnesWord = TENS[tens]\n }\n } else if (ones > 0) {\n tensOnesWord = ONES[ones]\n }\n\n // Combine with \"och\" after hundreds if there's a remainder\n if (hasHundred && tensOnesWord) {\n return { word: parts[0] + ' och ' + tensOnesWord, hasHundred: true, lessThan100: false }\n } else if (hasHundred) {\n return { word: parts[0], hasHundred: true, lessThan100: false }\n } else {\n return { word: tensOnesWord, hasHundred: false, lessThan100: true }\n }\n}\n\n// ============================================================================\n// Conversion Functions\n// ============================================================================\n\n/**\n * Converts a non-negative integer to Swedish words.\n *\n * @param {bigint} n - Non-negative integer to convert\n * @returns {string} Swedish words\n */\nfunction integerToWords (n) {\n if (n === 0n) return ZERO\n\n // Fast path: numbers < 1000\n if (n < 1000n) {\n return buildSegment(Number(n)).word\n }\n\n // Fast path: numbers < 1,000,000 (thousands)\n if (n < 1_000_000n) {\n const thousands = Number(n / 1000n)\n const remainder = Number(n % 1000n)\n\n // Omit \"ett\" before tusen\n let result = thousands === 1 ? SCALES[0] : buildSegment(thousands).word + ' ' + SCALES[0]\n\n if (remainder > 0) {\n const remainderResult = buildSegment(remainder)\n // Insert \"och\" if remainder < 100 (doesn't have hundred)\n if (remainderResult.lessThan100) {\n result += ' och ' + remainderResult.word\n } else {\n result += ' ' + remainderResult.word\n }\n }\n\n return result\n }\n\n // For numbers >= 1,000,000, use scale decomposition\n return buildLargeNumberWords(n)\n}\n\n/**\n * Builds words for numbers >= 1,000,000.\n *\n * @param {bigint} n - Number >= 1,000,000\n * @returns {string} Swedish words\n */\nfunction buildLargeNumberWords (n) {\n const numStr = n.toString()\n const len = numStr.length\n\n // Build segments of 3 digits from right to left\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 // Convert segments to words\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 segmentResult = buildSegment(segment)\n\n if (scaleIndex === 0) {\n // Units segment\n parts.push({\n word: segmentResult.word,\n hasHundred: segmentResult.hasHundred,\n isScale: false\n })\n } else {\n // Segment with scale word\n const scaleWord = SCALES[scaleIndex - 1]\n\n let segmentWord\n if (segment === 1) {\n // Omit \"ett\" before tusen, use \"en\" before million+\n if (scaleIndex === 1) {\n segmentWord = '' // Just \"tusen\"\n } else {\n segmentWord = 'en' // \"en miljon\"\n }\n } else {\n segmentWord = segmentResult.word\n }\n\n if (segmentWord) {\n parts.push({ word: segmentWord, hasHundred: false, isScale: false })\n }\n parts.push({ word: scaleWord, hasHundred: false, isScale: true })\n }\n }\n\n scaleIndex--\n }\n\n // Join with Swedish \"och\" rules\n return joinSwedishParts(parts)\n}\n\n/**\n * Joins parts with Swedish \"och\" rules.\n * Insert \"och\" before final segment if it follows a scale word and doesn't have \"hundra\".\n *\n * @param {Array} parts - Parts with metadata\n * @returns {string} Joined string\n */\nfunction joinSwedishParts (parts) {\n if (parts.length === 0) return ZERO\n if (parts.length === 1) return parts[0].word\n\n const result = []\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i]\n const isLast = i === parts.length - 1\n\n if (isLast && parts.length > 1) {\n const prevPart = parts[i - 1]\n // Insert \"och\" if previous was scale and this doesn't have hundred\n if (prevPart.isScale && !part.hasHundred) {\n result.push('och')\n }\n }\n\n result.push(part.word)\n }\n\n return result.join(' ')\n}\n\n/**\n * Converts decimal digits to Swedish words.\n *\n * @param {string} decimalPart - Decimal digits (without the point)\n * @returns {string} Swedish words for decimal part\n */\nfunction decimalPartToWords (decimalPart) {\n let result = ''\n\n // Handle leading zeros\n let i = 0\n while (i < decimalPart.length && decimalPart[i] === '0') {\n if (result) result += ' '\n result += ZERO\n i++\n }\n\n // Convert remainder as a single number\n const remainder = decimalPart.slice(i)\n if (remainder) {\n if (result) result += ' '\n result += integerToWords(BigInt(remainder))\n }\n\n return result\n}\n\n/**\n * Converts a numeric value to Swedish words.\n *\n * @param {number | string | bigint} value - The numeric value to convert\n * @returns {string} The number in Swedish words\n * @throws {TypeError} If value is not a valid numeric type\n * @throws {Error} If value is not a valid number format\n *\n * @example\n * toWords(42) // 'fyrtio-två'\n * toWords(101) // 'hundra och ett'\n * toWords(1000000) // 'en miljon'\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// Public API\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","HUNDRED","ZERO","SCALES","buildSegment","n","word","hasHundred","lessThan100","ones","tens","Math","floor","hundreds","parts","push","tensOnesWord","integerToWords","Number","thousands","remainder","result","remainderResult","numStr","toString","len","segments","remainderLen","pos","scaleIndex","i","segment","segmentResult","isScale","scaleWord","segmentWord","part","join","joinSwedishParts","buildLargeNumberWords","value","type","isFinite","Error","isSafeInteger","includes","numberToString","trimmed","trim","isNaN","normalizeString","TypeError","parseNumericValue","NEGATIVE","decimalPartToWords"],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- /*! n2words/sw v3.1.0 | MIT License | github.com/forzagreen/n2words */
2
- var n,i;n=this,i=function(n){"use strict";function i(n){const i="-"===n[0];i&&(n=n.slice(1));const e=n.indexOf(".");if(-1===e)return{isNegative:i,integerPart:BigInt(n)};const t=n.slice(0,e)||"0",r=n.slice(e+1);return{isNegative:i,integerPart:BigInt(t),decimalPart:r}}function e(n){const[i,e]=n.toLowerCase().split("e"),t=parseInt(e,10),r=i.indexOf("."),s=-1===r?i:i.slice(0,r)+i.slice(r+1),o=(-1===r?i.length:r)+t;return o>=s.length?s+"0".repeat(o-s.length):o<=0?"0."+"0".repeat(-o)+s:s.slice(0,o)+"."+s.slice(o)}const t=["sifuri","moja","mbili","tatu","nne","tano","sita","saba","nane","tisa"],r={10:"kumi",20:"ishirini",30:"thelathini",40:"arobaini",50:"hamsini",60:"sitini",70:"sabini",80:"themanini",90:"tisini"},s=["","elfu","milioni","bilioni","trilioni","kwadrilioni","kwintilioni"],o="sifuri";function u(n){if(n<10)return t[n];if(10===n)return r[10];if(n<20)return r[10]+" na "+t[n-10];const i=10*Math.trunc(n/10),e=n%10;return 0===e?r[i]:r[i]+" na "+t[e]}function a(n){if(n<100)return u(n);if(100===n)return"mia moja";const i=Math.trunc(n/100),e=n%100,r=[];return r.push("mia "+t[i]),e>0&&r.push(e<10?"na "+t[e]:u(e)),r.join(" ")}function f(n){if(0n===n)return o;const i=function(n){const i=[];let e=n;for(;e>0n;)i.push(Number(e%1000n)),e/=1000n;return i}(n),e=[];for(let n=i.length-1;n>=0;n--){const r=i[n];if(0!==r)if(0===n)e.push(r<10&&e.length>0?"na "+t[r]:100===r&&e.length>0?"mia":a(r));else{const i=1===r?"moja":a(r);e.push(s[n]+" "+i)}}return e.join(" ").trim()}n.sw=function(n){const{isNegative:t,integerPart:r,decimalPart:s}=function(n){const t=typeof n;if("bigint"===t)return n<0n?{isNegative:!0,integerPart:-n}:{isNegative:!1,integerPart:n};if("number"===t){if(!Number.isFinite(n))throw new Error("Number must be finite (NaN and Infinity are not supported)");return Number.isSafeInteger(n)?n<0?{isNegative:!0,integerPart:BigInt(-n)}:{isNegative:!1,integerPart:BigInt(n)}:i(function(n){const i=n.toString();return i.includes("e")||i.includes("E")?e(i):i}(n))}if("string"===t)return i(function(n){const i=n.trim();if(0===i.length||Number.isNaN(Number(i)))throw new Error(`Invalid number format: "${n}"`);return i.includes("e")||i.includes("E")?e(i):i}(n));throw new TypeError(`Invalid value type: expected number, string, or bigint, received ${t}`)}(n);let u="";return t&&(u="minus "),u+=f(r),s&&(u+=" nukta "+function(n){let i="",e=0;for(;e<n.length&&"0"===n[e];)i&&(i+=" "),i+=o,e++;const t=n.slice(e);return t&&(i&&(i+=" "),i+=f(BigInt(t))),i}(s)),u}},"object"==typeof exports&&"undefined"!=typeof module?i(exports):"function"==typeof define&&define.amd?define(["exports"],i):i((n="undefined"!=typeof globalThis?globalThis:n||self).n2words=n.n2words||{});
3
- //# sourceMappingURL=sw.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sw.js","sources":["../../lib/utils/parse-numeric.js","../../lib/languages/sw.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 * Swahili language converter - Functional Implementation\n *\n * Self-contained converter with precomputed lookup tables.\n *\n * Key features:\n * - \"na\" connector for compound numbers\n * - Reversed hundreds: \"mia moja\" (one hundred)\n * - Scale words: elfu, milioni, bilioni\n */\n\nimport { parseNumericValue } from '../utils/parse-numeric.js'\n\n// ============================================================================\n// Vocabulary\n// ============================================================================\n\nconst ONES = ['sifuri', 'moja', 'mbili', 'tatu', 'nne', 'tano', 'sita', 'saba', 'nane', 'tisa']\nconst TENS = { 10: 'kumi', 20: 'ishirini', 30: 'thelathini', 40: 'arobaini', 50: 'hamsini', 60: 'sitini', 70: 'sabini', 80: 'themanini', 90: 'tisini' }\n\nconst SCALE_WORDS = ['', 'elfu', 'milioni', 'bilioni', 'trilioni', 'kwadrilioni', 'kwintilioni']\n\nconst ZERO = 'sifuri'\nconst NEGATIVE = 'minus'\nconst DECIMAL_SEP = 'nukta'\n\n// ============================================================================\n// Conversion Functions\n// ============================================================================\n\nfunction wordsUnder100 (n) {\n if (n < 10) return ONES[n]\n if (n === 10) return TENS[10]\n if (n < 20) {\n // 11-19: 'kumi na <digit>'\n return TENS[10] + ' na ' + ONES[n - 10]\n }\n const tens = Math.trunc(n / 10) * 10\n const ones = n % 10\n if (ones === 0) return TENS[tens]\n return TENS[tens] + ' na ' + ONES[ones]\n}\n\nfunction wordsUnder1000 (n) {\n if (n < 100) return wordsUnder100(n)\n if (n === 100) return 'mia moja'\n const hundreds = Math.trunc(n / 100)\n const rest = n % 100\n const parts = []\n\n // Hundreds: 'mia <digit>'\n parts.push('mia ' + ONES[hundreds])\n if (rest > 0) {\n if (rest < 10) {\n parts.push('na ' + ONES[rest])\n } else {\n parts.push(wordsUnder100(rest))\n }\n }\n\n return parts.join(' ')\n}\n\nfunction extractSegments (n) {\n const segments = []\n let temp = n\n while (temp > 0n) {\n segments.push(Number(temp % 1000n))\n temp = temp / 1000n\n }\n return segments\n}\n\nfunction integerToWords (n) {\n if (n === 0n) return ZERO\n\n // segments stored least-significant first: [ones, thousands, millions, ...]\n const segments = extractSegments(n)\n const parts = []\n\n // Iterate from highest scale to lowest\n for (let scaleIndex = segments.length - 1; scaleIndex >= 0; scaleIndex--) {\n const val = segments[scaleIndex]\n if (val === 0) continue\n\n if (scaleIndex === 0) {\n // Units segment\n if (val < 10 && parts.length > 0) {\n parts.push('na ' + ONES[val])\n } else if (val === 100 && parts.length > 0) {\n // In compound numbers (e.g., 1100 -> 'elfu moja mia'), use 'mia' not 'mia moja'\n parts.push('mia')\n } else {\n parts.push(wordsUnder1000(val))\n }\n } else {\n // Scale segments: 'elfu moja', 'milioni mbili'\n const unit = (val === 1) ? 'moja' : wordsUnder1000(val)\n parts.push(SCALE_WORDS[scaleIndex] + ' ' + unit)\n }\n }\n\n return parts.join(' ').trim()\n}\n\nfunction decimalPartToWords (decimalPart) {\n let result = ''\n let i = 0\n\n while (i < decimalPart.length && decimalPart[i] === '0') {\n if (result) result += ' '\n result += ZERO\n i++\n }\n\n const remainder = decimalPart.slice(i)\n if (remainder) {\n if (result) result += ' '\n result += integerToWords(BigInt(remainder))\n }\n\n return result\n}\n\n/**\n * Converts a numeric value to Swahili words.\n *\n * @param {number | string | bigint} value - The numeric value to convert\n * @returns {string} The number in Swahili 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","TENS","SCALE_WORDS","ZERO","wordsUnder100","n","tens","Math","trunc","ones","wordsUnder1000","hundreds","rest","parts","push","join","integerToWords","segments","temp","Number","extractSegments","scaleIndex","val","unit","trim","value","type","isFinite","Error","isSafeInteger","toString","includes","numberToString","trimmed","isNaN","normalizeString","TypeError","parseNumericValue","result","NEGATIVE","i","remainder","decimalPartToWords"],"mappings":";0CAwEA,SAASA,EAAoBC,GAC3B,MAAMC,EAAwB,MAAXD,EAAI,GACnBC,IAAYD,EAAMA,EAAIE,MAAM,IAEhC,MAAMC,EAAWH,EAAII,QAAQ,KAC7B,IAAiB,IAAbD,EACF,MAAO,CAAEF,aAAYI,YAAaC,OAAON,IAG3C,MAAMO,EAAaP,EAAIE,MAAM,EAAGC,IAAa,IACvCK,EAAcR,EAAIE,MAAMC,EAAW,GACzC,MAAO,CAAEF,aAAYI,YAAaC,OAAOC,GAAaC,cACxD,CAKA,SAASC,EAA0BT,GACjC,MAAOU,EAAUC,GAAUX,EAAIY,cAAcC,MAAM,KAC7CC,EAAMC,SAASJ,EAAQ,IAEvBR,EAAWO,EAASN,QAAQ,KAC5BY,OAASb,EACXO,EACAA,EAASR,MAAM,EAAGC,GAAYO,EAASR,MAAMC,EAAW,GAEtDc,IAD6B,IAAbd,EAAkBO,EAASQ,OAASf,GACnBW,EAEvC,OAAIG,GAAkBD,EAAOE,OACpBF,EAAS,IAAIG,OAAOF,EAAiBD,EAAOE,QAEjDD,GAAkB,EACb,KAAO,IAAIE,QAAQF,GAAkBD,EAEvCA,EAAOd,MAAM,EAAGe,GAAkB,IAAMD,EAAOd,MAAMe,EAC9D,CC1FA,MAAMG,EAAO,CAAC,SAAU,OAAQ,QAAS,OAAQ,MAAO,OAAQ,OAAQ,OAAQ,OAAQ,QAClFC,EAAO,CAAE,GAAI,OAAQ,GAAI,WAAY,GAAI,aAAc,GAAI,WAAY,GAAI,UAAW,GAAI,SAAU,GAAI,SAAU,GAAI,YAAa,GAAI,UAEvIC,EAAc,CAAC,GAAI,OAAQ,UAAW,UAAW,WAAY,cAAe,eAE5EC,EAAO,SAQb,SAASC,EAAeC,GACtB,GAAIA,EAAI,GAAI,OAAOL,EAAKK,GACxB,GAAU,KAANA,EAAU,OAAOJ,EAAK,IAC1B,GAAII,EAAI,GAEN,OAAOJ,EAAK,IAAM,OAASD,EAAKK,EAAI,IAEtC,MAAMC,EAA4B,GAArBC,KAAKC,MAAMH,EAAI,IACtBI,EAAOJ,EAAI,GACjB,OAAa,IAATI,EAAmBR,EAAKK,GACrBL,EAAKK,GAAQ,OAASN,EAAKS,EACpC,CAEA,SAASC,EAAgBL,GACvB,GAAIA,EAAI,IAAK,OAAOD,EAAcC,GAClC,GAAU,MAANA,EAAW,MAAO,WACtB,MAAMM,EAAWJ,KAAKC,MAAMH,EAAI,KAC1BO,EAAOP,EAAI,IACXQ,EAAQ,GAYd,OATAA,EAAMC,KAAK,OAASd,EAAKW,IACrBC,EAAO,GAEPC,EAAMC,KADJF,EAAO,GACE,MAAQZ,EAAKY,GAEbR,EAAcQ,IAItBC,EAAME,KAAK,IACpB,CAYA,SAASC,EAAgBX,GACvB,GAAU,KAANA,EAAU,OAAOF,EAGrB,MAAMc,EAdR,SAA0BZ,GACxB,MAAMY,EAAW,GACjB,IAAIC,EAAOb,EACX,KAAOa,EAAO,IACZD,EAASH,KAAKK,OAAOD,EAAO,QAC5BA,GAAc,MAEhB,OAAOD,CACT,CAMmBG,CAAgBf,GAC3BQ,EAAQ,GAGd,IAAK,IAAIQ,EAAaJ,EAASnB,OAAS,EAAGuB,GAAc,EAAGA,IAAc,CACxE,MAAMC,EAAML,EAASI,GACrB,GAAY,IAARC,EAEJ,GAAmB,IAAfD,EAGAR,EAAMC,KADJQ,EAAM,IAAMT,EAAMf,OAAS,EAClB,MAAQE,EAAKsB,GACP,MAARA,GAAeT,EAAMf,OAAS,EAE5B,MAEAY,EAAeY,QAEvB,CAEL,MAAMC,EAAgB,IAARD,EAAa,OAASZ,EAAeY,GACnDT,EAAMC,KAAKZ,EAAYmB,GAAc,IAAME,EAC7C,CACF,CAEA,OAAOV,EAAME,KAAK,KAAKS,MACzB,MA2BA,SAAkBC,GAChB,MAAM5C,WAAEA,EAAUI,YAAEA,EAAWG,YAAEA,GDtH5B,SAA4BqC,GACjC,MAAMC,SAAcD,EAGpB,GAAa,WAATC,EACF,OAAOD,EAAQ,GACX,CAAE5C,YAAY,EAAMI,aAAcwC,GAClC,CAAE5C,YAAY,EAAOI,YAAawC,GAIxC,GAAa,WAATC,EAAmB,CACrB,IAAKP,OAAOQ,SAASF,GACnB,MAAM,IAAIG,MAAM,8DAElB,OAAIT,OAAOU,cAAcJ,GAChBA,EAAQ,EACX,CAAE5C,YAAY,EAAMI,YAAaC,QAAQuC,IACzC,CAAE5C,YAAY,EAAOI,YAAaC,OAAOuC,IAExC9C,EAgBX,SAAyB8C,GACvB,MAAM7C,EAAM6C,EAAMK,WAClB,OAAQlD,EAAImD,SAAS,MAAQnD,EAAImD,SAAS,KACtC1C,EAAyBT,GACzBA,CACN,CArB8BoD,CAAeP,GAC3C,CAGA,GAAa,WAATC,EACF,OAAO/C,EAqBX,SAA0B8C,GACxB,MAAMQ,EAAUR,EAAMD,OACtB,GAAuB,IAAnBS,EAAQnC,QAAgBqB,OAAOe,MAAMf,OAAOc,IAC9C,MAAM,IAAIL,MAAM,2BAA2BH,MAE7C,OAAQQ,EAAQF,SAAS,MAAQE,EAAQF,SAAS,KAC9C1C,EAAyB4C,GACzBA,CACN,CA7B8BE,CAAgBV,IAG5C,MAAM,IAAIW,UACR,oEAAoEV,IAExE,CCuFmDW,CAAkBZ,GAEnE,IAAIa,EAAS,GAYb,OAVIzD,IACFyD,EAASC,UAGXD,GAAUtB,EAAe/B,GAErBG,IACFkD,GAAU,UArCd,SAA6BlD,GAC3B,IAAIkD,EAAS,GACTE,EAAI,EAER,KAAOA,EAAIpD,EAAYU,QAA6B,MAAnBV,EAAYoD,IACvCF,IAAQA,GAAU,KACtBA,GAAUnC,EACVqC,IAGF,MAAMC,EAAYrD,EAAYN,MAAM0D,GAMpC,OALIC,IACEH,IAAQA,GAAU,KACtBA,GAAUtB,EAAe9B,OAAOuD,KAG3BH,CACT,CAoBwCI,CAAmBtD,IAGlDkD,CACT"}
@@ -1,3 +0,0 @@
1
- /*! n2words/ta v3.1.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("."),s=-1===i?t:t.slice(0,i)+t.slice(i+1),o=(-1===i?t.length:i)+r;return o>=s.length?s+"0".repeat(o-s.length):o<=0?"0."+"0".repeat(-o)+s:s.slice(0,o)+"."+s.slice(o)}const r="பூஜ்ஜியம்",i=["பூஜ்ஜியம்","ஒன்று","இரண்டு","மூன்று","நான்கு","ஐந்து","ஆறு","ஏழு","எட்டு","ஒன்பது","பத்து","பதினொன்று","பன்னிரண்டு","பதிமூன்று","பதினான்கு","பதினைந்து","பதினாறு","பதினேழு","பதினெட்டு","பத்தொன்பது","இருபது","இருபத்தொன்று","இருபத்திரண்டு","இருபத்திமூன்று","இருபத்திநான்கு","இருபத்தைந்து","இருபத்தாறு","இருபத்தேழு","இருபத்தெட்டு","இருபத்தொன்பது","முப்பது","முப்பத்தொன்று","முப்பத்திரண்டு","முப்பத்திமூன்று","முப்பத்திநான்கு","முப்பத்தைந்து","முப்பத்தாறு","முப்பத்தேழு","முப்பத்தெட்டு","முப்பத்தொன்பது","நாற்பது","நாற்பத்தொன்று","நாற்பத்திரண்டு","நாற்பத்திமூன்று","நாற்பத்திநான்கு","நாற்பத்தைந்து","நாற்பத்தாறு","நாற்பத்தேழு","நாற்பத்தெட்டு","நாற்பத்தொன்பது","ஐம்பது","ஐம்பத்தொன்று","ஐம்பத்திரண்டு","ஐம்பத்திமூன்று","ஐம்பத்திநான்கு","ஐம்பத்தைந்து","ஐம்பத்தாறு","ஐம்பத்தேழு","ஐம்பத்தெட்டு","ஐம்பத்தொன்பது","அறுபது","அறுபத்தொன்று","அறுபத்திரண்டு","அறுபத்திமூன்று","அறுபத்திநான்கு","அறுபத்தைந்து","அறுபத்தாறு","அறுபத்தேழு","அறுபத்தெட்டு","அறுபத்தொன்பது","எழுபது","எழுபத்தொன்று","எழுபத்திரண்டு","எழுபத்திமூன்று","எழுபத்திநான்கு","எழுபத்தைந்து","எழுபத்தாறு","எழுபத்தேழு","எழுபத்தெட்டு","எழுபத்தொன்பது","எண்பது","எண்பத்தொன்று","எண்பத்திரண்டு","எண்பத்திமூன்று","எண்பத்திநான்கு","எண்பத்தைந்து","எண்பத்தாறு","எண்பத்தேழு","எண்பத்தெட்டு","எண்பத்தொன்பது","தொண்ணூறு","தொண்ணூற்று ஒன்று","தொண்ணூற்று இரண்டு","தொண்ணூற்று மூன்று","தொண்ணூற்று நான்கு","தொண்ணூற்று ஐந்து","தொண்ணூற்று ஆறு","தொண்ணூற்று ஏழு","தொண்ணூற்று எட்டு","தொண்ணூற்று ஒன்பது"],s=["","நூறு","இருநூறு","முன்னூறு","நானூறு","ஐநூறு","அறுநூறு","எழுநூறு","எண்நூறு","தொள்ளாயிரம்"],o=["","நூற்று","இருநூற்று","முன்னூற்று","நானூற்று","ஐநூற்று","அறுநூற்று","எழுநூற்று","எண்நூற்று","தொள்ளாயிரத்து"],u=["ஒன்று","இரண்டு","மூன்று","நான்கு","ஐந்து","ஆறு","ஏழு","எட்டு","ஒன்பது"],c=["","ஆயிரம்","லட்சம்","கோடி","அரபு","கராபு","நீல்","பத்ம","சங்கு"];function f(e){if(0===e)return"";if(e<100)return i[e];const t=Math.trunc(e/100),n=e%100;return 0===n?s[t]:o[t]+" "+i[n]}e.ta=function(e){const{isNegative:s,integerPart:o,decimalPart:a}=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 g="";return s&&(g="மைனஸ் "),g+=function(e){if(0n===e)return r;if(e<1000n)return f(Number(e));const t=[];t.push(Number(e%1000n));let n=e/1000n;for(;n>0n;)t.push(Number(n%100n)),n/=100n;const s=[];for(let e=t.length-1;e>=0;e--){const n=t[e];0!==n&&(s.push(0===e?f(n):1===n?"ஒரு":i[n]),e>0&&c[e]&&s.push(c[e]))}return s.join(" ")}(o),a&&(g+=" புள்ளி "+function(e){const t=[];for(const n of e){const e=parseInt(n,10);t.push(0===e?r:u[e-1])}return t.join(" ")}(a)),g}},"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=ta.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ta.js","sources":["../../lib/utils/parse-numeric.js","../../lib/languages/ta.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 * Tamil language converter - Functional Implementation\n *\n * Self-contained module with its own input validation, ready for subpath exports.\n *\n * Key features:\n * - Indian numbering system (ஆயிரம், லட்சம், கோடி)\n * - Tamil script\n * - 3-2-2 grouping pattern\n * - Complete word forms for 0-99\n * - Special hundred word transformations (connected vs standalone)\n * - Per-digit decimal reading\n * - BigInt modulo for efficient segment extraction\n */\n\nimport { parseNumericValue } from '../utils/parse-numeric.js'\n\n// ============================================================================\n// Vocabulary\n// ============================================================================\n\nconst ZERO = 'பூஜ்ஜியம்'\nconst NEGATIVE = 'மைனஸ்'\nconst DECIMAL_SEP = 'புள்ளி'\n\nconst BELOW_HUNDRED = [\n 'பூஜ்ஜியம்', 'ஒன்று', 'இரண்டு', 'மூன்று', 'நான்கு', 'ஐந்து', 'ஆறு', 'ஏழு', 'எட்டு', 'ஒன்பது',\n 'பத்து', 'பதினொன்று', 'பன்னிரண்டு', 'பதிமூன்று', 'பதினான்கு', 'பதினைந்து', 'பதினாறு', 'பதினேழு', 'பதினெட்டு', 'பத்தொன்பது',\n 'இருபது', 'இருபத்தொன்று', 'இருபத்திரண்டு', 'இருபத்திமூன்று', 'இருபத்திநான்கு', 'இருபத்தைந்து', 'இருபத்தாறு', 'இருபத்தேழு', 'இருபத்தெட்டு', 'இருபத்தொன்பது',\n 'முப்பது', 'முப்பத்தொன்று', 'முப்பத்திரண்டு', 'முப்பத்திமூன்று', 'முப்பத்திநான்கு', 'முப்பத்தைந்து', 'முப்பத்தாறு', 'முப்பத்தேழு', 'முப்பத்தெட்டு', 'முப்பத்தொன்பது',\n 'நாற்பது', 'நாற்பத்தொன்று', 'நாற்பத்திரண்டு', 'நாற்பத்திமூன்று', 'நாற்பத்திநான்கு', 'நாற்பத்தைந்து', 'நாற்பத்தாறு', 'நாற்பத்தேழு', 'நாற்பத்தெட்டு', 'நாற்பத்தொன்பது',\n 'ஐம்பது', 'ஐம்பத்தொன்று', 'ஐம்பத்திரண்டு', 'ஐம்பத்திமூன்று', 'ஐம்பத்திநான்கு', 'ஐம்பத்தைந்து', 'ஐம்பத்தாறு', 'ஐம்பத்தேழு', 'ஐம்பத்தெட்டு', 'ஐம்பத்தொன்பது',\n 'அறுபது', 'அறுபத்தொன்று', 'அறுபத்திரண்டு', 'அறுபத்திமூன்று', 'அறுபத்திநான்கு', 'அறுபத்தைந்து', 'அறுபத்தாறு', 'அறுபத்தேழு', 'அறுபத்தெட்டு', 'அறுபத்தொன்பது',\n 'எழுபது', 'எழுபத்தொன்று', 'எழுபத்திரண்டு', 'எழுபத்திமூன்று', 'எழுபத்திநான்கு', 'எழுபத்தைந்து', 'எழுபத்தாறு', 'எழுபத்தேழு', 'எழுபத்தெட்டு', 'எழுபத்தொன்பது',\n 'எண்பது', 'எண்பத்தொன்று', 'எண்பத்திரண்டு', 'எண்பத்திமூன்று', 'எண்பத்திநான்கு', 'எண்பத்தைந்து', 'எண்பத்தாறு', 'எண்பத்தேழு', 'எண்பத்தெட்டு', 'எண்பத்தொன்பது',\n 'தொண்ணூறு', 'தொண்ணூற்று ஒன்று', 'தொண்ணூற்று இரண்டு', 'தொண்ணூற்று மூன்று', 'தொண்ணூற்று நான்கு', 'தொண்ணூற்று ஐந்து', 'தொண்ணூற்று ஆறு', 'தொண்ணூற்று ஏழு', 'தொண்ணூற்று எட்டு', 'தொண்ணூற்று ஒன்பது'\n]\n\n// Standalone hundreds (when not followed by remainder)\nconst HUNDREDS = ['', 'நூறு', 'இருநூறு', 'முன்னூறு', 'நானூறு', 'ஐநூறு', 'அறுநூறு', 'எழுநூறு', 'எண்நூறு', 'தொள்ளாயிரம்']\n\n// Connected form of hundreds (when followed by remainder) - precomputed\nconst HUNDREDS_CONNECTED = ['', 'நூற்று', 'இருநூற்று', 'முன்னூற்று', 'நானூற்று', 'ஐநூற்று', 'அறுநூற்று', 'எழுநூற்று', 'எண்நூற்று', 'தொள்ளாயிரத்து']\n\n// Ones for decimal reading\nconst ONES = ['ஒன்று', 'இரண்டு', 'மூன்று', 'நான்கு', 'ஐந்து', 'ஆறு', 'ஏழு', 'எட்டு', 'ஒன்பது']\n\n// Scale words: index 0 = units, 1 = thousand, 2 = lakh, etc.\nconst SCALE_WORDS = ['', 'ஆயிரம்', 'லட்சம்', 'கோடி', 'அரபு', 'கராபு', 'நீல்', 'பத்ம', 'சங்கு']\n\n// ============================================================================\n// Segment Building\n// ============================================================================\n\n/**\n * Builds words for a 0-999 segment.\n *\n * @param {number} n - Number 0-999\n * @returns {string} Tamil words for the segment\n */\nfunction buildSegment (n) {\n if (n === 0) return ''\n if (n < 100) return BELOW_HUNDRED[n]\n\n const hundreds = Math.trunc(n / 100)\n const remainder = n % 100\n\n if (remainder === 0) {\n return HUNDREDS[hundreds]\n }\n\n // Use connected form when followed by remainder\n return HUNDREDS_CONNECTED[hundreds] + ' ' + BELOW_HUNDRED[remainder]\n}\n\n// ============================================================================\n// Conversion Functions\n// ============================================================================\n\n/**\n * Converts a non-negative integer to Tamil words.\n *\n * Uses BigInt modulo for segment extraction (faster than string slicing).\n * South Asian 3-2-2 grouping: first 3 digits, then groups of 2.\n *\n * @param {bigint} n - Non-negative integer to convert\n * @returns {string} Tamil words\n */\nfunction integerToWords (n) {\n if (n === 0n) return ZERO\n\n // Fast path: numbers < 1000\n if (n < 1000n) {\n return buildSegment(Number(n))\n }\n\n // Extract segments using BigInt modulo\n const segments = []\n segments.push(Number(n % 1000n))\n let temp = n / 1000n\n\n while (temp > 0n) {\n segments.push(Number(temp % 100n))\n temp = temp / 100n\n }\n\n // Build result string (process from most-significant to least)\n const words = []\n for (let i = segments.length - 1; i >= 0; i--) {\n const segment = segments[i]\n if (segment === 0) continue\n\n if (i === 0) {\n words.push(buildSegment(segment))\n } else {\n // Use 'ஒரு' for 1 at scale positions\n const groupWords = (segment === 1) ? 'ஒரு' : BELOW_HUNDRED[segment]\n words.push(groupWords)\n }\n\n if (i > 0 && SCALE_WORDS[i]) {\n words.push(SCALE_WORDS[i])\n }\n }\n\n return words.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 - 1])\n }\n return digits.join(' ')\n}\n\n/**\n * Converts a numeric value to Tamil words.\n *\n * @param {number | string | bigint} value - The numeric value to convert\n * @returns {string} The number in Tamil 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","ZERO","BELOW_HUNDRED","HUNDREDS","HUNDREDS_CONNECTED","ONES","SCALE_WORDS","buildSegment","n","hundreds","Math","trunc","remainder","value","type","Number","isFinite","Error","isSafeInteger","toString","includes","numberToString","trimmed","trim","isNaN","normalizeString","TypeError","parseNumericValue","result","NEGATIVE","segments","push","temp","words","i","segment","join","integerToWords","char","d","decimalPartToWords"],"mappings":";0CAwEA,SAASA,EAAoBC,GAC3B,MAAMC,EAAwB,MAAXD,EAAI,GACnBC,IAAYD,EAAMA,EAAIE,MAAM,IAEhC,MAAMC,EAAWH,EAAII,QAAQ,KAC7B,IAAiB,IAAbD,EACF,MAAO,CAAEF,aAAYI,YAAaC,OAAON,IAG3C,MAAMO,EAAaP,EAAIE,MAAM,EAAGC,IAAa,IACvCK,EAAcR,EAAIE,MAAMC,EAAW,GACzC,MAAO,CAAEF,aAAYI,YAAaC,OAAOC,GAAaC,cACxD,CAKA,SAASC,EAA0BT,GACjC,MAAOU,EAAUC,GAAUX,EAAIY,cAAcC,MAAM,KAC7CC,EAAMC,SAASJ,EAAQ,IAEvBR,EAAWO,EAASN,QAAQ,KAC5BY,OAASb,EACXO,EACAA,EAASR,MAAM,EAAGC,GAAYO,EAASR,MAAMC,EAAW,GAEtDc,IAD6B,IAAbd,EAAkBO,EAASQ,OAASf,GACnBW,EAEvC,OAAIG,GAAkBD,EAAOE,OACpBF,EAAS,IAAIG,OAAOF,EAAiBD,EAAOE,QAEjDD,GAAkB,EACb,KAAO,IAAIE,QAAQF,GAAkBD,EAEvCA,EAAOd,MAAM,EAAGe,GAAkB,IAAMD,EAAOd,MAAMe,EAC9D,CCtFA,MAAMG,EAAO,YAIPC,EAAgB,CACpB,YAAa,QAAS,SAAU,SAAU,SAAU,QAAS,MAAO,MAAO,QAAS,SACpF,QAAS,YAAa,aAAc,YAAa,YAAa,YAAa,UAAW,UAAW,YAAa,aAC9G,SAAU,eAAgB,gBAAiB,iBAAkB,iBAAkB,eAAgB,aAAc,aAAc,eAAgB,gBAC3I,UAAW,gBAAiB,iBAAkB,kBAAmB,kBAAmB,gBAAiB,cAAe,cAAe,gBAAiB,iBACpJ,UAAW,gBAAiB,iBAAkB,kBAAmB,kBAAmB,gBAAiB,cAAe,cAAe,gBAAiB,iBACpJ,SAAU,eAAgB,gBAAiB,iBAAkB,iBAAkB,eAAgB,aAAc,aAAc,eAAgB,gBAC3I,SAAU,eAAgB,gBAAiB,iBAAkB,iBAAkB,eAAgB,aAAc,aAAc,eAAgB,gBAC3I,SAAU,eAAgB,gBAAiB,iBAAkB,iBAAkB,eAAgB,aAAc,aAAc,eAAgB,gBAC3I,SAAU,eAAgB,gBAAiB,iBAAkB,iBAAkB,eAAgB,aAAc,aAAc,eAAgB,gBAC3I,WAAY,mBAAoB,oBAAqB,oBAAqB,oBAAqB,mBAAoB,iBAAkB,iBAAkB,mBAAoB,qBAIvKC,EAAW,CAAC,GAAI,OAAQ,UAAW,WAAY,SAAU,QAAS,UAAW,UAAW,UAAW,eAGnGC,EAAqB,CAAC,GAAI,SAAU,YAAa,aAAc,WAAY,UAAW,YAAa,YAAa,YAAa,iBAG7HC,EAAO,CAAC,QAAS,SAAU,SAAU,SAAU,QAAS,MAAO,MAAO,QAAS,UAG/EC,EAAc,CAAC,GAAI,SAAU,SAAU,OAAQ,OAAQ,QAAS,OAAQ,OAAQ,SAYtF,SAASC,EAAcC,GACrB,GAAU,IAANA,EAAS,MAAO,GACpB,GAAIA,EAAI,IAAK,OAAON,EAAcM,GAElC,MAAMC,EAAWC,KAAKC,MAAMH,EAAI,KAC1BI,EAAYJ,EAAI,IAEtB,OAAkB,IAAdI,EACKT,EAASM,GAIXL,EAAmBK,GAAY,IAAMP,EAAcU,EAC5D,MAuEA,SAAkBC,GAChB,MAAM/B,WAAEA,EAAUI,YAAEA,EAAWG,YAAEA,GDpI5B,SAA4BwB,GACjC,MAAMC,SAAcD,EAGpB,GAAa,WAATC,EACF,OAAOD,EAAQ,GACX,CAAE/B,YAAY,EAAMI,aAAc2B,GAClC,CAAE/B,YAAY,EAAOI,YAAa2B,GAIxC,GAAa,WAATC,EAAmB,CACrB,IAAKC,OAAOC,SAASH,GACnB,MAAM,IAAII,MAAM,8DAElB,OAAIF,OAAOG,cAAcL,GAChBA,EAAQ,EACX,CAAE/B,YAAY,EAAMI,YAAaC,QAAQ0B,IACzC,CAAE/B,YAAY,EAAOI,YAAaC,OAAO0B,IAExCjC,EAgBX,SAAyBiC,GACvB,MAAMhC,EAAMgC,EAAMM,WAClB,OAAQtC,EAAIuC,SAAS,MAAQvC,EAAIuC,SAAS,KACtC9B,EAAyBT,GACzBA,CACN,CArB8BwC,CAAeR,GAC3C,CAGA,GAAa,WAATC,EACF,OAAOlC,EAqBX,SAA0BiC,GACxB,MAAMS,EAAUT,EAAMU,OACtB,GAAuB,IAAnBD,EAAQvB,QAAgBgB,OAAOS,MAAMT,OAAOO,IAC9C,MAAM,IAAIL,MAAM,2BAA2BJ,MAE7C,OAAQS,EAAQF,SAAS,MAAQE,EAAQF,SAAS,KAC9C9B,EAAyBgC,GACzBA,CACN,CA7B8BG,CAAgBZ,IAG5C,MAAM,IAAIa,UACR,oEAAoEZ,IAExE,CCqGmDa,CAAkBd,GAEnE,IAAIe,EAAS,GAYb,OAVI9C,IACF8C,EAASC,UAGXD,GAjEF,SAAyBpB,GACvB,GAAU,KAANA,EAAU,OAAOP,EAGrB,GAAIO,EAAI,MACN,OAAOD,EAAaQ,OAAOP,IAI7B,MAAMsB,EAAW,GACjBA,EAASC,KAAKhB,OAAOP,EAAI,QACzB,IAAIwB,EAAOxB,EAAI,MAEf,KAAOwB,EAAO,IACZF,EAASC,KAAKhB,OAAOiB,EAAO,OAC5BA,GAAc,KAIhB,MAAMC,EAAQ,GACd,IAAK,IAAIC,EAAIJ,EAAS/B,OAAS,EAAGmC,GAAK,EAAGA,IAAK,CAC7C,MAAMC,EAAUL,EAASI,GACT,IAAZC,IAGFF,EAAMF,KADE,IAANG,EACS3B,EAAa4B,GAGQ,IAAZA,EAAiB,MAAQjC,EAAciC,IAIzDD,EAAI,GAAK5B,EAAY4B,IACvBD,EAAMF,KAAKzB,EAAY4B,IAE3B,CAEA,OAAOD,EAAMG,KAAK,IACpB,CA2BYC,CAAenD,GAErBG,IACFuC,GAAU,WA5Bd,SAA6BvC,GAE3B,MAAMQ,EAAS,GACf,IAAK,MAAMyC,KAAQjD,EAAa,CAC9B,MAAMkD,EAAI3C,SAAS0C,EAAM,IACzBzC,EAAOkC,KAAW,IAANQ,EAAUtC,EAAOI,EAAKkC,EAAI,GACxC,CACA,OAAO1C,EAAOuC,KAAK,IACrB,CAoBwCI,CAAmBnD,IAGlDuC,CACT"}
@@ -1,3 +0,0 @@
1
- /*! n2words/te v3.1.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("."),s=-1===i?t:t.slice(0,i)+t.slice(i+1),o=(-1===i?t.length:i)+r;return o>=s.length?s+"0".repeat(o-s.length):o<=0?"0."+"0".repeat(-o)+s:s.slice(0,o)+"."+s.slice(o)}const r="సున్నా",i=["సున్నా","ఒకటి","రెండు","మూడు","నాలుగు","ఐదు","ఆరు","ఏడు","ఎనిమిది","తొమ్మిది","పది","పదకొండు","పన్నెండు","పదమూడు","పద్నాలుగు","పదిహేను","పదహారు","పదిహేడు","పద్దెనిమిది","పంతొమ్మిది","ఇరవై","ఇరవై ఒక్కటి","ఇరవై రెండు","ఇరవై మూడు","ఇరవై నాలుగు","ఇరవై ఐదు","ఇరవై ఆరు","ఇరవై ఏడు","ఇరవై ఎనిమిది","ఇరవై తొమ్మిది","ముప్పై","ముప్పై ఒకటి","ముప్పై రెండు","ముప్పై మూడు","ముప్పై నాలుగు","ముప్పై ఐదు","ముప్పై ఆరు","ముప్పై ఏడు","ముప్పై ఎనిమిది","ముప్పై తొమ్మిది","నలభై","నలభై ఒకటి","నలభై రెండు","నలభై మూడు","నలభై నాలుగు","నలభై ఐదు","నలభై ఆరు","నలభై ఏడు","నలభై ఎనిమిది","నలభై తొమ్మిది","యాభై","యాభై ఒకటి","యాభై రెండు","యాభై మూడు","యాభై నాలుగు","యాభై ఐదు","యాభై ఆరు","యాభై ఏడు","యాభై ఎనిమిది","యాభై తొమ్మిది","అరవై","అరవై ఒకటి","అరవై రెండు","అరవై మూడు","అరవై నాలుగు","అరవై ఐదు","అరవై ఆరు","అరవై ఏడు","అరవై ఎనిమిది","అరవై తొమ్మిది","డెబ్బై","డెబ్బై ఒకటి","డెబ్బై రెండు","డెబ్బై మూడు","డెబ్బై నాలుగు","డెబ్బై ఐదు","డెబ్బై ఆరు","డెబ్బై ఏడు","డెబ్బై ఎనిమిది","డెబ్బై తొమ్మిది","ఎనభై","ఎనభై ఒకటి","ఎనభై రెండు","ఎనభై మూడు","ఎనభై నాలుగు","ఎనభై ఐదు","ఎనభై ఆరు","ఎనభై ఏడు","ఎనభై ఎనిమిది","ఎనభై తొమ్మిది","తొంభై","తొంభై ఒకటి","తొంభై రెండు","తొంభై మూడు","తొంభై నాలుగు","తొంభై ఐదు","తొంభై ఆరు","తొంభై ఏడు","తొంభై ఎనిమిది","తొంభై తొమ్మిది"],s=["","వంద","రెండు వందలు","మూడు వందలు","నాలుగు వందలు","ఐదు వందలు","ఆరు వందలు","ఏడు వందలు","ఎనిమిది వందలు","తొమ్మిది వందలు"],o=["ఒకటి","రెండు","మూడు","నాలుగు","ఐదు","ఆరు","ఏడు","ఎనిమిది","తొమ్మిది"],u=["","వెయ్యి","లక్ష","కోటి","అరబ్","ఖరబ్","నిల్","పడ్మ","శంకు"];function c(e){if(0===e)return"";if(e<100)return i[e];const t=Math.trunc(e/100),n=e%100;return 0===n?s[t]:s[t]+" "+i[n]}e.te=function(e){const{isNegative:s,integerPart:f,decimalPart:a}=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 g="";return s&&(g="మైనస్ "),g+=function(e){if(0n===e)return r;if(e<1000n)return c(Number(e));const t=[];t.push(Number(e%1000n));let n=e/1000n;for(;n>0n;)t.push(Number(n%100n)),n/=100n;const s=[];for(let e=t.length-1;e>=0;e--){const n=t[e];0!==n&&(s.push(0===e?c(n):1===n?"ఒక":i[n]),e>0&&u[e]&&s.push(u[e]))}return s.join(" ")}(f),a&&(g+=" పాయింట్ "+function(e){const t=[];for(const n of e){const e=parseInt(n,10);t.push(0===e?r:o[e-1])}return t.join(" ")}(a)),g}},"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=te.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"te.js","sources":["../../lib/utils/parse-numeric.js","../../lib/languages/te.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 * Telugu language converter - Functional Implementation\n *\n * Self-contained module with its own input validation, ready for subpath exports.\n *\n * Key features:\n * - Indian numbering system (వెయ్యి, లక్ష, కోటి)\n * - Telugu script\n * - 3-2-2 grouping pattern\n * - Complete word forms for 0-99\n * - Per-digit decimal reading\n */\n\nimport { parseNumericValue } from '../utils/parse-numeric.js'\n\n// ============================================================================\n// Vocabulary\n// ============================================================================\n\nconst ZERO = 'సున్నా'\nconst NEGATIVE = 'మైనస్'\nconst DECIMAL_SEP = 'పాయింట్'\n\nconst BELOW_HUNDRED = [\n 'సున్నా', 'ఒకటి', 'రెండు', 'మూడు', 'నాలుగు', 'ఐదు', 'ఆరు', 'ఏడు', 'ఎనిమిది', 'తొమ్మిది',\n 'పది', 'పదకొండు', 'పన్నెండు', 'పదమూడు', 'పద్నాలుగు', 'పదిహేను', 'పదహారు', 'పదిహేడు', 'పద్దెనిమిది', 'పంతొమ్మిది',\n 'ఇరవై', 'ఇరవై ఒక్కటి', 'ఇరవై రెండు', 'ఇరవై మూడు', 'ఇరవై నాలుగు', 'ఇరవై ఐదు', 'ఇరవై ఆరు', 'ఇరవై ఏడు', 'ఇరవై ఎనిమిది', 'ఇరవై తొమ్మిది',\n 'ముప్పై', 'ముప్పై ఒకటి', 'ముప్పై రెండు', 'ముప్పై మూడు', 'ముప్పై నాలుగు', 'ముప్పై ఐదు', 'ముప్పై ఆరు', 'ముప్పై ఏడు', 'ముప్పై ఎనిమిది', 'ముప్పై తొమ్మిది',\n 'నలభై', 'నలభై ఒకటి', 'నలభై రెండు', 'నలభై మూడు', 'నలభై నాలుగు', 'నలభై ఐదు', 'నలభై ఆరు', 'నలభై ఏడు', 'నలభై ఎనిమిది', 'నలభై తొమ్మిది',\n 'యాభై', 'యాభై ఒకటి', 'యాభై రెండు', 'యాభై మూడు', 'యాభై నాలుగు', 'యాభై ఐదు', 'యాభై ఆరు', 'యాభై ఏడు', 'యాభై ఎనిమిది', 'యాభై తొమ్మిది',\n 'అరవై', 'అరవై ఒకటి', 'అరవై రెండు', 'అరవై మూడు', 'అరవై నాలుగు', 'అరవై ఐదు', 'అరవై ఆరు', 'అరవై ఏడు', 'అరవై ఎనిమిది', 'అరవై తొమ్మిది',\n 'డెబ్బై', 'డెబ్బై ఒకటి', 'డెబ్బై రెండు', 'డెబ్బై మూడు', 'డెబ్బై నాలుగు', 'డెబ్బై ఐదు', 'డెబ్బై ఆరు', 'డెబ్బై ఏడు', 'డెబ్బై ఎనిమిది', 'డెబ్బై తొమ్మిది',\n 'ఎనభై', 'ఎనభై ఒకటి', 'ఎనభై రెండు', 'ఎనభై మూడు', 'ఎనభై నాలుగు', 'ఎనభై ఐదు', 'ఎనభై ఆరు', 'ఎనభై ఏడు', 'ఎనభై ఎనిమిది', 'ఎనభై తొమ్మిది',\n 'తొంభై', 'తొంభై ఒకటి', 'తొంభై రెండు', 'తొంభై మూడు', 'తొంభై నాలుగు', 'తొంభై ఐదు', 'తొంభై ఆరు', 'తొంభై ఏడు', 'తొంభై ఎనిమిది', 'తొంభై తొమ్మిది'\n]\n\nconst HUNDREDS = ['', 'వంద', 'రెండు వందలు', 'మూడు వందలు', 'నాలుగు వందలు', 'ఐదు వందలు', 'ఆరు వందలు', 'ఏడు వందలు', 'ఎనిమిది వందలు', 'తొమ్మిది వందలు']\n\n// Ones for decimal reading\nconst ONES = ['ఒకటి', 'రెండు', 'మూడు', 'నాలుగు', 'ఐదు', 'ఆరు', 'ఏడు', 'ఎనిమిది', 'తొమ్మిది']\n\n// Scale words: index 0 = units, 1 = thousand, 2 = lakh, etc.\nconst SCALE_WORDS = ['', 'వెయ్యి', 'లక్ష', 'కోటి', 'అరబ్', 'ఖరబ్', 'నిల్', 'పడ్మ', 'శంకు']\n\n// ============================================================================\n// Segment Building\n// ============================================================================\n\n/**\n * Builds words for a 0-999 segment.\n */\nfunction buildSegment (n) {\n if (n === 0) return ''\n if (n < 100) return BELOW_HUNDRED[n]\n\n const hundreds = Math.trunc(n / 100)\n const remainder = n % 100\n\n if (remainder === 0) {\n return HUNDREDS[hundreds]\n }\n return HUNDREDS[hundreds] + ' ' + BELOW_HUNDRED[remainder]\n}\n\n// ============================================================================\n// Conversion Functions\n// ============================================================================\n\n/**\n * Converts a non-negative integer to Telugu words.\n *\n * Uses BigInt modulo for segment extraction (faster than string slicing).\n * South Asian 3-2-2 grouping: first 3 digits, then groups of 2.\n *\n * @param {bigint} n - Non-negative integer to convert\n * @returns {string} Telugu words\n */\nfunction integerToWords (n) {\n if (n === 0n) return ZERO\n\n // Fast path: numbers < 1000 (direct lookup)\n if (n < 1000n) {\n return buildSegment(Number(n))\n }\n\n // Extract segments using BigInt modulo\n const segments = []\n segments.push(Number(n % 1000n))\n let temp = n / 1000n\n\n while (temp > 0n) {\n segments.push(Number(temp % 100n))\n temp = temp / 100n\n }\n\n // Build result string (process from most-significant to least)\n const words = []\n for (let i = segments.length - 1; i >= 0; i--) {\n const segment = segments[i]\n if (segment === 0) continue\n\n if (i === 0) {\n words.push(buildSegment(segment))\n } else {\n // Use 'ఒక' for 1 at scale positions\n const groupWords = (segment === 1) ? 'ఒక' : BELOW_HUNDRED[segment]\n words.push(groupWords)\n }\n\n if (i > 0 && SCALE_WORDS[i]) {\n words.push(SCALE_WORDS[i])\n }\n }\n\n return words.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 - 1])\n }\n return digits.join(' ')\n}\n\n/**\n * Converts a numeric value to Telugu words.\n *\n * @param {number | string | bigint} value - The numeric value to convert\n * @returns {string} The number in Telugu 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","ZERO","BELOW_HUNDRED","HUNDREDS","ONES","SCALE_WORDS","buildSegment","n","hundreds","Math","trunc","remainder","value","type","Number","isFinite","Error","isSafeInteger","toString","includes","numberToString","trimmed","trim","isNaN","normalizeString","TypeError","parseNumericValue","result","NEGATIVE","segments","push","temp","words","i","segment","join","integerToWords","char","d","decimalPartToWords"],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- /*! n2words/th v3.1.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("."),s=-1===i?t:t.slice(0,i)+t.slice(i+1),o=(-1===i?t.length:i)+r;return o>=s.length?s+"0".repeat(o-s.length):o<=0?"0."+"0".repeat(-o)+s:s.slice(0,o)+"."+s.slice(o)}const r=["หนึ่ง","สอง","สาม","สี่","ห้า","หก","เจ็ด","แปด","เก้า"],i="ศูนย์";function s(e){if(0===e)return"";let t=e;const n=[],i=Math.trunc(t/1e5);t%=1e5;const s=Math.trunc(t/1e4);t%=1e4;const o=Math.trunc(t/1e3);t%=1e3;const u=Math.trunc(t/100);t%=100;const c=Math.trunc(t/10),f=t%10;return i>0&&n.push(r[i-1]+"แสน"),s>0&&n.push(1===s?"หนึ่งหมื่น":r[s-1]+"หมื่น"),o>0&&n.push(r[o-1]+"พัน"),u>0&&n.push(r[u-1]+"ร้อย"),c>0&&n.push(1===c?"สิบ":2===c?"ยี่สิบ":r[c-1]+"สิบ"),f>0&&n.push(1===f&&(c>0||i>0||s>0||o>0||u>0||c>0)?"เอ็ด":r[f-1]),n.join("")}e.th=function(e){const{isNegative:o,integerPart:u,decimalPart:c}=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 o&&(f="ลบ"),f+=function(e){if(0n===e)return i;const t=function(e){const t=[];let n=e;const r=1000000n;for(;n>0n;){const e=Number(n%r);t.unshift(e),n/=r}return t}(e),n=[];for(let e=0;e<t.length;e++){const r=t[e];if(0===r)continue;n.push(s(r));const i=t.length-e-1;i>0&&n.push("ล้าน".repeat(i))}return n.join("")}(u),c&&(f+="จุด"+function(e){const t=[];for(const n of e){const e=parseInt(n,10);t.push(0===e?i:r[e-1])}return t.join("")}(c)),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=th.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"th.js","sources":["../../lib/utils/parse-numeric.js","../../lib/languages/th.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 * Thai language converter - Functional Implementation\n *\n * Self-contained converter with precomputed lookup tables.\n *\n * Key features:\n * - No word separators (continuous Thai script)\n * - Million-based grouping (ล้าน)\n * - Special handling for 1 as \"เอ็ด\" in compounds\n * - 20 is \"ยี่สิบ\" (not \"สองสิบ\")\n * - Per-digit decimal reading\n */\n\nimport { parseNumericValue } from '../utils/parse-numeric.js'\n\n// ============================================================================\n// Vocabulary\n// ============================================================================\n\nconst ONES = ['หนึ่ง', 'สอง', 'สาม', 'สี่', 'ห้า', 'หก', 'เจ็ด', 'แปด', 'เก้า']\n\nconst ZERO = 'ศูนย์'\nconst NEGATIVE = 'ลบ'\nconst DECIMAL_SEP = 'จุด'\n\n// ============================================================================\n// Conversion Functions\n// ============================================================================\n\nfunction convertBelowMillion (n) {\n if (n === 0) return ''\n\n let value = n\n const parts = []\n\n const hundredThousands = Math.trunc(value / 100000)\n value %= 100000\n const tenThousands = Math.trunc(value / 10000)\n value %= 10000\n const thousands = Math.trunc(value / 1000)\n value %= 1000\n const hundreds = Math.trunc(value / 100)\n value %= 100\n const tens = Math.trunc(value / 10)\n const ones = value % 10\n\n if (hundredThousands > 0) {\n parts.push(ONES[hundredThousands - 1] + 'แสน')\n }\n\n if (tenThousands > 0) {\n if (tenThousands === 1) {\n parts.push('หนึ่งหมื่น')\n } else {\n parts.push(ONES[tenThousands - 1] + 'หมื่น')\n }\n }\n\n if (thousands > 0) {\n parts.push(ONES[thousands - 1] + 'พัน')\n }\n\n if (hundreds > 0) {\n parts.push(ONES[hundreds - 1] + 'ร้อย')\n }\n\n if (tens > 0) {\n if (tens === 1) {\n parts.push('สิบ')\n } else if (tens === 2) {\n parts.push('ยี่สิบ')\n } else {\n parts.push(ONES[tens - 1] + 'สิบ')\n }\n }\n\n if (ones > 0) {\n const hasHigher = hundredThousands > 0 || tenThousands > 0 || thousands > 0 || hundreds > 0 || tens > 0\n if (ones === 1 && (tens > 0 || hasHigher)) {\n parts.push('เอ็ด')\n } else {\n parts.push(ONES[ones - 1])\n }\n }\n\n return parts.join('')\n}\n\nfunction splitMillionGroups (n) {\n const groups = []\n let remaining = n\n\n const million = 1_000_000n\n while (remaining > 0n) {\n const chunk = Number(remaining % million)\n groups.unshift(chunk)\n remaining = remaining / million\n }\n\n return groups\n}\n\nfunction integerToWords (n) {\n if (n === 0n) return ZERO\n\n const groups = splitMillionGroups(n)\n const parts = []\n\n for (let i = 0; i < groups.length; i++) {\n const groupValue = groups[i]\n if (groupValue === 0) continue\n\n parts.push(convertBelowMillion(groupValue))\n const remaining = groups.length - i - 1\n if (remaining > 0) {\n parts.push('ล้าน'.repeat(remaining))\n }\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 - 1])\n }\n return digits.join('')\n}\n\n/**\n * Converts a numeric value to Thai words.\n *\n * @param {number | string | bigint} value - The numeric value to convert\n * @returns {string} The number in Thai 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","ZERO","convertBelowMillion","n","value","parts","hundredThousands","Math","trunc","tenThousands","thousands","hundreds","tens","ones","push","join","type","Number","isFinite","Error","isSafeInteger","toString","includes","numberToString","trimmed","trim","isNaN","normalizeString","TypeError","parseNumericValue","result","groups","remaining","million","chunk","unshift","splitMillionGroups","i","groupValue","integerToWords","char","d","decimalPartToWords"],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- /*! n2words/tr v3.1.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=["","bir","iki","üç","dört","beş","altı","yedi","sekiz","dokuz"],i=["on","on bir","on iki","on üç","on dört","on beş","on altı","on yedi","on sekiz","on dokuz"],o=["","","yirmi","otuz","kırk","elli","altmış","yetmiş","seksen","doksan"],s="bin",u="sıfır",c=["milyon","milyar","trilyon","katrilyon","kentilyon"];function l(e,t=" "){if(0===e)return"";const n=e%10,s=Math.floor(e/10)%10,u=Math.floor(e/100),c=[];u>0&&c.push(1===u?"yüz":r[u]+t+"yüz");const l=e%100;return 0===l||c.push(l<10?r[n]:l<20?i[n].replace(" ",t):0===n?o[s]:o[s]+t+r[n]),c.join(t)}function f(e,t={}){if(0n===e)return u;const n=t.dropSpaces?"":" ";if(e<1000n)return l(Number(e),n);if(e<1000000n){const t=Number(e/1000n),r=Number(e%1000n);let i;return i=1===t?s:l(t,n)+n+s,r>0&&(i+=n+l(r,n)),i}return function(e,t){const n=t.dropSpaces?"":" ",r=e.toString(),i=r.length,o=[],u=i%3;let f=0;for(u>0&&(o.push(Number(r.slice(0,u))),f=u);f<i;)o.push(Number(r.slice(f,f+3))),f+=3;const a=[];let d=o.length-1;for(let e=0;e<o.length;e++){const t=o[e];if(0!==t){const e=l(t,n);a.push(0===d?e:1===d?1===t?s:e+n+s:e+n+c[d-2])}d--}return a.join(n)}(e,t)}e.tr=function(e,r){r=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)}(r);const{isNegative:i,integerPart:o,decimalPart:s}=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),c=r.dropSpaces?"":" ";let l="";return i&&(l="eksi"+c),l+=f(o,r),s&&(l+=c+"virgül"+c+function(e,t){const n=t.dropSpaces?"":" ";let r="",i=0;for(;i<e.length&&"0"===e[i];)r&&(r+=n),r+=u,i++;const o=e.slice(i);return o&&(r&&(r+=n),r+=f(BigInt(o),t)),r}(s,r)),l}},"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=tr.js.map