"""Comprehensive renderer audit tests for static/ui.js renderMd().
This file covers the full suite of markdown constructs an LLM might produce,
with a focus on edge cases and combinations. Tests are grouped by construct.
Python mirrors the renderMd/inlineMd pipeline at the level needed for each
test — either source-level assertions (checking the JS source directly) or
behavioural assertions (checking rendered HTML via a Python mirror).
"""
import re
import pathlib
UI_JS = (pathlib.Path(__file__).parent.parent / "static" / "ui.js").read_text(encoding="utf-8")
import html as _html
def _esc(s):
return _html.escape(str(s), quote=True)
def _inline_md(t):
"""Mirror of inlineMd() in ui.js — processes one line of text."""
_code_stash = []
t = re.sub(r"`([^`\n]+)`",
lambda m: (_code_stash.append(f"{_esc(m.group(1))}")
or f"\x00C{len(_code_stash)-1}\x00"), t)
t = re.sub(r"\*\*\*(.+?)\*\*\*", lambda m: f"{_esc(m.group(1))}", t)
t = re.sub(r"\*\*(.+?)\*\*", lambda m: f"{_esc(m.group(1))}", t)
t = re.sub(r"\*([^*\n]+)\*", lambda m: f"{_esc(m.group(1))}", t)
t = re.sub(r"~~(.+?)~~", lambda m: f"{_esc(m.group(1))}", t)
t = re.sub(r"\x00C(\d+)\x00", lambda m: _code_stash[int(m.group(1))], t)
return t
def _apply_blockquotes(src):
"""Mirror of _applyBlockquotes() — handles nested + lists + blank lines."""
def replacer(m):
block = m.group(0)
lines = block.split("\n")
while lines and (lines[-1].strip() in (">", "")):
if lines[-1].strip() == ">":
lines.pop(); break
lines.pop()
stripped = [re.sub(r"^>[ \t]?", "", l) for l in lines]
inner_raw = "\n".join(stripped)
if re.search(r"^>", inner_raw, re.MULTILINE):
inner = _apply_blockquotes(inner_raw)
elif re.search(r"^( )?[-*+] .+", inner_raw, re.MULTILINE):
def inner_list(lb):
ll = lb.strip().split("\n"); h = "
"
for li in ll:
txt = re.sub(r"^ {0,4}[-*+] ", "", li)
if re.match(r"\[x\] ", txt, re.I): ih = f"✅ {_inline_md(txt[4:])}"
elif txt.startswith("[ ] "): ih = f"☐ {_inline_md(txt[4:])}"
else: ih = _inline_md(txt)
h += f"- {ih}
"
return h + "
"
inner = re.sub(r"((?:^(?: )?[-*+] .+\n?)+)", lambda m2: inner_list(m2.group(0)),
inner_raw, flags=re.MULTILINE)
else:
inner = "\n".join("
" if l.strip() == "" else _inline_md(l) for l in stripped)
return f"{inner}
"
return re.sub(r"((?:^>[^\n]*(?:\n|$))+)", replacer, src, flags=re.MULTILINE)
# ─────────────────────────────────────────────────────────────────────────────
# Source-level structural checks (JS must contain these patterns)
# ─────────────────────────────────────────────────────────────────────────────
class TestSourceStructure:
"""Verify key patterns are present in ui.js."""
def test_crlf_normalisation_present(self):
assert ".replace(/\\r\\n/g,'\\n').replace(/\\r/g,'\\n')" in UI_JS, (
"renderMd must normalise \\r\\n and bare \\r to \\n at the start"
)
def test_strikethrough_in_inline_md(self):
assert "~~(.+?)~~" in UI_JS and "" in UI_JS, (
"inlineMd must handle ~~strikethrough~~ → "
)
def test_del_in_safe_tags(self):
assert "del" in UI_JS and "SAFE_TAGS" in UI_JS, (
" must be in SAFE_TAGS so it is not HTML-escaped"
)
def test_del_in_safe_inline(self):
# SAFE_INLINE is used inside inlineMd
safe_inline_idx = UI_JS.find("SAFE_INLINE")
assert safe_inline_idx >= 0
window = UI_JS[safe_inline_idx: safe_inline_idx + 100]
assert "del" in window, " must be in SAFE_INLINE"
def test_task_list_checked_handled(self):
assert "task-done" in UI_JS or "\\u2705" in UI_JS or "✅" in UI_JS, (
"Checked task list items [x] must produce a ✅ or task-done class"
)
def test_task_list_unchecked_handled(self):
assert "task-todo" in UI_JS or "\\u2610" in UI_JS or "☐" in UI_JS, (
"Unchecked task list items [ ] must produce ☐ or task-todo class"
)
def test_nested_blockquote_recurse(self):
assert "_applyBlockquotes" in UI_JS, (
"Blockquote handler must use a named function for recursive nesting"
)
def test_blockquote_handler_is_function(self):
assert "function _applyBlockquotes" in UI_JS, (
"Must define _applyBlockquotes as a named inner function for recursion"
)
def test_old_single_line_blockquote_removed(self):
assert "replace(/^> (.+)$/gm" not in UI_JS, (
"Old single-line blockquote rule must be removed"
)
def test_h1_h2_h3_handled(self):
for h in ("h1", "h2", "h3"):
assert f"<{h}>" in UI_JS or f"`<{h}>" in UI_JS
def test_ordered_list_value_attr(self):
assert 'value=' in UI_JS, "Ordered list items must use value= to preserve numbering"
def test_table_handler_present(self):
assert "" in UI_JS and "" in UI_JS
def test_fenced_code_lang_header(self):
assert "pre-header" in UI_JS
def test_autolink_present(self):
# JS stores regex slashes as \/ — search for both forms
assert ("https?:\\/\\/" in UI_JS or "https?://" in UI_JS) and "target=\"_blank\"" in UI_JS
# ─────────────────────────────────────────────────────────────────────────────
# Behavioural: inline formatting
# ─────────────────────────────────────────────────────────────────────────────
class TestInlineFormatting:
def test_bold(self):
assert _inline_md("**bold**") == "bold"
def test_italic(self):
assert _inline_md("*italic*") == "italic"
def test_bold_italic(self):
out = _inline_md("***bi***")
assert "" in out
def test_strikethrough(self):
out = _inline_md("~~deleted~~")
assert "deleted" == out
def test_strikethrough_inline(self):
out = _inline_md("keep ~~remove~~ keep")
assert "remove" in out
assert "keep" in out
def test_inline_code(self):
out = _inline_md("`git status`")
assert "git status" in out
def test_strikethrough_inside_code_not_processed(self):
out = _inline_md("`~~not deleted~~`")
assert "" not in out
assert "~~not deleted~~" in out
def test_bold_with_inline_code(self):
# **`code`** → code
out = _inline_md("**`code`**")
# The code stash protects the backtick span from bold regex
assert "" in out
def test_xss_in_bold(self):
out = _inline_md("****")
assert "