Private
Public Access
0
0

fix(markdown): strip backticks in table cells + add nested-list overlap workaround

FIX 1 (src/markdown_table.py): Cells now use imgui_md.render(c) instead of
imgui.text_wrapped(c). imgui_md uses MD4C which strips backtick-delimited
inline code spans BEFORE rendering, so backticks no longer appear as
literal characters in cell content. Side benefit: inline emphasis
(*foo*, **bar**) now renders in cells too.

FIX 2 (src/markdown_helper.py): Added MarkdownRenderer._normalize_nested_list_endings.
Upstream imgui_md (mekhontsev/imgui_md) BLOCK_UL exit only calls
ImGui::NewLine() for top-level list endings. For nested list endings, no
NewLine is emitted, so the next text starts at the same Y as the last
list item, causing visual overlap. The preprocessor inserts a blank
line before any line that follows a list item with MORE indent than
itself, forcing a paragraph break. Cannot fix the C++ from Python.

Tests:
- test_markdown_table_wrapped.py: updated to assert imgui_md.render is
  called for cell content (not imgui.text_wrapped).
- test_markdown_helper_bullets.py: added 4 tests for the new preprocessors
  (nested-list blank insertion + bullet delimiter conversion + edge cases).

20/20 markdown unit tests pass. 1-space indentation throughout.

KNOWN LIMITATIONS (cannot fix without forking imgui_md C++):
- Inline code spans render as plain text (no monospace font in cells)
- The ' * ' bullet delimiter has a Y-overlap bug upstream
  (workaround: pre-convert to '- ' via _normalize_bullet_delimiters)
- Nested list ending overlap (workaround: insert blank line via
  _normalize_nested_list_endings)
This commit is contained in:
Conductor
2026-06-03 21:33:47 -04:00
parent feed18eb0f
commit fd5f4d0eda
4 changed files with 79 additions and 11 deletions
+28
View File
@@ -116,6 +116,7 @@ class MarkdownRenderer:
return
from src.markdown_table import parse_tables, render_table
text = self._normalize_bullet_delimiters(text)
text = self._normalize_nested_list_endings(text)
blocks = parse_tables(text)
lines = text.splitlines(keepends=True)
if not lines:
@@ -203,6 +204,33 @@ class MarkdownRenderer:
import re
return re.sub(r"(?m)^([ \t]*)\*[ \t]+", r"\1- ", text)
def _normalize_nested_list_endings(self, text: str) -> str:
"""Insert blank lines before non-list text that follows a nested list item.
Workaround for imgui_md (mekhontsev/imgui_md) BLOCK_UL exit which only
calls ImGui::NewLine() for top-level list endings. For nested list
endings, no NewLine is emitted, so the next text starts at the same Y
as the last list item (overlap). Inserting a blank line forces a
paragraph break. Cannot fix the upstream C++ from Python.
[C: src/markdown_helper.py:MarkdownRenderer.render]
"""
import re
lines = text.split("\n")
out: list[str] = []
for i, line in enumerate(lines):
if (
line.strip()
and not re.match(r"^\s*[-*+\d]", line)
and i > 0
and re.match(r"^\s*[-*+\d]", lines[i - 1])
):
prev_indent = len(lines[i - 1]) - len(lines[i - 1].lstrip())
curr_indent = len(line) - len(line.lstrip())
if curr_indent < prev_indent:
out.append("")
out.append(line)
return "\n".join(out)
def render_unindented(self, text: str) -> None:
"""Render Markdown text with automatic unindentation."""
imgui_md.render_unindented(text)
+2 -2
View File
@@ -1,6 +1,6 @@
import re
from dataclasses import dataclass
from imgui_bundle import imgui
from imgui_bundle import imgui, imgui_md
_TABLE_SEPARATOR = re.compile(r"^\|?\s*:?-{2,}:?\s*(\|\s*:?-{2,}:?\s*)+\|?\s*$")
@@ -19,7 +19,7 @@ def render_table(block: "TableBlock") -> None:
imgui.table_next_row()
for c in row:
imgui.table_next_column()
imgui.text_wrapped(c)
imgui_md.render(c)
imgui.end_table()
@dataclass(frozen=True)