66import fs from "node:fs" ;
77import path from "node:path" ;
88import { fileURLToPath } from "node:url" ;
9- import { commercialLabel , esc , PERSPECTIVE_LABELS , verifiedAge } from "./lib/shared.mjs" ;
9+ import { commercialLabel , esc , PERSPECTIVE_LABELS , unquoteScalar , verifiedAge } from "./lib/shared.mjs" ;
1010import { entryPageHtml } from "./lib/entry-page.mjs" ;
1111import { LinkError , makeLinkResolver } from "./lib/links.mjs" ;
1212import { llmsFullTxt , llmsTxt } from "./lib/llms.mjs" ;
@@ -38,7 +38,7 @@ function parseScalar(raw) {
3838 ( v . startsWith ( '"' ) && v . endsWith ( '"' ) ) ||
3939 ( v . startsWith ( "'" ) && v . endsWith ( "'" ) )
4040 ) {
41- return v . slice ( 1 , - 1 ) ;
41+ return unquoteScalar ( v ) ;
4242 }
4343 if ( v . startsWith ( "[" ) && v . endsWith ( "]" ) ) {
4444 const inner = v . slice ( 1 , - 1 ) . trim ( ) ;
@@ -382,16 +382,22 @@ function copyDir(src, dest) {
382382 }
383383}
384384
385- /** Writes dist/entry/<id>/index.html for every entry. */
386- function writeEntryPages ( { entries, bodies, config, stats, stamp, hasCard, now } ) {
387- const errors = [ ] ;
388- const written = [ ] ;
385+ /** Returns entry => link resolver for links in that entry's body. */
386+ function linkResolvers ( entries , config ) {
389387 const idByPath = new Map ( entries . map ( ( e ) => [ e . path , e . id ] ) ) ;
390388 const kindOf = ( repoPath ) => {
391389 const full = path . join ( ROOT , repoPath ) ;
392390 if ( ! fs . existsSync ( full ) ) return null ;
393391 return fs . statSync ( full ) . isDirectory ( ) ? "dir" : "file" ;
394392 } ;
393+ return ( entry ) => makeLinkResolver ( { entryPath : entry . path , idByPath, repo : config . site . repo , kindOf } ) ;
394+ }
395+
396+ /** Writes dist/entry/<id>/index.html for every entry. */
397+ function writeEntryPages ( { entries, bodies, config, stats, stamp, hasCard, now } ) {
398+ const errors = [ ] ;
399+ const written = [ ] ;
400+ const resolverFor = linkResolvers ( entries , config ) ;
395401 // Prev/next follow the homepage's default order: category, then name.
396402 const visible = entries . filter ( ( e ) => e . status !== "deprecated" ) ;
397403 const neighbours = new Map ( ) ;
@@ -403,7 +409,7 @@ function writeEntryPages({ entries, bodies, config, stats, stamp, hasCard, now }
403409 const body = bodies . get ( entry . id ) || "" ;
404410 const file = `${ entry . path } (body)` ;
405411 try {
406- const resolveLink = makeLinkResolver ( { entryPath : entry . path , idByPath , repo : config . site . repo , kindOf } ) ;
412+ const resolveLink = resolverFor ( entry ) ;
407413 const { lead, rest, restFirstLine } = splitEntryBody ( body ) ;
408414 const leadHtml = renderBlocks ( lead , { file, resolveLink } ) ;
409415 const restHtml = renderBlocks ( rest , { file, resolveLink, firstLine : restFirstLine } ) ;
@@ -530,11 +536,6 @@ function main() {
530536 fs . writeFileSync ( path . join ( DIST , "sitemap.xml" ) , sitemapXml ( config . site , visible ) ) ;
531537 fs . writeFileSync ( path . join ( DIST , "robots.txt" ) , robotsTxt ( config . site ) ) ;
532538 fs . writeFileSync ( path . join ( DIST , "404.html" ) , notFoundHtml ( config . site ) ) ;
533- fs . writeFileSync ( path . join ( DIST , "llms.txt" ) , llmsTxt ( { entries, site : config . site , categories : config . categories } ) ) ;
534- fs . writeFileSync (
535- path . join ( DIST , "llms-full.txt" ) ,
536- llmsFullTxt ( { entries, site : config . site , categories : config . categories , bodies } )
537- ) ;
538539
539540 const pages = writeEntryPages ( { entries, bodies, config, stats, stamp, hasCard, now } ) ;
540541 const pageErrors = [ ...pages . errors , ...checkPages ( [ "index.html" , ...pages . written ] ) ] ;
@@ -544,6 +545,20 @@ function main() {
544545 process . exit ( 1 ) ;
545546 }
546547
548+ // After the page gate: every body link has resolved by now, so the llms
549+ // files cannot hit a link error of their own.
550+ fs . writeFileSync ( path . join ( DIST , "llms.txt" ) , llmsTxt ( { entries, site : config . site , categories : config . categories } ) ) ;
551+ fs . writeFileSync (
552+ path . join ( DIST , "llms-full.txt" ) ,
553+ llmsFullTxt ( {
554+ entries,
555+ site : config . site ,
556+ categories : config . categories ,
557+ bodies,
558+ resolverFor : linkResolvers ( entries , config ) ,
559+ } )
560+ ) ;
561+
547562 console . log (
548563 `Built ${ entries . length } entries → site/dist (${ stats . active } active, ${ stats . commercialOk } commercial-ok, ${ stats . commercialVaries } per-file)`
549564 ) ;
0 commit comments