markdown-flow-ui 0.2.1 → 0.2.3-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/markdown-flow-ui.css +1 -1
- package/dist/components/ContentRender/IframeSandbox.cjs.js +7 -7
- package/dist/components/ContentRender/IframeSandbox.cjs.js.map +1 -1
- package/dist/components/ContentRender/IframeSandbox.es.js +283 -252
- package/dist/components/ContentRender/IframeSandbox.es.js.map +1 -1
- package/dist/components/ContentRender/SandboxApp.cjs.js +2 -2
- package/dist/components/ContentRender/SandboxApp.cjs.js.map +1 -1
- package/dist/components/ContentRender/SandboxApp.es.js +106 -95
- package/dist/components/ContentRender/SandboxApp.es.js.map +1 -1
- package/dist/components/ContentRender/blackboard-vendor.cjs.js +1 -1
- package/dist/components/ContentRender/blackboard-vendor.cjs.js.map +1 -1
- package/dist/components/ContentRender/blackboard-vendor.d.ts +2 -0
- package/dist/components/ContentRender/blackboard-vendor.es.js +9 -12
- package/dist/components/ContentRender/blackboard-vendor.es.js.map +1 -1
- package/dist/components/ContentRender/utils/iframe-scaling.cjs.js +12 -9
- package/dist/components/ContentRender/utils/iframe-scaling.cjs.js.map +1 -1
- package/dist/components/ContentRender/utils/iframe-scaling.es.js +16 -12
- package/dist/components/ContentRender/utils/iframe-scaling.es.js.map +1 -1
- package/dist/components/ContentRender/utils/link-targets.cjs.js +2 -0
- package/dist/components/ContentRender/utils/link-targets.cjs.js.map +1 -0
- package/dist/components/ContentRender/utils/link-targets.d.ts +6 -0
- package/dist/components/ContentRender/utils/link-targets.es.js +26 -0
- package/dist/components/ContentRender/utils/link-targets.es.js.map +1 -0
- package/dist/components/ContentRender/utils/link-targets.test.d.ts +1 -0
- package/dist/components/ContentRender/utils/presentation-scaling.cjs.js +2 -0
- package/dist/components/ContentRender/utils/presentation-scaling.cjs.js.map +1 -0
- package/dist/components/ContentRender/utils/presentation-scaling.d.ts +34 -0
- package/dist/components/ContentRender/utils/presentation-scaling.es.js +67 -0
- package/dist/components/ContentRender/utils/presentation-scaling.es.js.map +1 -0
- package/dist/components/ContentRender/utils/presentation-scaling.test.d.ts +1 -0
- package/dist/components/ContentRender/utils/tailwind-runtime.cjs.js +2 -0
- package/dist/components/ContentRender/utils/tailwind-runtime.cjs.js.map +1 -0
- package/dist/components/ContentRender/utils/tailwind-runtime.d.ts +5 -0
- package/dist/components/ContentRender/utils/tailwind-runtime.es.js +11 -0
- package/dist/components/ContentRender/utils/tailwind-runtime.es.js.map +1 -0
- package/dist/components/ContentRender/utils/tailwind-runtime.test.d.ts +1 -0
- package/dist/components/Slide/MarkdownSlideScaling.cjs.js +2 -0
- package/dist/components/Slide/MarkdownSlideScaling.cjs.js.map +1 -0
- package/dist/components/Slide/MarkdownSlideScaling.d.ts +13 -0
- package/dist/components/Slide/MarkdownSlideScaling.es.js +109 -0
- package/dist/components/Slide/MarkdownSlideScaling.es.js.map +1 -0
- package/dist/components/Slide/Slide.cjs.js +1 -1
- package/dist/components/Slide/Slide.cjs.js.map +1 -1
- package/dist/components/Slide/Slide.d.ts +7 -0
- package/dist/components/Slide/Slide.es.js +803 -708
- package/dist/components/Slide/Slide.es.js.map +1 -1
- package/dist/components/Slide/Slide.stories.d.ts +2473 -0
- package/dist/components/Slide/constants.cjs.js +2 -0
- package/dist/components/Slide/constants.cjs.js.map +1 -0
- package/dist/components/Slide/constants.d.ts +1 -0
- package/dist/components/Slide/constants.es.js +5 -0
- package/dist/components/Slide/constants.es.js.map +1 -0
- package/dist/components/Slide/utils/imageOnlyStepVisualReady.cjs.js +2 -0
- package/dist/components/Slide/utils/imageOnlyStepVisualReady.cjs.js.map +1 -0
- package/dist/components/Slide/utils/imageOnlyStepVisualReady.d.ts +13 -0
- package/dist/components/Slide/utils/imageOnlyStepVisualReady.es.js +12 -0
- package/dist/components/Slide/utils/imageOnlyStepVisualReady.es.js.map +1 -0
- package/dist/components/Slide/utils/interactionPlayback.cjs.js +1 -1
- package/dist/components/Slide/utils/interactionPlayback.cjs.js.map +1 -1
- package/dist/components/Slide/utils/interactionPlayback.d.ts +8 -0
- package/dist/components/Slide/utils/interactionPlayback.es.js +9 -2
- package/dist/components/Slide/utils/interactionPlayback.es.js.map +1 -1
- package/dist/components/Slide/utils/interactionResolution.cjs.js +2 -0
- package/dist/components/Slide/utils/interactionResolution.cjs.js.map +1 -0
- package/dist/components/Slide/utils/interactionResolution.d.ts +13 -0
- package/dist/components/Slide/utils/interactionResolution.es.js +33 -0
- package/dist/components/Slide/utils/interactionResolution.es.js.map +1 -0
- package/dist/components/Slide/utils/interactionResolution.test.d.ts +1 -0
- package/dist/components/Slide/utils/markdownScaling.cjs.js +2 -0
- package/dist/components/Slide/utils/markdownScaling.cjs.js.map +1 -0
- package/dist/components/Slide/utils/markdownScaling.d.ts +7 -0
- package/dist/components/Slide/utils/markdownScaling.es.js +12 -0
- package/dist/components/Slide/utils/markdownScaling.es.js.map +1 -0
- package/dist/components/Slide/utils/markdownScaling.test.d.ts +1 -0
- package/dist/components/Slide/utils/silentStepAutoAdvance.cjs.js +2 -0
- package/dist/components/Slide/utils/silentStepAutoAdvance.cjs.js.map +1 -0
- package/dist/components/Slide/utils/silentStepAutoAdvance.d.ts +14 -0
- package/dist/components/Slide/utils/silentStepAutoAdvance.es.js +37 -0
- package/dist/components/Slide/utils/silentStepAutoAdvance.es.js.map +1 -0
- package/dist/components/Slide/utils/silentStepAutoAdvance.test.d.ts +1 -0
- package/dist/markdown-flow-ui-lib.css +1 -1
- package/package.json +1 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { j as R } from "../../_virtual/jsx-runtime.es.js";
|
|
2
2
|
import { useRef as f, useState as q, useEffect as N } from "react";
|
|
3
|
-
import
|
|
4
|
-
import { getContentRenderLocaleTexts as
|
|
5
|
-
|
|
3
|
+
import ie from "../ui/loading-overlay-card.es.js";
|
|
4
|
+
import { getContentRenderLocaleTexts as le } from "./contentRenderI18n.es.js";
|
|
5
|
+
import { isAnchorElement as ue, shouldForceAnchorHrefToNewTab as P, mergeAnchorRelValue as X, resolveClosestAnchor as fe } from "./utils/link-targets.es.js";
|
|
6
|
+
const de = [
|
|
6
7
|
"src",
|
|
7
8
|
"srcset",
|
|
8
9
|
"sizes",
|
|
@@ -16,55 +17,55 @@ const ce = [
|
|
|
16
17
|
"crossorigin",
|
|
17
18
|
"referrerpolicy",
|
|
18
19
|
"fetchpriority"
|
|
19
|
-
],
|
|
20
|
+
], Y = (o) => de.map(
|
|
20
21
|
(n) => `${n}:${o.getAttribute(n) || ""}`
|
|
21
|
-
).join("|"),
|
|
22
|
+
).join("|"), he = (o) => {
|
|
22
23
|
const n = /* @__PURE__ */ new Map();
|
|
23
24
|
return o.querySelectorAll("img").forEach((i) => {
|
|
24
|
-
const l = i,
|
|
25
|
-
|
|
25
|
+
const l = i, s = Y(l), a = n.get(s) || [];
|
|
26
|
+
a.push(l), n.set(s, a);
|
|
26
27
|
}), n;
|
|
27
|
-
},
|
|
28
|
+
}, me = (o, n) => {
|
|
28
29
|
const i = Array.from(o.attributes), l = new Set(
|
|
29
|
-
i.map((
|
|
30
|
+
i.map((s) => s.name)
|
|
30
31
|
);
|
|
31
|
-
Array.from(n.attributes).forEach((
|
|
32
|
-
l.has(
|
|
33
|
-
}), i.forEach((
|
|
34
|
-
n.setAttribute(
|
|
32
|
+
Array.from(n.attributes).forEach((s) => {
|
|
33
|
+
l.has(s.name) || n.removeAttribute(s.name);
|
|
34
|
+
}), i.forEach((s) => {
|
|
35
|
+
n.setAttribute(s.name, s.value);
|
|
35
36
|
});
|
|
36
|
-
},
|
|
37
|
+
}, pe = (o, n) => {
|
|
37
38
|
n.size && o.querySelectorAll("img").forEach((i) => {
|
|
38
|
-
const l = i,
|
|
39
|
-
p && (
|
|
39
|
+
const l = i, s = Y(l), a = n.get(s), p = a?.shift();
|
|
40
|
+
p && (me(l, p), l.replaceWith(p), a && a.length === 0 && n.delete(s));
|
|
40
41
|
});
|
|
41
|
-
},
|
|
42
|
+
}, Ae = ({
|
|
42
43
|
html: o,
|
|
43
44
|
locale: n,
|
|
44
45
|
loadingText: i,
|
|
45
46
|
styleLoadingText: l,
|
|
46
|
-
scriptLoadingText:
|
|
47
|
-
resetToken:
|
|
47
|
+
scriptLoadingText: s,
|
|
48
|
+
resetToken: a = 0,
|
|
48
49
|
mode: p = "content",
|
|
49
|
-
hasRootVhHeight:
|
|
50
|
-
stretchRootHeight:
|
|
51
|
-
enableScaling:
|
|
52
|
-
disableLoadingOverlay:
|
|
50
|
+
hasRootVhHeight: Z = !1,
|
|
51
|
+
stretchRootHeight: ee = !1,
|
|
52
|
+
enableScaling: F = !1,
|
|
53
|
+
disableLoadingOverlay: k = !1
|
|
53
54
|
}) => {
|
|
54
|
-
const
|
|
55
|
+
const L = le(n), T = f(null), [te, A] = q(!1), [re, S] = q(!1), [ne, j] = q(!1), _ = f([]), H = f([]), z = f(0), U = f(0), y = f(null), g = f(null), b = f(!1), x = f(!1), V = f(a), se = 200, d = (t) => {
|
|
55
56
|
t.current && (clearTimeout(t.current), t.current = null);
|
|
56
|
-
},
|
|
57
|
-
const
|
|
58
|
-
d(
|
|
59
|
-
t(!1), D?.(),
|
|
57
|
+
}, W = (t, c, u, D) => {
|
|
58
|
+
const h = performance.now() - u.current, I = Math.max(0, se - h);
|
|
59
|
+
d(c), c.current = window.setTimeout(() => {
|
|
60
|
+
t(!1), D?.(), c.current = null;
|
|
60
61
|
}, I);
|
|
61
62
|
};
|
|
62
63
|
N(() => {
|
|
63
|
-
const t =
|
|
64
|
+
const t = T.current?.ownerDocument;
|
|
64
65
|
if (!t) return;
|
|
65
|
-
const
|
|
66
|
-
let u = t.getElementById(
|
|
67
|
-
u || (u = t.createElement("style"), u.id =
|
|
66
|
+
const c = "sandbox-spinner-style";
|
|
67
|
+
let u = t.getElementById(c);
|
|
68
|
+
u || (u = t.createElement("style"), u.id = c, t.head?.appendChild(u)), u.textContent = `
|
|
68
69
|
.sandbox-wrapper { align-items: center; }
|
|
69
70
|
.sandbox-container { position: relative; width: 100%; }
|
|
70
71
|
.sandbox-container svg,
|
|
@@ -85,76 +86,86 @@ const ce = [
|
|
|
85
86
|
.overflow-y-auto { overflow-y: visible !important; }
|
|
86
87
|
`;
|
|
87
88
|
}, []), N(() => {
|
|
88
|
-
|
|
89
|
-
const t =
|
|
89
|
+
a !== V.current && (j(!1), V.current = a), d(y), d(g), b.current = !1, x.current = !1;
|
|
90
|
+
const t = T.current;
|
|
90
91
|
if (!t) return;
|
|
91
|
-
const
|
|
92
|
+
const c = t.ownerDocument, u = c?.body;
|
|
92
93
|
if (!u) return;
|
|
93
|
-
const D =
|
|
94
|
-
_.current.forEach((e) => e.remove()), _.current = [],
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
94
|
+
const D = he(t);
|
|
95
|
+
_.current.forEach((e) => e.remove()), _.current = [], H.current.forEach((e) => e.remove()), H.current = [], A(!1), S(!1);
|
|
96
|
+
const h = c.createElement("div");
|
|
97
|
+
h.innerHTML = o, h.querySelectorAll("a[href]").forEach((e) => {
|
|
98
|
+
ue(e) && P(e.getAttribute("href")) && (e.setAttribute("target", "_blank"), e.setAttribute("rel", X(e.getAttribute("rel"))));
|
|
99
|
+
});
|
|
100
|
+
const I = (o.match(/<script[\s>]/gi) || []).length, ae = (o.match(/<\/script>/gi) || []).length, B = I > 0 && I === ae, v = [];
|
|
101
|
+
Array.from(h.querySelectorAll("style, script")).forEach((e) => {
|
|
99
102
|
if (e.tagName.toLowerCase() === "style") {
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}),
|
|
103
|
+
const r = c.createElement("style");
|
|
104
|
+
r.textContent = e.textContent || "", Array.from(e.attributes).forEach((m) => {
|
|
105
|
+
r.setAttribute(m.name, m.value);
|
|
106
|
+
}), v.push(r);
|
|
104
107
|
} else {
|
|
105
|
-
const
|
|
106
|
-
Array.from(e.attributes).forEach((
|
|
107
|
-
|
|
108
|
-
}),
|
|
108
|
+
const r = c.createElement("script");
|
|
109
|
+
Array.from(e.attributes).forEach((m) => {
|
|
110
|
+
r.setAttribute(m.name, m.value);
|
|
111
|
+
}), r.textContent = e.textContent || "", v.push(r);
|
|
109
112
|
}
|
|
110
113
|
e.remove();
|
|
111
|
-
}),
|
|
112
|
-
const O =
|
|
114
|
+
}), pe(h, D);
|
|
115
|
+
const O = v.some(
|
|
113
116
|
(e) => e.tagName.toLowerCase() === "style"
|
|
114
|
-
), G =
|
|
117
|
+
), G = v.some(
|
|
115
118
|
(e) => e.tagName.toLowerCase() === "script"
|
|
116
119
|
);
|
|
117
|
-
O && (b.current = !0,
|
|
118
|
-
const $ = Array.from(
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
120
|
+
O && (b.current = !0, z.current = performance.now(), d(y), A(!0)), G && (x.current = !0, U.current = performance.now(), d(g), S(!0));
|
|
121
|
+
const $ = Array.from(h.childNodes), K = $.length > 0;
|
|
122
|
+
j(K), t.replaceChildren(...$);
|
|
123
|
+
const Q = (e) => {
|
|
124
|
+
const r = fe(e.target);
|
|
125
|
+
r && P(r.getAttribute("href")) && (r.setAttribute("target", "_blank"), r.setAttribute(
|
|
126
|
+
"rel",
|
|
127
|
+
X(r.getAttribute("rel"))
|
|
128
|
+
));
|
|
129
|
+
};
|
|
130
|
+
t.addEventListener("click", Q, !0);
|
|
131
|
+
let w = null;
|
|
132
|
+
const J = () => t.childNodes.length === 0 ? !1 : (j(!0), w?.disconnect(), w = null, !0);
|
|
133
|
+
return !K && G && B && (w = new MutationObserver(() => {
|
|
134
|
+
J();
|
|
135
|
+
}), w.observe(t, {
|
|
125
136
|
childList: !0,
|
|
126
137
|
subtree: !0
|
|
127
|
-
})),
|
|
138
|
+
})), v.forEach((e) => {
|
|
128
139
|
if (e.tagName.toLowerCase() === "style") {
|
|
129
|
-
|
|
140
|
+
c.head?.appendChild(e), _.current.push(e);
|
|
130
141
|
return;
|
|
131
142
|
}
|
|
132
|
-
if (
|
|
133
|
-
const
|
|
134
|
-
if (!
|
|
143
|
+
if (B) {
|
|
144
|
+
const r = e, m = r.textContent || "";
|
|
145
|
+
if (!r.src)
|
|
135
146
|
try {
|
|
136
|
-
new Function(
|
|
147
|
+
new Function(m);
|
|
137
148
|
} catch {
|
|
138
|
-
|
|
149
|
+
r.remove();
|
|
139
150
|
return;
|
|
140
151
|
}
|
|
141
152
|
try {
|
|
142
|
-
u.appendChild(
|
|
153
|
+
u.appendChild(r), H.current.push(r);
|
|
143
154
|
} catch {
|
|
144
|
-
|
|
155
|
+
r.remove();
|
|
145
156
|
}
|
|
146
157
|
} else
|
|
147
158
|
e.remove();
|
|
148
|
-
}),
|
|
149
|
-
O &&
|
|
150
|
-
|
|
159
|
+
}), J(), F && t.ownerDocument?.defaultView?.__mdf_triggerFitContent?.(), requestAnimationFrame(() => {
|
|
160
|
+
O && W(
|
|
161
|
+
A,
|
|
151
162
|
y,
|
|
152
|
-
|
|
163
|
+
z,
|
|
153
164
|
() => {
|
|
154
165
|
b.current = !1;
|
|
155
166
|
}
|
|
156
|
-
), G &&
|
|
157
|
-
|
|
167
|
+
), G && W(
|
|
168
|
+
S,
|
|
158
169
|
g,
|
|
159
170
|
U,
|
|
160
171
|
() => {
|
|
@@ -162,49 +173,49 @@ const ce = [
|
|
|
162
173
|
}
|
|
163
174
|
);
|
|
164
175
|
}), () => {
|
|
165
|
-
|
|
176
|
+
w?.disconnect(), t.removeEventListener("click", Q, !0);
|
|
166
177
|
};
|
|
167
|
-
}, [o,
|
|
178
|
+
}, [o, a, F]), N(
|
|
168
179
|
() => () => {
|
|
169
180
|
d(y), d(g);
|
|
170
181
|
},
|
|
171
182
|
[]
|
|
172
183
|
), N(() => {
|
|
173
|
-
|
|
174
|
-
}, [
|
|
175
|
-
const
|
|
184
|
+
k && (d(y), d(g), b.current = !1, x.current = !1, A(!1), S(!1));
|
|
185
|
+
}, [k]);
|
|
186
|
+
const C = k ? null : re || x.current ? s || i || L.sandboxScriptLoadingText : te || b.current ? l || i || L.sandboxStyleLoadingText : ne ? null : i || L.sandboxLoadingText, M = p === "blackboard", E = M && ee, oe = {
|
|
176
187
|
position: "relative",
|
|
177
188
|
width: "100%",
|
|
178
189
|
height: "100%",
|
|
179
190
|
display: "flex",
|
|
180
191
|
flexDirection: "column",
|
|
181
192
|
// Keep blackboard scroll behavior while centering content in non-blackboard mode
|
|
182
|
-
justifyContent:
|
|
183
|
-
},
|
|
184
|
-
pointerEvents:
|
|
185
|
-
margin:
|
|
193
|
+
justifyContent: E ? "flex-start" : M ? "space-around" : "flex-start"
|
|
194
|
+
}, ce = {
|
|
195
|
+
pointerEvents: C ? "none" : void 0,
|
|
196
|
+
margin: M ? void 0 : "auto 0",
|
|
186
197
|
width: "100%",
|
|
187
|
-
height:
|
|
188
|
-
minHeight:
|
|
189
|
-
flex:
|
|
198
|
+
height: E ? "100%" : void 0,
|
|
199
|
+
minHeight: E ? 0 : void 0,
|
|
200
|
+
flex: E ? "1 1 auto" : void 0
|
|
190
201
|
};
|
|
191
202
|
return /* @__PURE__ */ R.jsxs(
|
|
192
203
|
"div",
|
|
193
204
|
{
|
|
194
|
-
"data-root-vh":
|
|
205
|
+
"data-root-vh": Z ? "true" : "false",
|
|
195
206
|
className: "sandbox-wrapper",
|
|
196
|
-
style:
|
|
197
|
-
"aria-busy": !!
|
|
207
|
+
style: oe,
|
|
208
|
+
"aria-busy": !!C,
|
|
198
209
|
children: [
|
|
199
210
|
/* @__PURE__ */ R.jsx(
|
|
200
211
|
"div",
|
|
201
212
|
{
|
|
202
|
-
ref:
|
|
213
|
+
ref: T,
|
|
203
214
|
className: "sandbox-container",
|
|
204
|
-
style:
|
|
215
|
+
style: ce
|
|
205
216
|
}
|
|
206
217
|
),
|
|
207
|
-
|
|
218
|
+
C && /* @__PURE__ */ R.jsx(
|
|
208
219
|
"div",
|
|
209
220
|
{
|
|
210
221
|
style: {
|
|
@@ -216,7 +227,7 @@ const ce = [
|
|
|
216
227
|
justifyContent: "center",
|
|
217
228
|
pointerEvents: "none"
|
|
218
229
|
},
|
|
219
|
-
children: /* @__PURE__ */ R.jsx(
|
|
230
|
+
children: /* @__PURE__ */ R.jsx(ie, { message: C })
|
|
220
231
|
}
|
|
221
232
|
)
|
|
222
233
|
]
|
|
@@ -224,6 +235,6 @@ const ce = [
|
|
|
224
235
|
);
|
|
225
236
|
};
|
|
226
237
|
export {
|
|
227
|
-
|
|
238
|
+
Ae as default
|
|
228
239
|
};
|
|
229
240
|
//# sourceMappingURL=SandboxApp.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SandboxApp.es.js","sources":["../../../src/components/ContentRender/SandboxApp.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from \"react\";\nimport LoadingOverlayCard from \"../ui/loading-overlay-card\";\nimport type { MarkdownFlowLocale } from \"../../lib/locale\";\nimport { getContentRenderLocaleTexts } from \"./contentRenderI18n\";\nimport type { ScalingWindow } from \"./utils/iframe-scaling\";\n\nexport interface SandboxAppProps {\n html: string;\n locale?: MarkdownFlowLocale;\n loadingText?: string;\n styleLoadingText?: string;\n scriptLoadingText?: string;\n resetToken?: number;\n mode?: \"content\" | \"blackboard\";\n hasRootVhHeight?: boolean;\n stretchRootHeight?: boolean;\n enableScaling?: boolean;\n disableLoadingOverlay?: boolean;\n}\n\nconst IMAGE_REUSE_ATTRIBUTES = [\n \"src\",\n \"srcset\",\n \"sizes\",\n \"alt\",\n \"class\",\n \"width\",\n \"height\",\n \"style\",\n \"loading\",\n \"decoding\",\n \"crossorigin\",\n \"referrerpolicy\",\n \"fetchpriority\",\n];\n\nconst getImageReuseKey = (image: HTMLImageElement) =>\n IMAGE_REUSE_ATTRIBUTES.map(\n (attribute) => `${attribute}:${image.getAttribute(attribute) || \"\"}`\n ).join(\"|\");\n\nconst collectReusableImages = (root: ParentNode) => {\n const imageMap = new Map<string, HTMLImageElement[]>();\n root.querySelectorAll(\"img\").forEach((node) => {\n const image = node as HTMLImageElement;\n const key = getImageReuseKey(image);\n const bucket = imageMap.get(key) || [];\n bucket.push(image);\n imageMap.set(key, bucket);\n });\n return imageMap;\n};\n\nconst syncImageAttributes = (\n sourceImage: HTMLImageElement,\n targetImage: HTMLImageElement\n) => {\n const sourceAttributes = Array.from(sourceImage.attributes);\n const sourceAttributeNames = new Set(\n sourceAttributes.map((attribute) => attribute.name)\n );\n\n Array.from(targetImage.attributes).forEach((attribute) => {\n if (!sourceAttributeNames.has(attribute.name)) {\n targetImage.removeAttribute(attribute.name);\n }\n });\n\n sourceAttributes.forEach((attribute) => {\n targetImage.setAttribute(attribute.name, attribute.value);\n });\n};\n\nconst reuseRenderedImages = (\n root: ParentNode,\n imageMap: Map<string, HTMLImageElement[]>\n) => {\n if (!imageMap.size) return;\n\n root.querySelectorAll(\"img\").forEach((node) => {\n const nextImage = node as HTMLImageElement;\n const key = getImageReuseKey(nextImage);\n const bucket = imageMap.get(key);\n const preservedImage = bucket?.shift();\n if (!preservedImage) return;\n\n syncImageAttributes(nextImage, preservedImage);\n nextImage.replaceWith(preservedImage);\n\n if (bucket && bucket.length === 0) {\n imageMap.delete(key);\n }\n });\n};\n\nconst SandboxApp: React.FC<SandboxAppProps> = ({\n html,\n locale,\n loadingText,\n styleLoadingText,\n scriptLoadingText,\n resetToken = 0,\n mode = \"content\",\n hasRootVhHeight = false,\n stretchRootHeight = false,\n enableScaling = false,\n disableLoadingOverlay = false,\n}) => {\n const localeTexts = getContentRenderLocaleTexts(locale);\n const containerRef = useRef<HTMLDivElement>(null);\n const [isGeneratingStyles, setIsGeneratingStyles] = useState(false);\n const [isGeneratingScripts, setIsGeneratingScripts] = useState(false);\n const [hasRenderedContent, setHasRenderedContent] = useState(false);\n const appendedStylesRef = useRef<HTMLStyleElement[]>([]);\n const appendedScriptsRef = useRef<HTMLScriptElement[]>([]);\n const styleStartRef = useRef(0);\n const scriptStartRef = useRef(0);\n const styleTimerRef = useRef<number | null>(null);\n const scriptTimerRef = useRef<number | null>(null);\n const hasStylesRef = useRef(false);\n const hasScriptsRef = useRef(false);\n const prevResetTokenRef = useRef(resetToken);\n const MIN_LOADING_MS = 200;\n\n const clearTimer = (timerRef: React.MutableRefObject<number | null>) => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n };\n\n const settleStateWithMinimumDelay = (\n setter: React.Dispatch<React.SetStateAction<boolean>>,\n timerRef: React.MutableRefObject<number | null>,\n startRef: React.MutableRefObject<number>,\n onDone?: () => void\n ) => {\n const elapsed = performance.now() - startRef.current;\n const delay = Math.max(0, MIN_LOADING_MS - elapsed);\n clearTimer(timerRef);\n timerRef.current = window.setTimeout(() => {\n setter(false);\n onDone?.();\n timerRef.current = null;\n }, delay);\n };\n\n useEffect(() => {\n const doc = containerRef.current?.ownerDocument;\n if (!doc) return;\n const styleId = \"sandbox-spinner-style\";\n let styleEl = doc.getElementById(styleId) as HTMLStyleElement | null;\n if (!styleEl) {\n styleEl = doc.createElement(\"style\");\n styleEl.id = styleId;\n doc.head?.appendChild(styleEl);\n }\n styleEl.textContent = `\n .sandbox-wrapper { align-items: center; }\n .sandbox-container { position: relative; width: 100%; }\n .sandbox-container svg,\n .sandbox-container img { display: block; margin-left: auto; margin-right: auto; }\n /* Hide scroll UI without removing scroll semantics. Content roots with\n inline style=\"height:100vh; overflow-y:auto\" are the signal that\n IframeSandbox.getInnerScrollableHeight relies on to grow the iframe\n when content exceeds the viewport. We must not change overflow-y,\n but sub-pixel rounding (1px below the +1 detection threshold) can\n still surface a phantom scrollbar on content that visually fits.\n Hide the scrollbar UI globally; when content truly overflows the\n iframe is resized and no scrollbar would render anyway. */\n .sandbox-container *::-webkit-scrollbar { display: none; }\n .sandbox-container * { scrollbar-width: none; -ms-overflow-style: none; }\n .justify-\\\\[safe_center\\\\]{\n justify-content: safe center;\n }\n .overflow-y-auto { overflow-y: visible !important; }\n `;\n }, []);\n\n useEffect(() => {\n if (resetToken !== prevResetTokenRef.current) {\n setHasRenderedContent(false);\n prevResetTokenRef.current = resetToken;\n }\n clearTimer(styleTimerRef);\n clearTimer(scriptTimerRef);\n hasStylesRef.current = false;\n hasScriptsRef.current = false;\n\n const container = containerRef.current;\n if (!container) return;\n const doc = container.ownerDocument;\n const body = doc?.body;\n if (!body) return;\n const reusableImages = collectReusableImages(container);\n\n appendedStylesRef.current.forEach((node) => node.remove());\n appendedStylesRef.current = [];\n appendedScriptsRef.current.forEach((node) => node.remove());\n appendedScriptsRef.current = [];\n\n setIsGeneratingStyles(false);\n setIsGeneratingScripts(false);\n const wrapper = doc.createElement(\"div\");\n wrapper.innerHTML = html;\n\n const openScriptCount = (html.match(/<script[\\s>]/gi) || []).length;\n const closeScriptCount = (html.match(/<\\/script>/gi) || []).length;\n const shouldExecuteScripts =\n openScriptCount > 0 && openScriptCount === closeScriptCount;\n\n const resourceQueue: HTMLElement[] = [];\n\n Array.from(wrapper.querySelectorAll(\"style, script\")).forEach((node) => {\n if (node.tagName.toLowerCase() === \"style\") {\n const cloned = doc.createElement(\"style\");\n cloned.textContent = node.textContent || \"\";\n Array.from(node.attributes).forEach((attr) => {\n cloned.setAttribute(attr.name, attr.value);\n });\n resourceQueue.push(cloned);\n } else {\n const replacement = doc.createElement(\"script\");\n Array.from(node.attributes).forEach((attr) => {\n replacement.setAttribute(attr.name, attr.value);\n });\n replacement.textContent = node.textContent || \"\";\n resourceQueue.push(replacement);\n }\n node.remove();\n });\n reuseRenderedImages(wrapper, reusableImages);\n\n const hasStyles = resourceQueue.some(\n (node) => node.tagName.toLowerCase() === \"style\"\n );\n const hasScripts = resourceQueue.some(\n (node) => node.tagName.toLowerCase() === \"script\"\n );\n if (hasStyles) {\n hasStylesRef.current = true;\n styleStartRef.current = performance.now();\n clearTimer(styleTimerRef);\n setIsGeneratingStyles(true);\n }\n if (hasScripts) {\n hasScriptsRef.current = true;\n scriptStartRef.current = performance.now();\n clearTimer(scriptTimerRef);\n setIsGeneratingScripts(true);\n }\n\n const contentNodes = Array.from(wrapper.childNodes);\n const hasInitialContent = contentNodes.length > 0;\n setHasRenderedContent(hasInitialContent);\n container.replaceChildren(...contentNodes);\n\n let scriptContentObserver: MutationObserver | null = null;\n const markRenderedContentFromContainer = () => {\n if (container.childNodes.length === 0) {\n return false;\n }\n\n setHasRenderedContent(true);\n scriptContentObserver?.disconnect();\n scriptContentObserver = null;\n return true;\n };\n if (!hasInitialContent && hasScripts && shouldExecuteScripts) {\n scriptContentObserver = new MutationObserver(() => {\n markRenderedContentFromContainer();\n });\n scriptContentObserver.observe(container, {\n childList: true,\n subtree: true,\n });\n }\n\n resourceQueue.forEach((node) => {\n if (node.tagName.toLowerCase() === \"style\") {\n doc.head?.appendChild(node);\n appendedStylesRef.current.push(node as HTMLStyleElement);\n return;\n }\n\n if (shouldExecuteScripts) {\n const scriptNode = node as HTMLScriptElement;\n const scriptText = scriptNode.textContent || \"\";\n const shouldValidate = !scriptNode.src;\n\n if (shouldValidate) {\n try {\n // Validate script is syntactically complete before executing\n\n new Function(scriptText);\n } catch {\n scriptNode.remove();\n return;\n }\n }\n\n try {\n body.appendChild(scriptNode);\n appendedScriptsRef.current.push(scriptNode);\n } catch {\n scriptNode.remove();\n }\n } else {\n // Defer execution until all script tags are fully received\n node.remove();\n }\n });\n markRenderedContentFromContainer();\n if (enableScaling) {\n const win = container.ownerDocument?.defaultView as ScalingWindow | null;\n win?.__mdf_triggerFitContent?.();\n }\n\n requestAnimationFrame(() => {\n if (hasStyles) {\n settleStateWithMinimumDelay(\n setIsGeneratingStyles,\n styleTimerRef,\n styleStartRef,\n () => {\n hasStylesRef.current = false;\n }\n );\n }\n if (hasScripts) {\n settleStateWithMinimumDelay(\n setIsGeneratingScripts,\n scriptTimerRef,\n scriptStartRef,\n () => {\n hasScriptsRef.current = false;\n }\n );\n }\n });\n\n return () => {\n scriptContentObserver?.disconnect();\n };\n }, [html, resetToken, enableScaling]);\n\n useEffect(\n () => () => {\n clearTimer(styleTimerRef);\n clearTimer(scriptTimerRef);\n },\n []\n );\n\n useEffect(() => {\n if (!disableLoadingOverlay) {\n return;\n }\n\n clearTimer(styleTimerRef);\n clearTimer(scriptTimerRef);\n hasStylesRef.current = false;\n hasScriptsRef.current = false;\n setIsGeneratingStyles(false);\n setIsGeneratingScripts(false);\n }, [disableLoadingOverlay]);\n\n const overlayMessage = (() => {\n if (disableLoadingOverlay) {\n return null;\n }\n\n if (isGeneratingScripts || hasScriptsRef.current)\n return (\n scriptLoadingText || loadingText || localeTexts.sandboxScriptLoadingText\n );\n if (isGeneratingStyles || hasStylesRef.current)\n return (\n styleLoadingText || loadingText || localeTexts.sandboxStyleLoadingText\n );\n if (!hasRenderedContent)\n return loadingText || localeTexts.sandboxLoadingText;\n return null;\n })();\n\n const isBlackboard = mode === \"blackboard\";\n const shouldStretchRootHeight = isBlackboard && stretchRootHeight;\n const sandboxWrapperStyle: React.CSSProperties = {\n position: \"relative\",\n width: \"100%\",\n height: \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n // Keep blackboard scroll behavior while centering content in non-blackboard mode\n justifyContent: shouldStretchRootHeight\n ? \"flex-start\"\n : isBlackboard\n ? \"space-around\"\n : \"flex-start\",\n };\n const sandboxContainerStyle: React.CSSProperties = {\n pointerEvents: overlayMessage ? \"none\" : undefined,\n margin: isBlackboard ? undefined : \"auto 0\",\n width: \"100%\",\n height: shouldStretchRootHeight ? \"100%\" : undefined,\n minHeight: shouldStretchRootHeight ? 0 : undefined,\n flex: shouldStretchRootHeight ? \"1 1 auto\" : undefined,\n };\n\n return (\n <div\n data-root-vh={hasRootVhHeight ? \"true\" : \"false\"}\n className=\"sandbox-wrapper\"\n style={sandboxWrapperStyle}\n aria-busy={!!overlayMessage}\n >\n <div\n ref={containerRef}\n className=\"sandbox-container\"\n style={sandboxContainerStyle}\n />\n {overlayMessage && (\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n zIndex: 20,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n pointerEvents: \"none\",\n }}\n >\n <LoadingOverlayCard message={overlayMessage} />\n </div>\n )}\n </div>\n );\n};\n\nexport default SandboxApp;\n"],"names":["IMAGE_REUSE_ATTRIBUTES","getImageReuseKey","image","attribute","collectReusableImages","root","imageMap","node","key","bucket","syncImageAttributes","sourceImage","targetImage","sourceAttributes","sourceAttributeNames","reuseRenderedImages","nextImage","preservedImage","SandboxApp","html","locale","loadingText","styleLoadingText","scriptLoadingText","resetToken","mode","hasRootVhHeight","stretchRootHeight","enableScaling","disableLoadingOverlay","localeTexts","getContentRenderLocaleTexts","containerRef","useRef","isGeneratingStyles","setIsGeneratingStyles","useState","isGeneratingScripts","setIsGeneratingScripts","hasRenderedContent","setHasRenderedContent","appendedStylesRef","appendedScriptsRef","styleStartRef","scriptStartRef","styleTimerRef","scriptTimerRef","hasStylesRef","hasScriptsRef","prevResetTokenRef","MIN_LOADING_MS","clearTimer","timerRef","settleStateWithMinimumDelay","setter","startRef","onDone","elapsed","delay","useEffect","doc","styleId","styleEl","container","body","reusableImages","wrapper","openScriptCount","closeScriptCount","shouldExecuteScripts","resourceQueue","cloned","attr","replacement","hasStyles","hasScripts","contentNodes","hasInitialContent","scriptContentObserver","markRenderedContentFromContainer","scriptNode","scriptText","overlayMessage","isBlackboard","shouldStretchRootHeight","sandboxWrapperStyle","sandboxContainerStyle","jsxs","jsx","LoadingOverlayCard"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SandboxApp.es.js","sources":["../../../src/components/ContentRender/SandboxApp.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from \"react\";\nimport LoadingOverlayCard from \"../ui/loading-overlay-card\";\nimport type { MarkdownFlowLocale } from \"../../lib/locale\";\nimport { getContentRenderLocaleTexts } from \"./contentRenderI18n\";\nimport type { ScalingWindow } from \"./utils/iframe-scaling\";\nimport {\n isAnchorElement,\n mergeAnchorRelValue,\n resolveClosestAnchor,\n shouldForceAnchorHrefToNewTab,\n} from \"./utils/link-targets\";\n\nexport interface SandboxAppProps {\n html: string;\n locale?: MarkdownFlowLocale;\n loadingText?: string;\n styleLoadingText?: string;\n scriptLoadingText?: string;\n resetToken?: number;\n mode?: \"content\" | \"blackboard\";\n hasRootVhHeight?: boolean;\n stretchRootHeight?: boolean;\n enableScaling?: boolean;\n disableLoadingOverlay?: boolean;\n}\n\nconst IMAGE_REUSE_ATTRIBUTES = [\n \"src\",\n \"srcset\",\n \"sizes\",\n \"alt\",\n \"class\",\n \"width\",\n \"height\",\n \"style\",\n \"loading\",\n \"decoding\",\n \"crossorigin\",\n \"referrerpolicy\",\n \"fetchpriority\",\n];\n\nconst getImageReuseKey = (image: HTMLImageElement) =>\n IMAGE_REUSE_ATTRIBUTES.map(\n (attribute) => `${attribute}:${image.getAttribute(attribute) || \"\"}`\n ).join(\"|\");\n\nconst collectReusableImages = (root: ParentNode) => {\n const imageMap = new Map<string, HTMLImageElement[]>();\n root.querySelectorAll(\"img\").forEach((node) => {\n const image = node as HTMLImageElement;\n const key = getImageReuseKey(image);\n const bucket = imageMap.get(key) || [];\n bucket.push(image);\n imageMap.set(key, bucket);\n });\n return imageMap;\n};\n\nconst syncImageAttributes = (\n sourceImage: HTMLImageElement,\n targetImage: HTMLImageElement\n) => {\n const sourceAttributes = Array.from(sourceImage.attributes);\n const sourceAttributeNames = new Set(\n sourceAttributes.map((attribute) => attribute.name)\n );\n\n Array.from(targetImage.attributes).forEach((attribute) => {\n if (!sourceAttributeNames.has(attribute.name)) {\n targetImage.removeAttribute(attribute.name);\n }\n });\n\n sourceAttributes.forEach((attribute) => {\n targetImage.setAttribute(attribute.name, attribute.value);\n });\n};\n\nconst reuseRenderedImages = (\n root: ParentNode,\n imageMap: Map<string, HTMLImageElement[]>\n) => {\n if (!imageMap.size) return;\n\n root.querySelectorAll(\"img\").forEach((node) => {\n const nextImage = node as HTMLImageElement;\n const key = getImageReuseKey(nextImage);\n const bucket = imageMap.get(key);\n const preservedImage = bucket?.shift();\n if (!preservedImage) return;\n\n syncImageAttributes(nextImage, preservedImage);\n nextImage.replaceWith(preservedImage);\n\n if (bucket && bucket.length === 0) {\n imageMap.delete(key);\n }\n });\n};\n\nconst SandboxApp: React.FC<SandboxAppProps> = ({\n html,\n locale,\n loadingText,\n styleLoadingText,\n scriptLoadingText,\n resetToken = 0,\n mode = \"content\",\n hasRootVhHeight = false,\n stretchRootHeight = false,\n enableScaling = false,\n disableLoadingOverlay = false,\n}) => {\n const localeTexts = getContentRenderLocaleTexts(locale);\n const containerRef = useRef<HTMLDivElement>(null);\n const [isGeneratingStyles, setIsGeneratingStyles] = useState(false);\n const [isGeneratingScripts, setIsGeneratingScripts] = useState(false);\n const [hasRenderedContent, setHasRenderedContent] = useState(false);\n const appendedStylesRef = useRef<HTMLStyleElement[]>([]);\n const appendedScriptsRef = useRef<HTMLScriptElement[]>([]);\n const styleStartRef = useRef(0);\n const scriptStartRef = useRef(0);\n const styleTimerRef = useRef<number | null>(null);\n const scriptTimerRef = useRef<number | null>(null);\n const hasStylesRef = useRef(false);\n const hasScriptsRef = useRef(false);\n const prevResetTokenRef = useRef(resetToken);\n const MIN_LOADING_MS = 200;\n\n const clearTimer = (timerRef: React.MutableRefObject<number | null>) => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n };\n\n const settleStateWithMinimumDelay = (\n setter: React.Dispatch<React.SetStateAction<boolean>>,\n timerRef: React.MutableRefObject<number | null>,\n startRef: React.MutableRefObject<number>,\n onDone?: () => void\n ) => {\n const elapsed = performance.now() - startRef.current;\n const delay = Math.max(0, MIN_LOADING_MS - elapsed);\n clearTimer(timerRef);\n timerRef.current = window.setTimeout(() => {\n setter(false);\n onDone?.();\n timerRef.current = null;\n }, delay);\n };\n\n useEffect(() => {\n const doc = containerRef.current?.ownerDocument;\n if (!doc) return;\n const styleId = \"sandbox-spinner-style\";\n let styleEl = doc.getElementById(styleId) as HTMLStyleElement | null;\n if (!styleEl) {\n styleEl = doc.createElement(\"style\");\n styleEl.id = styleId;\n doc.head?.appendChild(styleEl);\n }\n styleEl.textContent = `\n .sandbox-wrapper { align-items: center; }\n .sandbox-container { position: relative; width: 100%; }\n .sandbox-container svg,\n .sandbox-container img { display: block; margin-left: auto; margin-right: auto; }\n /* Hide scroll UI without removing scroll semantics. Content roots with\n inline style=\"height:100vh; overflow-y:auto\" are the signal that\n IframeSandbox.getInnerScrollableHeight relies on to grow the iframe\n when content exceeds the viewport. We must not change overflow-y,\n but sub-pixel rounding (1px below the +1 detection threshold) can\n still surface a phantom scrollbar on content that visually fits.\n Hide the scrollbar UI globally; when content truly overflows the\n iframe is resized and no scrollbar would render anyway. */\n .sandbox-container *::-webkit-scrollbar { display: none; }\n .sandbox-container * { scrollbar-width: none; -ms-overflow-style: none; }\n .justify-\\\\[safe_center\\\\]{\n justify-content: safe center;\n }\n .overflow-y-auto { overflow-y: visible !important; }\n `;\n }, []);\n\n useEffect(() => {\n if (resetToken !== prevResetTokenRef.current) {\n setHasRenderedContent(false);\n prevResetTokenRef.current = resetToken;\n }\n clearTimer(styleTimerRef);\n clearTimer(scriptTimerRef);\n hasStylesRef.current = false;\n hasScriptsRef.current = false;\n\n const container = containerRef.current;\n if (!container) return;\n const doc = container.ownerDocument;\n const body = doc?.body;\n if (!body) return;\n const reusableImages = collectReusableImages(container);\n\n appendedStylesRef.current.forEach((node) => node.remove());\n appendedStylesRef.current = [];\n appendedScriptsRef.current.forEach((node) => node.remove());\n appendedScriptsRef.current = [];\n\n setIsGeneratingStyles(false);\n setIsGeneratingScripts(false);\n const wrapper = doc.createElement(\"div\");\n wrapper.innerHTML = html;\n wrapper.querySelectorAll(\"a[href]\").forEach((node) => {\n if (!isAnchorElement(node)) {\n return;\n }\n\n if (!shouldForceAnchorHrefToNewTab(node.getAttribute(\"href\"))) {\n return;\n }\n\n node.setAttribute(\"target\", \"_blank\");\n node.setAttribute(\"rel\", mergeAnchorRelValue(node.getAttribute(\"rel\")));\n });\n\n const openScriptCount = (html.match(/<script[\\s>]/gi) || []).length;\n const closeScriptCount = (html.match(/<\\/script>/gi) || []).length;\n const shouldExecuteScripts =\n openScriptCount > 0 && openScriptCount === closeScriptCount;\n\n const resourceQueue: HTMLElement[] = [];\n\n Array.from(wrapper.querySelectorAll(\"style, script\")).forEach((node) => {\n if (node.tagName.toLowerCase() === \"style\") {\n const cloned = doc.createElement(\"style\");\n cloned.textContent = node.textContent || \"\";\n Array.from(node.attributes).forEach((attr) => {\n cloned.setAttribute(attr.name, attr.value);\n });\n resourceQueue.push(cloned);\n } else {\n const replacement = doc.createElement(\"script\");\n Array.from(node.attributes).forEach((attr) => {\n replacement.setAttribute(attr.name, attr.value);\n });\n replacement.textContent = node.textContent || \"\";\n resourceQueue.push(replacement);\n }\n node.remove();\n });\n reuseRenderedImages(wrapper, reusableImages);\n\n const hasStyles = resourceQueue.some(\n (node) => node.tagName.toLowerCase() === \"style\"\n );\n const hasScripts = resourceQueue.some(\n (node) => node.tagName.toLowerCase() === \"script\"\n );\n if (hasStyles) {\n hasStylesRef.current = true;\n styleStartRef.current = performance.now();\n clearTimer(styleTimerRef);\n setIsGeneratingStyles(true);\n }\n if (hasScripts) {\n hasScriptsRef.current = true;\n scriptStartRef.current = performance.now();\n clearTimer(scriptTimerRef);\n setIsGeneratingScripts(true);\n }\n\n const contentNodes = Array.from(wrapper.childNodes);\n const hasInitialContent = contentNodes.length > 0;\n setHasRenderedContent(hasInitialContent);\n container.replaceChildren(...contentNodes);\n\n const handleLinkClick = (event: MouseEvent) => {\n const anchor = resolveClosestAnchor(event.target);\n if (!anchor) {\n return;\n }\n\n if (!shouldForceAnchorHrefToNewTab(anchor.getAttribute(\"href\"))) {\n return;\n }\n\n anchor.setAttribute(\"target\", \"_blank\");\n anchor.setAttribute(\n \"rel\",\n mergeAnchorRelValue(anchor.getAttribute(\"rel\"))\n );\n };\n container.addEventListener(\"click\", handleLinkClick, true);\n\n let scriptContentObserver: MutationObserver | null = null;\n const markRenderedContentFromContainer = () => {\n if (container.childNodes.length === 0) {\n return false;\n }\n\n setHasRenderedContent(true);\n scriptContentObserver?.disconnect();\n scriptContentObserver = null;\n return true;\n };\n if (!hasInitialContent && hasScripts && shouldExecuteScripts) {\n scriptContentObserver = new MutationObserver(() => {\n markRenderedContentFromContainer();\n });\n scriptContentObserver.observe(container, {\n childList: true,\n subtree: true,\n });\n }\n\n resourceQueue.forEach((node) => {\n if (node.tagName.toLowerCase() === \"style\") {\n doc.head?.appendChild(node);\n appendedStylesRef.current.push(node as HTMLStyleElement);\n return;\n }\n\n if (shouldExecuteScripts) {\n const scriptNode = node as HTMLScriptElement;\n const scriptText = scriptNode.textContent || \"\";\n const shouldValidate = !scriptNode.src;\n\n if (shouldValidate) {\n try {\n // Validate script is syntactically complete before executing\n\n new Function(scriptText);\n } catch {\n scriptNode.remove();\n return;\n }\n }\n\n try {\n body.appendChild(scriptNode);\n appendedScriptsRef.current.push(scriptNode);\n } catch {\n scriptNode.remove();\n }\n } else {\n // Defer execution until all script tags are fully received\n node.remove();\n }\n });\n markRenderedContentFromContainer();\n if (enableScaling) {\n const win = container.ownerDocument?.defaultView as ScalingWindow | null;\n win?.__mdf_triggerFitContent?.();\n }\n\n requestAnimationFrame(() => {\n if (hasStyles) {\n settleStateWithMinimumDelay(\n setIsGeneratingStyles,\n styleTimerRef,\n styleStartRef,\n () => {\n hasStylesRef.current = false;\n }\n );\n }\n if (hasScripts) {\n settleStateWithMinimumDelay(\n setIsGeneratingScripts,\n scriptTimerRef,\n scriptStartRef,\n () => {\n hasScriptsRef.current = false;\n }\n );\n }\n });\n\n return () => {\n scriptContentObserver?.disconnect();\n container.removeEventListener(\"click\", handleLinkClick, true);\n };\n }, [html, resetToken, enableScaling]);\n\n useEffect(\n () => () => {\n clearTimer(styleTimerRef);\n clearTimer(scriptTimerRef);\n },\n []\n );\n\n useEffect(() => {\n if (!disableLoadingOverlay) {\n return;\n }\n\n clearTimer(styleTimerRef);\n clearTimer(scriptTimerRef);\n hasStylesRef.current = false;\n hasScriptsRef.current = false;\n setIsGeneratingStyles(false);\n setIsGeneratingScripts(false);\n }, [disableLoadingOverlay]);\n\n const overlayMessage = (() => {\n if (disableLoadingOverlay) {\n return null;\n }\n\n if (isGeneratingScripts || hasScriptsRef.current)\n return (\n scriptLoadingText || loadingText || localeTexts.sandboxScriptLoadingText\n );\n if (isGeneratingStyles || hasStylesRef.current)\n return (\n styleLoadingText || loadingText || localeTexts.sandboxStyleLoadingText\n );\n if (!hasRenderedContent)\n return loadingText || localeTexts.sandboxLoadingText;\n return null;\n })();\n\n const isBlackboard = mode === \"blackboard\";\n const shouldStretchRootHeight = isBlackboard && stretchRootHeight;\n const sandboxWrapperStyle: React.CSSProperties = {\n position: \"relative\",\n width: \"100%\",\n height: \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n // Keep blackboard scroll behavior while centering content in non-blackboard mode\n justifyContent: shouldStretchRootHeight\n ? \"flex-start\"\n : isBlackboard\n ? \"space-around\"\n : \"flex-start\",\n };\n const sandboxContainerStyle: React.CSSProperties = {\n pointerEvents: overlayMessage ? \"none\" : undefined,\n margin: isBlackboard ? undefined : \"auto 0\",\n width: \"100%\",\n height: shouldStretchRootHeight ? \"100%\" : undefined,\n minHeight: shouldStretchRootHeight ? 0 : undefined,\n flex: shouldStretchRootHeight ? \"1 1 auto\" : undefined,\n };\n\n return (\n <div\n data-root-vh={hasRootVhHeight ? \"true\" : \"false\"}\n className=\"sandbox-wrapper\"\n style={sandboxWrapperStyle}\n aria-busy={!!overlayMessage}\n >\n <div\n ref={containerRef}\n className=\"sandbox-container\"\n style={sandboxContainerStyle}\n />\n {overlayMessage && (\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n zIndex: 20,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n pointerEvents: \"none\",\n }}\n >\n <LoadingOverlayCard message={overlayMessage} />\n </div>\n )}\n </div>\n );\n};\n\nexport default SandboxApp;\n"],"names":["IMAGE_REUSE_ATTRIBUTES","getImageReuseKey","image","attribute","collectReusableImages","root","imageMap","node","key","bucket","syncImageAttributes","sourceImage","targetImage","sourceAttributes","sourceAttributeNames","reuseRenderedImages","nextImage","preservedImage","SandboxApp","html","locale","loadingText","styleLoadingText","scriptLoadingText","resetToken","mode","hasRootVhHeight","stretchRootHeight","enableScaling","disableLoadingOverlay","localeTexts","getContentRenderLocaleTexts","containerRef","useRef","isGeneratingStyles","setIsGeneratingStyles","useState","isGeneratingScripts","setIsGeneratingScripts","hasRenderedContent","setHasRenderedContent","appendedStylesRef","appendedScriptsRef","styleStartRef","scriptStartRef","styleTimerRef","scriptTimerRef","hasStylesRef","hasScriptsRef","prevResetTokenRef","MIN_LOADING_MS","clearTimer","timerRef","settleStateWithMinimumDelay","setter","startRef","onDone","elapsed","delay","useEffect","doc","styleId","styleEl","container","body","reusableImages","wrapper","isAnchorElement","shouldForceAnchorHrefToNewTab","mergeAnchorRelValue","openScriptCount","closeScriptCount","shouldExecuteScripts","resourceQueue","cloned","attr","replacement","hasStyles","hasScripts","contentNodes","hasInitialContent","handleLinkClick","event","anchor","resolveClosestAnchor","scriptContentObserver","markRenderedContentFromContainer","scriptNode","scriptText","overlayMessage","isBlackboard","shouldStretchRootHeight","sandboxWrapperStyle","sandboxContainerStyle","jsxs","jsx","LoadingOverlayCard"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("./vendor/tailwindcss-v3.min.cjs.js"),l=require("./vendor/daisyui-v4.min.css.cjs.js"),s=require("./vendor/gsap-v3.min.cjs.js"),a=require("./utils/tailwind-runtime.cjs.js");function d(e){const t=e.createElement("script");t.textContent=r.default,e.head.appendChild(t),a.refreshTailwindRuntime(e);const i=e.createElement("style");i.textContent=l.default,e.head.appendChild(i);const n=e.createElement("script");n.textContent=s.default,e.head.appendChild(n)}exports.refreshTailwindRuntime=a.refreshTailwindRuntime;exports.injectBlackboardLibraries=d;
|
|
2
2
|
//# sourceMappingURL=blackboard-vendor.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blackboard-vendor.cjs.js","sources":["../../../src/components/ContentRender/blackboard-vendor.ts"],"sourcesContent":["import tailwindScript from \"./vendor/tailwindcss-v3.min.js?raw\";\nimport daisyuiCss from \"./vendor/daisyui-v4.min.css?raw\";\nimport gsapScript from \"./vendor/gsap-v3.min.js?raw\";\nimport {
|
|
1
|
+
{"version":3,"file":"blackboard-vendor.cjs.js","sources":["../../../src/components/ContentRender/blackboard-vendor.ts"],"sourcesContent":["import tailwindScript from \"./vendor/tailwindcss-v3.min.js?raw\";\nimport daisyuiCss from \"./vendor/daisyui-v4.min.css?raw\";\nimport gsapScript from \"./vendor/gsap-v3.min.js?raw\";\nimport { refreshTailwindRuntime } from \"./utils/tailwind-runtime\";\n\nexport { refreshTailwindRuntime };\n\n/**\n * Inject blackboard-mode libraries (Tailwind CSS, DaisyUI, GSAP)\n * into an iframe document using DOM API to avoid template-string escaping issues.\n */\nexport function injectBlackboardLibraries(doc: Document): void {\n // 1. Tailwind CSS v3 (JIT compiler, must load first)\n const tailwindEl = doc.createElement(\"script\");\n tailwindEl.textContent = tailwindScript;\n // The Play CDN script replaces window.tailwind with its Proxy during execution,\n // so configure that runtime only after the synchronous append completes.\n doc.head.appendChild(tailwindEl);\n refreshTailwindRuntime(doc);\n\n // 2. DaisyUI v4 CSS\n const daisyuiEl = doc.createElement(\"style\");\n daisyuiEl.textContent = daisyuiCss;\n doc.head.appendChild(daisyuiEl);\n\n // 3. GSAP v3\n const gsapEl = doc.createElement(\"script\");\n gsapEl.textContent = gsapScript;\n doc.head.appendChild(gsapEl);\n}\n"],"names":["injectBlackboardLibraries","doc","tailwindEl","tailwindScript","refreshTailwindRuntime","daisyuiEl","daisyuiCss","gsapEl","gsapScript"],"mappings":"4QAWO,SAASA,EAA0BC,EAAqB,CAE7D,MAAMC,EAAaD,EAAI,cAAc,QAAQ,EAC7CC,EAAW,YAAcC,EAAAA,QAGzBF,EAAI,KAAK,YAAYC,CAAU,EAC/BE,EAAAA,uBAAuBH,CAAG,EAG1B,MAAMI,EAAYJ,EAAI,cAAc,OAAO,EAC3CI,EAAU,YAAcC,EAAAA,QACxBL,EAAI,KAAK,YAAYI,CAAS,EAG9B,MAAME,EAASN,EAAI,cAAc,QAAQ,EACzCM,EAAO,YAAcC,EAAAA,QACrBP,EAAI,KAAK,YAAYM,CAAM,CAC7B"}
|
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
import r from "./vendor/tailwindcss-v3.min.es.js";
|
|
2
|
-
import
|
|
2
|
+
import a from "./vendor/daisyui-v4.min.css.es.js";
|
|
3
3
|
import p from "./vendor/gsap-v3.min.es.js";
|
|
4
|
-
import {
|
|
4
|
+
import { refreshTailwindRuntime as l } from "./utils/tailwind-runtime.es.js";
|
|
5
5
|
function c(t) {
|
|
6
6
|
const e = t.createElement("script");
|
|
7
|
-
e.textContent = r, t.head.appendChild(e);
|
|
8
|
-
const i = t.
|
|
9
|
-
i
|
|
10
|
-
|
|
11
|
-
)
|
|
12
|
-
const n = t.createElement("style");
|
|
13
|
-
n.textContent = l, t.head.appendChild(n);
|
|
14
|
-
const a = t.createElement("script");
|
|
15
|
-
a.textContent = p, t.head.appendChild(a);
|
|
7
|
+
e.textContent = r, t.head.appendChild(e), l(t);
|
|
8
|
+
const i = t.createElement("style");
|
|
9
|
+
i.textContent = a, t.head.appendChild(i);
|
|
10
|
+
const n = t.createElement("script");
|
|
11
|
+
n.textContent = p, t.head.appendChild(n);
|
|
16
12
|
}
|
|
17
13
|
export {
|
|
18
|
-
c as injectBlackboardLibraries
|
|
14
|
+
c as injectBlackboardLibraries,
|
|
15
|
+
l as refreshTailwindRuntime
|
|
19
16
|
};
|
|
20
17
|
//# sourceMappingURL=blackboard-vendor.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blackboard-vendor.es.js","sources":["../../../src/components/ContentRender/blackboard-vendor.ts"],"sourcesContent":["import tailwindScript from \"./vendor/tailwindcss-v3.min.js?raw\";\nimport daisyuiCss from \"./vendor/daisyui-v4.min.css?raw\";\nimport gsapScript from \"./vendor/gsap-v3.min.js?raw\";\nimport {
|
|
1
|
+
{"version":3,"file":"blackboard-vendor.es.js","sources":["../../../src/components/ContentRender/blackboard-vendor.ts"],"sourcesContent":["import tailwindScript from \"./vendor/tailwindcss-v3.min.js?raw\";\nimport daisyuiCss from \"./vendor/daisyui-v4.min.css?raw\";\nimport gsapScript from \"./vendor/gsap-v3.min.js?raw\";\nimport { refreshTailwindRuntime } from \"./utils/tailwind-runtime\";\n\nexport { refreshTailwindRuntime };\n\n/**\n * Inject blackboard-mode libraries (Tailwind CSS, DaisyUI, GSAP)\n * into an iframe document using DOM API to avoid template-string escaping issues.\n */\nexport function injectBlackboardLibraries(doc: Document): void {\n // 1. Tailwind CSS v3 (JIT compiler, must load first)\n const tailwindEl = doc.createElement(\"script\");\n tailwindEl.textContent = tailwindScript;\n // The Play CDN script replaces window.tailwind with its Proxy during execution,\n // so configure that runtime only after the synchronous append completes.\n doc.head.appendChild(tailwindEl);\n refreshTailwindRuntime(doc);\n\n // 2. DaisyUI v4 CSS\n const daisyuiEl = doc.createElement(\"style\");\n daisyuiEl.textContent = daisyuiCss;\n doc.head.appendChild(daisyuiEl);\n\n // 3. GSAP v3\n const gsapEl = doc.createElement(\"script\");\n gsapEl.textContent = gsapScript;\n doc.head.appendChild(gsapEl);\n}\n"],"names":["injectBlackboardLibraries","doc","tailwindEl","tailwindScript","refreshTailwindRuntime","daisyuiEl","daisyuiCss","gsapEl","gsapScript"],"mappings":";;;;AAWO,SAASA,EAA0BC,GAAqB;AAE7D,QAAMC,IAAaD,EAAI,cAAc,QAAQ;AAC7C,EAAAC,EAAW,cAAcC,GAGzBF,EAAI,KAAK,YAAYC,CAAU,GAC/BE,EAAuBH,CAAG;AAG1B,QAAMI,IAAYJ,EAAI,cAAc,OAAO;AAC3C,EAAAI,EAAU,cAAcC,GACxBL,EAAI,KAAK,YAAYI,CAAS;AAG9B,QAAME,IAASN,EAAI,cAAc,QAAQ;AACzC,EAAAM,EAAO,cAAcC,GACrBP,EAAI,KAAK,YAAYM,CAAM;AAC7B;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./presentation-scaling.cjs.js"),n=`
|
|
2
2
|
/* Gamma-style scaling base */
|
|
3
|
-
:root { --mdf-fs:
|
|
3
|
+
:root { --mdf-fs: ${e.PRESENTATION_DEFAULT_FONT_SIZE_PX}px; }
|
|
4
4
|
|
|
5
5
|
*, *::before, *::after {
|
|
6
6
|
box-sizing: border-box;
|
|
@@ -25,13 +25,13 @@ html, body {
|
|
|
25
25
|
/* Hide scrollbars inside scaled content — overflow handled by compression */
|
|
26
26
|
.sandbox-container *::-webkit-scrollbar { display: none; }
|
|
27
27
|
.sandbox-container * { scrollbar-width: none; -ms-overflow-style: none; }
|
|
28
|
-
`,
|
|
28
|
+
`,s=`
|
|
29
29
|
!function() {
|
|
30
30
|
var fitTimer = null;
|
|
31
|
-
var baseFontSize =
|
|
31
|
+
var baseFontSize = ${e.PRESENTATION_DEFAULT_FONT_SIZE_PX};
|
|
32
32
|
var compressionRatio = 1;
|
|
33
33
|
var lastCompressTime = 0;
|
|
34
|
-
var MIN_FONT_PX =
|
|
34
|
+
var MIN_FONT_PX = ${e.PRESENTATION_MIN_FONT_SIZE_PX};
|
|
35
35
|
|
|
36
36
|
function applyFs(fs) {
|
|
37
37
|
document.documentElement.style.setProperty('--mdf-fs', fs + 'px');
|
|
@@ -48,8 +48,8 @@ html, body {
|
|
|
48
48
|
var naturalH = slide.offsetHeight;
|
|
49
49
|
var naturalW = slide.scrollWidth;
|
|
50
50
|
|
|
51
|
-
var overflowH = naturalH > viewH +
|
|
52
|
-
var overflowW = naturalW > viewW +
|
|
51
|
+
var overflowH = naturalH > viewH + ${e.PRESENTATION_OVERFLOW_TOLERANCE_PX};
|
|
52
|
+
var overflowW = naturalW > viewW + ${e.PRESENTATION_OVERFLOW_TOLERANCE_PX};
|
|
53
53
|
|
|
54
54
|
if (overflowH || overflowW) {
|
|
55
55
|
var now = Date.now();
|
|
@@ -84,7 +84,10 @@ html, body {
|
|
|
84
84
|
function syncFs() {
|
|
85
85
|
var w = document.documentElement.clientWidth;
|
|
86
86
|
var h = document.documentElement.clientHeight;
|
|
87
|
-
baseFontSize = Math.min(
|
|
87
|
+
baseFontSize = Math.min(
|
|
88
|
+
Math.max(${e.PRESENTATION_MIN_BASE_FONT_SIZE_PX}, w / ${e.PRESENTATION_WIDTH_FONT_DIVISOR}),
|
|
89
|
+
h * ${e.PRESENTATION_HEIGHT_FONT_RATIO}
|
|
90
|
+
);
|
|
88
91
|
applyFs(Math.max(baseFontSize * compressionRatio, MIN_FONT_PX));
|
|
89
92
|
clearTimeout(fitTimer);
|
|
90
93
|
fitTimer = setTimeout(fitContent, 60);
|
|
@@ -157,5 +160,5 @@ html, body {
|
|
|
157
160
|
delete window.__mdf_cleanupScaling;
|
|
158
161
|
};
|
|
159
162
|
}();
|
|
160
|
-
`;function
|
|
163
|
+
`;function r(t){const o=t.createElement("style");o.id="mdf-scaling-style",o.textContent=n,t.head.appendChild(o);const i=t.createElement("script");i.id="mdf-scaling-script",i.textContent=s,t.head.appendChild(i)}exports.injectScalingSystem=r;
|
|
161
164
|
//# sourceMappingURL=iframe-scaling.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iframe-scaling.cjs.js","sources":["../../../../src/components/ContentRender/utils/iframe-scaling.ts"],"sourcesContent":["/**\n * Gamma-style font-size scaling system for iframe sandbox.\n *\n * Injects CSS + JS into an iframe document so that:\n * 1. A base font-size is computed from the viewport: clamp(12px, width/48, height*3%)\n * 2. The CSS variable --mdf-fs drives html/body font-size; all em children follow.\n * 3. When content overflows the viewport, a compression ratio shrinks font-size.\n * 4. ResizeObserver / MutationObserver keep everything in sync.\n */\n\n/** Window extension for the scaling system injected into the iframe. */\nexport interface ScalingWindow extends Window {\n __mdf_triggerFitContent?: () => void;\n __mdf_cleanupScaling?: () => void;\n}\n\nconst SCALING_CSS = `\n/* Gamma-style scaling base */\n:root { --mdf-fs:
|
|
1
|
+
{"version":3,"file":"iframe-scaling.cjs.js","sources":["../../../../src/components/ContentRender/utils/iframe-scaling.ts"],"sourcesContent":["/**\n * Gamma-style font-size scaling system for iframe sandbox.\n *\n * Injects CSS + JS into an iframe document so that:\n * 1. A base font-size is computed from the viewport: clamp(12px, width/48, height*3%)\n * 2. The CSS variable --mdf-fs drives html/body font-size; all em children follow.\n * 3. When content overflows the viewport, a compression ratio shrinks font-size.\n * 4. ResizeObserver / MutationObserver keep everything in sync.\n */\n\nimport {\n PRESENTATION_DEFAULT_FONT_SIZE_PX,\n PRESENTATION_HEIGHT_FONT_RATIO,\n PRESENTATION_MIN_BASE_FONT_SIZE_PX,\n PRESENTATION_MIN_FONT_SIZE_PX,\n PRESENTATION_OVERFLOW_TOLERANCE_PX,\n PRESENTATION_WIDTH_FONT_DIVISOR,\n} from \"./presentation-scaling\";\n\n/** Window extension for the scaling system injected into the iframe. */\nexport interface ScalingWindow extends Window {\n __mdf_triggerFitContent?: () => void;\n __mdf_cleanupScaling?: () => void;\n}\n\nconst SCALING_CSS = `\n/* Gamma-style scaling base */\n:root { --mdf-fs: ${PRESENTATION_DEFAULT_FONT_SIZE_PX}px; }\n\n*, *::before, *::after {\n box-sizing: border-box;\n overflow-wrap: break-word;\n word-break: break-word;\n}\n\nhtml, body {\n font-size: var(--mdf-fs);\n overflow-x: hidden;\n overflow-y: auto;\n}\n\n/* Force sandbox content children into the em scaling chain */\n.sandbox-container > * {\n height: auto !important;\n min-height: 100vh !important;\n overflow: hidden !important;\n font-size: var(--mdf-fs) !important;\n}\n\n/* Hide scrollbars inside scaled content — overflow handled by compression */\n.sandbox-container *::-webkit-scrollbar { display: none; }\n.sandbox-container * { scrollbar-width: none; -ms-overflow-style: none; }\n`;\n\nconst SCALING_JS = `\n!function() {\n var fitTimer = null;\n var baseFontSize = ${PRESENTATION_DEFAULT_FONT_SIZE_PX};\n var compressionRatio = 1;\n var lastCompressTime = 0;\n var MIN_FONT_PX = ${PRESENTATION_MIN_FONT_SIZE_PX};\n\n function applyFs(fs) {\n document.documentElement.style.setProperty('--mdf-fs', fs + 'px');\n if (document.body) document.body.style.fontSize = fs + 'px';\n }\n\n function fitContent() {\n var container = document.querySelector('.sandbox-container');\n if (!container || !container.firstElementChild) return;\n\n var slide = container.firstElementChild;\n var viewH = document.documentElement.clientHeight;\n var viewW = document.documentElement.clientWidth;\n var naturalH = slide.offsetHeight;\n var naturalW = slide.scrollWidth;\n\n var overflowH = naturalH > viewH + ${PRESENTATION_OVERFLOW_TOLERANCE_PX};\n var overflowW = naturalW > viewW + ${PRESENTATION_OVERFLOW_TOLERANCE_PX};\n\n if (overflowH || overflowW) {\n var now = Date.now();\n if (now - lastCompressTime < 300) return;\n lastCompressTime = now;\n\n var ratioH = overflowH ? (viewH / naturalH) : 1;\n var ratioW = overflowW ? (viewW / naturalW) : 1;\n compressionRatio = compressionRatio * Math.min(ratioH, ratioW);\n compressionRatio = Math.max(compressionRatio, MIN_FONT_PX / baseFontSize);\n applyFs(baseFontSize * compressionRatio);\n\n if (baseFontSize * compressionRatio <= MIN_FONT_PX * 1.1 && viewH < 400) {\n document.documentElement.style.overflowY = 'hidden';\n if (document.body) document.body.style.overflowY = 'hidden';\n }\n } else {\n if (compressionRatio < 1 && naturalH > 0) {\n var maxRatio = viewH * compressionRatio / naturalH;\n if (maxRatio >= 1) {\n compressionRatio = 1;\n } else if (maxRatio > compressionRatio) {\n compressionRatio = maxRatio;\n }\n applyFs(baseFontSize * compressionRatio);\n }\n document.documentElement.style.overflowY = '';\n if (document.body) document.body.style.overflowY = '';\n }\n }\n\n function syncFs() {\n var w = document.documentElement.clientWidth;\n var h = document.documentElement.clientHeight;\n baseFontSize = Math.min(\n Math.max(${PRESENTATION_MIN_BASE_FONT_SIZE_PX}, w / ${PRESENTATION_WIDTH_FONT_DIVISOR}),\n h * ${PRESENTATION_HEIGHT_FONT_RATIO}\n );\n applyFs(Math.max(baseFontSize * compressionRatio, MIN_FONT_PX));\n clearTimeout(fitTimer);\n fitTimer = setTimeout(fitContent, 60);\n }\n\n var rootResizeObs = null;\n if (window.ResizeObserver) {\n rootResizeObs = new ResizeObserver(syncFs);\n rootResizeObs.observe(document.documentElement);\n } else {\n window.addEventListener('resize', syncFs);\n }\n syncFs();\n\n var slideResizeObs = null;\n function observeSlide(slide) {\n if (!window.ResizeObserver) return;\n if (slideResizeObs) slideResizeObs.disconnect();\n slideResizeObs = new ResizeObserver(function() {\n clearTimeout(fitTimer);\n fitTimer = setTimeout(fitContent, 50);\n });\n slideResizeObs.observe(slide);\n }\n\n var mutationObs = null;\n function startFitObserver() {\n var c = document.querySelector('.sandbox-container');\n if (!c) return;\n mutationObs = new MutationObserver(function(mutations) {\n var hasNewContent = false;\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 &&\n node.tagName !== 'STYLE' && node.tagName !== 'SCRIPT') {\n hasNewContent = true;\n observeSlide(node);\n }\n });\n });\n if (hasNewContent) {\n compressionRatio = 1;\n lastCompressTime = 0;\n applyFs(baseFontSize);\n }\n clearTimeout(fitTimer);\n fitTimer = setTimeout(fitContent, 80);\n });\n mutationObs.observe(c, { childList: true });\n }\n\n if (document.readyState !== 'loading') {\n startFitObserver();\n } else {\n document.addEventListener('DOMContentLoaded', startFitObserver);\n }\n\n window.__mdf_triggerFitContent = function() {\n clearTimeout(fitTimer);\n fitTimer = setTimeout(fitContent, 100);\n };\n\n window.__mdf_cleanupScaling = function() {\n clearTimeout(fitTimer);\n if (rootResizeObs) rootResizeObs.disconnect();\n if (slideResizeObs) slideResizeObs.disconnect();\n if (mutationObs) mutationObs.disconnect();\n window.removeEventListener('resize', syncFs);\n delete window.__mdf_triggerFitContent;\n delete window.__mdf_cleanupScaling;\n };\n}();\n`;\n\n/**\n * Inject the Gamma-style font-size scaling system into an iframe document.\n * Must be called AFTER blackboard vendor libraries (Tailwind/DaisyUI/GSAP)\n * so that the scaling CSS rules take precedence.\n */\nexport function injectScalingSystem(doc: Document): void {\n const styleEl = doc.createElement(\"style\");\n styleEl.id = \"mdf-scaling-style\";\n styleEl.textContent = SCALING_CSS;\n doc.head.appendChild(styleEl);\n\n const scriptEl = doc.createElement(\"script\");\n scriptEl.id = \"mdf-scaling-script\";\n scriptEl.textContent = SCALING_JS;\n doc.head.appendChild(scriptEl);\n}\n"],"names":["SCALING_CSS","PRESENTATION_DEFAULT_FONT_SIZE_PX","SCALING_JS","PRESENTATION_MIN_FONT_SIZE_PX","PRESENTATION_OVERFLOW_TOLERANCE_PX","PRESENTATION_MIN_BASE_FONT_SIZE_PX","PRESENTATION_WIDTH_FONT_DIVISOR","PRESENTATION_HEIGHT_FONT_RATIO","injectScalingSystem","doc","styleEl","scriptEl"],"mappings":"iIAyBMA,EAAc;AAAA;AAAA,oBAEAC,mCAAiC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA2B/CC,EAAa;AAAA;AAAA;AAAA,uBAGID,mCAAiC;AAAA;AAAA;AAAA,sBAGlCE,+BAA6B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yCAiBVC,oCAAkC;AAAA,yCAClCA,oCAAkC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAoC1DC,EAAAA,kCAAkC,SAASC,iCAA+B;AAAA,YAC/EC,EAAAA,8BAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiFnC,SAASC,EAAoBC,EAAqB,CACvD,MAAMC,EAAUD,EAAI,cAAc,OAAO,EACzCC,EAAQ,GAAK,oBACbA,EAAQ,YAAcV,EACtBS,EAAI,KAAK,YAAYC,CAAO,EAE5B,MAAMC,EAAWF,EAAI,cAAc,QAAQ,EAC3CE,EAAS,GAAK,qBACdA,EAAS,YAAcT,EACvBO,EAAI,KAAK,YAAYE,CAAQ,CAC/B"}
|