Skip to content

Commit 2b3fc5a

Browse files
authored
Send page map and page map json with DOM (#673)
* improved extension * fixed performance issue and iframe inspection issue
1 parent 006ad7b commit 2b3fc5a

4 files changed

Lines changed: 290 additions & 36 deletions

File tree

Apps/Web/aiplugin/background.js

Lines changed: 61 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ const defaultIcon = 'zeuz.png';
66
var zeuz_url;
77
var zeuz_key;
88
var zeuz_node_id;
9+
const _aiContentTimers = {}; // per-tab debounce for node_ai_contents
10+
const _aiContentHashes = {}; // per-tab hashes to avoid resending unchanged contents
911

1012
fetch("data.json")
1113
.then(Response => Response.json())
@@ -135,7 +137,7 @@ if (navigator.userAgentData.platform.toLowerCase().includes('mac')) {
135137
}
136138
browserAppData.runtime.onMessage.addListener(
137139
function (request, sender, sendResponse) {
138-
140+
139141
if (request.action === 'toggle_from_content_script') {
140142
// allows the floating button to trigger the toggle logic
141143
toggle(sender.tab);
@@ -171,36 +173,71 @@ browserAppData.runtime.onMessage.addListener(
171173
.then(text => { console.log(text); sendResponse(text); })
172174

173175
return true; // Will respond asynchronously.
174-
} else if (request.apiName == 'node_ai_contents'){
175-
var url = `${zeuz_url}/node_ai_contents/`;
176-
fetch(url, {
177-
method: "POST",
178-
headers: {
179-
// "Content-Type": "application/json",
180-
"X-Api-Key": zeuz_key,
181-
},
182-
body: JSON.stringify({
183-
"dom_web": { "dom": request.dom },
184-
"node_id": zeuz_node_id
185-
}),
186-
})
187-
.then(response => response.json())
188-
.then(text => { console.log(text); sendResponse(text); })
176+
} else if (request.apiName == 'node_ai_contents') {
177+
const tabId = sender.tab ? sender.tab.id : 'unknown';
178+
if (_aiContentTimers[tabId]) clearTimeout(_aiContentTimers[tabId]);
179+
_aiContentTimers[tabId] = setTimeout(async () => {
180+
delete _aiContentTimers[tabId];
181+
182+
const contentObj = { "dom": request.dom, "page_map": request.page_map, "page_map_json": request.page_map_json };
183+
const contentStr = JSON.stringify(contentObj);
184+
185+
let hash = '';
186+
try {
187+
const msgUint8 = new TextEncoder().encode(contentStr);
188+
const hashBuffer = await crypto.subtle.digest('SHA-256', msgUint8);
189+
const hashArray = Array.from(new Uint8Array(hashBuffer));
190+
hash = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
191+
} catch (e) {
192+
console.error("Error generating hash", e);
193+
hash = contentStr.length.toString(); // Fallback
194+
}
195+
196+
if (_aiContentHashes[tabId] === hash) {
197+
console.log('node_ai_contents skipped, content unchanged for tab:', tabId, 'hash:', hash);
198+
try { sendResponse({ status: "skipped" }); } catch (e) { }
199+
return;
200+
}
201+
_aiContentHashes[tabId] = hash;
202+
console.log('node_ai_contents sending, new hash for tab:', tabId, 'hash:', hash);
203+
204+
var url = `${zeuz_url}/node_ai_contents/`;
205+
fetch(url, {
206+
method: "POST",
207+
headers: {
208+
// "Content-Type": "application/json",
209+
"X-Api-Key": zeuz_key,
210+
},
211+
body: JSON.stringify({
212+
"dom_web": contentObj,
213+
"node_id": zeuz_node_id
214+
}),
215+
})
216+
.then(response => {
217+
if (!response.ok) {
218+
console.error("node_ai_contents failed with status:", response.status, response.statusText);
219+
}
220+
return response.json();
221+
})
222+
.then(text => { console.log("node_ai_contents response:", text); try { sendResponse(text); } catch (e) { } })
223+
.catch(e => console.error("node_ai_contents fetch error:", e));
224+
}, 2000);
225+
return true; // Will respond asynchronously.
189226
}
190227
}
191228
);
192229

193230
// add AI Inspector to the right click menu
194231
browserAppData.runtime.onInstalled.addListener(() => {
195-
browserAppData.contextMenus.create({
196-
id: "toggle-ai-inspect",
197-
title: "Inspect with AI",
198-
contexts: ["all"]
199-
});
232+
browserAppData.contextMenus.create({
233+
id: "toggle-ai-inspect",
234+
title: "Inspect with AI",
235+
contexts: ["all"]
236+
});
200237
});
201238

202239
browserAppData.contextMenus.onClicked.addListener((info, tab) => {
203-
if (info.menuItemId === "toggle-ai-inspect" && tab) {
204-
toggle(tab);
205-
}
240+
if (info.menuItemId === "toggle-ai-inspect" && tab) {
241+
toggle(tab);
242+
}
206243
});

Apps/Web/aiplugin/inspect.js

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
const browserAppData = chrome || browser;
22
setInterval(() => {
3+
// Only run this periodic extraction on the main page, not inside iframes
4+
// (this prevents tracking pixels from overwriting the main page DOM)
5+
if (window.top !== window.self) return;
6+
37
var html = document.createElement('html');
4-
html.setAttribute('zeuz','aiplugin');
8+
html.setAttribute('zeuz', 'aiplugin');
59
var myString = document.documentElement.outerHTML;
610
html.innerHTML = myString;
7-
11+
812
var elements = html.getElementsByTagName('head');
913
while (elements[0])
1014
elements[0].parentNode.removeChild(elements[0])
@@ -20,16 +24,27 @@ setInterval(() => {
2024
var elements = html.getElementsByTagName('style');
2125
while (elements[0])
2226
elements[0].parentNode.removeChild(elements[0])
23-
27+
2428
// AI model works better on indented dom, so not removing indentation.
2529
// var result = html.outerHTML.replace(/\s+/g, ' ').replace(/>\s+</g, '><');
2630

2731
//The following code removes non-unicode characters except newline and tab
2832
var result = html.outerHTML.replace(/[\x00-\x08\x0B-\x1F\x7F]/g, '');
2933

34+
let mapData = { page_map_json: null, page_map: "" };
35+
if (typeof extractPageMapData === 'function') {
36+
try {
37+
mapData = extractPageMapData();
38+
} catch (e) {
39+
console.error("Error extracting page map:", e);
40+
}
41+
}
42+
3043
browserAppData.runtime.sendMessage({
3144
apiName: 'node_ai_contents',
3245
dom: result,
46+
page_map: mapData.page_map,
47+
page_map_json: mapData.page_map_json
3348
})
3449

3550
}, 5000);
@@ -68,7 +83,7 @@ class Inspector {
6883
if (response["info"] == "success") {
6984
const modalText = 'Element data was recorded. Please Click "Add by AI"';
7085
console.log(modalText);
71-
86+
7287
if (this.successContainer) {
7388
this.successContainer.textContent = modalText;
7489
this.successContainer.classList.add('show');
@@ -88,9 +103,9 @@ class Inspector {
88103
data: data,
89104
html: refinedHtml,
90105
},
91-
response => {
92-
insert_modal_text(response, modal_id);
93-
}
106+
response => {
107+
insert_modal_text(response, modal_id);
108+
}
94109
);
95110
}
96111

@@ -477,19 +492,19 @@ class Inspector {
477492
let value = e.target.getAttribute(name);
478493
elementText += `${name}="${value}" `;
479494
}
480-
495+
481496
this.attributesContainer.textContent = elementText.trim();
482497
}
483498

484499
activate() {
485500
this.createOverlayElements();
486501
this.createSuccessMessage();
487-
502+
488503
const style = document.createElement('style');
489504
style.id = this.cssNode;
490505
style.textContent = '*{cursor:crosshair!important;}';
491506
document.head.appendChild(style);
492-
507+
493508
// add listeners
494509
document.addEventListener('click', this.getData, true);
495510
this.options.inspector && (document.addEventListener('mouseover', this.draw));
@@ -506,15 +521,15 @@ class Inspector {
506521
'zeuz-success-host'
507522
]
508523

509-
for (let elemId of Remove){
524+
for (let elemId of Remove) {
510525
const elem = document.getElementById(elemId);
511526
elem && elem.remove();
512527
}
513528

514529
// remove listeners
515530
document.removeEventListener('click', this.getData, true);
516531
this.options && this.options.inspector && (document.removeEventListener('mouseover', this.draw));
517-
532+
518533
// reset
519534
this.attributesHost = null;
520535
this.attributesContainer = null;

Apps/Web/aiplugin/manifest.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"https://*/*"
2828
],
2929
"js": [
30+
"page_map_extractor.js",
3031
"inspect.js"
3132
]
3233
},

0 commit comments

Comments
 (0)