UNPKG

rvx

Version:

A signal based rendering library

62 lines (58 loc) 1.78 kB
import { ASYNC, AsyncContext } from "../async/async-context.js"; import { Context } from "../core/context.js"; import { ENV } from "../core/env.js"; import { capture } from "../core/lifecycle.js"; import type { Component } from "../core/types.js"; import { render, View } from "../core/view.js"; import { Node, WINDOW } from "./model.js"; function renderDetachedView(view: View) { const { first, last } = view; if (!(first instanceof Node)) { throw new Error("root is not an rvx dom node"); } if (first === last) { return first.outerHTML; } else { return first.parentNode!.outerHTML; } } /** * Render a component to HTML using rvx dom. */ export function renderToString(component: Component): string; export function renderToString<P>(component: Component<P>, props: P): string; export function renderToString<P>(component: Component<P>, props?: P): string { let html: string; capture(() => { ENV.inject(WINDOW, () => { const view = render(component(props!)); html = renderDetachedView(view); }); })(); return html!; } /** * Render a component to HTML using rvx dom. * * This injects a new {@link AsyncContext} to wait for rendering to complete. */ export async function renderToStringAsync(component: Component): Promise<string>; export async function renderToStringAsync<P>(component: Component<P>, props: P): Promise<string>; export async function renderToStringAsync<P>(component: Component<P>, props?: P): Promise<string> { const asyncCtx = new AsyncContext(); let view: View; const dispose = capture(() => { Context.inject([ ENV.with(WINDOW), ASYNC.with(asyncCtx), ], () => { view = render(component(props!)); }); }); try { await asyncCtx.complete(); return renderDetachedView(view!); } finally { dispose(); } }