Skip to content

Commit fd55e85

Browse files
committed
dehydrate code
1 parent 63f6338 commit fd55e85

File tree

11 files changed

+118
-267
lines changed

11 files changed

+118
-267
lines changed

package-lock.json

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

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@
7979
"remark-stringify": "^11.0.0",
8080
"semver": "^7.7.1",
8181
"shiki": "^3.4.2",
82-
"sval": "^0.6.7",
8382
"tailwindcss": "^4.1.8",
8483
"unified": "^11.0.5",
8584
"unist-builder": "^4.0.0",

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import styles from '@node-core/ui-components/Containers/NavBar/index.module.css'
55
import GitHubIcon from '@node-core/ui-components/Icons/Social/GitHub';
66

77
import { useTheme } from '../hooks/useTheme.mjs';
8-
import SearchBox from './SearchBox';
98

109
const MDXNavBar = () => {
1110
const [theme, toggleTheme] = useTheme();
@@ -16,7 +15,6 @@ const MDXNavBar = () => {
1615
sidebarItemTogglerAriaLabel="Toggle navigation menu"
1716
navItems={[]}
1817
>
19-
<SearchBox />
2018
<ThemeToggle
2119
onClick={toggleTheme}
2220
aria-label={`Switch to ${theme === 'light' ? 'dark' : 'light'} theme`}

src/generators/web/client/components/SearchBox/constants.mjs

Lines changed: 0 additions & 99 deletions
This file was deleted.

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

Lines changed: 0 additions & 66 deletions
This file was deleted.

src/generators/web/client/components/SearchBox/utils.mjs

Lines changed: 0 additions & 29 deletions
This file was deleted.

src/generators/web/index.mjs

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,102 @@
11
import { readFile, writeFile } from 'node:fs/promises';
2+
import { createRequire } from 'node:module';
23
import { join } from 'node:path';
34

4-
import { generate } from '@babel/generator';
55
import { estreeToBabel } from 'estree-to-babel';
66
import Mustache from 'mustache';
77

8+
import { ESBUILD_RESOLVE_DIR } from './constants.mjs';
89
import createASTBuilder from './utils/build.mjs';
910
import bundleCode from './utils/bundle.mjs';
1011

1112
/**
12-
* This generator generates a JavaScript / HTML / CSS bundle from the input JSX AST
13-
*
14-
* @typedef {Array<ApiDocMetadataEntry>} Input
15-
*
16-
* @type {GeneratorMetadata<Input, string>}
13+
* Executes server-side code in a safe, isolated context
14+
* @param {string} serverCode - The server code to execute
15+
* @param {Function} require - Node.js require function for dependencies
16+
* @returns {Promise<string>} The rendered HTML output
17+
*/
18+
async function executeServerCode(serverCode, require) {
19+
// Bundle the server code for execution
20+
const { js: bundledServer } = await bundleCode(serverCode, true);
21+
22+
// Create a safe execution context that returns the rendered content
23+
const executedFunction = new Function(
24+
'require',
25+
`
26+
let code;
27+
${bundledServer}
28+
return code;
29+
`
30+
);
31+
32+
return executedFunction(require);
33+
}
34+
35+
/**
36+
* Web bundle generator - converts JSX AST entries into HTML/CSS/JS bundles
37+
* Generates static HTML files with embedded JavaScript and CSS
1738
*/
1839
export default {
1940
name: 'web',
2041
version: '1.0.0',
21-
description:
22-
'Generates a JavaScript / HTML / CSS bundle from the input JSX AST',
42+
description: 'Generates HTML/CSS/JS bundles from JSX AST entries',
2343
dependsOn: 'jsx-ast',
2444

2545
/**
26-
* Generates a JavaScript / HTML / CSS bundle
27-
*
28-
* @param {import('../jsx-ast/utils/buildContent.mjs').JSXContent[]} entries
29-
* @param {Partial<GeneratorOptions>} options
46+
* Main generation function - processes JSX entries into web bundles
47+
* @param {Array} entries - JSX content entries to process
48+
* @param {Object} options - Generation options
49+
* @param {string} options.output - Output directory path
50+
* @returns {Promise<string[]>} Array of rendered HTML strings
3051
*/
3152
async generate(entries, { output }) {
53+
// Load the HTML template
3254
const template = await readFile(
3355
new URL('template.html', import.meta.url),
3456
'utf-8'
3557
);
3658

37-
const { buildClientProgram } = createASTBuilder();
59+
// Set up AST builders for server and client code
60+
const { buildServerProgram, buildClientProgram } = createASTBuilder();
61+
const require = createRequire(ESBUILD_RESOLVE_DIR);
3862

39-
let css;
63+
let css; // Will store CSS from the first bundle
4064

65+
// Process each entry in parallel
4166
const bundles = await Promise.all(
4267
entries.map(async entry => {
68+
// Convert JSX AST to Babel AST
4369
const { program } = estreeToBabel(entry);
44-
const clientCode = generate(buildClientProgram(program)).code;
4570

46-
const bundled = await bundleCode(clientCode);
71+
// Generate and execute server-side code for SSR
72+
const serverCode = buildServerProgram(program);
73+
const serverRenderedHTML = await executeServerCode(serverCode, require);
74+
75+
// Generate and bundle client-side code
76+
const clientCode = buildClientProgram(program);
77+
const clientBundle = await bundleCode(clientCode);
4778

48-
// Extract CSS from first bundle only
49-
css ??= bundled.css;
79+
// Extract CSS only from the first bundle to avoid duplicates
80+
css ??= clientBundle.css;
5081

51-
// TODO: Remove mustache
52-
const rendered = Mustache.render(template, {
82+
// Render the final HTML using the template
83+
const finalHTML = Mustache.render(template, {
5384
title: entry.data.heading.data.name,
54-
javascript: bundled.js,
85+
javascript: clientBundle.js,
86+
dehydrated: serverRenderedHTML,
5587
});
5688

89+
// Write individual HTML file if output directory is specified
5790
if (output) {
58-
await writeFile(join(output, `${entry.data.api}.html`), rendered);
91+
const filename = `${entry.data.api}.html`;
92+
await writeFile(join(output, filename), finalHTML);
5993
}
6094

61-
return rendered;
95+
return finalHTML;
6296
})
6397
);
6498

99+
// Write shared CSS file if we have CSS and an output directory
65100
if (output && css) {
66101
await writeFile(join(output, 'styles.css'), css);
67102
}

src/generators/web/template.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<link rel="stylesheet" href="styles.css" />
66
</head>
77
<body>
8-
<div id="root">{{{htmlContent}}}</div>
8+
<div id="root">{{{dehydrated}}}</div>
99
<script>{{{javascript}}}</script>
1010
</body>
1111
</html>

0 commit comments

Comments
 (0)