aboutsummaryrefslogtreecommitdiff
path: root/website/scripts/check-built-docs.mjs
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-09-01 14:48:45 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-09-01 14:48:45 +0300
commit8a6d697308162874a236c84aac0b0f8c7ac01f83 (patch)
treeed7dc7e8c6f50d66bde721fae78576aede929f66 /website/scripts/check-built-docs.mjs
parentb54a78aa510b87d1e3b56c619b72eaeb59e4a2a1 (diff)
refactor: separate website presentation from runtime
Diffstat (limited to 'website/scripts/check-built-docs.mjs')
-rw-r--r--website/scripts/check-built-docs.mjs178
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;
-}