2023-09-06 13:44:00 +01:00
|
|
|
from html import unescape
|
|
|
|
from re import Match
|
|
|
|
from textwrap import dedent
|
|
|
|
from typing import Any
|
|
|
|
|
2023-10-25 01:03:35 +01:00
|
|
|
from html5tagger import HTML, E
|
2023-09-06 13:44:00 +01:00
|
|
|
from mistune import HTMLRenderer
|
|
|
|
from mistune.block_parser import BlockParser
|
|
|
|
from mistune.core import BlockState
|
|
|
|
from mistune.directives import DirectivePlugin, RSTDirective
|
|
|
|
from mistune.markdown import Markdown
|
|
|
|
|
2023-10-25 03:02:26 +01:00
|
|
|
|
2023-09-06 13:44:00 +01:00
|
|
|
class Mermaid(DirectivePlugin):
|
2023-10-25 04:13:13 +01:00
|
|
|
def parse(self, block: BlockParser, m: Match, state: BlockState) -> dict[str, Any]:
|
2023-09-06 13:44:00 +01:00
|
|
|
info = m.groupdict()
|
|
|
|
|
|
|
|
new_state = block.state_cls()
|
|
|
|
new_state.process(dedent(info["text"]))
|
|
|
|
block.parse(new_state)
|
|
|
|
|
|
|
|
text = HTML(info["text"].strip())
|
|
|
|
|
|
|
|
return {
|
|
|
|
"type": "mermaid",
|
|
|
|
"text": text,
|
|
|
|
"children": [{"type": "text", "text": text}],
|
|
|
|
"attrs": {},
|
|
|
|
}
|
|
|
|
|
|
|
|
def __call__(self, directive: RSTDirective, md: Markdown) -> None: # type: ignore
|
|
|
|
directive.register("mermaid", self.parse)
|
|
|
|
|
|
|
|
if md.renderer.NAME == "html":
|
|
|
|
md.renderer.register("mermaid", self._render_mermaid)
|
|
|
|
|
|
|
|
def _render_mermaid(self, renderer: HTMLRenderer, text: str, **attrs):
|
|
|
|
return str(E.div(class_="mermaid")(HTML(unescape(text))))
|