Skip to content

Commit 375326b

Browse files
authored
feat(web): more customizable templates (#747)
1 parent 63c24b9 commit 375326b

16 files changed

Lines changed: 149 additions & 141 deletions

File tree

package-lock.json

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

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@node-core/doc-kit",
33
"type": "module",
4-
"version": "1.3.1",
4+
"version": "1.3.2",
55
"repository": {
66
"type": "git",
77
"url": "git+https://github.com/nodejs/doc-kit.git"

src/generators/jsx-ast/utils/buildContent.mjs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { SKIP, visit } from 'unist-util-visit';
99
import { createJSXElement } from './ast.mjs';
1010
import { extractHeadings, extractTextContent } from './buildBarProps.mjs';
1111
import { enforceArray } from '../../../utils/array.mjs';
12-
import { extractPrimitives } from '../../../utils/misc.mjs';
12+
import { omitKeys } from '../../../utils/misc.mjs';
1313
import { JSX_IMPORTS } from '../../web/constants.mjs';
1414
import {
1515
STABILITY_LEVELS,
@@ -296,7 +296,13 @@ export const createDocumentLayout = (entries, metadata) =>
296296
* @returns {Promise<JSXContent>}
297297
*/
298298
const buildContent = async (metadataEntries, head) => {
299-
const metadata = extractPrimitives(head);
299+
// The metadata is the heading without the node children
300+
const metadata = omitKeys(head, [
301+
'content',
302+
'heading',
303+
'stability',
304+
'changes',
305+
]);
300306

301307
// Create root document AST with all layout components and processed content
302308
const root = createDocumentLayout(metadataEntries, metadata);

src/generators/web/README.md

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,16 @@ The `web` generator transforms JSX AST entries into complete web bundles, produc
66

77
The `web` generator accepts the following configuration options:
88

9-
| Name | Type | Default | Description |
10-
| -------------- | -------- | --------------------------------------------- | --------------------------------------------------------------------- |
11-
| `output` | `string` | - | The directory where HTML, JavaScript, and CSS files will be written |
12-
| `templatePath` | `string` | `'template.html'` | Path to the HTML template file |
13-
| `editURL` | `string` | `'${GITHUB_EDIT_URL}/doc/api{path}.md'` | URL template for "edit this page" links |
14-
| `pageURL` | `string` | `'{baseURL}/latest-{version}/api{path}.html'` | URL template for documentation page links |
15-
| `imports` | `object` | See below | Object mapping `#theme/` aliases to component paths for customization |
9+
| Name | Type | Default | Description |
10+
| ---------------- | -------- | --------------------------------------------- | --------------------------------------------------------------------- |
11+
| `output` | `string` | - | The directory where HTML, JavaScript, and CSS files will be written |
12+
| `templatePath` | `string` | `'template.html'` | Path to the HTML template file |
13+
| `project` | `string` | `'Node.js'` | Project name used in page titles and the version selector |
14+
| `title` | `string` | `'{project} v{version} Documentation'` | Title template for HTML pages (supports `{project}`, `{version}`) |
15+
| `editURL` | `string` | `'${GITHUB_EDIT_URL}/doc/api{path}.md'` | URL template for "edit this page" links |
16+
| `pageURL` | `string` | `'{baseURL}/latest-{version}/api{path}.html'` | URL template for documentation page links |
17+
| `imports` | `object` | See below | Object mapping `#theme/` aliases to component paths for customization |
18+
| `virtualImports` | `object` | `{}` | Additional virtual module mappings merged into the build |
1619

1720
#### Default `imports`
1821

@@ -42,14 +45,16 @@ export default {
4245
The `web` generator provides a `#theme/config` virtual module that exposes pre-computed configuration as named exports. Any component (including custom overrides) can import the values it needs, and tree-shaking removes the rest.
4346

4447
```js
45-
import { title, repository, editURL } from '#theme/config';
48+
import { project, repository, editURL } from '#theme/config';
4649
```
4750

4851
#### Available exports
4952

53+
All scalar (non-object) configuration values are automatically exported. The defaults include:
54+
5055
| Export | Type | Description |
5156
| ------------------------ | ------------------------------ | --------------------------------------------------------------------------------------------------- |
52-
| `title` | `string` | Site title (e.g. `'Node.js'`) |
57+
| `project` | `string` | Project name (e.g. `'Node.js'`) |
5358
| `repository` | `string` | GitHub repository in `owner/repo` format |
5459
| `version` | `string` | Current version label (e.g. `'v22.x'`) |
5560
| `versions` | `Array<{ url, label, major }>` | Pre-computed version entries with labels and URL templates (only `{path}` remains for per-page use) |

src/generators/web/index.mjs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ export default createLazyGenerator({
2929

3030
defaultConfiguration: {
3131
templatePath: join(import.meta.dirname, 'template.html'),
32-
title: 'Node.js',
32+
project: 'Node.js',
33+
title: '{project} v{version} Documentation',
3334
editURL: `${GITHUB_EDIT_URL}/doc/api{path}.md`,
3435
pageURL: '{baseURL}/latest-{version}/api{path}.html',
3536
imports: {
@@ -40,5 +41,6 @@ export default createLazyGenerator({
4041
'#theme/Footer': join(import.meta.dirname, './ui/components/NoOp'),
4142
'#theme/Layout': join(import.meta.dirname, './ui/components/Layout'),
4243
},
44+
virtualImports: {},
4345
},
4446
});

src/generators/web/template.html

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
<meta charset="UTF-8" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
77
<link rel="icon" href="https://nodejs.org/static/images/favicons/favicon.png"/>
8-
<title>{{title}}</title>
8+
<title>{title}</title>
99
<meta name="description" content="Node.js® is a free, open-source, cross-platform JavaScript runtime environment that lets developers create servers, web apps, command line tools and scripts.">
10-
<link rel="stylesheet" href="{{root}}styles.css" />
11-
<meta property="og:title" content="{{ogTitle}}">
10+
<link rel="stylesheet" href="{root}styles.css" />
11+
<meta property="og:title" content="{title}">
1212
<meta property="og:description" content="Node.js® is a free, open-source, cross-platform JavaScript runtime environment that lets developers create servers, web apps, command line tools and scripts.">
1313
<meta property="og:image" content="https://nodejs.org/en/next-data/og/announcement/Node.js%20%E2%80%94%20Run%20JavaScript%20Everywhere" />
1414
<meta property="og:type" content="website">
@@ -20,12 +20,12 @@
2020

2121
<!-- Apply theme before paint to avoid Flash of Unstyled Content -->
2222
<script>document.documentElement.setAttribute("data-theme", document.documentElement.style.colorScheme = localStorage.getItem("theme") || (matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"));</script>
23-
<script type="importmap">{{importMap}}</script>
24-
<script type="speculationrules">{{speculationRules}}</script>
23+
<script type="importmap">{importMap}</script>
24+
<script type="speculationrules">{speculationRules}</script>
2525
</head>
2626

2727
<body>
28-
<div id="root">{{dehydrated}}</div>
29-
<script type="module" src="{{root}}{{entrypoint}}"></script>
28+
<div id="root">{dehydrated}</div>
29+
<script type="module" src="{root}{entrypoint}"></script>
3030
</body>
3131
</html>

src/generators/web/types.d.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import type { JSXContent } from '../jsx-ast/utils/buildContent.mjs';
22

3+
export type Configuration = {
4+
templatePath: string;
5+
title: string;
6+
imports: Record<string, string>;
7+
virtualImports: Record<string, string>;
8+
};
9+
310
export type Generator = GeneratorMetadata<
4-
{
5-
templatePath: string;
6-
title: string;
7-
imports: Record<string, string>;
8-
},
11+
Configuration,
912
Generate<Array<JSXContent>, AsyncGenerator<{ html: string; css: string }>>
1013
>;

src/generators/web/ui/components/NavBar.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import GitHubIcon from '@node-core/ui-components/Icons/Social/GitHub';
66
import SearchBox from './SearchBox';
77
import { useTheme } from '../hooks/useTheme.mjs';
88

9-
import { title, repository } from '#theme/config';
9+
import { repository } from '#theme/config';
1010
import Logo from '#theme/Logo';
1111

1212
/**
@@ -28,7 +28,7 @@ export default ({ metadata }) => {
2828
/>
2929
<a
3030
href={`https://github.com/${repository}`}
31-
aria-label={`${title} GitHub`}
31+
aria-label={`View ${repository} on GitHub`}
3232
className={styles.ghIconWrapper}
3333
>
3434
<GitHubIcon />

src/generators/web/ui/components/SearchBox/index.jsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import SearchResults from '@node-core/ui-components/Common/Search/Results';
88
import SearchHit from '@node-core/ui-components/Common/Search/Results/Hit';
99

1010
import styles from './index.module.css';
11+
import { relative } from '../../../../../utils/url.mjs';
1112
import useOrama from '../../hooks/useOrama.mjs';
1213

1314
const SearchBox = ({ pathname }) => {
@@ -18,7 +19,14 @@ const SearchBox = ({ pathname }) => {
1819
<div className={styles.searchResultsContainer}>
1920
<SearchResults
2021
noResultsTitle="No results found for"
21-
onHit={hit => <SearchHit document={hit.document} />}
22+
onHit={hit => (
23+
<SearchHit
24+
document={{
25+
...hit.document,
26+
href: relative(hit.document.href, pathname),
27+
}}
28+
/>
29+
)}
2230
/>
2331
</div>
2432

src/generators/web/ui/components/SideBar/index.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import SideBar from '@node-core/ui-components/Containers/Sidebar';
44
import styles from './index.module.css';
55
import { relative } from '../../../../../utils/url.mjs';
66

7-
import { title, version, versions, pages } from '#theme/config';
7+
import { project, version, versions, pages } from '#theme/config';
88

99
/**
1010
* Extracts the major version number from a version string.
@@ -54,7 +54,7 @@ export default ({ metadata }) => {
5454
>
5555
<div>
5656
<Select
57-
label={`${title} version`}
57+
label={`${project} version`}
5858
values={compatibleVersions}
5959
inline={true}
6060
className={styles.select}

0 commit comments

Comments
 (0)