@lobehub/ui
Version:
Lobe UI is an open-source UI component library for building AIGC web apps
63 lines (62 loc) • 2.38 kB
JavaScript
//#region src/HtmlPreview/const.ts
/**
* Default sandbox attribute for HTML preview iframes.
*
* Why this exact set:
* - `allow-scripts` — required by the use case (three.js / p5.js / Tailwind
* CDN style demos). Without it inline preview degrades to source view.
* - `allow-forms` — lets demos handle `<form>` submissions in-frame.
* - `allow-modals` — `alert`/`confirm`/`prompt` are common in toy demos.
*
* Deliberately omitted:
* - `allow-same-origin` — would let scripts read parent cookies / localStorage
* under cloud deployments, and bridge the IPC boundary on desktop builds.
* - `allow-popups`, `allow-top-navigation` — phishing surface.
*
* Override at your own risk via `sandbox` prop.
*/
const DEFAULT_SANDBOX = "allow-scripts allow-forms allow-modals";
const DEFAULT_HEIGHT = 400;
/**
* Cap for srcDoc length. Beyond a few MB browsers start misbehaving;
* we fall back to source-only above this threshold.
*/
const SRCDOC_MAX_LENGTH = 5 * 1024 * 1024;
const FULL_HTML_MARKERS = [
"<!doctype html",
"<html",
"<HTML"
];
/**
* Is the content a "full" HTML document (has `<html>` or `<!DOCTYPE html>`)?
* Fragments without these markers render poorly inline and should not auto-mount.
*/
const isFullHtmlDocument = (content) => {
if (!content) return false;
const head = content.slice(0, 1024).toLowerCase();
return FULL_HTML_MARKERS.some((marker) => head.includes(marker.toLowerCase()));
};
/**
* Heuristic for whether streaming HTML is "stable enough to mount the iframe".
* Re-mounting srcDoc on every token reboots scripts (p5.js setup runs each
* time), so we wait for a clear closing signal.
*/
const isHtmlContentClosed = (content) => {
if (!content) return false;
return content.slice(-1024).toLowerCase().includes("</html>");
};
/**
* Does the content contain a `<script>` tag?
*
* Used by `streamingMode: 'auto'` to decide whether live-streaming the
* iframe is safe. Script-bearing content gets deferred until stable so we
* don't re-run `setup()` on every token; script-less content (pure
* markup + styles) streams live for a more responsive feel.
*/
const containsScript = (content) => {
if (!content) return false;
return /<script\b/i.test(content);
};
//#endregion
export { DEFAULT_HEIGHT, DEFAULT_SANDBOX, SRCDOC_MAX_LENGTH, containsScript, isFullHtmlDocument, isHtmlContentClosed };
//# sourceMappingURL=const.mjs.map