indickit 0.5.0 → 0.6.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 +53 -7
- package/dist/romanize.js +743 -0
- package/dist/types/js/romanize.d.ts +55 -0
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
Small, exact utilities for text in the languages of India, in Go and
|
|
4
4
|
TypeScript. They fix the places where ordinary string code goes wrong on
|
|
5
5
|
Indian text: a search that misses a word because it is spelled, encoded or
|
|
6
|
-
inflected another way,
|
|
6
|
+
inflected another way, a letter count that cuts a letter in two, and a name
|
|
7
|
+
that must be written in Latin letters.
|
|
7
8
|
|
|
8
9
|
```
|
|
9
10
|
stem किताब किताबें किताबों → किताब
|
|
10
11
|
phonetic राम ರಾಮ രാമ ராம رام Ram → rn
|
|
11
12
|
segment ಲಕ್ಷ್ಮಿ → ಲ ಕ್ಷ್ಮಿ
|
|
13
|
+
romanize लक्ष्मी ലക്ഷ്മി லக்ஷ்மி → lakshmi
|
|
12
14
|
```
|
|
13
15
|
|
|
14
16
|
Each utility gives the same output in Go and in TypeScript, and each was
|
|
@@ -23,6 +25,7 @@ measured on data that its rules were never built on.
|
|
|
23
25
|
| let a search for हिन्दी also find हिंदी, and keep words whole | `fold` |
|
|
24
26
|
| find a person's name typed in another script | `phonetic` |
|
|
25
27
|
| count letters, cut at a length, or move a cursor | `segment` |
|
|
28
|
+
| write a name or a text in Latin letters (लक्ष्मी → lakshmi) | `romanize` |
|
|
26
29
|
|
|
27
30
|
## Install
|
|
28
31
|
|
|
@@ -47,13 +50,20 @@ TypeScript, set `moduleResolution` to `nodenext` or `bundler`; the old
|
|
|
47
50
|
In a browser, with no build step:
|
|
48
51
|
|
|
49
52
|
```js
|
|
50
|
-
import { normalize } from "https://cdn.jsdelivr.net/gh/micahchoo/indickit@v0.
|
|
51
|
-
import { stem } from "https://cdn.jsdelivr.net/gh/micahchoo/indickit@v0.
|
|
52
|
-
import { match } from "https://cdn.jsdelivr.net/gh/micahchoo/indickit@v0.
|
|
53
|
-
import { segment } from "https://cdn.jsdelivr.net/gh/micahchoo/indickit@v0.
|
|
53
|
+
import { normalize } from "https://cdn.jsdelivr.net/gh/micahchoo/indickit@v0.6.0/dist/normalize.js";
|
|
54
|
+
import { stem } from "https://cdn.jsdelivr.net/gh/micahchoo/indickit@v0.6.0/dist/stem.js";
|
|
55
|
+
import { match } from "https://cdn.jsdelivr.net/gh/micahchoo/indickit@v0.6.0/dist/phonetic.js";
|
|
56
|
+
import { segment } from "https://cdn.jsdelivr.net/gh/micahchoo/indickit@v0.6.0/dist/segment.js";
|
|
57
|
+
import { load } from "https://cdn.jsdelivr.net/gh/micahchoo/indickit@v0.6.0/dist/romanize.js";
|
|
54
58
|
```
|
|
55
59
|
|
|
56
60
|
Each utility is its own file, so a page loads only the rules it uses.
|
|
61
|
+
`romanize` also loads one language's tables when you ask for them (0.2–1.8
|
|
62
|
+
MB). The npm package carries no tables: `load()` reads them beside the
|
|
63
|
+
module (a jsDelivr or GitHub-tag install), else from jsDelivr at the same
|
|
64
|
+
version. Offline, pass your own `fetch`. In Go, `go get` downloads the
|
|
65
|
+
tables of every language once (14 MB); a program carries only the languages
|
|
66
|
+
it imports.
|
|
57
67
|
|
|
58
68
|
## Recipes
|
|
59
69
|
|
|
@@ -152,6 +162,33 @@ segment("ਕ੍ਕ"); // ["ਕ੍","ਕ"]: Gurmukhi shows this virama, so these
|
|
|
152
162
|
count("ಕನ್ನಡ"); // 3
|
|
153
163
|
```
|
|
154
164
|
|
|
165
|
+
### Write it in Latin letters
|
|
166
|
+
|
|
167
|
+
`romanize` gives a ranked list of spellings, most likely first. Use the
|
|
168
|
+
`"words"` mode for text and the `"names"` mode for a field that holds a
|
|
169
|
+
person's name:
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
import { load } from "indickit/romanize";
|
|
173
|
+
|
|
174
|
+
const hi = await load("hi"); // fetches the Hindi tables
|
|
175
|
+
hi.word("लक्ष्मी", 2); // ["lakshmi","laxmi"]
|
|
176
|
+
hi.text("भारत के प्रधानमंत्री"); // "bharat ke pradhaanmantri"
|
|
177
|
+
const ur = await load("ur", "names");
|
|
178
|
+
ur.word("پرویز", 1); // ["parvez"]
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
In Go, import the languages you need; a program carries only their tables:
|
|
182
|
+
|
|
183
|
+
```go
|
|
184
|
+
import (
|
|
185
|
+
"github.com/micahchoo/indickit/romanize"
|
|
186
|
+
_ "github.com/micahchoo/indickit/romanize/lang/hi"
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
romanize.Word("लक्ष्मी", "hi", romanize.Words, 2) // [lakshmi laxmi]
|
|
190
|
+
```
|
|
191
|
+
|
|
155
192
|
### The same in Go
|
|
156
193
|
|
|
157
194
|
```go
|
|
@@ -182,6 +219,9 @@ segment.Segment("ಲಕ್ಷ್ಮಿ") // [ಲ ಕ್ಷ
|
|
|
182
219
|
| `phonetic.Words(name)` | `words(name)` | the words, split as the others split them |
|
|
183
220
|
| `segment.Segment(s)` | `segment(text)` | the letters, in order; joined, they give the text back |
|
|
184
221
|
| `segment.Count(s)` | `count(text)` | how many letters a reader sees |
|
|
222
|
+
| `romanize.Word(w, lang, mode, n)` | `(await load(lang, mode)).word(w, n?)` | up to n spellings, most likely first |
|
|
223
|
+
| `romanize.Text(s, lang, mode)` | `(await load(lang, mode)).text(text)` | each word of the language's script in Latin letters |
|
|
224
|
+
| `romanize.Languages(mode)` | `languages(mode)` | the languages with tables (Go: those imported) |
|
|
185
225
|
|
|
186
226
|
Three things hold for all of them:
|
|
187
227
|
|
|
@@ -208,6 +248,7 @@ other tools tried and each weak spot are in `docs/`.
|
|
|
208
248
|
| `stem` | finds 6–15 points more of the right sentences than exact search, in 13 languages | ahead in 5 languages, level in 2, a trade in 4, behind in Nepali | 3 KB | [docs/stem.md](docs/stem.md) |
|
|
209
249
|
| `phonetic` | finds the right person 84% of the time, in 21 languages, on clean names; 42% on a real roster as written (70% with titles and initials removed) | romanize + Soundex: 23% in Tamil, 70% in Hindi; cannot read Urdu | 4 KB | [docs/phonetic.md](docs/phonetic.md) |
|
|
210
250
|
| `segment` | cuts 0.05% of Kannada words wrongly | `Intl.Segmenter`: 50.3% | 9 KB | [docs/segment.md](docs/segment.md) |
|
|
251
|
+
| `romanize` | writes 48.9% of the words of running text as people typed them, in 11 languages; 71.3% of names (tables: 0.2–1.8 MB a language) | IndicXlit (Python, a 119 MB model): 37.9% and 49.0% | 5 KB | [docs/romanize.md](docs/romanize.md) |
|
|
211
252
|
|
|
212
253
|
(Browser files are gzipped.)
|
|
213
254
|
|
|
@@ -231,6 +272,9 @@ other tools tried and each weak spot are in `docs/`.
|
|
|
231
272
|
- **Some languages have no table.** `stem` covers 13 languages; Bodo,
|
|
232
273
|
Dogri, Kashmiri, Konkani, Maithili, Manipuri, Odia, Santali and Sindhi
|
|
233
274
|
are not among them.
|
|
275
|
+
- **`romanize` is behind IndicXlit on places and on rare single words**
|
|
276
|
+
(by 7–13 and 5.5 points). Santali has names only; Bodo and Dogri have
|
|
277
|
+
text only. See [docs/romanize.md](docs/romanize.md).
|
|
234
278
|
- **Go reads invalid UTF-8 as U+FFFD**, so for such input the output does
|
|
235
279
|
not join back into the original bytes.
|
|
236
280
|
- **"The same output" holds inside the blocks indickit reads.** Go reads
|
|
@@ -249,10 +293,12 @@ Each utility's own weak spots are at the end of its file in `docs/`.
|
|
|
249
293
|
|
|
250
294
|
Every table and switch of a utility is in its rules file
|
|
251
295
|
(`normalize/rules.json`, `stem/rules.json`, `phonetic/rules.json`,
|
|
252
|
-
`segment/rules.json`
|
|
296
|
+
`segment/rules.json`; `romanize/rules.json` and its tables in
|
|
297
|
+
`romanize/lang/`); the Go and TypeScript code is a short loop over it.
|
|
253
298
|
Both are checked against a conformance file of inputs with the outputs that
|
|
254
299
|
a reference implementation gave them: 345,276 inputs for `normalize`,
|
|
255
|
-
418,665 for `stem`, 195,994 for `phonetic`, 858,654 for `segment
|
|
300
|
+
418,665 for `stem`, 195,994 for `phonetic`, 858,654 for `segment`, 2,397
|
|
301
|
+
for `romanize`
|
|
256
302
|
(`*/testdata/conformance.jsonl.gz`). A change that makes any one disagree
|
|
257
303
|
on any input fails the build.
|
|
258
304
|
|
package/dist/romanize.js
ADDED
|
@@ -0,0 +1,743 @@
|
|
|
1
|
+
// romanize/rules.json
|
|
2
|
+
var rules_default = {
|
|
3
|
+
beam: {
|
|
4
|
+
names: 12,
|
|
5
|
+
words: 8
|
|
6
|
+
},
|
|
7
|
+
bos: "<s>",
|
|
8
|
+
eos: "</s>",
|
|
9
|
+
families: {
|
|
10
|
+
names: {
|
|
11
|
+
as: {
|
|
12
|
+
file: "as.names.bin",
|
|
13
|
+
group: "brahmic",
|
|
14
|
+
lookup: 669,
|
|
15
|
+
pooled: "names-brahmic.bin",
|
|
16
|
+
tag: "as"
|
|
17
|
+
},
|
|
18
|
+
bn: {
|
|
19
|
+
file: "bn.names.bin",
|
|
20
|
+
group: "brahmic",
|
|
21
|
+
lookup: 1785,
|
|
22
|
+
pooled: "names-brahmic.bin",
|
|
23
|
+
tag: "bn"
|
|
24
|
+
},
|
|
25
|
+
gom: {
|
|
26
|
+
file: "gom.names.bin",
|
|
27
|
+
group: "brahmic",
|
|
28
|
+
lookup: 17,
|
|
29
|
+
pooled: "names-brahmic.bin",
|
|
30
|
+
tag: "gom"
|
|
31
|
+
},
|
|
32
|
+
gu: {
|
|
33
|
+
file: "gu.names.bin",
|
|
34
|
+
group: "brahmic",
|
|
35
|
+
lookup: 131,
|
|
36
|
+
pooled: "names-brahmic.bin",
|
|
37
|
+
tag: "gu"
|
|
38
|
+
},
|
|
39
|
+
hi: {
|
|
40
|
+
file: "hi.names.bin",
|
|
41
|
+
group: "brahmic",
|
|
42
|
+
lookup: 1152,
|
|
43
|
+
pooled: "names-brahmic.bin",
|
|
44
|
+
tag: "hi"
|
|
45
|
+
},
|
|
46
|
+
kn: {
|
|
47
|
+
file: "kn.names.bin",
|
|
48
|
+
group: "brahmic",
|
|
49
|
+
lookup: 448,
|
|
50
|
+
pooled: "names-brahmic.bin",
|
|
51
|
+
tag: "kn"
|
|
52
|
+
},
|
|
53
|
+
ks: {
|
|
54
|
+
file: "ks.names.bin",
|
|
55
|
+
group: "arabic",
|
|
56
|
+
lookup: 130,
|
|
57
|
+
pooled: "names-arabic.bin",
|
|
58
|
+
tag: "ks"
|
|
59
|
+
},
|
|
60
|
+
mai: {
|
|
61
|
+
file: "mai.names.bin",
|
|
62
|
+
group: "brahmic",
|
|
63
|
+
lookup: 150,
|
|
64
|
+
pooled: "names-brahmic.bin",
|
|
65
|
+
tag: "mai"
|
|
66
|
+
},
|
|
67
|
+
ml: {
|
|
68
|
+
file: "ml.names.bin",
|
|
69
|
+
group: "brahmic",
|
|
70
|
+
lookup: 908,
|
|
71
|
+
pooled: "names-brahmic.bin",
|
|
72
|
+
tag: "ml"
|
|
73
|
+
},
|
|
74
|
+
mni: {
|
|
75
|
+
file: "mni.names.bin",
|
|
76
|
+
group: "meetei",
|
|
77
|
+
lookup: 253,
|
|
78
|
+
pooled: "names-meetei.bin",
|
|
79
|
+
tag: "mni"
|
|
80
|
+
},
|
|
81
|
+
mr: {
|
|
82
|
+
file: "mr.names.bin",
|
|
83
|
+
group: "brahmic",
|
|
84
|
+
lookup: 716,
|
|
85
|
+
pooled: "names-brahmic.bin",
|
|
86
|
+
tag: "mr"
|
|
87
|
+
},
|
|
88
|
+
ne: {
|
|
89
|
+
file: "ne.names.bin",
|
|
90
|
+
group: "brahmic",
|
|
91
|
+
lookup: 146,
|
|
92
|
+
pooled: "names-brahmic.bin",
|
|
93
|
+
tag: "ne"
|
|
94
|
+
},
|
|
95
|
+
or: {
|
|
96
|
+
file: "or.names.bin",
|
|
97
|
+
group: "brahmic",
|
|
98
|
+
lookup: 610,
|
|
99
|
+
pooled: "names-brahmic.bin",
|
|
100
|
+
tag: "or"
|
|
101
|
+
},
|
|
102
|
+
pa: {
|
|
103
|
+
file: "pa.names.bin",
|
|
104
|
+
group: "brahmic",
|
|
105
|
+
lookup: 996,
|
|
106
|
+
pooled: "names-brahmic.bin",
|
|
107
|
+
tag: "pa"
|
|
108
|
+
},
|
|
109
|
+
sa: {
|
|
110
|
+
file: "sa.names.bin",
|
|
111
|
+
group: "brahmic",
|
|
112
|
+
lookup: 66,
|
|
113
|
+
pooled: "names-brahmic.bin",
|
|
114
|
+
tag: "sa"
|
|
115
|
+
},
|
|
116
|
+
sat: {
|
|
117
|
+
file: "sat.names.bin",
|
|
118
|
+
group: "olchiki",
|
|
119
|
+
lookup: 407,
|
|
120
|
+
pooled: "names-olchiki.bin",
|
|
121
|
+
tag: "sat"
|
|
122
|
+
},
|
|
123
|
+
sd: {
|
|
124
|
+
file: "sd.names.bin",
|
|
125
|
+
group: "arabic",
|
|
126
|
+
lookup: 72,
|
|
127
|
+
pooled: "names-arabic.bin",
|
|
128
|
+
tag: "sd"
|
|
129
|
+
},
|
|
130
|
+
ta: {
|
|
131
|
+
file: "ta.names.bin",
|
|
132
|
+
group: "brahmic",
|
|
133
|
+
lookup: 3961,
|
|
134
|
+
pooled: "names-brahmic.bin",
|
|
135
|
+
tag: "ta"
|
|
136
|
+
},
|
|
137
|
+
te: {
|
|
138
|
+
file: "te.names.bin",
|
|
139
|
+
group: "brahmic",
|
|
140
|
+
lookup: 2126,
|
|
141
|
+
pooled: "names-brahmic.bin",
|
|
142
|
+
tag: "te"
|
|
143
|
+
},
|
|
144
|
+
ur: {
|
|
145
|
+
file: "ur.names.bin",
|
|
146
|
+
group: "arabic",
|
|
147
|
+
lookup: 1961,
|
|
148
|
+
pooled: "names-arabic.bin",
|
|
149
|
+
tag: "ur"
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
words: {
|
|
153
|
+
as: {
|
|
154
|
+
file: "as.words.bin",
|
|
155
|
+
group: "brahmic",
|
|
156
|
+
lookup: 0,
|
|
157
|
+
pooled: "words-brahmic.bin",
|
|
158
|
+
tag: "as:w"
|
|
159
|
+
},
|
|
160
|
+
bn: {
|
|
161
|
+
file: "bn.words.bin",
|
|
162
|
+
group: "brahmic",
|
|
163
|
+
lookup: 0,
|
|
164
|
+
pooled: "words-brahmic.bin",
|
|
165
|
+
tag: "bn:w"
|
|
166
|
+
},
|
|
167
|
+
brx: {
|
|
168
|
+
file: "brx.words.bin",
|
|
169
|
+
group: "brahmic",
|
|
170
|
+
lookup: 0,
|
|
171
|
+
pooled: "words-brahmic.bin",
|
|
172
|
+
tag: "brx:w"
|
|
173
|
+
},
|
|
174
|
+
doi: {
|
|
175
|
+
file: "doi.words.bin",
|
|
176
|
+
group: "brahmic",
|
|
177
|
+
lookup: 0,
|
|
178
|
+
pooled: "words-brahmic.bin",
|
|
179
|
+
tag: "doi:w"
|
|
180
|
+
},
|
|
181
|
+
gom: {
|
|
182
|
+
file: "gom.words.bin",
|
|
183
|
+
group: "brahmic",
|
|
184
|
+
lookup: 0,
|
|
185
|
+
pooled: "words-brahmic.bin",
|
|
186
|
+
tag: "gom:w"
|
|
187
|
+
},
|
|
188
|
+
gu: {
|
|
189
|
+
file: "gu.words.bin",
|
|
190
|
+
group: "brahmic",
|
|
191
|
+
lookup: 0,
|
|
192
|
+
pooled: "words-brahmic.bin",
|
|
193
|
+
tag: "gu:w"
|
|
194
|
+
},
|
|
195
|
+
hi: {
|
|
196
|
+
file: "hi.words.bin",
|
|
197
|
+
group: "brahmic",
|
|
198
|
+
lookup: 0,
|
|
199
|
+
pooled: "words-brahmic.bin",
|
|
200
|
+
tag: "hi:w"
|
|
201
|
+
},
|
|
202
|
+
kn: {
|
|
203
|
+
file: "kn.words.bin",
|
|
204
|
+
group: "brahmic",
|
|
205
|
+
lookup: 0,
|
|
206
|
+
pooled: "words-brahmic.bin",
|
|
207
|
+
tag: "kn:w"
|
|
208
|
+
},
|
|
209
|
+
ks: {
|
|
210
|
+
file: "ks.words.bin",
|
|
211
|
+
group: "arabic",
|
|
212
|
+
lookup: 0,
|
|
213
|
+
pooled: "words-arabic.bin",
|
|
214
|
+
tag: "ks:w"
|
|
215
|
+
},
|
|
216
|
+
mai: {
|
|
217
|
+
file: "mai.words.bin",
|
|
218
|
+
group: "brahmic",
|
|
219
|
+
lookup: 0,
|
|
220
|
+
pooled: "words-brahmic.bin",
|
|
221
|
+
tag: "mai:w"
|
|
222
|
+
},
|
|
223
|
+
ml: {
|
|
224
|
+
file: "ml.words.bin",
|
|
225
|
+
group: "brahmic",
|
|
226
|
+
lookup: 0,
|
|
227
|
+
pooled: "words-brahmic.bin",
|
|
228
|
+
tag: "ml:w"
|
|
229
|
+
},
|
|
230
|
+
mni: {
|
|
231
|
+
file: "mni.words.bin",
|
|
232
|
+
group: "meetei",
|
|
233
|
+
lookup: 0,
|
|
234
|
+
pooled: "words-meetei.bin",
|
|
235
|
+
tag: "mni:w"
|
|
236
|
+
},
|
|
237
|
+
mr: {
|
|
238
|
+
file: "mr.words.bin",
|
|
239
|
+
group: "brahmic",
|
|
240
|
+
lookup: 0,
|
|
241
|
+
pooled: "words-brahmic.bin",
|
|
242
|
+
tag: "mr:w"
|
|
243
|
+
},
|
|
244
|
+
ne: {
|
|
245
|
+
file: "ne.words.bin",
|
|
246
|
+
group: "brahmic",
|
|
247
|
+
lookup: 0,
|
|
248
|
+
pooled: "words-brahmic.bin",
|
|
249
|
+
tag: "ne:w"
|
|
250
|
+
},
|
|
251
|
+
or: {
|
|
252
|
+
file: "or.words.bin",
|
|
253
|
+
group: "brahmic",
|
|
254
|
+
lookup: 0,
|
|
255
|
+
pooled: "words-brahmic.bin",
|
|
256
|
+
tag: "or:w"
|
|
257
|
+
},
|
|
258
|
+
pa: {
|
|
259
|
+
file: "pa.words.bin",
|
|
260
|
+
group: "brahmic",
|
|
261
|
+
lookup: 0,
|
|
262
|
+
pooled: "words-brahmic.bin",
|
|
263
|
+
tag: "pa:w"
|
|
264
|
+
},
|
|
265
|
+
sa: {
|
|
266
|
+
file: "sa.words.bin",
|
|
267
|
+
group: "brahmic",
|
|
268
|
+
lookup: 0,
|
|
269
|
+
pooled: "words-brahmic.bin",
|
|
270
|
+
tag: "sa:w"
|
|
271
|
+
},
|
|
272
|
+
sd: {
|
|
273
|
+
file: "sd.words.bin",
|
|
274
|
+
group: "arabic",
|
|
275
|
+
lookup: 0,
|
|
276
|
+
pooled: "words-arabic.bin",
|
|
277
|
+
tag: "sd:w"
|
|
278
|
+
},
|
|
279
|
+
ta: {
|
|
280
|
+
file: "ta.words.bin",
|
|
281
|
+
group: "brahmic",
|
|
282
|
+
lookup: 0,
|
|
283
|
+
pooled: "words-brahmic.bin",
|
|
284
|
+
tag: "ta:w"
|
|
285
|
+
},
|
|
286
|
+
te: {
|
|
287
|
+
file: "te.words.bin",
|
|
288
|
+
group: "brahmic",
|
|
289
|
+
lookup: 0,
|
|
290
|
+
pooled: "words-brahmic.bin",
|
|
291
|
+
tag: "te:w"
|
|
292
|
+
},
|
|
293
|
+
ur: {
|
|
294
|
+
file: "ur.words.bin",
|
|
295
|
+
group: "arabic",
|
|
296
|
+
lookup: 0,
|
|
297
|
+
pooled: "words-arabic.bin",
|
|
298
|
+
tag: "ur:w"
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
},
|
|
302
|
+
files: {
|
|
303
|
+
"as.names.bin": 89974,
|
|
304
|
+
"as.words.bin": 235757,
|
|
305
|
+
"bn.names.bin": 182011,
|
|
306
|
+
"bn.words.bin": 377491,
|
|
307
|
+
"brx.words.bin": 208654,
|
|
308
|
+
"doi.words.bin": 48681,
|
|
309
|
+
"gom.names.bin": 9361,
|
|
310
|
+
"gom.words.bin": 324293,
|
|
311
|
+
"gu.names.bin": 38634,
|
|
312
|
+
"gu.words.bin": 370117,
|
|
313
|
+
"hi.names.bin": 162471,
|
|
314
|
+
"hi.words.bin": 468425,
|
|
315
|
+
"kn.names.bin": 73095,
|
|
316
|
+
"kn.words.bin": 273776,
|
|
317
|
+
"ks.names.bin": 36223,
|
|
318
|
+
"ks.words.bin": 445883,
|
|
319
|
+
"mai.names.bin": 40421,
|
|
320
|
+
"mai.words.bin": 381362,
|
|
321
|
+
"ml.names.bin": 133130,
|
|
322
|
+
"ml.words.bin": 342656,
|
|
323
|
+
"mni.names.bin": 12382,
|
|
324
|
+
"mni.words.bin": 133350,
|
|
325
|
+
"mr.names.bin": 119082,
|
|
326
|
+
"mr.words.bin": 327753,
|
|
327
|
+
"names-arabic.bin": 188775,
|
|
328
|
+
"names-brahmic.bin": 594055,
|
|
329
|
+
"names-meetei.bin": 43805,
|
|
330
|
+
"names-olchiki.bin": 97591,
|
|
331
|
+
"ne.names.bin": 37468,
|
|
332
|
+
"ne.words.bin": 297072,
|
|
333
|
+
"or.names.bin": 83867,
|
|
334
|
+
"or.words.bin": 285972,
|
|
335
|
+
"pa.names.bin": 140045,
|
|
336
|
+
"pa.words.bin": 419426,
|
|
337
|
+
"sa.names.bin": 24600,
|
|
338
|
+
"sa.words.bin": 243993,
|
|
339
|
+
"sat.names.bin": 73397,
|
|
340
|
+
"sd.names.bin": 11896,
|
|
341
|
+
"sd.words.bin": 463475,
|
|
342
|
+
"ta.names.bin": 295030,
|
|
343
|
+
"ta.words.bin": 244532,
|
|
344
|
+
"te.names.bin": 229077,
|
|
345
|
+
"te.words.bin": 295013,
|
|
346
|
+
"ur.names.bin": 192400,
|
|
347
|
+
"ur.words.bin": 540255,
|
|
348
|
+
"words-arabic.bin": 1182486,
|
|
349
|
+
"words-brahmic.bin": 2542643,
|
|
350
|
+
"words-meetei.bin": 198229,
|
|
351
|
+
"words-olchiki.bin": 61705
|
|
352
|
+
},
|
|
353
|
+
groups: {
|
|
354
|
+
arabic: [
|
|
355
|
+
1536,
|
|
356
|
+
1791
|
|
357
|
+
],
|
|
358
|
+
brahmic: [
|
|
359
|
+
2304,
|
|
360
|
+
3455
|
|
361
|
+
],
|
|
362
|
+
meetei: [
|
|
363
|
+
43744,
|
|
364
|
+
44031
|
|
365
|
+
],
|
|
366
|
+
olchiki: [
|
|
367
|
+
7248,
|
|
368
|
+
7295
|
|
369
|
+
]
|
|
370
|
+
},
|
|
371
|
+
max_n: 3,
|
|
372
|
+
order: 3,
|
|
373
|
+
rules_version: "2026-10-07",
|
|
374
|
+
unify: {
|
|
375
|
+
from: [
|
|
376
|
+
2432,
|
|
377
|
+
3455
|
|
378
|
+
],
|
|
379
|
+
mask: 127,
|
|
380
|
+
to_block: 2304
|
|
381
|
+
},
|
|
382
|
+
unknown_penalty: 20,
|
|
383
|
+
version: 1
|
|
384
|
+
};
|
|
385
|
+
// package.json
|
|
386
|
+
var version = "0.6.0";
|
|
387
|
+
|
|
388
|
+
// js/lang.ts
|
|
389
|
+
var ISO_639_2 = "asm as ben bn guj gu hin hi kan kn kas ks mal ml mar mr nep ne ori or pan pa san sa snd sd tam ta tel te urd ur ";
|
|
390
|
+
function langCode(tag) {
|
|
391
|
+
const t = (tag ?? "").toLowerCase().split(/[-_]/)[0];
|
|
392
|
+
const i = t.length === 3 ? ISO_639_2.indexOf(t + " ") : -1;
|
|
393
|
+
return i >= 0 && i % 7 === 0 ? ISO_639_2.slice(i + 4, i + 6) : t;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// js/romanize.ts
|
|
397
|
+
var RULES = rules_default;
|
|
398
|
+
var RULES_VERSION = RULES.rules_version;
|
|
399
|
+
function languages(mode = "words") {
|
|
400
|
+
return Object.keys(RULES.families[mode]).sort();
|
|
401
|
+
}
|
|
402
|
+
var CDN = `https://cdn.jsdelivr.net/gh/micahchoo/indickit@v${version}/romanize/lang/`;
|
|
403
|
+
async function fetchBytes(url) {
|
|
404
|
+
const res = await fetch(url);
|
|
405
|
+
if (!res.ok)
|
|
406
|
+
throw new Error(`romanize: ${url}: ${res.status}`);
|
|
407
|
+
return res.arrayBuffer();
|
|
408
|
+
}
|
|
409
|
+
function defaultFetcher(local) {
|
|
410
|
+
return async (url) => {
|
|
411
|
+
try {
|
|
412
|
+
return await fetchBytes(url);
|
|
413
|
+
} catch {
|
|
414
|
+
return fetchBytes(new URL(url.href.slice(local.href.length), CDN));
|
|
415
|
+
}
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
function code(lang) {
|
|
419
|
+
const c = langCode(lang);
|
|
420
|
+
return c === "kok" ? "gom" : c;
|
|
421
|
+
}
|
|
422
|
+
var pooledCache = new Map;
|
|
423
|
+
async function load(lang, mode = "words", opts = {}) {
|
|
424
|
+
const c = code(lang);
|
|
425
|
+
const l = RULES.families[mode][c];
|
|
426
|
+
if (!l)
|
|
427
|
+
throw new Error(`romanize: no ${mode} tables for "${lang}"`);
|
|
428
|
+
const base = new URL(opts.base ?? "../romanize/lang/", import.meta.url);
|
|
429
|
+
const get = opts.fetch ?? (opts.base ? fetchBytes : defaultFetcher(base));
|
|
430
|
+
const poolKey = `${base}${l.group}/${l.pooled}`;
|
|
431
|
+
if (!pooledCache.has(poolKey))
|
|
432
|
+
pooledCache.set(poolKey, get(new URL(`${l.group}/${l.pooled}`, base)));
|
|
433
|
+
const [own, pool] = await Promise.all([get(new URL(`${c}/${l.file}`, base)), pooledCache.get(poolKey)]);
|
|
434
|
+
return fromBytes(c, mode, new Uint8Array(own), new Uint8Array(pool));
|
|
435
|
+
}
|
|
436
|
+
function fromBytes(lang, mode, own, pool) {
|
|
437
|
+
const l = RULES.families[mode][lang];
|
|
438
|
+
if (!l)
|
|
439
|
+
throw new Error(`romanize: no ${mode} tables for "${lang}"`);
|
|
440
|
+
const x = new Mix(own, pool, l.tag, RULES.beam[mode]);
|
|
441
|
+
const [lo, hi] = RULES.groups[l.group];
|
|
442
|
+
const inScript = (ch) => {
|
|
443
|
+
const cp = ch.codePointAt(0);
|
|
444
|
+
return cp >= lo && cp <= hi || cp === 8204 || cp === 8205;
|
|
445
|
+
};
|
|
446
|
+
const letter = /[\p{L}\p{M}]/u;
|
|
447
|
+
const word = (w, n = 4) => {
|
|
448
|
+
const s = w.normalize("NFC");
|
|
449
|
+
const known = x.lookup.get(s);
|
|
450
|
+
if (known)
|
|
451
|
+
return known.slice(0, n);
|
|
452
|
+
return x.decode(unify(s), n).filter((o) => o !== "");
|
|
453
|
+
};
|
|
454
|
+
const r = {
|
|
455
|
+
lang,
|
|
456
|
+
mode,
|
|
457
|
+
word,
|
|
458
|
+
text(t) {
|
|
459
|
+
const cs = [...t.normalize("NFC")];
|
|
460
|
+
let out = "";
|
|
461
|
+
for (let i = 0;i < cs.length; ) {
|
|
462
|
+
if (!(inScript(cs[i]) && letter.test(cs[i]))) {
|
|
463
|
+
out += cs[i++];
|
|
464
|
+
continue;
|
|
465
|
+
}
|
|
466
|
+
let j = i;
|
|
467
|
+
while (j < cs.length && inScript(cs[j]) && letter.test(cs[j]))
|
|
468
|
+
j++;
|
|
469
|
+
const run = cs.slice(i, j).join("");
|
|
470
|
+
out += word(run, 1)[0] ?? run;
|
|
471
|
+
i = j;
|
|
472
|
+
}
|
|
473
|
+
return out;
|
|
474
|
+
}
|
|
475
|
+
};
|
|
476
|
+
Object.defineProperty(r, "_mix", { value: x });
|
|
477
|
+
return r;
|
|
478
|
+
}
|
|
479
|
+
function unify(w) {
|
|
480
|
+
const u = RULES.unify;
|
|
481
|
+
let out = "";
|
|
482
|
+
for (const ch of w) {
|
|
483
|
+
const cp = ch.codePointAt(0);
|
|
484
|
+
out += cp >= u.from[0] && cp <= u.from[1] ? String.fromCodePoint(u.to_block + (cp & u.mask)) : ch;
|
|
485
|
+
}
|
|
486
|
+
return out;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
class Reader {
|
|
490
|
+
b;
|
|
491
|
+
pos = 4;
|
|
492
|
+
constructor(b) {
|
|
493
|
+
this.b = b;
|
|
494
|
+
if (b[0] !== 73 || b[1] !== 75 || b[2] !== 82 || b[3] !== 49)
|
|
495
|
+
throw new Error("romanize: not an IKR1 file");
|
|
496
|
+
}
|
|
497
|
+
varint() {
|
|
498
|
+
let v = 0;
|
|
499
|
+
let shift = 1;
|
|
500
|
+
for (;; ) {
|
|
501
|
+
const byte = this.b[this.pos++];
|
|
502
|
+
v += (byte & 127) * shift;
|
|
503
|
+
if (byte < 128)
|
|
504
|
+
return v;
|
|
505
|
+
shift *= 128;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
str() {
|
|
509
|
+
const n = this.varint();
|
|
510
|
+
const s = DECODER.decode(this.b.subarray(this.pos, this.pos + n));
|
|
511
|
+
this.pos += n;
|
|
512
|
+
return s;
|
|
513
|
+
}
|
|
514
|
+
float64() {
|
|
515
|
+
const v = new DataView(this.b.buffer, this.b.byteOffset + this.pos, 8).getFloat64(0, true);
|
|
516
|
+
this.pos += 8;
|
|
517
|
+
return v;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
var DECODER = new TextDecoder;
|
|
521
|
+
var ID = 2 ** 21;
|
|
522
|
+
function ctxKey(ctx, from) {
|
|
523
|
+
let k = 0;
|
|
524
|
+
for (let i = from;i < ctx.length; i++)
|
|
525
|
+
k = k * ID + (ctx[i] + 1);
|
|
526
|
+
return k;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
class Model {
|
|
530
|
+
vocab;
|
|
531
|
+
levels = [];
|
|
532
|
+
constructor(r, strs, ids) {
|
|
533
|
+
this.vocab = r.varint();
|
|
534
|
+
for (let l = r.varint();l > 0; l--) {
|
|
535
|
+
const lv = { stats: new Map, counts: new Map };
|
|
536
|
+
for (let c = r.varint();c > 0; c--) {
|
|
537
|
+
const ctx = [];
|
|
538
|
+
for (let i = r.varint();i > 0; i--)
|
|
539
|
+
ctx.push(ids.id(strs[r.varint()]));
|
|
540
|
+
const key = ctxKey(ctx, 0);
|
|
541
|
+
const counts = new Map;
|
|
542
|
+
let total = 0;
|
|
543
|
+
let prev = 0;
|
|
544
|
+
for (let t = r.varint();t > 0; t--) {
|
|
545
|
+
prev += r.varint();
|
|
546
|
+
const k = r.varint();
|
|
547
|
+
counts.set(ids.id(strs[prev]), k);
|
|
548
|
+
total += k;
|
|
549
|
+
}
|
|
550
|
+
lv.stats.set(key, [total, counts.size]);
|
|
551
|
+
lv.counts.set(key, counts);
|
|
552
|
+
}
|
|
553
|
+
this.levels.push(lv);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
stats(ctx) {
|
|
557
|
+
const s = { counts: [], total: [], wb: [] };
|
|
558
|
+
for (let n = 0;n < this.levels.length; n++) {
|
|
559
|
+
const key = ctxKey(ctx, ctx.length - n);
|
|
560
|
+
const st = this.levels[n].stats.get(key);
|
|
561
|
+
if (st && st[1] !== 0) {
|
|
562
|
+
s.counts[n] = this.levels[n].counts.get(key);
|
|
563
|
+
s.total[n] = st[0];
|
|
564
|
+
s.wb[n] = st[0] / (st[0] + st[1]);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
return s;
|
|
568
|
+
}
|
|
569
|
+
prob(s, tok) {
|
|
570
|
+
let p = 1 / (this.vocab + 1);
|
|
571
|
+
for (let n = 0;n < this.levels.length; n++) {
|
|
572
|
+
const c = s.counts[n];
|
|
573
|
+
if (!c)
|
|
574
|
+
continue;
|
|
575
|
+
const lam = s.wb[n];
|
|
576
|
+
p = lam * (c.get(tok) ?? 0) / s.total[n] + (1 - lam) * p;
|
|
577
|
+
}
|
|
578
|
+
return p;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
class Interner {
|
|
583
|
+
ids = new Map;
|
|
584
|
+
strs = [];
|
|
585
|
+
id(s) {
|
|
586
|
+
let v = this.ids.get(s);
|
|
587
|
+
if (v === undefined) {
|
|
588
|
+
v = this.strs.length;
|
|
589
|
+
this.ids.set(s, v);
|
|
590
|
+
this.strs.push(s);
|
|
591
|
+
}
|
|
592
|
+
return v;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
function before(a, b) {
|
|
596
|
+
if (a.score !== b.score)
|
|
597
|
+
return a.score > b.score;
|
|
598
|
+
if (a.out !== b.out)
|
|
599
|
+
return a.out < b.out;
|
|
600
|
+
return a.idx < b.idx;
|
|
601
|
+
}
|
|
602
|
+
function top(cs, k) {
|
|
603
|
+
const best = [];
|
|
604
|
+
for (const c of cs) {
|
|
605
|
+
if (best.length === k && !before(c, best[k - 1]))
|
|
606
|
+
continue;
|
|
607
|
+
let lo = 0;
|
|
608
|
+
let hi = best.length;
|
|
609
|
+
while (lo < hi) {
|
|
610
|
+
const mid = lo + hi >> 1;
|
|
611
|
+
if (before(c, best[mid]))
|
|
612
|
+
hi = mid;
|
|
613
|
+
else
|
|
614
|
+
lo = mid + 1;
|
|
615
|
+
}
|
|
616
|
+
best.splice(lo, 0, c);
|
|
617
|
+
if (best.length > k)
|
|
618
|
+
best.pop();
|
|
619
|
+
}
|
|
620
|
+
return best;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
class Mix {
|
|
624
|
+
beam;
|
|
625
|
+
a;
|
|
626
|
+
b;
|
|
627
|
+
lam;
|
|
628
|
+
start = [];
|
|
629
|
+
eos;
|
|
630
|
+
options = new Map;
|
|
631
|
+
lookup = new Map;
|
|
632
|
+
constructor(own, pool, tag, beam) {
|
|
633
|
+
this.beam = beam;
|
|
634
|
+
const ids = new Interner;
|
|
635
|
+
let r = new Reader(pool);
|
|
636
|
+
let strs = readStrings(r);
|
|
637
|
+
this.b = new Model(r, strs, ids);
|
|
638
|
+
r = new Reader(own);
|
|
639
|
+
strs = readStrings(r);
|
|
640
|
+
this.lam = r.float64();
|
|
641
|
+
this.a = new Model(r, strs, ids);
|
|
642
|
+
for (let k = r.varint();k > 0; k--) {
|
|
643
|
+
const native = r.str();
|
|
644
|
+
const sp = [];
|
|
645
|
+
for (let i = r.varint();i > 0; i--)
|
|
646
|
+
sp.push(strs[r.varint()]);
|
|
647
|
+
this.lookup.set(native, sp);
|
|
648
|
+
}
|
|
649
|
+
for (let i = 0;i < RULES.order - 2; i++)
|
|
650
|
+
this.start.push(ids.id(RULES.bos));
|
|
651
|
+
this.start.push(ids.id(`<s:${tag}>`));
|
|
652
|
+
this.eos = ids.id(RULES.eos);
|
|
653
|
+
const seen = new Set;
|
|
654
|
+
for (const m of [this.a, this.b]) {
|
|
655
|
+
for (const counts of m.levels[0].counts.values()) {
|
|
656
|
+
for (const t of counts.keys()) {
|
|
657
|
+
if (t === this.eos || seen.has(t))
|
|
658
|
+
continue;
|
|
659
|
+
seen.add(t);
|
|
660
|
+
const s = ids.strs[t];
|
|
661
|
+
const i = s.indexOf("|");
|
|
662
|
+
const chunk = s.slice(0, i);
|
|
663
|
+
const list = this.options.get(chunk) ?? [];
|
|
664
|
+
list.push({ tok: t, en: s.slice(i + 1) });
|
|
665
|
+
this.options.set(chunk, list);
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
for (const list of this.options.values())
|
|
670
|
+
list.sort((p, q) => p.en < q.en ? -1 : p.en > q.en ? 1 : 0);
|
|
671
|
+
if (this.start.length > 2 || ids.strs.length >= ID)
|
|
672
|
+
throw new Error("romanize: beyond the engine's limits");
|
|
673
|
+
}
|
|
674
|
+
logp(sa, sb, tok) {
|
|
675
|
+
const pa = Math.exp(Math.log(this.a.prob(sa, tok)));
|
|
676
|
+
const pb = Math.exp(Math.log(this.b.prob(sb, tok)));
|
|
677
|
+
return Math.log(this.lam * pa + (1 - this.lam) * pb);
|
|
678
|
+
}
|
|
679
|
+
decode(word, n) {
|
|
680
|
+
const w = [...word];
|
|
681
|
+
const h = RULES.order - 1;
|
|
682
|
+
const root = { score: 0, out: "", ctx: this.start };
|
|
683
|
+
const beams = Array.from({ length: w.length + 1 }, () => []);
|
|
684
|
+
beams[0].push({ score: 0, out: "", parent: null, tok: -1, idx: 0 });
|
|
685
|
+
const context = (c) => {
|
|
686
|
+
if (c.tok < 0)
|
|
687
|
+
return c.parent.ctx;
|
|
688
|
+
const ctx = [...c.parent.ctx, c.tok];
|
|
689
|
+
return ctx.slice(ctx.length - h);
|
|
690
|
+
};
|
|
691
|
+
for (let i = 0;i < w.length; i++) {
|
|
692
|
+
if (beams[i].length === 0)
|
|
693
|
+
continue;
|
|
694
|
+
for (const c of top(beams[i], this.beam)) {
|
|
695
|
+
const hy = i === 0 ? root : { score: c.score, out: c.out, ctx: context(c) };
|
|
696
|
+
let moved = false;
|
|
697
|
+
const sa = this.a.stats(hy.ctx);
|
|
698
|
+
const sb = this.b.stats(hy.ctx);
|
|
699
|
+
for (let k = 1;k <= RULES.max_n && i + k <= w.length; k++) {
|
|
700
|
+
const opts = this.options.get(w.slice(i, i + k).join(""));
|
|
701
|
+
if (!opts)
|
|
702
|
+
continue;
|
|
703
|
+
for (const o of opts) {
|
|
704
|
+
const next = beams[i + k];
|
|
705
|
+
next.push({ score: hy.score + this.logp(sa, sb, o.tok), out: hy.out + o.en, parent: hy, tok: o.tok, idx: next.length });
|
|
706
|
+
moved = true;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
if (!moved) {
|
|
710
|
+
const next = beams[i + 1];
|
|
711
|
+
next.push({ score: hy.score - RULES.unknown_penalty, out: hy.out, parent: hy, tok: -1, idx: next.length });
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
const final = new Map;
|
|
716
|
+
for (const c of beams[w.length]) {
|
|
717
|
+
const ctx = c.parent === null ? this.start : context(c);
|
|
718
|
+
const s = c.score + this.logp(this.a.stats(ctx), this.b.stats(ctx), this.eos);
|
|
719
|
+
const v = final.get(c.out);
|
|
720
|
+
if (v === undefined || s > v)
|
|
721
|
+
final.set(c.out, s);
|
|
722
|
+
}
|
|
723
|
+
return [...final].sort((p, q) => p[1] !== q[1] ? q[1] - p[1] : p[0] < q[0] ? -1 : p[0] > q[0] ? 1 : 0).slice(0, n).map((e) => e[0]);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
function readStrings(r) {
|
|
727
|
+
const strs = [];
|
|
728
|
+
for (let i = r.varint();i > 0; i--)
|
|
729
|
+
strs.push(r.str());
|
|
730
|
+
return strs;
|
|
731
|
+
}
|
|
732
|
+
function _decode(r, word, n) {
|
|
733
|
+
return r._mix.decode(word, n);
|
|
734
|
+
}
|
|
735
|
+
export {
|
|
736
|
+
unify,
|
|
737
|
+
load,
|
|
738
|
+
languages,
|
|
739
|
+
fromBytes,
|
|
740
|
+
_decode,
|
|
741
|
+
RULES_VERSION,
|
|
742
|
+
CDN
|
|
743
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Indian-language text in Latin letters, the way people spell it:
|
|
3
|
+
* लक्ष्मी → lakshmi, മലൈക → malaika, پرویز → parvez.
|
|
4
|
+
*
|
|
5
|
+
* A ranked list: one word has several accepted spellings (Choudhury,
|
|
6
|
+
* Chowdhury), and the first is the most likely. Two modes: "words" for
|
|
7
|
+
* running text (the default) and "names" for fields known to hold person
|
|
8
|
+
* names, where a lookup of known names comes first.
|
|
9
|
+
*
|
|
10
|
+
* The tables are learned from data and loaded per language, on demand:
|
|
11
|
+
*
|
|
12
|
+
* const r = await load("hi"); // fetches the Hindi and Brahmic files (beside this module, else jsDelivr)
|
|
13
|
+
* r.word("लक्ष्मी"); // ["lakshmi", ...]
|
|
14
|
+
*
|
|
15
|
+
* The output is deterministic: the same input gives the same list in Go and
|
|
16
|
+
* in TypeScript.
|
|
17
|
+
*
|
|
18
|
+
* @module
|
|
19
|
+
*/
|
|
20
|
+
/** The tables: "words" for running text, "names" for person names. */
|
|
21
|
+
export type Mode = "words" | "names";
|
|
22
|
+
/** Changes whenever any output changes: store it beside romanized text. */
|
|
23
|
+
export declare const RULES_VERSION: string;
|
|
24
|
+
/** The language codes that have tables, for one mode. */
|
|
25
|
+
export declare function languages(mode?: Mode): string[];
|
|
26
|
+
/** Fetches one data file's bytes. The default reads it beside this module. */
|
|
27
|
+
export type Fetcher = (url: URL) => Promise<ArrayBuffer>;
|
|
28
|
+
/** Where the tables are when they are not beside this module: jsDelivr, at this package's version. */
|
|
29
|
+
export declare const CDN: string;
|
|
30
|
+
/** One language's loaded tables. */
|
|
31
|
+
export interface Romanizer {
|
|
32
|
+
readonly lang: string;
|
|
33
|
+
readonly mode: Mode;
|
|
34
|
+
/** Up to n spellings of one word (default 4), most likely first. */
|
|
35
|
+
word(word: string, n?: number): string[];
|
|
36
|
+
/** Every run of the language's script romanized (its top spelling); everything else kept. */
|
|
37
|
+
text(text: string): string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Loads a language's tables for one mode: its own file and its script
|
|
41
|
+
* group's pooled file (shared by the group, fetched once). It reads them
|
|
42
|
+
* beside this module, else from jsDelivr at this package's version (the npm
|
|
43
|
+
* package carries no tables); `base` or `fetch` replaces both. Rejects when
|
|
44
|
+
* the language has no tables for the mode.
|
|
45
|
+
*/
|
|
46
|
+
export declare function load(lang: string, mode?: Mode, opts?: {
|
|
47
|
+
fetch?: Fetcher;
|
|
48
|
+
base?: URL | string;
|
|
49
|
+
}): Promise<Romanizer>;
|
|
50
|
+
/** Builds a Romanizer from a language's two files (for tests and offline use). */
|
|
51
|
+
export declare function fromBytes(lang: string, mode: Mode, own: Uint8Array, pool: Uint8Array): Romanizer;
|
|
52
|
+
/** Moves every Brahmic code point to the Devanagari block by its offset (rules.json "unify"). */
|
|
53
|
+
export declare function unify(w: string): string;
|
|
54
|
+
/** @internal The model's own list for a unified word (no lookup), for the conformance test. */
|
|
55
|
+
export declare function _decode(r: Romanizer, word: string, n: number): string[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "indickit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Small, exact utilities for text in Indian languages: a phonetic key that matches a name across 21 Indian scripts and English, a normalizer that gives text that looks the same one encoding, a segmenter for the letters a reader sees, and a stemmer for search.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"packageManager": "bun@1.3.14",
|
|
@@ -25,6 +25,10 @@
|
|
|
25
25
|
"./stem": {
|
|
26
26
|
"types": "./dist/types/js/stem.d.ts",
|
|
27
27
|
"default": "./dist/stem.js"
|
|
28
|
+
},
|
|
29
|
+
"./romanize": {
|
|
30
|
+
"types": "./dist/types/js/romanize.d.ts",
|
|
31
|
+
"default": "./dist/romanize.js"
|
|
28
32
|
}
|
|
29
33
|
},
|
|
30
34
|
"files": [
|
|
@@ -32,7 +36,7 @@
|
|
|
32
36
|
],
|
|
33
37
|
"sideEffects": false,
|
|
34
38
|
"scripts": {
|
|
35
|
-
"build": "bun build js/phonetic.ts --outfile dist/phonetic.js --target browser --format esm && bun build js/normalize.ts --outfile dist/normalize.js --target browser --format esm && bun build js/segment.ts --outfile dist/segment.js --target browser --format esm && bun build js/stem.ts --outfile dist/stem.js --target browser --format esm && tsc -p tsconfig.json",
|
|
39
|
+
"build": "bun build js/phonetic.ts --outfile dist/phonetic.js --target browser --format esm && bun build js/normalize.ts --outfile dist/normalize.js --target browser --format esm && bun build js/segment.ts --outfile dist/segment.js --target browser --format esm && bun build js/stem.ts --outfile dist/stem.js --target browser --format esm && bun build js/romanize.ts --outfile dist/romanize.js --target browser --format esm && tsc -p tsconfig.json",
|
|
36
40
|
"test": "bun test",
|
|
37
41
|
"check-dist": "node js/check-dist.mjs"
|
|
38
42
|
},
|