|
158 | 158 | return null; |
159 | 159 | } |
160 | 160 | function getText(el) { |
161 | | - return el.getAttribute("aria-label") ? el.getAttribute("aria-label") : "INPUT" === el.tagName ? el.value || el.placeholder || "" : "IMG" === el.tagName ? el.alt || "" : (el.innerText || "").replace(/\s+/g, " ").trim().substring(0, 100); |
| 161 | + if (el.getAttribute("aria-label")) return el.getAttribute("aria-label"); |
| 162 | + if ("INPUT" === el.tagName) { |
| 163 | + const t = el.getAttribute && el.getAttribute("type") || el.type || ""; |
| 164 | + return "password" === String(t).toLowerCase() ? el.placeholder || "" : el.value || el.placeholder || ""; |
| 165 | + } |
| 166 | + return "IMG" === el.tagName ? el.alt || "" : (el.innerText || "").replace(/\s+/g, " ").trim().substring(0, 100); |
162 | 167 | } |
163 | 168 | function getClassName(el) { |
164 | 169 | if (!el || !el.className) return ""; |
|
268 | 273 | try { |
269 | 274 | !1 !== options.waitForStability && await async function(options = {}) { |
270 | 275 | const {minNodeCount: minNodeCount = 500, quietPeriod: quietPeriod = 200, maxWait: maxWait = 5e3} = options, startTime = Date.now(); |
| 276 | + try { |
| 277 | + window.__sentience_lastMutationTs = performance.now(); |
| 278 | + } catch (e) {} |
271 | 279 | return new Promise(resolve => { |
272 | 280 | if (document.querySelectorAll("*").length >= minNodeCount) { |
273 | 281 | let lastChange = Date.now(); |
274 | 282 | const observer = new MutationObserver(() => { |
275 | 283 | lastChange = Date.now(); |
| 284 | + try { |
| 285 | + window.__sentience_lastMutationTs = performance.now(); |
| 286 | + } catch (e) {} |
276 | 287 | }); |
277 | 288 | observer.observe(document.body, { |
278 | 289 | childList: !0, |
|
288 | 299 | } else { |
289 | 300 | const observer = new MutationObserver(() => { |
290 | 301 | const currentCount = document.querySelectorAll("*").length, totalWait = Date.now() - startTime; |
| 302 | + try { |
| 303 | + window.__sentience_lastMutationTs = performance.now(); |
| 304 | + } catch (e) {} |
291 | 305 | if (currentCount >= minNodeCount) { |
292 | 306 | observer.disconnect(); |
293 | 307 | let lastChange = Date.now(); |
294 | 308 | const quietObserver = new MutationObserver(() => { |
295 | 309 | lastChange = Date.now(); |
| 310 | + try { |
| 311 | + window.__sentience_lastMutationTs = performance.now(); |
| 312 | + } catch (e) {} |
296 | 313 | }); |
297 | 314 | quietObserver.observe(document.body, { |
298 | 315 | childList: !0, |
|
323 | 340 | if (!el.getBoundingClientRect) return; |
324 | 341 | const rect = el.getBoundingClientRect(); |
325 | 342 | if (rect.width < 5 || rect.height < 5) return; |
326 | | - if ("span" === el.tagName.toLowerCase()) { |
| 343 | + const tagName = el.tagName.toLowerCase(); |
| 344 | + if ("span" === tagName) { |
327 | 345 | if (el.closest("a")) return; |
328 | 346 | const childLink = el.querySelector("a[href]"); |
329 | 347 | if (childLink && childLink.href) return; |
330 | 348 | options.debug && el.className && el.className.includes("titleline"); |
331 | 349 | } |
332 | 350 | window.sentience_registry[idx] = el; |
333 | | - const semanticText = function(el, options = {}) { |
| 351 | + const inputType = "input" === tagName ? toSafeString(el.getAttribute && el.getAttribute("type") || el.type || null) : null, isPasswordInput = inputType && "password" === inputType.toLowerCase(), semanticText = function(el, options = {}) { |
334 | 352 | if (!el) return { |
335 | 353 | text: "", |
336 | 354 | source: null |
|
341 | 359 | source: "explicit_aria_label" |
342 | 360 | }; |
343 | 361 | if ("INPUT" === el.tagName) { |
344 | | - const value = (el.value || el.placeholder || "").trim(); |
| 362 | + const t = el.getAttribute && el.getAttribute("type") || el.type || "", isPassword = "password" === String(t).toLowerCase(), value = (isPassword ? el.placeholder || "" : el.value || el.placeholder || "").trim(); |
345 | 363 | if (value) return { |
346 | 364 | text: value, |
347 | | - source: "input_value" |
| 365 | + source: isPassword ? "input_placeholder" : "input_value" |
348 | 366 | }; |
349 | 367 | } |
350 | 368 | if ("IMG" === el.tagName) { |
|
417 | 435 | } |
418 | 436 | return null; |
419 | 437 | }(el); |
| 438 | + let safeValue = null, valueRedacted = null; |
| 439 | + try { |
| 440 | + if (void 0 !== el.value || el.getAttribute && null !== el.getAttribute("value")) if (isPasswordInput) safeValue = null, |
| 441 | + valueRedacted = "true"; else { |
| 442 | + const rawValue = void 0 !== el.value ? String(el.value) : String(el.getAttribute("value")); |
| 443 | + safeValue = rawValue.length > 200 ? rawValue.substring(0, 200) : rawValue, valueRedacted = "false"; |
| 444 | + } |
| 445 | + } catch (e) {} |
| 446 | + const accessibleName = toSafeString(function(el) { |
| 447 | + if (!el || !el.getAttribute) return ""; |
| 448 | + const ariaLabel = el.getAttribute("aria-label"); |
| 449 | + if (ariaLabel && ariaLabel.trim()) return ariaLabel.trim().substring(0, 200); |
| 450 | + const labelledBy = el.getAttribute("aria-labelledby"); |
| 451 | + if (labelledBy && labelledBy.trim()) { |
| 452 | + const ids = labelledBy.split(/\s+/).filter(id => id.trim()), texts = []; |
| 453 | + for (const id of ids) try { |
| 454 | + const ref = document.getElementById(id); |
| 455 | + if (!ref) continue; |
| 456 | + const txt = (ref.innerText || ref.textContent || ref.getAttribute?.("aria-label") || "").toString().trim(); |
| 457 | + txt && texts.push(txt); |
| 458 | + } catch (e) {} |
| 459 | + if (texts.length > 0) return texts.join(" ").substring(0, 200); |
| 460 | + } |
| 461 | + try { |
| 462 | + if (el.labels && el.labels.length > 0) { |
| 463 | + const t = (el.labels[0].innerText || el.labels[0].textContent || "").toString().trim(); |
| 464 | + if (t) return t.substring(0, 200); |
| 465 | + } |
| 466 | + } catch (e) {} |
| 467 | + try { |
| 468 | + const parentLabel = el.closest && el.closest("label"); |
| 469 | + if (parentLabel) { |
| 470 | + const t = (parentLabel.innerText || parentLabel.textContent || "").toString().trim(); |
| 471 | + if (t) return t.substring(0, 200); |
| 472 | + } |
| 473 | + } catch (e) {} |
| 474 | + const tag = (el.tagName || "").toUpperCase(); |
| 475 | + if ("INPUT" === tag || "TEXTAREA" === tag) { |
| 476 | + const ph = (el.getAttribute("placeholder") || "").toString().trim(); |
| 477 | + if (ph) return ph.substring(0, 200); |
| 478 | + } |
| 479 | + const title = el.getAttribute("title"); |
| 480 | + return title && title.trim() ? title.trim().substring(0, 200) : ""; |
| 481 | + }(el) || null); |
420 | 482 | rawData.push({ |
421 | 483 | id: idx, |
422 | | - tag: el.tagName.toLowerCase(), |
| 484 | + tag: tagName, |
423 | 485 | rect: { |
424 | 486 | x: rect.x, |
425 | 487 | y: rect.y, |
|
441 | 503 | attributes: { |
442 | 504 | role: toSafeString(el.getAttribute("role")), |
443 | 505 | type_: toSafeString(el.getAttribute("type")), |
| 506 | + input_type: inputType, |
444 | 507 | aria_label: "explicit_aria_label" === semanticText?.source ? semanticText.text : toSafeString(el.getAttribute("aria-label")), |
| 508 | + name: accessibleName, |
445 | 509 | inferred_label: semanticText?.source && ![ "explicit_aria_label", "input_value", "img_alt", "inner_text" ].includes(semanticText.source) ? toSafeString(semanticText.text) : null, |
446 | 510 | label_source: semanticText?.source || null, |
447 | 511 | inferred_role: inferredRole ? toSafeString(inferredRole) : null, |
448 | 512 | href: toSafeString(el.href || el.getAttribute("href") || el.closest && el.closest("a")?.href || null), |
449 | 513 | class: toSafeString(getClassName(el)), |
450 | | - value: void 0 !== el.value ? toSafeString(el.value) : toSafeString(el.getAttribute("value")), |
451 | | - checked: void 0 !== el.checked ? String(el.checked) : null |
| 514 | + value: null !== safeValue ? toSafeString(safeValue) : null, |
| 515 | + value_redacted: valueRedacted, |
| 516 | + checked: void 0 !== el.checked ? String(el.checked) : null, |
| 517 | + disabled: void 0 !== el.disabled ? String(el.disabled) : null, |
| 518 | + aria_checked: toSafeString(el.getAttribute("aria-checked")), |
| 519 | + aria_disabled: toSafeString(el.getAttribute("aria-disabled")), |
| 520 | + aria_expanded: toSafeString(el.getAttribute("aria-expanded")) |
452 | 521 | }, |
453 | 522 | text: toSafeString(textVal), |
454 | 523 | in_viewport: inView, |
|
576 | 645 | }(options.screenshot)); |
577 | 646 | const cleanedElements = cleanElement(processed.elements), cleanedRawElements = cleanElement(processed.raw_elements); |
578 | 647 | cleanedElements.length, cleanedRawElements.length; |
| 648 | + let diagnostics; |
| 649 | + try { |
| 650 | + const lastMutationTs = window.__sentience_lastMutationTs, now = performance.now(), quietMs = "number" == typeof lastMutationTs && Number.isFinite(lastMutationTs) ? Math.max(0, now - lastMutationTs) : null, nodeCount = document.querySelectorAll("*").length; |
| 651 | + diagnostics = { |
| 652 | + metrics: { |
| 653 | + ready_state: document.readyState || null, |
| 654 | + quiet_ms: quietMs, |
| 655 | + node_count: nodeCount |
| 656 | + } |
| 657 | + }; |
| 658 | + } catch (e) {} |
579 | 659 | return { |
580 | 660 | status: "success", |
581 | 661 | url: window.location.href, |
|
585 | 665 | }, |
586 | 666 | elements: cleanedElements, |
587 | 667 | raw_elements: cleanedRawElements, |
588 | | - screenshot: screenshot |
| 668 | + screenshot: screenshot, |
| 669 | + diagnostics: diagnostics |
589 | 670 | }; |
590 | 671 | } catch (error) { |
591 | 672 | return { |
|
0 commit comments