diff --git a/modules/html_generator.py b/modules/html_generator.py index 492b52bd..ccc232a0 100644 --- a/modules/html_generator.py +++ b/modules/html_generator.py @@ -196,50 +196,45 @@ def extract_thinking_block(string): return None, string -@functools.lru_cache(maxsize=None) -def convert_to_markdown(string, message_id=None): - if not string: +def build_thinking_block(thinking_content, message_id, has_remaining_content): + """Build HTML for a thinking block.""" + if thinking_content is None: + return None + + # Process the thinking content through markdown + thinking_html = process_markdown_content(thinking_content) + + # Generate unique ID for the thinking block + block_id = f"thinking-{message_id}-0" + + # Check if thinking is complete or still in progress + is_streaming = not has_remaining_content + title_text = "Thinking..." if is_streaming else "Thought" + + return f''' +
+ + {info_svg_small} + {title_text} + +
{thinking_html}
+
+ ''' + + +def build_main_content_block(content): + """Build HTML for the main content block.""" + if not content: return "" - # Use a default message ID if none provided - if message_id is None: - message_id = "unknown" - - # Extract thinking block if present - thinking_content, remaining_content = extract_thinking_block(string) - - # Process the main content - html_output = process_markdown_content(remaining_content) - - # If thinking content was found, process it using the same function - if thinking_content is not None: - thinking_html = process_markdown_content(thinking_content) - - # Generate unique ID for the thinking block - block_id = f"thinking-{message_id}-0" - - # Check if thinking is complete or still in progress - is_streaming = not remaining_content - title_text = "Thinking..." if is_streaming else "Thought" - - thinking_block = f''' -
- - {info_svg_small} - {title_text} - -
{thinking_html}
-
- ''' - - # Prepend the thinking block to the message HTML - html_output = thinking_block + html_output - - return html_output + return process_markdown_content(content) def process_markdown_content(string): - """Process a string through the markdown conversion pipeline.""" + """ + Process a string through the markdown conversion pipeline. + Uses robust manual parsing to ensure correct LaTeX and Code Block rendering. + """ if not string: return "" @@ -280,7 +275,7 @@ def process_markdown_content(string): pattern = re.compile(r'\\begin{blockquote}(.*?)\\end{blockquote}', re.DOTALL) string = pattern.sub(replace_blockquote, string) - # Code + # Code block standardization string = string.replace('\\begin{code}', '```') string = string.replace('\\end{code}', '```') string = string.replace('\\begin{align*}', '$$') @@ -301,6 +296,7 @@ def process_markdown_content(string): is_code = False is_latex = False + # Manual line iteration for robust structure parsing for line in string.split('\n'): stripped_line = line.strip() @@ -371,6 +367,39 @@ def process_markdown_content(string): return html_output +@functools.lru_cache(maxsize=None) +def convert_to_markdown(string, message_id=None): + """ + Convert a string to markdown HTML with support for multiple block types. + Blocks are assembled in order: thinking, main content, etc. + """ + if not string: + return "" + + # Use a default message ID if none provided + if message_id is None: + message_id = "unknown" + + # Extract different components from the string + thinking_content, remaining_content = extract_thinking_block(string) + + # Build individual HTML blocks + blocks = [] + + # Add thinking block if present + thinking_html = build_thinking_block(thinking_content, message_id, bool(remaining_content)) + if thinking_html: + blocks.append(thinking_html) + + # Add main content block + main_html = build_main_content_block(remaining_content) + if main_html: + blocks.append(main_html) + + # Assemble all blocks into final HTML + return ''.join(blocks) + + def convert_to_markdown_wrapped(string, message_id=None, use_cache=True): ''' Used to avoid caching convert_to_markdown calls during streaming.