From 7cbd3bb1e760dff0f4a3cc080f0e48dc1f7a664a Mon Sep 17 00:00:00 2001 From: Maciej Pienczyn Date: Mon, 23 Feb 2026 08:54:35 +0100 Subject: [PATCH] fix: forum markdown parser - autolinks, line spacing, Windows line endings - Normalize \r\n to \n before processing - Strip leading whitespace from lines (textarea indentation) - Auto-link bare URLs works correctly inside list items - Smart
insertion: skip block elements (ul, li, blockquote, pre) Co-Authored-By: Claude Opus 4.6 --- utils/markdown.py | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/utils/markdown.py b/utils/markdown.py index 8cbb62a..a3196f1 100644 --- a/utils/markdown.py +++ b/utils/markdown.py @@ -3,7 +3,7 @@ Simple Markdown Parser for Forum ================================ Converts basic markdown to safe HTML. -Supports: bold, italic, code, links, lists, quotes, @mentions +Supports: bold, italic, code, links, auto-links, lists, quotes, @mentions """ import re @@ -19,6 +19,7 @@ def parse_forum_markdown(text): - *italic* or _italic_ - `inline code` - [link text](url) + - bare https://... URLs (auto-linked) - - list items - > quotes - @mentions (highlighted) @@ -32,6 +33,9 @@ def parse_forum_markdown(text): if not text: return Markup('') + # Normalize line endings (Windows \r\n -> \n) + text = text.replace('\r\n', '\n').replace('\r', '\n') + # Escape HTML first for security text = str(escape(text)) @@ -44,6 +48,17 @@ def parse_forum_markdown(text): for line in lines: stripped = line.strip() + # Skip empty lines but preserve paragraph spacing + if not stripped: + if in_list: + result_lines.append('') + in_list = False + if in_quote: + result_lines.append('') + in_quote = False + result_lines.append('') + continue + # Quote blocks (> text) if stripped.startswith('> '): # Escaped > if not in_quote: @@ -66,7 +81,7 @@ def parse_forum_markdown(text): result_lines.append('') in_list = False - result_lines.append(line) + result_lines.append(stripped) # Close open blocks if in_list: @@ -121,11 +136,21 @@ def parse_forum_markdown(text): text ) - # Convert newlines to
(but not inside pre/blockquote) - # Simple approach: just convert \n to
- text = text.replace('\n', '
\n') + # Convert newlines to
but skip lines that are HTML block elements + lines = text.split('\n') + output = [] + for i, line in enumerate(lines): + output.append(line) + # Don't add
after block elements or before them + if i < len(lines) - 1: + stripped = line.strip() + next_stripped = lines[i + 1].strip() if i + 1 < len(lines) else '' + is_block = any(stripped.startswith(t) for t in ['', '', '', '']) + next_is_block = any(next_stripped.startswith(t) for t in ['', '', '', '']) + if not is_block and not next_is_block: + output.append('
') - return Markup(text) + return Markup('\n'.join(output)) def register_markdown_filter(app):