browser_control/dom/
scripts.rs1pub const GET_DOM_JS: &str = r#"
5(function(selector) {
6 const root = selector ? document.querySelector(selector) : document.documentElement;
7 if (!root) return null;
8 if (typeof root.getHTML === 'function') {
9 try { return root.getHTML({ serializableShadowRoots: true }); } catch (e) {}
10 }
11 return root.outerHTML;
12})
13"#;
14
15pub const GET_CLIP_RECT_JS: &str = r#"
19(function(selector) {
20 const el = document.querySelector(selector);
21 if (!el) return null;
22 el.scrollIntoView({ block: 'center', inline: 'center' });
23 const r = el.getBoundingClientRect();
24 if (r.width === 0 || r.height === 0) return null;
25 return {
26 x: r.left + window.scrollX,
27 y: r.top + window.scrollY,
28 width: r.width,
29 height: r.height,
30 };
31})
32"#;
33
34pub const SELECT_ELEMENT_JS: &str = r#"
36(function() {
37 function cssPath(el) {
38 if (!(el instanceof Element)) return '';
39 const path = [];
40 while (el && el.nodeType === 1) {
41 let selector = el.nodeName.toLowerCase();
42 if (el.id) { selector += '#' + el.id; path.unshift(selector); break; }
43 else {
44 let sib = el, nth = 1;
45 while ((sib = sib.previousElementSibling)) { if (sib.nodeName === el.nodeName) nth++; }
46 selector += ':nth-of-type(' + nth + ')';
47 }
48 path.unshift(selector);
49 el = el.parentNode;
50 }
51 return path.join(' > ');
52 }
53 return new Promise((resolve) => {
54 const overlay = document.createElement('div');
55 overlay.style.cssText = 'position:fixed;inset:0;z-index:2147483647;cursor:crosshair;background:rgba(0,150,255,0.05);';
56 document.body.appendChild(overlay);
57 overlay.addEventListener('click', (e) => {
58 e.preventDefault(); e.stopPropagation();
59 overlay.remove();
60 const x = e.clientX, y = e.clientY;
61 const el = document.elementFromPoint(x, y);
62 resolve(cssPath(el));
63 }, { capture: true, once: true });
64 });
65})()
66"#;
67
68pub const FETCH_JS: &str = r#"
70(async function(argsJson) {
71 const args = JSON.parse(argsJson);
72 const timeoutMs = Number(args.timeoutMs || 0);
73 const controller = timeoutMs > 0 && typeof AbortController !== 'undefined'
74 ? new AbortController()
75 : null;
76 const timer = controller
77 ? setTimeout(() => controller.abort(), timeoutMs)
78 : null;
79 try {
80 const r = await fetch(args.url, {
81 method: args.method || 'GET',
82 headers: args.headers || {},
83 body: args.body,
84 credentials: 'include',
85 signal: controller ? controller.signal : undefined,
86 });
87 const text = await r.text();
88 const headers = {};
89 r.headers.forEach((v,k) => { headers[k] = v; });
90 return JSON.stringify({ ok: true, status: r.status, statusText: r.statusText, headers, body: text });
91 } catch (e) {
92 const aborted = controller && controller.signal.aborted;
93 return JSON.stringify({
94 ok: false,
95 error: aborted ? `fetch timed out after ${timeoutMs}ms` : String(e),
96 errorName: e && e.name ? e.name : null,
97 });
98 } finally {
99 if (timer) clearTimeout(timer);
100 }
101})
102"#;