1const STORAGE_KEY = 'ic.workspace.split'; 2const DEFAULT_PREF = { lhsWidth: '30%', collapsed: false }; 3const MIN_LHS_PX = 280; 4const MAX_LHS_RATIO = 0.6; 5const WIDTH_PATTERN = /^\d+(\.\d+)?(%|px)$/; 6 7function readPref() { 8 try { 9 const raw = localStorage.getItem(STORAGE_KEY); 10 if (!raw) return { ...DEFAULT_PREF }; 11 const parsed = JSON.parse(raw); 12 return { 13 lhsWidth: typeof parsed.lhsWidth === 'string' && WIDTH_PATTERN.test(parsed.lhsWidth) ? parsed.lhsWidth : DEFAULT_PREF.lhsWidth, 14 collapsed: Boolean(parsed.collapsed) 15 }; 16 } catch (error) { 17 return { ...DEFAULT_PREF }; 18 } 19} 20 21function writePref(pref) { 22 try { 23 localStorage.setItem(STORAGE_KEY, JSON.stringify(pref)); 24 } catch (error) { 25 // Private browsing or storage quota â the split simply won't persist. 26 } 27} 28 29function applyPref(pref) { 30 document.documentElement.style.setProperty('--lhs-width', pref.lhsWidth); 31 document.documentElement.classList.toggle('is-preview-collapsed', pref.collapsed); 32} 33 34export function installWorkspaceSplitPanel() { 35 const workspace = document.getElementById('view-editor'); 36 const divider = document.getElementById('workspace-divider'); 37 const toggle = document.getElementById('workspace-collapse-toggle'); 38 if (!workspace || !divider || !toggle) return; 39 40 applyPref(readPref()); 41 42 divider.addEventListener('pointerdown', (event) => { 43 if (document.documentElement.classList.contains('is-preview-collapsed')) return; 44 event.preventDefault(); 45 divider.setPointerCapture(event.pointerId); 46 const rect = workspace.getBoundingClientRect(); 47 48 const onMove = (moveEvent) => { 49 const maxPx = rect.width * MAX_LHS_RATIO; 50 const px = Math.min(Math.max(moveEvent.clientX - rect.left, MIN_LHS_PX), maxPx); 51 const pct = ((px / rect.width) * 100).toFixed(2) + '%'; 52 document.documentElement.style.setProperty('--lhs-width', pct); 53 }; 54 const onUp = () => { 55 divider.releasePointerCapture(event.pointerId); 56 divider.removeEventListener('pointermove', onMove); 57 divider.removeEventListener('pointerup', onUp); 58 const lhsWidth = document.documentElement.style.getPropertyValue('--lhs-width').trim() || DEFAULT_PREF.lhsWidth; 59 writePref({ ...readPref(), lhsWidth }); 60 }; 61 divider.addEventListener('pointermove', onMove); 62 divider.addEventListener('pointerup', onUp); 63 }); 64 65 toggle.addEventListener('click', () => { 66 const pref = readPref(); 67 const next = { ...pref, collapsed: !pref.collapsed }; 68 applyPref(next); 69 writePref(next); 70 toggle.setAttribute('aria-expanded', String(!next.collapsed)); 71 toggle.title = next.collapsed ? 'Expand preview panel' : 'Collapse preview panel'; 72 toggle.setAttribute('aria-label', toggle.title); 73 }); 74}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.