-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtokenizer.ts
More file actions
88 lines (77 loc) · 2.24 KB
/
Copy pathtokenizer.ts
File metadata and controls
88 lines (77 loc) · 2.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/**
* Language detection and tokenizer selection utilities.
*
* Pure functions that determine the best FTS tokenizer based on
* the character distribution of sample text content.
*/
// ---------------------------------------------------------------------------
// Language detection
// ---------------------------------------------------------------------------
/** Language category for FTS tokenizer selection. */
export type LanguageHint = 'cjk' | 'latin' | 'mixed';
/**
* Check whether a character is CJK (Chinese / Japanese / Korean).
*/
export function isCJK(ch: string): boolean {
const cp = ch.codePointAt(0)!;
return (
(cp >= 0x4e00 && cp <= 0x9fff) || // CJK Unified
(cp >= 0x3400 && cp <= 0x4dbf) || // CJK Ext-A
(cp >= 0x3040 && cp <= 0x30ff) || // Hiragana + Katakana
(cp >= 0xac00 && cp <= 0xd7af) // Hangul
);
}
/**
* Check whether a string contains any CJK characters.
*/
export function containsCJK(text: string): boolean {
for (const ch of text) {
if (isCJK(ch)) return true;
}
return false;
}
/**
* Detect the dominant language category of a text sample.
*
* - 'cjk' → jieba (Chinese word segmentation)
* - 'latin' → standard (English stemmer + stop words)
* - 'mixed' → jieba (the more general choice for mixed scripts)
*
* Heuristic: if > 15% of characters are CJK, classify as CJK-dominant.
*/
export function detectLanguage(text: string): LanguageHint {
if (!text) return 'latin';
let cjkCount = 0;
let alphaCount = 0;
for (const ch of text) {
if (isCJK(ch)) {
cjkCount++;
} else if (/[a-zA-Z]/.test(ch)) {
alphaCount++;
}
}
const total = cjkCount + alphaCount || 1;
const cjkRatio = cjkCount / total;
if (cjkRatio > 0.15) {
return alphaCount > 0 ? 'mixed' : 'cjk';
}
return 'latin';
}
/**
* Pick the best FTS tokenizer name for a given language hint.
*/
export function tokenizerForLanguage(hint: LanguageHint): string {
switch (hint) {
case 'cjk':
case 'mixed':
return 'jieba';
case 'latin':
return 'standard';
}
}
/**
* Convenience: detect language from text and return the matching tokenizer.
*/
export function detectTokenizer(text: string): string {
return tokenizerForLanguage(detectLanguage(text));
}