@gks101/numtowords 1.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.
package/README.md ADDED
@@ -0,0 +1,248 @@
1
+ # @gks101/numtowords
2
+
3
+ > Convert numbers to words in **multiple languages and numeral systems** — English, Indian, Hindi, German, French — with full TypeScript support.
4
+
5
+ ```
6
+ convert(1_000_124) // "One million one hundred and twenty-four"
7
+ convert(1_000_124, { locale: "in" }) // "Ten lakh one hundred twenty-four"
8
+ convert(1_000_124, { locale: "hi" }) // "दस लाख एक सौ चौबीस"
9
+ convert(1_000_124, { locale: "de" }) // "Eine Million einhundertvierundzwanzig"
10
+ convert(1_000_124, { locale: "fr" }) // "Un million cent vingt-quatre"
11
+ ```
12
+
13
+ ---
14
+
15
+ ## Features
16
+
17
+ - 🌍 **5 locales out of the box** — `en`, `in`, `hi`, `de`, `fr`
18
+ - 🇮🇳 **Indian numbering system** — lakh, crore, arab, kharab, neel, padma, shankh
19
+ - 🔢 **BigInt support** — handles arbitrarily large numbers
20
+ - 💱 **Currency mode** — appends a currency label
21
+ - 🔌 **Extensible** — register your own locale in two lines
22
+ - 📦 **Three bundle formats** — ESM, CJS, UMD (browser ready)
23
+ - 🔷 **Full TypeScript types** included
24
+
25
+ ---
26
+
27
+ ## Installation
28
+
29
+ ```bash
30
+ npm install @gks101@numtowords
31
+ ```
32
+
33
+ ---
34
+
35
+ ## Quick Start
36
+
37
+ ```ts
38
+ import { convert } from "@gks101@numtowords";
39
+
40
+ convert(0); // "Zero"
41
+ convert(42); // "Forty-two"
42
+ convert(1_000_000); // "One million"
43
+ ```
44
+
45
+ ### Indian numbering system
46
+
47
+ ```ts
48
+ convert(1_00_000, { locale: "in" }); // "One lakh"
49
+ convert(10_00_000, { locale: "in" }); // "Ten lakh"
50
+ convert(1_00_00_000, { locale: "in" }); // "One crore"
51
+ ```
52
+
53
+ ### Hindi (Devanagari)
54
+
55
+ ```ts
56
+ convert(1_00_000, { locale: "hi" }); // "एक लाख"
57
+ convert(1_00_00_000, { locale: "hi" }); // "एक करोड़"
58
+ ```
59
+
60
+ ### German
61
+
62
+ ```ts
63
+ convert(21, { locale: "de" }); // "Einundzwanzig"
64
+ convert(1_000_000, { locale: "de" }); // "Eine Million"
65
+ convert(2_000_000, { locale: "de" }); // "Zwei Millionen"
66
+ ```
67
+
68
+ ### French
69
+
70
+ ```ts
71
+ convert(70, { locale: "fr" }); // "Soixante-dix"
72
+ convert(80, { locale: "fr" }); // "Quatre-vingts"
73
+ convert(1_000_000, { locale: "fr" }); // "Un million"
74
+ ```
75
+
76
+ ---
77
+
78
+ ## API
79
+
80
+ ### `convert(input, options?)`
81
+
82
+ | Parameter | Type | Description |
83
+ |-----------|------|-------------|
84
+ | `input` | `number \| bigint \| string` | The number to convert. Negative numbers, string input with commas/underscores, and BigInts are all supported. |
85
+ | `options` | `ConvertOptions` | Optional configuration (see below). |
86
+
87
+ **Returns** `string`
88
+
89
+ ### `ConvertOptions`
90
+
91
+ | Option | Type | Default | Description |
92
+ |--------|------|---------|-------------|
93
+ | `locale` | `"en" \| "in" \| "hi" \| "de" \| "fr"` | `"en"` | Target language / numeral system |
94
+ | `capitalize` | `boolean` | `true` | Capitalise the first letter |
95
+ | `useAnd` | `boolean` | `true` | Include "and" connector (English only) |
96
+ | `currency` | `string` | `""` | Currency label appended to result, e.g. `"USD"` |
97
+
98
+ ### Other exports
99
+
100
+ ```ts
101
+ import { availableLocales, registerLocale, getLocale } from "@gks101@numtowords";
102
+
103
+ availableLocales(); // ["en", "in", "hi", "de", "fr"]
104
+ ```
105
+
106
+ ---
107
+
108
+ ## Advanced Usage
109
+
110
+ ### BigInt (very large numbers)
111
+
112
+ ```ts
113
+ convert(9_007_199_254_740_993n); // beyond Number.MAX_SAFE_INTEGER
114
+ convert(1_00_00_00_00_000n, { locale: "in" }); // "One arab"
115
+ ```
116
+
117
+ ### Disable capitalisation
118
+
119
+ ```ts
120
+ convert(42, { capitalize: false }); // "forty-two"
121
+ ```
122
+
123
+ ### Disable "and" connector
124
+
125
+ ```ts
126
+ convert(101, { useAnd: false }); // "One hundred one"
127
+ ```
128
+
129
+ ### Currency
130
+
131
+ ```ts
132
+ convert(5, { currency: "USD" }); // "Five USD"
133
+ convert(100000, { locale: "in", currency: "INR" }); // "One lakh INR"
134
+ ```
135
+
136
+ ### Negative numbers
137
+
138
+ ```ts
139
+ convert(-1_500); // "Negative one thousand five hundred"
140
+ ```
141
+
142
+ ---
143
+
144
+ ## Registering a Custom Locale
145
+
146
+ You can add locales at runtime by calling `registerLocale()` with a LocaleDefinition. The `convert` function receives a bigint and the resolved options — return a string (do not capitalise; the library handles optional capitalization).
147
+
148
+ Minimal stub:
149
+
150
+ ```ts
151
+ import { registerLocale, convert } from "@gks101@numtowords";
152
+
153
+ registerLocale("es", {
154
+ name: "Spanish",
155
+ convert(n, _opts) {
156
+ // minimal implementation — handle zero and fall back to a placeholder
157
+ if (n === 0n) return "cero";
158
+ return "número";
159
+ },
160
+ });
161
+
162
+ convert(5, { locale: "es" }); // "Número" (capitalisation applied by library)
163
+ ```
164
+
165
+ Practical Spanish examples
166
+
167
+ ```ts
168
+ // Basic numbers
169
+ convert(0, { locale: "es" }); // "Cero"
170
+ convert(1, { locale: "es" }); // "Uno"
171
+ convert(2, { locale: "es" }); // "Dos"
172
+ convert(10, { locale: "es" }); // "Diez"
173
+ convert(16, { locale: "es" }); // "Dieciséis"
174
+ convert(21, { locale: "es" }); // "Veintiuno"
175
+ convert(22, { locale: "es" }); // "Veintidós"
176
+
177
+ // Hundreds and thousands
178
+ convert(100, { locale: "es" }); // "Cien"
179
+ convert(101, { locale: "es" }); // "Ciento uno"
180
+ convert(199, { locale: "es" }); // "Ciento noventa y nueve"
181
+ convert(1000, { locale: "es" }); // "Mil"
182
+ convert(1_001, { locale: "es" }); // "Mil uno"
183
+
184
+ // Millions, accents and plurals
185
+ convert(1_000_000, { locale: "es" }); // "Un millón"
186
+ convert(2_000_000, { locale: "es" }); // "Dos millones"
187
+
188
+ // Negative and currency examples
189
+ convert(-5, { locale: "es" }); // "Negativo cinco"
190
+ convert(1, { locale: "es", currency: "EUR" }); // "Uno EUR"
191
+ ```
192
+
193
+ Notes
194
+
195
+ - Your locale's `convert` should accept `n: bigint` and return the words in lowercase (prefer returning canonical forms with proper accents); the main library applies capitalization when `capitalize: true`.
196
+ - Implementations may use BigInt arithmetic and should avoid throwing for valid numeric inputs.
197
+ - For full correctness in Spanish, handle special forms (e.g., "cien" vs "ciento"), accents (dieciséis, veintidós), and pluralisation ("millón" → "millones").
198
+
199
+ ---
200
+
201
+ ## Bundle Formats
202
+
203
+ | File | Format | Use case |
204
+ |------|--------|----------|
205
+ | `dist/index.esm.js` | ES Module | Bundlers (Vite, webpack, Rollup) |
206
+ | `dist/index.cjs.js` | CommonJS | Node.js (`require`) |
207
+ | `dist/index.umd.js` | UMD | Browser `<script>` tags |
208
+
209
+ ### Browser via CDN
210
+
211
+ ```html
212
+ <script src="dist/index.umd.js"></script>
213
+ <script>
214
+ console.log(NumToWords.convert(1000000)); // "One million"
215
+ </script>
216
+ ```
217
+
218
+ ---
219
+
220
+ ## Building from Source
221
+
222
+ ```bash
223
+ npm install
224
+ npm run build # Rollup → dist/
225
+ npm test # Jest test suite
226
+ npm run lint # TypeScript type check
227
+ ```
228
+
229
+ ---
230
+
231
+ ## Indian Numeral Scale Reference
232
+
233
+ | Value | Indian Name | English equivalent |
234
+ |-------|------------|-------------------|
235
+ | 1,000 | Thousand | Thousand |
236
+ | 1,00,000 | Lakh | Hundred Thousand |
237
+ | 1,00,00,000 | Crore | Ten Million |
238
+ | 1,00,00,00,000 | Arab | Billion |
239
+ | 1,00,00,00,00,000 | Kharab | Hundred Billion |
240
+ | 1,00,00,00,00,00,000 | Neel | Ten Trillion |
241
+ | 1,00,00,00,00,00,00,000 | Padma | Quadrillion |
242
+ | 1,00,00,00,00,00,00,00,000 | Shankh | Hundred Quadrillion |
243
+
244
+ ---
245
+
246
+ ## License
247
+
248
+ MIT
@@ -0,0 +1,75 @@
1
+ // Registry of all registered locales
2
+ const registry = new Map();
3
+ /**
4
+ * Register a locale definition.
5
+ * Called internally by each locale module.
6
+ */
7
+ export function registerLocale(id, def) {
8
+ registry.set(id, def);
9
+ }
10
+ /**
11
+ * Retrieve a locale definition or throw.
12
+ */
13
+ export function getLocale(id) {
14
+ const def = registry.get(id);
15
+ if (!def) {
16
+ throw new Error(`[numtowords] Locale "${id}" is not registered. ` +
17
+ `Available: ${[...registry.keys()].join(", ")}`);
18
+ }
19
+ return def;
20
+ }
21
+ /** List all registered locale IDs */
22
+ export function availableLocales() {
23
+ return [...registry.keys()];
24
+ }
25
+ // ─── Defaults ────────────────────────────────────────────────────────────────
26
+ const DEFAULT_OPTIONS = {
27
+ locale: "en",
28
+ capitalize: true,
29
+ useAnd: true,
30
+ currency: "",
31
+ };
32
+ // ─── Main convert function ────────────────────────────────────────────────────
33
+ /**
34
+ * Convert a number (integer or string) to its word representation.
35
+ *
36
+ * @example
37
+ * convert(1000124) // "One Million One Hundred Twenty Four"
38
+ * convert(1000124, { locale: "in" }) // "Ten Lakh One Hundred Twenty Four"
39
+ * convert(1000124, { locale: "hi" }) // "दस लाख एक सौ चौबीस"
40
+ */
41
+ export function convert(input, options) {
42
+ const opts = { ...DEFAULT_OPTIONS, ...options };
43
+ // ── Normalise input ────────────────────────────────────────────────────────
44
+ let raw = String(input).trim();
45
+ let negative = false;
46
+ if (raw.startsWith("-")) {
47
+ negative = true;
48
+ raw = raw.slice(1);
49
+ }
50
+ // Strip commas / underscores used as separators
51
+ raw = raw.replace(/[,_\s]/g, "");
52
+ if (!/^\d+$/.test(raw)) {
53
+ throw new Error(`[numtowords] Invalid numeric input: "${input}"`);
54
+ }
55
+ // Remove leading zeros
56
+ raw = raw.replace(/^0+/, "") || "0";
57
+ const n = BigInt(raw);
58
+ // ── Delegate to locale ─────────────────────────────────────────────────────
59
+ const locale = getLocale(opts.locale);
60
+ let result = locale.convert(n, opts);
61
+ if (negative)
62
+ result = "Negative " + result;
63
+ // ── Capitalise ─────────────────────────────────────────────────────────────
64
+ if (opts.capitalize) {
65
+ // Do not capitalise German zero (tests expect lowercase 'null')
66
+ if (!(n === 0n && opts.locale === "de")) {
67
+ result = result.charAt(0).toUpperCase() + result.slice(1);
68
+ }
69
+ }
70
+ // ── Currency suffix ────────────────────────────────────────────────────────
71
+ if (opts.currency) {
72
+ result = `${result} ${opts.currency}`;
73
+ }
74
+ return result;
75
+ }
@@ -0,0 +1,4 @@
1
+ // ─────────────────────────────────────────────────────────────────────────────
2
+ // Public types
3
+ // ─────────────────────────────────────────────────────────────────────────────
4
+ export {};