Hi,给他介绍一款markdown的帮助文档生成器

Stella981
• 阅读 568

      当今大多数的团队都实现了前、后端分支。前端与后端的沟通都是通过接口来实现的(一般情况下都是webapi接口)。这种情况你肯定需要一个接口查询的帮助文档,这个当然用swagger都可以实现。但做为前端开发的我们是否也应该考虑把自己写的组件以帮助文档的方式公开都团队其他人员使用。就像iview,easyui等UI组件都有自己的帮助文档。今天我们都介绍一套工具(其中某些组件经过本人的改造)

一、需要的组件

1. Hexo:静态博客生成器

2. Hexo-theme-doc:基于Hexo实现的帮助文档类型的皮肤,并对其中的某些逻辑进行完善

3. lunr-languages:实现lunr搜索对多语言的支持

二、实现的效果

Hi,给他介绍一款markdown的帮助文档生成器

上述演示效果为本人开发的ko-easyui插件的帮助文档。你可以访问此地址查看https://ko-plugins.gitee.io/koeasyui/index.html

效果看上去是简单了点,但却能达到对一套UI组件的说明,也是不错的。

三、对插件的改造

3.1 Hexo-them-doc的改造

对components.jsx中触发搜索的参数进行调整如下(使用其更快的触发搜索):

class SearchForm extends React.Component {

  constructor (props) {
    super(props);
  }

   handleKeyUp (e) {

     if (query.length < 2) { return; }

   }
    
}

主要就是把query.length < 3改为query.length < 2。

然后,引入修改后的lunr-languages(支持中文搜索的控件),修正代码如下(search/build.js):

let support = require('lunr-languages/lunr.stemmer.support');
let zhcn = require('lunr-languages/lunr.zhcn');
support(lunr);
zhcn(lunr);
module.exports = function build (ctx) {
  const index = lunr(function () {
     //添加对中文的支持
     this.use(lunr.zhcn);

     this.ref('id');
     this.field('title');
     this.field('body');
 }
}

上述是缩减之后的代码,其中主要是对lunr.zhcn的使用。

3.2 lunr-languages的改造

对lunr-languages的改造,增加了lunr.zhcn.js文件,增加对中文搜索的支持,代码如下:

/**
 * lunr对中文分词的支持
 */
;
(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.');
    }

    /*
    Thai tokenization is the same to Japanense, which does not take into account spaces.
    So, it uses the same logic to assign tokenization function due to different Lunr versions.
    */
    var isLunr2 = lunr.version[0] == "2";

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

        if (isLunr2) { // for lunr version 2.0.0
            this.tokenizer = lunr.zhcn.tokenizer;
        } else {
            if (lunr.tokenizer) { // for lunr version 0.6.0
                lunr.tokenizer = lunr.zhcn.tokenizer;
            }
            if (this.tokenizerFn) { // for lunr version 0.7.0 -> 1.0.0
                this.tokenizerFn = lunr.zhcn.tokenizer;
            }
        }
    };


    var segmenter = new lunr.TinySegmenter(); 

    lunr.zhcn.tokenizer = function(obj) {
      var i;
      var str;
      var len;
      var segs;
      var tokens;
      var char;
      var sliceLength;
      var sliceStart;
      var sliceEnd;
      var segStart;

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

      str = obj.toString().toLowerCase().replace(/^\s+/, '');
      for (i = str.length - 1; i >= 0; i--) {
        if (/\S/.test(str.charAt(i))) {
          str = str.substring(0, i + 1);
          break;
        }
      }

      tokens = [];
      len = str.length;
      for (sliceEnd = 0, sliceStart = 0; sliceEnd <= len; sliceEnd++) {
        char = str.charAt(sliceEnd);
        sliceLength = sliceEnd - sliceStart;

        if ((char.match(/\s/) || sliceEnd == len)) {
          if (sliceLength > 0) {
            segs = segmenter.segment(str.slice(sliceStart, sliceEnd)).filter(
              function(token) {
                return !!token;
              }
            );

            segStart = sliceStart;
            for (i = 0; i < segs.length; i++) {
              if (isLunr2) {
                tokens.push(
                  new lunr.Token(
                    segs[i], {
                      position: [segStart, segs[i].length],
                      index: tokens.length
                    }
                  )
                );
              } else {
                tokens.push(segs[i]);
              }
              segStart += segs[i].length;
            }
          }

          sliceStart = sliceEnd + 1;
        }
      }

      return tokens;
    }

    lunr.zhcn.stemmer = (function(){
      return function(word) {
        return word;
      }
    })();
    
    lunr.Pipeline.registerFunction(lunr.zhcn.stemmer, 'stemmer-zhcn');

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


    /* lunr stop word filter. see https://www.ranks.nl/stopwords/chinese-stopwords */
    lunr.zhcn.stopWordFilter = lunr.generateStopWordFilter('的 一 不 在 人 有 是 为 以 于 上 他 而 后 之 来 及 了 因 下 可 到 由 这 与 也 此 但 并 个 其 已 无 小 我 们 起 最 再 今 去 好 只 又 或 很 亦 某 把 那 你 乃 它 吧 被 比 别 趁 当 从 到 得 打 凡 儿 尔 该 各 给 跟 和 何 还 即 几 既 看 据 距 靠 啦 了 另 么 每 们 嘛 拿 哪 那 您 凭 且 却 让 仍 啥 如 若 使 谁 虽 随 同 所 她 哇 嗡 往 哪 些 向 沿 哟 用 于 咱 则 怎 曾 至 致 着 诸 自'.split(' '));
    lunr.Pipeline.registerFunction(lunr.zhcn.stopWordFilter, 'stopWordFilter-zhcn');
  };
}))
点赞
收藏
评论区
推荐文章
刚刚好 刚刚好
4个月前
css问题
1、在IOS中图片不显示(给图片加了圆角或者img没有父级)<div<imgsrc""/</divdiv{width:20px;height:20px;borderradius:20px;overflow:h
Symbol卢 Symbol卢
1年前
聊聊前后端接口对接的那些事
前言在现在的前后端分离的项目开发中,为了不影响项目的进度,都是前后端同时进行开发。为了不影响咱们前端开发的进度,通常都是由后端同学,先提供接口文档,然后前端同学对照这接口文档来进行数据的模拟来完成前后端对接的工作。这里的数据模拟其实也就是大家平时所说的mock数据,那么前端当中有哪些方式来实现mock数据呢???…(⊙_⊙;)…咱们接着往下聊!(●^o^●)
晴空闲云 晴空闲云
4个月前
css中box-sizing解放盒子实际宽高计算
我们知道传统的盒子模型,如果增加内边距padding和边框border,那么会撑大整个盒子,造成盒子的宽度不好计算,在实务中特别不方便。boxsizing可以设置盒模型的方式,可以很好的设置固定宽高的盒模型。盒子宽高计算假如我们设置如下盒子:宽度和高度均为200px,那么这会这个盒子实际的宽高就都是200px。但是当我们设置这个盒子的边框和内间距的时候,那
艾木酱 艾木酱
3个月前
快速入门|使用MemFire Cloud构建React Native应用程序
MemFireCloud是一款提供云数据库,用户可以创建云数据库,并对数据库进行管理,还可以对数据库进行备份操作。它还提供后端即服务,用户可以在1分钟内新建一个应用,使用自动生成的API和SDK,访问云数据库、对象存储、用户认证与授权等功能,可专
Stella981 Stella981
1年前
IDEA Spring使用Swagger2 API接口
根据Swagger2可以快速帮助我们编写最新的API接口文档,再也不用担心开会前仍忙于整理各种资料了,间接提升了团队开发的沟通效率。1\.引入依赖<!Swagger2api接口插件<dependency<groupIdio.springfox</groupId
Wesley13 Wesley13
1年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
liam liam
8个月前
这个API文档,太拽了吧!
一、前言在当前主流的前端后端分离模式开发下,拥有一个接口文档并且是好用的接口文档是很有必要的一个东西。PS:😖以下观点是真实开发场景下碰到并且悟出来的痛点。1.在项目的开发过程中,有一个接口文档的存在能让前端后端工程师保持的数据信息概念是统一的。例如:”项目需求的接口字段,参数字段。所有只要请求的返回参数记录到文档中的情况后,前后端工程师编写代码的同时就能
helloworld_28799839 helloworld_28799839
4个月前
常用知识整理
Javascript判断对象是否为空jsObject.keys(myObject).length0经常使用的三元运算我们经常遇到处理表格列状态字段如status的时候可以用到vue
liam liam
7个月前
先写API文档还是先写代码?
代码未动,文档先行其实大家都知道API文档先行的重要性,但是在实践过程中往往会遇到很多困难。程序员最讨厌的两件事:1.写文档,2.别人不写文档。大多数开发人员不愿意写API文档的原因是写文档短期收益远低于付出的成本,然而并不是所有人都能够坚持做有长期收益的事情的。作为一个前后端分离模式开发的团队,我们经常会看到这样的场景:前端开发和后端开发在一起
liam liam
8个月前
这才是,2022年的 API 文档该有的样子!
前后端差点打起来事情是这样的:今天我们公司的后端说他接口写完了,并分享了一个接口文档给我。用的就是SwaggerUI自动生成的那种接口文档,就像这种:这种Swagger文档我每次看着就头大,毛病多多:查看多级模型时要一级级点开在接口数量变多的时候非常难用,连分类菜单都没有提交参数为JSON的时候不能格式化参数出错的时候查找麻烦返回结果