Skip to content

Commit 7d9abc6

Browse files
committed
feat(web): add all.html generation
1 parent 05f0e64 commit 7d9abc6

7 files changed

Lines changed: 126 additions & 38 deletions

File tree

package-lock.json

Lines changed: 2 additions & 36 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/generators/index.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import metadata from './metadata/index.mjs';
1616
import oramaDb from './orama-db/index.mjs';
1717
import sitemap from './sitemap/index.mjs';
1818
import web from './web/index.mjs';
19+
import webAll from './web-all/index.mjs';
1920

2021
export const publicGenerators = {
2122
'json-simple': jsonSimple,
@@ -30,6 +31,7 @@ export const publicGenerators = {
3031
'llms-txt': llmsTxt,
3132
sitemap,
3233
web,
34+
'web-all': webAll,
3335
};
3436

3537
// These ones are special since they don't produce standard output,

src/generators/web-all/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
## `web-all` Generator
2+
3+
The `web-all` generator creates a single `all.html` file containing all API documentation modules rendered through the `web` generator pipeline. This is the modern equivalent of `legacy-html-all` for the new web tooling.
4+
5+
It is intended for offline browsing and for environments where JavaScript is unavailable: the in-page searchbar shipped with `web` requires JS, so a single all-in-one page makes browser-native text search (`Ctrl`+`F`) usable across the full documentation set.
6+
7+
### Configuring
8+
9+
The `web-all` generator accepts the following configuration options:
10+
11+
| Name | Type | Default | Description |
12+
| -------------- | -------- | -------------------- | ---------------------------------------------- |
13+
| `output` | `string` | - | The directory where `all.html` will be written |
14+
| `templatePath` | `string` | Inherited from `web` | Path to the HTML template file |
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
'use strict';
2+
3+
import { readFile } from 'node:fs/promises';
4+
import { join } from 'node:path';
5+
6+
import getConfig from '../../utils/configuration/index.mjs';
7+
import { writeFile } from '../../utils/file.mjs';
8+
import buildContent from '../jsx-ast/utils/buildContent.mjs';
9+
import { processJSXEntries } from '../web/utils/processing.mjs';
10+
11+
/**
12+
* Generates a single `all.html` file containing every API documentation
13+
* module rendered through the `web` generator pipeline.
14+
*
15+
* @type {import('./types').Generator['generate']}
16+
*/
17+
export async function generate(input) {
18+
const config = getConfig('web-all');
19+
20+
const template = await readFile(config.templatePath, 'utf-8');
21+
22+
// Match `legacy-html-all`: skip the synthetic `index` entries.
23+
const entries = input.filter(entry => entry.api !== 'index');
24+
25+
// Build a single combined JSXContent that wraps every entry's content in
26+
// one Layout component, mirroring how `jsx-ast` produces per-module pages.
27+
const combined = await buildContent(entries, {
28+
api: 'all',
29+
path: '/all',
30+
basename: 'all.html',
31+
heading: {
32+
type: 'heading',
33+
depth: 1,
34+
children: [{ type: 'text', value: 'All' }],
35+
data: { name: 'All', text: 'All', slug: 'all' },
36+
},
37+
});
38+
39+
// Pass the original metadata entries as the sidebar source so `all.html`
40+
// exposes the same navigation as the per-module pages produced by `web`.
41+
const sidebarEntries = entries.map(entry => ({ data: entry }));
42+
43+
const { results, css, chunks } = await processJSXEntries(
44+
[combined],
45+
template,
46+
sidebarEntries
47+
);
48+
49+
if (config.output) {
50+
for (const { html, path } of results) {
51+
await writeFile(join(config.output, `${path}.html`), html, 'utf-8');
52+
}
53+
54+
for (const chunk of chunks) {
55+
await writeFile(join(config.output, chunk.fileName), chunk.code, 'utf-8');
56+
}
57+
58+
await writeFile(join(config.output, 'styles.css'), css, 'utf-8');
59+
}
60+
61+
return { html: results[0].html.toString(), css };
62+
}

src/generators/web-all/index.mjs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
'use strict';
2+
3+
import { createLazyGenerator } from '../../utils/generators.mjs';
4+
import web from '../web/index.mjs';
5+
6+
/**
7+
* Web "all" generator - produces a single `all.html` page that contains every
8+
* API documentation module rendered into one combined web bundle.
9+
*
10+
* Mirrors the role of `legacy-html-all` for the new `web` generator. Useful
11+
* for offline browsing and for reading the full documentation in environments
12+
* where JavaScript is unavailable, since the `web` searchbar requires JS.
13+
*
14+
* @type {import('./types').Generator}
15+
*/
16+
export default createLazyGenerator({
17+
name: 'web-all',
18+
19+
version: '1.0.0',
20+
21+
description:
22+
'Generates the `all.html` file from the `web` generator, which includes all the modules in one single file',
23+
24+
dependsOn: 'metadata',
25+
26+
defaultConfiguration: {
27+
templatePath: web.defaultConfiguration.templatePath,
28+
},
29+
});

src/generators/web-all/types.d.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import type { MetadataEntry } from '../metadata/types';
2+
3+
export type Configuration = {
4+
templatePath: string;
5+
};
6+
7+
export type Generator = GeneratorMetadata<
8+
Configuration,
9+
Generate<Array<MetadataEntry>, Promise<{ html: string; css: string }>>
10+
>;

src/generators/web/utils/processing.mjs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,18 @@ async function executeServerCode(serverCodeMap, requireFn, virtualImports) {
9696
*
9797
* @param {Array<import('../../jsx-ast/utils/buildContent.mjs').JSXContent>} entries - The JSX AST entries to process.
9898
* @param {string} template - The HTML template string for the output pages.
99+
* @param {Array<{ data: import('../../metadata/types').MetadataEntry }>} [sidebarEntries] - Entries used to build the sidebar page list. Defaults to `entries`. Pass the full set when rendering a subset (e.g. the `all` page) so the sidebar still links to every module.
99100
*/
100-
export async function processJSXEntries(entries, template) {
101+
export async function processJSXEntries(
102+
entries,
103+
template,
104+
sidebarEntries = entries
105+
) {
101106
const config = getConfig('web');
102107
const astBuilders = createASTBuilder();
103108
const requireFn = createRequire(import.meta.url);
104109
const virtualImports = {
105-
'#theme/config': createConfigSource(entries),
110+
'#theme/config': createConfigSource(sidebarEntries),
106111
...config.virtualImports,
107112
};
108113
// Step 1: Convert JSX AST to JavaScript

0 commit comments

Comments
 (0)