From ad2f7b47ee5c1a284ee34f22be00d8b38312c664 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 17 May 2026 19:15:56 +0000 Subject: [PATCH] Fix phase7 index.html: restore main base, apply only PWA additions Cherry-pick had auto-merged with wrong base (reverted TOC/callout CSS and renderTocTag). Now uses main's index.html with only the three phase7 additions applied on top: manifest link, SW registration script, and offline-message localStorage handling. https://claude.ai/code/session_01UP8Wo2CKPNhvvTkzX48CWF --- app/index.html | 119 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 92 insertions(+), 27 deletions(-) diff --git a/app/index.html b/app/index.html index ca0b5c4..df1a053 100644 --- a/app/index.html +++ b/app/index.html @@ -793,6 +793,39 @@ body { .main-content { padding: 1rem 1rem 3rem; } } +/* ═══════════════════════════════════════════ + TAG SYSTEM: CALLOUTS + ═══════════════════════════════════════════ */ +.mdcms-callout { + border-left: 4px solid; + border-radius: 0 6px 6px 0; + padding: 0.85rem 1rem 0.85rem 1rem; + margin: 1.25rem 0; +} +.mdcms-callout-title { + display: flex; + align-items: center; + gap: 0.4rem; + font-weight: 700; + font-size: 0.95rem; + margin-bottom: 0.45rem; +} +.mdcms-callout-title .mdcms-icon { font-size: 1.1em; } +.mdcms-callout-body { font-size: 0.95rem; } +.mdcms-callout-body > *:first-child { margin-top: 0; } +.mdcms-callout-body > *:last-child { margin-bottom: 0; } + +/* ═══════════════════════════════════════════ + TAG SYSTEM: TABLE OF CONTENTS + ═══════════════════════════════════════════ */ +.mdcms-toc { margin: 1rem 0; } +.mdcms-toc-section { font-size: 1rem; font-weight: 600; margin: 1.5rem 0 0.4rem; color: var(--font-colour-muted); border-bottom: 1px solid var(--divider); padding-bottom: 0.25rem; } +.mdcms-toc-list { list-style: none; padding: 0; margin: 0 0 0.5rem; } +.mdcms-toc-list li { padding: 0.2rem 0; border-bottom: 1px solid var(--divider); } +.mdcms-toc-list li:last-child { border-bottom: none; } +.mdcms-toc-list a { color: var(--accent); text-decoration: none; font-size: 0.95rem; } +.mdcms-toc-list a:hover { text-decoration: underline; } + /* ═══════════════════════════════════════════ TAG SYSTEM: POST LISTINGS ═══════════════════════════════════════════ */ @@ -870,32 +903,6 @@ body { } .post-load-more:hover { background: var(--nav-hover-bg); } -/* ── Callout tags ──────────────────────────────────────── */ -.mdcms-callout { - border-left: 4px solid var(--callout-primary, var(--accent)); - background: var(--callout-bg, transparent); - border-radius: 0 0.4rem 0.4rem 0; - padding: 0.75rem 1rem; - margin: 1rem 0; -} -.mdcms-callout-title { - display: flex; - align-items: center; - gap: 0.45rem; - font-weight: 700; - color: var(--callout-primary, var(--accent)); - margin-bottom: 0.4rem; -} -.mdcms-callout-title .mdcms-icon svg { - fill: var(--callout-primary, var(--accent)); - width: 1.2em; - height: 1.2em; - display: block; -} -.mdcms-callout-body { margin: 0; } -.mdcms-callout-body > :first-child { margin-top: 0; } -.mdcms-callout-body > :last-child { margin-bottom: 0; } - @media print { .sidebar, .topbar, .scroll-top, .hamburger, .mobile-header, .theme-toggle, .search-container { display: none !important; } @@ -1322,6 +1329,7 @@ body { // ─── Fonts ──────────────────────────────────────────────── function loadFonts(tc) { + if (document.querySelector('link[data-mdcms-fonts]')) return; function parseFont(spec) { if (!spec) return null; const parts = spec.split(':'); @@ -1897,12 +1905,70 @@ function fmtDatetime(dtStr) { return 'rgba(' + r + ',' + g + ',' + b + ',' + alpha + ')'; } + function renderTocTag(container) { + const byCode = {}; + navSections.forEach(s => { byCode[s.code] = s; }); + + const sortedSections = navSections + .filter(s => !isDraftSection(s.code, byCode)) + .sort((a, b) => ((a.sort ?? 999) - (b.sort ?? 999)) || (a.code || '').localeCompare(b.code || '')); + + const visiblePages = navData.filter(p => { + if (p.file === currentPage) return false; + if (!pageShouldDisplay(p)) return false; + const sid = p['section-id']; + if (sid && isDraftSection(sid, byCode)) return false; + return true; + }); + + const bySection = {}; + const unsectioned = []; + visiblePages.forEach(p => { + const sid = p['section-id'] || null; + if (sid) { (bySection[sid] = bySection[sid] || []).push(p); } + else unsectioned.push(p); + }); + + function sortPages(pages) { + return [...pages].sort((a, b) => + ((a.sort ?? 999) - (b.sort ?? 999)) || a.file.localeCompare(b.file)); + } + + function makeList(pages) { + const ul = document.createElement('ul'); + ul.className = 'mdcms-toc-list'; + pages.forEach(p => { + const a = el('a', { href: '#' + p.file, textContent: pageDisplayTitle(p) }); + a.addEventListener('click', e => { e.preventDefault(); navigateTo(p.file); }); + ul.appendChild(el('li', {}, a)); + }); + return ul; + } + + const div = el('div', { className: 'mdcms-toc' }); + + if (unsectioned.length) div.appendChild(makeList(sortPages(unsectioned))); + + sortedSections.forEach(section => { + const pages = bySection[section.code]; + if (!pages || !pages.length) return; + div.appendChild(el('h3', { className: 'mdcms-toc-section', textContent: sectionDisplayName(section) })); + div.appendChild(makeList(sortPages(pages))); + }); + + if (!div.children.length) div.textContent = 'No pages found.'; + + container.replaceWith(div); + } + function hydrateMdcmsTags() { document.querySelectorAll('.mdcms-tag').forEach(function(tagEl) { try { var cfg = JSON.parse(tagEl.getAttribute('data-config')); if (/^callout-(info|warning|success|error)$/.test(cfg.tagName)) { renderCalloutTag(tagEl, cfg); + } else if (cfg.tagName === 'toc') { + renderTocTag(tagEl); } else { renderPostTag(tagEl, cfg); } @@ -2648,7 +2714,6 @@ function fmtDatetime(dtStr) { } catch (e) { /* fall back to hardcoded CSS defaults */ } } - // Write offline message to localStorage for SW offline fallback const offlineMsgCfg = config['offline-message']; if (offlineMsgCfg) { const offlineText = typeof offlineMsgCfg === 'string'