""" Simple Markdown Parser for Forum ================================ Converts basic markdown to safe HTML. Supports: bold, italic, code, links, lists, quotes, @mentions """ import re from markupsafe import Markup, escape def parse_forum_markdown(text): """ Convert markdown text to safe HTML. Supported syntax: - **bold** or __bold__ - *italic* or _italic_ - `inline code` - [link text](url) - - list items - > quotes - @mentions (highlighted) Args: text: Raw markdown text Returns: Markup object with safe HTML """ if not text: return Markup('') # Escape HTML first for security text = str(escape(text)) # Process line by line for block elements lines = text.split('\n') result_lines = [] in_list = False in_quote = False for line in lines: stripped = line.strip() # Quote blocks (> text) if stripped.startswith('> '): # Escaped > if not in_quote: result_lines.append('
') in_quote = True result_lines.append(stripped[5:]) # Remove > prefix continue elif in_quote: result_lines.append('
') in_quote = False # List items (- text) if stripped.startswith('- '): if not in_list: result_lines.append('') in_list = False result_lines.append(line) # Close open blocks if in_list: result_lines.append('') if in_quote: result_lines.append('') text = '\n'.join(result_lines) # Inline formatting (order matters!) # Code blocks (``` ... ```) text = re.sub( r'```(.*?)```', r'
\1
', text, flags=re.DOTALL ) # Inline code (`code`) text = re.sub(r'`([^`]+)`', r'\1', text) # Bold (**text** or __text__) text = re.sub(r'\*\*([^*]+)\*\*', r'\1', text) text = re.sub(r'__([^_]+)__', r'\1', text) # Italic (*text* or _text_) - careful not to match bold text = re.sub(r'(?\1', text) text = re.sub(r'(?\1', text) # Links [text](url) - only allow http/https def safe_link(match): link_text = match.group(1) url = match.group(2) if url.startswith(('http://', 'https://', '/')): return f'{link_text}' return match.group(0) # Return original if not safe text = re.sub(r'\[([^\]]+)\]\(([^)]+)\)', safe_link, text) # @mentions - highlight them text = re.sub( r'@([\w.\-]+)', r'@\1', text ) # Convert newlines to
(but not inside pre/blockquote) # Simple approach: just convert \n to
text = text.replace('\n', '
\n') return Markup(text) def register_markdown_filter(app): """Register the markdown filter with Flask app.""" app.jinja_env.filters['forum_markdown'] = parse_forum_markdown