Skip to main content

browser_control/dom/
scripts.rs

1//! JavaScript payloads injected into the browser by MCP tools.
2
3/// Serializes the DOM with shadow roots included.
4pub 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
15/// Interactive element picker. Resolves with the selector string for the picked element.
16pub const SELECT_ELEMENT_JS: &str = r#"
17(function() {
18    function cssPath(el) {
19        if (!(el instanceof Element)) return '';
20        const path = [];
21        while (el && el.nodeType === 1) {
22            let selector = el.nodeName.toLowerCase();
23            if (el.id) { selector += '#' + el.id; path.unshift(selector); break; }
24            else {
25                let sib = el, nth = 1;
26                while ((sib = sib.previousElementSibling)) { if (sib.nodeName === el.nodeName) nth++; }
27                selector += ':nth-of-type(' + nth + ')';
28            }
29            path.unshift(selector);
30            el = el.parentNode;
31        }
32        return path.join(' > ');
33    }
34    return new Promise((resolve) => {
35        const overlay = document.createElement('div');
36        overlay.style.cssText = 'position:fixed;inset:0;z-index:2147483647;cursor:crosshair;background:rgba(0,150,255,0.05);';
37        document.body.appendChild(overlay);
38        overlay.addEventListener('click', (e) => {
39            e.preventDefault(); e.stopPropagation();
40            overlay.remove();
41            const x = e.clientX, y = e.clientY;
42            const el = document.elementFromPoint(x, y);
43            resolve(cssPath(el));
44        }, { capture: true, once: true });
45    });
46})()
47"#;
48
49/// Performs a fetch from the page context. Receives JSON-string args.
50pub const FETCH_JS: &str = r#"
51(async function(argsJson) {
52    const args = JSON.parse(argsJson);
53    const r = await fetch(args.url, {
54        method: args.method || 'GET',
55        headers: args.headers || {},
56        body: args.body,
57        credentials: 'include',
58    });
59    const text = await r.text();
60    const headers = {};
61    r.headers.forEach((v,k) => { headers[k] = v; });
62    return JSON.stringify({ status: r.status, statusText: r.statusText, headers, body: text });
63})
64"#;