mirror of
https://github.com/basketikun/infinite-canvas.git
synced 2026-07-25 16:04:30 +08:00
55 lines
1.6 KiB
TypeScript
55 lines
1.6 KiB
TypeScript
type OramaTokenizer = {
|
|
language: string;
|
|
normalizationCache: Map<string, string>;
|
|
tokenize: (raw: string, language?: string, prop?: string, withCache?: boolean) => string[];
|
|
};
|
|
|
|
const wordPattern = /[\p{Script=Han}]+|[a-z0-9][a-z0-9_'-]*/giu;
|
|
const hanPattern = /^\p{Script=Han}+$/u;
|
|
const chineseSegmenter = 'Segmenter' in Intl ? new Intl.Segmenter('zh-CN', { granularity: 'word' }) : null;
|
|
|
|
function getChineseSegments(value: string) {
|
|
if (!chineseSegmenter) return [];
|
|
|
|
return Array.from(chineseSegmenter.segment(value))
|
|
.filter((item) => item.isWordLike)
|
|
.map((item) => item.segment);
|
|
}
|
|
|
|
function addChineseTokens(tokens: string[], value: string) {
|
|
const chars = Array.from(value);
|
|
if (chars.length <= 12) tokens.push(value);
|
|
tokens.push(...getChineseSegments(value));
|
|
|
|
for (let size = 1; size <= 3; size += 1) {
|
|
if (chars.length < size) continue;
|
|
for (let i = 0; i <= chars.length - size; i += 1) {
|
|
tokens.push(chars.slice(i, i + size).join(''));
|
|
}
|
|
}
|
|
}
|
|
|
|
export function createDocsSearchTokenizer(): OramaTokenizer {
|
|
return {
|
|
language: 'zh-CN',
|
|
normalizationCache: new Map(),
|
|
tokenize(raw) {
|
|
if (typeof raw !== 'string') return [raw];
|
|
|
|
const tokens: string[] = [];
|
|
const input = raw.normalize('NFKC').toLowerCase();
|
|
|
|
for (const match of input.matchAll(wordPattern)) {
|
|
const value = match[0];
|
|
if (hanPattern.test(value)) {
|
|
addChineseTokens(tokens, value);
|
|
} else {
|
|
tokens.push(value);
|
|
}
|
|
}
|
|
|
|
return Array.from(new Set(tokens.filter(Boolean)));
|
|
},
|
|
};
|
|
}
|