easy-jsx-html-engine
Version:
Dead simple HTML engine using JSX syntax.
61 lines • 2.44 kB
JavaScript
import { loaderScript, ResolvedTemplate as DefaultResolvedTemplate, } from "./suspense";
function noop() { }
export function renderToStream(body, options) {
const waitUntil = (typeof options === "object" ? options.waitUntil : options) ?? noop;
const ResolvedTemplate = (typeof options === "object" && options.ResolvedTemplate) ||
DefaultResolvedTemplate;
const rid = globalThis.SUSPENSE_ROOT.counter++;
const requestData = { children: [] };
SUSPENSE_ROOT.requests.set(rid, requestData);
if (typeof body === "function") {
try {
body = body(rid);
}
catch (error) {
// Avoids memory leaks by removing the request data
SUSPENSE_ROOT.requests.delete(rid);
throw error;
}
}
// No suspense was used, just return the HTML
if (!requestData || !requestData.children.length) {
SUSPENSE_ROOT.requests.delete(rid);
return Promise.resolve(body).then((elem) => elem.toHTML());
}
const { readable, writable } = new TransformStream();
waitUntil(sendToStream(writable, body, requestData, ResolvedTemplate).finally(() => {
// Removes the current state
SUSPENSE_ROOT.requests.delete(rid);
}));
return readable;
}
async function sendToStream(writable, layout, requestData, ResolvedTemplate) {
const w = writable.getWriter();
try {
const encoder = new TextEncoder();
await w.write(encoder.encode((await layout).toHTML()));
if (!requestData.children.length) {
return;
}
await w.write(encoder.encode(loaderScript));
let count = 0;
const children = [];
while (count < requestData.children.length || children.length) {
for (; count < requestData.children.length; count++) {
children.push([requestData.children[count], count]);
}
const [html, id] = await Promise.race(children.map(async ([e, i]) => [await e, i]));
await w.write(encoder.encode((await ResolvedTemplate({
id,
children: html,
})).toHTML()));
children.splice(children.findIndex(([, i]) => i === id), 1);
}
await w.write(encoder.encode("<script data-suspense>suspense.cleanup()</script>"));
}
finally {
await w.close();
w.releaseLock();
}
}
//# sourceMappingURL=stream-webapi.js.map