50 lines
1.6 KiB
Python
50 lines
1.6 KiB
Python
from __future__ import annotations
|
|
|
|
import re
|
|
from html import escape
|
|
|
|
from markdown.extensions import Extension
|
|
from markdown.preprocessors import Preprocessor
|
|
|
|
SHORTCODE_RE = re.compile(r"<!--\s*md:(version|default|flag)\s*(.*?)\s*-->", re.I)
|
|
|
|
class BadgePreprocessor(Preprocessor):
|
|
def run(self, lines: list[str]) -> list[str]:
|
|
return [SHORTCODE_RE.sub(self._replace, line) for line in lines]
|
|
|
|
def _replace(self, match: re.Match[str]) -> str:
|
|
kind, args = match.groups()
|
|
args = args.strip()
|
|
|
|
if kind == "version":
|
|
return _badge(":material-tag-outline:", escape(args))
|
|
|
|
if kind == "default":
|
|
value = escape(args or "none")
|
|
return _badge(":material-water:", f"<code>{value}</code>")
|
|
|
|
if kind == "flag" and args == "experimental":
|
|
return _badge(":material-test-tube:")
|
|
|
|
return match.group(0)
|
|
|
|
|
|
# Формирует HTML-разметку бейджа. Иконки остаются Zensical-шорткодами
|
|
# и рендерятся штатным `pymdownx.emoji` на следующем этапе обработки Markdown.
|
|
def _badge(icon: str, text: str = "") -> str:
|
|
return "".join([
|
|
'<span class="mdx-badge">',
|
|
f'<span class="mdx-badge__icon">{icon}</span>',
|
|
*([f'<span class="mdx-badge__text">{text}</span>'] if text else []),
|
|
'</span>',
|
|
])
|
|
|
|
|
|
class InlineBadgeExtension(Extension):
|
|
def extendMarkdown(self, md):
|
|
md.preprocessors.register(BadgePreprocessor(md), "inline_badges", 175)
|
|
|
|
|
|
def makeExtension(**kwargs):
|
|
return InlineBadgeExtension(**kwargs)
|