from __future__ import annotations import html import re _MD_TO_HTML_MAP = [ (r"\*\*(.+?)\*\*", r"\1"), (r"__(.+?)__", r"\1"), (r"(?\1"), (r"(?\1"), (r"~~(.+?)~~", r"\1"), (r"`([^`\n]+?)`", r"\1"), ] _HEADING_PATTERN = re.compile(r"^(#{1,6})\s+(.+)$", re.MULTILINE) _LINK_PATTERN = re.compile(r"\[(.+?)\]\((.+?)\)") _CODE_BLOCK_PATTERN = re.compile(r"```(?:\w+)?\n(.+?)```", re.DOTALL) _BLOCKQUOTE_PATTERN = re.compile(r"^>\s?(.*)$", re.MULTILINE) _HR_PATTERN = re.compile(r"^(?:[-*_]\s*){3,}$", re.MULTILINE) _UNORDERED_LIST_PATTERN = re.compile(r"^[\-\*\+]\s+(.+)$", re.MULTILINE) _ORDERED_LIST_PATTERN = re.compile(r"^\d+\.\s+(.+)$", re.MULTILINE) _UNSAFE_TAGS = re.compile( r"<\s*(script|iframe|object|embed|form|input|svg|style|link|meta|base|applet)[^>]*>", re.IGNORECASE, ) _UNSAFE_ATTRS = re.compile( r'\s(on\w+|href\s*=\s*["\']javascript:|style\s*=\s*["\']\s*expression)', re.IGNORECASE, ) def markdown_to_matrix_html(text: str) -> str: result = text result = _CODE_BLOCK_PATTERN.sub(_code_block_replacement, result) result = _HEADING_PATTERN.sub(_heading_replacement, result) for pattern, replacement in _MD_TO_HTML_MAP: result = re.sub(pattern, replacement, result) result = _LINK_PATTERN.sub(r'\1', result) result = _UNORDERED_LIST_PATTERN.sub(r"
  • \1
  • ", result) result = _ORDERED_LIST_PATTERN.sub(r"
  • \1
  • ", result) result = _BLOCKQUOTE_PATTERN.sub(r"
    \1
    ", result) result = _HR_PATTERN.sub(r"
    ", result) result = result.replace("\n", "
    ") result = _sanitize_html(result) return result def _code_block_replacement(match: re.Match) -> str: content = match.group(1) safe_content = html.escape(content) return f"
    {safe_content}
    " def _heading_replacement(match: re.Match) -> str: level = len(match.group(1)) text_content = match.group(2) return f"{text_content}" def _sanitize_html(text: str) -> str: text = _UNSAFE_TAGS.sub("", text) text = _UNSAFE_ATTRS.sub("", text) return text