Python mkdocs包的meta.py源码文件解析与使用

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包扩展类,这个也是后期要学习的地方。后面会进一步完善自己的博客平台,然后分享给大家。感谢阅读!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我在那路边

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值