UNPKG

@monitoro/herd

Version:

Automate your browser, build AI web tools and MCP servers with Monitoro Herd

142 lines (141 loc) 5.1 kB
import { EventEmitter } from 'events'; export class Node extends EventEmitter { constructor(serialized, page) { super(); this._children = []; this._serialized = serialized; this._page = page; // Initialize children if (serialized.children) { this._children = serialized.children .filter((child) => child !== null) .map(child => new Node(child, page)); } } // Node type properties get nodeType() { return this._serialized.nodeType === 'text' ? 3 : 1; // Element = 1, Text = 3 } get nodeName() { return this._serialized.tagName || '#text'; } get nodeValue() { return this._serialized.textContent || null; } // Element-like properties get tagName() { return this._serialized.tagName || ''; } get textContent() { // For text nodes, return their content directly if (this.nodeType === 3) { return this._serialized.textContent || null; } // For element nodes, concatenate text content of all child nodes let content = ''; for (const child of this._children) { const childContent = child.textContent; if (childContent) { // Add space for inline elements, newline for block elements const separator = this.isBlockElement(child) ? "\n" : " "; content += separator + childContent; } } return content || null; } isBlockElement(node) { const blockElements = [ 'address', 'article', 'aside', 'blockquote', 'canvas', 'dd', 'div', 'dl', 'dt', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hr', 'li', 'main', 'nav', 'noscript', 'ol', 'p', 'pre', 'section', 'table', 'tfoot', 'ul', 'video' ]; return blockElements.includes(node.tagName.toLowerCase()); } get innerText() { return this.textContent; } get innerHTML() { return this._serialized.innerHTML; } // Child access methods get childNodes() { return this._children; } get firstChild() { return this._children[0] || null; } get lastChild() { return this._children[this._children.length - 1] || null; } // Attribute methods getAttribute(name) { return this._serialized.attributes?.[name] || null; } hasAttribute(name) { return !!this._serialized.attributes?.[name]; } // DOM-like methods implemented via Page async click(options = {}) { const selector = this._serialized._meta.selector; await this._page.click(selector, options); } async type(text, options = {}) { const selector = this._serialized._meta.selector; await this._page.type(selector, text, options); } async focus(options = {}) { const selector = this._serialized._meta.selector; await this._page.focus(selector, options); } async blur(options = {}) { const selector = this._serialized._meta.selector; await this._page.blur(selector, options); } async hover(options = {}) { const selector = this._serialized._meta.selector; await this._page.hover(selector, options); } async scrollIntoView(options = {}) { const selector = this._serialized._meta.selector; await this._page.scrollIntoView(selector, options); } async setValue(value, options = {}) { const selector = this._serialized._meta.selector; await this._page.setValue(selector, value, options); } async dispatchEvent(eventName, detail, options = {}) { const selector = this._serialized._meta.selector; await this._page.dispatchEvent(eventName, selector, detail, options); } async dragTo(target, options = {}) { const sourceSelector = this._serialized._meta.selector; const targetSelector = typeof target === 'string' ? target : target._serialized._meta.selector; await this._page.drag(sourceSelector, targetSelector, options); } // Query methods that return new Node instances async $(selector) { const result = await this._page._$(selector, this._serialized._meta.selector); return result ? new Node(result, this._page) : null; } async $$(selector) { const results = await this._page._$$(selector, this._serialized._meta.selector); return results.map(result => new Node(result, this._page)); } async querySelector(selector) { return this.$(selector); } async querySelectorAll(selector) { return this.$$(selector); } // Position and size getBoundingClientRect() { return { x: this._serialized.position?.x || 0, y: this._serialized.position?.y || 0, width: this._serialized.size?.width || 0, height: this._serialized.size?.height || 0 }; } }