import { readFile, readdir } from 'node:fs/promises'; import { join, relative, resolve, sep } from 'node:path'; import { parseHTML } from 'linkedom'; async function listFiles(root, directory = root) { const entries = await readdir(directory, { withFileTypes: true }); const files = []; for (const entry of entries) { const path = join(directory, entry.name); if (entry.isDirectory()) files.push(...await listFiles(root, path)); else if (entry.isFile()) files.push(path); } return files.sort(); } export async function checkRenderedOutput({ distRoot }) { const absoluteDistRoot = resolve(distRoot); const files = await listFiles(absoluteDistRoot); const relativeFiles = files.map((file) => relative(absoluteDistRoot, file).split(sep).join('/')); const htmlFiles = files.filter((file) => { const path = relative(absoluteDistRoot, file).split(sep).join('/'); return path.endsWith('.html') && path !== '404.html'; }); const headingIssues = []; for (const file of htmlFiles) { const path = relative(absoluteDistRoot, file).split(sep).join('/'); const { document } = parseHTML(await readFile(file, 'utf8')); if (document.querySelector('meta[http-equiv="refresh"]')) continue; const h1Count = document.querySelectorAll('h1').length; if (h1Count !== 1) headingIssues.push({ file: path, h1Count }); } return { htmlFilesChecked: htmlFiles.length, headingIssues, unpublishedPaths: relativeFiles.filter((path) => path.split('/').includes('to-be-studied')), }; }