From 55ddd0680ede6ba1a5b50876c200c5884673bb90 Mon Sep 17 00:00:00 2001 From: Fabien POLLY Date: Tue, 9 Dec 2025 14:23:33 +0100 Subject: [PATCH] feat: Add small badge styles and enhance content loader with persistent local storage caching and TTL. --- index.html | 70 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 7 deletions(-) diff --git a/index.html b/index.html index 87418c8..49408e0 100644 --- a/index.html +++ b/index.html @@ -393,6 +393,21 @@ outline-offset: 2px; } + .badge-sm { + transform: scale(.75); + transform-origin: top left; + margin-bottom: calc(-6px * .75); + } + + .badge-sm:hover { + transform: scale(.80); + transition: transform .15s ease; + } + + ::-webkit-scrollbar-thumb { + background: linear-gradient(180deg, var(--accent-green), var(--border-color)); + } + /* --- PRINT STYLESHEET --- */ @media print { body { @@ -584,29 +599,35 @@
:: JOIN US ::
+ @@ -891,7 +912,7 @@ hljs.highlightAll(); } - // --- 5. CONTENT LOADER --- + // --- 5. CONTENT LOADER (PERSISTENT CACHE OPTIMIZED) --- async function loadContent(folder, title, filename, pushHistory = true) { const viewer = document.getElementById('markdown-viewer'); const pageNav = document.getElementById('page-nav'); @@ -903,6 +924,7 @@ ${cleanFolder} / ${title} `; + // Only show loader if not in RAM cache if (!STATE.contentCache[`${folder}/${filename}`]) { viewer.innerHTML = `
`; } @@ -913,10 +935,30 @@ try { let text; const cacheKey = `${folder}/${filename}`; + const storageKey = `bjorn_content_${cacheKey}`; + const now = Date.now(); + const TTL = 3600 * 1000 * 24; // 24 Hours Cache + // 1. Check RAM (Fastest) if (STATE.contentCache[cacheKey]) { text = STATE.contentCache[cacheKey]; - } else { + } + // 2. Check LocalStorage (Persistence) + else { + const stored = localStorage.getItem(storageKey); + if (stored) { + try { + const data = JSON.parse(stored); + if (now - data.ts < TTL) { + text = data.content; + STATE.contentCache[cacheKey] = text; // Restore to RAM + } + } catch (e) { localStorage.removeItem(storageKey); } + } + } + + // 3. Network Fetch (Fallback) + if (!text) { try { const path1 = `./wiki/${folder}/${filename}`; const res = await fetch(path1); @@ -934,7 +976,15 @@ throw new Error(`Content not found.`); } } + + // Save to caches STATE.contentCache[cacheKey] = text; + try { + localStorage.setItem(storageKey, JSON.stringify({ + ts: now, + content: text + })); + } catch (e) { console.warn("LocalStorage full"); } } const cleanHTML = DOMPurify.sanitize(marked.parse(text)); @@ -1018,8 +1068,14 @@ [idx - 1, idx + 1].forEach(i => { if (flatList[i]) { const url = `./wiki/${flatList[i].folder}/${flatList[i].file}`; + const cacheKey = `${flatList[i].folder}/${flatList[i].file}`; + + // Check persistent cache first to avoid fetch + const storageKey = `bjorn_content_${cacheKey}`; + if (localStorage.getItem(storageKey)) return; + fetch(url).then(r => r.text()).then(t => { - STATE.contentCache[`${flatList[i].folder}/${flatList[i].file}`] = t; + STATE.contentCache[cacheKey] = t; }).catch(() => { }); } });