release: WRNexusJS 0.3.5

This commit is contained in:
2026-07-24 12:46:44 +05:30
parent 44ba847210
commit c81dedff17
2114 changed files with 65790 additions and 150559 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ssr",
"version": "0.3.4",
"version": "0.3.5",
"type": "module",
"main": "src/index.ts",
"exports": {
+25
View File
@@ -31,6 +31,12 @@ export interface RenderOptions {
extraBody?: string;
/** Attributes for the `<html>` element, e.g. ` data-theme="dark"` (trusted). */
htmlAttrs?: string;
/**
* Optional application-authored full document shell. It must contain
* `<html>`, `<head>`, and `<body>`. Framework metadata, assets, and scripts
* are merged into it instead of wrapping the rendered body again.
*/
documentTemplate?: string;
}
/**
@@ -59,6 +65,25 @@ export function renderDocument(opts: RenderOptions): string {
? (opts.htmlAttrs ?? "")
: `${opts.htmlAttrs ?? ""} lang="en"`;
if (opts.documentTemplate) {
let document = opts.documentTemplate.trim();
if (!/^<!doctype\s+html>/i.test(document)) document = `<!doctype html>\n${document}`;
document = document.replace(/<html([^>]*)>/i, (_match, existing: string) => {
const language = /(?:^|\s)lang\s*=/.test(`${existing}${opts.htmlAttrs ?? ""}`)
? ""
: ' lang="en"';
return `<html${existing}${opts.htmlAttrs ?? ""}${language}>`;
});
const headContent = `
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
<title>${title}</title>${seoTags}${preloadTags}${extraHead}`;
document = document.replace(/<head([^>]*)>/i, `<head$1>${headContent}`);
document = document.replace(/<\/body>/i, `${scriptTags}${extraBody}\n </body>`);
return `${document}\n`;
}
return `<!doctype html>
<html${htmlAttrs}>
<head>
+18
View File
@@ -36,6 +36,24 @@ test("always emits a document language and preserves an explicit language", () =
expect(explicit).not.toContain('lang="en"');
});
test("merges framework head and scripts into an application document template", () => {
const html = renderDocument({
meta: { title: "Document layout" },
body: "",
htmlAttrs: ' data-theme="dark"',
scripts: ["/page.js"],
documentTemplate:
'<html data-ui-font="system"><head><meta name="custom" content="yes" /></head><body><div id="app">Page</div></body></html>',
});
expect(html).toStartWith("<!doctype html>");
expect(html).toContain('<html data-ui-font="system" data-theme="dark" lang="en">');
expect(html).toContain("<title>Document layout</title>");
expect(html).toContain('<meta name="custom" content="yes" />');
expect(html).toContain('<script type="module" src="/page.js"></script>');
expect(html.match(/<html/g)).toHaveLength(1);
expect(html.match(/<body/g)).toHaveLength(1);
});
test("streams async body chunks inside the document shell", async () => {
async function* body() {
yield "<h1>Shell</h1>";