Conversion of User Guide to the SHH stack (#2781)
This commit is contained in:
0
guide/webapp/display/plugins/__init__.py
Normal file
0
guide/webapp/display/plugins/__init__.py
Normal file
40
guide/webapp/display/plugins/attrs.py
Normal file
40
guide/webapp/display/plugins/attrs.py
Normal file
@@ -0,0 +1,40 @@
|
||||
from re import Match
|
||||
from textwrap import dedent
|
||||
from typing import Any
|
||||
|
||||
from mistune.block_parser import BlockParser
|
||||
from mistune.core import BlockState
|
||||
from mistune.directives import DirectivePlugin
|
||||
|
||||
from html5tagger import HTML, E
|
||||
|
||||
|
||||
class Attributes(DirectivePlugin):
|
||||
def __call__(self, directive, md):
|
||||
directive.register("attrs", self.parse)
|
||||
|
||||
if md.renderer.NAME == "html":
|
||||
md.renderer.register("attrs", self._render)
|
||||
|
||||
def parse(
|
||||
self, block: BlockParser, m: Match, state: BlockState
|
||||
) -> dict[str, Any]:
|
||||
info = m.groupdict()
|
||||
options = dict(self.parse_options(m))
|
||||
new_state = block.state_cls()
|
||||
new_state.process(dedent(info["text"]))
|
||||
block.parse(new_state)
|
||||
options.setdefault("class_", "additional-attributes")
|
||||
classes = options.pop("class", "")
|
||||
if classes:
|
||||
options["class_"] += f" {classes}"
|
||||
|
||||
return {
|
||||
"type": "attrs",
|
||||
"text": info["text"],
|
||||
"children": new_state.tokens,
|
||||
"attrs": options,
|
||||
}
|
||||
|
||||
def _render(self, _, text: str, **attrs) -> str:
|
||||
return str(E.div(HTML(text), **attrs))
|
||||
45
guide/webapp/display/plugins/columns.py
Normal file
45
guide/webapp/display/plugins/columns.py
Normal file
@@ -0,0 +1,45 @@
|
||||
from re import Match
|
||||
from textwrap import dedent
|
||||
from typing import Any
|
||||
|
||||
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
|
||||
|
||||
|
||||
class Column(DirectivePlugin):
|
||||
def parse(
|
||||
self, block: BlockParser, m: Match, state: BlockState
|
||||
) -> dict[str, Any]:
|
||||
info = m.groupdict()
|
||||
|
||||
new_state = block.state_cls()
|
||||
new_state.process(dedent(info["text"]))
|
||||
block.parse(new_state)
|
||||
|
||||
return {
|
||||
"type": "column",
|
||||
"text": info["text"],
|
||||
"children": new_state.tokens,
|
||||
"attrs": {},
|
||||
}
|
||||
|
||||
def __call__( # type: ignore
|
||||
self, directive: RSTDirective, md: Markdown
|
||||
) -> None:
|
||||
directive.register("column", self.parse)
|
||||
|
||||
if md.renderer.NAME == "html":
|
||||
md.renderer.register("column", self._render_column)
|
||||
|
||||
def _render_column(self, renderer: HTMLRenderer, text: str, **attrs):
|
||||
start = (
|
||||
'<div class="columns mt-3 is-multiline">\n'
|
||||
if attrs.get("first")
|
||||
else ""
|
||||
)
|
||||
end = "</div>\n" if attrs.get("last") else ""
|
||||
col = f'<div class="column is-half">{text}</div>\n'
|
||||
return start + (col) + end
|
||||
31
guide/webapp/display/plugins/hook.py
Normal file
31
guide/webapp/display/plugins/hook.py
Normal file
@@ -0,0 +1,31 @@
|
||||
from mistune.core import BlockState
|
||||
from mistune.directives import DirectivePlugin, RSTDirective
|
||||
from mistune.markdown import Markdown
|
||||
|
||||
|
||||
class Hook(DirectivePlugin):
|
||||
def __call__( # type: ignore
|
||||
self, directive: RSTDirective, md: Markdown
|
||||
) -> None:
|
||||
if md.renderer.NAME == "html":
|
||||
md.before_render_hooks.append(self._hook)
|
||||
|
||||
def _hook(self, md: Markdown, state: BlockState) -> None:
|
||||
prev = None
|
||||
for idx, token in enumerate(state.tokens):
|
||||
for type_ in ("column", "tab"):
|
||||
if token["type"] == type_:
|
||||
maybe_next = (
|
||||
state.tokens[idx + 1]
|
||||
if idx + 1 < len(state.tokens)
|
||||
else None
|
||||
)
|
||||
token.setdefault("attrs", {})
|
||||
if prev and prev["type"] != type_:
|
||||
token["attrs"]["first"] = True
|
||||
if (
|
||||
maybe_next and maybe_next["type"] != type_
|
||||
) or not maybe_next:
|
||||
token["attrs"]["last"] = True
|
||||
|
||||
prev = token
|
||||
41
guide/webapp/display/plugins/mermaid.py
Normal file
41
guide/webapp/display/plugins/mermaid.py
Normal file
@@ -0,0 +1,41 @@
|
||||
from html import unescape
|
||||
from re import Match
|
||||
from textwrap import dedent
|
||||
from typing import Any
|
||||
|
||||
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
|
||||
|
||||
from html5tagger import HTML, E
|
||||
|
||||
|
||||
class Mermaid(DirectivePlugin):
|
||||
def parse(
|
||||
self, block: BlockParser, m: Match, state: BlockState
|
||||
) -> dict[str, Any]:
|
||||
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))))
|
||||
47
guide/webapp/display/plugins/notification.py
Normal file
47
guide/webapp/display/plugins/notification.py
Normal file
@@ -0,0 +1,47 @@
|
||||
from mistune.directives import Admonition
|
||||
|
||||
from html5tagger import HTML, E
|
||||
|
||||
|
||||
class Notification(Admonition):
|
||||
SUPPORTED_NAMES = {
|
||||
"success",
|
||||
"info",
|
||||
"warning",
|
||||
"danger",
|
||||
"tip",
|
||||
"new",
|
||||
"note",
|
||||
}
|
||||
|
||||
def __call__(self, directive, md):
|
||||
for name in self.SUPPORTED_NAMES:
|
||||
directive.register(name, self.parse)
|
||||
|
||||
if md.renderer.NAME == "html":
|
||||
md.renderer.register("admonition", self._render_admonition)
|
||||
md.renderer.register(
|
||||
"admonition_title", self._render_admonition_title
|
||||
)
|
||||
md.renderer.register(
|
||||
"admonition_content", self._render_admonition_content
|
||||
)
|
||||
|
||||
def _render_admonition(self, _, text, name, **attrs) -> str:
|
||||
return str(
|
||||
E.div(
|
||||
HTML(text),
|
||||
class_=f"notification is-{name}",
|
||||
)
|
||||
)
|
||||
|
||||
def _render_admonition_title(self, _, text) -> str:
|
||||
return str(
|
||||
E.p(
|
||||
text,
|
||||
class_="notification-title",
|
||||
)
|
||||
)
|
||||
|
||||
def _render_admonition_content(self, _, text) -> str:
|
||||
return text
|
||||
26
guide/webapp/display/plugins/span.py
Normal file
26
guide/webapp/display/plugins/span.py
Normal file
@@ -0,0 +1,26 @@
|
||||
import re
|
||||
|
||||
from mistune.markdown import Markdown
|
||||
|
||||
|
||||
def parse_inline_span(inline, m: re.Match, state):
|
||||
state.append_token(
|
||||
{
|
||||
"type": "span",
|
||||
"attrs": {"classes": m.group("classes")},
|
||||
"raw": m.group("content"),
|
||||
}
|
||||
)
|
||||
return m.end()
|
||||
|
||||
|
||||
SPAN_PATTERN = r"{span:(?:(?P<classes>[^\:]+?):)?(?P<content>.*?)}"
|
||||
|
||||
|
||||
def span(md: Markdown) -> None:
|
||||
md.inline.register(
|
||||
"span",
|
||||
SPAN_PATTERN,
|
||||
parse_inline_span,
|
||||
before="link",
|
||||
)
|
||||
50
guide/webapp/display/plugins/tabs.py
Normal file
50
guide/webapp/display/plugins/tabs.py
Normal file
@@ -0,0 +1,50 @@
|
||||
from re import Match
|
||||
from textwrap import dedent
|
||||
from typing import Any
|
||||
|
||||
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
|
||||
|
||||
|
||||
class Tabs(DirectivePlugin):
|
||||
def parse(
|
||||
self, block: BlockParser, m: Match, state: BlockState
|
||||
) -> dict[str, Any]:
|
||||
info = m.groupdict()
|
||||
|
||||
new_state = block.state_cls()
|
||||
new_state.process(dedent(info["text"]))
|
||||
block.parse(new_state)
|
||||
|
||||
return {
|
||||
"type": "tab",
|
||||
"text": info["text"],
|
||||
"children": new_state.tokens,
|
||||
"attrs": {
|
||||
"title": info["title"],
|
||||
},
|
||||
}
|
||||
|
||||
def __call__( # type: ignore
|
||||
self,
|
||||
directive: RSTDirective,
|
||||
md: Markdown,
|
||||
) -> None:
|
||||
directive.register("tab", self.parse)
|
||||
|
||||
if md.renderer.NAME == "html":
|
||||
md.renderer.register("tab", self._render_tab)
|
||||
|
||||
def _render_tab(self, renderer: HTMLRenderer, text: str, **attrs):
|
||||
start = '<div class="tabs mt-6"><ul>\n' if attrs.get("first") else ""
|
||||
end = (
|
||||
'</ul></div><div class="tab-display"></div>\n'
|
||||
if attrs.get("last")
|
||||
else ""
|
||||
)
|
||||
content = f'<div class="tab-content">{text}</div>\n'
|
||||
tab = f'<li><a>{attrs["title"]}</a>{content}</li>\n'
|
||||
return start + tab + end
|
||||
Reference in New Issue
Block a user