blob: b136cddb30ffa1675a5053e300a4476858c31c5d [file]
import lunr from "lunr";
/**
* Split a sentence to tokens, considering a sequence of consecutive Chinese words as a single token.
*
* @param text - Text to be tokenized.
* @param language - Languages used.
*
* @returns Tokens.
*/
// Languages that need their own segmenter instead of the default word regex.
const SEGMENTER_LANGUAGES = ["ja", "jp", "th"];
/**
* Whether a language is indexed with its own segmenter.
*
* The segmenter also splits SQL identifiers on `_` and `-`, which the index
* then drops as punctuation, so a query for a full identifier can come back
* empty and has to be retried with its parts.
*/
export function usesSegmenterTokenizer(language: string[]): boolean {
return language.length === 1 && SEGMENTER_LANGUAGES.includes(language[0]);
}
export function tokenize(text: string, language: string[]): string[] {
// Some languages have their own tokenizer.
if (usesSegmenterTokenizer(language)) {
return ((lunr as any)[language[0]] as typeof lunr)
.tokenizer(text)
.map((token) => token.toString());
}
let regExpMatchWords = /[^-\s]+/g;
// Especially optimization for `zh`.
if (language.includes("zh")) {
// Currently only works fine with letters in Latin alphabet and Chinese.
// https://zhuanlan.zhihu.com/p/33335629
regExpMatchWords = /\w+|\p{Unified_Ideograph}+/gu;
// regExpMatchWords = /\p{Unified_Ideograph}+|[^-\s\p{Unified_Ideograph}]+/gu;
// https://mothereff.in/regexpu#input=const+regex+%3D+/%5Cp%7BUnified_Ideograph%7D/u%3B&unicodePropertyEscape=1
// regExpMatchWords = /\w+|[\u3400-\u4DBF\u4E00-\u9FFC\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29\u{20000}-\u{2A6DD}\u{2A700}-\u{2B734}\u{2B740}-\u{2B81D}\u{2B820}-\u{2CEA1}\u{2CEB0}-\u{2EBE0}\u{30000}-\u{3134A}]+/gu
}
return text.toLowerCase().match(regExpMatchWords) || [];
}