from __future__ import annotations import re _LINK_PATTERN = re.compile(r"\[([^\]]*)\]\([^)]*\)") _IMG_PATTERN = re.compile(r"!\[([^\]]*)\]\([^)]*\)") _BOLD_PATTERN = re.compile(r"\*\*(.+?)\*\*") _BOLD_ALT_PATTERN = re.compile(r"__(.+?)__") _ITALIC_PATTERN = re.compile(r"\*(.+?)\*") _ITALIC_ALT_PATTERN = re.compile(r"_(.+?)_") _STRIKETHROUGH_PATTERN = re.compile(r"~~(.+?)~~") _FENCED_CODE_PATTERN = re.compile(r"```[^\n]*\n(.*?)```", re.DOTALL) _INLINE_CODE_PATTERN = re.compile(r"`([^`]+)`") _HEADING_PATTERN = re.compile(r"^#{1,6}\s+", re.MULTILINE) _UNORDERED_LIST_PATTERN = re.compile(r"^[\-\*]\s+", re.MULTILINE) _ORDERED_LIST_PATTERN = re.compile(r"^\d+\.\s+", re.MULTILINE) _BLOCKQUOTE_PATTERN = re.compile(r"^>\s?", re.MULTILINE) _HR_PATTERN = re.compile(r"^[\-\*_]{3,}\s*$", re.MULTILINE) _MULTISPACE_PATTERN = re.compile(r"[ \t]+") _MULTINEWLINE_PATTERN = re.compile(r"\n{3,}") def strip_twitch_markdown(text: str) -> str: if not text: return text text = _IMG_PATTERN.sub("", text) text = _LINK_PATTERN.sub(r"\1", text) text = _FENCED_CODE_PATTERN.sub(r"\1", text) text = _HR_PATTERN.sub("", text) text = _BOLD_PATTERN.sub(r"\1", text) text = _BOLD_ALT_PATTERN.sub(r"\1", text) text = _ITALIC_PATTERN.sub(r"\1", text) text = _ITALIC_ALT_PATTERN.sub(r"\1", text) text = _STRIKETHROUGH_PATTERN.sub(r"\1", text) text = _INLINE_CODE_PATTERN.sub(r"\1", text) text = _HEADING_PATTERN.sub("", text) text = _ORDERED_LIST_PATTERN.sub("", text) text = _UNORDERED_LIST_PATTERN.sub("", text) text = _BLOCKQUOTE_PATTERN.sub("", text) text = _MULTISPACE_PATTERN.sub(" ", text) text = _MULTINEWLINE_PATTERN.sub("\n\n", text) return text.strip()