release: WRNexusJS 0.8.0
This commit is contained in:
@@ -23,6 +23,46 @@ export interface ScriptAsset {
|
||||
|
||||
export type RenderScript = string | ScriptAsset;
|
||||
|
||||
export interface PartialPrerenderResult {
|
||||
shell: string;
|
||||
regions: Array<{ id: string; html: string }>;
|
||||
}
|
||||
|
||||
/** Extract compiler-emitted dynamic regions into a cacheable static shell. */
|
||||
export function partialPrerender(html: string, startIndex = 0): PartialPrerenderResult {
|
||||
const regions: PartialPrerenderResult["regions"] = [];
|
||||
const shell = html.replace(
|
||||
/<wrn-dynamic-region\b[^>]*>([\s\S]*?)<\/wrn-dynamic-region>/gi,
|
||||
(_whole, content: string) => {
|
||||
const id = `wrn-region-${startIndex + regions.length}`;
|
||||
regions.push({ id, html: content });
|
||||
return `<template data-wrn-dynamic-placeholder="${id}"></template>`;
|
||||
},
|
||||
);
|
||||
return { shell, regions };
|
||||
}
|
||||
|
||||
/** Stream the static shell first, followed by inert region templates for client insertion. */
|
||||
export function streamPartialDocument(
|
||||
result: PartialPrerenderResult,
|
||||
nonce?: string,
|
||||
): ReadableStream<Uint8Array> {
|
||||
const encoder = new TextEncoder();
|
||||
return new ReadableStream({
|
||||
start(controller) {
|
||||
controller.enqueue(encoder.encode(result.shell));
|
||||
for (const region of result.regions) {
|
||||
controller.enqueue(
|
||||
encoder.encode(
|
||||
`<template data-wrn-dynamic-content="${region.id}">${region.html}</template><script${nonce ? ` nonce="${escapeHtml(nonce)}"` : ""}>(function(){var p=document.querySelector('template[data-wrn-dynamic-placeholder="${region.id}"]');var c=document.querySelector('template[data-wrn-dynamic-content="${region.id}"]');if(p&&c){p.replaceWith(c.content);c.remove()}})()</script>`,
|
||||
),
|
||||
);
|
||||
}
|
||||
controller.close();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export interface RenderOptions {
|
||||
/** Page metadata for the document head. */
|
||||
meta: PageMeta;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { serializeForHtml } from "@wrnexus/security";
|
||||
import { escapeHtml } from "@wrnexus/core";
|
||||
import { createRequestStoreContainer } from "@wrnexus/store/server";
|
||||
import type { StoreContainer } from "@wrnexus/store";
|
||||
|
||||
@@ -21,5 +22,5 @@ export async function disposeRequestStores(request: object): Promise<void> {
|
||||
|
||||
export function renderStoreHydration(container: StoreContainer, nonce?: string): string {
|
||||
const json = serializeForHtml(container.serialize());
|
||||
return `<script type="application/json" data-wrnexus-store-hydration${nonce ? ` nonce="${nonce}"` : ""}>${json}</script>`;
|
||||
return `<script type="application/json" data-wrnexus-store-hydration${nonce ? ` nonce="${escapeHtml(nonce)}"` : ""}>${json}</script>`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user