让 Icarus Insight 搜索插件支持拼音检索文章

让 Icarus Insight 搜索插件支持拼音检索文章

要是 Icarus 能用拼音搜文章就好了,如果你也有这样的想法,那这篇文章也许会对你有帮助。

效果

前提

  1. Icarus 版本 3.0 以上
  2. 搜索插件使用的是 Insight

方法

  1. 保存下面的文件到 themes/icarus/source/js,并重命名为 pinyin.js
    https://github.com/xmflswood/pinyin-match/blob/master/dist/main.js
  2. 保存下面的文件到 themes/icarus/layout/search,并重命名为 insight.jsx
    https://github.com/ppoffice/hexo-component-inferno/raw/master/src/view/search/insight.jsx
  3. 保存下面的文件到 themes/icarus/source/js,并重命名为 insight.js
    https://github.com/ppoffice/hexo-component-inferno/raw/master/asset/js/insight.js
  4. 修改 themes/icarus/layout/search/insight.jsx,加入拼音检索开关和依赖的 pinyin.js
    insight.jsx >folded
    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
    diff --git a/src/view/search/insight.jsx b/src/view/search/insight.jsx
    index 05a1c40..cce136d 100644
    --- a/src/view/search/insight.jsx
    +++ b/src/view/search/insight.jsx
    @@ -3,7 +3,7 @@
    * @module view/search/insight
    */
    const { Component, Fragment } = require('inferno');
    -const { cacheComponent } = require('../../util/cache');
    +const { cacheComponent } = require('hexo-component-inferno/lib/util/cache');

    /**
    * Algolia search engine JSX component.
    @@ -36,11 +36,18 @@ class Insight extends Component {
    <div class="searchbox-input-container">
    <input type="text" class="searchbox-input" placeholder={translation.hint}/>
    </div>
    + <div class="searchbox-pinyin">
    + <label class="checkbox">
    + <input id="search-by-pinyin" type="checkbox" checked="checked"/>
    + <span>&nbsp;拼音检索</span>
    + </label>
    + </div>
    <a class="searchbox-close" href="javascript:;">&times;</a>
    </div>
    <div class="searchbox-body"></div>
    </div>
    </div>
    + <script src="/js/pinyin.js" defer={true}></script>
    <script src={jsUrl} defer={true}></script>
    <script dangerouslySetInnerHTML={{ __html: js }}></script>
    </Fragment>;
  5. 修改 themes/icarus/source/js/insight.js,在原有匹配代码基础上增加拼音匹配代码
    insight.js >folded
    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
    diff --git a/asset/js/insight.js b/asset/js/insight.js
    index 33150b3..205a096 100644
    --- a/asset/js/insight.js
    +++ b/asset/js/insight.js
    @@ -6,6 +6,19 @@ function loadInsight(config, translation) { // eslint-disable-line no-unused-var
    const $main = $('.searchbox');
    const $input = $main.find('.searchbox-input');
    const $container = $main.find('.searchbox-body');
    + const $searchByPinyin = $main.find('#search-by-pinyin');
    +
    + /**
    + * 查询匹配拼音的数据。性能低于普通匹配,如果未启用拼音检索模式,直接返回 false。
    + * https://github.com/xmflswood/pinyin-match
    + * @param input {string} 目标字符串
    + * @param keyword {string} 输入的拼音或其他关键词
    + * @returns {[Array]|{Boolean}} 找到返回出现位置,未找到 / 未启用返回 false
    + */
    + function pinyinMatch(input, keyword) {
    + if (!$searchByPinyin.prop("checked")) return false;
    + return PinyinMatch.match(input, keyword);
    + }

    function section(title) {
    return $('<section>').addClass('searchbox-result-section').append($('<header>').text(title));
    @@ -33,10 +46,12 @@ function loadInsight(config, translation) { // eslint-disable-line no-unused-var
    const testText = text.toLowerCase();
    const indices = matches.map(match => {
    const index = testText.indexOf(match.toLowerCase());
    - if (!match || index === -1) {
    - return null;
    + if (match && index !== -1) {
    + return [index, index + match.length];
    }
    - return [index, index + match.length];
    + // Search by pinyin
    + const pinyinIndex = pinyinMatch(testText, match.toLowerCase());
    + return pinyinIndex ? [pinyinIndex[0], pinyinIndex[1] + 1] : null;
    }).filter(match => {
    return match !== null;
    }).sort((a, b) => {
    @@ -140,6 +155,8 @@ function loadInsight(config, translation) { // eslint-disable-line no-unused-var
    }
    if (obj[field].toLowerCase().indexOf(keyword) > -1) {
    return true;
    + } else if (pinyinMatch(obj[field].toLowerCase(), keyword)) {
    + return true;
    }
    return false;
    });
    @@ -266,10 +283,12 @@ function loadInsight(config, translation) { // eslint-disable-line no-unused-var
    if (location.hash.trim() === '#insight-search') {
    $main.addClass('show');
    }
    - $input.on('input', function() {
    - const keywords = $(this).val();
    + function onInputChange() {
    + const keywords = $input.val();
    searchResultToDOM(keywords, search(json, keywords));
    - });
    + }
    + $input.on('input', onInputChange);
    + $searchByPinyin.on('change', onInputChange);
    $input.trigger('input');
    });
  6. 修改 themes/icarus/include/style/search.styl,调整拼音检索复选框大小和位置
    search.styl >folded
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    diff --git a/include/style/search.styl b/include/style/search.styl
    index 0cdedd9..02d9b5e 100644
    --- a/include/style/search.styl
    +++ b/include/style/search.styl
    @@ -96,6 +96,16 @@ $searchbox-bg-pagination-item-disabled ?= $searchbox-bg-container
    padding: .75em 0 .75em 1.25em
    background: $searchbox-bg-input

    + .searchbox-pinyin
    + display: flex
    + align-items: center
    + user-select: none
    + input
    + vertical-align: middle
    + span
    + position: relative
    + top: 1px
    +
    .searchbox-close
    display: inline-block
    font-size: 1.5em

感谢

xmflswood 提供的 pinyin-match

   Landscape Vectors by Vecteezy

评论