diff --git a/src/layouts/Entry.astro b/src/layouts/Entry.astro index 5713f1b..073c979 100644 --- a/src/layouts/Entry.astro +++ b/src/layouts/Entry.astro @@ -15,15 +15,33 @@ const { title, frontmatter, id } = Astro.props;

{title}

{id && ( - +
+ + +
)}
+ {id && ( + + )}
@@ -38,4 +56,123 @@ const { title, frontmatter, id } = Astro.props; const slug = (e.currentTarget as HTMLElement).dataset.slug; window.dispatchEvent(new CustomEvent('open-editor', { detail: { slug, apiBase: '/pages' } })); }); + + const historyBtn = document.getElementById('history-btn') as HTMLElement | null; + const historyPanel = document.getElementById('page-history') as HTMLElement | null; + const historyList = document.getElementById('history-list') as HTMLElement | null; + const historyClose = document.getElementById('history-close') as HTMLElement | null; + + if (historyBtn && historyPanel && historyList) { + let loaded = false; + const slug = historyBtn.dataset.slug!; + + function esc(s: string) { + return s.replace(/&/g, '&').replace(//g, '>'); + } + + function renderDiff(text: string): string { + return text.split('\n').map(line => { + if (line.startsWith('diff ') || line.startsWith('index ') || line.startsWith('new file') || + line.startsWith('deleted file') || line.startsWith('similarity') || line.startsWith('rename')) { + return `${esc(line)}`; + } + if (line.startsWith('--- ') || line.startsWith('+++ ')) { + return `${esc(line)}`; + } + if (line.startsWith('@@')) { + return `${esc(line)}`; + } + if (line.startsWith('+')) { + return `${esc(line)}`; + } + if (line.startsWith('-')) { + return `${esc(line)}`; + } + return `${esc(line)}`; + }).join('\n'); + } + + historyBtn.addEventListener('click', async () => { + if (!historyPanel.classList.contains('hidden')) { + historyPanel.classList.add('hidden'); + return; + } + historyPanel.classList.remove('hidden'); + if (loaded) return; + loaded = true; + + try { + const r = await fetch(`/api/history/${slug}`, { credentials: 'include' }); + if (!r.ok) throw new Error(String(r.status)); + const { log } = await r.json(); + if (!log?.length) { + historyList.innerHTML = '

Nessuna modifica registrata.

'; + return; + } + historyList.innerHTML = log.map((e: any) => { + const [author, rest] = e.message.includes(': ') ? e.message.split(': ', 2) : ['', e.message]; + return ` +
+ + +
`; + }).join(''); + + historyList.addEventListener('click', async (ev) => { + const btn = (ev.target as Element).closest('.hist-row'); + if (!btn) return; + const hash = btn.dataset.hash!; + const diffDiv = historyList.querySelector(`.hist-diff[data-hash="${hash}"]`); + const pre = diffDiv?.querySelector('pre'); + const chevron = btn.querySelector('.hist-chevron'); + if (!diffDiv || !pre) return; + + if (btn.getAttribute('aria-expanded') === 'true') { + diffDiv.classList.add('hidden'); + btn.setAttribute('aria-expanded', 'false'); + if (chevron) chevron.style.transform = ''; + return; + } + btn.setAttribute('aria-expanded', 'true'); + if (chevron) chevron.style.transform = 'rotate(90deg)'; + diffDiv.classList.remove('hidden'); + if (pre.dataset.loaded) return; + + pre.textContent = 'Caricamento diff…'; + pre.style.color = 'var(--text-5)'; + try { + const diffUrl = `/api/diff/${hash}?file=pages/${encodeURIComponent(slug)}.md`; + const dr = await fetch(diffUrl, { credentials: 'include' }); + if (!dr.ok) throw new Error(String(dr.status)); + const { diff } = await dr.json(); + pre.dataset.loaded = '1'; + if (!diff.trim()) { + pre.textContent = '(nessuna modifica ai file)'; + pre.style.color = 'var(--text-5)'; + } else { + pre.innerHTML = renderDiff(diff); + pre.style.color = ''; + } + } catch { + pre.textContent = 'Errore nel caricamento della diff.'; + pre.style.color = '#f87171'; + } + }); + } catch { + historyList.innerHTML = '

Errore nel caricamento.

'; + } + }); + + historyClose?.addEventListener('click', () => { + historyPanel.classList.add('hidden'); + }); + }