需求
- 整站文档使用markdown,方便产品&运营童鞋们编写
- 支持搜索
- 点击图片能放大
最终完成效果如下:
左侧导航栏支持多层级嵌套,右侧为当前文档内标题导航。
顶部右侧搜索栏(目前只支持分词搜索,不支持整句):
图片放大:
实现
更全面的信息请移步官网:
mkdocs官网
mkdocs-material官网
环境搭建
python: 3.7.2
# 安装依赖
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.6
目录说明&基础配置
项目目录如下:
-
assets:自定义资源
- css
- js
- syntax:语法示例(可忽略)
- img:存储文档内图片资源
- label:文档内容
- index.md:首页
mkdocs.yml配置
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的工作原理可以概括为两步:
- 提取页面纯文字版内容到一个json文件,包含锚点位置、标题、描述及标题与描述对应的分词库。大概长这样:
- 把搜索框输入的内容根据分隔符(空格、标点符号等)切成分词,并和第1步的分词库进行比对,根据对应锚点寻址页面。
实现中文搜索困难的地方在于中文分词的机制和英文不同,不能简单使用分隔符去切词,而中文分词的算法复杂,将所有页面信息临时构建成分词库的效率就会很低。
英文版的lunr现在已经支持日文,对于“帮助文档简介”,可以得到三个分词:帮助,文档,简介。这种机制是,lunr分词是由分隔符导向,同时对词长有一定限制,类似这种汉字过多的成句,只能保留每段分割的前两个字。所以在搜索的时候,成句(一般是大于俩字)目前是搜索不到的,但可以通过空格切割成句进行搜索。
改动如下:
- 进入python的安装目录修改search_index.py文件
我的目录在/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
- 修改lunr.js
我的目录:/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/user_manual_1.png){.img-fluid tag=1}
# 带说明描述
![流程图](./../img/user_manual_1.png){.img-fluid tag=2 title="测试说明"}
# 图片组
![流程图](./../img/user_manual_1.png){.img-fluid tag=3}
![流程图](./../img/user_manual_1.png){.img-fluid tag=3}
![流程图](./../img/user_manual_1.png){.img-fluid tag=3}
搞定~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。