feat: render document previews with marked.js instead of raw pre tags
All checks were successful
Deploy / deploy (push) Successful in 11s
All checks were successful
Deploy / deploy (push) Successful in 11s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
36
webui.py
36
webui.py
@@ -394,6 +394,16 @@ tr:last-child td{border-bottom:none}
|
|||||||
.conflict-card{border:1px solid #ffc107;border-radius:6px;padding:14px;margin-bottom:12px}
|
.conflict-card{border:1px solid #ffc107;border-radius:6px;padding:14px;margin-bottom:12px}
|
||||||
.conflict-card h3{margin:0 0 10px;font-size:.95rem;font-family:monospace}
|
.conflict-card h3{margin:0 0 10px;font-size:.95rem;font-family:monospace}
|
||||||
.diff-container{margin-top:10px}
|
.diff-container{margin-top:10px}
|
||||||
|
.md-preview{background:#f8f9fa;border-radius:4px;padding:12px 16px;max-height:340px;overflow:auto;font-size:.85rem;line-height:1.6}
|
||||||
|
.md-preview h1,.md-preview h2,.md-preview h3{margin:.6em 0 .3em;font-size:1em;font-weight:700}
|
||||||
|
.md-preview p{margin:.4em 0}
|
||||||
|
.md-preview ul,.md-preview ol{padding-left:1.4em;margin:.4em 0}
|
||||||
|
.md-preview code{background:#e9ecef;padding:1px 5px;border-radius:3px;font-size:.9em}
|
||||||
|
.md-preview pre{background:#e9ecef;padding:10px;border-radius:4px;overflow:auto}
|
||||||
|
.md-preview pre code{background:none;padding:0}
|
||||||
|
.md-preview blockquote{border-left:3px solid #ccc;margin:.4em 0;padding:.2em .8em;color:#666}
|
||||||
|
.md-preview a{color:#0066cc}
|
||||||
|
.md-preview table{width:auto;font-size:.85em}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_SCRIPT = r"""
|
_SCRIPT = r"""
|
||||||
@@ -795,12 +805,12 @@ async def review_page():
|
|||||||
<div style="display:flex;gap:8px;margin-top:8px">
|
<div style="display:flex;gap:8px;margin-top:8px">
|
||||||
<div style="flex:1">
|
<div style="flex:1">
|
||||||
<div style="font-size:.75rem;color:#888;margin-bottom:4px">remote · {r_ts}</div>
|
<div style="font-size:.75rem;color:#888;margin-bottom:4px">remote · {r_ts}</div>
|
||||||
<div id="rc-{enc}" style="background:#f8f9fa;padding:8px;border-radius:4px;font-size:.8rem;white-space:pre-wrap;max-height:300px;overflow:auto">
|
<div id="rc-{enc}" class="md-preview">
|
||||||
<em style="color:#999">click View to load</em></div>
|
<em style="color:#999">click View to load</em></div>
|
||||||
</div>
|
</div>
|
||||||
<div style="flex:1">
|
<div style="flex:1">
|
||||||
<div style="font-size:.75rem;color:#888;margin-bottom:4px">local · {l_ts}</div>
|
<div style="font-size:.75rem;color:#888;margin-bottom:4px">local · {l_ts}</div>
|
||||||
<div id="lc-{enc}" style="background:#f8f9fa;padding:8px;border-radius:4px;font-size:.8rem;white-space:pre-wrap;max-height:300px;overflow:auto">
|
<div id="lc-{enc}" class="md-preview">
|
||||||
<em style="color:#999">click View to load</em></div>
|
<em style="color:#999">click View to load</em></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -870,17 +880,27 @@ async def review_page():
|
|||||||
{l_section}
|
{l_section}
|
||||||
{c_section}
|
{c_section}
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/marked/lib/marked.umd.js"></script>
|
||||||
<script>
|
<script>
|
||||||
let resolved = 0;
|
let resolved = 0;
|
||||||
const total = {total};
|
const total = {total};
|
||||||
|
|
||||||
|
function renderMd(text) {{
|
||||||
|
const html = marked.parse(text || '*(empty)*');
|
||||||
|
const el = document.createElement('div');
|
||||||
|
el.className = 'md-preview';
|
||||||
|
el.innerHTML = html;
|
||||||
|
return el;
|
||||||
|
}}
|
||||||
|
|
||||||
async function loadContent(enc, docId, instance) {{
|
async function loadContent(enc, docId, instance) {{
|
||||||
const el = document.getElementById('content-' + enc);
|
const el = document.getElementById('content-' + enc);
|
||||||
el.style.display = 'block';
|
el.style.display = 'block';
|
||||||
el.innerHTML = '<em style="color:#999">Loading…</em>';
|
el.innerHTML = '<em style="color:#999">Loading…</em>';
|
||||||
const r = await fetch('/review/content?doc_id=' + docId + '&instance=' + instance);
|
const r = await fetch('/review/content?doc_id=' + docId + '&instance=' + instance);
|
||||||
const d = await r.json();
|
const d = await r.json();
|
||||||
el.innerHTML = '<pre style="background:#f8f9fa;padding:8px;border-radius:4px;font-size:.78rem;white-space:pre-wrap;max-height:300px;overflow:auto">' + escHtml(d.text || '(empty)') + '</pre>';
|
el.innerHTML = '';
|
||||||
|
el.appendChild(renderMd(d.text));
|
||||||
}}
|
}}
|
||||||
|
|
||||||
async function loadConflict(enc, remoteId, localId) {{
|
async function loadConflict(enc, remoteId, localId) {{
|
||||||
@@ -888,8 +908,10 @@ async function loadConflict(enc, remoteId, localId) {{
|
|||||||
fetch('/review/content?doc_id=' + remoteId + '&instance=remote').then(r=>r.json()),
|
fetch('/review/content?doc_id=' + remoteId + '&instance=remote').then(r=>r.json()),
|
||||||
fetch('/review/content?doc_id=' + localId + '&instance=local' ).then(r=>r.json()),
|
fetch('/review/content?doc_id=' + localId + '&instance=local' ).then(r=>r.json()),
|
||||||
]);
|
]);
|
||||||
document.getElementById('rc-' + enc).textContent = rr.text || '(empty)';
|
const rc = document.getElementById('rc-' + enc);
|
||||||
document.getElementById('lc-' + enc).textContent = lr.text || '(empty)';
|
const lc = document.getElementById('lc-' + enc);
|
||||||
|
rc.innerHTML = ''; rc.appendChild(renderMd(rr.text));
|
||||||
|
lc.innerHTML = ''; lc.appendChild(renderMd(lr.text));
|
||||||
}}
|
}}
|
||||||
|
|
||||||
async function applyAction(enc, action) {{
|
async function applyAction(enc, action) {{
|
||||||
@@ -913,10 +935,6 @@ async function applyAction(enc, action) {{
|
|||||||
alert('Error: ' + (d.error || 'unknown'));
|
alert('Error: ' + (d.error || 'unknown'));
|
||||||
}}
|
}}
|
||||||
}}
|
}}
|
||||||
|
|
||||||
function escHtml(s) {{
|
|
||||||
return s.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
|
|
||||||
}}
|
|
||||||
</script>"""
|
</script>"""
|
||||||
|
|
||||||
return HTMLResponse(_page("Review Differences", body))
|
return HTMLResponse(_page("Review Differences", body))
|
||||||
|
|||||||
Reference in New Issue
Block a user