@@ -4,42 +4,78 @@ import { readFile } from 'node:fs/promises';
44import { join } from 'node:path' ;
55
66import { processJSXEntries } from './utils/processing.mjs' ;
7+ import { buildNotFoundPage } from './utils/synthetic/404.mjs' ;
8+ import { buildAllPage } from './utils/synthetic/all.mjs' ;
9+ import { buildIndexPage } from './utils/synthetic/index.mjs' ;
710import getConfig from '../../utils/configuration/index.mjs' ;
811import { writeFile } from '../../utils/file.mjs' ;
12+ import buildContent from '../jsx-ast/utils/buildContent.mjs' ;
913
1014/**
1115 * Main generation function that processes JSX AST entries into web bundles.
1216 *
17+ * Generates the regular per-module pages plus, when enabled by configuration,
18+ * the synthetic `all`, `index`, and `404` pages. Everything is bundled in a
19+ * single pass so shared component chunks and CSS are produced once.
20+ *
1321 * @type {import('./types').Generator['generate'] }
1422 */
1523export async function generate ( input ) {
1624 const config = getConfig ( 'web' ) ;
1725
1826 const template = await readFile ( config . templatePath , 'utf-8' ) ;
1927
20- // The `web-all` generator re-generates `index.html` with a stability
21- // overview, so skip the synthetic `index` entry here .
28+ // The synthetic `index` entry from Core is replaced by our own
29+ // `index.html` (with stability overview) when `generateIndexPage` is on .
2230 //
2331 // TODO(@avivkeller): Once this lands in core, remove the `index.html`
2432 // page from Core, then remove this check.
25- const entries = input . filter ( entry => entry . data . api !== 'index' ) ;
33+ const moduleEntries = input . filter ( entry => entry . data . api !== 'index' ) ;
34+
35+ // Reconstruct the flat metadata list from the per-module section entries
36+ // attached by `jsx-ast`. Used to build the synthetic `all` and `index`
37+ // pages without a separate `metadata` dependency.
38+ const synthDescriptors = [ ] ;
39+
40+ if ( config . generateAllPage || config . generateIndexPage ) {
41+ const metadata = moduleEntries . flatMap ( entry => entry . sectionEntries ) ;
42+
43+ if ( config . generateAllPage ) {
44+ synthDescriptors . push ( buildAllPage ( metadata ) ) ;
45+ }
46+ if ( config . generateIndexPage ) {
47+ synthDescriptors . push ( buildIndexPage ( metadata ) ) ;
48+ }
49+ }
50+
51+ if ( config . generateNotFoundPage ) {
52+ synthDescriptors . push ( buildNotFoundPage ( ) ) ;
53+ }
54+
55+ const syntheticEntries = await Promise . all (
56+ synthDescriptors . map ( ( { head, entries } ) => buildContent ( entries , head ) )
57+ ) ;
58+
59+ // Sidebar lists only the real module pages.
60+ const sidebarEntries = moduleEntries . map ( entry => ( { data : entry . data } ) ) ;
61+
62+ const allEntries = [ ...moduleEntries , ...syntheticEntries ] ;
2663
27- // Process all entries: convert JSX to HTML/CSS/JS
28- const { results, css, chunks } = await processJSXEntries ( entries , template ) ;
64+ const { results, css, chunks } = await processJSXEntries (
65+ allEntries ,
66+ template ,
67+ sidebarEntries
68+ ) ;
2969
30- // Process all entries together (required for code-split bundles)
3170 if ( config . output ) {
32- // Write HTML files
3371 for ( const { html, path } of results ) {
3472 await writeFile ( join ( config . output , `${ path } .html` ) , html , 'utf-8' ) ;
3573 }
3674
37- // Write code-split JavaScript chunks
3875 for ( const chunk of chunks ) {
3976 await writeFile ( join ( config . output , chunk . fileName ) , chunk . code , 'utf-8' ) ;
4077 }
4178
42- // Write CSS bundle
4379 await writeFile ( join ( config . output , 'styles.css' ) , css , 'utf-8' ) ;
4480 }
4581
0 commit comments