静态网站框架mkdocs+material学习笔记
这个静态网站的框架已经从Pelican换成了Mkdocs,搭配mkdocs-material主题,托管在GitHub上,使用自有域名。
把一些技术细节记在这里,备忘。
问题
Caution
以汉字开头的markdown文件可能导致奇怪的问题。可以数字时间开头,如“2021-03-17”。
安装
1
2
3
4
5
6
7
8
9
10
11
12 | pip install mkdocs-material
# 以下是插件,按需要安装
pip install mkdocs-mermaid2-plugin
pip install mknotebooks
pip install mkdocs-macros-plugin
pip install mkdocs-git-revision-date-plugin
# pip install mkdocs-redirects
pip install jieba
# pip install click-man
# click-man --target path/to/man/pages mkdocs
|
生成项目
设置文件
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 | # mkdocs.yml
site_name: 嬉戏实验室
nav: # 导航结构
- Home: index.md # [定制主页](https://github.com/squidfunk/mkdocs-material/issues/1996)
- 儿童识字:
- '2020-06-24-自制儿童启蒙集中识字语料库与分级字表.md'
- '2020-06-24-自制儿童启蒙集中识字分级字表.md'
- 老编辑的效率工具:
- '2018-11-7-奇技淫巧志.md'
- '两种markdown文件解析方法': '2021-02-04-两种markdown文件解析方法.ipynb' # 原本只支持markdown文件,其他文件需要插件支持,同时可能需要制定标题
- About: about.md
theme:
name: material # 指定mkdocs-material模板
favicon: img/favicon.ico
logo: img/logo.png
palette: # 更改配色
primary: blue grey # 主色
accent: pink # 强调色
features:
- navigation.instant
- navigation.tabs # 栏头加标签(一级导航)
- navigation.tabs.sticky # 固定(浏览时不收起)标签
language: zh
custom_dir: overrides # 指定模板文件夹,放自定的覆盖模板
markdown_extensions:
- meta # 支持markdown博客文件头的元数据,比如标题
- toc:
permalink: "#"
baselevel: 1
separator: "_"
- footnotes # 支持脚注
- admonition # 支持提示块
- pymdownx.details # 提示块可折叠
- attr_list
- pymdownx.inlinehilite # 支持行内语法高亮
# - pymdownx.highlight: # 支持代码块语法高亮,!!!跟mermaid冲突
# linenums: true # 显示行号
- pymdownx.superfences: # 可在列表等处嵌入块
# make exceptions to highlighting of code:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:mermaid2.fence_mermaid
plugins:
- mknotebooks:
enable_default_jupyter_cell_styling: false
enable_default_pandas_dataframe_styling: false
# write_markdown: true
- search: # 搜索
lang:
- en
- ja # 日文,也勉强支持中文
separator: '[\s\-\.]+' # 分词分隔符
# prebuild_index: true # 预制索引,不成功
- mermaid2:
arguments:
securityLevel: 'loose'
- macros:
# 替换默认的jinja宏标志{{}},否则类似的地方可能报错
# 或用raw标签包裹
# [[% raw %]]
j2_block_start_string: '[[%'
j2_block_end_string: '%]]'
j2_variable_start_string: '[['
j2_variable_end_string: ']]'
# [[% endraw %]]
# - redirects: # 重定向,改动文件名时使用
# redirect_maps:
# path/to/old/file.md: path/to/new/file.md
# google_analytics: # 谷歌分析
# - XX-XXXXXXXXX-X
# - auto
gtag:
- G-XXXXXXXXXX
extra:
social: # 社交账号
- icon: fontawesome/brands/github
link: https://github.com/Fusyong
# name: Fusyong on Github
- icon: fontawesome/brands/facebook
link: https://www.facebook.com/Aahuaang/
# name: Fusyong on Facebook
- icon: fontawesome/brands/twitter
link: https://twitter.com/fusyong
# name: Fusyong on Twitter
# disqus: XXXXXXXX # disqus评论插件
|
运行服务器
| cd your\blog\dir
mkdocs serve
|
生成发布版本
| cd your\blog\dir\
mkdocs build
|
or清理文件夹后在生成
| cd your\blog\dir\
mkdocs build --clean
|
标题取用顺序
- 从配置文件的导航配置
nav
中;
- 博文元数据的
title
值;
- Markdown的第一个1级标题;
- 博文的文件名。
mkdocs-material模板覆盖文件夹overrides
的结构
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 | .
├─ .icons/ # Bundled icon sets
├─ assets/
│ ├─ images/ # Images and icons
│ ├─ javascripts/ # JavaScript
│ └─ stylesheets/ # Stylesheets
├─ partials/
│ ├─ integrations/ # Third-party integrations
│ │ ├─ analytics.html # - Google Analytics
│ │ └─ disqus.html # - Disqus
│ ├─ languages/ # Localized languages
│ ├─ footer.html # Footer bar
│ ├─ header.html # Header bar
│ ├─ language.html # Localized labels
│ ├─ logo.html # Logo in header and sidebar
│ ├─ nav.html # 主导航
│ ├─ nav-item.html # 主导航条目
│ ├─ palette.html # Color palette
│ ├─ search.html # Search box
│ ├─ social.html # Social links
│ ├─ source.html # Repository information
│ ├─ source-date.html # Last updated date
│ ├─ source-link.html # Link to source file
│ ├─ tabs.html # Tabs navigation
│ ├─ tabs-item.html # Tabs navigation item
│ ├─ toc.html # Table of contents
│ └─ toc-item.html # Table of contents item
├─ 404.html # 404错误页
├─ base.html # Base template
└─ main.html # Default page
|
下载官方库src
中的对应文件,修改后放在上述的本地文件夹overrides
中的相应位置。
在导航条目下加一行更新时间
拷贝官方的nav-item.html
文件到overrides\partials\nav-item.html
,修改其中的一段如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | <!-- Main navigation item -->
...
<li class="{{ class }}">
<a href="{{ nav_item.url | url }}" class="md-nav__link">
{{ nav_item.title }}
</a>
<!-- 这里是修改:根据markdown文章的meta数据,显示Status值为new的文章的Modified时间 -->
{% if nav_item.meta.Status and nav_item.meta.Status == "new" %}
<font size=0.5em color="grey">
{{ nav_item.meta.Modified }} 更新
</font>
<br>
{% endif %}
<!-- 修改结束 -->
</li>
...
|
markdown_extensions
Markdown格式支持:
提示块插件
设置如下:
| markdown_extensions:
- admonition # 提示块
- pymdownx.details # 提示块可折叠
|
语法如下:
| !!! note "可以双引号中指明标题"
随便多少缩进文本.
空行分段.
|
效果如下:
可以双引号中指明标题
随便多少缩进文本.
空行分段.
note
用作CSS类名和默认标题,只能是一个单词例如
效果如下:
如果不想要标题则引号内留空""
。
效果是:
可以附加额外的CSS类,用空格隔开,会附在type.
后:
| !!! danger highlight blink "不要在家里做"
...
|
效果:
共支持这些类型
- note, seealso
- abstract, summary, tldr
- info, todo
- tip, hint, important
- success, check, done
- question, help, faq
- warning, caution, attention
- failure, fail, missing
- danger, error
- bug
- example
- quote, cite
插件
markdown增强
目前支持
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 | import re
from mkdocs.plugins import BasePlugin
class Extended_markdown(BasePlugin):
def __init__(self):
# 行内脚注格式`^[脚注内容]`
self.inline_footnote_pattern = re.compile(r"\^\[([^\[\]]+)\]")
self.inline_footnote_inplace = r"[^\1]"
# 替换`[汉字]^(拼音)`表达式为html的ruby标签
self.pinyin_pattern = re.compile(r"\[([^\[\]]+)\]\^\(([^\(\)]+)\)")
self.ruby_pattern = r"<ruby>\1<rp>(</rp><rt>\2</rt><rp>)</rp></ruby>"
# 处理每篇文章的markdown文件
def on_page_markdown(self, markdown, page, config, files):
"""
"""
# 替换拼音
markdown = re.sub(self.pinyin_pattern,
self.ruby_pattern,
markdown)
# 抽取行内脚注内容
footnote_list = (f'[^{m.group(1)}]: {m.group(1)}'
for m in re.finditer(self.inline_footnote_pattern, markdown))
if footnote_list:
# 替换行内脚注
markdown = re.sub(self.inline_footnote_pattern,
self.inline_footnote_inplace,
markdown)
# 附加脚注
markdown = markdown + "\n" + "\n".join(footnote_list)
return markdown
|
简单支持中文搜索
更新:冯唐正先生已经做出相当完善的方案,并已经提交到官方代码库,方案详见A Possible Version for Chinese Search Support #3761
找了一遍,网上为Mkdocs实现中文搜索的方法都不灵,而且挺麻烦。
以下只是简单更改mkdocs-material默认的search组件,对内容进行分词,以支持简单的中文搜索。之所以说“简单”,是说引擎不会为用户分词,用户输入的关键词必须自己用空格分开,像英文那样。
在配置中启用search插件,指定英语、日语和分隔符:
| plugins:
- search:
lang:
- en
- ja
separator: '[\s\-\.]+'
|
更改默认的search插件mkdocs.contrib.search.search_index.py
,添加有注释的代码行,对内容进行中文分词:
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 | import jieba # 中文分词用模块
class SearchIndex:
# 以上不变,略
def _add_entry(self, title, text, loc):
"""
A simple wrapper to add an entry and ensure the contents
is UTF8 encoded.
"""
text = text.replace('\u3000', ' ') # 替换中文全角空格
text = text.replace('\u00a0', ' ')
text = re.sub(r'[ \t\n\r\f\v]+', ' ', text.strip())
# 给正文分词
text_seg_list = jieba.cut_for_search(text) # 结巴分词,搜索引擎模式,召回率更高
text = " ".join(text_seg_list) # 用空格连接词语
# 给标题分词
title_seg_list = jieba.cut(title, cut_all=False) # 结巴分词,精确模式,更可读
title = " ".join(title_seg_list) # 用空格连接词语
self._entries.append({
'title': title,
'text': str(text.encode('utf-8'), encoding='utf-8'),
'location': loc
})
# 以下不变,略
|
实际效果参见我的博客,如下:
也可以把search组件复制、更改为自己的插件,参考插件fastsearch。
如果要更改搜索引擎的行为,比如给输入的搜索内容进行分词、排除停用词等,可参考lunr的日语组件
通过变量和宏释放Mkdocs的威力。号称:
Note
This is more than a plugin: it's a mini-framework!
似乎比较慢。不如用插件直接替换markdown锚点。
部署到GitHub
参见GitHub Pages官方文档