diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-09-01 14:48:45 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-09-01 14:48:45 +0300 |
| commit | 8a6d697308162874a236c84aac0b0f8c7ac01f83 (patch) | |
| tree | ed7dc7e8c6f50d66bde721fae78576aede929f66 /website/scripts/check-built-docs.mjs | |
| parent | b54a78aa510b87d1e3b56c619b72eaeb59e4a2a1 (diff) | |
refactor: separate website presentation from runtime
Diffstat (limited to 'website/scripts/check-built-docs.mjs')
| -rw-r--r-- | website/scripts/check-built-docs.mjs | 178 |
1 files changed, 0 insertions, 178 deletions
diff --git a/website/scripts/check-built-docs.mjs b/website/scripts/check-built-docs.mjs deleted file mode 100644 index f6a2f199..00000000 --- a/website/scripts/check-built-docs.mjs +++ /dev/null @@ -1,178 +0,0 @@ -import { access, readFile, readdir, stat } from 'node:fs/promises'; -import { dirname, join, resolve } from 'node:path'; -import { fileURLToPath } from 'node:url'; - -const websiteDir = resolve(dirname(fileURLToPath(import.meta.url)), '..'); -const distDir = resolve(websiteDir, 'dist'); -const nonCanonicalDocsUrl = /https:\/\/herdr\.dev\/(?:ja\/|zh-cn\/)?docs\/(?:preview|\d+\.\d+\.\d+)(?:\/|<)/; -const versions = JSON.parse( - await readFile(resolve(websiteDir, 'src/data/docs-versions.json'), 'utf8'), -); - -for (const entry of versions.versions) { - const scope = versions.scopes[entry.version]; - if (!scope) throw new Error(`missing generated scope for ${entry.version}`); - for (const [locale, pages] of Object.entries(scope.locales)) { - const localePrefix = locale === 'root' ? '' : `${locale}/`; - for (const page of pages) { - const output = resolve( - distDir, - localePrefix, - 'docs', - entry.version, - page, - 'index.html', - ); - await access(output); - } - } -} - -const stable = await readFile(resolve(distDir, 'docs/index.html'), 'utf8'); -const preview = await readFile(resolve(distDir, 'docs/preview/index.html'), 'utf8'); -const archived = await readFile( - resolve(distDir, 'docs', versions.current, 'index.html'), - 'utf8', -); - -assertIncludes(stable, 'data-pagefind-filter="version[content]" content="stable"'); -if (stable.includes('name="robots" content="noindex')) { - throw new Error('stable docs must remain indexable'); -} -assertIncludes(preview, 'data-pagefind-filter="version[content]" content="preview"'); -assertIncludes(preview, `Preview build <code dir="auto">${versions.preview.build_id}</code>`); -if (versions.preview.commit !== 'master') { - assertIncludes(preview, versions.preview.commit.slice(0, 12)); -} -assertIncludes(preview, 'name="robots" content="noindex, nofollow"'); -assertIncludes(archived, `data-pagefind-filter="version[content]" content="${versions.current}"`); -assertIncludes(archived, 'name="robots" content="noindex, nofollow"'); -if (archived.includes(`This page documents Herdr ${versions.current}`)) { - throw new Error('the current documentation version must not be labeled as outdated'); -} -const versionSelect = stable.match(/<select[^>]*aria-label="Documentation version"[^>]*>([\s\S]*?)<\/select>/)?.[1]; -if (!versionSelect) throw new Error('stable docs are missing the version selector'); -if (versionSelect.includes(`value="/docs/${versions.current}/"`)) { - throw new Error('the current release is duplicated in the version selector'); -} - -const previous = versions.versions.find((entry) => entry.version !== versions.current); -if (previous) { - const previousArchive = await readFile( - resolve(distDir, 'docs', previous.version, 'index.html'), - 'utf8', - ); - assertIncludes(previousArchive, `This page documents Herdr ${previous.version}`); -} - -const sitemap = await readFile(resolve(distDir, 'sitemap-0.xml'), 'utf8'); -assertIncludes(sitemap, 'https://herdr.dev/docs/'); -if (nonCanonicalDocsUrl.test(sitemap)) { - throw new Error('preview or versioned documentation URLs must not appear in the sitemap'); -} - -const llmsIndex = await readFile(resolve(distDir, 'llms.txt'), 'utf8'); -const llmsPreview = await readFile(resolve(distDir, 'llms-preview.txt'), 'utf8'); -const llmsSmall = await readFile(resolve(distDir, 'llms-small.txt'), 'utf8'); -const llmsFull = await readFile(resolve(distDir, 'llms-full.txt'), 'utf8'); -const headers = await readFile(resolve(distDir, '_headers'), 'utf8'); -const currentDocs = versions.versions.find((entry) => entry.version === versions.current); -if (!currentDocs?.tag || !currentDocs.source) { - throw new Error(`current docs version ${versions.current} is missing its tag or source`); -} -const stableRawRoot = `https://raw.githubusercontent.com/herdrdev/herdr/${currentDocs.tag}`; -const stableRawBase = `${stableRawRoot}/${currentDocs.source}`; -const stableConfigReferenceUrl = `${stableRawRoot}/${currentDocs.source.replace(/\/content\/docs$/, '/data/config-reference.json')}`; -const previewRawRoot = `https://raw.githubusercontent.com/herdrdev/herdr/${versions.preview.commit}`; -const previewRawBase = `${previewRawRoot}/docs/next/website/src/content/docs`; -const previewConfigReferenceUrl = `${previewRawRoot}/docs/next/website/src/data/config-reference.json`; -assertIncludes(llmsIndex, `Current stable release: ${versions.current}.`); -assertIncludes(llmsIndex, `${stableRawBase}/quick-start.mdx`); -assertIncludes(llmsIndex, `- [Config reference](${stableConfigReferenceUrl})`); -assertIncludes(llmsIndex, '## Using the config reference'); -assertIncludes(llmsIndex, "jq --arg key 'ui.sidebar_width'"); -if (llmsIndex.includes(`${stableRawBase}/config-reference.mdx`)) { - throw new Error('llms.txt must link to config reference data instead of the unrendered MDX component'); -} -assertIncludes(llmsIndex, 'https://herdr.dev/llms-small.txt'); -assertIncludes(llmsIndex, 'https://herdr.dev/llms-full.txt'); -assertIncludes(llmsIndex, 'https://herdr.dev/agent-guide.md'); -assertIncludes(llmsIndex, 'https://herdr.dev/llms-preview.txt'); -assertIncludes(llmsPreview, `Active preview build: ${versions.preview.build_id}`); -assertIncludes(llmsPreview, `${previewRawBase}/quick-start.mdx`); -assertIncludes(llmsPreview, `- [Config reference](${previewConfigReferenceUrl})`); -if (llmsPreview.includes(`${previewRawBase}/config-reference.mdx`)) { - throw new Error('llms-preview.txt must link to config reference data instead of the unrendered MDX component'); -} -assertIncludes(llmsPreview, 'https://herdr.dev/llms.txt'); -const stablePageLinks = llmsIndex - .split('\n') - .filter( - (line) => - line.includes(`](${stableRawBase}/`) || line.includes(`](${stableConfigReferenceUrl})`), - ); -if (stablePageLinks.length !== versions.scopes.stable.locales.root.length) { - throw new Error( - `llms.txt lists ${stablePageLinks.length} stable pages, expected ${versions.scopes.stable.locales.root.length}`, - ); -} -const previewPageLinks = llmsPreview - .split('\n') - .filter( - (line) => - line.includes(`](${previewRawBase}/`) || line.includes(`](${previewConfigReferenceUrl})`), - ); -if (previewPageLinks.length !== versions.scopes.preview.locales.root.length) { - throw new Error( - `llms-preview.txt lists ${previewPageLinks.length} preview pages, expected ${versions.scopes.preview.locales.root.length}`, - ); -} -for (const path of ['/llms.txt', '/llms-preview.txt', '/llms-small.txt', '/llms-full.txt']) { - assertIncludes(headers, `${path}\n Content-Type: text/markdown; charset=utf-8`); -} -for (const [name, content] of [ - ['llms-small.txt', llmsSmall], - ['llms-full.txt', llmsFull], -]) { - assertIncludes(content, '# Herdr documentation'); - assertIncludes(content, '# Troubleshooting'); - assertIncludes(content, '# Socket API'); - if (content.match(/^# Herdr documentation$/gm)?.length !== 1) { - throw new Error(`${name} must contain exactly one stable documentation set`); - } - if (/\]\(\/docs\/(?:preview|\d+\.\d+\.\d+)(?:\/|\))/.test(content)) { - throw new Error(`${name} must not link to preview or versioned documentation`); - } -} - -const build = await inspectFiles(distDir); -if (build.count > 20_000) { - throw new Error(`website build has ${build.count} files, exceeding the Cloudflare Pages free-plan limit`); -} -if (build.largest.bytes > 25 * 1024 * 1024) { - throw new Error(`website asset ${build.largest.path} is ${build.largest.bytes} bytes, exceeding Cloudflare Pages' 25 MiB limit`); -} -process.stdout.write(`validated ${versions.versions.length} documentation versions in ${build.count} website files\n`); - -function assertIncludes(content, expected) { - if (!content.includes(expected)) throw new Error(`built documentation is missing ${expected}`); -} - -async function inspectFiles(directory, root = directory) { - const result = { count: 0, largest: { path: '', bytes: 0 } }; - for (const entry of await readdir(directory, { withFileTypes: true })) { - const path = join(directory, entry.name); - if (entry.isDirectory()) { - const nested = await inspectFiles(path, root); - result.count += nested.count; - if (nested.largest.bytes > result.largest.bytes) result.largest = nested.largest; - } else if (entry.isFile()) { - result.count += 1; - const { size } = await stat(path); - if (size > result.largest.bytes) { - result.largest = { path: path.slice(root.length + 1), bytes: size }; - } - } - } - return result; -} |
