rabbit-browser
Version:
Browser automation tool for detecting interactive elements on web pages
187 lines • 7.34 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.simpleRabbitBrowser = exports.SimpleRabbitBrowser = void 0;
const logger_1 = require("./utils/logger");
const puppeteer_1 = require("./browser/puppeteer");
const elementDetector_1 = require("./highlighting/elementDetector");
const highlighter_1 = require("./highlighting/highlighter");
/**
* Simple API to detect and highlight interactive elements on web pages
*/
class SimpleRabbitBrowser {
/**
* Create a new SimpleRabbitBrowser instance
*/
constructor(options = {}) {
this.browser = null;
this.page = null;
this.elements = [];
this.textBlocks = [];
this.pageContext = null;
// Default options
this.options = {
focusOnConsent: options.focusOnConsent ?? false,
waitTime: options.waitTime ?? 3000,
logDetails: options.logDetails ?? false,
earlyReturn: options.earlyReturn ?? true,
includePageContext: options.includePageContext ?? true,
includeFormInputs: options.includeFormInputs ?? true,
includeTextBlocks: options.includeTextBlocks ?? true,
highlightAllText: options.highlightAllText ?? true,
};
}
/**
* Navigate to a URL and detect elements
* @param url The URL to navigate to
* @returns Promise resolving when navigation and detection are complete
*/
async go(url) {
try {
// Launch browser if not already running
if (!this.browser) {
this.browser = await (0, puppeteer_1.setupBrowser)();
}
// Create a new page if needed
if (!this.page) {
this.page = await (0, puppeteer_1.setupPage)(this.browser);
}
// Clear previous elements
this.elements = [];
this.textBlocks = [];
this.pageContext = null;
// Navigate to URL
await (0, puppeteer_1.navigateTo)(this.page, url);
// Initialize components
await (0, highlighter_1.initializeHighlighter)(this.page);
await (0, elementDetector_1.initializeElementDetector)(this.page, {
focusOnConsent: this.options.focusOnConsent,
includeFormInputs: this.options.includeFormInputs,
highlightAllText: this.options.highlightAllText,
});
// Start detecting elements
await this.page.evaluate(() => {
window.processedElements = new Set();
window.processedTextBlocks = new Set();
window.highlightedElements = window.highlightedElements || [];
window.highlightedTextBlocks = window.highlightedTextBlocks || [];
window.startObservingNewElements();
});
// Log if enabled
if (this.options.logDetails) {
(0, logger_1.log)("Detecting interactive elements and text blocks...");
}
// Progressive checking for elements
const checkIntervals = [300, 500, 700, 1000, 1500];
let totalWaitTime = 0;
// Check at increasing intervals
for (const interval of checkIntervals) {
if (totalWaitTime >= this.options.waitTime)
break;
await new Promise((resolve) => setTimeout(resolve, interval));
totalWaitTime += interval;
// Collect elements and text blocks
const data = await (0, highlighter_1.collectElementData)(this.page);
this.elements = data.elements;
this.textBlocks = data.textBlocks;
// Early return if we found elements
if (this.options.earlyReturn && this.elements.length > 0) {
if (this.options.logDetails) {
(0, logger_1.log)(`Found ${this.elements.length} elements and ${this.textBlocks.length} text blocks after ${totalWaitTime}ms - returning early`);
}
break;
}
}
// Final wait if needed
if (this.elements.length === 0 && totalWaitTime < this.options.waitTime) {
const remainingTime = this.options.waitTime - totalWaitTime;
if (this.options.logDetails) {
(0, logger_1.log)(`Waiting additional ${remainingTime}ms for elements...`);
}
await new Promise((resolve) => setTimeout(resolve, remainingTime));
const data = await (0, highlighter_1.collectElementData)(this.page);
this.elements = data.elements;
this.textBlocks = data.textBlocks;
}
// Collect page context if requested
if (this.options.includePageContext) {
if (this.options.logDetails) {
(0, logger_1.log)("Collecting page text context for AI analysis...");
}
const contextData = await (0, highlighter_1.collectPageTextContext)(this.page);
this.pageContext = contextData.pageContext;
}
// Log results if enabled
if (this.options.logDetails) {
if (this.elements.length === 0) {
(0, logger_1.log)("WARNING: No interactive elements were detected");
}
else {
(0, logger_1.log)(`Detected ${this.elements.length} elements and ${this.textBlocks.length} text blocks`);
}
}
}
catch (error) {
// Clean up on error
if (this.browser) {
try {
await this.browser.close();
}
catch (e) {
// Ignore errors when closing
}
this.browser = null;
this.page = null;
}
(0, logger_1.log)(`Error detecting elements: ${error}`);
throw error;
}
}
/**
* Get detected elements
* @returns Array of detected elements
*/
getElements() {
return this.elements;
}
/**
* Get text blocks
* @returns Array of text blocks
*/
getTextBlocks() {
return this.textBlocks;
}
/**
* Get page context information including text content
* @returns Page context object with text content
*/
getPageContext() {
return this.pageContext;
}
/**
* Get complete data with both elements and page context
* @returns Object containing elements and page context
*/
getCompleteData() {
return {
elements: this.elements,
textBlocks: this.textBlocks,
pageContext: this.pageContext,
};
}
/**
* Close the browser if it's open
*/
async close() {
if (this.browser) {
await this.browser.close();
this.browser = null;
this.page = null;
}
}
}
exports.SimpleRabbitBrowser = SimpleRabbitBrowser;
/**
* Global instance for simple use
*/
exports.simpleRabbitBrowser = new SimpleRabbitBrowser();
//# sourceMappingURL=SimpleRabbitBrowser.js.map