also looking at this
fix: name the document a refused Markdown link is in, and report all of them
#95
3 files
+195
-7
| @@ -13,7 +13,8 @@ import { generateRssFeed } from '../src/rss' | ||
| 13 | 13 | import { buildSearchIndex, SEARCH_INDEX_PATH } from '../src/search-index' |
| 14 | 14 | import { generateSitemap } from '../src/sitemap' |
| 15 | 15 | import { siteUrl } from '../src/site-url' |
| 16 | import { createMarkdownPageCatalog, findMarkdownFiles } from '../src/markdown-pages' | |
| 16 | import type { MarkdownLinkFailure } from '../src/markdown-pages' | |
| 17 | import { createMarkdownPageCatalog, describeLinkFailures, findMarkdownFiles } from '../src/markdown-pages' | |
| 17 | 18 | import { withBuildOutput } from '../src/build-output' |
| 18 | 19 | import { verifyBuildManifest, writeBuildManifest } from '../src/build-manifest' |
| 19 | 20 | import { cleanCommand } from './commands/clean' |
| @@ -224,11 +225,28 @@ export async function buildDocs(options: CliOption = {}): Promise<boolean> { | ||
| 224 | 225 | const catalog = createMarkdownPageCatalog(markdownFiles, docsDir, i18n) |
| 225 | 226 | const renderTargets = catalog.pages |
| 226 | 227 | |
| 228 | /* | |
| 229 | * Every refused link, not the first one. | |
| 230 | * | |
| 231 | * Throwing on the first meant a documentation set with N dead links took | |
| 232 | * N builds to clean up: fix one, rebuild, learn the next. Each run is a | |
| 233 | * full build, and the count is unknowable until the last one passes. | |
| 234 | * That is felt most on the first build after adopting the check, when a | |
| 235 | * set that has never been link-checked is checked all at once. | |
| 236 | * | |
| 237 | * Collecting changes nothing about what is published. The throw below | |
| 238 | * still happens inside `withBuildOutput`, before anything is moved into | |
| 239 | * place, so a build with a dead link still refuses and still leaves the | |
| 240 | * previous complete output alone. | |
| 241 | */ | |
| 242 | const linkFailures: MarkdownLinkFailure[] = [] | |
| 243 | const collectLinkFailures = (failure: MarkdownLinkFailure): void => { linkFailures.push(failure) } | |
| 244 | ||
| 227 | 245 | for (const target of renderTargets) { |
| 228 | 246 | const markdown = await Bun.file(target.sourceFile).text() |
| 229 | 247 | |
| 230 | 248 | // Convert markdown to HTML (handles frontmatter, hero, features, etc.) |
| 231 | const { html, frontmatter } = await markdownToHtml(markdown, docsDir, { page: target, catalog }) | |
| 249 | const { html, frontmatter } = await markdownToHtml(markdown, docsDir, { page: target, catalog, collectLinkFailures }) | |
| 232 | 250 | |
| 233 | 251 | const relativePath = target.relativePath |
| 234 | 252 | const currentPath = `/${relativePath}` |
| @@ -267,6 +285,11 @@ export async function buildDocs(options: CliOption = {}): Promise<boolean> { | ||
| 267 | 285 | } |
| 268 | 286 | } |
| 269 | 287 | |
| 288 | // Reported together, and only once every page has had its turn, so the | |
| 289 | // list is the whole truth rather than the first thing encountered. | |
| 290 | if (linkFailures.length > 0) | |
| 291 | throw new Error(describeLinkFailures(linkFailures)) | |
| 292 | ||
| 270 | 293 | if (verbose) { |
| 271 | 294 | console.log(`Processed ${markdownFiles.length} markdown files into ${renderTargets.length} pages.`) |
| 272 | 295 | } |