const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args)); module.exports = async function() { const GITEA_API = 'https://git.firefrostgaming.com/api/v1'; const REPO_OWNER = 'firefrost-gaming'; const REPO_NAME = 'firefrost-operations-manual'; const TOKEN = process.env.GITEA_TOKEN || 'e0e330cba1749b01ab505093a160e4423ebbbe36'; const tasks = []; try { // Get list of task directories const response = await fetch( `${GITEA_API}/repos/${REPO_OWNER}/${REPO_NAME}/contents/docs/tasks?ref=master`, { headers: { 'Authorization': `token ${TOKEN}`, 'Accept': 'application/json' }, timeout: 30000 } ); if (!response.ok) { console.error('Failed to fetch task list:', response.status); return []; } const dirs = await response.json(); const taskDirs = dirs.filter(d => d.type === 'dir' && d.name !== '_archive'); // Fetch each task's README for (const dir of taskDirs) { try { // Try README.md first let readmePath = `docs/tasks/${dir.name}/README.md`; let readmeResponse = await fetch( `${GITEA_API}/repos/${REPO_OWNER}/${REPO_NAME}/contents/${encodeURIComponent(readmePath)}?ref=master`, { headers: { 'Authorization': `token ${TOKEN}`, 'Accept': 'application/json' } } ); if (!readmeResponse.ok) { // Try to find any .md file const filesResponse = await fetch( `${GITEA_API}/repos/${REPO_OWNER}/${REPO_NAME}/contents/docs/tasks/${encodeURIComponent(dir.name)}?ref=master`, { headers: { 'Authorization': `token ${TOKEN}`, 'Accept': 'application/json' } } ); if (filesResponse.ok) { const files = await filesResponse.json(); const mdFile = files.find(f => f.name.endsWith('.md')); if (mdFile) { readmePath = `docs/tasks/${dir.name}/${mdFile.name}`; readmeResponse = await fetch( `${GITEA_API}/repos/${REPO_OWNER}/${REPO_NAME}/contents/${encodeURIComponent(readmePath)}?ref=master`, { headers: { 'Authorization': `token ${TOKEN}`, 'Accept': 'application/json' } } ); } } } if (readmeResponse && readmeResponse.ok) { const fileData = await readmeResponse.json(); const content = Buffer.from(fileData.content, 'base64').toString('utf-8'); // Parse YAML frontmatter const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/); if (frontmatterMatch) { const frontmatter = {}; frontmatterMatch[1].split('\n').forEach(line => { const match = line.match(/^(\w+):\s*(.+)$/); if (match) { frontmatter[match[1]] = match[2].trim(); } }); // Extract title from first H1 const titleMatch = content.match(/^#\s+(.+)$/m); const title = titleMatch ? titleMatch[1] : dir.name; tasks.push({ slug: dir.name, title: title, status: frontmatter.status || 'open', priority: frontmatter.priority || 'P3', owner: frontmatter.owner || 'Michael', created: frontmatter.created || '2026-01-01', giteaUrl: `https://git.firefrostgaming.com/${REPO_OWNER}/${REPO_NAME}/src/branch/master/docs/tasks/${encodeURIComponent(dir.name)}` }); } } } catch (err) { console.error(`Error processing ${dir.name}:`, err.message); } } // Sort by priority (P1 first) then by title tasks.sort((a, b) => { if (a.priority !== b.priority) { return a.priority.localeCompare(b.priority); } return a.title.localeCompare(b.title); }); console.log(`[11ty] Loaded ${tasks.length} tasks from Gitea`); return tasks; } catch (err) { console.error('[11ty] Error fetching tasks:', err.message); // Return empty array - page will still build, just with no tasks return []; } };