UNPKG

@web-widget/web-widget

Version:
200 lines (199 loc) 6.84 kB
import { getClientModuleId, getDisplayModuleId, unsafePropsToAttrs } from "./chunk-L7YKSBOA.js"; import { __forAwait, __objRest, __privateAdd, __privateGet, __privateSet, __spreadProps, __spreadValues } from "./chunk-PFFVE7GG.js"; // src/server.ts import { mergeMeta, rebaseMeta, renderMetaToString } from "@web-widget/helpers"; import { renderLifecycleCacheLayer, callSyncCacheProvider } from "@web-widget/lifecycle-cache/server"; var __FEATURE_INJECTING_STYLES__ = false; var showWebContainerWarning = true; async function readableStreamToString(readableStream) { let result = ""; const textDecoder = new TextDecoder(); try { for (var iter = __forAwait(readableStream), more, temp, error; more = !(temp = await iter.next()).done; more = false) { const chunk = temp.value; result += textDecoder.decode(chunk, { stream: true }); } } catch (temp) { error = [temp]; } finally { try { more && (temp = iter.return) && await temp.call(iter); } finally { if (error) throw error[0]; } } return result; } var getType = (obj) => Object.prototype.toString.call(obj).slice(8, -1); function unsafeAttrsToHtml(attrs) { return Object.entries(attrs).map( ([attrName, attrValue]) => `${attrName}${attrValue === "" ? "" : '="' + attrValue + '"'}` ).join(" "); } var _children, _clientImport, _loader, _options, _renderStage; var ServerWebWidgetRenderer = class { constructor(loader, _a) { __privateAdd(this, _children); __privateAdd(this, _clientImport); __privateAdd(this, _loader); __privateAdd(this, _options); __privateAdd(this, _renderStage); this.localName = "web-widget"; var _b = _a, { children = "", renderStage } = _b, options = __objRest(_b, ["children", "renderStage"]); if (children && options.renderTarget !== "shadow") { throw new Error( `Rendering content in a slot requires "options.renderTarget = 'shadow'".` ); } __privateSet(this, _children, children); __privateSet(this, _clientImport, getClientModuleId(loader, options)); __privateSet(this, _loader, loader); __privateSet(this, _options, options); __privateSet(this, _renderStage, renderStage); } get attributes() { const clientImport = __privateGet(this, _clientImport); const _a = __privateGet(this, _options), { data: contextdata, meta: contextmeta } = _a, options = __objRest(_a, ["data", "meta"]); const renderStage = __privateGet(this, _renderStage); if (renderStage === "server") { return unsafePropsToAttrs({ name: options.name }); } const attrs = unsafePropsToAttrs(__spreadProps(__spreadValues({}, options), { // base: options.base?.startsWith("file://") ? undefined : options.base, contextdata: JSON.stringify(contextdata), contextmeta: JSON.stringify(contextmeta), import: clientImport, recovering: renderStage !== "client" })); if (attrs.contextdata === "{}") { delete attrs.contextdata; } if (attrs.contextmeta === "{}") { delete attrs.contextmeta; } return attrs; } async renderInnerHTMLToString() { var _a, _b, _c, _d; const children = __privateGet(this, _children); const clientImport = __privateGet(this, _clientImport); const loader = __privateGet(this, _loader); const options = __privateGet(this, _options); const renderStage = __privateGet(this, _renderStage); let result = ""; if (renderStage === "client") { return result; } const module = await loader(); if (typeof module.render !== "function") { throw new TypeError( `The module does not export a "render" method: ${getDisplayModuleId( loader, options )}` ); } const meta = rebaseMeta( mergeMeta((_a = module.meta) != null ? _a : {}, (_b = options.meta) != null ? _b : {}), clientImport ); if ((_c = meta.script) == null ? void 0 : _c.length) { console.warn(`Script tags in meta will be ignored.`); } const styleLinks = meta.link ? meta.link.filter(({ rel }) => rel === "stylesheet") : []; const styles = meta.style || []; const hasStyle = styleLinks.length || styles.length; const context = { children: options.renderTarget === "light" ? children : void 0, data: options.data, meta, module }; const rawResult = await callSyncCacheProvider( () => module.render(context) ); if (getType(rawResult) === "ReadableStream") { result = await readableStreamToString(rawResult); } else if (typeof rawResult === "string") { result = rawResult; } else { throw new TypeError( `Render results in an unknown format: ${getDisplayModuleId( loader, options )}` ); } if (hasStyle && __FEATURE_INJECTING_STYLES__) { result += renderMetaToString({ link: styleLinks, style: styles }); result += `<web-widget.body>${result}</web-widget.body>`; } if (options.renderTarget === "shadow") { const shimCode = `(${(a, c = document.currentScript, p = c && c.parentElement, _ = c && c.remove()) => a && p && a(p)})(window.attachShadowRoots)`.replace(/\s/g, ""); result += `<template shadowrootmode="open">${result}</template>`; result += `<script>${shimCode}</script>`; result += children; } try { result += renderLifecycleCacheLayer(); } catch (error) { if ((_d = error == null ? void 0 : error.message) == null ? void 0 : _d.includes("Context is not available")) { if (isWebContainer()) { if (showWebContainerWarning) { console.warn( `WARN: LifecycleCache cannot be serialized. WARN: This may be because the WebContainer environment does not support AsyncLocalStorage. WARN: Please see https://github.com/stackblitz/webcontainer-core/issues/1169` ); showWebContainerWarning = false; } } else { } } else { throw error; } } return result; } async renderOuterHTMLToString() { const tag = this.localName; const attributes = this.attributes; const children = await this.renderInnerHTMLToString(); return `<${tag} ${unsafeAttrsToHtml(attributes)}>${children}</${tag}>`; } }; _children = new WeakMap(); _clientImport = new WeakMap(); _loader = new WeakMap(); _options = new WeakMap(); _renderStage = new WeakMap(); function isWebContainer() { var _a, _b; return typeof ((_b = (_a = Reflect.get(globalThis, "process")) == null ? void 0 : _a.versions) == null ? void 0 : _b.webcontainer) === "string"; } var WebWidgetRenderer = ServerWebWidgetRenderer; export { WebWidgetRenderer }; //# sourceMappingURL=web-widget.server.js.map