@levo-so/site-runtime 0.1.113
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 +93 -0
- package/dist/LevoSiteProvider.d.ts +25 -0
- package/dist/LevoSiteProvider.js +23 -0
- package/dist/client.d.ts +26 -0
- package/dist/client.js +14 -0
- package/dist/data/index.d.ts +101 -0
- package/dist/data/index.js +79 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +6 -0
- package/dist/inspector/dom.d.ts +56 -0
- package/dist/inspector/dom.js +224 -0
- package/dist/inspector/editorChannel.d.ts +7 -0
- package/dist/inspector/editorChannel.js +19 -0
- package/dist/inspector/historyWatcher.d.ts +8 -0
- package/dist/inspector/historyWatcher.js +24 -0
- package/dist/inspector/index.d.ts +2 -0
- package/dist/inspector/index.js +191 -0
- package/dist/inspector/messageRouter.d.ts +38 -0
- package/dist/inspector/messageRouter.js +134 -0
- package/dist/inspector/originalsStash.d.ts +12 -0
- package/dist/inspector/originalsStash.js +24 -0
- package/dist/inspector/protocol.d.ts +180 -0
- package/dist/inspector/stagedOverrides.d.ts +28 -0
- package/dist/inspector/stagedOverrides.js +60 -0
- package/dist/inspector/textEditController.d.ts +24 -0
- package/dist/inspector/textEditController.js +62 -0
- package/dist/pageHead.d.ts +75 -0
- package/dist/pageHead.js +102 -0
- package/package.json +47 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
//#region src/inspector/dom.ts
|
|
2
|
+
var e = {
|
|
3
|
+
ring: 99997,
|
|
4
|
+
overlay: 99998,
|
|
5
|
+
label: 99999
|
|
6
|
+
}, t = {
|
|
7
|
+
hover: "#3b82f6",
|
|
8
|
+
hoverBg: "rgba(59,130,246,0.12)",
|
|
9
|
+
hoverLabelBg: "#1d4ed8",
|
|
10
|
+
select: "#16a34a",
|
|
11
|
+
selectGlow: "rgba(22,163,74,0.18)"
|
|
12
|
+
}, n = (e) => {
|
|
13
|
+
let t = e?.getAttribute("data-tsd-source");
|
|
14
|
+
return t ? t.replace(/^\//, "") : null;
|
|
15
|
+
}, r = (e) => Array.from(document.querySelectorAll("[data-tsd-source]")).filter((t) => n(t) === e), i = (e, t) => {
|
|
16
|
+
let n = r(t).indexOf(e);
|
|
17
|
+
return n < 0 ? 0 : n;
|
|
18
|
+
}, a = (e, t = 0) => {
|
|
19
|
+
let n = r(e);
|
|
20
|
+
return n[t] ?? n[0] ?? null;
|
|
21
|
+
}, o = (e, t) => {
|
|
22
|
+
let n = (e.getAttribute("data-staged-key") || "").split(/\s+/).filter(Boolean);
|
|
23
|
+
n.includes(t) || e.setAttribute("data-staged-key", [...n, t].join(" "));
|
|
24
|
+
}, s = (e, t) => {
|
|
25
|
+
let n = (e.getAttribute("data-staged-key") || "").split(/\s+/).filter((e) => e && e !== t);
|
|
26
|
+
n.length ? e.setAttribute("data-staged-key", n.join(" ")) : e.removeAttribute("data-staged-key");
|
|
27
|
+
}, c = (e, t) => {
|
|
28
|
+
let n = Object.entries(t.styles).filter(([e]) => /^-?[a-zA-Z][a-zA-Z0-9-]*$/.test(e)).map(([e, t]) => `${e}:${String(t).replace(/[;{}]/g, "")} !important;`).join("");
|
|
29
|
+
if (!n) return "";
|
|
30
|
+
let r = `[data-staged-key~="${CSS.escape(e)}"]{${n}}`, i = t.media?.replace(/[;{}]/g, "").trim();
|
|
31
|
+
return i ? `@media ${i}{${r}}` : r;
|
|
32
|
+
}, l = (e) => {
|
|
33
|
+
let t = e.tagName.toLowerCase();
|
|
34
|
+
return t === "input" ? {
|
|
35
|
+
checkbox: "Checkbox",
|
|
36
|
+
radio: "Radio button",
|
|
37
|
+
submit: "Button",
|
|
38
|
+
button: "Button",
|
|
39
|
+
range: "Slider",
|
|
40
|
+
file: "File upload"
|
|
41
|
+
}[(e.getAttribute("type") || "text").toLowerCase()] || "Input" : {
|
|
42
|
+
a: "Link",
|
|
43
|
+
button: "Button",
|
|
44
|
+
img: "Image",
|
|
45
|
+
picture: "Image",
|
|
46
|
+
svg: "Icon",
|
|
47
|
+
h1: "Heading",
|
|
48
|
+
h2: "Heading",
|
|
49
|
+
h3: "Heading",
|
|
50
|
+
h4: "Heading",
|
|
51
|
+
h5: "Heading",
|
|
52
|
+
h6: "Heading",
|
|
53
|
+
p: "Text",
|
|
54
|
+
span: "Text",
|
|
55
|
+
strong: "Text",
|
|
56
|
+
em: "Text",
|
|
57
|
+
ul: "List",
|
|
58
|
+
ol: "List",
|
|
59
|
+
li: "List item",
|
|
60
|
+
nav: "Navigation",
|
|
61
|
+
header: "Header",
|
|
62
|
+
footer: "Footer",
|
|
63
|
+
form: "Form",
|
|
64
|
+
label: "Label",
|
|
65
|
+
select: "Dropdown",
|
|
66
|
+
textarea: "Text field",
|
|
67
|
+
video: "Video",
|
|
68
|
+
section: "Section",
|
|
69
|
+
article: "Article",
|
|
70
|
+
main: "Section",
|
|
71
|
+
aside: "Sidebar",
|
|
72
|
+
div: "Container"
|
|
73
|
+
}[t] || `${t.charAt(0).toUpperCase()}${t.slice(1)}`;
|
|
74
|
+
}, u = 36, d = (e) => {
|
|
75
|
+
let t = l(e), n = ((e) => e.replace(/\s+/g, " ").trim())(e.getAttribute("aria-label") || e.getAttribute("alt") || e.getAttribute("title") || e.getAttribute("name") || "");
|
|
76
|
+
return n ? `${t} · ${n.length > u ? `${n.slice(0, u - 1).trimEnd()}…` : n}` : t;
|
|
77
|
+
}, f = (e) => {
|
|
78
|
+
let t = [], n = e;
|
|
79
|
+
for (; n && n.nodeType === 1 && n !== document.body && t.length < 8;) t.unshift(n.tagName.toLowerCase()), n = n.parentElement;
|
|
80
|
+
return t.join(" > ");
|
|
81
|
+
}, p = () => {
|
|
82
|
+
let n = document.createElement("div");
|
|
83
|
+
n.style.cssText = `position:fixed;pointer-events:none;z-index:${e.overlay};background:${t.hoverBg};outline:2px solid ${t.hover};border-radius:2px;display:none`;
|
|
84
|
+
let r = document.createElement("div");
|
|
85
|
+
r.style.cssText = `position:fixed;pointer-events:none;z-index:${e.label};background:${t.hoverLabelBg};color:#fff;font:11px/1.6 ui-monospace,monospace;padding:1px 6px;border-radius:4px;display:none;max-width:70vw;white-space:nowrap;overflow:hidden;text-overflow:ellipsis`;
|
|
86
|
+
let i = document.createElement("div");
|
|
87
|
+
i.style.cssText = `position:fixed;pointer-events:none;z-index:${e.ring};outline:2px solid ${t.select};outline-offset:1px;border-radius:3px;box-shadow:0 0 0 4px ${t.selectGlow};display:none`;
|
|
88
|
+
let a = document.createElement("div");
|
|
89
|
+
return a.style.cssText = `position:fixed;pointer-events:none;z-index:${e.label};background:${t.select};color:#fff;font:11px/1.6 ui-monospace,monospace;padding:1px 6px;border-radius:4px;display:none;max-width:70vw;white-space:nowrap;overflow:hidden;text-overflow:ellipsis`, {
|
|
90
|
+
overlay: n,
|
|
91
|
+
label: r,
|
|
92
|
+
ring: i,
|
|
93
|
+
ringLabel: a
|
|
94
|
+
};
|
|
95
|
+
}, m = (e, t, n) => {
|
|
96
|
+
let r = n.getBoundingClientRect();
|
|
97
|
+
e.style.display = "block", e.style.left = `${r.left}px`, e.style.top = `${r.top}px`, e.style.width = `${r.width}px`, e.style.height = `${r.height}px`, t.style.display = "block", t.textContent = d(n), t.style.left = `${Math.max(4, r.left)}px`, t.style.top = `${r.top > 26 ? r.top - 22 : r.bottom + 4}px`;
|
|
98
|
+
}, h = (e) => {
|
|
99
|
+
let t = (e instanceof Element ? e : null)?.closest("a[href]");
|
|
100
|
+
if (!t || t.target === "_blank") return null;
|
|
101
|
+
let n;
|
|
102
|
+
try {
|
|
103
|
+
n = new URL(t.href, location.href);
|
|
104
|
+
} catch {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
return n.protocol !== "http:" && n.protocol !== "https:" || n.origin === location.origin ? null : n.href;
|
|
108
|
+
}, g = (e) => {
|
|
109
|
+
if (!e.childNodes.length) return !1;
|
|
110
|
+
let t = !1;
|
|
111
|
+
for (let n of e.childNodes) {
|
|
112
|
+
if (n.nodeType !== 3) return !1;
|
|
113
|
+
(n.textContent ?? "").trim() && (t = !0);
|
|
114
|
+
}
|
|
115
|
+
return t;
|
|
116
|
+
}, _ = 2e3, v = (e) => {
|
|
117
|
+
let t = [], r = e;
|
|
118
|
+
for (; r && r.nodeType === 1 && r !== document.body && t.length < 8;) {
|
|
119
|
+
let e = n(r);
|
|
120
|
+
e && t.unshift({
|
|
121
|
+
tag: r.tagName.toLowerCase(),
|
|
122
|
+
text: (r.textContent || "").trim().slice(0, 60),
|
|
123
|
+
source: e
|
|
124
|
+
}), r = r.parentElement;
|
|
125
|
+
}
|
|
126
|
+
return t;
|
|
127
|
+
}, y = (e) => {
|
|
128
|
+
let t = n(e), a = t ? r(t).length : 1, o = t ? i(e, t) : 0, s = t && g(e) ? (e.textContent ?? "").replace(/\s+/g, " ").trim().slice(0, _) : void 0, c = b(e);
|
|
129
|
+
return {
|
|
130
|
+
tag: e.tagName.toLowerCase(),
|
|
131
|
+
classes: typeof e.className == "string" ? e.className.trim() : "",
|
|
132
|
+
text: (e.innerText || "").trim().slice(0, 120),
|
|
133
|
+
label: d(e),
|
|
134
|
+
path: f(e),
|
|
135
|
+
source: t,
|
|
136
|
+
index: o,
|
|
137
|
+
occurrences: a,
|
|
138
|
+
ancestors: v(e),
|
|
139
|
+
...s === void 0 ? {} : { fullText: s },
|
|
140
|
+
...c ? { sourceBinding: c } : {}
|
|
141
|
+
};
|
|
142
|
+
}, b = (e) => {
|
|
143
|
+
let t = e.closest("[data-levo-source]");
|
|
144
|
+
if (!t) return;
|
|
145
|
+
let r = t.getAttribute("data-levo-source") ?? "", a = n(t), o;
|
|
146
|
+
try {
|
|
147
|
+
o = JSON.parse(r);
|
|
148
|
+
} catch {
|
|
149
|
+
o = void 0;
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
raw: r,
|
|
153
|
+
element: {
|
|
154
|
+
source: a ?? "",
|
|
155
|
+
index: a ? i(t, a) : 0
|
|
156
|
+
},
|
|
157
|
+
...o === void 0 ? {} : { config: o }
|
|
158
|
+
};
|
|
159
|
+
}, x = () => Array.from(document.querySelectorAll("[data-levo-source]")).map((e) => {
|
|
160
|
+
let t = e.getAttribute("data-levo-source") ?? "", r = n(e), a;
|
|
161
|
+
try {
|
|
162
|
+
a = JSON.parse(t);
|
|
163
|
+
} catch {
|
|
164
|
+
a = void 0;
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
raw: t,
|
|
168
|
+
element: {
|
|
169
|
+
source: r ?? "",
|
|
170
|
+
index: r ? i(e, r) : 0
|
|
171
|
+
},
|
|
172
|
+
tag: e.tagName.toLowerCase(),
|
|
173
|
+
label: d(e),
|
|
174
|
+
...a === void 0 ? {} : { config: a }
|
|
175
|
+
};
|
|
176
|
+
}), S = 14, C = 2e3, w = 100, T = 48, E = new Set([
|
|
177
|
+
"script",
|
|
178
|
+
"style",
|
|
179
|
+
"template",
|
|
180
|
+
"noscript"
|
|
181
|
+
]), D = (e, t) => t.includes(e) || e.id === "studio-staged" || E.has(e.tagName.toLowerCase()), O = (e) => {
|
|
182
|
+
let t = !1, r = 0, i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map();
|
|
183
|
+
for (let e of Array.from(document.querySelectorAll("[data-tsd-source]"))) {
|
|
184
|
+
let t = n(e);
|
|
185
|
+
if (!t) continue;
|
|
186
|
+
let r = a.get(t) ?? 0;
|
|
187
|
+
i.set(e, r), a.set(t, r + 1);
|
|
188
|
+
}
|
|
189
|
+
let o = (e) => {
|
|
190
|
+
for (let t of e.childNodes) {
|
|
191
|
+
if (t.nodeType !== 3) continue;
|
|
192
|
+
let e = (t.textContent ?? "").replace(/\s+/g, " ").trim();
|
|
193
|
+
if (e) return e.length > T ? `${e.slice(0, T).trimEnd()}…` : e;
|
|
194
|
+
}
|
|
195
|
+
}, s = (a, c) => {
|
|
196
|
+
r++;
|
|
197
|
+
let l = n(a), u = o(a), d = Array.from(a.children).filter((t) => !D(t, e)), f = {
|
|
198
|
+
tag: a.tagName.toLowerCase(),
|
|
199
|
+
...l ? {
|
|
200
|
+
source: l,
|
|
201
|
+
index: i.get(a) ?? 0
|
|
202
|
+
} : {},
|
|
203
|
+
...u === void 0 ? {} : { text: u },
|
|
204
|
+
...a.classList.contains("hidden") ? { hidden: !0 } : {},
|
|
205
|
+
childCount: d.length,
|
|
206
|
+
children: []
|
|
207
|
+
};
|
|
208
|
+
if (c >= S) return d.length && (t = !0), f;
|
|
209
|
+
for (let e of d) {
|
|
210
|
+
if (f.children.length >= w || r >= C) {
|
|
211
|
+
t = !0;
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
f.children.push(s(e, c + 1));
|
|
215
|
+
}
|
|
216
|
+
return f;
|
|
217
|
+
};
|
|
218
|
+
return {
|
|
219
|
+
tree: s(document.body, 0),
|
|
220
|
+
truncated: t
|
|
221
|
+
};
|
|
222
|
+
};
|
|
223
|
+
//#endregion
|
|
224
|
+
export { t as COLOR, o as addStagedKey, O as buildLayersTree, p as createOverlayNodes, c as cssRuleFor, x as enumerateSources, h as externalLinkHref, g as isTextLeaf, a as nodeForSource, r as nodesForSource, m as positionBox, s as removeStagedKey, y as selectedPayload, i as sourceIndex, n as sourceOf };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { IPreviewToEditor } from './protocol';
|
|
2
|
+
export type IEditorChannel = ReturnType<typeof createEditorChannel>;
|
|
3
|
+
export declare const createEditorChannel: () => {
|
|
4
|
+
send: (msg: IPreviewToEditor) => void;
|
|
5
|
+
acceptOrigin: (e: MessageEvent) => boolean;
|
|
6
|
+
};
|
|
7
|
+
//# sourceMappingURL=editorChannel.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/inspector/editorChannel.ts
|
|
2
|
+
var e = () => {
|
|
3
|
+
let e = null;
|
|
4
|
+
return {
|
|
5
|
+
send: (t) => {
|
|
6
|
+
parent.postMessage({
|
|
7
|
+
source: "web-chat-preview",
|
|
8
|
+
...t
|
|
9
|
+
}, e ?? "*");
|
|
10
|
+
},
|
|
11
|
+
acceptOrigin: (t) => {
|
|
12
|
+
if (e === null) e = t.origin;
|
|
13
|
+
else if (t.origin !== e) return !1;
|
|
14
|
+
return !0;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
//#endregion
|
|
19
|
+
export { e as createEditorChannel };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type IHistoryWatcher = ReturnType<typeof createHistoryWatcher>;
|
|
2
|
+
export declare const createHistoryWatcher: (deps: {
|
|
3
|
+
/** Fired AFTER `location.pathname` actually changed (dedup handled here). */
|
|
4
|
+
onPathChange: () => void;
|
|
5
|
+
}) => {
|
|
6
|
+
teardown: () => void;
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=historyWatcher.d.ts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region src/inspector/historyWatcher.ts
|
|
2
|
+
var e = (e) => {
|
|
3
|
+
let t = location.pathname, n = () => {
|
|
4
|
+
location.pathname !== t && (t = location.pathname, e.onPathChange());
|
|
5
|
+
}, r = !1;
|
|
6
|
+
if (!history.pushState.__inspectorPatched) {
|
|
7
|
+
let e = history.pushState, t = history.replaceState, i = function(...t) {
|
|
8
|
+
let r = e.apply(this, t);
|
|
9
|
+
return n(), r;
|
|
10
|
+
}, a = function(...e) {
|
|
11
|
+
let r = t.apply(this, e);
|
|
12
|
+
return n(), r;
|
|
13
|
+
};
|
|
14
|
+
i.__inspectorPatched = !0, i.__orig = e, a.__inspectorPatched = !0, a.__orig = t, history.pushState = i, history.replaceState = a, r = !0;
|
|
15
|
+
}
|
|
16
|
+
return window.addEventListener("popstate", n), { teardown: () => {
|
|
17
|
+
if (window.removeEventListener("popstate", n), r) {
|
|
18
|
+
let e = history.pushState, t = history.replaceState;
|
|
19
|
+
e.__inspectorPatched && e.__orig && (history.pushState = e.__orig), t.__inspectorPatched && t.__orig && (history.replaceState = t.__orig);
|
|
20
|
+
}
|
|
21
|
+
} };
|
|
22
|
+
};
|
|
23
|
+
//#endregion
|
|
24
|
+
export { e as createHistoryWatcher };
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { createOverlayNodes as e, externalLinkHref as t, isTextLeaf as n, positionBox as r, selectedPayload as ee, sourceOf as te } from "./dom.js";
|
|
2
|
+
import { createEditorChannel as ne } from "./editorChannel.js";
|
|
3
|
+
import { createHistoryWatcher as re } from "./historyWatcher.js";
|
|
4
|
+
import { createMessageRouter as ie } from "./messageRouter.js";
|
|
5
|
+
import { createOriginalsStash as i } from "./originalsStash.js";
|
|
6
|
+
import { createStagedOverrides as a } from "./stagedOverrides.js";
|
|
7
|
+
import { createTextEditController as ae } from "./textEditController.js";
|
|
8
|
+
import { useEffect as o } from "react";
|
|
9
|
+
//#region src/inspector/index.tsx
|
|
10
|
+
function s() {
|
|
11
|
+
return o(() => c(), []), null;
|
|
12
|
+
}
|
|
13
|
+
function c() {
|
|
14
|
+
let o = !1, s = null, c = null, l = !1, u = null, d = i(), f = ne(), { overlay: p, label: m, ring: h, ringLabel: g } = e();
|
|
15
|
+
document.body.append(p, m, h, g);
|
|
16
|
+
let _ = [
|
|
17
|
+
p,
|
|
18
|
+
m,
|
|
19
|
+
h,
|
|
20
|
+
g
|
|
21
|
+
], v = null, y = (e) => {
|
|
22
|
+
e && !v ? (v = document.createElement("style"), v.id = "studio-pick-cursor", v.textContent = "*,*::before,*::after{cursor:crosshair !important}", document.head.appendChild(v)) : !e && v && (v.remove(), v = null);
|
|
23
|
+
}, b = (e) => !e || _.includes(e) || e === document.body || e === document.documentElement, x = (e) => {
|
|
24
|
+
if (!e || b(e)) return null;
|
|
25
|
+
let t = te(e) ? e : e.closest("[data-tsd-source]");
|
|
26
|
+
return !t || b(t) || !n(t) ? null : t;
|
|
27
|
+
}, S = (e) => r(p, m, e), C = () => {
|
|
28
|
+
if (c) {
|
|
29
|
+
if (!c.isConnected) {
|
|
30
|
+
M();
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
r(h, g, c);
|
|
34
|
+
}
|
|
35
|
+
}, w = 0, T = () => {
|
|
36
|
+
w || !c || l || (w = requestAnimationFrame(() => {
|
|
37
|
+
w = 0, C();
|
|
38
|
+
}));
|
|
39
|
+
}, E = new ResizeObserver(T), D = new MutationObserver((e) => {
|
|
40
|
+
for (let t of e) {
|
|
41
|
+
let e = t.target;
|
|
42
|
+
if (!_.some((t) => t === e) && !(t.type === "attributes" && t.attributeName === "data-staged-key")) {
|
|
43
|
+
T(), I.scheduleReapply();
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}), O = !1, k = () => {
|
|
48
|
+
O ||= (D.observe(document.documentElement, {
|
|
49
|
+
attributes: !0,
|
|
50
|
+
childList: !0,
|
|
51
|
+
characterData: !0,
|
|
52
|
+
subtree: !0
|
|
53
|
+
}), !0);
|
|
54
|
+
}, A = () => {
|
|
55
|
+
O &&= (D.disconnect(), !1);
|
|
56
|
+
}, j = () => {
|
|
57
|
+
E.disconnect(), c?.isConnected && (E.observe(c), k());
|
|
58
|
+
}, M = () => {
|
|
59
|
+
c = null, E.disconnect(), L(), w &&= (cancelAnimationFrame(w), 0), h.style.display = "none", g.style.display = "none";
|
|
60
|
+
}, N = (e) => S(e), P = () => {
|
|
61
|
+
p.style.display = "none", m.style.display = "none";
|
|
62
|
+
}, F = ae({
|
|
63
|
+
channel: f,
|
|
64
|
+
originals: d,
|
|
65
|
+
clearTextHover: () => {
|
|
66
|
+
u = null, P();
|
|
67
|
+
}
|
|
68
|
+
}), I = a({
|
|
69
|
+
originals: d,
|
|
70
|
+
editingNode: F.editingNode
|
|
71
|
+
}), L = () => {
|
|
72
|
+
c?.isConnected || I.count() ? k() : A();
|
|
73
|
+
}, R = (e) => {
|
|
74
|
+
e && l && z(!1), o = !!e, y(o), o || (s = null, p.style.display = "none", m.style.display = "none"), f.send({
|
|
75
|
+
type: "inspect-state",
|
|
76
|
+
enabled: o
|
|
77
|
+
});
|
|
78
|
+
}, z = (e) => {
|
|
79
|
+
l = !!e, l ? (o && R(!1), h.style.display = "none", g.style.display = "none") : (F.commitIfEditing(), P(), document.documentElement.style.cursor = "", c && C()), f.send({
|
|
80
|
+
type: "text-edit-state",
|
|
81
|
+
enabled: l
|
|
82
|
+
});
|
|
83
|
+
}, B = 0, V = 0, H = 0, oe = () => {
|
|
84
|
+
B = 0;
|
|
85
|
+
let e = document.elementFromPoint(V, H);
|
|
86
|
+
if (!b(e)) {
|
|
87
|
+
if (l) {
|
|
88
|
+
let t = x(e);
|
|
89
|
+
if (t && t === F.editingNode()) {
|
|
90
|
+
u = null, P(), document.documentElement.style.cursor = "";
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
u = t, document.documentElement.style.cursor = t ? "text" : "", t ? N(t) : P();
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
o && (s = e, e && S(e));
|
|
97
|
+
}
|
|
98
|
+
}, U = (e) => {
|
|
99
|
+
!o && !l || (V = e.clientX, H = e.clientY, B ||= requestAnimationFrame(oe));
|
|
100
|
+
}, W = 0, se = () => {
|
|
101
|
+
W = 0, o && s && S(s), l && !F.editingNode() && u?.isConnected && N(u), c && !l && C();
|
|
102
|
+
}, G = () => {
|
|
103
|
+
W ||= requestAnimationFrame(se);
|
|
104
|
+
}, K = (e) => {
|
|
105
|
+
let n = t(e.target);
|
|
106
|
+
return n ? (e.preventDefault(), e.stopPropagation(), window.open(n, "_blank", "noopener,noreferrer"), !0) : !1;
|
|
107
|
+
}, q = (e) => {
|
|
108
|
+
if (l) {
|
|
109
|
+
let t = x(document.elementFromPoint(e.clientX, e.clientY) || e.target);
|
|
110
|
+
if (!t || t === F.editingNode()) {
|
|
111
|
+
K(e);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
e.preventDefault(), e.stopPropagation(), e.stopImmediatePropagation(), F.startEdit(t);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (!o) {
|
|
118
|
+
K(e);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
e.preventDefault(), e.stopPropagation(), e.stopImmediatePropagation();
|
|
122
|
+
let t = s || e.target;
|
|
123
|
+
if (b(t)) return;
|
|
124
|
+
let n = t.closest("[data-tsd-source]") || t;
|
|
125
|
+
c = n, C(), j(), f.send({
|
|
126
|
+
type: "element-selected",
|
|
127
|
+
element: ee(n)
|
|
128
|
+
});
|
|
129
|
+
}, J = ie({
|
|
130
|
+
channel: f,
|
|
131
|
+
originals: d,
|
|
132
|
+
staged: I,
|
|
133
|
+
setInspect: R,
|
|
134
|
+
setTextEdit: z,
|
|
135
|
+
isInspecting: () => o,
|
|
136
|
+
isTextEditing: () => l,
|
|
137
|
+
editingNode: F.editingNode,
|
|
138
|
+
setSelected: (e) => {
|
|
139
|
+
c = e, j();
|
|
140
|
+
},
|
|
141
|
+
positionSelected: C,
|
|
142
|
+
clearSelection: M,
|
|
143
|
+
syncDomObserver: L,
|
|
144
|
+
positionHover: S,
|
|
145
|
+
hideTextHover: P,
|
|
146
|
+
startEditAtEnd: (e) => F.startEdit(e, !0),
|
|
147
|
+
editableTarget: x,
|
|
148
|
+
ownNodes: _
|
|
149
|
+
}), Y = [
|
|
150
|
+
"mousedown",
|
|
151
|
+
"mouseup",
|
|
152
|
+
"dblclick",
|
|
153
|
+
"auxclick",
|
|
154
|
+
"pointerdown",
|
|
155
|
+
"pointerup",
|
|
156
|
+
"mouseover",
|
|
157
|
+
"mouseout",
|
|
158
|
+
"mouseenter",
|
|
159
|
+
"mouseleave",
|
|
160
|
+
"pointerover",
|
|
161
|
+
"pointerout",
|
|
162
|
+
"pointerenter",
|
|
163
|
+
"pointerleave",
|
|
164
|
+
"touchstart",
|
|
165
|
+
"touchend",
|
|
166
|
+
"submit"
|
|
167
|
+
], X = (e) => {
|
|
168
|
+
o && (e.cancelable && e.preventDefault(), e.stopPropagation(), e.stopImmediatePropagation());
|
|
169
|
+
}, Z = () => {
|
|
170
|
+
c && !l && C();
|
|
171
|
+
}, Q = () => {
|
|
172
|
+
let e = location.pathname.replace(/\/$/, "") || "/";
|
|
173
|
+
f.send({
|
|
174
|
+
type: "route",
|
|
175
|
+
route: e
|
|
176
|
+
});
|
|
177
|
+
}, ce = re({ onPathChange: () => {
|
|
178
|
+
M(), Q();
|
|
179
|
+
} }), $ = (e) => {
|
|
180
|
+
e.key !== "Escape" || F.editingNode() || (l ? z(!1) : o && R(!1));
|
|
181
|
+
};
|
|
182
|
+
window.addEventListener("mousemove", U, !0), window.addEventListener("scroll", G, !0), window.addEventListener("resize", Z), window.addEventListener("click", q, !0), window.addEventListener("keydown", $, !0), window.addEventListener("message", J.onMessage);
|
|
183
|
+
for (let e of Y) window.addEventListener(e, X, !0);
|
|
184
|
+
return Q(), f.send({ type: "ready" }), () => {
|
|
185
|
+
window.removeEventListener("mousemove", U, !0), window.removeEventListener("keydown", $, !0), window.removeEventListener("scroll", G, !0), window.removeEventListener("resize", Z), window.removeEventListener("click", q, !0), window.removeEventListener("message", J.onMessage);
|
|
186
|
+
for (let e of Y) window.removeEventListener(e, X, !0);
|
|
187
|
+
E.disconnect(), D.disconnect(), w && cancelAnimationFrame(w), B && cancelAnimationFrame(B), W && cancelAnimationFrame(W), I.teardown(), ce.teardown(), F.teardown(), document.documentElement.style.cursor = "", v?.remove(), p.remove(), m.remove(), h.remove(), g.remove();
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
//#endregion
|
|
191
|
+
export { s as Inspector };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { IEditorChannel } from './editorChannel';
|
|
2
|
+
import { IOriginalsStash } from './originalsStash';
|
|
3
|
+
import { IStagedOverrides } from './stagedOverrides';
|
|
4
|
+
export interface IMessageRouterContext {
|
|
5
|
+
channel: IEditorChannel;
|
|
6
|
+
originals: IOriginalsStash;
|
|
7
|
+
staged: IStagedOverrides;
|
|
8
|
+
/** Enter/exit select mode (mutual exclusion + state echo live in the setter). */
|
|
9
|
+
setInspect: (on: boolean) => void;
|
|
10
|
+
/** Enter/exit text mode (mutual exclusion + state echo live in the setter). */
|
|
11
|
+
setTextEdit: (on: boolean) => void;
|
|
12
|
+
isInspecting: () => boolean;
|
|
13
|
+
isTextEditing: () => boolean;
|
|
14
|
+
/** The node currently in contenteditable, or null. */
|
|
15
|
+
editingNode: () => Element | null;
|
|
16
|
+
/** Adopt `node` as the persistent selection (ring bookkeeping + observers re-arm). */
|
|
17
|
+
setSelected: (node: Element) => void;
|
|
18
|
+
/** Redraw the selection ring (internally drops a disconnected selection). */
|
|
19
|
+
positionSelected: () => void;
|
|
20
|
+
/** Drop the persistent selection + its ring. */
|
|
21
|
+
clearSelection: () => void;
|
|
22
|
+
/** Re-arbitrate the document-wide MutationObserver (selection OR staged need it). */
|
|
23
|
+
syncDomObserver: () => void;
|
|
24
|
+
/** Draw the transient hover outline + label on `el`. */
|
|
25
|
+
positionHover: (el: Element) => void;
|
|
26
|
+
/** Hide the transient hover outline + label. */
|
|
27
|
+
hideTextHover: () => void;
|
|
28
|
+
/** Begin an in-place text edit on `el`, caret at the end (programmatic start). */
|
|
29
|
+
startEditAtEnd: (el: Element) => void;
|
|
30
|
+
/** The nearest editable text-leaf for `el`, or null (mirrors the click-path test). */
|
|
31
|
+
editableTarget: (el: Element | null) => Element | null;
|
|
32
|
+
/** The runtime's own overlay artifacts, skipped by the layers snapshot. */
|
|
33
|
+
ownNodes: readonly Element[];
|
|
34
|
+
}
|
|
35
|
+
export declare const createMessageRouter: (ctx: IMessageRouterContext) => {
|
|
36
|
+
onMessage: (e: MessageEvent) => void;
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=messageRouter.d.ts.map
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { buildLayersTree as e, enumerateSources as t, nodeForSource as n, selectedPayload as r } from "./dom.js";
|
|
2
|
+
//#region src/inspector/messageRouter.ts
|
|
3
|
+
var i = (i) => {
|
|
4
|
+
let { channel: a, originals: o, staged: s } = i, c = a.send, l = null;
|
|
5
|
+
return { onMessage: (u) => {
|
|
6
|
+
let d = u.data;
|
|
7
|
+
if (!(!d || d.source !== "web-chat") && a.acceptOrigin(u)) {
|
|
8
|
+
if (d.type === "set-inspect") i.setInspect(d.enabled);
|
|
9
|
+
else if (d.type === "set-text-edit") i.setTextEdit(d.enabled);
|
|
10
|
+
else if (d.type === "revert-text") {
|
|
11
|
+
let e = String(d.element?.source || ""), t = Number.isInteger(d.element?.index) ? d.element.index : 0, r = o.restore(`${e}#${t}`), i = r == null ? null : n(e, t);
|
|
12
|
+
i && r != null && (i.textContent = r);
|
|
13
|
+
} else if (d.type === "stage-style") {
|
|
14
|
+
let e = String(d.stageId || ""), t = String(d.element?.source || ""), n = Number.isInteger(d.element?.index) ? d.element.index : 0, r = d.styles && typeof d.styles == "object" ? d.styles : null;
|
|
15
|
+
if (!e || /\s/.test(e) || !t || !r) return;
|
|
16
|
+
let a = {
|
|
17
|
+
kind: "style",
|
|
18
|
+
source: t,
|
|
19
|
+
index: n,
|
|
20
|
+
styles: r,
|
|
21
|
+
media: typeof d.media == "string" && d.media.trim() ? d.media : void 0
|
|
22
|
+
};
|
|
23
|
+
s.upsert(e, a), i.syncDomObserver(), c({
|
|
24
|
+
type: "staged-ack",
|
|
25
|
+
stageId: e
|
|
26
|
+
});
|
|
27
|
+
} else if (d.type === "stage-text") {
|
|
28
|
+
let e = String(d.stageId || ""), t = String(d.element?.source || ""), n = Number.isInteger(d.element?.index) ? d.element.index : 0;
|
|
29
|
+
if (!e || /\s/.test(e) || !t || typeof d.value != "string") return;
|
|
30
|
+
let r = {
|
|
31
|
+
kind: "text",
|
|
32
|
+
source: t,
|
|
33
|
+
index: n,
|
|
34
|
+
value: d.value
|
|
35
|
+
};
|
|
36
|
+
s.upsert(e, r), i.syncDomObserver(), c({
|
|
37
|
+
type: "staged-ack",
|
|
38
|
+
stageId: e
|
|
39
|
+
});
|
|
40
|
+
} else if (d.type === "clear-staged") {
|
|
41
|
+
if (d.stageId == null) {
|
|
42
|
+
let e = s.ids();
|
|
43
|
+
s.clearAll();
|
|
44
|
+
for (let t of e) c({
|
|
45
|
+
type: "staged-ack",
|
|
46
|
+
stageId: t
|
|
47
|
+
});
|
|
48
|
+
} else {
|
|
49
|
+
let e = String(d.stageId);
|
|
50
|
+
s.clearOne(e), c({
|
|
51
|
+
type: "staged-ack",
|
|
52
|
+
stageId: e
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
i.syncDomObserver();
|
|
56
|
+
} else if (d.type === "select-element") {
|
|
57
|
+
let e = String(d.element?.source || ""), t = Number.isInteger(d.element?.index) ? d.element.index : 0, a = e ? n(e, t) : null;
|
|
58
|
+
if (!a) {
|
|
59
|
+
c({
|
|
60
|
+
type: "select-miss",
|
|
61
|
+
element: {
|
|
62
|
+
source: e,
|
|
63
|
+
index: t
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
l = null, i.hideTextHover(), i.setSelected(a), i.isTextEditing() || i.positionSelected(), a.scrollIntoView({
|
|
69
|
+
block: "center",
|
|
70
|
+
behavior: "smooth"
|
|
71
|
+
}), c({
|
|
72
|
+
type: "element-selected",
|
|
73
|
+
element: r(a)
|
|
74
|
+
});
|
|
75
|
+
} else if (d.type === "edit-element") {
|
|
76
|
+
let e = String(d.element?.source || ""), t = Number.isInteger(d.element?.index) ? d.element.index : 0, a = e ? n(e, t) : null;
|
|
77
|
+
if (!a) {
|
|
78
|
+
c({
|
|
79
|
+
type: "select-miss",
|
|
80
|
+
element: {
|
|
81
|
+
source: e,
|
|
82
|
+
index: t
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
l = null, i.hideTextHover(), i.setSelected(a), a.scrollIntoView({
|
|
88
|
+
block: "center",
|
|
89
|
+
behavior: "smooth"
|
|
90
|
+
}), c({
|
|
91
|
+
type: "element-selected",
|
|
92
|
+
element: r(a)
|
|
93
|
+
}), i.isTextEditing() || i.setTextEdit(!0);
|
|
94
|
+
let o = i.editableTarget(a);
|
|
95
|
+
o && i.startEditAtEnd(o);
|
|
96
|
+
} else if (d.type === "highlight-element") {
|
|
97
|
+
let e = String(d.element?.source || ""), t = Number.isInteger(d.element?.index) ? d.element.index : 0, r = e ? n(e, t) : null;
|
|
98
|
+
if (!r) l = null, i.hideTextHover(), c({
|
|
99
|
+
type: "highlight-miss",
|
|
100
|
+
element: {
|
|
101
|
+
source: e,
|
|
102
|
+
index: t
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
else {
|
|
106
|
+
l = r, i.positionHover(r);
|
|
107
|
+
let e = r.getBoundingClientRect(), t = window.innerHeight || document.documentElement.clientHeight, n = window.innerWidth || document.documentElement.clientWidth;
|
|
108
|
+
(e.bottom < 0 || e.top > t || e.right < 0 || e.left > n) && r.scrollIntoView({
|
|
109
|
+
block: "center",
|
|
110
|
+
behavior: "smooth"
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
} else if (d.type === "clear-highlight") l && (l = null, !i.isInspecting() && !i.editingNode() && i.hideTextHover());
|
|
114
|
+
else if (d.type === "request-layers") {
|
|
115
|
+
let { tree: t, truncated: n } = e(i.ownNodes);
|
|
116
|
+
c({
|
|
117
|
+
type: "layers-tree",
|
|
118
|
+
tree: t,
|
|
119
|
+
truncated: n
|
|
120
|
+
});
|
|
121
|
+
} else if (d.type === "request-sources") c({
|
|
122
|
+
type: "sources-list",
|
|
123
|
+
sources: t()
|
|
124
|
+
});
|
|
125
|
+
else if (d.type === "clear-selection") i.clearSelection();
|
|
126
|
+
else if (d.type === "navigate") {
|
|
127
|
+
let e = String(d.route || "/");
|
|
128
|
+
/^\/(?!\/)[A-Za-z0-9\-._~/?#[\]@!$&'()*+,;=%]*$/.test(e) && location.assign(e);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
} };
|
|
132
|
+
};
|
|
133
|
+
//#endregion
|
|
134
|
+
export { i as createMessageRouter };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type IOriginalsStash = ReturnType<typeof createOriginalsStash>;
|
|
2
|
+
export declare const createOriginalsStash: () => {
|
|
3
|
+
/** Stash unconditionally (edit start) — a fresh edit re-captures the current text. */
|
|
4
|
+
capture: (key: string, text: string) => void;
|
|
5
|
+
/** Stash only if absent (staged re-apply) — never overwrite the true original. */
|
|
6
|
+
captureOnce: (key: string, text: string) => void;
|
|
7
|
+
/** Peek without consuming — commit keeps the stash for a possible later revert. */
|
|
8
|
+
get: (key: string) => string | undefined;
|
|
9
|
+
/** Consume: return the original AND drop it (cancel / clear-staged / revert-text). */
|
|
10
|
+
restore: (key: string) => string | undefined;
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=originalsStash.d.ts.map
|