flexsearch.js で多言語検索 #
Hugo のテーマ「hugo-book」は、検索のために flexsearch.js が同梱されてていい感じなんだけれども、日本語だと半角英数字が検索できない。
単語の分かち書き処理の話なんだけど、オフィシャル
だと
var index = FlexSearch.create({
encode: str => str.replace(/[\x00-\x7F]/g, "").split("")
});
と書かれてますね。で、hoog-book だとどうなってるかというと themes/book/i18n/ja.yaml
で
- id: bookSearchConfig
translation: |
{
encode: false,
tokenize: function(str) {
return str.replace(/[\x00-\x7F]/g, '').split('');
}
}
と本家で言ってる通りになってて、半角英数字はがっつりドロップされてますわー。
これじゃぁ困るよね、ってんで先人の知恵
config.toml 内に書けばいいんだろうと思って、ja.yaml を toml で書き直したり、config.toml を config.yaml にしたり色々やったけど、BookSearchConfig の部分がどうも読み込まれない。
ちゃんとテンプレートファイル追っかけていけばいいんだろうけど、面倒なんで i18n/ja.yaml
作って上書きして解決。元のやつそのまんまで上書き適用してくれる仕組みは楽ちん。
形態素解析すればもっと精度あがるんだろうけど、遅くなるだろうし、ひとまずこれでいいや。
- id: Search
translation: Search
#- id: Edit this page
# translation: このページを編集する
#- id: Last modified by
# translation: 最終更新者
#- id: Expand
# translation: 展開
# https://wp-kyoto.net/make-pr-to-add-search-form-to-website/
# https://www.broadleaves.dev/posts/2019-08-03-gridsome-flexsearch/
- id: bookSearchConfig
translation: |
{
encode: false,
tokenize: function(str) {
if (!str) return [];
const splitedTexts = str
// 処理前にアルファベットを小文字に変換
.toLowerCase()
// 漢字、カナ、半角英数の連続する塊を切り出し
// かなと全角英数は対象外
.match(/[一-龠]+|[ァ-ヴー]+|[a-z0-9]+/g);
if (!splitedTexts) return [];
const mappedTexts = splitedTexts
.filter((word) => word.length > 1)
// 半角英数の場合、前方一致検索ができるように処理
.map((word) => {
if (word.match(/[a-z0-9]+/g)) {
let token = '';
return Array.from(word)
.map((char) => (token += char))
.filter((token) => token.length > 1);
} else {
return word;
}
});
const flatted = mappedTexts.flat();
return [...new Set(flatted)];
}
}