最终完成效果以下:
左侧导航栏支持多层级嵌套,右侧为当前文档内标题导航。javascript
顶部右侧搜索栏(目前只支持分词搜索,不支持整句):css
图片放大:java
更全面的信息请移步官网:
mkdocs官网
mkdocs-material官网node
python: 3.7.2python
# 安装依赖 pip install mkdocs mkdocs-material pip install jieba # 本地调试 mkdocs serve # 打包 mkdocs build
包名 | 模块名 | 版本 |
---|---|---|
mkdocs | mkdocs | 1.0.4 |
mkdocs-material | material | 3.0.6 |
Markdown | markdown | 3.0.1 |
pymdown-extensions | pymdownx | 6.0 |
jieba | jieba | 0.39 |
笔者使用mkdocs-material 4.0.1时遇着大坑,建议制定版本安装3.0.6jquery
项目目录以下:git
assets:自定义资源github
mkdocs.yml配置web
site_name: '帮助中心' site_author: zzm site_url: http://xxx.com/help/ # 静态资源输出文件夹 site_dir: ../dist/help # 左侧导航 nav: - 介绍: index.md - 标签服务系统帮助文档: - 标签平台用户手册: label/user_manual.md - 标签数听说明文档: label/data_desc.md - 标签需求对接流程: label/demand_process.md - 统一标签API服务: - 0.常见问题: # 本地调试端口 dev_addr: 127.0.0.1:4050 # 主题配色 theme: name: material language: 'zh' favicon: 'assets/favicon.ico' logo: icon: ' ' palette: primary: 'Light Blue' accent: 'Light Blue' feature: tabs: false # 自定义css extra_css: - 'assets/css/custom.css' - 'assets/css/simpleLightbox.min.css' # 自定义js extra_javascript: - 'assets/js/jquery-3.2.1.min.js' - 'assets/js/simpleLightbox.min.js' - 'assets/js/custom.js' # 一些扩展 markdown_extensions: - markdown.extensions.attr_list - admonition - codehilite: guess_lang: false linenums: false - toc: permalink: true - footnotes - meta - def_list - pymdownx.arithmatex - pymdownx.betterem: smart_enable: all - pymdownx.caret - pymdownx.critic - pymdownx.details - pymdownx.inlinehilite - pymdownx.magiclink - pymdownx.mark - pymdownx.smartsymbols - pymdownx.superfences - pymdownx.tasklist - pymdownx.tilde
目前网上找到的教程都是针对lunr源码替换,但不少都是历史版本的解决方案,随着lunr的更新,不少API已经面目全非,文件夹啥的都对不上,比较懵圈。这里会提供稍微新一点的方案。固然,最终解决方案仍是要改造下lunr。算法
lunr的工做原理能够归纳为两步:
实现中文搜索困难的地方在于中文分词的机制和英文不一样,不能简单使用分隔符去切词,而中文分词的算法复杂,将全部页面信息临时构建成分词库的效率就会很低。
英文版的lunr如今已经支持日文,对于“帮助文档简介”,能够获得三个分词:帮助,文档,简介。这种机制是,lunr分词是由分隔符导向,同时对词长有必定限制,相似这种汉字过多的成句,只能保留每段分割的前两个字。因此在搜索的时候,成句(通常是大于俩字)目前是搜索不到的,但能够经过空格切割成句进行搜索。
改动以下:
个人目录在/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/mkdocs/contrib/search/,修改generate_search_index
def generate_search_index(self): """python to json conversion""" page_dicts = { 'docs': self._entries, 'config': self.config } for doc in page_dicts['docs']: # 调用jieba的cut接口生成分词库,过滤重复词,过滤空格 tokens = list(set([token.lower() for token in jieba.cut_for_search(doc['title'].replace('\n', ''), True)])) if '' in tokens: tokens.remove('') doc['title_tokens'] = tokens tokens = list(set([token.lower() for token in jieba.cut_for_search(doc['text'].replace('\n', ''), True)])) if '' in tokens: tokens.remove('') doc['text_tokens'] = tokens data = json.dumps(page_dicts, sort_keys=True, separators=(',', ':'), ensure_ascii=False) if self.config['prebuild_index']: try: script_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'prebuild-index.js') p = subprocess.Popen( ['node', script_path], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) idx, err = p.communicate(data.encode('utf-8')) if not err: idx = idx.decode('utf-8') if hasattr(idx, 'decode') else idx page_dicts['index'] = json.loads(idx) data = json.dumps(page_dicts, sort_keys=True, separators=(',', ':'), ensure_ascii=False) log.debug('Pre-built search index created successfully.') else: log.warning('Failed to pre-build search index. Error: {}'.format(err)) except (OSError, IOError, ValueError) as e: log.warning('Failed to pre-build search index. Error: {}'.format(e)) return data
个人目录:/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/mkdocs/contrib/search/templates/search/,搜索lunr.Builder.prototype.add替换部分代码
// 仅替换前15行 lunr.Builder.prototype.add = function (doc, attributes) { var docRef = doc[this._ref], fields = Object.keys(this._fields) this._documents[docRef] = attributes || {} this.documentCount += 1 for (var i = 0; i < fields.length; i++) { var fieldName = fields[i], extractor = this._fields[fieldName].extractor, field = extractor ? extractor(doc) : doc[fieldName], tokens = doc[fieldName + '_tokens'], terms = this.pipeline.run(tokens), fieldRef = new lunr.FieldRef (docRef, fieldName), fieldTerms = Object.create(null)
还有一部分需替换
lunr.trimmer = function (token) { return token.update(function (s) { return s.replace(/^\s+/, '').replace(/\s+$/, '') }) }
搞定~ 如今输入中文搜索不到的问题就解决啦
图片放大又称Lightbox,主要是提供一个浮窗,以展现页面上缩略图的大图版。另外一类叫zoom-in,主要是实现鼠标悬停时出现放大镜。目前在markdown中要使用只都能经过外部引入。
首先 下载css及js并引入: Simple lightbox
|---assets | |---css | | |----simpleLightbox.min.css | | `----custom.css | `---js | |----simpleLightbox.min.js | `----custom.js
下一步,在配置文件mkdocs.yml中设置extra_css与extra_javascript(如前文配置);
下一步,在custom.css和custom.js中分别添加:
/* custom.css */ a.boxedThumb { display: block; padding: 4px; line-height: 20px; border: 1px solid #ddd; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); -webkit-transition: -webkit-transform .15s ease; -moz-transition: -moz-transform .15s ease; -o-transition: -o-transform .15s ease; -ms-transition: -ms-transform .15s ease; transition: transform .15s ease; } a.boxedThumb:hover { -webkit-transform: scale(1.05); -moz-transform: scale(1.05); -o-transform: scale(1.05); -ms-transform: scale(1.05); transform: scale(1.05); z-index: 5; }
$(document).ready(function () { let productImageGroups = [] $('.img-fluid').each(function () { let productImageSource = $(this).attr('src') let productImageTag = $(this).attr('tag') let productImageTitle = $(this).attr('title') if (productImageTitle) { productImageTitle = 'title="' + productImageTitle + '" ' } else { productImageTitle = '' } $(this). wrap('<a class="boxedThumb ' + productImageTag + '" ' + productImageTitle + 'href="' + productImageSource + '"></a>') productImageGroups.push('.' + productImageTag) }) jQuery.unique(productImageGroups) productImageGroups.forEach(productImageGroupsSet) function productImageGroupsSet (value) { $(value).simpleLightbox() } })
注:此处要确保下述插件开启,它容许在MarkDown连接/图片后用括号指明任意标签的字段。
markdown_extensions: - markdown.extensions.attr_list
使用时
{.img-fluid tag=1} # 带说明描述 {.img-fluid tag=2 title="测试说明"} # 图片组 {.img-fluid tag=3} {.img-fluid tag=3} {.img-fluid tag=3}
搞定~