import * as ssr from "./ssr.ts"; // @ts-ignore no types :( import * as marko from "marko/debug/html"; // @ts-ignore no types :( export * from "marko/debug/html"; export const createTemplate = (templateId: string, renderer) => { const { render } = marko.createTemplate(templateId, renderer); function wrap(props: Record, n: number) { // Marko components const cloverAsyncMarker = { isAsync: false }; let r: ssr.Render | undefined = undefined; try { r = ssr.getCurrentRender(); } catch {} // Support using Marko outside of Clover SSR if (r) { const markoResult = render.call(renderer, { ...props, $global: { clover: r, cloverAsyncMarker }, }); if (cloverAsyncMarker.isAsync) { return markoResult.then(ssr.html); } const rr = markoResult.toString(); return ssr.html(rr); } else { return renderer(props, n); } } wrap.render = render; wrap.unwrapped = renderer; return wrap; }; export const dynamicTag = ( scopeId, accessor, tag, inputOrArgs, content, inputIsArgs, serializeReason, ) => { if (typeof tag === "function") { clover: { const unwrapped = tag.unwrapped; if (unwrapped) { tag = unwrapped; break clover; } let r: ssr.Render; try { r = ssr.getCurrentRender(); if (!r) throw 0; } catch { r = marko.$global().clover as ssr.Render; } if (!r) throw new Error("No Clover Render Active"); const subRender = ssr.initRender(r.async !== -1, r.user); const resolved = ssr.resolveNode(subRender, [ ssr.kElement, tag, inputOrArgs, ]); if (subRender.async > 0) { const marker = marko.$global().cloverAsyncMarker; marker.isAsync = true; // Wait for async work to finish const { resolve, reject, promise } = Promise.withResolvers(); subRender.asyncDone = () => { const rejections = subRender.rejections; if (!rejections) return resolve(ssr.renderNodeOrUndefined(resolved)); (r.rejections ??= []).push(...rejections); return reject(new Error("Render had errors")); }; marko.fork( scopeId, accessor, promise, (string: string) => marko.write(string), 0, ); } else { marko.write(ssr.renderNodeOrUndefined(resolved)); } return; } } return marko.dynamicTag( scopeId, accessor, tag, inputOrArgs, content, inputIsArgs, serializeReason, ); }; export function fork(scopeId, accessor, promise, callback, serializeMarker) { const marker = marko.$global().cloverAsyncMarker; marker.isAsync = true; marko.fork(scopeId, accessor, promise, callback, serializeMarker); }