import { readFile, stat } from "node:fs/promises"; import path from "node:path"; import { fileURLToPath } from "node:url"; const siteRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); const errors = []; const requiredFiles = [ "index.html", "styles.css", "app.js", "assets/goodbuddy-light.png", "assets/goodbuddy-dark.png", "README.md", ]; const report = (condition, message) => { if (!condition) { errors.push(message); } }; const readSiteFile = async (relativePath) => { try { return await readFile(path.join(siteRoot, relativePath), "utf8"); } catch { errors.push(`缺少文件:${relativePath}`); return ""; } }; await Promise.all( requiredFiles.map(async (relativePath) => { try { const fileStats = await stat(path.join(siteRoot, relativePath)); report(fileStats.isFile(), `不是普通文件:${relativePath}`); } catch { errors.push(`缺少文件:${relativePath}`); } }), ); const [html, css, appJs] = await Promise.all([ readSiteFile("index.html"), readSiteFile("styles.css"), readSiteFile("app.js"), ]); for (const [relativePath, content] of [ ["index.html", html], ["styles.css", css], ["app.js", appJs], ]) { report(!/[ \t]+$/m.test(content), `${relativePath} 包含行尾空白`); report(!content.includes("\t"), `${relativePath} 包含 Tab 缩进`); } report(//.test(html), "页面语言必须是 zh-CN"); report(//.test( html, ), "canonical 地址必须指向 GitHub Pages 正式站点", ); report((html.match(/