document.addEventListener('alpine:init', () => { Alpine.data('pkgChangelog', (count, i18n) => ({ state: 'loading', // 'loading' | 'loaded' | 'error' i18n: i18n, entries: [], async init() { try { const res = await fetch('https://packages.danix.xyz/ChangeLog.txt'); if (!res.ok) throw new Error('HTTP ' + res.status); const text = await res.text(); this.entries = parseChangelog(text, count); this.state = 'loaded'; } catch (e) { console.error('pkg-changelog fetch error:', e); this.state = 'error'; } } })); }); function parseChangelog(text, maxEntries) { const SEPARATOR = '+--------------------------+'; const chunks = text.split(SEPARATOR); const entries = []; for (const chunk of chunks) { if (entries.length >= maxEntries) break; const lines = chunk.split('\n').map(l => l.trimEnd()).filter(l => l.trim() !== ''); if (lines.length < 2) continue; const timestamp = lines[0].trim(); // Validate it looks like a timestamp (starts with a day name) if (!/^(Mon|Tue|Wed|Thu|Fri|Sat|Sun)/.test(timestamp)) continue; const changes = lines.slice(1).join('\n').trim(); entries.push({ timestamp, changes }); } return entries; }