async function loadManifest() { const res = await fetch('../data/manifest.json'); if (!res.ok) throw new Error('Failed to load manifest.json'); return res.json(); } function parseCSV(text) { const lines = text.trim().split(/\r?\n/); if (!lines.length) return { headers: [], rows: [] }; const headers = lines[0].split(',').map(h => h.trim()); const rows = lines.slice(1).map(line => { const cols = []; let current = ''; let inQuotes = false; for (let i = 0; i < line.length; i++) { const ch = line[i]; if (ch === '"') { if (inQuotes && line[i + 1] === '"') { current += '"'; i++; } else { inQuotes = !inQuotes; } } else if (ch === ',' && !inQuotes) { cols.push(current); current = ''; } else { current += ch; } } cols.push(current); return cols; }); return { headers, rows }; } function renderCSVList(files) { const list = document.getElementById('csv-list'); list.innerHTML = ''; if (!files.length) { list.textContent = 'No CSV files listed in manifest.json yet.'; return; } files.forEach(f => { const pill = document.createElement('div'); pill.className = 'csv-pill'; pill.textContent = f; list.appendChild(pill); }); } function renderPreview(headers, rows) { const preview = document.getElementById('preview'); if (!headers.length) { preview.textContent = 'No data loaded yet.'; return; } const table = document.createElement('table'); table.className = 'table'; const thead = document.createElement('thead'); const trh = document.createElement('tr'); headers.forEach(h => { const th = document.createElement('th'); th.textContent = h; trh.appendChild(th); }); thead.appendChild(trh); table.appendChild(thead); const tbody = document.createElement('tbody'); rows.slice(0, 10).forEach(r => { const tr = document.createElement('tr'); r.forEach(cell => { const td = document.createElement('td'); td.textContent = cell; tr.appendChild(td); }); tbody.appendChild(tr); }); table.appendChild(tbody); preview.innerHTML = ''; preview.appendChild(table); } async function loadFirstCSV(files) { if (!files.length) return; const res = await fetch(`../data/${files[0]}`); if (!res.ok) throw new Error(`Failed to load ${files[0]}`); const text = await res.text(); const { headers, rows } = parseCSV(text); renderPreview(headers, rows); } async function init() { try { const manifest = await loadManifest(); const files = manifest.csvFiles || []; renderCSVList(files); await loadFirstCSV(files); } catch (err) { document.getElementById('csv-list').textContent = err.message; console.error(err); } } init();