MkDocs全文搜索中的中文支持

2023-11-13

在前一篇MkDocs全文搜索中使用模糊匹配中已经实现了模糊匹配,这次通过lunr-languages来实现lunr对中文搜索的支持

###MkDocs版本 v0.16.3、lunr.js版本2.0.3、lunr-languages版本1.0.0

一 、下载lunr.stemmer.support.js和tinyseg.js(tinyseg.js原是用于lunr.ja.js,因其原理不清楚,此处照搬)并放到lunr.min.js同一目录下

cd /usr/lib/python2.7/site-packages/mkdocs/assets/search/mkdocs/js
wget https://raw.githubusercontent.com/MihaiValentin/lunr-languages/master/lunr.stemmer.support.js
wget https://raw.githubusercontent.com/MihaiValentin/lunr-languages/master/tinyseg.js

二 、在此目录下继续增加lunr.cn.js(根据lunr.ja.js做的修改,lunr.cn.wordCharacters不知其用途,沿用了ja的值未做修改;lunr.cn.stopWordFilter根据Chinese stopwords提供的数据做了修改)文件,内容如下:

/*!
 * Lunr languages, `Chinese` language
 * https://github.com/MihaiValentin/lunr-languages
 *
 * Copyright 2017, Xiang Li
 * http://www.mozilla.org/MPL/
 */
/*!
 * based on
 * Snowball JavaScript Library v0.3
 * http://code.google.com/p/urim/
 * http://snowball.tartarus.org/
 *
 * Copyright 2010, Oleg Mazko
 * http://www.mozilla.org/MPL/
 */

/**
 * export the module via AMD, CommonJS or as a browser global
 * Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
 */
;
(function(root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(factory)
    } else if (typeof exports === 'object') {
        /**
         * Node. Does not work with strict CommonJS, but
         * only CommonJS-like environments that support module.exports,
         * like Node.
         */
        module.exports = factory()
    } else {
        // Browser globals (root is window)
        factory()(root.lunr);
    }
}(this, function() {
    /**
     * Just return a value to define the module export.
     * This example returns an object, but the module
     * can return a function as the exported value.
     */
    return function(lunr) {
        /* throw error if lunr is not yet included */
        if ('undefined' === typeof lunr) {
            throw new Error('Lunr is not present. Please include / require Lunr before this script.');
        }

        /* throw error if lunr stemmer support is not yet included */
        if ('undefined' === typeof lunr.stemmerSupport) {
            throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
        }

        /*
        Chinese tokenization is trickier, since it does not
        take into account spaces.
        Since the tokenization function is represented different
        internally for each of the Lunr versions, this had to be done
        in order to try to try to pick the best way of doing this based
        on the Lunr version
         */
        var isLunr2 = lunr.version[0] == "2";

        /* register specific locale function */
        lunr.cn = function() {
            this.pipeline.reset();
            this.pipeline.add(
                lunr.cn.stopWordFilter,
                lunr.cn.stemmer
            );

            // change the tokenizer for chinese one
            if (isLunr2) { // for lunr version 2.0.0
                this.tokenizer = lunr.cn.tokenizer;
            } else {
                if (lunr.tokenizer) { // for lunr version 0.6.0
                    lunr.tokenizer = lunr.cn.tokenizer;
                }
                if (this.tokenizerFn) { // for lunr version 0.7.0 -> 1.0.0
                    this.tokenizerFn = lunr.cn.tokenizer;
                }
            }
        };
        var segmenter = new lunr.TinySegmenter();

        lunr.cn.tokenizer = function (obj) {
            if (!arguments.length || obj == null || obj == undefined) return []
            if (Array.isArray(obj)) return obj.map(function (t) { return isLunr2 ? new lunr.Token(t.toLowerCase()) : t.toLowerCase() })

            var str = obj.toString().toLowerCase().replace(/^\s+/, '')

            for (var i = str.length - 1; i >= 0; i--) {
                if (/\S/.test(str.charAt(i))) {
                    str = str.substring(0, i + 1)
                    break
                }
            }

            var segs = segmenter.segment(str); 
            return segs.filter(function (token) {
                    return !!token
                })
                .map(function (token) {
                    return isLunr2 ? new lunr.Token(token) : token
                })
        }

        /* lunr stemmer function */
        lunr.cn.stemmer = (function() {

            /* TODO chinese stemmer  */
            return function(word) {
                return word;
            }
        })();

        lunr.Pipeline.registerFunction(lunr.cn.stemmer, 'stemmer-cn');
        lunr.cn.wordCharacters = "一二三四五六七八九十百千万億兆一-龠々〆ヵヶぁ-んァ-ヴーア-ン゙a-zA-Za-zA-Z0-90-9";

        /* stop word filter function */
        lunr.cn.stopWordFilter = function(token) {
            if (lunr.cn.stopWordFilter.stopWords.indexOf(isLunr2 ? token.toString() : token) === -1) {
                return token;
            }
        };

        // stopword for chinese is from http://www.ranks.nl/stopwords/chinese-stopwords
        lunr.cn.stopWordFilter = lunr.generateStopWordFilter(
            '的 一 不 在 人 有 是 为 以 于 上 他 而 后 之 来 及 了 因 下 可 到 由 这 与 也 此 但 并 个 其 已 无 小 我 们 起 最 再 今 去 好 只 又 或 很 亦 某 把 那 你 乃 它 吧 被 比 别 趁 当 从 到 得 打 凡 儿 尔 该 各 给 跟 和 何 还 即 几 既 看 据 距 靠 啦 了 另 么 每 们 嘛 拿 哪 那 您 凭 且 却 让 仍 啥 如 若 使 谁 虽 随 同 所 她 哇 嗡 往 哪 些 向 沿 哟 用 于 咱 则 怎 曾 至 致 着 诸 自'.split(' '));

        lunr.Pipeline.registerFunction(lunr.cn.stopWordFilter, 'stopWordFilter-cn');
    };
}))

三 、修改search.js文件

require([
    base_url + '/mkdocs/js/mustache.min.js',
    base_url + '/mkdocs/js/lunr.min.js',
    base_url + '/mkdocs/js/lunr.stemmer.support.js',
    base_url + '/mkdocs/js/tinyseg.js',
    base_url + '/mkdocs/js/lunr.cn.js',
    'text!search-results-template.mustache',
    'text!../search_index.json',
], function (Mustache, lunr,stemmerSupport, TinySegmenter,  ja, results_template,    data) {
   "use strict";


    stemmerSupport(lunr); // adds lunr.stemmerSupport
    TinySegmenter(lunr);
    ja(lunr); // adds lunr.de key


    function getSearchTerm()
    {
        var sPageURL = window.location.search.substring(1);
        var sURLVariables = sPageURL.split('&');
        for (var i = 0; i < sURLVariables.length; i++)
        {
            var sParameterName = sURLVariables[i].split('=');
            if (sParameterName[0] == 'q')
            {
                return decodeURIComponent(sParameterName[1].replace(/\+/g, '%20'));
            }
        }
    }

    var documents = {};
    var doc;
    var index = lunr(function () {
        this.use(lunr.cn);
        this.field('title', {BOOST: 10});
        this.field('text');
        this.ref('location');

        data = JSON.parse(data);
        //var documents = {};

        for (var i=0; i < data.docs.length; i++){
            doc = data.docs[i];
            doc.location = base_url + doc.location;
            this.add(doc);
            documents[doc.location] = doc;
        }   

    });

    /*data = JSON.parse(data);
    var documents = {};

    for (var i=0; i < data.docs.length; i++){
        var doc = data.docs[i];
        doc.location = base_url + doc.location;
        index.add(doc);
        documents[doc.location] = doc;
    }*/

    var search = function(){

        var query = document.getElementById('mkdocs-search-query').value;
        var search_results = document.getElementById("mkdocs-search-results");
        while (search_results.firstChild) {
            search_results.removeChild(search_results.firstChild);
        }

        if(query === ''){
            return;
        }

        var results = index.search(query);

        if (results.length > 0){
            for (var i=0; i < results.length; i++){
                var result = results[i];
                doc = documents[result.ref];
                doc.base_url = base_url;
                doc.summary = doc.text.substring(0, 200);
                var html = Mustache.to_html(results_template, doc);
                search_results.insertAdjacentHTML('beforeend', html);
            }
        } else {
            search_results.insertAdjacentHTML('beforeend', "<p>No results found</p>");
        }

        if(jQuery){
            /*
             * We currently only automatically hide bootstrap models. This
             * requires jQuery to work.
             */
            jQuery('#mkdocs_search_modal a').click(function(){
                jQuery('#mkdocs_search_modal').modal('hide');
            });
        }

    };

    var search_input = document.getElementById('mkdocs-search-query');

    var term = getSearchTerm();
    if (term){
        search_input.value = term;
        search();
    }

    search_input.addEventListener("keyup", search);

});

大功告成,因为是根据lunr.ja.js做的修改,部分数据未做修改,可能会在搜索时出现未知的问题,目前测试运行良好

转载于:https://my.oschina.net/u/3465063/blog/895142

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MkDocs全文搜索中的中文支持 的相关文章

随机推荐

  • Linux如何给服务器增加白名单

    1 查看系统白名单配置 iptables L n 2 增加白名单 19 40 145 140 是需要增加的服务器IP iptables I INPUT s 19 40 145 140 32 p tcp j ACCEPT 注 I I是i的大写
  • oracle 函数使用方法----replace函数

    例 sql语句如下 select from cen sys TB DIC JDLX t 查询结果如下 需求 需要获取字段 PID 的值并 新增一个字段 PNAME PNAME的值为字段PID去掉 市平台前置机 剩下的字段 实现 select
  • 后端返回parentId,前端处理成children嵌套数据

    rouyi 的 vuetree函数结合elementui el table组件使用 把有parentId和id结构的数据处理成children嵌套数据 字段名称不一致 可以设置 vuetree函数 构造树型结构数据 param data 数
  • html 调用ActiveX

    html网页调用ActiveX控件时 要获取到ActiveX的ClassID 这个ClassID是注册到系统里的 而不是工程中的uuid 下图为uuid 正确的是在注册表的HKEY CLASSES ROOT中查找你的工程名的 项 找到后 其
  • flink state ttl 清理逻辑(截止到flink1.8之前的逻辑)

    在我们开发Flink应用时 许多有状态流应用程序的一个常见要求是自动清理应用程序状态以有效管理状态大小 或控制应用程序状态的访问时间 TTL Time To Live 功能在Flink 1 6 0中开始启动 并在Apache Flink中启
  • openwrt golang mysql_golang1.9编译openwrt运行程序 ,window7下liteide编译

    网上看了好多资料发现都很过时了 基本都是用的https github com gomini go mips32编译的 但是go1 9早就支持mips了 设置好编译参数 开始build 这时在go pkg下会出现linux mips目录 就是
  • Thumb / Thumb-2 / ThumbEE

    本文转载至 http zh wikipedia org wiki ARM E6 9E B6 E6 A7 8B Thumb 较新的ARM处理器有一种16 bit指令模式 叫做Thumb 也许跟每个条件式运行指令均耗用4位的情形有关 在Thum
  • 问题定位及解决方案

    1 视频沉浸页快速滑动后 必现不能向下划动 复现步骤 进入视频沉浸页 快速向下划动 滑动到第一页最后一个时 不能再向下划动 解决步骤 1 确定请求API mtop aliexpress ugc feed video list 2 找到触发请
  • uniapp开发小程序,编译时报错Cannot read property ‘forceUpdate‘ of undefined的解决方案

    1 这个报错 主要是没有在uniapp的开发平台为这个应用注册一个appid 2 登录uniapp开发平台 https dev dcloud net cn 注册成为开发者 并创建一个应用 此应用的名称要与本地的项目的名称一致 3 重现获取u
  • Android开发---Fragment可见/不可见时的生命周期回调函数

    Fragment可见 不可见时的生命周期回调函数 项目中经常会碰到 需要在fragment失去焦点和获得焦点的方法中进行一些设置 但是fragment没有onpause 和onResume 方法 你重写的这两个方法 都是fragment依附
  • python安装

    Python 环境搭建 本章节我们将向大家介绍如何在本地搭建Python开发环境 Python可应用于多平台包括 Linux 和 Mac OS X 你可以通过终端窗口输入 python 命令来查看本地是否已经安装Python以及Python
  • ORA-32021: parameter value longer than 255 characters 解决方法

    在增加节点完后 用dbca 添加数据库实例时 报ORA 32021 parameter value longer than 255 characters 错误 oraagent log 2011 10 24 09 18 32 724 USR
  • 框架学习笔记——Spring

    Spring 文章目录 Spring 1 Spring简介 1 1 框架的主要特征 1 2 Spring的主要特点 1 3 组成 2 Spring之控制反转 IOC 2 1 百科 2 2 两种方式 2 3 依赖注入 推导 2 3 1 新建一
  • Centos7.5安装应用服务教程 ---- jdk1.8安装教程

    1 下载jdk1 8压缩包 建议装在 usr local目录下 2 解压 tar zxvf jdk 8u301 linux x64 tar gz 3 配置环境变量 修改文件配置 vi vim etc profile 在文件底部加入以下配置
  • C++中queue使用详细说明

    一 queue 的介绍 queue 翻译为队列 在 STL 中主要则是实现了一个先进先出的容器 二 queue 的定义 单独定义一个 queue queue
  • linux开放tomcat8080端口,防火墙开启/关闭/状态查询

    linux开放tomcat8080端口 防火墙开启 关闭 状态查询 最终效果 开放8080端口成功访问tomcat页面 要实现开放端口8080有两种方式 仅限于我所知道的 条条大路通罗马 能实现功能就行 废话不多说上干货 一是单独开放808
  • github 如何删除不需要的项目(两种方法)

    在Github上删除项目是一项非常基本的操作 但是对于很多使用者来说 却可能会因为缺乏经验而无从下手 如果你也处于这个情况 那么这篇文章就为你提供了一些详细的指导 删除Github上的项目可以采用两种方式 通过网站进行删除 或者通过Git客
  • JavaScript中的promise

    概述 promise 承诺 是异步编程的一种解决方案 可以替代传统的解决方案 回调函数和事件 ES6统一了用法 并原生提供了Promise对象 promise是异步编程的一种解决方案 什么时候我们会来处理异步事件呢 一种很常见的场景就应该是
  • [1228]Python prometheus-client使用方式

    文章目录 安装 prometheus client 基本使用介绍 应用实例 收集 CPU 使用率指标 收集自定义指标 Python封装 调用 github https github com prometheus client python
  • MkDocs全文搜索中的中文支持

    在前一篇MkDocs全文搜索中使用模糊匹配中已经实现了模糊匹配 这次通过lunr languages来实现lunr对中文搜索的支持 MkDocs版本 v0 16 3 lunr js版本2 0 3 lunr languages版本1 0 0