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"", 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"{value}") 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([ '', f'{icon}', *([f'{text}'] if text else []), '', ]) class InlineBadgeExtension(Extension): def extendMarkdown(self, md): md.preprocessors.register(BadgePreprocessor(md), "inline_badges", 175) def makeExtension(**kwargs): return InlineBadgeExtension(**kwargs)