markdown解析高亮及mermaid

记录于  2023-09-11


我平时用typora写记录,完稿后再上传到网站上,typora支持需要许多的第三方markdown扩展语法,写起来很方便,但是我网站使用的python解析库——markdown,将markdown文本转为html,它并不支持第三方语法,我比较烦心高亮和mermaid语法的支持,所以花了一点时间给markdown库写了两个插件,分别用来解析这两种语法。

自定义解析扩展markdown语法

解析,其实就是将目标文本替换成特定的其他文本,比如html标签,自定义的markdown库的插件,可以选择在它解析前后进行自定义解析,处理原理是一样的,不同的是,在markdow它解析前,你处理的对象是普通的markdow文本,而解析后处理的是htnl文本。

这里,我选择用正则表达式来实现具体的解析操作,高亮的语法是两个==包裹的文本内容,比如需要将其查找出来,并将其内容替换到mark标签内。

import markdown
import re
class HighlightExtension(markdown.Extension):
    def extendMarkdown(self, md: Markdown):
       """
       :param md: Markdown实例
       :return: list
       """
        md.registerExtension(self)
        md.preprocessors.register(HighlightPreprocessor(), 'highlight_preprocessor', 5)


class HighlightPreprocessor(markdown.preprocessors.Preprocessor):
    def run(self, lines: list) -> list:
       """
       执行函数
       :param lines: 文本列表
       :return: list
       """
        text = '\n'.join(lines)
        # 正则模式字符串
        pattern = r'==(.+?)=='
        # 替换匹配结果
        highlighted_text = re.sub(pattern, r'<mark>\1</mark>', text)
        return highlighted_text.splitlines()

# 测试
def md2html(text):
    """
    :param text: str
    :return: str
    """
    html = markdown.markdown(text, extensions=[
        HighlightExtension()# 引入自定义的插件
    ])
    return html

现在,就能正常解析高亮文本了,比如:这是高亮内容

解析mermaid代码

Mermaid是一个基于Javascript的图表绘制工具,它能解析类似markd的语法,然后生成图像,让你像以写文章一样的方式的绘制图表,非常顺滑。

markdown 到mermaid的过程中,除了将mermaid的代码块解析为特定的标签,还需在html文档中引入mermaid的依赖文件,

<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>

然后添加一个js标签,待文档加载完成后渲染。

<script defer>
    mermaid.initialize({ startOnLoad: true });
</script>
import markdown
import re

# 继承Extension类
class MermaidExtension(markdown.Extension):
    def extendMarkdown(self, md: Markdown):
       """
       :param md: Markdown 实例
       :return: 
       """
        # 注册插件
        md.registerExtension(self)
        # 注册解析前处理器
        md.preprocessors.register(MermaidPreprocessor(), 'mermaid_preprocessor', 1000)
        # 注册解析后处理器
        # md.postprocessors.register(MermaidPostprocessor(), 'mermaid_postprocessor', 25)

# 解析前处理器
class MermaidPreprocessor(markdown.preprocessors.Preprocessor):
   def run(self, lines: list) -> list:
       """
       执行函数
       :param lines: 文本列表
       :return: list
       """
        text = '\n'.join(lines)
        post_text = re.sub(pattern, r'<div class="mermaid">\1</div>', text, flags=re.S)
        # 分解行
        return post_text.splitlines()

# 解析后处理器
class MermaidPostprocessor(markdown.postprocessors.Postprocessor):
   def run(self, text: str) -> str:
       """
       执行函数
       :param text: 文本
       :return: 
       """
       pattern = r"<code>mermaid(.+?)</code>"
       post_text = re.sub(pattern, r'<div class="mermaid">\1</div>', text, flags=re.S )
       return post_text



# 测试
def md2html(text):
    """
    :param text: str
    :return: str
    """
    html = markdown.markdown(text, extensions=[
        MermaidExtension(),# 引入自定义的插件
    ])
    return html

你看,现在就能直接在markdown中绘图了,amazing!

这是一个表示饼图的语法:

pie title 水果
    "香蕉" : 386
    "苹果" : 85
    "橘子" : 15

渲染之后如下:

pie title 水果 "香蕉" : 386 "苹果" : 85 "橘子" : 15

流程图:

flowchart TD
    A[Christmas] -->|Get money| B(Go shopping)
    B --> C{Let me think}
    C -->|One| D[Laptop]
    C -->|Two| E[iPhone]
    C -->|Three| F[fa:fa-car Car]
flowchart TD A[Christmas] -->|Get money| B(Go shopping) B --> C{Let me think} C -->|One| D[Laptop] C -->|Two| E[iPhone] C -->|Three| F[fa:fa-car Car]

类图:

classDiagram
    Animal <|-- Duck
    Animal <|-- Fish
    Animal <|-- Zebra
    Animal : +int age
    Animal : +String gender
    Animal: +isMammal()
    Animal: +mate()
    class Duck{
      +String beakColor
      +swim()
      +quack()
    }
    class Fish{
      -int sizeInFeet
      -canEat()
    }
    class Zebra{
      +bool is_wild
      +run()
    }
classDiagram Animal <|-- Duck Animal <|-- Fish Animal <|-- Zebra Animal : +int age Animal : +String gender Animal: +isMammal() Animal: +mate() class Duck{ +String beakColor +swim() +quack() } class Fish{ -int sizeInFeet -canEat() } class Zebra{ +bool is_wild +run() }

状态图:

stateDiagram-v2
    [*] --> Still
    Still --> [*]
    Still --> Moving
    Moving --> Still
    Moving --> Crash
    Crash --> [*]
stateDiagram-v2 [*] --> Still Still --> [*] Still --> Moving Moving --> Still Moving --> Crash Crash --> [*]

ER图:

erDiagram
    CUSTOMER }|..|{ DELIVERY-ADDRESS : has
    CUSTOMER ||--o{ ORDER : places
    CUSTOMER ||--o{ INVOICE : "liable for"
    DELIVERY-ADDRESS ||--o{ ORDER : receives
    INVOICE ||--|{ ORDER : covers
    ORDER ||--|{ ORDER-ITEM : includes
    PRODUCT-CATEGORY ||--|{ PRODUCT : contains
    PRODUCT ||--o{ ORDER-ITEM : "ordered in"
erDiagram CUSTOMER }|..|{ DELIVERY-ADDRESS : has CUSTOMER ||--o{ ORDER : places CUSTOMER ||--o{ INVOICE : "liable for" DELIVERY-ADDRESS ||--o{ ORDER : receives INVOICE ||--|{ ORDER : covers ORDER ||--|{ ORDER-ITEM : includes PRODUCT-CATEGORY ||--|{ PRODUCT : contains PRODUCT ||--o{ ORDER-ITEM : "ordered in"

甘特图:

gantt
    title A Gantt Diagram
    dateFormat  YYYY-MM-DD
    section Section
    A task           :a1, 2014-01-01, 30d
    Another task     :after a1  , 20d
    section Another
    Task in sec      :2014-01-12  , 12d
    another task      : 24d
gantt title A Gantt Diagram dateFormat YYYY-MM-DD section Section A task :a1, 2014-01-01, 30d Another task :after a1 , 20d section Another Task in sec :2014-01-12 , 12d another task : 24d

旅程图:

journey
    title My working day
    section Go to work
      Make tea: 5: Me
      Go upstairs: 3: Me
      Do work: 1: Me, Cat
    section Go home
      Go downstairs: 5: Me
      Sit down: 3: Me
journey title My working day section Go to work Make tea: 5: Me Go upstairs: 3: Me Do work: 1: Me, Cat section Go home Go downstairs: 5: Me Sit down: 3: Me

Git关系图:

gitGraph
    commit
    commit
    branch develop
    checkout develop
    commit
    commit
    checkout main
    merge develop
    commit
    commit
gitGraph commit commit branch develop checkout develop commit commit checkout main merge develop commit commit

思维导图:

mindmap
  root((mindmap))
    Origins
      Long history
      ::icon(fa fa-book)
      Popularisation
        British popular psychology author Tony Buzan
    Research
      On effectivness<br/>and features
      On Automatic creation
        Uses
            Creative techniques
            Strategic planning
            Argument mapping
    Tools
      Pen and paper
      Mermaid
mindmap root((mindmap)) Origins Long history ::icon(fa fa-book) Popularisation British popular psychology author Tony Buzan Research On effectivness
and features On Automatic creation Uses Creative techniques Strategic planning Argument mapping Tools Pen and paper Mermaid

更多图表语法,可以前往该网站查看Online FlowChart & Diagrams Editor - Mermaid Live Editor