indickit 0.5.0 → 0.8.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.
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Indian-language text from Latin typing, the reverse of romanize:
3
+ * namaste → नमस्ते, ahmad → احمد, vanakkam → வணக்கம்.
4
+ *
5
+ * A ranked list: one typed word can stand for several native words (kamal:
6
+ * कमल, कमाल), 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.
9
+ *
10
+ * It writes the word it is given in the language's script, so English words
11
+ * in mixed text ("kal meeting hai") are written in it too: identify each
12
+ * word's language first.
13
+ *
14
+ * The tables are learned from data and loaded per language, on demand:
15
+ *
16
+ * const d = await load("hi"); // fetches the Hindi and Brahmic files (beside this module, else jsDelivr)
17
+ * d.word("namaste"); // ["नमस्ते", ...]
18
+ *
19
+ * The output is deterministic: the same input gives the same list in Go and
20
+ * in TypeScript.
21
+ *
22
+ * @module
23
+ */
24
+ /** The tables: "words" for running text, "names" for person names. */
25
+ export type Mode = "words" | "names";
26
+ /** Changes whenever any output changes. */
27
+ export declare const RULES_VERSION: string;
28
+ /** The language codes that have tables, for one mode. */
29
+ export declare function languages(mode?: Mode): string[];
30
+ /** Fetches one data file's bytes. The default reads it beside this module. */
31
+ export type Fetcher = (url: URL) => Promise<ArrayBuffer>;
32
+ /** Where the tables are when they are not beside this module: jsDelivr, at this package's version. */
33
+ export declare const CDN: string;
34
+ /** One language's loaded tables. */
35
+ export interface Deromanizer {
36
+ readonly lang: string;
37
+ readonly mode: Mode;
38
+ /** Up to n native spellings of one Latin-typed word (default 4), most likely first. */
39
+ word(latin: string, n?: number): string[];
40
+ /** Every run of Latin letters written as its first native spelling; everything else kept. */
41
+ text(text: string): string;
42
+ }
43
+ /** The input as the training pairs were read: accents removed, lower case, a-z only. */
44
+ export declare function clean(s: string): string;
45
+ /**
46
+ * Loads a language's tables for one mode: its own files, its word list and its
47
+ * script group's pooled files (shared by the group, fetched once). It reads them
48
+ * beside this module, else from jsDelivr at this package's version (the npm
49
+ * package carries no tables); `base` or `fetch` replaces both. Rejects when the
50
+ * language has no tables for the mode.
51
+ */
52
+ export declare function load(lang: string, mode?: Mode, opts?: {
53
+ fetch?: Fetcher;
54
+ base?: URL | string;
55
+ }): Promise<Deromanizer>;
56
+ /** Builds a Deromanizer from its files, by file name (for tests and offline use). */
57
+ export declare function fromBytes(lang: string, mode: Mode, files: Record<string, Uint8Array>): Deromanizer;
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Phonetic search: the key finds candidates, and a scorer learned from data
3
+ * ranks them 0..100. A Latin query finds a name in any script; a name in one
4
+ * Indian script finds it in another.
5
+ *
6
+ * const s = await loadSearch("hi"); // fetches the Hindi table (a few KB)
7
+ * const ix = s.index(["नरेंद्र मोदी", "नरेश मोदी"]);
8
+ * ix.search("Narendra Modi", THRESHOLDS.names); // [{ name: 0, score: 100 }]
9
+ *
10
+ * Two profiles: "names" (a list of names: a roster, a directory) and "text"
11
+ * (a name among the words of a running text). A score is relative to the
12
+ * other candidates of its search, so it belongs to the search, not to a pair.
13
+ * Every step is integer arithmetic: Go, TypeScript and the reference give the
14
+ * same scores.
15
+ *
16
+ * @module
17
+ */
18
+ /** "names": a list of names; "text": a name among a text's words. */
19
+ export type Profile = "names" | "text";
20
+ type ProfileRules = {
21
+ key: number;
22
+ cost: number;
23
+ vowel: number;
24
+ div: number;
25
+ stop_permille: number | null;
26
+ stop_min_names: number;
27
+ round: boolean;
28
+ };
29
+ /** Changes whenever any score changes. */
30
+ export declare const SEARCH_VERSION: string;
31
+ /** The scores measured for each use: names in a list 74, villages 72, a name
32
+ * in text 80 (at most 10% of hits wrong) or 70 (20%). */
33
+ export declare const THRESHOLDS: Readonly<Record<string, number>>;
34
+ type Sparse = [number, [number, number][]];
35
+ type RawTable = {
36
+ latin?: string[];
37
+ native?: string[];
38
+ x?: string[];
39
+ y?: string[];
40
+ c: Sparse[];
41
+ units?: [number, number, number, [number, number][]][];
42
+ };
43
+ declare class CostTable {
44
+ readonly idx: Map<string, number>;
45
+ readonly v: number;
46
+ readonly c: Float64Array;
47
+ readonly units: Map<number, Float64Array<ArrayBufferLike>>;
48
+ constructor(raw: RawTable);
49
+ ids(rs: string[]): number[];
50
+ align(a: number[], b: number[], withUnits: boolean): number;
51
+ }
52
+ /** Fetches one data file's bytes. The default reads it beside this module, else from jsDelivr. */
53
+ export type Fetcher = (url: URL) => Promise<ArrayBuffer>;
54
+ /** Where the tables are when they are not beside this module: jsDelivr, at this package's version. */
55
+ export declare const CDN: string;
56
+ declare class Scorer {
57
+ readonly lang: string;
58
+ private latin;
59
+ private pairs;
60
+ constructor(lang: string, latin: CostTable | undefined, pairs: Map<string, CostTable>);
61
+ cost(a: string, b: string): number | undefined;
62
+ calibrations(a: string, cands: string[]): Map<string, number>;
63
+ wordSim(a: string, b: string, cal: Map<string, number> | undefined, p: ProfileRules): number;
64
+ }
65
+ /** A name found by a search: its position among the indexed names, and its score. */
66
+ export interface Hit {
67
+ name: number;
68
+ score: number;
69
+ }
70
+ /** Names of one language, keyed once for searching. */
71
+ export declare class Index {
72
+ private readonly scorer;
73
+ private readonly words;
74
+ private readonly n;
75
+ private readonly df;
76
+ private readonly maps;
77
+ private readonly p;
78
+ /** @internal Use Search.index. */
79
+ constructor(scorer: Scorer, names: string[], profile: Profile);
80
+ private common;
81
+ private weight;
82
+ private candidates;
83
+ private nameScore;
84
+ /** @internal */
85
+ scoreAll(query: string, which: number[]): Hit[];
86
+ /** The names scoring at least threshold, best first (ties in index order). */
87
+ search(query: string, threshold?: number): Hit[];
88
+ }
89
+ /** A loaded language: index names, or score candidates. */
90
+ export interface Search {
91
+ readonly lang: string;
92
+ /** Key names (of this language, or Latin) once for searching. */
93
+ index(names: string[], profile?: Profile): Index;
94
+ /** One score per candidate name, calibrated among these candidates. */
95
+ score(query: string, candidates: string[], profile?: Profile): number[];
96
+ }
97
+ /** Loads one language's table (Latin queries against its script) and, for
98
+ * native-to-native search, the tables between the scripts named in `scripts`
99
+ * (e.g. ["deva", "arab", "beng"]). A missing table falls back to the fine keys. */
100
+ export declare function loadSearch(lang: string, options?: {
101
+ scripts?: string[];
102
+ fetcher?: Fetcher;
103
+ }): Promise<Search>;
104
+ export {};
@@ -10,6 +10,13 @@
10
10
  *
11
11
  * @module
12
12
  */
13
+ /** @internal For ./phonetic-search: the engine compiler, the normalizer and the
14
+ * search key's engine (keys of a normalized word). Not part of the API. */
15
+ export declare const _internal: {
16
+ compile: (r: unknown) => (word: string) => string[];
17
+ normalize: (w: string) => string;
18
+ engine: (word: string) => string[];
19
+ };
13
20
  /** The rules every key from this module was made with. */
14
21
  export declare const RULES_VERSION: string;
15
22
  /** NameKeys stops here: a long Tamil name can have many key combinations. */
@@ -23,6 +30,13 @@ export declare function words(name: string): string[];
23
30
  * separated by a space. Two names match when these share an element, so
24
31
  * these are what to index. At most MAX_NAME_KEYS. */
25
32
  export declare function nameKeys(name: string): string[];
33
+ /** Joined keys shorter than this (in classes) are not returned: they find too many names. */
34
+ export declare const JOINED_MIN_CLASSES: number;
35
+ /** The keys of a name written as one word, its words joined: "Ram Nath" and
36
+ * இராம்நாத் share no nameKeys, but can share a joined key. Only keys of at
37
+ * least JOINED_MIN_CLASSES classes. A search looks them up only when
38
+ * nameKeys find nobody; match does not use them. */
39
+ export declare function joinedKeys(name: string): string[];
26
40
  /** Whether two names have the same number of words and every pair of words,
27
41
  * in order, shares a key. */
28
42
  export declare function match(a: string, b: string): boolean;
@@ -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.5.0",
3
+ "version": "0.8.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,18 @@
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"
32
+ },
33
+ "./phonetic-search": {
34
+ "types": "./dist/types/js/phonetic-search.d.ts",
35
+ "default": "./dist/phonetic-search.js"
36
+ },
37
+ "./deromanize": {
38
+ "types": "./dist/types/js/deromanize.d.ts",
39
+ "default": "./dist/deromanize.js"
28
40
  }
29
41
  },
30
42
  "files": [
@@ -32,7 +44,7 @@
32
44
  ],
33
45
  "sideEffects": false,
34
46
  "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",
47
+ "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 && bun build js/phonetic-search.ts --outfile dist/phonetic-search.js --target browser --format esm && bun build js/deromanize.ts --outfile dist/deromanize.js --target browser --format esm && tsc -p tsconfig.json",
36
48
  "test": "bun test",
37
49
  "check-dist": "node js/check-dist.mjs"
38
50
  },