Merge remote-tracking branch pr/1260 into stage/batch-v0.50.239

This commit is contained in:
Hermes Agent 2026-04-29 15:55:51 +00:00
commit 8e546c0273
3 changed files with 38 additions and 2 deletions

View file

@ -35,6 +35,12 @@
:root[data-font-size="large"] .msg-body h2 { font-size: 19px; }
:root[data-font-size="small"] .msg-body h3 { font-size: 12px; }
:root[data-font-size="large"] .msg-body h3 { font-size: 16px; }
:root[data-font-size="small"] .msg-body h4 { font-size: 11px; }
:root[data-font-size="large"] .msg-body h4 { font-size: 15px; }
:root[data-font-size="small"] .msg-body h5 { font-size: 11px; }
:root[data-font-size="large"] .msg-body h5 { font-size: 14px; }
:root[data-font-size="small"] .msg-body h6 { font-size: 10px; }
:root[data-font-size="large"] .msg-body h6 { font-size: 13px; }
:root[data-font-size="small"] .msg-body code { font-size: 10.5px; }
:root[data-font-size="large"] .msg-body code { font-size: 14.5px; }
:root[data-font-size="small"] .msg-body pre code { font-size: 11px; }
@ -602,8 +608,9 @@
.msg-body{font-size:14px;line-height:1.75;color:var(--text);padding-left:30px;max-width:680px;overflow-wrap:anywhere;}
.msg-body p{margin-bottom:10px;}.msg-body p:last-child{margin-bottom:0;}
.msg-body ul,.msg-body ol{margin:6px 0 10px 20px;}.msg-body li{margin-bottom:3px;}
.msg-body h1,.msg-body h2,.msg-body h3{margin:16px 0 6px;font-weight:600;}
.msg-body h1,.msg-body h2,.msg-body h3,.msg-body h4,.msg-body h5,.msg-body h6{margin:16px 0 6px;font-weight:600;}
.msg-body h1{font-size:18px;}.msg-body h2{font-size:16px;}.msg-body h3{font-size:14px;}
.msg-body h4{font-size:13px;}.msg-body h5{font-size:12px;}.msg-body h6{font-size:11px;color:var(--muted);}
.msg-body strong{color:var(--strong);font-weight:600;}.msg-body em{color:var(--em);font-style:italic;}
.msg-body code{font-family:"SF Mono","Fira Code",ui-monospace,monospace;font-size:12.5px;background:var(--code-inline-bg);padding:1px 5px;border-radius:4px;color:var(--code-text);}
.msg-body pre{background:var(--code-bg);border:1px solid var(--border);border-radius:10px;padding:14px 16px;overflow-x:auto;margin:10px 0;}

View file

@ -990,7 +990,7 @@ function renderMd(raw){
s=s.replace(/\*([^*\n]+)\*/g,(_,t)=>`<em>${esc(t)}</em>`);
s=s.replace(/~~(.+?)~~/g,(_,t)=>`<del>${esc(t)}</del>`);
s=s.replace(/\x00O(\d+)\x00/g,(_,i)=>_ob_stash[+i]);
s=s.replace(/^### (.+)$/gm,(_,t)=>`<h3>${inlineMd(t)}</h3>`).replace(/^## (.+)$/gm,(_,t)=>`<h2>${inlineMd(t)}</h2>`).replace(/^# (.+)$/gm,(_,t)=>`<h1>${inlineMd(t)}</h1>`);
s=s.replace(/^###### (.+)$/gm,(_,t)=>`<h6>${inlineMd(t)}</h6>`).replace(/^##### (.+)$/gm,(_,t)=>`<h5>${inlineMd(t)}</h5>`).replace(/^#### (.+)$/gm,(_,t)=>`<h4>${inlineMd(t)}</h4>`).replace(/^### (.+)$/gm,(_,t)=>`<h3>${inlineMd(t)}</h3>`).replace(/^## (.+)$/gm,(_,t)=>`<h2>${inlineMd(t)}</h2>`).replace(/^# (.+)$/gm,(_,t)=>`<h1>${inlineMd(t)}</h1>`);
s=s.replace(/^---+$/gm,'<hr>');
// (Blockquotes are handled by the pre-pass at the top of renderMd, before
// fence_stash. The per-line passes below never see > prefixes.)

View file

@ -525,3 +525,32 @@ class TestRawPreCodePreservation:
f"<code> content inside <pre> must not be rewritten to backticks: {out!r}"
)
assert "After paragraph." in out and "Done." in out
class TestHeadingLevelsH1ThroughH6:
"""Issue #1258 — `####`, `#####`, `######` previously fell through the
heading pass and emitted as literal text starting with `#`. Pin all six
levels so a future edit cannot silently regress h4–h6 again."""
def test_all_six_heading_levels_render(self, driver_path):
src = "# H1\n## H2\n### H3\n#### H4\n##### H5\n###### H6"
out = _render(driver_path, src)
assert "<h1>H1</h1>" in out, f"h1 missing: {out!r}"
assert "<h2>H2</h2>" in out, f"h2 missing: {out!r}"
assert "<h3>H3</h3>" in out, f"h3 missing: {out!r}"
assert "<h4>H4</h4>" in out, f"h4 missing: {out!r}"
assert "<h5>H5</h5>" in out, f"h5 missing: {out!r}"
assert "<h6>H6</h6>" in out, f"h6 missing: {out!r}"
def test_h6_does_not_partial_match_as_lower_level(self, driver_path):
"""Replacers must run longest-first; otherwise `###### H6` could be
captured by the `^### ` rule and emit `<h3>### H6</h3>`."""
out = _render(driver_path, "###### H6")
assert "<h6>H6</h6>" in out, f"h6 must not be partial-matched: {out!r}"
assert "<h3>" not in out and "###" not in out
def test_h4_inline_markdown_still_processes(self, driver_path):
out = _render(driver_path, "#### **bold** in h4")
assert "<h4><strong>bold</strong> in h4</h4>" in out, (
f"inline markdown inside h4 must still render: {out!r}"
)