flexsearch.js で多言語検索

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)];
      }
    }    

See Also

Copyright © 髭。/ Hugo + hugo-book