@viceme-ai/sdk 0.2.0 → 0.3.0
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/README.md +49 -45
- package/dist/chunks/client-DKsaEtwq.js +941 -0
- package/dist/chunks/client-DKsaEtwq.js.map +1 -0
- package/dist/chunks/version-C3KVoLNb.js +51 -0
- package/dist/chunks/version-C3KVoLNb.js.map +1 -0
- package/dist/core/build-endpoints.d.ts +4 -1
- package/dist/core/build-endpoints.d.ts.map +1 -1
- package/dist/core/capabilities.d.ts +79 -0
- package/dist/core/capabilities.d.ts.map +1 -0
- package/dist/core/client.d.ts +34 -8
- package/dist/core/client.d.ts.map +1 -1
- package/dist/core/config.d.ts +14 -4
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/errors.d.ts +1 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/lifecycle.d.ts +4 -2
- package/dist/core/lifecycle.d.ts.map +1 -1
- package/dist/core/presentation.d.ts +24 -0
- package/dist/core/presentation.d.ts.map +1 -0
- package/dist/danmaku.js +44 -48
- package/dist/danmaku.js.map +1 -1
- package/dist/generated/public-contract.d.ts +617 -13
- package/dist/generated/public-contract.d.ts.map +1 -1
- package/dist/index.d.ts +8 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +112 -95
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +30 -18
- package/dist/session/session.d.ts +67 -0
- package/dist/session/session.d.ts.map +1 -0
- package/dist/testing/test-adapter.d.ts +59 -0
- package/dist/testing/test-adapter.d.ts.map +1 -0
- package/dist/testing.d.ts +9 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +75 -0
- package/dist/testing.js.map +1 -0
- package/dist/transport/transport.d.ts +44 -0
- package/dist/transport/transport.d.ts.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/viceme.min.js +232 -1
- package/dist/viceme.min.js.map +1 -1
- package/package.json +6 -2
- package/dist/chunks/version-BbUa2jZV.js +0 -38
- package/dist/chunks/version-BbUa2jZV.js.map +0 -1
package/dist/danmaku.js
CHANGED
|
@@ -1,47 +1,43 @@
|
|
|
1
|
-
import { V as H,
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
global: "https://viceme.ai"
|
|
5
|
-
};
|
|
6
|
-
function G(n = window, a = document) {
|
|
7
|
-
const t = te(n, a), e = ae(n, a);
|
|
1
|
+
import { V as H, B as j, S as ee } from "./chunks/version-C3KVoLNb.js";
|
|
2
|
+
function G(r = window, a = document) {
|
|
3
|
+
const t = te(r, a), e = ae(r, a);
|
|
8
4
|
return {
|
|
9
|
-
anchorKey: `page:${
|
|
5
|
+
anchorKey: `page:${re(t)}:scroll:${e}`,
|
|
10
6
|
scrollBucket: e
|
|
11
7
|
};
|
|
12
8
|
}
|
|
13
|
-
function te(
|
|
14
|
-
const t = a.querySelector('link[rel="canonical"][href]'), e = t?.href ||
|
|
9
|
+
function te(r, a) {
|
|
10
|
+
const t = a.querySelector('link[rel="canonical"][href]'), e = t?.href || r.location.href;
|
|
15
11
|
try {
|
|
16
|
-
const i = new URL(e,
|
|
17
|
-
return i.username = "", i.password = "", t && !i.hash &&
|
|
12
|
+
const i = new URL(e, r.location.href);
|
|
13
|
+
return i.username = "", i.password = "", t && !i.hash && r.location.hash && (i.hash = r.location.hash), i.toString();
|
|
18
14
|
} catch {
|
|
19
|
-
return
|
|
15
|
+
return r.location.href;
|
|
20
16
|
}
|
|
21
17
|
}
|
|
22
|
-
function ae(
|
|
23
|
-
const t = a.documentElement, e = a.body, i =
|
|
18
|
+
function ae(r, a) {
|
|
19
|
+
const t = a.documentElement, e = a.body, i = r.scrollY || r.pageYOffset || t.scrollTop || e?.scrollTop || 0, m = Math.max(
|
|
24
20
|
t.scrollHeight,
|
|
25
21
|
t.offsetHeight,
|
|
26
22
|
t.clientHeight,
|
|
27
23
|
e?.scrollHeight ?? 0,
|
|
28
24
|
e?.offsetHeight ?? 0
|
|
29
|
-
), p = Math.max(0, m -
|
|
25
|
+
), p = Math.max(0, m - r.innerHeight);
|
|
30
26
|
if (p <= 1) return "0-100";
|
|
31
27
|
const w = Math.max(0, Math.min(99, i / p * 100)), y = Math.min(90, Math.floor(w / 10) * 10);
|
|
32
28
|
return `${y}-${y + 10}`;
|
|
33
29
|
}
|
|
34
|
-
function
|
|
35
|
-
let a = 3735928559 ^
|
|
36
|
-
for (let e = 0; e <
|
|
37
|
-
const i =
|
|
30
|
+
function re(r) {
|
|
31
|
+
let a = 3735928559 ^ r.length, t = 1103547991 ^ r.length;
|
|
32
|
+
for (let e = 0; e < r.length; e += 1) {
|
|
33
|
+
const i = r.charCodeAt(e);
|
|
38
34
|
a = Math.imul(a ^ i, 2654435761), t = Math.imul(t ^ i, 1597334677);
|
|
39
35
|
}
|
|
40
36
|
return a = Math.imul(a ^ a >>> 16, 2246822507), a ^= Math.imul(t ^ t >>> 13, 3266489909), t = Math.imul(t ^ t >>> 16, 2246822507), t ^= Math.imul(a ^ a >>> 13, 3266489909), ((t >>> 0).toString(36).padStart(7, "0") + (a >>> 0).toString(36).padStart(7, "0")).slice(0, 16);
|
|
41
37
|
}
|
|
42
|
-
const C = 32, oe = 56,
|
|
43
|
-
async function le(
|
|
44
|
-
if (await
|
|
38
|
+
const C = 32, oe = 56, ne = 360, L = 480, se = 120, ie = 1e3, Y = 8e3;
|
|
39
|
+
async function le(r, a) {
|
|
40
|
+
if (await r.ready(), !r.hasCapability("danmaku"))
|
|
45
41
|
throw new H({
|
|
46
42
|
code: "CAPABILITY_DISABLED",
|
|
47
43
|
message: "Danmaku is not available in this SDK build.",
|
|
@@ -56,7 +52,7 @@ async function le(n, a) {
|
|
|
56
52
|
retryable: !1,
|
|
57
53
|
capability: "danmaku"
|
|
58
54
|
});
|
|
59
|
-
const i =
|
|
55
|
+
const i = j[r.region];
|
|
60
56
|
let m = G(e, t);
|
|
61
57
|
const p = t.documentElement.lang.trim() || e.navigator.language || "en";
|
|
62
58
|
let w = !1, y, b, u, A = !1, P = 0, S = "", M = !1;
|
|
@@ -66,7 +62,7 @@ async function le(n, a) {
|
|
|
66
62
|
g.style.boxSizing = "border-box", g.style.position = "fixed", g.style.inset = "0", g.style.width = "100%", g.style.height = "100%", g.style.pointerEvents = "none", Z.append(g);
|
|
67
63
|
const R = (o) => {
|
|
68
64
|
const l = new URL("/embed/danmaku", i);
|
|
69
|
-
return l.searchParams.set("mode", o), l.searchParams.set("workKey",
|
|
65
|
+
return l.searchParams.set("mode", o), l.searchParams.set("workKey", r.workKey), l.searchParams.set("theme", a.theme), l.searchParams.set("locale", p), l.searchParams.set("sdk", ee), l.searchParams.set("anchorKey", m.anchorKey), l;
|
|
70
66
|
}, _ = (o, l, k) => {
|
|
71
67
|
const s = t.createElement("iframe");
|
|
72
68
|
return s.title = l, s.src = k, s.loading = "eager", s.referrerPolicy = "no-referrer", s.setAttribute("allowtransparency", "true"), s.setAttribute(
|
|
@@ -90,8 +86,8 @@ async function le(n, a) {
|
|
|
90
86
|
d.style.width = `${Math.min(W, o)}px`, d.style.height = `${O}px`;
|
|
91
87
|
};
|
|
92
88
|
D(), d.style.pointerEvents = "none";
|
|
93
|
-
const
|
|
94
|
-
|
|
89
|
+
const n = _("modal", "ViceMe Danmaku dialog", "about:blank");
|
|
90
|
+
n.dataset.src = R("modal").toString(), n.style.inset = "0", n.style.height = "100%", n.style.display = "none", n.style.pointerEvents = "none", g.append(f, d, n);
|
|
95
91
|
const T = (o) => {
|
|
96
92
|
I.has(o) && o.contentWindow?.postMessage(
|
|
97
93
|
{
|
|
@@ -102,7 +98,7 @@ async function le(n, a) {
|
|
|
102
98
|
i
|
|
103
99
|
);
|
|
104
100
|
}, K = () => {
|
|
105
|
-
T(f), T(d),
|
|
101
|
+
T(f), T(d), n.getAttribute("src") !== "about:blank" && T(n);
|
|
106
102
|
}, U = () => {
|
|
107
103
|
if (w) return m;
|
|
108
104
|
const o = G(e, t);
|
|
@@ -115,13 +111,13 @@ async function le(n, a) {
|
|
|
115
111
|
const l = o.currentTarget;
|
|
116
112
|
l.getAttribute("src") !== "about:blank" && (I.add(l), T(l));
|
|
117
113
|
};
|
|
118
|
-
f.addEventListener("load", E), d.addEventListener("load", E),
|
|
114
|
+
f.addEventListener("load", E), d.addEventListener("load", E), n.addEventListener("load", E);
|
|
119
115
|
const F = (o = !1) => {
|
|
120
|
-
u !== void 0 && (e.clearTimeout(u), u = void 0),
|
|
116
|
+
u !== void 0 && (e.clearTimeout(u), u = void 0), n.style.display = "none", n.style.pointerEvents = "none", o && (S = "", M = !1, I.delete(n), n.src = "about:blank");
|
|
121
117
|
};
|
|
122
|
-
let
|
|
118
|
+
let B;
|
|
123
119
|
const J = new Promise((o, l) => {
|
|
124
|
-
|
|
120
|
+
B = o, b = e.setTimeout(() => {
|
|
125
121
|
l(
|
|
126
122
|
new H({
|
|
127
123
|
code: "INTERNAL_ERROR",
|
|
@@ -131,9 +127,9 @@ async function le(n, a) {
|
|
|
131
127
|
})
|
|
132
128
|
);
|
|
133
129
|
}, Y);
|
|
134
|
-
}),
|
|
130
|
+
}), V = (o) => {
|
|
135
131
|
if (o.origin !== i) return;
|
|
136
|
-
const l = o.source === f.contentWindow, k = o.source === d.contentWindow, s = o.source ===
|
|
132
|
+
const l = o.source === f.contentWindow, k = o.source === d.contentWindow, s = o.source === n.contentWindow;
|
|
137
133
|
if (!l && !k && !s) return;
|
|
138
134
|
const c = o.data;
|
|
139
135
|
if (!c || c.source !== "viceme-danmaku") return;
|
|
@@ -142,31 +138,31 @@ async function le(n, a) {
|
|
|
142
138
|
if (c.mode !== N) return;
|
|
143
139
|
if (N === "modal") {
|
|
144
140
|
if (c.frameToken !== S) return;
|
|
145
|
-
M = !0, u !== void 0 && (e.clearTimeout(u), u = void 0),
|
|
141
|
+
M = !0, u !== void 0 && (e.clearTimeout(u), u = void 0), n.style.display === "block" && (n.style.pointerEvents = "auto");
|
|
146
142
|
return;
|
|
147
143
|
}
|
|
148
|
-
x.add(N), x.has("stage") && x.has("controls") && !A && (A = !0, b !== void 0 && (e.clearTimeout(b), b = void 0), d.style.pointerEvents = "auto",
|
|
144
|
+
x.add(N), x.has("stage") && x.has("controls") && !A && (A = !0, b !== void 0 && (e.clearTimeout(b), b = void 0), d.style.pointerEvents = "auto", B?.());
|
|
149
145
|
return;
|
|
150
146
|
}
|
|
151
147
|
if (c.action === "resize-controls" && k) {
|
|
152
|
-
if (typeof c.width != "number" || !Number.isInteger(c.width) || c.width < C || c.width > L || typeof c.height != "number" || !Number.isInteger(c.height) || c.height < C || c.height >
|
|
148
|
+
if (typeof c.width != "number" || !Number.isInteger(c.width) || c.width < C || c.width > L || typeof c.height != "number" || !Number.isInteger(c.height) || c.height < C || c.height > ne)
|
|
153
149
|
return;
|
|
154
150
|
W = c.width, O = c.height, D();
|
|
155
151
|
}
|
|
156
|
-
if (c.action === "request-anchor" && T(s ?
|
|
152
|
+
if (c.action === "request-anchor" && T(s ? n : l ? f : d), c.action === "open-modal" && k) {
|
|
157
153
|
if (!A) return;
|
|
158
|
-
if (
|
|
154
|
+
if (n.getAttribute("src") === "about:blank") {
|
|
159
155
|
P += 1, S = String(P);
|
|
160
|
-
const q = new URL(
|
|
161
|
-
q.searchParams.set("frameToken", S),
|
|
156
|
+
const q = new URL(n.dataset.src ?? "about:blank");
|
|
157
|
+
q.searchParams.set("frameToken", S), n.src = q.toString();
|
|
162
158
|
}
|
|
163
|
-
|
|
159
|
+
n.style.display = "block", n.style.pointerEvents = M ? "auto" : "none", M || (u !== void 0 && e.clearTimeout(u), u = e.setTimeout(() => F(!0), Y));
|
|
164
160
|
}
|
|
165
161
|
c.action === "close-modal" && (s || k) && F(!M);
|
|
166
162
|
}, Q = e.setInterval(U, ie), $ = () => {
|
|
167
|
-
w || (w = !0, y !== void 0 && e.clearTimeout(y), b !== void 0 && e.clearTimeout(b), u !== void 0 && e.clearTimeout(u), e.clearInterval(Q), e.removeEventListener("message",
|
|
163
|
+
w || (w = !0, y !== void 0 && e.clearTimeout(y), b !== void 0 && e.clearTimeout(b), u !== void 0 && e.clearTimeout(u), e.clearInterval(Q), e.removeEventListener("message", V), e.removeEventListener("scroll", v), e.removeEventListener("resize", z), e.removeEventListener("popstate", v), e.removeEventListener("hashchange", v), f.removeEventListener("load", E), d.removeEventListener("load", E), n.removeEventListener("load", E), h.remove());
|
|
168
164
|
};
|
|
169
|
-
e.addEventListener("message",
|
|
165
|
+
e.addEventListener("message", V), e.addEventListener("scroll", v, { passive: !0 }), e.addEventListener("resize", z), e.addEventListener("popstate", v), e.addEventListener("hashchange", v);
|
|
170
166
|
try {
|
|
171
167
|
a.target.appendChild(h), K(), await J;
|
|
172
168
|
} catch (o) {
|
|
@@ -178,12 +174,12 @@ async function le(n, a) {
|
|
|
178
174
|
};
|
|
179
175
|
}
|
|
180
176
|
const X = /* @__PURE__ */ new WeakMap();
|
|
181
|
-
function de(
|
|
182
|
-
let t = X.get(
|
|
183
|
-
t || (t = /* @__PURE__ */ new WeakMap(), X.set(
|
|
177
|
+
function de(r, a) {
|
|
178
|
+
let t = X.get(r);
|
|
179
|
+
t || (t = /* @__PURE__ */ new WeakMap(), X.set(r, t));
|
|
184
180
|
const e = t.get(a.target);
|
|
185
181
|
if (e) return e;
|
|
186
|
-
const i = le(
|
|
182
|
+
const i = le(r, a).then((m) => {
|
|
187
183
|
let p = !1;
|
|
188
184
|
return {
|
|
189
185
|
capability: "danmaku",
|
package/dist/danmaku.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"danmaku.js","sources":["../src/core/build-endpoints.ts","../src/danmaku/anchor.ts","../src/danmaku/mount.ts","../src/danmaku/index.ts"],"sourcesContent":["declare const __VICEME_BUILD_CN_WIDGET_ORIGIN__: string | undefined;\ndeclare const __VICEME_BUILD_GLOBAL_WIDGET_ORIGIN__: string | undefined;\n\n/** Hosted Shop origins baked into immutable release artifacts. */\nexport const BUILD_WIDGET_ORIGINS = {\n cn:\n typeof __VICEME_BUILD_CN_WIDGET_ORIGIN__ === 'string'\n ? __VICEME_BUILD_CN_WIDGET_ORIGIN__\n : 'https://viceme.cn',\n global:\n typeof __VICEME_BUILD_GLOBAL_WIDGET_ORIGIN__ === 'string'\n ? __VICEME_BUILD_GLOBAL_WIDGET_ORIGIN__\n : 'https://viceme.ai',\n} as const;\n","export interface DanmakuPageAnchor {\n /** Stable page-and-position key sent to the hosted danmaku runtime. */\n anchorKey: string;\n /** Human-readable 10% scroll bucket, useful for diagnostics. */\n scrollBucket: string;\n}\n\n/**\n * Build a stable page-position anchor without exposing the page URL.\n *\n * Canonical URLs and SPA hash routes participate in the local hash. Only the\n * resulting opaque key leaves the host page.\n */\nexport function readDanmakuPageAnchor(\n windowObject: Window = window,\n documentObject: Document = document,\n): DanmakuPageAnchor {\n const pageUrl = canonicalPageUrl(windowObject, documentObject);\n const bucket = scrollBucket(windowObject, documentObject);\n return {\n anchorKey: `page:${hashString(pageUrl)}:scroll:${bucket}`,\n scrollBucket: bucket,\n };\n}\n\nfunction canonicalPageUrl(windowObject: Window, documentObject: Document): string {\n const canonical = documentObject.querySelector<HTMLLinkElement>('link[rel=\"canonical\"][href]');\n const rawUrl = canonical?.href || windowObject.location.href;\n try {\n const url = new URL(rawUrl, windowObject.location.href);\n url.username = '';\n url.password = '';\n if (canonical && !url.hash && windowObject.location.hash) {\n url.hash = windowObject.location.hash;\n }\n return url.toString();\n } catch {\n return windowObject.location.href;\n }\n}\n\nfunction scrollBucket(windowObject: Window, documentObject: Document): string {\n const root = documentObject.documentElement;\n const body = documentObject.body;\n const scrollTop =\n windowObject.scrollY || windowObject.pageYOffset || root.scrollTop || body?.scrollTop || 0;\n const scrollHeight = Math.max(\n root.scrollHeight,\n root.offsetHeight,\n root.clientHeight,\n body?.scrollHeight ?? 0,\n body?.offsetHeight ?? 0,\n );\n const maxScroll = Math.max(0, scrollHeight - windowObject.innerHeight);\n if (maxScroll <= 1) return '0-100';\n\n const percent = Math.max(0, Math.min(99, (scrollTop / maxScroll) * 100));\n const start = Math.min(90, Math.floor(percent / 10) * 10);\n return `${start}-${start + 10}`;\n}\n\n/** Deterministic 64-bit-style hash encoded as at most 16 base36 characters. */\nfunction hashString(value: string): string {\n let high = 0xdeadbeef ^ value.length;\n let low = 0x41c6ce57 ^ value.length;\n for (let index = 0; index < value.length; index += 1) {\n const character = value.charCodeAt(index);\n high = Math.imul(high ^ character, 2654435761);\n low = Math.imul(low ^ character, 1597334677);\n }\n high = Math.imul(high ^ (high >>> 16), 2246822507);\n high ^= Math.imul(low ^ (low >>> 13), 3266489909);\n low = Math.imul(low ^ (low >>> 16), 2246822507);\n low ^= Math.imul(high ^ (high >>> 13), 3266489909);\n return (\n (low >>> 0).toString(36).padStart(7, '0') + (high >>> 0).toString(36).padStart(7, '0')\n ).slice(0, 16);\n}\n","import type { ViceMeClient } from '../core/client.ts';\nimport { BUILD_WIDGET_ORIGINS } from '../core/build-endpoints.ts';\nimport { ViceMeError } from '../core/errors.ts';\nimport type { CapabilityMountHandle, CapabilityMountOptions } from '../loader/mount-handle.ts';\nimport { SDK_VERSION } from '../version.ts';\nimport { readDanmakuPageAnchor, type DanmakuPageAnchor } from './anchor.ts';\n\ntype DanmakuFrameMode = 'stage' | 'controls' | 'modal';\n\ninterface DanmakuBridgeMessage {\n source?: unknown;\n action?: unknown;\n frameToken?: unknown;\n mode?: unknown;\n width?: unknown;\n height?: unknown;\n}\n\nconst CONTROLS_MIN_SIZE = 32;\nconst CONTROLS_BAR_HEIGHT = 56;\nconst CONTROLS_MAX_HEIGHT = 360;\nconst CONTROLS_MAX_WIDTH = 480;\nconst ANCHOR_DEBOUNCE_MS = 120;\nconst LOCATION_POLL_MS = 1_000;\nexport const FRAME_READY_TIMEOUT_MS = 8_000;\n\nexport async function mount(\n client: ViceMeClient,\n options: CapabilityMountOptions,\n): Promise<CapabilityMountHandle> {\n await client.ready();\n if (!client.hasCapability('danmaku')) {\n throw new ViceMeError({\n code: 'CAPABILITY_DISABLED',\n message: 'Danmaku is not available in this SDK build.',\n retryable: false,\n capability: 'danmaku',\n });\n }\n\n const documentObject = options.target.ownerDocument;\n const windowObject = documentObject.defaultView;\n if (!windowObject) {\n throw new ViceMeError({\n code: 'CONFIG_INVALID',\n message: 'Danmaku requires a browser document.',\n retryable: false,\n capability: 'danmaku',\n });\n }\n\n const widgetOrigin = BUILD_WIDGET_ORIGINS[client.region];\n let currentAnchor = readDanmakuPageAnchor(windowObject, documentObject);\n const locale =\n documentObject.documentElement.lang.trim() || windowObject.navigator.language || 'en';\n let destroyed = false;\n let anchorTimer: number | undefined;\n let readyTimer: number | undefined;\n let modalReadyTimer: number | undefined;\n let initialFramesReady = false;\n let modalAttempt = 0;\n let modalFrameToken = '';\n let modalReady = false;\n const loadedFrames = new WeakSet<HTMLIFrameElement>();\n const readyModes = new Set<DanmakuFrameMode>();\n\n const portal = documentObject.createElement('div');\n portal.dataset.vicemeDanmaku = 'mounted';\n portal.style.all = 'initial';\n portal.style.position = 'fixed';\n portal.style.inset = '0';\n portal.style.width = '100%';\n portal.style.height = '100%';\n portal.style.pointerEvents = 'none';\n portal.style.zIndex = '2147483000';\n portal.style.contain = 'layout style size';\n\n const shadow = portal.attachShadow({ mode: 'open' });\n const root = documentObject.createElement('div');\n root.style.boxSizing = 'border-box';\n root.style.position = 'fixed';\n root.style.inset = '0';\n root.style.width = '100%';\n root.style.height = '100%';\n root.style.pointerEvents = 'none';\n shadow.append(root);\n\n const frameUrl = (mode: DanmakuFrameMode): URL => {\n const url = new URL('/embed/danmaku', widgetOrigin);\n url.searchParams.set('mode', mode);\n url.searchParams.set('workKey', client.workKey);\n url.searchParams.set('theme', options.theme);\n url.searchParams.set('locale', locale);\n url.searchParams.set('sdk', SDK_VERSION);\n url.searchParams.set('anchorKey', currentAnchor.anchorKey);\n return url;\n };\n\n const createFrame = (\n mode: DanmakuFrameMode,\n title: string,\n source: string,\n ): HTMLIFrameElement => {\n const frame = documentObject.createElement('iframe');\n frame.title = title;\n frame.src = source;\n frame.loading = 'eager';\n frame.referrerPolicy = 'no-referrer';\n frame.setAttribute('allowtransparency', 'true');\n frame.setAttribute(\n 'sandbox',\n 'allow-forms allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts',\n );\n frame.dataset.mode = mode;\n frame.style.boxSizing = 'border-box';\n frame.style.colorScheme = 'normal';\n frame.style.position = 'fixed';\n frame.style.margin = '0';\n frame.style.border = '0';\n frame.style.background = 'transparent';\n frame.style.width = '100%';\n frame.style.zIndex = '2147483000';\n return frame;\n };\n\n const stage = createFrame('stage', 'ViceMe Danmaku', frameUrl('stage').toString());\n stage.setAttribute('aria-hidden', 'true');\n stage.style.inset = '0';\n stage.style.height = '100%';\n stage.style.pointerEvents = 'none';\n\n const controls = createFrame(\n 'controls',\n 'ViceMe Danmaku controls',\n frameUrl('controls').toString(),\n );\n controls.style.left = '50%';\n controls.style.bottom = 'env(safe-area-inset-bottom, 0px)';\n controls.style.maxWidth = `${CONTROLS_MAX_WIDTH}px`;\n controls.style.transform = 'translateX(-50%)';\n let controlsRequestedWidth = CONTROLS_MAX_WIDTH;\n let controlsRequestedHeight = CONTROLS_BAR_HEIGHT;\n const applyControlsSize = (): void => {\n const viewportWidth = Math.max(\n CONTROLS_MIN_SIZE,\n Math.floor(windowObject.innerWidth || CONTROLS_MAX_WIDTH),\n );\n controls.style.width = `${Math.min(controlsRequestedWidth, viewportWidth)}px`;\n controls.style.height = `${controlsRequestedHeight}px`;\n };\n applyControlsSize();\n controls.style.pointerEvents = 'none';\n\n const modal = createFrame('modal', 'ViceMe Danmaku dialog', 'about:blank');\n modal.dataset.src = frameUrl('modal').toString();\n modal.style.inset = '0';\n modal.style.height = '100%';\n modal.style.display = 'none';\n modal.style.pointerEvents = 'none';\n\n root.append(stage, controls, modal);\n\n const postAnchor = (frame: HTMLIFrameElement): void => {\n if (!loadedFrames.has(frame)) return;\n frame.contentWindow?.postMessage(\n {\n source: 'viceme-danmaku',\n action: 'anchor-change',\n anchorKey: currentAnchor.anchorKey,\n },\n widgetOrigin,\n );\n };\n const postAnchorToMountedFrames = (): void => {\n postAnchor(stage);\n postAnchor(controls);\n if (modal.getAttribute('src') !== 'about:blank') postAnchor(modal);\n };\n\n const refreshAnchor = (): DanmakuPageAnchor => {\n if (destroyed) return currentAnchor;\n const next = readDanmakuPageAnchor(windowObject, documentObject);\n if (next.anchorKey !== currentAnchor.anchorKey) {\n currentAnchor = next;\n postAnchorToMountedFrames();\n }\n return currentAnchor;\n };\n const scheduleAnchorRefresh = (): void => {\n if (anchorTimer !== undefined) windowObject.clearTimeout(anchorTimer);\n anchorTimer = windowObject.setTimeout(refreshAnchor, ANCHOR_DEBOUNCE_MS);\n };\n const handleWindowResize = (): void => {\n applyControlsSize();\n scheduleAnchorRefresh();\n };\n\n const frameLoaded = (event: Event): void => {\n const frame = event.currentTarget as HTMLIFrameElement;\n if (frame.getAttribute('src') === 'about:blank') return;\n loadedFrames.add(frame);\n postAnchor(frame);\n };\n stage.addEventListener('load', frameLoaded);\n controls.addEventListener('load', frameLoaded);\n modal.addEventListener('load', frameLoaded);\n\n const hideModal = (resetFrame = false): void => {\n if (modalReadyTimer !== undefined) {\n windowObject.clearTimeout(modalReadyTimer);\n modalReadyTimer = undefined;\n }\n modal.style.display = 'none';\n modal.style.pointerEvents = 'none';\n if (resetFrame) {\n modalFrameToken = '';\n modalReady = false;\n loadedFrames.delete(modal);\n modal.src = 'about:blank';\n }\n };\n\n let resolveInitialFrames: (() => void) | undefined;\n const initialFrameReadiness = new Promise<void>((resolve, reject) => {\n resolveInitialFrames = resolve;\n readyTimer = windowObject.setTimeout(() => {\n reject(\n new ViceMeError({\n code: 'INTERNAL_ERROR',\n message: 'Hosted danmaku frames did not become ready in time.',\n retryable: true,\n capability: 'danmaku',\n }),\n );\n }, FRAME_READY_TIMEOUT_MS);\n });\n\n const onMessage = (event: MessageEvent): void => {\n if (event.origin !== widgetOrigin) return;\n const fromStage = event.source === stage.contentWindow;\n const fromControls = event.source === controls.contentWindow;\n const fromModal = event.source === modal.contentWindow;\n if (!fromStage && !fromControls && !fromModal) return;\n\n const message = event.data as DanmakuBridgeMessage | null;\n if (!message || message.source !== 'viceme-danmaku') return;\n\n const sourceMode: DanmakuFrameMode = fromModal ? 'modal' : fromStage ? 'stage' : 'controls';\n if (message.action === 'frame-ready') {\n if (message.mode !== sourceMode) return;\n if (sourceMode === 'modal') {\n if (message.frameToken !== modalFrameToken) return;\n modalReady = true;\n if (modalReadyTimer !== undefined) {\n windowObject.clearTimeout(modalReadyTimer);\n modalReadyTimer = undefined;\n }\n if (modal.style.display === 'block') modal.style.pointerEvents = 'auto';\n return;\n }\n readyModes.add(sourceMode);\n if (readyModes.has('stage') && readyModes.has('controls') && !initialFramesReady) {\n initialFramesReady = true;\n if (readyTimer !== undefined) {\n windowObject.clearTimeout(readyTimer);\n readyTimer = undefined;\n }\n controls.style.pointerEvents = 'auto';\n resolveInitialFrames?.();\n }\n return;\n }\n if (message.action === 'resize-controls' && fromControls) {\n if (\n typeof message.width !== 'number' ||\n !Number.isInteger(message.width) ||\n message.width < CONTROLS_MIN_SIZE ||\n message.width > CONTROLS_MAX_WIDTH ||\n typeof message.height !== 'number' ||\n !Number.isInteger(message.height) ||\n message.height < CONTROLS_MIN_SIZE ||\n message.height > CONTROLS_MAX_HEIGHT\n ) {\n return;\n }\n controlsRequestedWidth = message.width;\n controlsRequestedHeight = message.height;\n applyControlsSize();\n }\n if (message.action === 'request-anchor') {\n postAnchor(fromModal ? modal : fromStage ? stage : controls);\n }\n if (message.action === 'open-modal' && fromControls) {\n if (!initialFramesReady) return;\n if (modal.getAttribute('src') === 'about:blank') {\n modalAttempt += 1;\n modalFrameToken = String(modalAttempt);\n const modalUrl = new URL(modal.dataset.src ?? 'about:blank');\n modalUrl.searchParams.set('frameToken', modalFrameToken);\n modal.src = modalUrl.toString();\n }\n modal.style.display = 'block';\n modal.style.pointerEvents = modalReady ? 'auto' : 'none';\n if (!modalReady) {\n if (modalReadyTimer !== undefined) windowObject.clearTimeout(modalReadyTimer);\n modalReadyTimer = windowObject.setTimeout(() => hideModal(true), FRAME_READY_TIMEOUT_MS);\n }\n }\n if (message.action === 'close-modal' && (fromModal || fromControls)) {\n hideModal(!modalReady);\n }\n };\n\n const locationPoll = windowObject.setInterval(refreshAnchor, LOCATION_POLL_MS);\n const cleanup = (): void => {\n if (destroyed) return;\n destroyed = true;\n if (anchorTimer !== undefined) windowObject.clearTimeout(anchorTimer);\n if (readyTimer !== undefined) windowObject.clearTimeout(readyTimer);\n if (modalReadyTimer !== undefined) windowObject.clearTimeout(modalReadyTimer);\n windowObject.clearInterval(locationPoll);\n windowObject.removeEventListener('message', onMessage);\n windowObject.removeEventListener('scroll', scheduleAnchorRefresh);\n windowObject.removeEventListener('resize', handleWindowResize);\n windowObject.removeEventListener('popstate', scheduleAnchorRefresh);\n windowObject.removeEventListener('hashchange', scheduleAnchorRefresh);\n stage.removeEventListener('load', frameLoaded);\n controls.removeEventListener('load', frameLoaded);\n modal.removeEventListener('load', frameLoaded);\n portal.remove();\n };\n\n windowObject.addEventListener('message', onMessage);\n windowObject.addEventListener('scroll', scheduleAnchorRefresh, { passive: true });\n windowObject.addEventListener('resize', handleWindowResize);\n windowObject.addEventListener('popstate', scheduleAnchorRefresh);\n windowObject.addEventListener('hashchange', scheduleAnchorRefresh);\n try {\n options.target.appendChild(portal);\n postAnchorToMountedFrames();\n await initialFrameReadiness;\n } catch (error) {\n cleanup();\n throw error;\n }\n\n return {\n capability: 'danmaku',\n destroy: cleanup,\n };\n}\n","import type { ViceMeClient } from '../core/client.ts';\nimport { mount } from './mount.ts';\n\nexport interface DanmakuMountOptions {\n target: Element;\n theme: 'light' | 'dark' | 'auto';\n}\n\nexport interface DanmakuMountHandle {\n readonly capability: 'danmaku';\n destroy(): void;\n}\n\nconst mounts = new WeakMap<ViceMeClient, WeakMap<Element, Promise<DanmakuMountHandle>>>();\n\n/** Explicit ESM/npm entry point; the CDN loader calls the same mount function. */\nexport function mountDanmaku(\n client: ViceMeClient,\n options: DanmakuMountOptions,\n): Promise<DanmakuMountHandle> {\n let byTarget = mounts.get(client);\n if (!byTarget) {\n byTarget = new WeakMap();\n mounts.set(client, byTarget);\n }\n const existing = byTarget.get(options.target);\n if (existing) return existing;\n\n const pending: Promise<DanmakuMountHandle> = mount(client, options)\n .then((raw) => {\n let destroyed = false;\n return {\n capability: 'danmaku' as const,\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n if (byTarget.get(options.target) === pending) byTarget.delete(options.target);\n raw.destroy();\n },\n };\n })\n .catch((error: unknown) => {\n if (byTarget.get(options.target) === pending) byTarget.delete(options.target);\n throw error;\n });\n byTarget.set(options.target, pending);\n return pending;\n}\n"],"names":["BUILD_WIDGET_ORIGINS","readDanmakuPageAnchor","windowObject","documentObject","pageUrl","canonicalPageUrl","bucket","scrollBucket","hashString","canonical","rawUrl","url","root","body","scrollTop","scrollHeight","maxScroll","percent","start","value","high","low","index","character","CONTROLS_MIN_SIZE","CONTROLS_BAR_HEIGHT","CONTROLS_MAX_HEIGHT","CONTROLS_MAX_WIDTH","ANCHOR_DEBOUNCE_MS","LOCATION_POLL_MS","FRAME_READY_TIMEOUT_MS","mount","client","options","ViceMeError","widgetOrigin","currentAnchor","locale","destroyed","anchorTimer","readyTimer","modalReadyTimer","initialFramesReady","modalAttempt","modalFrameToken","modalReady","loadedFrames","readyModes","portal","shadow","frameUrl","mode","SDK_VERSION","createFrame","title","source","frame","stage","controls","controlsRequestedWidth","controlsRequestedHeight","applyControlsSize","viewportWidth","modal","postAnchor","postAnchorToMountedFrames","refreshAnchor","next","scheduleAnchorRefresh","handleWindowResize","frameLoaded","event","hideModal","resetFrame","resolveInitialFrames","initialFrameReadiness","resolve","reject","onMessage","fromStage","fromControls","fromModal","message","sourceMode","modalUrl","locationPoll","cleanup","error","mounts","mountDanmaku","byTarget","existing","pending","raw"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"danmaku.js","sources":["../src/danmaku/anchor.ts","../src/danmaku/mount.ts","../src/danmaku/index.ts"],"sourcesContent":["export interface DanmakuPageAnchor {\n /** Stable page-and-position key sent to the hosted danmaku runtime. */\n anchorKey: string;\n /** Human-readable 10% scroll bucket, useful for diagnostics. */\n scrollBucket: string;\n}\n\n/**\n * Build a stable page-position anchor without exposing the page URL.\n *\n * Canonical URLs and SPA hash routes participate in the local hash. Only the\n * resulting opaque key leaves the host page.\n */\nexport function readDanmakuPageAnchor(\n windowObject: Window = window,\n documentObject: Document = document,\n): DanmakuPageAnchor {\n const pageUrl = canonicalPageUrl(windowObject, documentObject);\n const bucket = scrollBucket(windowObject, documentObject);\n return {\n anchorKey: `page:${hashString(pageUrl)}:scroll:${bucket}`,\n scrollBucket: bucket,\n };\n}\n\nfunction canonicalPageUrl(windowObject: Window, documentObject: Document): string {\n const canonical = documentObject.querySelector<HTMLLinkElement>('link[rel=\"canonical\"][href]');\n const rawUrl = canonical?.href || windowObject.location.href;\n try {\n const url = new URL(rawUrl, windowObject.location.href);\n url.username = '';\n url.password = '';\n if (canonical && !url.hash && windowObject.location.hash) {\n url.hash = windowObject.location.hash;\n }\n return url.toString();\n } catch {\n return windowObject.location.href;\n }\n}\n\nfunction scrollBucket(windowObject: Window, documentObject: Document): string {\n const root = documentObject.documentElement;\n const body = documentObject.body;\n const scrollTop =\n windowObject.scrollY || windowObject.pageYOffset || root.scrollTop || body?.scrollTop || 0;\n const scrollHeight = Math.max(\n root.scrollHeight,\n root.offsetHeight,\n root.clientHeight,\n body?.scrollHeight ?? 0,\n body?.offsetHeight ?? 0,\n );\n const maxScroll = Math.max(0, scrollHeight - windowObject.innerHeight);\n if (maxScroll <= 1) return '0-100';\n\n const percent = Math.max(0, Math.min(99, (scrollTop / maxScroll) * 100));\n const start = Math.min(90, Math.floor(percent / 10) * 10);\n return `${start}-${start + 10}`;\n}\n\n/** Deterministic 64-bit-style hash encoded as at most 16 base36 characters. */\nfunction hashString(value: string): string {\n let high = 0xdeadbeef ^ value.length;\n let low = 0x41c6ce57 ^ value.length;\n for (let index = 0; index < value.length; index += 1) {\n const character = value.charCodeAt(index);\n high = Math.imul(high ^ character, 2654435761);\n low = Math.imul(low ^ character, 1597334677);\n }\n high = Math.imul(high ^ (high >>> 16), 2246822507);\n high ^= Math.imul(low ^ (low >>> 13), 3266489909);\n low = Math.imul(low ^ (low >>> 16), 2246822507);\n low ^= Math.imul(high ^ (high >>> 13), 3266489909);\n return (\n (low >>> 0).toString(36).padStart(7, '0') + (high >>> 0).toString(36).padStart(7, '0')\n ).slice(0, 16);\n}\n","import type { ViceMeClient } from '../core/client.ts';\nimport { BUILD_WIDGET_ORIGINS } from '../core/build-endpoints.ts';\nimport { ViceMeError } from '../core/errors.ts';\nimport type { CapabilityMountHandle, CapabilityMountOptions } from '../loader/mount-handle.ts';\nimport { SDK_VERSION } from '../version.ts';\nimport { readDanmakuPageAnchor, type DanmakuPageAnchor } from './anchor.ts';\n\ntype DanmakuFrameMode = 'stage' | 'controls' | 'modal';\n\ninterface DanmakuBridgeMessage {\n source?: unknown;\n action?: unknown;\n frameToken?: unknown;\n mode?: unknown;\n width?: unknown;\n height?: unknown;\n}\n\nconst CONTROLS_MIN_SIZE = 32;\nconst CONTROLS_BAR_HEIGHT = 56;\nconst CONTROLS_MAX_HEIGHT = 360;\nconst CONTROLS_MAX_WIDTH = 480;\nconst ANCHOR_DEBOUNCE_MS = 120;\nconst LOCATION_POLL_MS = 1_000;\nexport const FRAME_READY_TIMEOUT_MS = 8_000;\n\nexport async function mount(\n client: ViceMeClient,\n options: CapabilityMountOptions,\n): Promise<CapabilityMountHandle> {\n await client.ready();\n if (!client.hasCapability('danmaku')) {\n throw new ViceMeError({\n code: 'CAPABILITY_DISABLED',\n message: 'Danmaku is not available in this SDK build.',\n retryable: false,\n capability: 'danmaku',\n });\n }\n\n const documentObject = options.target.ownerDocument;\n const windowObject = documentObject.defaultView;\n if (!windowObject) {\n throw new ViceMeError({\n code: 'CONFIG_INVALID',\n message: 'Danmaku requires a browser document.',\n retryable: false,\n capability: 'danmaku',\n });\n }\n\n const widgetOrigin = BUILD_WIDGET_ORIGINS[client.region];\n let currentAnchor = readDanmakuPageAnchor(windowObject, documentObject);\n const locale =\n documentObject.documentElement.lang.trim() || windowObject.navigator.language || 'en';\n let destroyed = false;\n let anchorTimer: number | undefined;\n let readyTimer: number | undefined;\n let modalReadyTimer: number | undefined;\n let initialFramesReady = false;\n let modalAttempt = 0;\n let modalFrameToken = '';\n let modalReady = false;\n const loadedFrames = new WeakSet<HTMLIFrameElement>();\n const readyModes = new Set<DanmakuFrameMode>();\n\n const portal = documentObject.createElement('div');\n portal.dataset.vicemeDanmaku = 'mounted';\n portal.style.all = 'initial';\n portal.style.position = 'fixed';\n portal.style.inset = '0';\n portal.style.width = '100%';\n portal.style.height = '100%';\n portal.style.pointerEvents = 'none';\n portal.style.zIndex = '2147483000';\n portal.style.contain = 'layout style size';\n\n const shadow = portal.attachShadow({ mode: 'open' });\n const root = documentObject.createElement('div');\n root.style.boxSizing = 'border-box';\n root.style.position = 'fixed';\n root.style.inset = '0';\n root.style.width = '100%';\n root.style.height = '100%';\n root.style.pointerEvents = 'none';\n shadow.append(root);\n\n const frameUrl = (mode: DanmakuFrameMode): URL => {\n const url = new URL('/embed/danmaku', widgetOrigin);\n url.searchParams.set('mode', mode);\n url.searchParams.set('workKey', client.workKey);\n url.searchParams.set('theme', options.theme);\n url.searchParams.set('locale', locale);\n url.searchParams.set('sdk', SDK_VERSION);\n url.searchParams.set('anchorKey', currentAnchor.anchorKey);\n return url;\n };\n\n const createFrame = (\n mode: DanmakuFrameMode,\n title: string,\n source: string,\n ): HTMLIFrameElement => {\n const frame = documentObject.createElement('iframe');\n frame.title = title;\n frame.src = source;\n frame.loading = 'eager';\n frame.referrerPolicy = 'no-referrer';\n frame.setAttribute('allowtransparency', 'true');\n frame.setAttribute(\n 'sandbox',\n 'allow-forms allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts',\n );\n frame.dataset.mode = mode;\n frame.style.boxSizing = 'border-box';\n frame.style.colorScheme = 'normal';\n frame.style.position = 'fixed';\n frame.style.margin = '0';\n frame.style.border = '0';\n frame.style.background = 'transparent';\n frame.style.width = '100%';\n frame.style.zIndex = '2147483000';\n return frame;\n };\n\n const stage = createFrame('stage', 'ViceMe Danmaku', frameUrl('stage').toString());\n stage.setAttribute('aria-hidden', 'true');\n stage.style.inset = '0';\n stage.style.height = '100%';\n stage.style.pointerEvents = 'none';\n\n const controls = createFrame(\n 'controls',\n 'ViceMe Danmaku controls',\n frameUrl('controls').toString(),\n );\n controls.style.left = '50%';\n controls.style.bottom = 'env(safe-area-inset-bottom, 0px)';\n controls.style.maxWidth = `${CONTROLS_MAX_WIDTH}px`;\n controls.style.transform = 'translateX(-50%)';\n let controlsRequestedWidth = CONTROLS_MAX_WIDTH;\n let controlsRequestedHeight = CONTROLS_BAR_HEIGHT;\n const applyControlsSize = (): void => {\n const viewportWidth = Math.max(\n CONTROLS_MIN_SIZE,\n Math.floor(windowObject.innerWidth || CONTROLS_MAX_WIDTH),\n );\n controls.style.width = `${Math.min(controlsRequestedWidth, viewportWidth)}px`;\n controls.style.height = `${controlsRequestedHeight}px`;\n };\n applyControlsSize();\n controls.style.pointerEvents = 'none';\n\n const modal = createFrame('modal', 'ViceMe Danmaku dialog', 'about:blank');\n modal.dataset.src = frameUrl('modal').toString();\n modal.style.inset = '0';\n modal.style.height = '100%';\n modal.style.display = 'none';\n modal.style.pointerEvents = 'none';\n\n root.append(stage, controls, modal);\n\n const postAnchor = (frame: HTMLIFrameElement): void => {\n if (!loadedFrames.has(frame)) return;\n frame.contentWindow?.postMessage(\n {\n source: 'viceme-danmaku',\n action: 'anchor-change',\n anchorKey: currentAnchor.anchorKey,\n },\n widgetOrigin,\n );\n };\n const postAnchorToMountedFrames = (): void => {\n postAnchor(stage);\n postAnchor(controls);\n if (modal.getAttribute('src') !== 'about:blank') postAnchor(modal);\n };\n\n const refreshAnchor = (): DanmakuPageAnchor => {\n if (destroyed) return currentAnchor;\n const next = readDanmakuPageAnchor(windowObject, documentObject);\n if (next.anchorKey !== currentAnchor.anchorKey) {\n currentAnchor = next;\n postAnchorToMountedFrames();\n }\n return currentAnchor;\n };\n const scheduleAnchorRefresh = (): void => {\n if (anchorTimer !== undefined) windowObject.clearTimeout(anchorTimer);\n anchorTimer = windowObject.setTimeout(refreshAnchor, ANCHOR_DEBOUNCE_MS);\n };\n const handleWindowResize = (): void => {\n applyControlsSize();\n scheduleAnchorRefresh();\n };\n\n const frameLoaded = (event: Event): void => {\n const frame = event.currentTarget as HTMLIFrameElement;\n if (frame.getAttribute('src') === 'about:blank') return;\n loadedFrames.add(frame);\n postAnchor(frame);\n };\n stage.addEventListener('load', frameLoaded);\n controls.addEventListener('load', frameLoaded);\n modal.addEventListener('load', frameLoaded);\n\n const hideModal = (resetFrame = false): void => {\n if (modalReadyTimer !== undefined) {\n windowObject.clearTimeout(modalReadyTimer);\n modalReadyTimer = undefined;\n }\n modal.style.display = 'none';\n modal.style.pointerEvents = 'none';\n if (resetFrame) {\n modalFrameToken = '';\n modalReady = false;\n loadedFrames.delete(modal);\n modal.src = 'about:blank';\n }\n };\n\n let resolveInitialFrames: (() => void) | undefined;\n const initialFrameReadiness = new Promise<void>((resolve, reject) => {\n resolveInitialFrames = resolve;\n readyTimer = windowObject.setTimeout(() => {\n reject(\n new ViceMeError({\n code: 'INTERNAL_ERROR',\n message: 'Hosted danmaku frames did not become ready in time.',\n retryable: true,\n capability: 'danmaku',\n }),\n );\n }, FRAME_READY_TIMEOUT_MS);\n });\n\n const onMessage = (event: MessageEvent): void => {\n if (event.origin !== widgetOrigin) return;\n const fromStage = event.source === stage.contentWindow;\n const fromControls = event.source === controls.contentWindow;\n const fromModal = event.source === modal.contentWindow;\n if (!fromStage && !fromControls && !fromModal) return;\n\n const message = event.data as DanmakuBridgeMessage | null;\n if (!message || message.source !== 'viceme-danmaku') return;\n\n const sourceMode: DanmakuFrameMode = fromModal ? 'modal' : fromStage ? 'stage' : 'controls';\n if (message.action === 'frame-ready') {\n if (message.mode !== sourceMode) return;\n if (sourceMode === 'modal') {\n if (message.frameToken !== modalFrameToken) return;\n modalReady = true;\n if (modalReadyTimer !== undefined) {\n windowObject.clearTimeout(modalReadyTimer);\n modalReadyTimer = undefined;\n }\n if (modal.style.display === 'block') modal.style.pointerEvents = 'auto';\n return;\n }\n readyModes.add(sourceMode);\n if (readyModes.has('stage') && readyModes.has('controls') && !initialFramesReady) {\n initialFramesReady = true;\n if (readyTimer !== undefined) {\n windowObject.clearTimeout(readyTimer);\n readyTimer = undefined;\n }\n controls.style.pointerEvents = 'auto';\n resolveInitialFrames?.();\n }\n return;\n }\n if (message.action === 'resize-controls' && fromControls) {\n if (\n typeof message.width !== 'number' ||\n !Number.isInteger(message.width) ||\n message.width < CONTROLS_MIN_SIZE ||\n message.width > CONTROLS_MAX_WIDTH ||\n typeof message.height !== 'number' ||\n !Number.isInteger(message.height) ||\n message.height < CONTROLS_MIN_SIZE ||\n message.height > CONTROLS_MAX_HEIGHT\n ) {\n return;\n }\n controlsRequestedWidth = message.width;\n controlsRequestedHeight = message.height;\n applyControlsSize();\n }\n if (message.action === 'request-anchor') {\n postAnchor(fromModal ? modal : fromStage ? stage : controls);\n }\n if (message.action === 'open-modal' && fromControls) {\n if (!initialFramesReady) return;\n if (modal.getAttribute('src') === 'about:blank') {\n modalAttempt += 1;\n modalFrameToken = String(modalAttempt);\n const modalUrl = new URL(modal.dataset.src ?? 'about:blank');\n modalUrl.searchParams.set('frameToken', modalFrameToken);\n modal.src = modalUrl.toString();\n }\n modal.style.display = 'block';\n modal.style.pointerEvents = modalReady ? 'auto' : 'none';\n if (!modalReady) {\n if (modalReadyTimer !== undefined) windowObject.clearTimeout(modalReadyTimer);\n modalReadyTimer = windowObject.setTimeout(() => hideModal(true), FRAME_READY_TIMEOUT_MS);\n }\n }\n if (message.action === 'close-modal' && (fromModal || fromControls)) {\n hideModal(!modalReady);\n }\n };\n\n const locationPoll = windowObject.setInterval(refreshAnchor, LOCATION_POLL_MS);\n const cleanup = (): void => {\n if (destroyed) return;\n destroyed = true;\n if (anchorTimer !== undefined) windowObject.clearTimeout(anchorTimer);\n if (readyTimer !== undefined) windowObject.clearTimeout(readyTimer);\n if (modalReadyTimer !== undefined) windowObject.clearTimeout(modalReadyTimer);\n windowObject.clearInterval(locationPoll);\n windowObject.removeEventListener('message', onMessage);\n windowObject.removeEventListener('scroll', scheduleAnchorRefresh);\n windowObject.removeEventListener('resize', handleWindowResize);\n windowObject.removeEventListener('popstate', scheduleAnchorRefresh);\n windowObject.removeEventListener('hashchange', scheduleAnchorRefresh);\n stage.removeEventListener('load', frameLoaded);\n controls.removeEventListener('load', frameLoaded);\n modal.removeEventListener('load', frameLoaded);\n portal.remove();\n };\n\n windowObject.addEventListener('message', onMessage);\n windowObject.addEventListener('scroll', scheduleAnchorRefresh, { passive: true });\n windowObject.addEventListener('resize', handleWindowResize);\n windowObject.addEventListener('popstate', scheduleAnchorRefresh);\n windowObject.addEventListener('hashchange', scheduleAnchorRefresh);\n try {\n options.target.appendChild(portal);\n postAnchorToMountedFrames();\n await initialFrameReadiness;\n } catch (error) {\n cleanup();\n throw error;\n }\n\n return {\n capability: 'danmaku',\n destroy: cleanup,\n };\n}\n","import type { ViceMeClient } from '../core/client.ts';\nimport { mount } from './mount.ts';\n\nexport interface DanmakuMountOptions {\n target: Element;\n theme: 'light' | 'dark' | 'auto';\n}\n\nexport interface DanmakuMountHandle {\n readonly capability: 'danmaku';\n destroy(): void;\n}\n\nconst mounts = new WeakMap<ViceMeClient, WeakMap<Element, Promise<DanmakuMountHandle>>>();\n\n/** Explicit ESM/npm entry point; the CDN loader calls the same mount function. */\nexport function mountDanmaku(\n client: ViceMeClient,\n options: DanmakuMountOptions,\n): Promise<DanmakuMountHandle> {\n let byTarget = mounts.get(client);\n if (!byTarget) {\n byTarget = new WeakMap();\n mounts.set(client, byTarget);\n }\n const existing = byTarget.get(options.target);\n if (existing) return existing;\n\n const pending: Promise<DanmakuMountHandle> = mount(client, options)\n .then((raw) => {\n let destroyed = false;\n return {\n capability: 'danmaku' as const,\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n if (byTarget.get(options.target) === pending) byTarget.delete(options.target);\n raw.destroy();\n },\n };\n })\n .catch((error: unknown) => {\n if (byTarget.get(options.target) === pending) byTarget.delete(options.target);\n throw error;\n });\n byTarget.set(options.target, pending);\n return pending;\n}\n"],"names":["readDanmakuPageAnchor","windowObject","documentObject","pageUrl","canonicalPageUrl","bucket","scrollBucket","hashString","canonical","rawUrl","url","root","body","scrollTop","scrollHeight","maxScroll","percent","start","value","high","low","index","character","CONTROLS_MIN_SIZE","CONTROLS_BAR_HEIGHT","CONTROLS_MAX_HEIGHT","CONTROLS_MAX_WIDTH","ANCHOR_DEBOUNCE_MS","LOCATION_POLL_MS","FRAME_READY_TIMEOUT_MS","mount","client","options","ViceMeError","widgetOrigin","BUILD_WIDGET_ORIGINS","currentAnchor","locale","destroyed","anchorTimer","readyTimer","modalReadyTimer","initialFramesReady","modalAttempt","modalFrameToken","modalReady","loadedFrames","readyModes","portal","shadow","frameUrl","mode","SDK_VERSION","createFrame","title","source","frame","stage","controls","controlsRequestedWidth","controlsRequestedHeight","applyControlsSize","viewportWidth","modal","postAnchor","postAnchorToMountedFrames","refreshAnchor","next","scheduleAnchorRefresh","handleWindowResize","frameLoaded","event","hideModal","resetFrame","resolveInitialFrames","initialFrameReadiness","resolve","reject","onMessage","fromStage","fromControls","fromModal","message","sourceMode","modalUrl","locationPoll","cleanup","error","mounts","mountDanmaku","byTarget","existing","pending","raw"],"mappings":"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"}
|