MkDocs 是一个快速、简单且支持第三方主题的静态站点生成器,用于构建项目文档。文档源文件用 Markdown 编写,并使用单个 YAML 配置文件进行配置。
官网地址:https://www.mkdocs.org/
最近在开发一个基于Django搭建的个人博客系统,找了一些资源和文档,发现MkDocs是一个支持markdown文档发布很强大的静态站点生成器,只需要根据命令创建文档,yaml文件配置文档路径就可以快速的访问HTML静态站点。于是看了一下mkdocs包的源码,其中utils目录下的meta.py文件是通过正则提取markdown文档的meta信息和正文内容的工具包,代码可谓短小精悍。下面对meta.py的代码做一些注释说明,还有引用的使用方法。
demo.md
先粘贴一段markdown文档内容,此篇文章的主要是提取下面文档开头---
内的key:value信息生成字典,然后将字典和文章剩余的内容返回。
---
title: Hello World
date: 2022-07-14 10:00:00
tags: [markdown, python]
categories: [python, Django]
type: blog
---
## Quick Start
### Create a new project
$ python manage.py startproject blog
### Run server
$ python manage.py runserver
More info: [Deployment](https://docs.djangoproject.com/en/4.0/)
meta.py
粘贴了meta.py的主要代码,然后在代码上添加注释方便观看和理解。当然代码文件开头有版权信息,使用此文件不要删掉版权信息。
这里对下面正则表达式做一些说明:
- 解析:
^-{3}
以—开头[ \t]*\n
匹配\n结尾或\t\n结尾换行符^-{3}[ \t]*\n
以—开头,后边可以有空格,但是以\n结尾的一行数据(.*?\n)
配置^-{3}[ \t]*\n 之后包含\n的数据(?:\.{3}|-{3})[ \t]*\n
匹配…或者—字符串,后边可以有空格,但是以\n结尾的一行数据
- 参考:
*
代表匹配除换行符之外的所有字符.*?
后面多个问号,代表非贪婪模式,也就是说只匹配符合条件的最少字符(?: re)
类似 (…), 但是不表示一个组\s
匹配任意空白字符,等价于 [ \t\n\r\f]。
原文件地址: https://github.com/mkdocs/mkdocs/blob/master/mkdocs/utils/meta.py
import re
import yaml
try:
from yaml import CSafeLoader as SafeLoader
except ImportError: # pragma: no cover
from yaml import SafeLoader
# 匹配yaml格式的数据,数据始以---开始,以---或...结束的多行数据。
YAML_RE = re.compile(r'^-{3}[ \t]*\n(.*?\n)(?:\.{3}|-{3})[ \t]*\n', re.UNICODE | re.DOTALL)
# 匹配key: value形式数据
META_RE = re.compile(r'^[ ]{0,3}(?P<key>[A-Za-z0-9_-]+):\s*(?P<value>.*)')
# 匹配以4个空格开头或者tab开头的value数据
META_MORE_RE = re.compile(r'^([ ]{4}|\t)(\s*)(?P<value>.*)')
def get_data(doc):
data = {}
# 先用yaml正则匹配
m = YAML_RE.match(doc)
if m:
try:
# group(1)匹配(.*?\n)正则部分,也就是去除以---开头和结尾的两行数据
# yaml.load:解析key: value格式数据,SafeLoader:安全地加载YAML语言的子集。
data = yaml.load(m.group(1), SafeLoader)
if isinstance(data, dict):
# m.end()正则匹配到的最后位置开始截取,并删除开头的\n换行符
doc = doc[m.end():].lstrip('\n')
else:
data = {}
return doc, data
except Exception:
print(str(Exception))
# yaml解析失败则将文章分行,然后通过META_RE和META_MORE_RE正则匹配解析
lines = doc.replace('\r\n', '\n').replace('\r', '\n').split('\n')
# 下面这段没有特别函数,基于正则解析后数据提取逻辑,请自行观看就好~
key = None
while lines:
line = lines.pop(0) # 如果成功解析则删除,对应下面的解析失败再添加
if line.strip() == '':
break # blank line - done
m1 = META_RE.match(line)
if m1:
key = m1.group('key').lower().strip()
value = m1.group('value').strip()
if key in data:
data[key] += f' {value}'
else:
data[key] = value
else:
m2 = META_MORE_RE.match(line)
if m2 and key:
# Add another line to existing key
data[key] += ' {}'.format(m2.group('value').strip())
else:
lines.insert(0, line) # 解析失败再添加回原数据
break # no meta data - done
return '\n'.join(lines).lstrip('\n'), data
调用meta.py文件
在meta.py文件同目录下创建md_utils.py,然后输入下述内容并测试。
import meta
import os
def get_md_info(file_path):
with open(file_path, encoding='utf-8', errors='strict') as f:
source = f.read()
return meta.get_data(source)
if __name__ == '__main__':
base_path = "md_utils\docs"
file_path = os.path.join(base_path, "demo.md")
meta, doc = get_md_info(file_path=file_path)
print("# meta 字典内容:\n", meta)
print("# doc 文本内容:\n", doc)
执行md_utils.py文件,输出内容如下:
# meta 字典内容:
{'title': 'Hello World', 'date': datetime.datetime(2022, 7, 14, 10, 0), 'tags': ['markdown', 'python'], 'categories': ['python', 'Django'], 'type': 'blog'}
# doc 文本内容:
## Quick Start
### Create a new project
$ python manage.py startproject blog
### Run server
$ python manage.py runserver
More info: [Deployment](https://docs.djangoproject.com/en/4.0/)
小结
MkDocs是一个很成熟且轻量化的markdown静态站点生成器,可以快速的部署在github站点实现访问。MkDocs用到了python的markdown
包将文件转成html,同时也写了很好的markdown包扩展类,这个也是后期要学习的地方。后面会进一步完善自己的博客平台,然后分享给大家。感谢阅读!