@guidelytech/guide-runtime 0.9.0 → 0.11.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/dist/capture.cjs +183 -34
- package/dist/capture.cjs.map +1 -1
- package/dist/capture.js +9 -14
- package/dist/capture.js.map +1 -1
- package/dist/chunk-GUH2PQJ7.js +462 -0
- package/dist/chunk-GUH2PQJ7.js.map +1 -0
- package/dist/chunk-H3CROHPR.js +585 -0
- package/dist/chunk-H3CROHPR.js.map +1 -0
- package/dist/chunk-VJSQM23R.js +359 -0
- package/dist/chunk-VJSQM23R.js.map +1 -0
- package/dist/chunk-VQJ7MZ2K.js +463 -0
- package/dist/chunk-VQJ7MZ2K.js.map +1 -0
- package/dist/index.cjs +501 -121
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +70 -9
- package/dist/index.d.ts +70 -9
- package/dist/index.js +150 -25
- package/dist/index.js.map +1 -1
- package/dist/messenger.cjs +1171 -167
- package/dist/messenger.cjs.map +1 -1
- package/dist/messenger.d.cts +55 -5
- package/dist/messenger.d.ts +55 -5
- package/dist/messenger.js +1029 -96
- package/dist/messenger.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__publicField
|
|
3
|
+
} from "./chunk-PG7CMBHD.js";
|
|
4
|
+
|
|
5
|
+
// src/selectors.ts
|
|
6
|
+
import { matchUrlPattern } from "@guidelytech/shared/runtime";
|
|
7
|
+
function urlMatches(pattern, url) {
|
|
8
|
+
if (!pattern) return true;
|
|
9
|
+
if (matchUrlPattern(pattern, url)) return true;
|
|
10
|
+
try {
|
|
11
|
+
const u = new URL(url, "http://localhost");
|
|
12
|
+
if (!pattern.includes("?") && !pattern.includes("#")) return matchUrlPattern(pattern, u.pathname) || matchUrlPattern(pattern, u.origin + u.pathname);
|
|
13
|
+
} catch {
|
|
14
|
+
}
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
var TEXT_CANDIDATES = "button, a, [role='button'], [role='link'], [role='tab'], [role='menuitem'], h1, h2, h3, h4, h5, h6, label, summary";
|
|
18
|
+
var HOST_ID = "guidely-root";
|
|
19
|
+
function docOf(root) {
|
|
20
|
+
return root.nodeType === 9 ? root : root.ownerDocument;
|
|
21
|
+
}
|
|
22
|
+
function hasLayout(doc) {
|
|
23
|
+
const de = doc.documentElement;
|
|
24
|
+
if (!de) return false;
|
|
25
|
+
const r = de.getBoundingClientRect();
|
|
26
|
+
return r.width > 0 || r.height > 0;
|
|
27
|
+
}
|
|
28
|
+
function normalizeText(text) {
|
|
29
|
+
return (text || "").replace(/\s+/g, " ").trim();
|
|
30
|
+
}
|
|
31
|
+
function isVisible(el) {
|
|
32
|
+
if (!el.isConnected) return false;
|
|
33
|
+
const doc = el.ownerDocument;
|
|
34
|
+
const win = doc.defaultView;
|
|
35
|
+
let cur = el;
|
|
36
|
+
while (cur && cur !== doc.documentElement) {
|
|
37
|
+
if (cur.hidden) return false;
|
|
38
|
+
if (win) {
|
|
39
|
+
const cs = win.getComputedStyle(cur);
|
|
40
|
+
if (cs.display === "none" || cs.visibility === "hidden") return false;
|
|
41
|
+
}
|
|
42
|
+
cur = cur.parentElement ?? cur.getRootNode().host ?? null;
|
|
43
|
+
}
|
|
44
|
+
if (hasLayout(doc)) {
|
|
45
|
+
const r = el.getBoundingClientRect();
|
|
46
|
+
if (r.width === 0 && r.height === 0) return false;
|
|
47
|
+
}
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
function isGuidelyElement(el) {
|
|
51
|
+
if (!el) return false;
|
|
52
|
+
const root = el.getRootNode();
|
|
53
|
+
if (root instanceof ShadowRoot && root.host.id === HOST_ID) return true;
|
|
54
|
+
return el.id === HOST_ID || !!el.closest?.(`#${HOST_ID}`);
|
|
55
|
+
}
|
|
56
|
+
function safeQueryAll(root, selector) {
|
|
57
|
+
try {
|
|
58
|
+
return Array.from(root.querySelectorAll(selector));
|
|
59
|
+
} catch {
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
var SHADOW_SEPARATOR = " >>> ";
|
|
64
|
+
var SHADOW_SPLIT = /\s*>>>\s*/;
|
|
65
|
+
function isShadowRoot(node) {
|
|
66
|
+
return !!node && node.nodeType === 11 && !!node.host;
|
|
67
|
+
}
|
|
68
|
+
function shadowRootOf(el) {
|
|
69
|
+
const root = el.getRootNode?.();
|
|
70
|
+
return isShadowRoot(root) ? root : null;
|
|
71
|
+
}
|
|
72
|
+
function composedParent(el) {
|
|
73
|
+
return el.parentElement ?? shadowRootOf(el)?.host ?? null;
|
|
74
|
+
}
|
|
75
|
+
function containsComposed(ancestor, node) {
|
|
76
|
+
let cur = node ? node.nodeType === 1 ? node : node.parentElement : null;
|
|
77
|
+
for (; cur; cur = composedParent(cur)) if (cur === ancestor) return true;
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
function composedTarget(e) {
|
|
81
|
+
const path = typeof e.composedPath === "function" ? e.composedPath() : [];
|
|
82
|
+
const first = path[0] ?? e.target;
|
|
83
|
+
if (!first) return null;
|
|
84
|
+
return first.nodeType === 1 ? first : first.parentElement;
|
|
85
|
+
}
|
|
86
|
+
var shadowRootCache = null;
|
|
87
|
+
function shadowRootsIn(root) {
|
|
88
|
+
const cached = shadowRootCache?.get(root);
|
|
89
|
+
if (cached) return cached;
|
|
90
|
+
const out = [];
|
|
91
|
+
const visit = (scope) => {
|
|
92
|
+
const own = scope.nodeType === 1 ? scope.shadowRoot : null;
|
|
93
|
+
const hosts = own ? [scope] : [];
|
|
94
|
+
for (const el of safeQueryAll(scope, "*")) if (el.shadowRoot) hosts.push(el);
|
|
95
|
+
for (const host of hosts) {
|
|
96
|
+
if (host.id === HOST_ID || !host.shadowRoot || out.includes(host.shadowRoot)) continue;
|
|
97
|
+
out.push(host.shadowRoot);
|
|
98
|
+
visit(host.shadowRoot);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
visit(root);
|
|
102
|
+
shadowRootCache?.set(root, out);
|
|
103
|
+
return out;
|
|
104
|
+
}
|
|
105
|
+
function queryAllDeep(root, selector) {
|
|
106
|
+
const out = safeQueryAll(root, selector);
|
|
107
|
+
for (const sr of shadowRootsIn(root)) out.push(...safeQueryAll(sr, selector));
|
|
108
|
+
return out;
|
|
109
|
+
}
|
|
110
|
+
function queryCss(root, selector, deep) {
|
|
111
|
+
if (!selector.includes(">>>")) return deep ? queryAllDeep(root, selector) : safeQueryAll(root, selector);
|
|
112
|
+
const steps = selector.split(SHADOW_SPLIT).filter(Boolean);
|
|
113
|
+
let scopes = [root];
|
|
114
|
+
let matches = [];
|
|
115
|
+
steps.forEach((step, i) => {
|
|
116
|
+
matches = Array.from(new Set(scopes.flatMap((scope) => queryAllDeep(scope, step))));
|
|
117
|
+
if (i < steps.length - 1) scopes = matches.map((el) => el.shadowRoot).filter((sr) => !!sr);
|
|
118
|
+
});
|
|
119
|
+
return matches;
|
|
120
|
+
}
|
|
121
|
+
function closestComposed(el, selector) {
|
|
122
|
+
if (selector.includes(">>>")) {
|
|
123
|
+
const hits = new Set(queryCss(docOf(el), selector, true));
|
|
124
|
+
for (let cur = el; cur; cur = composedParent(cur)) if (hits.has(cur)) return cur;
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
for (let cur = el; cur; cur = composedParent(cur)) if (cur.matches(selector)) return cur;
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
function deepElementFromPoint(doc, x, y) {
|
|
131
|
+
let el = doc.elementFromPoint(x, y);
|
|
132
|
+
while (el?.shadowRoot && el.id !== HOST_ID && typeof el.shadowRoot.elementFromPoint === "function") {
|
|
133
|
+
const inner = el.shadowRoot.elementFromPoint(x, y);
|
|
134
|
+
if (!inner || inner === el) break;
|
|
135
|
+
el = inner;
|
|
136
|
+
}
|
|
137
|
+
return el;
|
|
138
|
+
}
|
|
139
|
+
function escapeCss(value) {
|
|
140
|
+
const g = globalThis;
|
|
141
|
+
if (g.CSS && typeof g.CSS.escape === "function") return g.CSS.escape(value);
|
|
142
|
+
return value.replace(/["\\]/g, "\\$&");
|
|
143
|
+
}
|
|
144
|
+
function queryXPath(root, expr) {
|
|
145
|
+
const doc = docOf(root);
|
|
146
|
+
const d = doc;
|
|
147
|
+
if (typeof d.evaluate !== "function") return [];
|
|
148
|
+
try {
|
|
149
|
+
const result = d.evaluate(expr, root, null, 7, null);
|
|
150
|
+
const out = [];
|
|
151
|
+
for (let i = 0; i < result.snapshotLength; i++) {
|
|
152
|
+
const n = result.snapshotItem(i);
|
|
153
|
+
if (n && n.nodeType === 1) out.push(n);
|
|
154
|
+
}
|
|
155
|
+
return out;
|
|
156
|
+
} catch {
|
|
157
|
+
return [];
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function queryText(root, text, deep) {
|
|
161
|
+
const needle = normalizeText(text).toLowerCase();
|
|
162
|
+
if (!needle) return [];
|
|
163
|
+
const candidates = queryCss(root, TEXT_CANDIDATES, deep);
|
|
164
|
+
const exact = candidates.filter((c) => normalizeText(c.textContent).toLowerCase() === needle);
|
|
165
|
+
if (exact.length) return exact;
|
|
166
|
+
return candidates.filter((c) => normalizeText(c.textContent).toLowerCase().includes(needle));
|
|
167
|
+
}
|
|
168
|
+
function querySelectorStrategy(strategy, root, deep = true) {
|
|
169
|
+
const value = strategy.value.trim();
|
|
170
|
+
if (!value) return [];
|
|
171
|
+
switch (strategy.kind) {
|
|
172
|
+
case "id": {
|
|
173
|
+
const id = value.startsWith("#") ? value.slice(1) : value;
|
|
174
|
+
return queryCss(root, `#${escapeCss(id)}`, deep);
|
|
175
|
+
}
|
|
176
|
+
case "guidely-id": {
|
|
177
|
+
const id = value.startsWith("#") ? value.slice(1) : value;
|
|
178
|
+
return queryCss(root, attrSelector("data-guidely-id", id), deep);
|
|
179
|
+
}
|
|
180
|
+
case "data-attr":
|
|
181
|
+
case "aria":
|
|
182
|
+
case "css":
|
|
183
|
+
return queryCss(root, value.startsWith("[") || /^[a-z*#.[]/i.test(value) ? value : `[${value}]`, deep);
|
|
184
|
+
case "text":
|
|
185
|
+
return queryText(root, value, deep);
|
|
186
|
+
case "xpath":
|
|
187
|
+
return queryXPath(root, value);
|
|
188
|
+
default:
|
|
189
|
+
return [];
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function resolveTarget(target, root = document) {
|
|
193
|
+
const selectors = Array.isArray(target) ? target : target.selectors;
|
|
194
|
+
const visibleMatches = (strategy, deep) => querySelectorStrategy(strategy, root, deep).filter((el) => !isGuidelyElement(el) && isVisible(el));
|
|
195
|
+
const outer = shadowRootCache;
|
|
196
|
+
shadowRootCache ?? (shadowRootCache = /* @__PURE__ */ new Map());
|
|
197
|
+
try {
|
|
198
|
+
for (const strategy of selectors) {
|
|
199
|
+
let matches = visibleMatches(strategy, false);
|
|
200
|
+
if (!matches.length && strategy.kind !== "xpath") matches = visibleMatches(strategy, true);
|
|
201
|
+
if (matches.length === 1) return matches[0];
|
|
202
|
+
}
|
|
203
|
+
return null;
|
|
204
|
+
} finally {
|
|
205
|
+
shadowRootCache = outer;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
var TargetTimeoutError = class extends Error {
|
|
209
|
+
constructor(message = "Target element not found before timeout") {
|
|
210
|
+
super(message);
|
|
211
|
+
__publicField(this, "name", "TargetTimeoutError");
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
function waitForTarget(target, options = {}) {
|
|
215
|
+
const timeoutMs = options.timeoutMs ?? 5e3;
|
|
216
|
+
const root = options.root ?? document;
|
|
217
|
+
const pollMs = Math.min(250, Math.max(16, options.pollMs ?? 250));
|
|
218
|
+
return new Promise((resolve, reject) => {
|
|
219
|
+
const immediate = resolveTarget(target, root);
|
|
220
|
+
if (immediate) return resolve(immediate);
|
|
221
|
+
if (options.signal?.aborted) return reject(new DOMException("Aborted", "AbortError"));
|
|
222
|
+
let done = false;
|
|
223
|
+
let observer = null;
|
|
224
|
+
let timer = null;
|
|
225
|
+
let timeout = null;
|
|
226
|
+
const cleanup = () => {
|
|
227
|
+
done = true;
|
|
228
|
+
observer?.disconnect();
|
|
229
|
+
if (timer) clearInterval(timer);
|
|
230
|
+
if (timeout) clearTimeout(timeout);
|
|
231
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
232
|
+
};
|
|
233
|
+
const check = () => {
|
|
234
|
+
if (done) return;
|
|
235
|
+
const el = resolveTarget(target, root);
|
|
236
|
+
if (el) {
|
|
237
|
+
cleanup();
|
|
238
|
+
resolve(el);
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
const onAbort = () => {
|
|
242
|
+
cleanup();
|
|
243
|
+
reject(new DOMException("Aborted", "AbortError"));
|
|
244
|
+
};
|
|
245
|
+
options.signal?.addEventListener("abort", onAbort);
|
|
246
|
+
const observeRoot = root.nodeType === 9 ? root.documentElement : root;
|
|
247
|
+
if (typeof MutationObserver !== "undefined" && observeRoot) {
|
|
248
|
+
observer = new MutationObserver(check);
|
|
249
|
+
observer.observe(observeRoot, { childList: true, subtree: true, attributes: true, attributeFilter: ["class", "style", "hidden", "id", "data-tour", "data-guidely-id", "aria-label"] });
|
|
250
|
+
}
|
|
251
|
+
timer = setInterval(check, pollMs);
|
|
252
|
+
if (timeoutMs > 0) {
|
|
253
|
+
timeout = setTimeout(() => {
|
|
254
|
+
cleanup();
|
|
255
|
+
reject(new TargetTimeoutError());
|
|
256
|
+
}, timeoutMs);
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
var GENERATED_ID = /(\d{4,}|:r[0-9a-z]+:|^radix-|^headlessui-|^mui-|^ember\d|^react-|^\w*-\d+$|__|^[a-f0-9]{8,}$|^svelte-)/i;
|
|
261
|
+
var GENERATED_CLASS = /(^css-|^sc-|^jss\d|^svelte-|^emotion-|^chakra-|^Mui|^_|[0-9a-f]{6,}|^\w{1,2}$|^[a-z]+-\d+$|[:[\]/])/;
|
|
262
|
+
var PREFERRED_DATA_ATTRS = ["data-testid", "data-tour", "data-test", "data-test-id", "data-cy", "data-qa", "data-id", "data-name", "data-guidely"];
|
|
263
|
+
var IGNORED_DATA_ATTRS = /^data-(guidely-id|state|v-|reactid|react|radix|headlessui|svelte|hydrated|orientation|highlighted|focus|key|index|rbd|dnd|rk-|sveltekit)/i;
|
|
264
|
+
function isStableId(id) {
|
|
265
|
+
return !!id && /^[A-Za-z][\w-]*$/.test(id) && !GENERATED_ID.test(id);
|
|
266
|
+
}
|
|
267
|
+
function isStableClass(cls) {
|
|
268
|
+
return !!cls && !GENERATED_CLASS.test(cls) && cls.length <= 40;
|
|
269
|
+
}
|
|
270
|
+
function uniqueWithin(root, selector, el) {
|
|
271
|
+
const all = safeQueryAll(root, selector);
|
|
272
|
+
return all.length === 1 && all[0] === el;
|
|
273
|
+
}
|
|
274
|
+
function attrSelector(name, value) {
|
|
275
|
+
return `[${name}='${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}']`;
|
|
276
|
+
}
|
|
277
|
+
function cssPath(el, root) {
|
|
278
|
+
const doc = el.ownerDocument;
|
|
279
|
+
const segments = [];
|
|
280
|
+
let cur = el;
|
|
281
|
+
while (cur && cur.nodeType === 1 && cur !== doc.body && cur !== doc.documentElement) {
|
|
282
|
+
const tag = cur.tagName.toLowerCase();
|
|
283
|
+
if (isStableId(cur.id)) {
|
|
284
|
+
segments.unshift(`#${cur.id}`);
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
let seg = tag;
|
|
288
|
+
const parent = cur.parentElement;
|
|
289
|
+
if (parent) {
|
|
290
|
+
const sameTag = Array.from(parent.children).filter((c) => c.tagName === cur.tagName);
|
|
291
|
+
if (sameTag.length > 1) {
|
|
292
|
+
const stableCls = Array.from(cur.classList).find((c) => isStableClass(c) && sameTag.filter((s) => s.classList.contains(c)).length === 1);
|
|
293
|
+
seg += stableCls ? `.${escapeCss(stableCls)}` : `:nth-of-type(${sameTag.indexOf(cur) + 1})`;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
segments.unshift(seg);
|
|
297
|
+
const candidate = segments.join(" > ");
|
|
298
|
+
if (uniqueWithin(root, candidate, el)) return candidate;
|
|
299
|
+
cur = parent;
|
|
300
|
+
}
|
|
301
|
+
const full = segments.join(" > ");
|
|
302
|
+
return uniqueWithin(root, full, el) ? full : null;
|
|
303
|
+
}
|
|
304
|
+
function shadowHostChain(el) {
|
|
305
|
+
const steps = [];
|
|
306
|
+
for (let root = shadowRootOf(el); root; root = shadowRootOf(root.host)) {
|
|
307
|
+
const host = root.host;
|
|
308
|
+
const step = cssPath(host, shadowRootOf(host) ?? host.ownerDocument);
|
|
309
|
+
if (!step) return null;
|
|
310
|
+
steps.unshift(step);
|
|
311
|
+
}
|
|
312
|
+
return steps.join(SHADOW_SEPARATOR);
|
|
313
|
+
}
|
|
314
|
+
function selectorFor(el, selector) {
|
|
315
|
+
const root = shadowRootOf(el);
|
|
316
|
+
if (!root) return uniqueWithin(el.ownerDocument, selector, el) ? selector : null;
|
|
317
|
+
if (!uniqueWithin(root, selector, el)) return null;
|
|
318
|
+
const doc = el.ownerDocument;
|
|
319
|
+
const only = (sel) => {
|
|
320
|
+
const all = queryCss(doc, sel, true);
|
|
321
|
+
return all.length === 1 && all[0] === el;
|
|
322
|
+
};
|
|
323
|
+
if (only(selector)) return selector;
|
|
324
|
+
const chain = shadowHostChain(el);
|
|
325
|
+
const scoped = chain ? chain + SHADOW_SEPARATOR + selector : null;
|
|
326
|
+
return scoped && only(scoped) ? scoped : null;
|
|
327
|
+
}
|
|
328
|
+
function shadowText(el) {
|
|
329
|
+
if (!el.shadowRoot) return "";
|
|
330
|
+
const parts = Array.from(el.shadowRoot.children).filter((c) => !/^(STYLE|SCRIPT|TEMPLATE)$/.test(c.tagName));
|
|
331
|
+
return normalizeText(parts.map((c) => c.innerText ?? c.textContent).join(" "));
|
|
332
|
+
}
|
|
333
|
+
function textSnapshotOf(el) {
|
|
334
|
+
const he = el;
|
|
335
|
+
const own = normalizeText(he.innerText ?? el.textContent) || shadowText(el);
|
|
336
|
+
const alt = normalizeText(el.getAttribute("aria-label") || el.getAttribute("title") || el.getAttribute("placeholder") || el.getAttribute("alt") || el.value);
|
|
337
|
+
return (own || alt).slice(0, 200);
|
|
338
|
+
}
|
|
339
|
+
function generateSelectors(el) {
|
|
340
|
+
const out = [];
|
|
341
|
+
const seen = /* @__PURE__ */ new Set();
|
|
342
|
+
const push = (s) => {
|
|
343
|
+
const k = `${s.kind}:${s.value}`;
|
|
344
|
+
if (!seen.has(k)) {
|
|
345
|
+
seen.add(k);
|
|
346
|
+
out.push(s);
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
const tag = el.tagName.toLowerCase();
|
|
350
|
+
const pushFor = (kind, selector, value, label) => {
|
|
351
|
+
const resolved = selectorFor(el, selector);
|
|
352
|
+
if (resolved === selector) push({ kind, value, label });
|
|
353
|
+
else if (resolved) push({ kind: "css", value: resolved, label });
|
|
354
|
+
return !!resolved;
|
|
355
|
+
};
|
|
356
|
+
const guidelyId = el.getAttribute("data-guidely-id");
|
|
357
|
+
if (guidelyId) pushFor("guidely-id", attrSelector("data-guidely-id", guidelyId), guidelyId, `Guidely id ${guidelyId}`);
|
|
358
|
+
if (isStableId(el.id)) pushFor("id", `#${escapeCss(el.id)}`, `#${el.id}`, `id ${el.id}`);
|
|
359
|
+
const dataAttrs = Array.from(el.attributes).filter((a) => a.name.startsWith("data-") && !IGNORED_DATA_ATTRS.test(a.name) && a.value && a.value.length <= 120 && !/\d{5,}/.test(a.value));
|
|
360
|
+
dataAttrs.sort((a, b) => {
|
|
361
|
+
const ia = PREFERRED_DATA_ATTRS.indexOf(a.name);
|
|
362
|
+
const ib = PREFERRED_DATA_ATTRS.indexOf(b.name);
|
|
363
|
+
return (ia === -1 ? 99 : ia) - (ib === -1 ? 99 : ib);
|
|
364
|
+
});
|
|
365
|
+
for (const a of dataAttrs) {
|
|
366
|
+
const sel = attrSelector(a.name, a.value);
|
|
367
|
+
if (!pushFor("data-attr", sel, sel, `${a.name}=${a.value}`)) pushFor("data-attr", tag + sel, tag + sel, `${a.name}=${a.value}`);
|
|
368
|
+
}
|
|
369
|
+
const aria = el.getAttribute("aria-label");
|
|
370
|
+
if (aria && aria.length <= 120) {
|
|
371
|
+
const sel = attrSelector("aria-label", aria);
|
|
372
|
+
if (!pushFor("aria", sel, sel, aria)) pushFor("aria", tag + sel, tag + sel, aria);
|
|
373
|
+
}
|
|
374
|
+
const name = el.getAttribute("name");
|
|
375
|
+
if (name) pushFor("css", tag + attrSelector("name", name), tag + attrSelector("name", name), `${tag} name=${name}`);
|
|
376
|
+
const role = el.getAttribute("role");
|
|
377
|
+
if (role) {
|
|
378
|
+
const title = el.getAttribute("title") || el.getAttribute("aria-labelledby");
|
|
379
|
+
const sel = title ? `[role='${role}']${attrSelector(el.getAttribute("title") ? "title" : "aria-labelledby", title)}` : `[role='${role}']`;
|
|
380
|
+
pushFor("css", sel, sel, `role ${role}`);
|
|
381
|
+
}
|
|
382
|
+
if (tag === "a") {
|
|
383
|
+
const href = el.getAttribute("href");
|
|
384
|
+
if (href && href.length <= 200) pushFor("css", `a${attrSelector("href", href)}`, `a${attrSelector("href", href)}`, `link ${href}`);
|
|
385
|
+
}
|
|
386
|
+
const path = cssPath(el, shadowRootOf(el) ?? el.ownerDocument);
|
|
387
|
+
if (path) pushFor("css", path, path, "css path");
|
|
388
|
+
if (/^(button|a|h[1-6]|label|summary)$/.test(tag) || role === "button" || role === "link" || role === "tab" || role === "menuitem") {
|
|
389
|
+
const text = normalizeText(el.innerText ?? el.textContent);
|
|
390
|
+
if (text && text.length <= 80) push({ kind: "text", value: text, label: `text "${text}"` });
|
|
391
|
+
}
|
|
392
|
+
return out.slice(0, 10);
|
|
393
|
+
}
|
|
394
|
+
function visualRect(el) {
|
|
395
|
+
const own = el.getBoundingClientRect();
|
|
396
|
+
if (!el.shadowRoot) return own;
|
|
397
|
+
const boxes = [own, ...Array.from(el.shadowRoot.children).map((c) => c.getBoundingClientRect())].filter((r) => r.width > 0 && r.height > 0);
|
|
398
|
+
if (boxes.length < 2) return boxes[0] ?? own;
|
|
399
|
+
const left = Math.min(...boxes.map((r) => r.left));
|
|
400
|
+
const top = Math.min(...boxes.map((r) => r.top));
|
|
401
|
+
const right = Math.max(...boxes.map((r) => r.right));
|
|
402
|
+
const bottom = Math.max(...boxes.map((r) => r.bottom));
|
|
403
|
+
return new DOMRect(left, top, right - left, bottom - top);
|
|
404
|
+
}
|
|
405
|
+
var ANCHOR_MAX_AREA_RATIO = 4;
|
|
406
|
+
var CONTROL_SELECTOR = "button, a[href], input, select, textarea, [role='button'], [role='link'], [role='checkbox'], [role='radio'], [role='switch'], [role='tab'], [role='menuitem'], [role='combobox'], [role='option']";
|
|
407
|
+
function componentAnchor(el) {
|
|
408
|
+
if (!hasLayout(el.ownerDocument)) return el;
|
|
409
|
+
let cur = el;
|
|
410
|
+
for (let root = shadowRootOf(cur); root; root = shadowRootOf(cur)) {
|
|
411
|
+
const host = root.host;
|
|
412
|
+
if (host.id === HOST_ID) break;
|
|
413
|
+
let control = null;
|
|
414
|
+
try {
|
|
415
|
+
control = cur.closest(CONTROL_SELECTOR);
|
|
416
|
+
} catch {
|
|
417
|
+
}
|
|
418
|
+
const r = visualRect(control ?? cur);
|
|
419
|
+
const area = r.width * r.height;
|
|
420
|
+
const h = visualRect(host);
|
|
421
|
+
const hostArea = h.width * h.height;
|
|
422
|
+
const inside = r.left >= h.left - 1 && r.top >= h.top - 1 && r.right <= h.right + 1 && r.bottom <= h.bottom + 1;
|
|
423
|
+
if (!area || !inside || hostArea > area * ANCHOR_MAX_AREA_RATIO) break;
|
|
424
|
+
cur = host;
|
|
425
|
+
}
|
|
426
|
+
return cur;
|
|
427
|
+
}
|
|
428
|
+
function describeElement(el) {
|
|
429
|
+
const target = componentAnchor(el);
|
|
430
|
+
const r = visualRect(target);
|
|
431
|
+
return {
|
|
432
|
+
selectors: generateSelectors(target),
|
|
433
|
+
textSnapshot: textSnapshotOf(target) || textSnapshotOf(el),
|
|
434
|
+
rect: { x: r.x, y: r.y, width: r.width, height: r.height },
|
|
435
|
+
tag: target.tagName.toLowerCase()
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
export {
|
|
440
|
+
urlMatches,
|
|
441
|
+
normalizeText,
|
|
442
|
+
isVisible,
|
|
443
|
+
isGuidelyElement,
|
|
444
|
+
SHADOW_SEPARATOR,
|
|
445
|
+
composedParent,
|
|
446
|
+
containsComposed,
|
|
447
|
+
composedTarget,
|
|
448
|
+
closestComposed,
|
|
449
|
+
deepElementFromPoint,
|
|
450
|
+
querySelectorStrategy,
|
|
451
|
+
resolveTarget,
|
|
452
|
+
TargetTimeoutError,
|
|
453
|
+
waitForTarget,
|
|
454
|
+
isStableId,
|
|
455
|
+
shadowHostChain,
|
|
456
|
+
textSnapshotOf,
|
|
457
|
+
generateSelectors,
|
|
458
|
+
visualRect,
|
|
459
|
+
componentAnchor,
|
|
460
|
+
describeElement
|
|
461
|
+
};
|
|
462
|
+
//# sourceMappingURL=chunk-GUH2PQJ7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/selectors.ts"],"sourcesContent":["import { matchUrlPattern } from \"@guidelytech/shared/runtime\";\nimport type { SelectorStrategy, StepTarget } from \"@guidelytech/shared\";\n\n/**\n * URL matching used for `step.url`, `urlPatterns` and `trigger.urlPattern`: a pattern matches the\n * full URL, the path+query+hash, or the bare path (so `/deals` also matches `/deals?x=1`).\n */\nexport function urlMatches(pattern: string | undefined | null, url: string): boolean {\n if (!pattern) return true;\n if (matchUrlPattern(pattern, url)) return true;\n try {\n const u = new URL(url, \"http://localhost\");\n if (!pattern.includes(\"?\") && !pattern.includes(\"#\")) return matchUrlPattern(pattern, u.pathname) || matchUrlPattern(pattern, u.origin + u.pathname);\n } catch {\n /* ignore */\n }\n return false;\n}\n\nexport type QueryRoot = Document | DocumentFragment | Element;\n\nconst TEXT_CANDIDATES =\n \"button, a, [role='button'], [role='link'], [role='tab'], [role='menuitem'], h1, h2, h3, h4, h5, h6, label, summary\";\n\nconst HOST_ID = \"guidely-root\";\n\nfunction docOf(root: QueryRoot): Document {\n return root.nodeType === 9 ? (root as Document) : (root.ownerDocument as Document);\n}\n\n/** True when the environment has a layout engine (real browsers). happy-dom/jsdom report zero sizes. */\nfunction hasLayout(doc: Document): boolean {\n const de = doc.documentElement;\n if (!de) return false;\n const r = de.getBoundingClientRect();\n return r.width > 0 || r.height > 0;\n}\n\n/** Normalises whitespace in a text snippet. */\nexport function normalizeText(text: string | null | undefined): string {\n return (text || \"\").replace(/\\s+/g, \" \").trim();\n}\n\n/** Is the element rendered (not hidden by `hidden`, `display:none`, `visibility:hidden`, or zero size)? */\nexport function isVisible(el: Element): boolean {\n if (!el.isConnected) return false;\n const doc = el.ownerDocument;\n const win = doc.defaultView;\n let cur: Element | null = el;\n while (cur && cur !== doc.documentElement) {\n if ((cur as HTMLElement).hidden) return false;\n if (win) {\n const cs = win.getComputedStyle(cur);\n if (cs.display === \"none\" || cs.visibility === \"hidden\") return false;\n }\n cur = cur.parentElement ?? ((cur.getRootNode() as ShadowRoot).host as Element | undefined) ?? null;\n }\n if (hasLayout(doc)) {\n const r = el.getBoundingClientRect();\n if (r.width === 0 && r.height === 0) return false;\n }\n return true;\n}\n\n/** Elements that belong to Guidely's own UI are never valid targets. */\nexport function isGuidelyElement(el: Element | null): boolean {\n if (!el) return false;\n const root = el.getRootNode();\n if (root instanceof ShadowRoot && root.host.id === HOST_ID) return true;\n return el.id === HOST_ID || !!el.closest?.(`#${HOST_ID}`);\n}\n\nfunction safeQueryAll(root: QueryRoot, selector: string): Element[] {\n try {\n return Array.from(root.querySelectorAll(selector));\n } catch {\n return [];\n }\n}\n\n// ---------------------------------------------------------------------------\n// Shadow DOM. Web-component apps (Salesforce Lightning Web Components, Shoelace, Ionic, Lit) keep\n// most of their elements inside shadow roots, which `querySelectorAll` never enters. Selectors\n// therefore search open shadow roots too, and a CSS value can step into one explicitly:\n// `c-app >>> button.save` is `button.save` anywhere inside `c-app`'s shadow tree. Closed shadow\n// roots are unreachable by design.\n// ---------------------------------------------------------------------------\n\n/** Separates the shadow-host steps of a CSS selector (`>>>` is not valid CSS, so it never clashes). */\nexport const SHADOW_SEPARATOR = \" >>> \";\nconst SHADOW_SPLIT = /\\s*>>>\\s*/;\n\nfunction isShadowRoot(node: Node | null | undefined): node is ShadowRoot {\n return !!node && node.nodeType === 11 && !!(node as ShadowRoot).host;\n}\n\n/** The shadow root an element lives in, or null when it is in the document itself. */\nfunction shadowRootOf(el: Element): ShadowRoot | null {\n const root = el.getRootNode?.();\n return isShadowRoot(root) ? root : null;\n}\n\n/** The element's parent in the composed tree: its parent element, or its shadow host at the top of a shadow root. */\nexport function composedParent(el: Element): Element | null {\n return el.parentElement ?? shadowRootOf(el)?.host ?? null;\n}\n\n/** Does `ancestor` contain `node`, looking through shadow boundaries? */\nexport function containsComposed(ancestor: Element, node: Node | null): boolean {\n let cur: Element | null = node ? (node.nodeType === 1 ? (node as Element) : node.parentElement) : null;\n for (; cur; cur = composedParent(cur)) if (cur === ancestor) return true;\n return false;\n}\n\n/** The element an event really started on: inside a shadow root `e.target` is retargeted to the host. */\nexport function composedTarget(e: Event): Element | null {\n const path = typeof e.composedPath === \"function\" ? e.composedPath() : [];\n const first = (path[0] ?? e.target) as Node | null;\n if (!first) return null;\n return first.nodeType === 1 ? (first as Element) : first.parentElement;\n}\n\n/** Set while `resolveTarget` runs, so its strategies share one walk of the page per root. */\nlet shadowRootCache: Map<QueryRoot, ShadowRoot[]> | null = null;\n\n/** Every open shadow root below `root`, nested ones included, except Guidely's own UI. */\nfunction shadowRootsIn(root: QueryRoot): ShadowRoot[] {\n const cached = shadowRootCache?.get(root);\n if (cached) return cached;\n const out: ShadowRoot[] = [];\n const visit = (scope: QueryRoot) => {\n const own = scope.nodeType === 1 ? (scope as Element).shadowRoot : null;\n const hosts = own ? [scope as Element] : [];\n for (const el of safeQueryAll(scope, \"*\")) if (el.shadowRoot) hosts.push(el);\n for (const host of hosts) {\n if (host.id === HOST_ID || !host.shadowRoot || out.includes(host.shadowRoot)) continue;\n out.push(host.shadowRoot);\n visit(host.shadowRoot);\n }\n };\n visit(root);\n shadowRootCache?.set(root, out);\n return out;\n}\n\n/** `querySelectorAll` that also searches every open shadow root below `root`. */\nfunction queryAllDeep(root: QueryRoot, selector: string): Element[] {\n const out = safeQueryAll(root, selector);\n for (const sr of shadowRootsIn(root)) out.push(...safeQueryAll(sr, selector));\n return out;\n}\n\n/**\n * Resolves a CSS selector. With `deep`, open shadow roots are searched too. A `>>>` chain is always\n * deep: each step is looked for anywhere inside the shadow trees of the previous step's matches.\n */\nfunction queryCss(root: QueryRoot, selector: string, deep: boolean): Element[] {\n if (!selector.includes(\">>>\")) return deep ? queryAllDeep(root, selector) : safeQueryAll(root, selector);\n const steps = selector.split(SHADOW_SPLIT).filter(Boolean);\n let scopes: QueryRoot[] = [root];\n let matches: Element[] = [];\n steps.forEach((step, i) => {\n matches = Array.from(new Set(scopes.flatMap((scope) => queryAllDeep(scope, step))));\n if (i < steps.length - 1) scopes = matches.map((el) => el.shadowRoot).filter((sr): sr is ShadowRoot => !!sr);\n });\n return matches;\n}\n\n/**\n * `Element.closest` across shadow boundaries: the nearest element, from `el` up through its shadow\n * hosts, that matches `selector` (which may be a `>>>` chain). Throws on an invalid plain selector,\n * like `closest` does.\n */\nexport function closestComposed(el: Element, selector: string): Element | null {\n if (selector.includes(\">>>\")) {\n const hits = new Set(queryCss(docOf(el), selector, true));\n for (let cur: Element | null = el; cur; cur = composedParent(cur)) if (hits.has(cur)) return cur;\n return null;\n }\n for (let cur: Element | null = el; cur; cur = composedParent(cur)) if (cur.matches(selector)) return cur;\n return null;\n}\n\n/** The innermost element at a point, looking inside open shadow roots (`elementFromPoint` stops at the host). */\nexport function deepElementFromPoint(doc: Document, x: number, y: number): Element | null {\n let el = doc.elementFromPoint(x, y);\n while (el?.shadowRoot && el.id !== HOST_ID && typeof el.shadowRoot.elementFromPoint === \"function\") {\n const inner = el.shadowRoot.elementFromPoint(x, y);\n if (!inner || inner === el) break;\n el = inner;\n }\n return el;\n}\n\nfunction escapeCss(value: string): string {\n const g = globalThis as { CSS?: { escape?: (v: string) => string } };\n if (g.CSS && typeof g.CSS.escape === \"function\") return g.CSS.escape(value);\n return value.replace(/[\"\\\\]/g, \"\\\\$&\");\n}\n\nfunction queryXPath(root: QueryRoot, expr: string): Element[] {\n const doc = docOf(root);\n const d = doc as Document & { evaluate?: Document[\"evaluate\"] };\n if (typeof d.evaluate !== \"function\") return [];\n try {\n const result = d.evaluate(expr, root, null, 7 /* ORDERED_NODE_SNAPSHOT_TYPE */, null);\n const out: Element[] = [];\n for (let i = 0; i < result.snapshotLength; i++) {\n const n = result.snapshotItem(i);\n if (n && n.nodeType === 1) out.push(n as Element);\n }\n return out;\n } catch {\n return [];\n }\n}\n\nfunction queryText(root: QueryRoot, text: string, deep: boolean): Element[] {\n const needle = normalizeText(text).toLowerCase();\n if (!needle) return [];\n const candidates = queryCss(root, TEXT_CANDIDATES, deep);\n const exact = candidates.filter((c) => normalizeText(c.textContent).toLowerCase() === needle);\n if (exact.length) return exact;\n return candidates.filter((c) => normalizeText(c.textContent).toLowerCase().includes(needle));\n}\n\n/**\n * Resolves every element matching one strategy (visible or not). `deep` (the default) also searches\n * open shadow roots; `>>>` chains are always followed. XPath cannot cross shadow boundaries.\n */\nexport function querySelectorStrategy(strategy: SelectorStrategy, root: QueryRoot, deep = true): Element[] {\n const value = strategy.value.trim();\n if (!value) return [];\n switch (strategy.kind) {\n case \"id\": {\n const id = value.startsWith(\"#\") ? value.slice(1) : value;\n return queryCss(root, `#${escapeCss(id)}`, deep);\n }\n case \"guidely-id\": {\n const id = value.startsWith(\"#\") ? value.slice(1) : value;\n return queryCss(root, attrSelector(\"data-guidely-id\", id), deep);\n }\n case \"data-attr\":\n case \"aria\":\n case \"css\":\n return queryCss(root, value.startsWith(\"[\") || /^[a-z*#.[]/i.test(value) ? value : `[${value}]`, deep);\n case \"text\":\n return queryText(root, value, deep);\n case \"xpath\":\n return queryXPath(root, value);\n default:\n return [];\n }\n}\n\n/**\n * Resolves a step target by trying each strategy in order. A strategy wins only when it\n * resolves to exactly one *visible* element; otherwise the next strategy is tried. Each strategy\n * looks in the document first and only searches shadow roots when nothing there is visible, so a\n * target that resolved before shadow-DOM support still resolves to the same element.\n */\nexport function resolveTarget(target: Pick<StepTarget, \"selectors\"> | SelectorStrategy[], root: QueryRoot = document): Element | null {\n const selectors = Array.isArray(target) ? target : target.selectors;\n const visibleMatches = (strategy: SelectorStrategy, deep: boolean) => querySelectorStrategy(strategy, root, deep).filter((el) => !isGuidelyElement(el) && isVisible(el));\n const outer = shadowRootCache;\n shadowRootCache ??= new Map();\n try {\n for (const strategy of selectors) {\n let matches = visibleMatches(strategy, false);\n if (!matches.length && strategy.kind !== \"xpath\") matches = visibleMatches(strategy, true);\n if (matches.length === 1) return matches[0] as Element;\n }\n return null;\n } finally {\n shadowRootCache = outer;\n }\n}\n\nexport interface WaitForTargetOptions {\n /** Give up after this many milliseconds (default 5000). */\n timeoutMs?: number;\n /** Abort early. */\n signal?: AbortSignal;\n root?: QueryRoot;\n /** Polling fallback interval (default 250ms, which is also the maximum). */\n pollMs?: number;\n}\n\nexport class TargetTimeoutError extends Error {\n override name = \"TargetTimeoutError\";\n constructor(message = \"Target element not found before timeout\") {\n super(message);\n }\n}\n\n/**\n * Waits until `resolveTarget` finds an element. Uses a MutationObserver plus a polling fallback\n * (at most every 250ms) so visibility changes without DOM mutations, and changes inside shadow\n * roots (which the observer does not see), are also detected.\n */\nexport function waitForTarget(target: Pick<StepTarget, \"selectors\"> | SelectorStrategy[], options: WaitForTargetOptions = {}): Promise<Element> {\n const timeoutMs = options.timeoutMs ?? 5000;\n const root = options.root ?? document;\n const pollMs = Math.min(250, Math.max(16, options.pollMs ?? 250));\n return new Promise<Element>((resolve, reject) => {\n const immediate = resolveTarget(target, root);\n if (immediate) return resolve(immediate);\n if (options.signal?.aborted) return reject(new DOMException(\"Aborted\", \"AbortError\"));\n let done = false;\n let observer: MutationObserver | null = null;\n let timer: ReturnType<typeof setInterval> | null = null;\n let timeout: ReturnType<typeof setTimeout> | null = null;\n const cleanup = () => {\n done = true;\n observer?.disconnect();\n if (timer) clearInterval(timer);\n if (timeout) clearTimeout(timeout);\n options.signal?.removeEventListener(\"abort\", onAbort);\n };\n const check = () => {\n if (done) return;\n const el = resolveTarget(target, root);\n if (el) {\n cleanup();\n resolve(el);\n }\n };\n const onAbort = () => {\n cleanup();\n reject(new DOMException(\"Aborted\", \"AbortError\"));\n };\n options.signal?.addEventListener(\"abort\", onAbort);\n const observeRoot = root.nodeType === 9 ? (root as Document).documentElement : (root as Element);\n if (typeof MutationObserver !== \"undefined\" && observeRoot) {\n observer = new MutationObserver(check);\n observer.observe(observeRoot, { childList: true, subtree: true, attributes: true, attributeFilter: [\"class\", \"style\", \"hidden\", \"id\", \"data-tour\", \"data-guidely-id\", \"aria-label\"] });\n }\n timer = setInterval(check, pollMs);\n if (timeoutMs > 0) {\n timeout = setTimeout(() => {\n cleanup();\n reject(new TargetTimeoutError());\n }, timeoutMs);\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// Selector generation (used by the element picker)\n// ---------------------------------------------------------------------------\n\nconst GENERATED_ID = /(\\d{4,}|:r[0-9a-z]+:|^radix-|^headlessui-|^mui-|^ember\\d|^react-|^\\w*-\\d+$|__|^[a-f0-9]{8,}$|^svelte-)/i;\nconst GENERATED_CLASS = /(^css-|^sc-|^jss\\d|^svelte-|^emotion-|^chakra-|^Mui|^_|[0-9a-f]{6,}|^\\w{1,2}$|^[a-z]+-\\d+$|[:[\\]/])/;\nconst PREFERRED_DATA_ATTRS = [\"data-testid\", \"data-tour\", \"data-test\", \"data-test-id\", \"data-cy\", \"data-qa\", \"data-id\", \"data-name\", \"data-guidely\"];\nconst IGNORED_DATA_ATTRS = /^data-(guidely-id|state|v-|reactid|react|radix|headlessui|svelte|hydrated|orientation|highlighted|focus|key|index|rbd|dnd|rk-|sveltekit)/i;\n\n/** Is this id stable enough to be used as a selector (not generated by a framework)? */\nexport function isStableId(id: string): boolean {\n return !!id && /^[A-Za-z][\\w-]*$/.test(id) && !GENERATED_ID.test(id);\n}\n\nfunction isStableClass(cls: string): boolean {\n return !!cls && !GENERATED_CLASS.test(cls) && cls.length <= 40;\n}\n\n/** Does `selector` match exactly `el` and nothing else directly inside `root` (shadow roots below are not searched)? */\nfunction uniqueWithin(root: QueryRoot, selector: string, el: Element): boolean {\n const all = safeQueryAll(root, selector);\n return all.length === 1 && all[0] === el;\n}\n\nfunction attrSelector(name: string, value: string): string {\n return `[${name}='${value.replace(/\\\\/g, \"\\\\\\\\\").replace(/'/g, \"\\\\'\")}']`;\n}\n\n/** Shortest unique `>`-path to `el` within its own root (the document, or the shadow root it lives in). */\nfunction cssPath(el: Element, root: Document | ShadowRoot): string | null {\n const doc = el.ownerDocument;\n const segments: string[] = [];\n let cur: Element | null = el;\n while (cur && cur.nodeType === 1 && cur !== doc.body && cur !== doc.documentElement) {\n const tag = cur.tagName.toLowerCase();\n if (isStableId(cur.id)) {\n segments.unshift(`#${cur.id}`);\n break;\n }\n let seg = tag;\n const parent: Element | null = cur.parentElement;\n if (parent) {\n const sameTag = Array.from(parent.children).filter((c) => c.tagName === cur!.tagName);\n if (sameTag.length > 1) {\n const stableCls = Array.from(cur.classList).find((c) => isStableClass(c) && sameTag.filter((s) => s.classList.contains(c)).length === 1);\n seg += stableCls ? `.${escapeCss(stableCls)}` : `:nth-of-type(${sameTag.indexOf(cur) + 1})`;\n }\n }\n segments.unshift(seg);\n const candidate = segments.join(\" > \");\n if (uniqueWithin(root, candidate, el)) return candidate;\n cur = parent;\n }\n const full = segments.join(\" > \");\n return uniqueWithin(root, full, el) ? full : null;\n}\n\n/**\n * The `>>>` chain of shadow hosts above an element (`c-app >>> c-form`), or \"\" for an element in\n * the document itself; null when some host has no unique path within its own root.\n */\nexport function shadowHostChain(el: Element): string | null {\n const steps: string[] = [];\n for (let root = shadowRootOf(el); root; root = shadowRootOf(root.host)) {\n const host = root.host;\n const step = cssPath(host, shadowRootOf(host) ?? host.ownerDocument);\n if (!step) return null;\n steps.unshift(step);\n }\n return steps.join(SHADOW_SEPARATOR);\n}\n\n/**\n * Turns a selector that is unique within `el`'s own root into one the resolver maps back to `el`.\n * In the document that is the selector itself (as before shadow-DOM support). Inside a shadow root\n * the bare selector is kept when no other match exists in any shadow tree; otherwise it is scoped\n * with the host chain. Returns null when neither form resolves to exactly `el`.\n */\nfunction selectorFor(el: Element, selector: string): string | null {\n const root = shadowRootOf(el);\n if (!root) return uniqueWithin(el.ownerDocument, selector, el) ? selector : null;\n if (!uniqueWithin(root, selector, el)) return null;\n const doc = el.ownerDocument;\n const only = (sel: string) => {\n const all = queryCss(doc, sel, true);\n return all.length === 1 && all[0] === el;\n };\n if (only(selector)) return selector;\n const chain = shadowHostChain(el);\n const scoped = chain ? chain + SHADOW_SEPARATOR + selector : null;\n return scoped && only(scoped) ? scoped : null;\n}\n\n/** Text a component renders in its shadow root (`innerText` of a host only covers its light DOM). */\nfunction shadowText(el: Element): string {\n if (!el.shadowRoot) return \"\";\n const parts = Array.from(el.shadowRoot.children).filter((c) => !/^(STYLE|SCRIPT|TEMPLATE)$/.test(c.tagName));\n return normalizeText(parts.map((c) => (c as HTMLElement).innerText ?? c.textContent).join(\" \"));\n}\n\n/** Short human-readable text for an element, trimmed to 200 characters. */\nexport function textSnapshotOf(el: Element): string {\n const he = el as HTMLElement;\n const own = normalizeText(he.innerText ?? el.textContent) || shadowText(el);\n const alt = normalizeText(el.getAttribute(\"aria-label\") || el.getAttribute(\"title\") || el.getAttribute(\"placeholder\") || el.getAttribute(\"alt\") || (el as HTMLInputElement).value);\n return (own || alt).slice(0, 200);\n}\n\n/**\n * Generates an ordered list of selector strategies for an element, most robust first:\n * stable id → data-* attributes → aria-label → role/name → short unique CSS path → visible text.\n */\nexport function generateSelectors(el: Element): SelectorStrategy[] {\n const out: SelectorStrategy[] = [];\n const seen = new Set<string>();\n const push = (s: SelectorStrategy) => {\n const k = `${s.kind}:${s.value}`;\n if (!seen.has(k)) {\n seen.add(k);\n out.push(s);\n }\n };\n const tag = el.tagName.toLowerCase();\n // A selector scoped into a shadow root (`host >>> sel`) is always pushed as plain CSS.\n const pushFor = (kind: SelectorStrategy[\"kind\"], selector: string, value: string, label: string) => {\n const resolved = selectorFor(el, selector);\n if (resolved === selector) push({ kind, value, label });\n else if (resolved) push({ kind: \"css\", value: resolved, label });\n return !!resolved;\n };\n\n // A Guidely id is shared with the mobile apps, so it is the most portable target there is.\n const guidelyId = el.getAttribute(\"data-guidely-id\");\n if (guidelyId) pushFor(\"guidely-id\", attrSelector(\"data-guidely-id\", guidelyId), guidelyId, `Guidely id ${guidelyId}`);\n if (isStableId(el.id)) pushFor(\"id\", `#${escapeCss(el.id)}`, `#${el.id}`, `id ${el.id}`);\n\n const dataAttrs = Array.from(el.attributes).filter((a) => a.name.startsWith(\"data-\") && !IGNORED_DATA_ATTRS.test(a.name) && a.value && a.value.length <= 120 && !/\\d{5,}/.test(a.value));\n dataAttrs.sort((a, b) => {\n const ia = PREFERRED_DATA_ATTRS.indexOf(a.name);\n const ib = PREFERRED_DATA_ATTRS.indexOf(b.name);\n return (ia === -1 ? 99 : ia) - (ib === -1 ? 99 : ib);\n });\n for (const a of dataAttrs) {\n const sel = attrSelector(a.name, a.value);\n if (!pushFor(\"data-attr\", sel, sel, `${a.name}=${a.value}`)) pushFor(\"data-attr\", tag + sel, tag + sel, `${a.name}=${a.value}`);\n }\n\n const aria = el.getAttribute(\"aria-label\");\n if (aria && aria.length <= 120) {\n const sel = attrSelector(\"aria-label\", aria);\n if (!pushFor(\"aria\", sel, sel, aria)) pushFor(\"aria\", tag + sel, tag + sel, aria);\n }\n\n const name = el.getAttribute(\"name\");\n if (name) pushFor(\"css\", tag + attrSelector(\"name\", name), tag + attrSelector(\"name\", name), `${tag} name=${name}`);\n const role = el.getAttribute(\"role\");\n if (role) {\n const title = el.getAttribute(\"title\") || el.getAttribute(\"aria-labelledby\");\n const sel = title ? `[role='${role}']${attrSelector(el.getAttribute(\"title\") ? \"title\" : \"aria-labelledby\", title)}` : `[role='${role}']`;\n pushFor(\"css\", sel, sel, `role ${role}`);\n }\n if (tag === \"a\") {\n const href = el.getAttribute(\"href\");\n if (href && href.length <= 200) pushFor(\"css\", `a${attrSelector(\"href\", href)}`, `a${attrSelector(\"href\", href)}`, `link ${href}`);\n }\n\n const path = cssPath(el, shadowRootOf(el) ?? el.ownerDocument);\n if (path) pushFor(\"css\", path, path, \"css path\");\n\n if (/^(button|a|h[1-6]|label|summary)$/.test(tag) || role === \"button\" || role === \"link\" || role === \"tab\" || role === \"menuitem\") {\n const text = normalizeText((el as HTMLElement).innerText ?? el.textContent);\n if (text && text.length <= 80) push({ kind: \"text\", value: text, label: `text \"${text}\"` });\n }\n return out.slice(0, 10);\n}\n\nexport interface ElementDescription {\n selectors: SelectorStrategy[];\n textSnapshot: string;\n rect: { x: number; y: number; width: number; height: number };\n tag: string;\n}\n\n/**\n * An element's on-screen box. For a shadow host that is its own box joined with its shadow content's:\n * an `inline` host (the default for custom elements) is only a line tall around a taller button, and\n * a `display: contents` host has no box at all.\n */\nexport function visualRect(el: Element): DOMRect {\n const own = el.getBoundingClientRect();\n if (!el.shadowRoot) return own;\n const boxes = [own, ...Array.from(el.shadowRoot.children).map((c) => c.getBoundingClientRect())].filter((r) => r.width > 0 && r.height > 0);\n if (boxes.length < 2) return boxes[0] ?? own;\n const left = Math.min(...boxes.map((r) => r.left));\n const top = Math.min(...boxes.map((r) => r.top));\n const right = Math.max(...boxes.map((r) => r.right));\n const bottom = Math.max(...boxes.map((r) => r.bottom));\n return new DOMRect(left, top, right - left, bottom - top);\n}\n\n/** Growth from a control's box to its component's that still counts as \"the same control\" (label + field). */\nconst ANCHOR_MAX_AREA_RATIO = 4;\nconst CONTROL_SELECTOR = \"button, a[href], input, select, textarea, [role='button'], [role='link'], [role='checkbox'], [role='radio'], [role='switch'], [role='tab'], [role='menuitem'], [role='combobox'], [role='option']\";\n\n/**\n * The element a pick should target. Inside a component (a shadow host) that is little more than the\n * picked control (`lightning-button` around its `<button>`, also when the pick is the button's icon;\n * `lightning-input` around its label and field), that is the component itself: the app's markup around a component is the app's, while a\n * design system can change a component's internals in any release. Repeats up nested components and\n * stops at the first one that is clearly more (a list, a form, the whole app). Without layout (tests,\n * hidden pages) the element is kept.\n */\nexport function componentAnchor(el: Element): Element {\n if (!hasLayout(el.ownerDocument)) return el;\n let cur = el;\n for (let root = shadowRootOf(cur); root; root = shadowRootOf(cur)) {\n const host = root.host;\n if (host.id === HOST_ID) break;\n let control: Element | null = null;\n try {\n control = cur.closest(CONTROL_SELECTOR); // stays within this shadow root\n } catch {\n /* ignore */\n }\n const r = visualRect(control ?? cur);\n const area = r.width * r.height;\n const h = visualRect(host);\n const hostArea = h.width * h.height;\n const inside = r.left >= h.left - 1 && r.top >= h.top - 1 && r.right <= h.right + 1 && r.bottom <= h.bottom + 1;\n if (!area || !inside || hostArea > area * ANCHOR_MAX_AREA_RATIO) break;\n cur = host;\n }\n return cur;\n}\n\n/**\n * Everything the authoring picker and how-to capture need for one element. Selectors and rect are\n * for its `componentAnchor`; the text falls back to the element's own.\n */\nexport function describeElement(el: Element): ElementDescription {\n const target = componentAnchor(el);\n const r = visualRect(target);\n return {\n selectors: generateSelectors(target),\n textSnapshot: textSnapshotOf(target) || textSnapshotOf(el),\n rect: { x: r.x, y: r.y, width: r.width, height: r.height },\n tag: target.tagName.toLowerCase(),\n };\n}\n"],"mappings":"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","names":[]}
|