91e75e620b
CI: cua-driver distro-compat matrix / Resolve release version (push) Waiting to run
CI: cua-driver distro-compat matrix / debian:12 (glibc 2.36) (push) Blocked by required conditions
CI: cua-driver distro-compat matrix / fedora:41 (glibc 2.40) (push) Blocked by required conditions
CI: cua-driver distro-compat matrix / rockylinux:9 (glibc 2.34) (push) Blocked by required conditions
CI: cua-driver distro-compat matrix / ubuntu:22.04 (glibc 2.35) (push) Blocked by required conditions
CI: cua-driver distro-compat matrix / ubuntu:24.04 (glibc 2.39) (push) Blocked by required conditions
CI: cua-driver distro-compat matrix / Distro compat summary (push) Blocked by required conditions
CI: Nix Linux Rust source / Nix / compositor build (push) Waiting to run
CI: Nix Linux Rust source / Nix / driver package (push) Waiting to run
CI: Nix Linux Rust source / Nix / Rust unit tests (push) Waiting to run
CI: Rust Linux unit / Rust Linux unit and compile (push) Waiting to run
CI: Rust Windows unit / Rust Windows unit and compile (push) Waiting to run
CI: SPDX Headers / Check SPDX headers (warn-only) (push) Waiting to run
CD: Docs MCP Server / build (linux/amd64) (push) Waiting to run
CD: Docs MCP Server / build (linux/arm64) (push) Waiting to run
CD: Docs MCP Server / merge (push) Blocked by required conditions
99 lines
2.5 KiB
TypeScript
99 lines
2.5 KiB
TypeScript
#!/usr/bin/env npx tsx
|
|
|
|
/**
|
|
* Documentation Link Checker
|
|
*
|
|
* Uses next-validate-link (by the Fumadocs author) to validate all internal
|
|
* links across MDX documentation files. Builds the valid URL map from the
|
|
* content directory and validates links using remark-based MDX parsing.
|
|
*
|
|
* Usage:
|
|
* pnpm docs:check-links # Check internal links
|
|
* pnpm docs:check-links:external # Also check external links
|
|
*/
|
|
|
|
import { readFiles, validateFiles, printErrors, type ScanResult } from 'next-validate-link';
|
|
import * as path from 'path';
|
|
import fg from 'fast-glob';
|
|
|
|
const DOCS_DIR = path.resolve(__dirname, '..');
|
|
const CONTENT_DIR = path.join(DOCS_DIR, 'content/docs');
|
|
|
|
/**
|
|
* Build the ScanResult (valid URL map) directly from content files.
|
|
* This is more reliable than scanURLs for catch-all routes.
|
|
*/
|
|
function buildScannedUrls(): ScanResult {
|
|
const urls = new Map<string, {}>();
|
|
const mdxFiles = fg.sync('**/*.mdx', { cwd: CONTENT_DIR });
|
|
|
|
for (const file of mdxFiles) {
|
|
const slug = file.replace(/\.mdx$/, '').replace(/\/index$/, '');
|
|
urls.set(`/${slug}`, {});
|
|
}
|
|
|
|
// Also add the root
|
|
urls.set('/', {});
|
|
|
|
return { urls, fallbackUrls: [] };
|
|
}
|
|
|
|
function pathToUrl(filePath: string): string | undefined {
|
|
const slug = filePath
|
|
.replace(/^content\/docs\//, '')
|
|
.replace(/\.mdx$/, '')
|
|
.replace(/\/index$/, '');
|
|
return `/${slug}`;
|
|
}
|
|
|
|
async function main() {
|
|
const args = process.argv.slice(2);
|
|
const checkExternal = args.includes('--external');
|
|
|
|
const scanned = buildScannedUrls();
|
|
|
|
// Read all MDX content files
|
|
const files = await readFiles('content/docs/**/*.mdx', { pathToUrl });
|
|
|
|
// Validate all links in the MDX files
|
|
const results = await validateFiles(files, {
|
|
scanned,
|
|
checkExternal,
|
|
// Fumadocs resolves relative MDX links at runtime, skip them here
|
|
checkRelativePaths: false,
|
|
checkRelativeUrls: false,
|
|
pathToUrl,
|
|
whitelist: (url: string) => {
|
|
const pathname = url.split(/[#?]/)[0];
|
|
const ext = path.extname(pathname).toLowerCase();
|
|
const staticExts = new Set([
|
|
'.png',
|
|
'.jpg',
|
|
'.jpeg',
|
|
'.gif',
|
|
'.svg',
|
|
'.ico',
|
|
'.webp',
|
|
'.avif',
|
|
'.mp4',
|
|
'.webm',
|
|
'.pdf',
|
|
'.css',
|
|
'.js',
|
|
'.woff',
|
|
'.woff2',
|
|
'.ttf',
|
|
'.eot',
|
|
]);
|
|
return staticExts.has(ext);
|
|
},
|
|
});
|
|
|
|
printErrors(results, true);
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error('Fatal error:', err);
|
|
process.exit(1);
|
|
});
|