From 75f6cab6f16a60ead1ab56ff2a2761ca461d3401 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Louis=20Pr=C3=A9?= Date: Tue, 21 Apr 2026 19:16:35 -0700 Subject: [PATCH] feat: Detect cross-section relative links in link validator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Relative links between site sections (e.g., from Guides to API Reference) don't work in GitBook — they must be absolute URLs. The validator now flags these. Co-Authored-By: Claude Opus 4.6 (1M context) --- codegen/validate-links.ts | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/codegen/validate-links.ts b/codegen/validate-links.ts index 9c0bb1145..ae7a25b99 100644 --- a/codegen/validate-links.ts +++ b/codegen/validate-links.ts @@ -1,7 +1,16 @@ import { existsSync, readdirSync, readFileSync } from 'node:fs' import { dirname, join, resolve } from 'node:path' -import { baseUrl, siteSections, siteUrlPrefix } from './lib/config.js' +import { + baseUrl, + type SiteSection, + siteSections, + siteUrlPrefix, +} from './lib/config.js' + +function findSiteSection(filePath: string): SiteSection | undefined { + return siteSections.find(({ root }) => filePath.startsWith(root + '/')) +} const absoluteUrlPattern = new RegExp( `${baseUrl.replaceAll('.', '\\.')}[^)\\s]+`, @@ -98,6 +107,23 @@ function checkRelativeLink(file: string, line: number, rawLink: string): void { url: rawLink, reason: `File not found: ${resolved}`, }) + return + } + + // Check that relative links don't cross site section boundaries + const sourceSection = findSiteSection(file) + const targetSection = findSiteSection(resolved) + if ( + sourceSection != null && + targetSection != null && + sourceSection.root !== targetSection.root + ) { + brokenLinks.push({ + file, + line, + url: rawLink, + reason: `Cross-section relative link: "${sourceSection.name}" -> "${targetSection.name}". Use an absolute URL instead`, + }) } }