import type { Element } from "cheerio"; import type { DocumentTraverser, IDocumentTraverser, } from "./document-traverser"; import { type ITagBuilder, TagBuilder } from "../../../elements"; import type { IAgentDriver } from "../agent-driver"; import type { DebugOpts } from "../../../types"; export interface IElementTypeHandler { handle(element: Element): string; } export class ElementTypeHandler implements IElementTypeHandler { element?: Element; docTraverser: IDocumentTraverser; output = ""; driver: IAgentDriver; tagBuilder: ITagBuilder; debug: boolean; opts: DebugOpts; constructor( driver: IAgentDriver, docTraverser: DocumentTraverser, opts: DebugOpts = {}, ) { this.driver = driver; this.debug = Boolean(opts.debug); this.opts = opts; this.docTraverser = docTraverser; this.tagBuilder = this.createTagBuilder(); } public handle(element: Element): string { this.element = element; this.handleMisc(); this.handleHeaderElement(); this.handleFormElement(); this.handleSections(); this.handleHeadersAndSectionElements(); return this.formatOutput(); } protected get $() { return this.docTraverser.$; } protected addToOutput(text: string) { this.output += text; } protected handleHeaderElement() { const { $, element } = this; if ($(element).is("h1, h2, h3, h4, h5, h6")) { this.addToOutput(`<${element?.name}>`); } } protected handleFormElement() { const { $, element } = this; if ($(element).is("form")) { this.addToOutput(`\n<${element?.name}>\n`); } } protected handleSections() { const { $, element } = this; if ($(element).is("div, section, main")) { this.addToOutput("\n"); } } protected handleHeadersAndSectionElements() { const { $, element } = this; if ($(element).is("h1, h2, h3, h4, h5, h6, div, section, main")) { this.addToOutput("\n"); } } protected makeTag(element?: Element) { if (!element) { throw new Error("Missing element to build tag from"); } return this.tagBuilder.build(element); } protected createTagBuilder() { return new TagBuilder(this.driver); } // biome-ignore lint/suspicious/noExplicitAny: protected handleSpecialAttr(elemTag: any) { const { $, element } = this; if ($(element).attr("pgpt-id")) { this.addToOutput(` ${elemTag.tagName ? elemTag.tagName : ""}`); return true; } return false; } protected handleNonSpecialTag() { const { $, element } = this; const parent = element?.parent; if (element?.type === "tag" && parent && !$(parent).attr("pgpt-id")) { this.addToOutput( ` ${ // biome-ignore lint/suspicious/noExplicitAny: (element as any).data?.trim() }`, ); return true; } return false; } protected handleMisc() { const elemTag = this.makeTag(this.element); this.handleSpecialAttr(elemTag) || this.handleNonSpecialTag(); } protected traverse(element: Element) { return this.docTraverser.traverse(element); } protected handleChildren() { const children = this.element?.children; if (children) { // biome-ignore lint/complexity/noForEach: // biome-ignore lint/suspicious/noExplicitAny: children.forEach((child: any) => { this.addToOutput(this.traverse(child)); }); } } protected formatOutput() { return this.output .replace(/[^\S\n]+/g, " ") .replace(/ \n+/g, "\n") .replace(/[\n]+/g, "\n"); } }