Skip to content

Commit 0502e4a

Browse files
authored
Merge pull request #69 from SentienceAPI/sync-extension-v2.0.5
Sync Extension: v2.0.5
2 parents e529111 + fd5ce88 commit 0502e4a

File tree

3 files changed

+190
-32
lines changed

3 files changed

+190
-32
lines changed

sentience/extension/injected_api.js

Lines changed: 160 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -726,17 +726,23 @@
726726
}
727727

728728
console.log(`[SentienceAPI] Found ${iframes.length} iframe(s), requesting snapshots...`);
729-
730729
// Request snapshot from each iframe
731730
const iframePromises = iframes.map((iframe, idx) => {
731+
// OPTIMIZATION: Skip common ad domains to save time
732+
const src = iframe.src || '';
733+
if (src.includes('doubleclick') || src.includes('googleadservices') || src.includes('ads system')) {
734+
console.log(`[SentienceAPI] Skipping ad iframe: ${src.substring(0, 30)}...`);
735+
return Promise.resolve(null);
736+
}
737+
732738
return new Promise((resolve) => {
733739
const requestId = `iframe-${idx}-${Date.now()}`;
734740

735741
// 1. EXTENDED TIMEOUT (Handle slow children)
736742
const timeout = setTimeout(() => {
737743
console.warn(`[SentienceAPI] ⚠️ Iframe ${idx} snapshot TIMEOUT (id: ${requestId})`);
738744
resolve(null);
739-
}, 10000); // Increased to 10s to handle slow processing
745+
}, 5000); // Increased to 5s to handle slow processing
740746

741747
// 2. ROBUST LISTENER with debugging
742748
const listener = (event) => {
@@ -1036,6 +1042,10 @@
10361042
return {
10371043
status: "success",
10381044
url: window.location.href,
1045+
viewport: {
1046+
width: window.innerWidth,
1047+
height: window.innerHeight
1048+
},
10391049
elements: cleanedElements,
10401050
raw_elements: cleanedRawElements,
10411051
screenshot: screenshot
@@ -1073,6 +1083,154 @@
10731083
};
10741084
},
10751085

1086+
// 2b. Find Text Rectangle - Get exact pixel coordinates of specific text
1087+
findTextRect: (options = {}) => {
1088+
const {
1089+
text,
1090+
containerElement = document.body,
1091+
caseSensitive = false,
1092+
wholeWord = false,
1093+
maxResults = 10
1094+
} = options;
1095+
1096+
if (!text || text.trim().length === 0) {
1097+
return {
1098+
status: "error",
1099+
error: "Text parameter is required"
1100+
};
1101+
}
1102+
1103+
const results = [];
1104+
const searchText = caseSensitive ? text : text.toLowerCase();
1105+
1106+
// Helper function to find text in a single text node
1107+
function findInTextNode(textNode) {
1108+
const nodeText = textNode.nodeValue;
1109+
const searchableText = caseSensitive ? nodeText : nodeText.toLowerCase();
1110+
1111+
let startIndex = 0;
1112+
while (startIndex < nodeText.length && results.length < maxResults) {
1113+
const foundIndex = searchableText.indexOf(searchText, startIndex);
1114+
1115+
if (foundIndex === -1) break;
1116+
1117+
// Check whole word matching if required
1118+
if (wholeWord) {
1119+
const before = foundIndex > 0 ? nodeText[foundIndex - 1] : ' ';
1120+
const after = foundIndex + text.length < nodeText.length
1121+
? nodeText[foundIndex + text.length]
1122+
: ' ';
1123+
1124+
// Check if surrounded by word boundaries
1125+
if (!/\s/.test(before) || !/\s/.test(after)) {
1126+
startIndex = foundIndex + 1;
1127+
continue;
1128+
}
1129+
}
1130+
1131+
try {
1132+
// Create range for this occurrence
1133+
const range = document.createRange();
1134+
range.setStart(textNode, foundIndex);
1135+
range.setEnd(textNode, foundIndex + text.length);
1136+
1137+
const rect = range.getBoundingClientRect();
1138+
1139+
// Only include visible rectangles
1140+
if (rect.width > 0 && rect.height > 0) {
1141+
results.push({
1142+
text: nodeText.substring(foundIndex, foundIndex + text.length),
1143+
rect: {
1144+
x: rect.left + window.scrollX,
1145+
y: rect.top + window.scrollY,
1146+
width: rect.width,
1147+
height: rect.height,
1148+
left: rect.left + window.scrollX,
1149+
top: rect.top + window.scrollY,
1150+
right: rect.right + window.scrollX,
1151+
bottom: rect.bottom + window.scrollY
1152+
},
1153+
viewport_rect: {
1154+
x: rect.left,
1155+
y: rect.top,
1156+
width: rect.width,
1157+
height: rect.height
1158+
},
1159+
context: {
1160+
before: nodeText.substring(Math.max(0, foundIndex - 20), foundIndex),
1161+
after: nodeText.substring(foundIndex + text.length, Math.min(nodeText.length, foundIndex + text.length + 20))
1162+
},
1163+
in_viewport: (
1164+
rect.top >= 0 &&
1165+
rect.left >= 0 &&
1166+
rect.bottom <= window.innerHeight &&
1167+
rect.right <= window.innerWidth
1168+
)
1169+
});
1170+
}
1171+
} catch (e) {
1172+
console.warn('[SentienceAPI] Failed to get rect for text:', e);
1173+
}
1174+
1175+
startIndex = foundIndex + 1;
1176+
}
1177+
}
1178+
1179+
// Tree walker to find all text nodes
1180+
const walker = document.createTreeWalker(
1181+
containerElement,
1182+
NodeFilter.SHOW_TEXT,
1183+
{
1184+
acceptNode: function(node) {
1185+
// Skip script, style, and empty text nodes
1186+
const parent = node.parentElement;
1187+
if (!parent) return NodeFilter.FILTER_REJECT;
1188+
1189+
const tagName = parent.tagName.toLowerCase();
1190+
if (tagName === 'script' || tagName === 'style' || tagName === 'noscript') {
1191+
return NodeFilter.FILTER_REJECT;
1192+
}
1193+
1194+
// Skip whitespace-only nodes
1195+
if (!node.nodeValue || node.nodeValue.trim().length === 0) {
1196+
return NodeFilter.FILTER_REJECT;
1197+
}
1198+
1199+
// Check if element is visible
1200+
const computedStyle = window.getComputedStyle(parent);
1201+
if (computedStyle.display === 'none' ||
1202+
computedStyle.visibility === 'hidden' ||
1203+
computedStyle.opacity === '0') {
1204+
return NodeFilter.FILTER_REJECT;
1205+
}
1206+
1207+
return NodeFilter.FILTER_ACCEPT;
1208+
}
1209+
}
1210+
);
1211+
1212+
// Walk through all text nodes
1213+
let currentNode;
1214+
while ((currentNode = walker.nextNode()) && results.length < maxResults) {
1215+
findInTextNode(currentNode);
1216+
}
1217+
1218+
return {
1219+
status: "success",
1220+
query: text,
1221+
case_sensitive: caseSensitive,
1222+
whole_word: wholeWord,
1223+
matches: results.length,
1224+
results: results,
1225+
viewport: {
1226+
width: window.innerWidth,
1227+
height: window.innerHeight,
1228+
scroll_x: window.scrollX,
1229+
scroll_y: window.scrollY
1230+
}
1231+
};
1232+
},
1233+
10761234
// 3. Click Action (unchanged)
10771235
click: (id) => {
10781236
const el = window.sentience_registry[id];

sentience/extension/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifest_version": 3,
33
"name": "Sentience Semantic Visual Grounding Extractor",
4-
"version": "2.0.2",
4+
"version": "2.0.5",
55
"description": "Extract semantic visual grounding data from web pages",
66
"permissions": ["activeTab", "scripting"],
77
"host_permissions": ["<all_urls>"],

sentience/extension/release.json

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{
2-
"url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/273025127",
3-
"assets_url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/273025127/assets",
4-
"upload_url": "https://uploads.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/273025127/assets{?name,label}",
5-
"html_url": "https://github.com/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/tag/v2.0.3",
6-
"id": 273025127,
2+
"url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/273049720",
3+
"assets_url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/273049720/assets",
4+
"upload_url": "https://uploads.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/273049720/assets{?name,label}",
5+
"html_url": "https://github.com/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/tag/v2.0.5",
6+
"id": 273049720,
77
"author": {
88
"login": "rcholic",
99
"id": 135060,
@@ -25,21 +25,21 @@
2525
"user_view_type": "public",
2626
"site_admin": false
2727
},
28-
"node_id": "RE_kwDOQshiJ84QRghn",
29-
"tag_name": "v2.0.3",
28+
"node_id": "RE_kwDOQshiJ84QRmh4",
29+
"tag_name": "v2.0.5",
3030
"target_commitish": "main",
31-
"name": "Release v2.0.3",
31+
"name": "Release v2.0.5",
3232
"draft": false,
3333
"immutable": false,
3434
"prerelease": false,
35-
"created_at": "2025-12-27T01:12:14Z",
36-
"updated_at": "2025-12-27T22:46:31Z",
37-
"published_at": "2025-12-27T22:46:13Z",
35+
"created_at": "2025-12-28T06:21:06Z",
36+
"updated_at": "2025-12-28T06:52:14Z",
37+
"published_at": "2025-12-28T06:52:03Z",
3838
"assets": [
3939
{
40-
"url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/assets/333567799",
41-
"id": 333567799,
42-
"node_id": "RA_kwDOQshiJ84T4dc3",
40+
"url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/assets/333698157",
41+
"id": 333698157,
42+
"node_id": "RA_kwDOQshiJ84T49Rt",
4343
"name": "extension-files.tar.gz",
4444
"label": "",
4545
"uploader": {
@@ -65,17 +65,17 @@
6565
},
6666
"content_type": "application/gzip",
6767
"state": "uploaded",
68-
"size": 73434,
69-
"digest": "sha256:ca93cdaf875792eb22333f7ba5b13dd129552f388900e624422e73959338d8fb",
68+
"size": 76157,
69+
"digest": "sha256:726e388826fc3a5c401250db27ebd663167a96205594608b1bed2c98196cabab",
7070
"download_count": 0,
71-
"created_at": "2025-12-27T22:46:31Z",
72-
"updated_at": "2025-12-27T22:46:31Z",
73-
"browser_download_url": "https://github.com/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/download/v2.0.3/extension-files.tar.gz"
71+
"created_at": "2025-12-28T06:52:13Z",
72+
"updated_at": "2025-12-28T06:52:14Z",
73+
"browser_download_url": "https://github.com/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/download/v2.0.5/extension-files.tar.gz"
7474
},
7575
{
76-
"url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/assets/333567800",
77-
"id": 333567800,
78-
"node_id": "RA_kwDOQshiJ84T4dc4",
76+
"url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/assets/333698156",
77+
"id": 333698156,
78+
"node_id": "RA_kwDOQshiJ84T49Rs",
7979
"name": "extension-package.zip",
8080
"label": "",
8181
"uploader": {
@@ -101,15 +101,15 @@
101101
},
102102
"content_type": "application/zip",
103103
"state": "uploaded",
104-
"size": 75584,
105-
"digest": "sha256:291750ec174d9aadade298d2a2aa1057d08a138e2650c97cd93d56b6bcbee713",
104+
"size": 78281,
105+
"digest": "sha256:311a65065fef9c6d4b02597e4680e9e3f408f0d721a1d7595f6090ad3d794793",
106106
"download_count": 0,
107-
"created_at": "2025-12-27T22:46:31Z",
108-
"updated_at": "2025-12-27T22:46:31Z",
109-
"browser_download_url": "https://github.com/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/download/v2.0.3/extension-package.zip"
107+
"created_at": "2025-12-28T06:52:13Z",
108+
"updated_at": "2025-12-28T06:52:13Z",
109+
"browser_download_url": "https://github.com/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/download/v2.0.5/extension-package.zip"
110110
}
111111
],
112-
"tarball_url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/tarball/v2.0.3",
113-
"zipball_url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/zipball/v2.0.3",
112+
"tarball_url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/tarball/v2.0.5",
113+
"zipball_url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/zipball/v2.0.5",
114114
"body": ""
115115
}

0 commit comments

Comments
 (0)