UNPKG

@lobehub/ui

Version:

Lobe UI is an open-source UI component library for building AIGC web apps

44 lines (43 loc) 2.43 kB
import { buildAutoHeightScript } from "./injectAutoHeightScript.mjs"; import { STORAGE_SHIM_SCRIPT } from "./injectStorageShim.mjs"; //#region src/HtmlPreview/buildStaticSrcDoc.ts const shimsBlock = (frameId) => `<script>${STORAGE_SHIM_SCRIPT}<\/script><script>${buildAutoHeightScript(frameId)}<\/script>`; const baseStyle = (background) => `<style>html,body{margin:0;padding:0;${background ? `background:${background};` : ""}color-scheme:light dark;}</style>`; /** * Wrap a user's HTML document with our shims so the iframe can load it as * a single self-contained srcDoc. This path is used when the content is * *static* (not streaming) — the browser parses it via the normal HTML * pipeline, so external `<script src=…>` tags load and execute exactly * like they would on a regular page. Tailwind CDN, Chart.js, p5.js — all * the things a Play CDN expects to see at parse time — work naturally. * * For *streaming* content we instead use `buildShellSrcDoc` + postMessage * morph, which trades reliable script execution for the ability to fade * in new nodes without reloading the iframe. * * Strategy: inject our shims (storage shim, auto-height) as early in the * resulting `<head>` as possible so they run before any user script. If * the user supplied a `<head>` open tag we slot the shims in right after * it; otherwise we wrap a minimal document around fragments. */ const buildStaticSrcDoc = ({ background, content, frameId }) => { const head = `${baseStyle(background)}${shimsBlock(frameId)}`; const lower = content.toLowerCase(); if (!lower.includes("<html")) return `<!DOCTYPE html><html><head><meta charset="utf-8">${head}</head><body>${content}</body></html>`; const headOpenMatch = content.match(/<head\b[^>]*>/i); if (headOpenMatch) { const idx = headOpenMatch.index + headOpenMatch[0].length; return content.slice(0, idx) + head + content.slice(idx); } const headCloseIdx = lower.indexOf("</head>"); if (headCloseIdx !== -1) return content.slice(0, headCloseIdx) + head + content.slice(headCloseIdx); const htmlOpenMatch = content.match(/<html\b[^>]*>/i); if (htmlOpenMatch) { const idx = htmlOpenMatch.index + htmlOpenMatch[0].length; return content.slice(0, idx) + `<head>${head}</head>` + content.slice(idx); } return `<!DOCTYPE html><html><head>${head}</head><body>${content}</body></html>`; }; //#endregion export { buildStaticSrcDoc }; //# sourceMappingURL=buildStaticSrcDoc.mjs.map