import { readFile, writeFile } from 'node:fs/promises'; const root = new URL('../../', import.meta.url); const taskmasterPath = new URL('.taskmaster/tasks/tasks.json', root); const shareTasksPath = new URL('taskmaster-share/tasks.json', root); const indexPath = new URL('taskmaster-share/index.html', root); const raw = JSON.parse(await readFile(taskmasterPath, 'utf8')); const data = raw.master ?? raw; await writeFile(shareTasksPath, `${JSON.stringify(data, null, 2)}\n`); let html = await readFile(indexPath, 'utf8'); const tasks = data.tasks ?? []; const subtasks = tasks.flatMap((task) => task.subtasks ?? []); const allItems = [...tasks, ...subtasks]; const counts = { parent: tasks.length, subtask: subtasks.length, pending: allItems.filter((item) => item.status !== 'done').length, done: allItems.filter((item) => item.status === 'done').length, }; const escapeHtml = (value) => String(value ?? '').replace(/[&<>"']/g, (char) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', })[char]); const badge = (value, prefix = '') => `${escapeHtml(value)}`; const formatDeps = (dependencies, parentId) => { if (!dependencies?.length) return ''; const values = dependencies.map((dependency) => String(dependency).includes('.') ? dependency : `${parentId}.${dependency}` ); return `

Depends on: ${escapeHtml(values.join(', '))}

`; }; const renderSubtask = (task, subtask) => `
  • ${escapeHtml(task.id)}.${escapeHtml(subtask.id)} ${escapeHtml(subtask.title)} ${badge(subtask.status)} ${badge(subtask.priority, 'priority-')}

    ${escapeHtml(subtask.description || subtask.details || '')}

    ${formatDeps(subtask.dependencies, task.id)}
  • `; const renderTask = (task) => `

    Task ${escapeHtml(task.id)}

    ${escapeHtml(task.title)}

    ${badge(task.status)}${badge(task.priority, 'priority-')}

    ${escapeHtml(task.description)}

    Details and test strategy

    ${escapeHtml(task.details)}

    ${task.testStrategy ? `

    Test strategy: ${escapeHtml(task.testStrategy)}

    ` : ''} ${task.dependencies?.length ? `

    Depends on: ${escapeHtml(task.dependencies.join(', '))}

    ` : ''}

    Subtasks (${(task.subtasks ?? []).length})

    `; const taskFive = tasks.find((task) => Number(task.id) === 5); if (!taskFive) { throw new Error('Task 5 is missing from Taskmaster data.'); } html = html .replace(/
    \d+<\/strong>parent tasks<\/span><\/div>/, `
    ${counts.parent}parent tasks
    `) .replace(/
    \d+<\/strong>subtasks<\/span><\/div>/, `
    ${counts.subtask}subtasks
    `) .replace(/
    \d+<\/strong>pending items<\/span><\/div>/, `
    ${counts.pending}pending items
    `) .replace(/
    \d+<\/strong>done items<\/span><\/div>/, `
    ${counts.done}done items
    `) .replace( 'Track security remediation, payment architecture, refactor decisions, and completed documentation work from one place.', 'Track security remediation, payment architecture, Telegram-native work, refactor decisions, and completed documentation work from one place.' ); const article = renderTask(taskFive); if (html.includes('Task 5

    ')) { html = html.replace( /\n
    \n
    \n
    \n

    Task 5<\/p>[\s\S]*?\n

    /, `\n${article}\n
    ` ); } else { html = html.replace( '\n
    ', `\n${article}\n
    ` ); } await writeFile(indexPath, html); console.log(`Updated share page: ${counts.parent} tasks, ${counts.subtask} subtasks.`);