From 5e50664458dbe7cb7af492d51058ffc3321eb237 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Sun, 7 Jun 2026 12:51:10 -0400 Subject: [PATCH] Sidebar sections always expanded; paste preserves undo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The more… expanders are gone — describes, rhymes, and synonyms render in full and the entry just scrolls. Smart paste inserts through the undo-aware path so Cmd+Z cleanly un-pastes. Co-Authored-By: Claude Opus 4.8 (1M context) --- static/index.html | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/static/index.html b/static/index.html index 8ace799..3bd875b 100644 --- a/static/index.html +++ b/static/index.html @@ -188,7 +188,6 @@ #histBar { color: var(--ink-dim); font-size: 12px; margin: 8px 2px 0; min-height: 0; } #histBar .hist { cursor: pointer; } #histBar .hist:hover { color: var(--accent); } - .more { color: var(--accent); cursor: pointer; font-size: 11px; letter-spacing: 0; text-transform: lowercase; } .res-label.sub { color: #6a5f52; margin: 8px 0 2px; } .lookup-row input { flex: 1; font-family: inherit; font-size: 14px; @@ -773,7 +772,7 @@ async function doLookup(){ el.textContent = 'not in the pronunciation dictionary'; } } - entry = {word, rhyme, syn, desc, expanded: {}}; + entry = {word, rhyme, syn, desc}; paintSections(); } @@ -808,37 +807,26 @@ function chipHtml(items, cls){ }).join('') + ''; } -function secLabel(id, label, truncated){ - return `
${label}` + - (truncated && !entry.expanded[id] ? ` more…` : '') + - '
'; -} - function paintSections(){ const e = entry; if(!e) return; let h = ''; if(e.desc && e.desc.length){ - const items = e.desc.map(d=>d.word); - const lim = e.expanded.desc ? items.length : 12; - h += secLabel('desc', 'describes', items.length > 12) + chipHtml(items.slice(0, lim)); + h += `
describes
` + chipHtml(e.desc.map(d=>d.word)); } if(e.rhyme && e.rhyme.known && (e.rhyme.words.length || (e.rhyme.near || []).length)){ - const lim = e.expanded.rhyme ? 999 : 8; const bySyl = {}; e.rhyme.words.forEach(d=>{ (bySyl[d.syl || 0] ||= []).push(d); }); - const truncated = e.rhyme.words.length > 16 || (e.rhyme.near || []).length > 8; const onWord = e.rhyme.rhyme_on ? ` — on “${esc(e.rhyme.rhyme_on)}”` : ''; - h += secLabel('rhyme', 'rhymes' + onWord, truncated); + h += `
rhymes${onWord}
`; Object.keys(bySyl).sort((a,b)=>a-b).forEach(k=>{ - h += `
${k == 0 ? '?' : k} syl
` + chipHtml(bySyl[k].slice(0, lim)); + h += `
${k == 0 ? '?' : k} syl
` + chipHtml(bySyl[k]); }); - const near = (e.rhyme.near || []).slice(0, e.expanded.rhyme ? 999 : 8); + const near = e.rhyme.near || []; if(near.length) h += `
near
` + chipHtml(near, 'near'); } if(e.syn && e.syn.known && e.syn.sections.length){ - // bottom section: always fully expanded — nothing below to crowd - h += secLabel('syn', 'synonyms', false); + h += `
synonyms
`; e.syn.sections.forEach(s=>{ if(s.label !== 'synonyms') h += `
${esc(s.label)}
`; h += chipHtml(s.words.map(d=>d.word), s.label === 'synonyms' ? '' : 'near'); @@ -847,8 +835,6 @@ function paintSections(){ resultsBox.innerHTML = h || `

nothing found for “${esc(e.word)}”.

`; resultsBox.querySelectorAll('.chip').forEach(c=> c.addEventListener('click', ()=> lookupFor(c.dataset.w))); - resultsBox.querySelectorAll('.more').forEach(m=> - m.addEventListener('click', ()=>{ entry.expanded[m.dataset.sec] = true; paintSections(); })); } /* ============================================================ @@ -1014,15 +1000,22 @@ editor.addEventListener('paste', e=>{ const cleaned = cleanPaste(text); if(cleaned === text) return; e.preventDefault(); - editor.setRangeText(cleaned, editor.selectionStart, editor.selectionEnd, 'end'); + // execCommand keeps the native undo stack intact (setRangeText doesn't) + editor.focus(); + if(!document.execCommand('insertText', false, cleaned)){ + editor.setRangeText(cleaned, editor.selectionStart, editor.selectionEnd, 'end'); + } render(); analyzeSoon(); }); lookupInput.addEventListener('paste', e=>{ const text = e.clipboardData && e.clipboardData.getData('text/plain'); if(text && /[\u2018\u2019]/.test(text)){ e.preventDefault(); - lookupInput.setRangeText(text.replace(/[\u2018\u2019]/g, "'"), - lookupInput.selectionStart, lookupInput.selectionEnd, 'end'); + lookupInput.focus(); + const fixed = text.replace(/[\u2018\u2019]/g, "'"); + if(!document.execCommand('insertText', false, fixed)){ + lookupInput.setRangeText(fixed, lookupInput.selectionStart, lookupInput.selectionEnd, 'end'); + } } });