UNPKG

@hyperbrowser/agent

Version:

Hyperbrowsers Web Agent

108 lines (107 loc) 4.47 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.buildDomView = void 0; const find_interactive_elements_1 = require("./find-interactive-elements"); const highlight_1 = require("./highlight"); const get_css_path_1 = require("./get-css-path"); const const_1 = require("./const"); const get_x_path_1 = require("./get-x-path"); // Helper function to convert ImageBitmap to PNG Data URL const imageBitmapToPngDataUrl = (bitmap) => { try { // Create an intermediate canvas const canvas = document.createElement("canvas"); canvas.width = bitmap.width; canvas.height = bitmap.height; // Get context and draw the bitmap const ctx = canvas.getContext("2d"); ctx.drawImage(bitmap, 0, 0); // Export as PNG Data URL // Note: might want to add error handling for toDataURL return canvas.toDataURL("image/png"); } finally { // Close the bitmap to free up resources (important!) bitmap.close(); } }; // --- Start new function definition --- const getElementTextContent = (el) => { const tagName = el.tagName.toLowerCase(); if (tagName === "input") { const inputElement = el; let labelText = null; // Try finding label by "for" attribute if (inputElement.id) { const label = document.querySelector(`label[for="${inputElement.id}"]`); if (label) { labelText = label.textContent?.trim() || null; } } // Use label text if found, otherwise use input value. Fallback to empty string if neither. return labelText ?? inputElement.value?.trim() ?? ""; } else { // Original logic for non-input elements return el.textContent?.trim() || ""; } }; // --- End new function definition --- const buildDomView = () => { const interactiveElements = (0, find_interactive_elements_1.findInteractiveElements)(); // 1. Render highlights to an ImageBitmap const screenBitmap = (0, highlight_1.renderHighlightsOffscreen)(interactiveElements.map((element, index) => ({ element: element.element, index: index + 1, // index range from 1 -> index parentIframe: element.iframe ?? null, })), window.innerWidth, window.innerHeight); // 2. Convert the ImageBitmap to a PNG Data URL const screenshotPngDataUrl = imageBitmapToPngDataUrl(screenBitmap); for (let idx = 0; idx < interactiveElements.length; idx++) { const element = interactiveElements[idx]; element.highlightIndex = idx + 1; // index range from 1 -> index element.cssPath = (0, get_css_path_1.getCSSPath)(element.element); element.xpath = (0, get_x_path_1.getXPath)(element.element); } const domRepresentation = []; const getTextBetween = (node, nextNode) => { const texts = []; let current = node.nextSibling; while (current && current !== nextNode) { if (current.nodeType === Node.TEXT_NODE && current.textContent) { const text = current.textContent.trim(); if (text) texts.push(text); } current = current.nextSibling; } return texts.join(" "); }; for (let i = 0; i < interactiveElements.length; i++) { const element = interactiveElements[i]; const el = element.element; const tagName = el.tagName.toLowerCase(); let attributes = ""; Array.from(el.attributes).forEach((attr) => { if (const_1.CONTEXT_ATTRIBUTES.includes(attr.name)) { attributes += ` ${attr.name}="${attr.value}"`; } }); // Use the helper function to get text content const textContent = getElementTextContent(el); const indexPrefix = `[${element.highlightIndex}]`; const elementString = `${indexPrefix}<${tagName}${attributes}>${textContent.replace(/\s+/g, " ")}</${tagName}>`; domRepresentation.push(elementString); const nextElement = interactiveElements[i + 1]?.element || null; const betweenText = getTextBetween(el, nextElement); if (betweenText) { domRepresentation.push(betweenText); } } return { elements: interactiveElements, domState: domRepresentation.join("\n"), screenshot: screenshotPngDataUrl, }; }; exports.buildDomView = buildDomView;