Private
Public Access
save to compare
This commit is contained in:
+24
-7
@@ -58,7 +58,7 @@ class MarkdownRenderer:
|
|||||||
self.options = imgui_md.MarkdownOptions()
|
self.options = imgui_md.MarkdownOptions()
|
||||||
# Base path for fonts (Inter family)
|
# Base path for fonts (Inter family)
|
||||||
self.options.font_options.font_base_path = "fonts/Inter"
|
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
|
# Configure callbacks
|
||||||
self.options.callbacks.on_open_link = self._on_open_link
|
self.options.callbacks.on_open_link = self._on_open_link
|
||||||
@@ -133,7 +133,7 @@ class MarkdownRenderer:
|
|||||||
def flush_md() -> None:
|
def flush_md() -> None:
|
||||||
if md_buf:
|
if md_buf:
|
||||||
chunk = "".join(md_buf)
|
chunk = "".join(md_buf)
|
||||||
if chunk.strip():
|
if chunk:
|
||||||
self._render_md_no_bullet_overlap(chunk)
|
self._render_md_no_bullet_overlap(chunk)
|
||||||
md_buf.clear()
|
md_buf.clear()
|
||||||
|
|
||||||
@@ -173,8 +173,13 @@ class MarkdownRenderer:
|
|||||||
continue
|
continue
|
||||||
if i in table_at_line:
|
if i in table_at_line:
|
||||||
flush_md()
|
flush_md()
|
||||||
try: render_table(blocks[table_at_line[i]])
|
block = blocks[table_at_line[i]]
|
||||||
except Exception: pass
|
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]
|
i = table_end[i]
|
||||||
continue
|
continue
|
||||||
md_buf.append(line)
|
md_buf.append(line)
|
||||||
@@ -193,7 +198,7 @@ class MarkdownRenderer:
|
|||||||
for m in list_pattern.finditer(chunk):
|
for m in list_pattern.finditer(chunk):
|
||||||
if m.start() > current_pos:
|
if m.start() > current_pos:
|
||||||
pre = chunk[current_pos:m.start()]
|
pre = chunk[current_pos:m.start()]
|
||||||
if pre.strip(): imgui_md.render(pre)
|
if pre: imgui_md.render(pre)
|
||||||
list_start = m.start()
|
list_start = m.start()
|
||||||
indent_len = len(m.group("indent"))
|
indent_len = len(m.group("indent"))
|
||||||
i = list_start
|
i = list_start
|
||||||
@@ -211,11 +216,23 @@ class MarkdownRenderer:
|
|||||||
i = line_end + 1
|
i = line_end + 1
|
||||||
list_block = chunk[list_start:i]
|
list_block = chunk[list_start:i]
|
||||||
for line in list_block.splitlines():
|
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
|
current_pos = i
|
||||||
if current_pos < len(chunk):
|
if current_pos < len(chunk):
|
||||||
tail = chunk[current_pos:]
|
tail = chunk[current_pos:]
|
||||||
if tail.strip(): imgui_md.render(tail)
|
if tail: imgui_md.render(tail)
|
||||||
|
|
||||||
def render_unindented(self, text: str) -> None:
|
def render_unindented(self, text: str) -> None:
|
||||||
"""Render Markdown text with automatic unindentation."""
|
"""Render Markdown text with automatic unindentation."""
|
||||||
|
|||||||
@@ -2,27 +2,28 @@ import re
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from imgui_bundle import imgui
|
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:
|
def render_table(block: "TableBlock") -> None:
|
||||||
"""Render a GFM table block via imgui.begin_table.
|
"""Render a GFM table block via imgui.begin_table.
|
||||||
[C: src/markdown_helper.py:MarkdownRenderer.render]
|
[C: src/markdown_helper.py:MarkdownRenderer.render]
|
||||||
"""
|
"""
|
||||||
|
from src.markdown_helper import render as render_md
|
||||||
n_cols = len(block.headers)
|
n_cols = len(block.headers)
|
||||||
if n_cols == 0: return
|
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
|
if not imgui.begin_table("md_table", n_cols, flags): return
|
||||||
for h in block.headers:
|
for h in block.headers:
|
||||||
imgui.table_setup_column(h, imgui.TableColumnFlags_.width_stretch)
|
imgui.table_setup_column(h, imgui.TableColumnFlags_.width_stretch)
|
||||||
imgui.table_headers_row()
|
imgui.table_headers_row()
|
||||||
for h in block.headers:
|
# Note: table_headers_row() renders the headers from setup_column.
|
||||||
imgui.table_next_column()
|
# No need for manual row here unless we want custom rendering for header cells.
|
||||||
imgui.text(h)
|
|
||||||
for row in block.rows:
|
for row in block.rows:
|
||||||
imgui.table_next_row()
|
imgui.table_next_row()
|
||||||
for c in row:
|
for c in row:
|
||||||
imgui.table_next_column()
|
imgui.table_next_column()
|
||||||
imgui.text(c)
|
render_md(c)
|
||||||
imgui.end_table()
|
imgui.end_table()
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
@@ -42,6 +43,7 @@ def _split_row(line: str) -> list[str]:
|
|||||||
|
|
||||||
def _is_table_at(lines: list[str], i: int) -> bool:
|
def _is_table_at(lines: list[str], i: int) -> bool:
|
||||||
if i + 1 >= len(lines): return False
|
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
|
if "|" not in lines[i]: return False
|
||||||
return bool(_TABLE_SEPARATOR.match(lines[i + 1]))
|
return bool(_TABLE_SEPARATOR.match(lines[i + 1]))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user