/* Kole UI · 在线测试(独立页) 编辑 H5 演示源码 → iframe srcdoc 实时重渲染;数据与文档站同源(同目录 data.json)。 零运行时依赖。 ── 预览帧的安全边界(2026-09-20 真实浏览器实测) ────────────────────────── 预览里跑的是用户随手改的代码,按「不可信内容」对待,三层隔离: 1) sandbox="allow-scripts" 且**不给** allow-same-origin —— 帧是不透明源。帧内读 parent/top、document.cookie、localStorage 全是 SecurityError;顶层跳转、 window.open、表单提交、下载全被拦;探针服务器上收不到任何帧发起的请求。 2) 帧内注入 meta CSP,**只写比父页更严的项**(connect-src / form-action / frame-src 一律 'none'):帧内彻底发不出网络请求(fetch / sendBeacon / WebSocket / 表单)。 两条策略取交集,所以这里写的每一项都只会收紧 —— 父页 CSP 继续负责"允许什么", 本页不重复声明,避免把 'self' 在不透明源下的解析差异带进来。 3) 帧内注入 :srcdoc 的基准 URL 默认是父页 /site/, 演示源码里的 "./Xxx.css" 会被解析成 /site/Xxx.css(404)→ 预览丢掉组件样式 (实测 79 个组件里 36 个命中)。钉到演示原页所在目录后,相对资源解析与 「演示原页」完全一致。 帧内的脚本报错与被沙箱拦下的请求经 postMessage 回传本页,在预览上方按纯文本提示: 预览不再静默白屏、也不静默丢样式。父页只认「来源严格等于本页预览帧」的消息, 且只取字符串渲染,预览里的代码无法借此碰到本页 DOM。 ───────────────────────────────────────────────────────────────────────── */ 'use strict'; (function () { var editor = document.getElementById('pg-editor'); var frame = document.getElementById('pg-frame'); var select = document.getElementById('pg-select'); var nameEl = document.getElementById('pg-name'); var statusEl = document.getElementById('pg-status'); var errorEl = document.getElementById('pg-error'); var noteEl = document.getElementById('pg-note'); var resetBtn = document.getElementById('pg-reset'); var copyBtn = document.getElementById('pg-copy'); var reloadBtn = document.getElementById('pg-reload'); var openLink = document.getElementById('pg-open'); var backLink = document.getElementById('pg-back'); var RENDER_DELAY = 300; var DEFAULT_SLUG = 'button'; /* 演示原页住在 /frameworks/:srcdoc 里必须以它为基准,否则 ./ 相对引用全错 */ var FRAME_BASE = '../frameworks/'; /* 只列比父页更严的三条(父页是 connect-src/form-action/frame-src 'self') */ var PREVIEW_CSP = "connect-src 'none'; form-action 'none'; frame-src 'none'; object-src 'none'"; /* 帧内上报器:跑在用户代码之前,捕获脚本报错与策略拦截 */ var REPORTER = '