diff --git a/src/markdown_helper.py b/src/markdown_helper.py index 5684fb2a..0c0cac28 100644 --- a/src/markdown_helper.py +++ b/src/markdown_helper.py @@ -58,7 +58,7 @@ class MarkdownRenderer: self.options = imgui_md.MarkdownOptions() # Base path for fonts (Inter family) self.options.font_options.font_base_path = "fonts/Inter" - self.options.font_options.regular_size = 16.0 + self.options.font_options.regular_size = 18.0 # Configure callbacks self.options.callbacks.on_open_link = self._on_open_link @@ -133,7 +133,7 @@ class MarkdownRenderer: def flush_md() -> None: if md_buf: chunk = "".join(md_buf) - if chunk.strip(): + if chunk: self._render_md_no_bullet_overlap(chunk) md_buf.clear() @@ -173,8 +173,13 @@ class MarkdownRenderer: continue if i in table_at_line: flush_md() - try: render_table(blocks[table_at_line[i]]) - except Exception: pass + block = blocks[table_at_line[i]] + try: + render_table(block) + except Exception as e: + # Fallback: if table rendering fails, just append lines to md_buf + for line_idx in range(block.span[0], block.span[1]): + md_buf.append(lines[line_idx]) i = table_end[i] continue md_buf.append(line) @@ -193,7 +198,7 @@ class MarkdownRenderer: for m in list_pattern.finditer(chunk): if m.start() > current_pos: pre = chunk[current_pos:m.start()] - if pre.strip(): imgui_md.render(pre) + if pre: imgui_md.render(pre) list_start = m.start() indent_len = len(m.group("indent")) i = list_start @@ -211,11 +216,23 @@ class MarkdownRenderer: i = line_end + 1 list_block = chunk[list_start:i] for line in list_block.splitlines(): - imgui.text(line) if line.strip() else imgui.spacing() + if not line.strip(): + imgui.spacing() + continue + stripped = line.lstrip(" \t") + indent = len(line) - len(stripped) + if stripped.startswith(("- ", "* ", "+ ")): + imgui.bullet() + imgui.same_line() + imgui_md.render(stripped[2:]) + else: + if indent > 0: imgui.indent(indent * 2) + imgui_md.render(stripped) + if indent > 0: imgui.unindent(indent * 2) current_pos = i if current_pos < len(chunk): tail = chunk[current_pos:] - if tail.strip(): imgui_md.render(tail) + if tail: imgui_md.render(tail) def render_unindented(self, text: str) -> None: """Render Markdown text with automatic unindentation.""" diff --git a/src/markdown_table.py b/src/markdown_table.py index 178d1911..76a0a157 100644 --- a/src/markdown_table.py +++ b/src/markdown_table.py @@ -2,27 +2,28 @@ import re from dataclasses import dataclass from imgui_bundle import imgui -_TABLE_SEPARATOR = re.compile(r"^\|?\s*:?-{2,}:?\s*(\|\s*:?-{2,}:?\s*)+\|?\s*$") +_TABLE_SEPARATOR = re.compile(r"^\s*\|?\s*:?-{2,}:?\s*(\|\s*:?-{2,}:?\s*)+\|?\s*$") def render_table(block: "TableBlock") -> None: """Render a GFM table block via imgui.begin_table. [C: src/markdown_helper.py:MarkdownRenderer.render] """ + from src.markdown_helper import render as render_md n_cols = len(block.headers) if n_cols == 0: return - flags = imgui.TableFlags_.borders | imgui.TableFlags_.row_bg | imgui.TableFlags_.resizable + flags = imgui.TableFlags_.borders | imgui.TableFlags_.row_bg | imgui.TableFlags_.resizable | imgui.TableFlags_.scroll_x if not imgui.begin_table("md_table", n_cols, flags): return for h in block.headers: imgui.table_setup_column(h, imgui.TableColumnFlags_.width_stretch) imgui.table_headers_row() - for h in block.headers: - imgui.table_next_column() - imgui.text(h) + # Note: table_headers_row() renders the headers from setup_column. + # No need for manual row here unless we want custom rendering for header cells. + for row in block.rows: imgui.table_next_row() for c in row: imgui.table_next_column() - imgui.text(c) + render_md(c) imgui.end_table() @dataclass(frozen=True) @@ -42,6 +43,7 @@ def _split_row(line: str) -> list[str]: def _is_table_at(lines: list[str], i: int) -> bool: if i + 1 >= len(lines): return False + # Header must have at least one pipe, or the separator must be very clear if "|" not in lines[i]: return False return bool(_TABLE_SEPARATOR.match(lines[i + 1]))