Re-staged from the contributor's rebased head (0cee92c9) which independently converged on the same 5-test-file class-tolerance fixups I'd made — shipping the contributor's exact version, not my private variant. Tags md/markdown/mdx fenced blocks with md-source-block class in both renderers; CSS wraps them while code/diff/csv keep horizontal-scroll. 90 renderer-family tests pass. Co-authored-by: nesquena-hermes <agent@nesquena-hermes> Co-authored-by: TomBanksAU <TomBanksAU@users.noreply.github.com>
This commit is contained in:
parent
de385c2664
commit
a30348b2c4
8 changed files with 42 additions and 10 deletions
|
|
@ -3,6 +3,12 @@
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
## [v0.51.580] — 2026-06-22 — Release UM (wrap markdown source previews)
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Markdown source previews now wrap normal prose instead of forcing horizontal scroll.** Fenced code blocks tagged `md`, `markdown`, or `mdx` (the inline viewer with the small `MD` header and Copy button) now render in a dedicated wrapping source-preview style, so ordinary markdown text flows to the message width while true code/diff blocks keep their existing horizontal-scroll behavior. Thanks @TomBanksAU. (#4669)
|
||||
|
||||
## [v0.51.579] — 2026-06-22 — Release UL (deflake TLS end-to-end tests)
|
||||
|
||||
### Fixed
|
||||
|
|
|
|||
|
|
@ -1687,6 +1687,9 @@
|
|||
.msg-body code{font-family:"SF Mono","Fira Code",ui-monospace,monospace;font-size:var(--message-code-font-size);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;}
|
||||
.msg-body pre code{background:none;padding:0;border-radius:0;color:var(--pre-text);font-size:var(--message-pre-code-font-size);line-height:1.6;}
|
||||
.msg-body pre.md-source-block,.preview-md pre.md-source-block{white-space:pre-wrap;overflow-x:hidden;overflow-wrap:anywhere;}
|
||||
.msg-body pre.md-source-block code,.preview-md pre.md-source-block code{display:block;white-space:inherit;overflow-wrap:anywhere;word-break:break-word;}
|
||||
.msg-body pre.md-source-block code .token,.preview-md pre.md-source-block code .token{white-space:inherit;overflow-wrap:anywhere;word-break:inherit;}
|
||||
.provider-error-details{margin:12px 0 0;border:1px solid var(--border);border-radius:10px;background:var(--surface);overflow:hidden;}
|
||||
.provider-error-details>summary{cursor:pointer;color:var(--muted);font-size:12px;font-weight:600;padding:8px 12px;}
|
||||
.provider-error-details>pre{margin:0;border:0;border-top:1px solid var(--border);border-radius:0;max-height:220px;}
|
||||
|
|
|
|||
|
|
@ -349,6 +349,7 @@ function _renderUserFencedBlocks(text){
|
|||
if(code.endsWith('\n')) code=code.slice(0,-1);
|
||||
const h=lang?`<div class="pre-header">${esc(lang)}</div>`:'';
|
||||
const langAttr=lang?` class="language-${esc(lang)}"`:'';
|
||||
const preClass=/^(md|markdown|mdx)$/.test(lang)?' class="md-source-block"':'';
|
||||
if(lang==='diff'||lang==='patch'){
|
||||
const colored=esc(code).split('\n').map(line=>{
|
||||
if(line.startsWith('@@')) return `<span class="diff-line diff-hunk">${line}</span>`;
|
||||
|
|
@ -358,7 +359,7 @@ function _renderUserFencedBlocks(text){
|
|||
}).join('\n');
|
||||
stash.push(`${h}<pre class="diff-block"><code${langAttr}>${colored}</code></pre>`);
|
||||
} else {
|
||||
stash.push(`${h}<pre><code${langAttr}>${esc(code)}</code></pre>`);
|
||||
stash.push(`${h}<pre${preClass}><code${langAttr}>${esc(code)}</code></pre>`);
|
||||
}
|
||||
return lead+'\x00UF'+(stash.length-1)+'\x00';
|
||||
});
|
||||
|
|
@ -4856,6 +4857,7 @@ function renderMd(raw){
|
|||
} else {
|
||||
const h=lang?`<div class="pre-header">${esc(lang)}</div>`:'';
|
||||
const langAttr=lang?` class="language-${esc(lang)}"`:'';
|
||||
const preClass=/^(md|markdown|mdx)$/.test(lang)?' class="md-source-block"':'';
|
||||
// For diff/patch blocks, wrap each line in a colored span
|
||||
if(lang==='diff'||lang==='patch'){
|
||||
const colored=esc(code.replace(/\n$/,'')).split('\n').map(line=>{
|
||||
|
|
@ -4881,10 +4883,10 @@ function renderMd(raw){
|
|||
const body=rows.slice(1).map(r=>'<tr>'+r.split(',').map(c=>`<td>${esc(c.trim())}</td>`).join('')+'</tr>').join('');
|
||||
_preBlock_stash.push(`${h}<div class="csv-table-wrap"><table class="csv-table"><thead><tr>${headers.map(h=>`<th>${esc(h)}</th>`).join('')}</tr></thead><tbody>${body}</tbody></table></div>`);
|
||||
} else {
|
||||
_preBlock_stash.push(`${h}<pre><code${langAttr}>${esc(code.replace(/\n$/,''))}</code></pre>`);
|
||||
_preBlock_stash.push(`${h}<pre${preClass}><code${langAttr}>${esc(code.replace(/\n$/,''))}</code></pre>`);
|
||||
}
|
||||
} else {
|
||||
_preBlock_stash.push(`${h}<pre><code${langAttr}>${esc(code.replace(/\n$/,''))}</code></pre>`);
|
||||
_preBlock_stash.push(`${h}<pre${preClass}><code${langAttr}>${esc(code.replace(/\n$/,''))}</code></pre>`);
|
||||
}
|
||||
}
|
||||
return lead+'\x00P'+(_preBlock_stash.length-1)+'\x00';
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ class TestUserFencedBlocks:
|
|||
def test_four_backtick_outer_fence_preserves_inner_triple_fence(self):
|
||||
"""User-message code fences should follow CommonMark fence-length matching too."""
|
||||
out = _run_user_render("````md\n```inner\nfoo\n```\n````")
|
||||
assert out.count("<pre>") == 1
|
||||
assert out.count("<pre class=\"md-source-block\">") == 1
|
||||
assert out.count("</pre>") == 1
|
||||
assert '<div class="pre-header">md</div>' in out
|
||||
assert "```inner" in out
|
||||
|
|
|
|||
|
|
@ -41,7 +41,9 @@ def test_csv_fence_fallback_for_insufficient_rows():
|
|||
src = f.read()
|
||||
fence_section = src[src.find("lang==='csv'"):src.find("lang==='csv'") + 800]
|
||||
assert 'rows.length>=2' in fence_section, "Should check for at least 2 rows"
|
||||
assert '<pre><code' in fence_section, "Fallback should render as <pre><code>"
|
||||
assert '<pre${preClass}><code${langAttr}>' in fence_section, (
|
||||
"Fallback should render via the shared preClass-aware code-block template"
|
||||
)
|
||||
|
||||
|
||||
def test_csv_media_file_handler():
|
||||
|
|
|
|||
|
|
@ -17,9 +17,10 @@ def test_fenced_code_blocks_add_prism_language_class():
|
|||
def test_fenced_code_blocks_keep_existing_pre_header_layout():
|
||||
js = _read_ui_js()
|
||||
# The fenced code rendering was moved into the stash callback (#1154 fix).
|
||||
# The template string now uses `lang` instead of `normalizedLang`.
|
||||
assert '${h}<pre><code${langAttr}>${esc(code.replace(/\\n$/,' in js, (
|
||||
"The syntax-highlight fix should preserve the existing fenced code block layout"
|
||||
# The template string now uses `lang` instead of `normalizedLang`, and
|
||||
# markdown-source fences may add a dedicated md-source-block class.
|
||||
assert '${h}<pre${preClass}><code${langAttr}>${esc(code.replace(/\\n$/,' in js, (
|
||||
"The syntax-highlight fix should preserve the shared fenced code block layout"
|
||||
)
|
||||
assert '<div class="code-block">' not in js, (
|
||||
"This fix should not introduce a new wrapper around fenced code blocks"
|
||||
|
|
|
|||
18
tests/test_markdown_source_code_blocks_wrap.py
Normal file
18
tests/test_markdown_source_code_blocks_wrap.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
UI_JS = (ROOT / "static" / "ui.js").read_text(encoding="utf-8")
|
||||
CSS = (ROOT / "static" / "style.css").read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_markdown_source_code_blocks_get_dedicated_pre_class_in_both_renderers():
|
||||
expected = "const preClass=/^(md|markdown|mdx)$/.test(lang)?' class=\"md-source-block\"':'';"
|
||||
|
||||
assert UI_JS.count(expected) >= 2, "Expected both fenced-code renderers to tag markdown source blocks"
|
||||
|
||||
|
||||
def test_markdown_source_code_blocks_have_desktop_wrap_css():
|
||||
assert ".msg-body pre.md-source-block,.preview-md pre.md-source-block{white-space:pre-wrap;overflow-x:hidden;overflow-wrap:anywhere;}" in CSS
|
||||
assert ".msg-body pre.md-source-block code,.preview-md pre.md-source-block code{display:block;white-space:inherit;overflow-wrap:anywhere;word-break:break-word;}" in CSS
|
||||
assert ".msg-body pre.md-source-block code .token,.preview-md pre.md-source-block code .token{white-space:inherit;overflow-wrap:anywhere;word-break:inherit;}" in CSS
|
||||
|
|
@ -397,7 +397,7 @@ class TestFencedCodeFenceLength:
|
|||
"That is much more correct than pretending"
|
||||
)
|
||||
out = _render(driver_path, src)
|
||||
assert out.count("<pre>") == 1
|
||||
assert out.count("<pre class=\"md-source-block\">") == 1
|
||||
assert out.count("</pre>") == 1
|
||||
assert '<div class="pre-header">md</div>' in out
|
||||
assert "```novelcrafter" in out
|
||||
|
|
@ -408,7 +408,7 @@ class TestFencedCodeFenceLength:
|
|||
|
||||
def test_four_backtick_outer_fence_preserves_inner_triple_fence(self, driver_path):
|
||||
out = _render(driver_path, "````md\n```inner\nfoo\n```\n````\n")
|
||||
assert out.count("<pre>") == 1
|
||||
assert out.count("<pre class=\"md-source-block\">") == 1
|
||||
assert out.count("</pre>") == 1
|
||||
assert '<div class="pre-header">md</div>' in out
|
||||
assert "```inner" in out
|
||||
|
|
|
|||
Loading…
Reference in a new issue