@mcp-b/smart-dom-reader 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/content-detection.ts","../src/selectors.ts","../src/traversal.ts","../src/markdown-formatter.ts","../src/progressive.ts","../src/types.ts","../src/index.ts"],"sourcesContent":["export class ContentDetection {\n /**\n * Find the main content area of a page\n * Inspired by dom-to-semantic-markdown's approach\n */\n static findMainContent(doc: Document): Element {\n // First, check for explicit main element\n const mainElement = doc.querySelector('main, [role=\"main\"]');\n if (mainElement) {\n return mainElement;\n }\n\n // If no explicit main, detect it\n if (!doc.body) {\n return doc.documentElement;\n }\n\n return this.detectMainContent(doc.body);\n }\n\n /**\n * Detect main content using scoring algorithm\n */\n private static detectMainContent(rootElement: Element): Element {\n const candidates: Element[] = [];\n const minScore = 15;\n\n this.collectCandidates(rootElement, candidates, minScore);\n\n if (candidates.length === 0) {\n return rootElement;\n }\n\n // Sort by score\n candidates.sort((a, b) => this.calculateContentScore(b) - this.calculateContentScore(a));\n\n // Find best independent candidate\n let bestCandidate = candidates[0];\n for (let i = 1; i < candidates.length; i++) {\n // Check if this candidate is not contained in any other\n const isIndependent = !candidates.some(\n (other, j) => j !== i && other.contains(candidates[i])\n );\n\n if (\n isIndependent &&\n this.calculateContentScore(candidates[i]) > this.calculateContentScore(bestCandidate)\n ) {\n bestCandidate = candidates[i];\n }\n }\n\n return bestCandidate;\n }\n\n /**\n * Collect content candidates\n */\n private static collectCandidates(\n element: Element,\n candidates: Element[],\n minScore: number\n ): void {\n const score = this.calculateContentScore(element);\n if (score >= minScore) {\n candidates.push(element);\n }\n\n // Recursively check children\n Array.from(element.children).forEach((child) => {\n this.collectCandidates(child, candidates, minScore);\n });\n }\n\n /**\n * Calculate content score for an element\n */\n static calculateContentScore(element: Element): number {\n let score = 0;\n\n // High impact semantic indicators\n const semanticClasses = [\n 'article',\n 'content',\n 'main-container',\n 'main',\n 'main-content',\n 'post',\n 'entry',\n ];\n const semanticIds = ['content', 'main', 'article', 'post', 'entry'];\n\n // Check classes\n semanticClasses.forEach((cls) => {\n if (element.classList.contains(cls)) {\n score += 10;\n }\n });\n\n // Check ID\n semanticIds.forEach((id) => {\n if (element.id && element.id.toLowerCase().includes(id)) {\n score += 10;\n }\n });\n\n // High value tags\n const tag = element.tagName.toLowerCase();\n const highValueTags = ['article', 'main', 'section'];\n if (highValueTags.includes(tag)) {\n score += 8;\n }\n\n // Paragraph density\n const paragraphs = element.getElementsByTagName('p').length;\n score += Math.min(paragraphs * 2, 10);\n\n // Heading presence\n const headings = element.querySelectorAll('h1, h2, h3').length;\n score += Math.min(headings * 3, 9);\n\n // Text content length\n const textLength = element.textContent?.trim().length || 0;\n if (textLength > 300) {\n score += Math.min(Math.floor(textLength / 300) * 2, 10);\n }\n\n // Link density (lower is better for content)\n const linkDensity = this.calculateLinkDensity(element);\n if (linkDensity < 0.3) {\n score += 5;\n } else if (linkDensity > 0.5) {\n score -= 5;\n }\n\n // Data attributes\n if (\n element.hasAttribute('data-main') ||\n element.hasAttribute('data-content') ||\n element.hasAttribute('itemprop')\n ) {\n score += 8;\n }\n\n // ARIA landmarks\n const role = element.getAttribute('role');\n if (role === 'main' || role === 'article') {\n score += 10;\n }\n\n // Penalize certain elements\n if (\n element.matches(\n 'aside, nav, header, footer, .sidebar, .navigation, .menu, .ad, .advertisement'\n )\n ) {\n score -= 10;\n }\n\n // Check for form density (forms are usually not main content)\n const forms = element.getElementsByTagName('form').length;\n if (forms > 2) {\n score -= 5;\n }\n\n return Math.max(0, score);\n }\n\n /**\n * Calculate link density in an element\n */\n private static calculateLinkDensity(element: Element): number {\n const links = element.getElementsByTagName('a');\n let linkTextLength = 0;\n\n for (const link of Array.from(links)) {\n linkTextLength += link.textContent?.length || 0;\n }\n\n const totalTextLength = element.textContent?.length || 1;\n return linkTextLength / totalTextLength;\n }\n\n /**\n * Check if an element is likely navigation\n */\n static isNavigation(element: Element): boolean {\n const tag = element.tagName.toLowerCase();\n\n // Explicit navigation elements\n if (tag === 'nav' || element.getAttribute('role') === 'navigation') {\n return true;\n }\n\n // Check for navigation patterns\n const navPatterns = [/nav/i, /menu/i, /sidebar/i, /toolbar/i];\n\n const classesAndId = (element.className + ' ' + element.id).toLowerCase();\n return navPatterns.some((pattern) => pattern.test(classesAndId));\n }\n\n /**\n * Check if element is likely supplementary content\n */\n static isSupplementary(element: Element): boolean {\n const tag = element.tagName.toLowerCase();\n\n // Explicit supplementary elements\n if (tag === 'aside' || element.getAttribute('role') === 'complementary') {\n return true;\n }\n\n // Check for supplementary patterns\n const supplementaryPatterns = [/sidebar/i, /widget/i, /related/i, /advertisement/i, /social/i];\n\n const classesAndId = (element.className + ' ' + element.id).toLowerCase();\n return supplementaryPatterns.some((pattern) => pattern.test(classesAndId));\n }\n\n /**\n * Detect page landmarks\n */\n static detectLandmarks(doc: Document): Record<string, Element[]> {\n const landmarks: Record<string, Element[]> = {\n navigation: [],\n main: [],\n complementary: [],\n contentinfo: [],\n banner: [],\n search: [],\n form: [],\n region: [],\n };\n\n // Find explicit landmarks\n const landmarkSelectors = {\n navigation: 'nav, [role=\"navigation\"]',\n main: 'main, [role=\"main\"]',\n complementary: 'aside, [role=\"complementary\"]',\n contentinfo: 'footer, [role=\"contentinfo\"]',\n banner: 'header, [role=\"banner\"]',\n search: '[role=\"search\"]',\n form: 'form[aria-label], form[aria-labelledby], [role=\"form\"]',\n region: 'section[aria-label], section[aria-labelledby], [role=\"region\"]',\n };\n\n for (const [landmark, selector] of Object.entries(landmarkSelectors)) {\n const elements = doc.querySelectorAll(selector);\n landmarks[landmark] = Array.from(elements);\n }\n\n return landmarks;\n }\n}\n","import { ElementSelector, type ElementSelectorCandidate } from './types';\n\nexport class SelectorGenerator {\n /**\n * Generate multiple selector strategies for an element\n */\n static generateSelectors(element: Element): ElementSelector {\n const doc = element.ownerDocument || document;\n const candidates: ElementSelectorCandidate[] = [];\n\n // 1) Unique ID\n if (element.id && this.isUniqueId(element.id, doc)) {\n candidates.push({ type: 'id', value: `#${CSS.escape(element.id)}`, score: 100 });\n }\n\n // 2) data-testid variants\n const testId = this.getDataTestId(element);\n if (testId) {\n const v = `[data-testid=\"${CSS.escape(testId)}\"]`;\n candidates.push({\n type: 'data-testid',\n value: v,\n score: 90 + (this.isUniqueSelectorSafe(v, doc) ? 5 : 0),\n });\n }\n\n // 3) role + aria-label\n const role = element.getAttribute('role');\n const aria = element.getAttribute('aria-label');\n if (role && aria) {\n const v = `[role=\"${CSS.escape(role)}\"][aria-label=\"${CSS.escape(aria)}\"]`;\n candidates.push({\n type: 'role-aria',\n value: v,\n score: 85 + (this.isUniqueSelectorSafe(v, doc) ? 5 : 0),\n });\n }\n\n // 4) name attribute (useful for inputs)\n const nameAttr = element.getAttribute('name');\n if (nameAttr) {\n const v = `[name=\"${CSS.escape(nameAttr)}\"]`;\n candidates.push({\n type: 'name',\n value: v,\n score: 78 + (this.isUniqueSelectorSafe(v, doc) ? 5 : 0),\n });\n }\n\n // 5) Class-based CSS path (try to avoid structural :nth-child when possible)\n const pathCss = this.generateCSSSelector(element, doc);\n const structuralPenalty = (pathCss.match(/:nth-child\\(/g) || []).length * 10;\n const classBonus = pathCss.includes('.') ? 8 : 0;\n const pathScore = Math.max(0, 70 + classBonus - structuralPenalty);\n candidates.push({ type: 'class-path', value: pathCss, score: pathScore });\n\n // 6) XPath (fallback)\n const xpath = this.generateXPath(element, doc);\n candidates.push({ type: 'xpath', value: xpath, score: 40 });\n\n // 7) Text-based (only for hints)\n const textBased = this.generateTextBasedSelector(element);\n if (textBased) candidates.push({ type: 'text', value: textBased, score: 30 });\n\n // Rank candidates by score (desc)\n candidates.sort((a, b) => b.score - a.score);\n\n const bestCss =\n candidates.find((c) => c.type !== 'xpath' && c.type !== 'text')?.value || pathCss;\n\n return {\n css: bestCss,\n xpath,\n textBased,\n dataTestId: testId || undefined,\n ariaLabel: aria || undefined,\n candidates,\n };\n }\n\n /**\n * Generate a unique CSS selector for an element\n */\n private static generateCSSSelector(element: Element, doc: Document): string {\n // If element has a unique ID, use it\n if (element.id && this.isUniqueId(element.id, doc)) {\n return `#${CSS.escape(element.id)}`;\n }\n\n // Try data-testid or data-test-id\n const testId = this.getDataTestId(element);\n if (testId) {\n return `[data-testid=\"${CSS.escape(testId)}\"]`;\n }\n\n // Build a path from the element to the root\n const path: string[] = [];\n let current: Element | null = element;\n\n while (current && current.nodeType === Node.ELEMENT_NODE) {\n let selector = current.nodeName.toLowerCase();\n\n if (current.id && this.isUniqueId(current.id, doc)) {\n selector = `#${CSS.escape(current.id)}`;\n path.unshift(selector);\n break;\n }\n\n // Add classes if they exist and are meaningful\n const classes = this.getMeaningfulClasses(current);\n if (classes.length > 0) {\n selector += '.' + classes.map((c) => CSS.escape(c)).join('.');\n }\n\n // Add position if needed for uniqueness\n const siblings = current.parentElement?.children;\n if (siblings && siblings.length > 1) {\n const index = Array.from(siblings).indexOf(current);\n if (index > 0 || !this.isUniqueSelector(selector, current.parentElement!)) {\n selector += `:nth-child(${index + 1})`;\n }\n }\n\n path.unshift(selector);\n current = current.parentElement;\n }\n\n // Optimize the path\n return this.optimizePath(path, element, doc);\n }\n\n /**\n * Generate XPath for an element\n */\n private static generateXPath(element: Element, doc: Document): string {\n if (element.id && this.isUniqueId(element.id, doc)) {\n return `//*[@id=\"${element.id}\"]`;\n }\n\n const path: string[] = [];\n let current: Element | null = element;\n\n while (current && current.nodeType === Node.ELEMENT_NODE) {\n const tagName = current.nodeName.toLowerCase();\n\n if (current.id && this.isUniqueId(current.id, doc)) {\n path.unshift(`//*[@id=\"${current.id}\"]`);\n break;\n }\n\n let xpath = tagName;\n\n // Add index if there are siblings with same tag\n const siblings = current.parentElement?.children;\n if (siblings) {\n const sameTagSiblings = Array.from(siblings).filter(\n (s) => s.nodeName.toLowerCase() === tagName\n );\n if (sameTagSiblings.length > 1) {\n const index = sameTagSiblings.indexOf(current) + 1;\n xpath += `[${index}]`;\n }\n }\n\n path.unshift(xpath);\n current = current.parentElement;\n }\n\n return '//' + path.join('/');\n }\n\n /**\n * Generate a text-based selector for buttons and links\n */\n private static generateTextBasedSelector(element: Element): string | undefined {\n const text = element.textContent?.trim();\n if (!text || text.length > 50) return undefined;\n\n const tag = element.nodeName.toLowerCase();\n if (['button', 'a', 'label'].includes(tag)) {\n // Escape special characters in text\n const escapedText = text.replace(/['\"\\\\]/g, '\\\\$&');\n return `${tag}:contains(\"${escapedText}\")`;\n }\n\n return undefined;\n }\n\n /**\n * Get data-testid or similar attributes\n */\n private static getDataTestId(element: Element): string | undefined {\n return (\n element.getAttribute('data-testid') ||\n element.getAttribute('data-test-id') ||\n element.getAttribute('data-test') ||\n element.getAttribute('data-cy') ||\n undefined\n );\n }\n\n /**\n * Check if an ID is unique in the document\n */\n private static isUniqueId(id: string, doc: Document): boolean {\n return doc.querySelectorAll(`#${CSS.escape(id)}`).length === 1;\n }\n\n /**\n * Check if a selector is unique within a container\n */\n private static isUniqueSelector(selector: string, container: Element): boolean {\n try {\n return container.querySelectorAll(selector).length === 1;\n } catch {\n return false;\n }\n }\n\n private static isUniqueSelectorSafe(selector: string, doc: Document): boolean {\n try {\n return doc.querySelectorAll(selector).length === 1;\n } catch {\n return false;\n }\n }\n\n /**\n * Get meaningful classes (filtering out utility classes)\n */\n private static getMeaningfulClasses(element: Element): string[] {\n const classes = Array.from(element.classList);\n\n // Filter out common utility classes\n const utilityPatterns = [\n /^(p|m|w|h|text|bg|border|flex|grid|col|row)-/,\n /^(xs|sm|md|lg|xl|2xl):/,\n /^(hover|focus|active|disabled|checked):/,\n /^js-/,\n /^is-/,\n /^has-/,\n ];\n\n return classes\n .filter((cls) => {\n // Keep semantic classes\n if (cls.length < 3) return false;\n return !utilityPatterns.some((pattern) => pattern.test(cls));\n })\n .slice(0, 2); // Limit to 2 most meaningful classes\n }\n\n /**\n * Optimize the selector path by removing unnecessary parts\n */\n private static optimizePath(path: string[], element: Element, doc: Document): string {\n // Try progressively shorter paths\n for (let i = 0; i < path.length - 1; i++) {\n const shortPath = path.slice(i).join(' > ');\n try {\n const matches = doc.querySelectorAll(shortPath);\n if (matches.length === 1 && matches[0] === element) {\n return shortPath;\n }\n } catch {\n // Invalid selector, continue\n }\n }\n\n return path.join(' > ');\n }\n\n /**\n * Get a human-readable path description\n */\n static getContextPath(element: Element): string[] {\n const path: string[] = [];\n let current: Element | null = element;\n let depth = 0;\n const maxDepth = 5;\n\n while (current && current !== element.ownerDocument?.body && depth < maxDepth) {\n const tag = current.nodeName.toLowerCase();\n let descriptor = tag;\n\n // Add semantic information\n if (current.id) {\n descriptor = `${tag}#${current.id}`;\n } else if (current.className && typeof current.className === 'string') {\n const firstClass = current.className.split(' ')[0];\n if (firstClass) {\n descriptor = `${tag}.${firstClass}`;\n }\n }\n\n // Add role information\n const role = current.getAttribute('role');\n if (role) {\n descriptor += `[role=\"${role}\"]`;\n }\n\n path.unshift(descriptor);\n current = current.parentElement;\n depth++;\n }\n\n return path;\n }\n}\n","import { SelectorGenerator } from './selectors';\nimport {\n ElementContext,\n ElementInteraction,\n ExtractedElement,\n ExtractionOptions,\n FilterOptions,\n} from './types';\n\nexport class DOMTraversal {\n private static INTERACTIVE_SELECTORS = [\n 'button',\n 'a[href]',\n 'input:not([type=\"hidden\"])',\n 'textarea',\n 'select',\n '[role=\"button\"]',\n '[onclick]',\n '[contenteditable=\"true\"]',\n 'summary',\n '[tabindex]:not([tabindex=\"-1\"])',\n ];\n\n private static SEMANTIC_SELECTORS = [\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'article',\n 'section',\n 'nav',\n 'aside',\n 'main',\n 'header',\n 'footer',\n 'form',\n 'table',\n 'ul',\n 'ol',\n 'img[alt]',\n 'figure',\n 'video',\n 'audio',\n '[role=\"navigation\"]',\n '[role=\"main\"]',\n '[role=\"complementary\"]',\n '[role=\"contentinfo\"]',\n ];\n\n /**\n * Check if element is visible\n */\n static isVisible(element: Element, computedStyle?: CSSStyleDeclaration): boolean {\n const rect = element.getBoundingClientRect();\n const style = computedStyle || element.ownerDocument?.defaultView?.getComputedStyle(element);\n\n if (!style) return false;\n\n return !!(\n rect.width > 0 &&\n rect.height > 0 &&\n style.display !== 'none' &&\n style.visibility !== 'hidden' &&\n style.opacity !== '0' &&\n (element as HTMLElement).offsetParent !== null\n );\n }\n\n /**\n * Check if element is in viewport\n */\n static isInViewport(element: Element, viewport?: { width: number; height: number }): boolean {\n const rect = element.getBoundingClientRect();\n const view = viewport || {\n width: element.ownerDocument?.defaultView?.innerWidth || 0,\n height: element.ownerDocument?.defaultView?.innerHeight || 0,\n };\n\n return rect.top < view.height && rect.bottom > 0 && rect.left < view.width && rect.right > 0;\n }\n\n /**\n * Check if element passes filter criteria\n */\n static passesFilter(element: Element, filter: FilterOptions | undefined): boolean {\n if (!filter) return true;\n\n const htmlElement = element as HTMLElement;\n\n // Check exclude selectors first\n if (filter.excludeSelectors?.length) {\n for (const selector of filter.excludeSelectors) {\n if (element.matches(selector)) return false;\n }\n }\n\n // Check include selectors\n if (filter.includeSelectors?.length) {\n let matches = false;\n for (const selector of filter.includeSelectors) {\n if (element.matches(selector)) {\n matches = true;\n break;\n }\n }\n if (!matches) return false;\n }\n\n // Check tag filters\n if (filter.tags?.length && !filter.tags.includes(element.tagName.toLowerCase())) {\n return false;\n }\n\n // Check text content filters\n const textContent = htmlElement.textContent?.toLowerCase() || '';\n if (filter.textContains?.length) {\n let hasText = false;\n for (const text of filter.textContains) {\n if (textContent.includes(text.toLowerCase())) {\n hasText = true;\n break;\n }\n }\n if (!hasText) return false;\n }\n\n // Check text regex patterns\n if (filter.textMatches?.length) {\n let matches = false;\n for (const pattern of filter.textMatches) {\n if (pattern.test(textContent)) {\n matches = true;\n break;\n }\n }\n if (!matches) return false;\n }\n\n // Check required attributes\n if (filter.hasAttributes?.length) {\n for (const attr of filter.hasAttributes) {\n if (!element.hasAttribute(attr)) return false;\n }\n }\n\n // Check attribute values\n if (filter.attributeValues) {\n for (const [attr, value] of Object.entries(filter.attributeValues)) {\n const attrValue = element.getAttribute(attr);\n if (!attrValue) return false;\n\n if (typeof value === 'string') {\n if (attrValue !== value) return false;\n } else if (value instanceof RegExp) {\n if (!value.test(attrValue)) return false;\n }\n }\n }\n\n // Check within selectors\n if (filter.withinSelectors?.length) {\n let isWithin = false;\n for (const selector of filter.withinSelectors) {\n if (element.closest(selector)) {\n isWithin = true;\n break;\n }\n }\n if (!isWithin) return false;\n }\n\n // Check interaction types\n if (filter.interactionTypes?.length) {\n const interaction = this.getInteractionInfo(element);\n let hasInteraction = false;\n for (const type of filter.interactionTypes) {\n if (interaction[type]) {\n hasInteraction = true;\n break;\n }\n }\n if (!hasInteraction) return false;\n }\n\n // Check nearText\n if (filter.nearText) {\n const parent = element.parentElement;\n if (!parent || !parent.textContent?.toLowerCase().includes(filter.nearText.toLowerCase())) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Extract element information\n */\n static extractElement(\n element: Element,\n options: ExtractionOptions,\n depth: number = 0\n ): ExtractedElement | null {\n // Check depth limit\n if (options.maxDepth && depth > options.maxDepth) {\n return null;\n }\n\n // Check visibility\n if (!options.includeHidden && !this.isVisible(element)) {\n return null;\n }\n\n // Check viewport\n if (options.viewportOnly && !this.isInViewport(element)) {\n return null;\n }\n\n // Apply filters\n if (!this.passesFilter(element, options.filter)) {\n return null;\n }\n\n const htmlElement = element as HTMLElement;\n\n const extracted: ExtractedElement = {\n tag: element.tagName.toLowerCase(),\n text: this.getElementText(element, options),\n selector: SelectorGenerator.generateSelectors(element),\n attributes: this.getRelevantAttributes(element, options),\n context: this.getElementContext(element),\n interaction: this.getInteractionInfo(element),\n // bounds removed to save tokens\n };\n\n // Extract children for semantic elements in full mode\n if (options.mode === 'full' && this.isSemanticContainer(element)) {\n const children: ExtractedElement[] = [];\n\n // Handle shadow DOM\n if (options.includeShadowDOM && htmlElement.shadowRoot) {\n const shadowChildren = this.extractChildren(htmlElement.shadowRoot, options, depth + 1);\n children.push(...shadowChildren);\n }\n\n // Handle regular children\n const regularChildren = this.extractChildren(element, options, depth + 1);\n children.push(...regularChildren);\n\n if (children.length > 0) {\n extracted.children = children;\n }\n }\n\n return extracted;\n }\n\n /**\n * Extract children elements\n */\n private static extractChildren(\n container: Element | ShadowRoot,\n options: ExtractionOptions,\n depth: number\n ): ExtractedElement[] {\n const children: ExtractedElement[] = [];\n const elements = container.querySelectorAll('*');\n\n for (const child of Array.from(elements)) {\n // Skip if element is nested inside another extracted element\n if (this.hasExtractedAncestor(child, elements)) {\n continue;\n }\n\n const extracted = this.extractElement(child, options, depth);\n if (extracted) {\n children.push(extracted);\n }\n }\n\n return children;\n }\n\n /**\n * Check if element has an ancestor that was already extracted\n */\n private static hasExtractedAncestor(\n element: Element,\n extractedElements: NodeListOf<Element>\n ): boolean {\n let parent = element.parentElement;\n while (parent) {\n if (Array.from(extractedElements).includes(parent)) {\n return true;\n }\n parent = parent.parentElement;\n }\n return false;\n }\n\n /**\n * Get relevant attributes for an element\n */\n private static getRelevantAttributes(\n element: Element,\n options: ExtractionOptions\n ): Record<string, string> {\n const relevant = [\n 'id',\n 'class',\n 'name',\n 'type',\n 'value',\n 'placeholder',\n 'href',\n 'src',\n 'alt',\n 'title',\n 'action',\n 'method',\n 'aria-label',\n 'aria-describedby',\n 'aria-controls',\n 'role',\n 'disabled',\n 'readonly',\n 'required',\n 'checked',\n 'min',\n 'max',\n 'pattern',\n 'step',\n 'autocomplete',\n 'data-testid',\n 'data-test',\n 'data-cy',\n ];\n\n const attributes: Record<string, string> = {};\n const attrTruncate = options.attributeTruncateLength ?? 100;\n const dataAttrTruncate = options.dataAttributeTruncateLength ?? 50;\n\n for (const attr of relevant) {\n const value = element.getAttribute(attr);\n if (value) {\n // Truncate long values based on options\n attributes[attr] =\n value.length > attrTruncate ? value.substring(0, attrTruncate) + '...' : value;\n }\n }\n\n // Include data attributes\n for (const attr of element.attributes) {\n if (attr.name.startsWith('data-') && !relevant.includes(attr.name)) {\n attributes[attr.name] =\n attr.value.length > dataAttrTruncate\n ? attr.value.substring(0, dataAttrTruncate) + '...'\n : attr.value;\n }\n }\n\n return attributes;\n }\n\n /**\n * Get element context information\n */\n private static getElementContext(element: Element): ElementContext {\n const context: ElementContext = {\n parentChain: SelectorGenerator.getContextPath(element),\n };\n\n // Find nearest semantic containers\n const form = element.closest('form');\n if (form) {\n context.nearestForm = SelectorGenerator.generateSelectors(form).css;\n }\n\n const section = element.closest('section, [role=\"region\"]');\n if (section) {\n context.nearestSection = SelectorGenerator.generateSelectors(section).css;\n }\n\n const main = element.closest('main, [role=\"main\"]');\n if (main) {\n context.nearestMain = SelectorGenerator.generateSelectors(main).css;\n }\n\n const nav = element.closest('nav, [role=\"navigation\"]');\n if (nav) {\n context.nearestNav = SelectorGenerator.generateSelectors(nav).css;\n }\n\n return context;\n }\n\n /**\n * Get interaction information for an element (compact format)\n */\n private static getInteractionInfo(element: Element): ElementInteraction {\n const htmlElement = element as HTMLElement;\n const interaction: ElementInteraction = {};\n\n // Only include true values to reduce token usage\n const hasClickHandler = !!(\n htmlElement.onclick ||\n element.getAttribute('onclick') ||\n element.matches('button, a[href], [role=\"button\"], [tabindex]:not([tabindex=\"-1\"])')\n );\n if (hasClickHandler) interaction.click = true;\n\n const hasChangeHandler = !!(\n (htmlElement as HTMLInputElement).onchange ||\n element.getAttribute('onchange') ||\n element.matches('input, select, textarea')\n );\n if (hasChangeHandler) interaction.change = true;\n\n const hasSubmitHandler = !!(\n (htmlElement as HTMLFormElement).onsubmit ||\n element.getAttribute('onsubmit') ||\n element.matches('form')\n );\n if (hasSubmitHandler) interaction.submit = true;\n\n const triggersNavigation = element.matches('a[href], button[type=\"submit\"]');\n if (triggersNavigation) interaction.nav = true;\n\n const isDisabled =\n htmlElement.hasAttribute('disabled') || htmlElement.getAttribute('aria-disabled') === 'true';\n if (isDisabled) interaction.disabled = true;\n\n const isHidden = !this.isVisible(element);\n if (isHidden) interaction.hidden = true;\n\n const ariaRole = element.getAttribute('role');\n if (ariaRole) interaction.role = ariaRole;\n\n // Check form association\n if (element.matches('input, textarea, select, button')) {\n const form = (element as HTMLInputElement).form || element.closest('form');\n if (form) {\n interaction.form = SelectorGenerator.generateSelectors(form).css;\n }\n }\n\n return interaction;\n }\n\n /**\n * Get text content of an element (limited length)\n */\n private static getElementText(element: Element, options?: ExtractionOptions): string {\n // For input elements, get value or placeholder\n if (element.matches('input, textarea')) {\n const input = element as HTMLInputElement;\n return input.value || input.placeholder || '';\n }\n\n // For images, get alt text\n if (element.matches('img')) {\n return (element as HTMLImageElement).alt || '';\n }\n\n // Get text content, but limit length based on options\n const text = element.textContent?.trim() || '';\n const maxLength = options?.textTruncateLength;\n\n if (maxLength && text.length > maxLength) {\n return text.substring(0, maxLength) + '...';\n }\n\n return text;\n }\n\n /**\n * Check if element is a semantic container\n */\n private static isSemanticContainer(element: Element): boolean {\n return element.matches(\n 'article, section, nav, aside, main, header, footer, form, ' +\n 'table, ul, ol, dl, figure, details, dialog, [role=\"region\"], ' +\n '[role=\"navigation\"], [role=\"main\"], [role=\"complementary\"]'\n );\n }\n\n /**\n * Get interactive elements\n */\n static getInteractiveElements(\n container: Element | Document = document,\n options: ExtractionOptions\n ): ExtractedElement[] {\n const elements: ExtractedElement[] = [];\n const selector = this.INTERACTIVE_SELECTORS.join(', ');\n const found = container.querySelectorAll(selector);\n\n for (const element of Array.from(found)) {\n const extracted = this.extractElement(element, options);\n if (extracted) {\n elements.push(extracted);\n }\n }\n\n // Add custom selectors if provided\n if (options.customSelectors) {\n for (const customSelector of options.customSelectors) {\n try {\n const customFound = container.querySelectorAll(customSelector);\n for (const element of Array.from(customFound)) {\n const extracted = this.extractElement(element, options);\n if (extracted) {\n elements.push(extracted);\n }\n }\n } catch (e) {\n console.warn(`Invalid custom selector: ${customSelector}`);\n }\n }\n }\n\n return elements;\n }\n\n /**\n * Get semantic elements (for full mode)\n */\n static getSemanticElements(\n container: Element | Document = document,\n options: ExtractionOptions\n ): ExtractedElement[] {\n const elements: ExtractedElement[] = [];\n const selector = this.SEMANTIC_SELECTORS.join(', ');\n const found = container.querySelectorAll(selector);\n\n for (const element of Array.from(found)) {\n const extracted = this.extractElement(element, options);\n if (extracted) {\n elements.push(extracted);\n }\n }\n\n return elements;\n }\n}\n","import type {\n ExtractedContent,\n ExtractedElement,\n RegionInfo,\n SmartDOMResult,\n StructuralOverview,\n} from './types';\n\nexport type MarkdownDetailLevel = 'summary' | 'region' | 'deep';\n\nexport interface MarkdownFormatOptions {\n detail?: MarkdownDetailLevel;\n maxTextLength?: number;\n maxElements?: number;\n}\n\ntype PageMeta = { title?: string; url?: string };\n\nfunction truncate(text: string | undefined, len?: number): string {\n const t = (text ?? '').trim();\n if (!len || t.length <= len) return t;\n\n // Smart truncation: keep start and preserve key action words if present\n const keywords = [\n 'login',\n 'log in',\n 'sign in',\n 'sign up',\n 'submit',\n 'search',\n 'filter',\n 'add to cart',\n 'next',\n 'continue',\n ];\n const lower = t.toLowerCase();\n const hit = keywords.map((k) => ({ k, i: lower.indexOf(k) })).find((x) => x.i > -1);\n const head = Math.max(0, Math.floor(len * 0.66));\n if (hit && hit.i > head) {\n const tailWindow = Math.max(12, len - head - 5);\n const start = Math.max(0, hit.i - Math.floor(tailWindow / 2));\n const end = Math.min(t.length, start + tailWindow);\n return t.slice(0, head).trimEnd() + ' … ' + t.slice(start, end).trim() + '…';\n }\n // Default: simple head truncation on word boundary\n const slice = t.slice(0, len);\n const lastSpace = slice.lastIndexOf(' ');\n return (lastSpace > 32 ? slice.slice(0, lastSpace) : slice) + '…';\n}\n\nfunction bestSelector(el: Pick<ExtractedElement, 'selector' | 'tag' | 'text'>): string {\n return el.selector?.css || '';\n}\n\nfunction hashId(input: string): string {\n let h = 5381;\n for (let i = 0; i < input.length; i++) h = (h * 33) ^ input.charCodeAt(i);\n // Convert to unsigned and base36 for compactness\n return 'sec-' + (h >>> 0).toString(36);\n}\n\nfunction iconForRegion(key: string): string {\n switch (key) {\n case 'header':\n return '🧭';\n case 'navigation':\n return '📑';\n case 'main':\n return '📄';\n case 'sections':\n return '🗂️';\n case 'sidebar':\n return '📚';\n case 'footer':\n return '🔻';\n case 'modals':\n return '💬';\n default:\n return '🔹';\n }\n}\n\nfunction elementLine(el: ExtractedElement, opts?: MarkdownFormatOptions): string {\n const txt = truncate(el.text || el.attributes?.ariaLabel, opts?.maxTextLength ?? 80);\n const sel = bestSelector(el);\n const tag = el.tag.toLowerCase();\n const action = el.interaction?.submit\n ? 'submit'\n : el.interaction?.click\n ? 'click'\n : el.interaction?.change\n ? 'change'\n : undefined;\n const actionText = action ? ` (${action})` : '';\n return `- ${tag.toUpperCase()}: ${txt || '(no text)'} → \\`${sel}\\`${actionText}`;\n}\n\nfunction selectorQualitySummary(inter: SmartDOMResult['interactive']): string {\n const all: string[] = [];\n all.push(...inter.buttons.map((e) => e.selector?.css || ''));\n all.push(...inter.links.map((e) => e.selector?.css || ''));\n all.push(...inter.inputs.map((e) => e.selector?.css || ''));\n all.push(...inter.clickable.map((e) => e.selector?.css || ''));\n const total = all.length || 1;\n const idCount = all.filter((s) => s.startsWith('#')).length;\n const testIdCount = all.filter((s) => /\\[data-testid=/.test(s)).length;\n const nthCount = all.filter((s) => /:nth-child\\(/.test(s)).length;\n const stable = idCount + testIdCount;\n const stablePct = Math.round((stable / total) * 100);\n const nthPct = Math.round((nthCount / total) * 100);\n return `Selector quality: ${stablePct}% stable (ID/data-testid), ${nthPct}% structural (:nth-child)`;\n}\n\nfunction renderInteractive(\n inter: SmartDOMResult['interactive'],\n opts?: MarkdownFormatOptions\n): string {\n const parts: string[] = [];\n\n const limit = (arr: ExtractedElement[]) =>\n typeof opts?.maxElements === 'number' ? arr.slice(0, opts.maxElements) : arr;\n\n if (inter.buttons.length) {\n parts.push('Buttons:');\n for (const el of limit(inter.buttons)) parts.push(elementLine(el, opts));\n }\n if (inter.links.length) {\n parts.push('Links:');\n for (const el of limit(inter.links)) parts.push(elementLine(el, opts));\n }\n if (inter.inputs.length) {\n parts.push('Inputs:');\n for (const el of limit(inter.inputs)) parts.push(elementLine(el, opts));\n }\n if (inter.clickable.length) {\n parts.push('Other Clickable:');\n for (const el of limit(inter.clickable)) parts.push(elementLine(el, opts));\n }\n if (inter.forms.length) {\n parts.push('Forms:');\n for (const f of limit(inter.forms as unknown as ExtractedElement[])) {\n // FormInfo is not ExtractedElement; render minimally\n // @ts-expect-error — using selector from FormInfo shape\n parts.push(`- FORM: action=${f.action ?? '-'} method=${f.method ?? '-'} → \\`${f.selector}\\``);\n }\n }\n\n return parts.join('\\n');\n}\n\nfunction renderRegionInfo(region: RegionInfo): string {\n const icon = iconForRegion('region');\n const id = hashId(`${region.selector}|${region.label ?? ''}|${region.role ?? ''}`);\n const label = region.label ? ` ${region.label}` : '';\n const stats: string[] = [];\n if (region.buttonCount) stats.push(`${region.buttonCount} buttons`);\n if (region.linkCount) stats.push(`${region.linkCount} links`);\n if (region.inputCount) stats.push(`${region.inputCount} inputs`);\n if (region.textPreview) stats.push(`“${truncate(region.textPreview, 80)}”`);\n const statsLine = stats.length ? ` — ${stats.join(', ')}` : '';\n return `${icon} ${label} → \\`${region.selector}\\` [${id}]${statsLine}`;\n}\n\nfunction wrapXml(body: string, meta?: PageMeta, type: string = 'section'): string {\n const attrs = [\n meta?.title ? `title=\"${escapeXml(meta!.title!)}\"` : null,\n meta?.url ? `url=\"${escapeXml(meta!.url!)}\"` : null,\n ]\n .filter(Boolean)\n .join(' ');\n return `<page ${attrs}>\\n <${type}><![CDATA[\\n${body}\\n]]></${type}>\\n</page>`;\n}\n\nfunction escapeXml(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;');\n}\n\nexport class MarkdownFormatter {\n static structure(\n overview: StructuralOverview,\n _opts: MarkdownFormatOptions = {},\n meta?: PageMeta\n ): string {\n const lines: string[] = [];\n lines.push(`# Page Outline`);\n if (meta?.title || meta?.url) {\n lines.push(`Title: ${meta?.title ?? ''}`.trim());\n lines.push(`URL: ${meta?.url ?? ''}`.trim());\n }\n lines.push('');\n\n const regions = overview.regions;\n const entries: Array<[string, RegionInfo | RegionInfo[] | undefined]> = [\n ['header', regions.header],\n ['navigation', regions.navigation],\n ['main', regions.main],\n ['sections', regions.sections],\n ['sidebar', regions.sidebar],\n ['footer', regions.footer],\n ['modals', regions.modals],\n ];\n\n for (const [key, value] of entries) {\n if (!value) continue;\n const icon = iconForRegion(key);\n if (Array.isArray(value)) {\n if (!value.length) continue;\n lines.push(`## ${icon} ${capitalize(key)}`);\n for (const region of value) lines.push(renderRegionInfo(region));\n } else {\n lines.push(`## ${icon} ${capitalize(key)}`);\n lines.push(renderRegionInfo(value));\n }\n lines.push('');\n }\n\n // Suggestions\n if (overview.suggestions?.length) {\n lines.push('## Suggestions');\n for (const s of overview.suggestions) lines.push(`- ${s}`);\n lines.push('');\n }\n\n lines.push(\n 'Next: choose a region (by selector or [sectionId]) and call dom_extract_region for actionable details.'\n );\n\n const body = lines.join('\\n');\n return wrapXml(body, meta, 'outline');\n }\n\n static region(result: SmartDOMResult, opts: MarkdownFormatOptions = {}, meta?: PageMeta): string {\n const lines: string[] = [];\n lines.push(`# Region Details`);\n if (meta?.title || meta?.url) {\n lines.push(`Title: ${meta?.title ?? ''}`.trim());\n lines.push(`URL: ${meta?.url ?? ''}`.trim());\n }\n lines.push('');\n\n const inter = result.interactive;\n // Page state diagnostics if available\n if (result.page) {\n const ps = [\n result.page.hasErrors ? 'errors: yes' : 'errors: no',\n result.page.isLoading ? 'loading: yes' : 'loading: no',\n result.page.hasModals ? 'modals: yes' : 'modals: no',\n ];\n lines.push(`Page state: ${ps.join(', ')}`);\n }\n\n const summary: string[] = [];\n const count = (arr: unknown[]) => (arr ? arr.length : 0);\n summary.push(`${count(inter.buttons)} buttons`);\n summary.push(`${count(inter.links)} links`);\n summary.push(`${count(inter.inputs)} inputs`);\n if (inter.forms?.length) summary.push(`${count(inter.forms)} forms`);\n lines.push(`Summary: ${summary.join(', ')}`);\n lines.push(selectorQualitySummary(inter));\n lines.push('');\n\n lines.push(renderInteractive(inter, opts));\n lines.push('');\n lines.push(\n 'Next: write a script using the most stable selectors above. If selectors look unstable, rerun dom_extract_region with higher detail or call dom_extract_content for text context.'\n );\n\n const body = lines.join('\\n');\n return wrapXml(body, meta, 'section');\n }\n\n static content(\n content: ExtractedContent,\n opts: MarkdownFormatOptions = {},\n meta?: PageMeta\n ): string {\n const lines: string[] = [];\n lines.push(`# Content`);\n lines.push(`Selector: \\`${content.selector}\\``);\n lines.push('');\n\n if (content.text.headings?.length) {\n lines.push('Headings:');\n for (const h of content.text.headings)\n lines.push(`- H${h.level}: ${truncate(h.text, opts.maxTextLength ?? 120)}`);\n lines.push('');\n }\n if (content.text.paragraphs?.length) {\n const limit =\n typeof opts.maxElements === 'number' ? opts.maxElements : content.text.paragraphs.length;\n lines.push('Paragraphs:');\n for (const p of content.text.paragraphs.slice(0, limit))\n lines.push(`- ${truncate(p, opts.maxTextLength ?? 200)}`);\n lines.push('');\n }\n if (content.text.lists?.length) {\n lines.push('Lists:');\n for (const list of content.text.lists) {\n lines.push(`- ${list.type.toUpperCase()}:`);\n const limit = typeof opts.maxElements === 'number' ? opts.maxElements : list.items.length;\n for (const item of list.items.slice(0, limit))\n lines.push(` - ${truncate(item, opts.maxTextLength ?? 120)}`);\n }\n lines.push('');\n }\n\n if (content.tables?.length) {\n lines.push('Tables:');\n for (const t of content.tables) {\n lines.push(`- Headers: ${t.headers.join(' | ')}`);\n const limit = typeof opts.maxElements === 'number' ? opts.maxElements : t.rows.length;\n for (const row of t.rows.slice(0, limit)) lines.push(` - ${row.join(' | ')}`);\n }\n lines.push('');\n }\n\n if (content.media?.length) {\n lines.push('Media:');\n const limit = typeof opts.maxElements === 'number' ? opts.maxElements : content.media.length;\n for (const m of content.media.slice(0, limit)) {\n lines.push(`- ${m.type.toUpperCase()}: ${m.alt ?? ''} ${m.src ? `→ ${m.src}` : ''}`.trim());\n }\n lines.push('');\n }\n\n lines.push(\n 'Next: if text is insufficient for targeting, call dom_extract_region for interactive selectors.'\n );\n\n const body = lines.join('\\n');\n return wrapXml(body, meta, 'content');\n }\n}\n\nfunction capitalize(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n","import { ContentDetection } from './content-detection';\nimport type { SmartDOMReader as SmartDOMReaderClass } from './index';\nimport { SelectorGenerator } from './selectors';\nimport { DOMTraversal } from './traversal';\nimport {\n ContentExtractionOptions,\n ExtractedContent,\n ExtractionOptions,\n RegionInfo,\n SmartDOMResult,\n StructuralOverview,\n} from './types';\n\ntype SmartDomReaderNamespace = typeof import('./index');\ntype SmartDomReaderCtor = new (options?: Partial<ExtractionOptions>) => SmartDOMReaderClass;\n\ntype SmartDomReaderWindow = Window & {\n SmartDOMReader?: SmartDomReaderCtor;\n SmartDOMReaderNamespace?: SmartDomReaderNamespace;\n};\n\nfunction resolveSmartDomReader(): SmartDomReaderCtor | undefined {\n if (typeof window !== 'undefined') {\n const globalWindow = window as Partial<SmartDomReaderWindow>;\n const direct = globalWindow.SmartDOMReader;\n if (typeof direct === 'function') {\n return direct;\n }\n\n const namespace = globalWindow.SmartDOMReaderNamespace;\n if (namespace && typeof namespace.SmartDOMReader === 'function') {\n return namespace.SmartDOMReader as SmartDomReaderCtor;\n }\n }\n\n try {\n if (typeof require === 'function') {\n const moduleExports = require('./index') as SmartDomReaderNamespace;\n if (moduleExports && typeof moduleExports.SmartDOMReader === 'function') {\n return moduleExports.SmartDOMReader as SmartDomReaderCtor;\n }\n\n if (moduleExports && typeof moduleExports.default === 'function') {\n return moduleExports.default as SmartDomReaderCtor;\n }\n }\n } catch {\n // Ignore resolution errors when require is unavailable (e.g. browser bundles)\n }\n\n return undefined;\n}\n\nexport class ProgressiveExtractor {\n /**\n * Step 1: Extract high-level structural overview\n * This provides a \"map\" of the page for the AI to understand structure\n */\n static extractStructure(root: Document | Element): StructuralOverview {\n const regions: StructuralOverview['regions'] = {};\n\n // Find header (scoped to root)\n const header = root.querySelector('header, [role=\"banner\"], .header, #header');\n if (header) {\n regions.header = this.analyzeRegion(header);\n }\n\n // Find navigation areas (scoped to root)\n const navs = root.querySelectorAll('nav, [role=\"navigation\"], .nav, .navigation');\n if (navs.length > 0) {\n regions.navigation = Array.from(navs).map((nav) => this.analyzeRegion(nav));\n }\n\n // Find main content\n if (root instanceof Document) {\n const main = ContentDetection.findMainContent(root);\n if (main) {\n regions.main = this.analyzeRegion(main);\n // Find sections within main\n const sections = main.querySelectorAll('section, article, [role=\"region\"]');\n if (sections.length > 0) {\n regions.sections = Array.from(sections)\n .filter((section) => !section.closest('nav, header, footer'))\n .map((section) => this.analyzeRegion(section));\n }\n }\n } else {\n // When scoped to an Element, treat the element itself as the main region\n regions.main = this.analyzeRegion(root);\n const sections = root.querySelectorAll('section, article, [role=\"region\"]');\n if (sections.length > 0) {\n regions.sections = Array.from(sections)\n .filter((section) => !section.closest('nav, header, footer'))\n .map((section) => this.analyzeRegion(section));\n }\n }\n\n // Find sidebars (scoped)\n const sidebars = root.querySelectorAll('aside, [role=\"complementary\"], .sidebar, #sidebar');\n if (sidebars.length > 0) {\n regions.sidebar = Array.from(sidebars).map((sidebar) => this.analyzeRegion(sidebar));\n }\n\n // Find footer (scoped)\n const footer = root.querySelector('footer, [role=\"contentinfo\"], .footer, #footer');\n if (footer) {\n regions.footer = this.analyzeRegion(footer);\n }\n\n // Find modals/dialogs (scoped)\n const modals = root.querySelectorAll('[role=\"dialog\"], .modal, .popup, .overlay');\n const visibleModals = Array.from(modals).filter((modal) => DOMTraversal.isVisible(modal));\n if (visibleModals.length > 0) {\n regions.modals = visibleModals.map((modal) => this.analyzeRegion(modal));\n }\n\n // Extract form information (scoped)\n const forms = this.extractFormOverview(root);\n\n // Calculate summary statistics (scoped)\n const summary = this.calculateSummary(root, regions, forms);\n\n // Generate AI-friendly suggestions\n const suggestions = this.generateSuggestions(regions, summary);\n\n return { regions, forms, summary, suggestions };\n }\n\n /**\n * Step 2: Extract detailed information from a specific region\n */\n static extractRegion(\n selector: string,\n doc: Document,\n options: Partial<ExtractionOptions> = {},\n smartDomReaderCtor?: SmartDomReaderCtor\n ): SmartDOMResult | null {\n const element = doc.querySelector(selector);\n if (!element) return null;\n\n const SmartDOMReaderCtor = smartDomReaderCtor ?? resolveSmartDomReader();\n if (!SmartDOMReaderCtor) {\n throw new Error(\n 'SmartDOMReader is unavailable. Ensure the Smart DOM Reader module is loaded before calling extractRegion.'\n );\n }\n const reader = new SmartDOMReaderCtor(options);\n\n // Extract from the specific element/region\n return reader.extract(element, options);\n }\n\n /**\n * Step 3: Extract readable content from a region\n */\n static extractContent(\n selector: string,\n doc: Document,\n options: ContentExtractionOptions = {}\n ): ExtractedContent | null {\n const element = doc.querySelector(selector);\n if (!element) return null;\n\n const result: ExtractedContent = {\n selector,\n text: {},\n metadata: {\n wordCount: 0,\n hasInteractive: false,\n },\n };\n\n // Extract headings\n if (options.includeHeadings !== false) {\n const headings = element.querySelectorAll('h1, h2, h3, h4, h5, h6');\n result.text.headings = Array.from(headings).map((h) => ({\n level: parseInt(h.tagName[1]),\n text: this.getTextContent(h, options.maxTextLength),\n }));\n }\n\n // Extract paragraphs\n const paragraphs = element.querySelectorAll('p');\n if (paragraphs.length > 0) {\n result.text.paragraphs = Array.from(paragraphs)\n .map((p) => this.getTextContent(p, options.maxTextLength))\n .filter((text) => text.length > 0);\n }\n\n // Extract lists\n if (options.includeLists !== false) {\n const lists = element.querySelectorAll('ul, ol');\n result.text.lists = Array.from(lists).map((list) => ({\n type: list.tagName.toLowerCase() as 'ul' | 'ol',\n items: Array.from(list.querySelectorAll('li')).map((li) =>\n this.getTextContent(li, options.maxTextLength)\n ),\n }));\n }\n\n // Extract tables\n if (options.includeTables !== false) {\n const tables = element.querySelectorAll('table');\n result.tables = Array.from(tables).map((table) => {\n const headers = Array.from(table.querySelectorAll('th')).map((th) =>\n this.getTextContent(th)\n );\n const rows = Array.from(table.querySelectorAll('tr'))\n .filter((tr) => tr.querySelector('td'))\n .map((tr) => Array.from(tr.querySelectorAll('td')).map((td) => this.getTextContent(td)));\n return { headers, rows };\n });\n }\n\n // Extract media\n if (options.includeMedia !== false) {\n const images = element.querySelectorAll('img');\n const videos = element.querySelectorAll('video');\n const audios = element.querySelectorAll('audio');\n\n result.media = [\n ...Array.from(images).map((img) => ({\n type: 'img' as const,\n alt: img.getAttribute('alt') || undefined,\n src: img.getAttribute('src') || undefined,\n })),\n ...Array.from(videos).map((video) => ({\n type: 'video' as const,\n src: video.getAttribute('src') || undefined,\n })),\n ...Array.from(audios).map((audio) => ({\n type: 'audio' as const,\n src: audio.getAttribute('src') || undefined,\n })),\n ];\n }\n\n // Calculate metadata\n const allText = element.textContent || '';\n result.metadata.wordCount = allText.trim().split(/\\s+/).length;\n result.metadata.hasInteractive =\n element.querySelectorAll('button, a, input, textarea, select').length > 0;\n\n return result;\n }\n\n /**\n * Analyze a region and extract summary information\n */\n private static analyzeRegion(element: Element): RegionInfo {\n const selector = SelectorGenerator.generateSelectors(element).css;\n const buttons = element.querySelectorAll('button, [role=\"button\"]');\n const links = element.querySelectorAll('a[href]');\n const inputs = element.querySelectorAll('input, textarea, select');\n const forms = element.querySelectorAll('form');\n const lists = element.querySelectorAll('ul, ol');\n const tables = element.querySelectorAll('table');\n const media = element.querySelectorAll('img, video, audio');\n\n const interactiveCount = buttons.length + links.length + inputs.length;\n\n // Get label from aria-label, aria-labelledby, or heading\n let label: string | undefined;\n const ariaLabel = element.getAttribute('aria-label');\n if (ariaLabel) {\n label = ariaLabel;\n } else if (element.getAttribute('aria-labelledby')) {\n const labelId = element.getAttribute('aria-labelledby');\n if (labelId) {\n const labelElement = element.ownerDocument?.getElementById(labelId);\n if (labelElement) {\n label = labelElement.textContent?.trim();\n }\n }\n } else {\n const heading = element.querySelector('h1, h2, h3');\n if (heading) {\n label = heading.textContent?.trim();\n }\n }\n\n // Get text preview\n const textContent = element.textContent?.trim() || '';\n const textPreview =\n textContent.length > 50 ? textContent.substring(0, 50) + '...' : textContent;\n\n return {\n selector,\n label,\n role: element.getAttribute('role') || undefined,\n interactiveCount,\n hasForm: forms.length > 0,\n hasList: lists.length > 0,\n hasTable: tables.length > 0,\n hasMedia: media.length > 0,\n buttonCount: buttons.length > 0 ? buttons.length : undefined,\n linkCount: links.length > 0 ? links.length : undefined,\n inputCount: inputs.length > 0 ? inputs.length : undefined,\n textPreview: textPreview.length > 0 ? textPreview : undefined,\n };\n }\n\n /**\n * Extract overview of forms on the page\n */\n private static extractFormOverview(root: Document | Element): StructuralOverview['forms'] {\n const forms = root.querySelectorAll('form');\n return Array.from(forms).map((form) => {\n const inputs = form.querySelectorAll('input, textarea, select');\n const selector = SelectorGenerator.generateSelectors(form).css;\n\n // Determine which region the form is in\n let location = 'unknown';\n if (form.closest('header, [role=\"banner\"]')) {\n location = 'header';\n } else if (form.closest('nav, [role=\"navigation\"]')) {\n location = 'navigation';\n } else if (form.closest('main, [role=\"main\"]')) {\n location = 'main';\n } else if (form.closest('aside, [role=\"complementary\"]')) {\n location = 'sidebar';\n } else if (form.closest('footer, [role=\"contentinfo\"]')) {\n location = 'footer';\n }\n\n // Infer purpose from form attributes and content\n let purpose: string | undefined;\n const formId = form.getAttribute('id')?.toLowerCase();\n const formClass = form.getAttribute('class')?.toLowerCase();\n const formAction = form.getAttribute('action')?.toLowerCase();\n const hasEmail = form.querySelector('input[type=\"email\"]');\n const hasPassword = form.querySelector('input[type=\"password\"]');\n const hasSearch = form.querySelector('input[type=\"search\"]');\n\n if (hasSearch || formId?.includes('search') || formClass?.includes('search')) {\n purpose = 'search';\n } else if (hasPassword && hasEmail) {\n purpose = 'login';\n } else if (hasPassword) {\n purpose = 'authentication';\n } else if (formId?.includes('contact') || formClass?.includes('contact')) {\n purpose = 'contact';\n } else if (formId?.includes('subscribe') || formClass?.includes('subscribe')) {\n purpose = 'subscription';\n } else if (formAction?.includes('checkout') || formClass?.includes('checkout')) {\n purpose = 'checkout';\n }\n\n return {\n selector,\n location,\n inputCount: inputs.length,\n purpose,\n };\n });\n }\n\n /**\n * Calculate summary statistics\n */\n private static calculateSummary(\n root: Document | Element,\n regions: StructuralOverview['regions'],\n forms: StructuralOverview['forms']\n ): StructuralOverview['summary'] {\n const allInteractive = root.querySelectorAll('button, a[href], input, textarea, select');\n const allSections = root.querySelectorAll('section, article, [role=\"region\"]');\n const hasModals = (regions.modals?.length || 0) > 0;\n\n // Check for errors\n const errorSelectors = ['.error', '.alert-danger', '[role=\"alert\"]'];\n const hasErrors = errorSelectors.some((sel) => {\n const element = root.querySelector(sel);\n return element ? DOMTraversal.isVisible(element) : false;\n });\n\n // Check for loading\n const loadingSelectors = ['.loading', '.spinner', '[aria-busy=\"true\"]'];\n const isLoading = loadingSelectors.some((sel) => {\n const element = root.querySelector(sel);\n return element ? DOMTraversal.isVisible(element) : false;\n });\n\n const mainContentSelector = regions.main?.selector;\n\n return {\n totalInteractive: allInteractive.length,\n totalForms: forms.length,\n totalSections: allSections.length,\n hasModals,\n hasErrors,\n isLoading,\n mainContentSelector,\n };\n }\n\n /**\n * Generate AI-friendly suggestions\n */\n private static generateSuggestions(\n regions: StructuralOverview['regions'],\n summary: StructuralOverview['summary']\n ): string[] {\n const suggestions: string[] = [];\n\n if (summary.hasErrors) {\n suggestions.push('Page has error indicators - check error messages before interacting');\n }\n\n if (summary.isLoading) {\n suggestions.push('Page appears to be loading - wait or check loading state');\n }\n\n if (summary.hasModals) {\n suggestions.push('Modal/dialog is open - may need to interact with or close it first');\n }\n\n if (regions.main && regions.main.interactiveCount > 10) {\n suggestions.push(\n `Main content has ${regions.main.interactiveCount} interactive elements - consider filtering`\n );\n }\n\n if (summary.totalForms > 0) {\n suggestions.push(`Found ${summary.totalForms} form(s) on the page`);\n }\n\n if (!regions.main) {\n suggestions.push('No clear main content area detected - may need to explore regions');\n }\n\n return suggestions;\n }\n\n /**\n * Get text content with optional truncation\n */\n private static getTextContent(element: Element, maxLength?: number): string {\n const text = element.textContent?.trim() || '';\n if (maxLength && text.length > maxLength) {\n return text.substring(0, maxLength) + '...';\n }\n return text;\n }\n}\n","export type ExtractionMode = 'interactive' | 'full' | 'structure' | 'content';\n\nexport interface ElementSelector {\n css: string;\n xpath: string;\n textBased?: string;\n dataTestId?: string;\n ariaLabel?: string;\n // Ranked selector candidates by stability/robustness (highest score first)\n candidates?: ElementSelectorCandidate[];\n}\n\nexport interface ElementSelectorCandidate {\n type: 'id' | 'data-testid' | 'role-aria' | 'name' | 'class-path' | 'css-path' | 'xpath' | 'text';\n value: string;\n score: number; // Higher is better\n}\n\nexport interface ElementContext {\n nearestForm?: string;\n nearestSection?: string;\n nearestMain?: string;\n nearestNav?: string;\n parentChain: string[];\n}\n\nexport interface ElementInteraction {\n // Compact format: only include true values\n click?: boolean; // hasClickHandler\n change?: boolean; // hasChangeHandler\n submit?: boolean; // hasSubmitHandler\n nav?: boolean; // triggersNavigation\n disabled?: boolean; // isDisabled\n hidden?: boolean; // isHidden\n role?: string; // ariaRole\n form?: string; // formAssociation\n}\n\nexport interface ExtractedElement {\n tag: string;\n text: string;\n selector: ElementSelector;\n attributes: Record<string, string>;\n context: ElementContext;\n interaction: ElementInteraction;\n // bounds removed to save tokens\n children?: ExtractedElement[];\n}\n\nexport interface FormInfo {\n selector: string;\n action?: string;\n method?: string;\n inputs: ExtractedElement[];\n buttons: ExtractedElement[];\n}\n\nexport interface PageLandmarks {\n navigation: string[];\n main: string[];\n forms: string[];\n headers: string[];\n footers: string[];\n articles: string[];\n sections: string[];\n}\n\nexport interface PageState {\n url: string;\n title: string;\n hasErrors: boolean;\n isLoading: boolean;\n hasModals: boolean;\n hasFocus?: string;\n}\n\nexport interface SmartDOMResult {\n mode: ExtractionMode;\n timestamp: number;\n page: PageState;\n landmarks: PageLandmarks;\n interactive: {\n buttons: ExtractedElement[];\n links: ExtractedElement[];\n inputs: ExtractedElement[];\n forms: FormInfo[];\n clickable: ExtractedElement[];\n };\n semantic?: {\n headings: ExtractedElement[];\n images: ExtractedElement[];\n tables: ExtractedElement[];\n lists: ExtractedElement[];\n articles: ExtractedElement[];\n };\n metadata?: {\n totalElements: number;\n extractedElements: number;\n mainContent?: string;\n language?: string;\n };\n}\n\nexport interface FilterOptions {\n // Element selectors to include/exclude\n includeSelectors?: string[]; // CSS selectors for elements to include\n excludeSelectors?: string[]; // CSS selectors for elements to exclude\n\n // Text content filters\n textContains?: string[]; // Include elements containing these text strings\n textMatches?: RegExp[]; // Include elements matching these patterns\n\n // Attribute filters\n hasAttributes?: string[]; // Include elements with these attributes\n attributeValues?: Record<string, string | RegExp>; // Attribute value filters\n\n // Element type filters\n tags?: string[]; // Include only these tag types\n interactionTypes?: Array<keyof ElementInteraction>; // Include only elements with these interactions\n\n // Context filters\n withinSelectors?: string[]; // Only include elements within these containers\n nearText?: string; // Include elements near this text content\n}\n\nexport interface ExtractionOptions {\n mode: ExtractionMode;\n maxDepth?: number;\n includeHidden?: boolean;\n includeShadowDOM?: boolean;\n includeIframes?: boolean;\n viewportOnly?: boolean;\n mainContentOnly?: boolean;\n customSelectors?: string[];\n\n // Token optimization options\n attributeTruncateLength?: number; // Max length for attribute values (default: 100)\n dataAttributeTruncateLength?: number; // Max length for data-* attributes (default: 50)\n textTruncateLength?: number; // Max length for text content (default: unlimited)\n\n // Filtering options\n filter?: FilterOptions;\n}\n\n// Progressive Extraction Types\n\nexport interface RegionInfo {\n selector: string;\n label?: string; // Semantic label (e.g., \"Navigation\", \"Product List\")\n role?: string; // ARIA role if present\n interactiveCount: number; // Count of interactive elements\n hasForm?: boolean;\n hasList?: boolean;\n hasTable?: boolean;\n hasMedia?: boolean;\n buttonCount?: number;\n linkCount?: number;\n inputCount?: number;\n textPreview?: string; // First 50 chars of text content\n}\n\nexport interface StructuralOverview {\n regions: {\n header?: RegionInfo;\n navigation?: RegionInfo[];\n main?: RegionInfo;\n sidebar?: RegionInfo[];\n footer?: RegionInfo;\n modals?: RegionInfo[];\n sections?: RegionInfo[]; // Major content sections\n };\n forms: Array<{\n selector: string;\n location: string; // Which region it's in\n inputCount: number;\n purpose?: string; // Inferred from form attributes/content\n }>;\n summary: {\n totalInteractive: number;\n totalForms: number;\n totalSections: number;\n hasModals: boolean;\n hasErrors: boolean;\n isLoading: boolean;\n mainContentSelector?: string;\n };\n suggestions?: string[]; // AI-friendly hints about what to explore next\n}\n\nexport interface ContentExtractionOptions {\n includeHeadings?: boolean;\n includeLists?: boolean;\n includeTables?: boolean;\n includeMedia?: boolean;\n preserveFormatting?: boolean;\n maxTextLength?: number;\n}\n\nexport interface ExtractedContent {\n selector: string;\n text: {\n headings?: Array<{ level: number; text: string }>;\n paragraphs?: string[];\n lists?: Array<{ type: 'ul' | 'ol'; items: string[] }>;\n };\n tables?: Array<{\n headers: string[];\n rows: string[][];\n }>;\n media?: Array<{\n type: 'img' | 'video' | 'audio';\n alt?: string;\n src?: string;\n }>;\n metadata: {\n wordCount: number;\n hasInteractive: boolean;\n };\n}\n","import { ContentDetection } from './content-detection';\nimport { SelectorGenerator } from './selectors';\nimport { DOMTraversal } from './traversal';\nimport {\n ExtractedElement,\n ExtractionMode,\n ExtractionOptions,\n FormInfo,\n PageLandmarks,\n PageState,\n SmartDOMResult,\n} from './types';\n\nexport type {\n ExtractContentArgs,\n ExtractFullArgs,\n ExtractInteractiveArgs,\n ExtractionArgs,\n ExtractionMethod,\n ExtractionResult,\n ExtractRegionArgs,\n ExtractStructureArgs,\n} from './bundle-types';\n// Re-export modules for external use\nexport { ContentDetection } from './content-detection';\nexport { type MarkdownFormatOptions, MarkdownFormatter } from './markdown-formatter';\nexport { ProgressiveExtractor } from './progressive';\nexport { SelectorGenerator } from './selectors';\nexport * from './types';\n\n/**\n * Smart DOM Reader - Full Extraction Approach\n *\n * This class provides complete DOM extraction in a single pass.\n * Use this when you need all information upfront and have sufficient\n * token budget for processing the complete output.\n *\n * Features:\n * - Single-pass extraction of all elements\n * - Two modes: 'interactive' (UI elements) or 'full' (includes content)\n * - Efficient for automation and testing scenarios\n * - Returns complete structured data immediately\n */\nexport class SmartDOMReader {\n private options: ExtractionOptions;\n\n constructor(options: Partial<ExtractionOptions> = {}) {\n this.options = {\n mode: options.mode || 'interactive',\n maxDepth: options.maxDepth || 5,\n includeHidden: options.includeHidden || false,\n includeShadowDOM: options.includeShadowDOM || true,\n includeIframes: options.includeIframes || false,\n viewportOnly: options.viewportOnly || false,\n mainContentOnly: options.mainContentOnly || false,\n customSelectors: options.customSelectors || [],\n attributeTruncateLength: options.attributeTruncateLength,\n dataAttributeTruncateLength: options.dataAttributeTruncateLength,\n textTruncateLength: options.textTruncateLength,\n filter: options.filter,\n };\n }\n\n /**\n * Main extraction method - extracts all data in one pass\n * @param rootElement The document or element to extract from\n * @param runtimeOptions Options to override constructor options\n */\n extract(\n rootElement: Document | Element = document,\n runtimeOptions?: Partial<ExtractionOptions>\n ): SmartDOMResult {\n const startTime = Date.now();\n const doc = rootElement instanceof Document ? rootElement : rootElement.ownerDocument!;\n\n // Merge runtime options with constructor options\n const options: ExtractionOptions = { ...this.options, ...runtimeOptions };\n\n // Determine the container to search\n // IMPORTANT: Respect the provided rootElement when it's an Element.\n // Previous behavior incorrectly defaulted to the whole document, causing\n // region-scoped extractions to include page-wide data.\n let container: Element | Document =\n rootElement instanceof Document ? doc : (rootElement as Element);\n // Only override container with detected main content when starting from the document.\n if (options.mainContentOnly && rootElement instanceof Document) {\n container = ContentDetection.findMainContent(doc);\n }\n\n // Extract page state\n const pageState = this.extractPageState(doc);\n\n // Extract landmarks\n const landmarks = this.extractLandmarks(doc);\n\n // Extract interactive elements\n const interactive = this.extractInteractiveElements(container, options);\n\n // Build result\n const result: SmartDOMResult = {\n mode: options.mode,\n timestamp: startTime,\n page: pageState,\n landmarks,\n interactive,\n };\n\n // Add semantic elements in full mode\n if (options.mode === 'full') {\n result.semantic = this.extractSemanticElements(container, options);\n result.metadata = this.extractMetadata(doc, container, options);\n }\n\n return result;\n }\n\n /**\n * Extract page state information\n */\n private extractPageState(doc: Document): PageState {\n return {\n url: doc.location?.href || '',\n title: doc.title || '',\n hasErrors: this.detectErrors(doc),\n isLoading: this.detectLoading(doc),\n hasModals: this.detectModals(doc),\n hasFocus: this.getFocusedElement(doc),\n };\n }\n\n /**\n * Extract page landmarks\n */\n private extractLandmarks(doc: Document): PageLandmarks {\n const detected = ContentDetection.detectLandmarks(doc);\n return {\n navigation: this.elementsToSelectors(detected.navigation || []),\n main: this.elementsToSelectors(detected.main || []),\n forms: this.elementsToSelectors(detected.form || []),\n headers: this.elementsToSelectors(detected.banner || []),\n footers: this.elementsToSelectors(detected.contentinfo || []),\n articles: this.elementsToSelectors(detected.region || []),\n sections: this.elementsToSelectors(detected.region || []),\n };\n }\n\n /**\n * Convert elements to selector strings\n */\n private elementsToSelectors(elements: Element[]): string[] {\n return elements.map((el) => SelectorGenerator.generateSelectors(el).css);\n }\n\n /**\n * Extract interactive elements\n */\n private extractInteractiveElements(\n container: Element | Document,\n options: ExtractionOptions\n ): SmartDOMResult['interactive'] {\n const buttons: ExtractedElement[] = [];\n const links: ExtractedElement[] = [];\n const inputs: ExtractedElement[] = [];\n const clickable: ExtractedElement[] = [];\n\n // Extract buttons\n const buttonElements = container.querySelectorAll(\n 'button, [role=\"button\"], input[type=\"button\"], input[type=\"submit\"]'\n );\n buttonElements.forEach((el) => {\n if (this.shouldIncludeElement(el, options)) {\n const extracted = DOMTraversal.extractElement(el, options);\n if (extracted) buttons.push(extracted);\n }\n });\n\n // Extract links\n const linkElements = container.querySelectorAll('a[href]');\n linkElements.forEach((el) => {\n if (this.shouldIncludeElement(el, options)) {\n const extracted = DOMTraversal.extractElement(el, options);\n if (extracted) links.push(extracted);\n }\n });\n\n // Extract form inputs\n const inputElements = container.querySelectorAll(\n 'input:not([type=\"button\"]):not([type=\"submit\"]), textarea, select'\n );\n inputElements.forEach((el) => {\n if (this.shouldIncludeElement(el, options)) {\n const extracted = DOMTraversal.extractElement(el, options);\n if (extracted) inputs.push(extracted);\n }\n });\n\n // Extract custom selectors\n if (options.customSelectors) {\n options.customSelectors.forEach((selector) => {\n const elements = container.querySelectorAll(selector);\n elements.forEach((el) => {\n if (this.shouldIncludeElement(el, options)) {\n const extracted = DOMTraversal.extractElement(el, options);\n if (extracted) clickable.push(extracted);\n }\n });\n });\n }\n\n // Extract forms\n const forms = this.extractForms(container, options);\n\n return {\n buttons,\n links,\n inputs,\n forms,\n clickable,\n };\n }\n\n /**\n * Extract form information\n */\n private extractForms(container: Element | Document, options: ExtractionOptions): FormInfo[] {\n const forms: FormInfo[] = [];\n const formElements = container.querySelectorAll('form');\n\n formElements.forEach((form) => {\n if (!this.shouldIncludeElement(form, options)) return;\n\n const formInputs: ExtractedElement[] = [];\n const formButtons: ExtractedElement[] = [];\n\n // Extract form inputs\n const inputs = form.querySelectorAll(\n 'input:not([type=\"button\"]):not([type=\"submit\"]), textarea, select'\n );\n inputs.forEach((input) => {\n const extracted = DOMTraversal.extractElement(input, options);\n if (extracted) formInputs.push(extracted);\n });\n\n // Extract form buttons\n const buttons = form.querySelectorAll('button, input[type=\"button\"], input[type=\"submit\"]');\n buttons.forEach((button) => {\n const extracted = DOMTraversal.extractElement(button, options);\n if (extracted) formButtons.push(extracted);\n });\n\n forms.push({\n selector: SelectorGenerator.generateSelectors(form).css,\n action: form.getAttribute('action') || undefined,\n method: form.getAttribute('method') || undefined,\n inputs: formInputs,\n buttons: formButtons,\n });\n });\n\n return forms;\n }\n\n /**\n * Extract semantic elements (full mode only)\n */\n private extractSemanticElements(\n container: Element | Document,\n options: ExtractionOptions\n ): SmartDOMResult['semantic'] {\n const headings: ExtractedElement[] = [];\n const images: ExtractedElement[] = [];\n const tables: ExtractedElement[] = [];\n const lists: ExtractedElement[] = [];\n const articles: ExtractedElement[] = [];\n\n // Extract headings\n container.querySelectorAll('h1, h2, h3, h4, h5, h6').forEach((el) => {\n if (this.shouldIncludeElement(el, options)) {\n const extracted = DOMTraversal.extractElement(el, options);\n if (extracted) headings.push(extracted);\n }\n });\n\n // Extract images\n container.querySelectorAll('img').forEach((el) => {\n if (this.shouldIncludeElement(el, options)) {\n const extracted = DOMTraversal.extractElement(el, options);\n if (extracted) images.push(extracted);\n }\n });\n\n // Extract tables\n container.querySelectorAll('table').forEach((el) => {\n if (this.shouldIncludeElement(el, options)) {\n const extracted = DOMTraversal.extractElement(el, options);\n if (extracted) tables.push(extracted);\n }\n });\n\n // Extract lists\n container.querySelectorAll('ul, ol').forEach((el) => {\n if (this.shouldIncludeElement(el, options)) {\n const extracted = DOMTraversal.extractElement(el, options);\n if (extracted) lists.push(extracted);\n }\n });\n\n // Extract articles\n container.querySelectorAll('article, [role=\"article\"]').forEach((el) => {\n if (this.shouldIncludeElement(el, options)) {\n const extracted = DOMTraversal.extractElement(el, options);\n if (extracted) articles.push(extracted);\n }\n });\n\n return {\n headings,\n images,\n tables,\n lists,\n articles,\n };\n }\n\n /**\n * Extract metadata\n */\n private extractMetadata(\n doc: Document,\n container: Element | Document,\n options: ExtractionOptions\n ): SmartDOMResult['metadata'] {\n const allElements = container.querySelectorAll('*');\n const extractedElements = container.querySelectorAll(\n 'button, a, input, textarea, select, h1, h2, h3, h4, h5, h6, img, table, ul, ol, article'\n ).length;\n\n return {\n totalElements: allElements.length,\n extractedElements,\n mainContent:\n options.mainContentOnly && container instanceof Element\n ? SelectorGenerator.generateSelectors(container).css\n : undefined,\n language: doc.documentElement.getAttribute('lang') || undefined,\n };\n }\n\n /**\n * Check if element should be included based on options\n */\n private shouldIncludeElement(element: Element, options: ExtractionOptions): boolean {\n // Check visibility\n if (!options.includeHidden && !DOMTraversal.isVisible(element)) {\n return false;\n }\n\n // Check viewport\n if (options.viewportOnly && !DOMTraversal.isInViewport(element)) {\n return false;\n }\n\n // Check custom filter\n if (options.filter && !DOMTraversal.passesFilter(element, options.filter)) {\n return false;\n }\n\n return true;\n }\n\n /**\n * Detect errors on the page\n */\n private detectErrors(doc: Document): boolean {\n const errorSelectors = ['.error', '.alert-danger', '[role=\"alert\"]', '.error-message'];\n return errorSelectors.some((sel) => {\n const element = doc.querySelector(sel);\n return element ? DOMTraversal.isVisible(element) : false;\n });\n }\n\n /**\n * Detect if page is loading\n */\n private detectLoading(doc: Document): boolean {\n const loadingSelectors = ['.loading', '.spinner', '[aria-busy=\"true\"]', '.loader'];\n return loadingSelectors.some((sel) => {\n const element = doc.querySelector(sel);\n return element ? DOMTraversal.isVisible(element) : false;\n });\n }\n\n /**\n * Detect modal dialogs\n */\n private detectModals(doc: Document): boolean {\n const modalSelectors = ['[role=\"dialog\"]', '.modal', '.popup', '.overlay'];\n return modalSelectors.some((sel) => {\n const element = doc.querySelector(sel);\n return element ? DOMTraversal.isVisible(element) : false;\n });\n }\n\n /**\n * Get currently focused element\n */\n private getFocusedElement(doc: Document): string | undefined {\n const focused = doc.activeElement;\n if (focused && focused !== doc.body) {\n return SelectorGenerator.generateSelectors(focused).css;\n }\n return undefined;\n }\n\n // ===== Static convenience methods =====\n\n /**\n * Quick extraction for interactive elements only\n * @param doc The document to extract from\n * @param options Extraction options\n */\n static extractInteractive(\n doc: Document,\n options: Partial<ExtractionOptions> = {}\n ): SmartDOMResult {\n const reader = new SmartDOMReader({\n ...options,\n mode: 'interactive',\n });\n return reader.extract(doc);\n }\n\n /**\n * Quick extraction for full content\n * @param doc The document to extract from\n * @param options Extraction options\n */\n static extractFull(doc: Document, options: Partial<ExtractionOptions> = {}): SmartDOMResult {\n const reader = new SmartDOMReader({\n ...options,\n mode: 'full',\n });\n return reader.extract(doc);\n }\n\n /**\n * Extract from a specific element\n * @param element The element to extract from\n * @param mode The extraction mode\n * @param options Additional options\n */\n static extractFromElement(\n element: Element,\n mode: ExtractionMode = 'interactive',\n options: Partial<ExtractionOptions> = {}\n ): SmartDOMResult {\n const reader = new SmartDOMReader({\n ...options,\n mode,\n });\n return reader.extract(element);\n }\n}\n\n/**\n * Default export for convenience - full extraction approach\n */\nexport default SmartDOMReader;\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,82 @@
1
+ {
2
+ "name": "@mcp-b/smart-dom-reader",
3
+ "version": "1.0.1",
4
+ "description": "Token-efficient DOM extraction library for AI-powered browser automation",
5
+ "keywords": [
6
+ "mcp",
7
+ "model-context-protocol",
8
+ "browser",
9
+ "dom",
10
+ "extraction",
11
+ "ai",
12
+ "selector",
13
+ "interactive",
14
+ "semantic"
15
+ ],
16
+ "homepage": "https://github.com/MiguelsPizza/WebMCP#readme",
17
+ "bugs": {
18
+ "url": "https://github.com/MiguelsPizza/WebMCP/issues"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/MiguelsPizza/WebMCP.git",
23
+ "directory": "packages/smart-dom-reader"
24
+ },
25
+ "license": "MIT",
26
+ "author": "Alex Nahas",
27
+ "sideEffects": true,
28
+ "type": "module",
29
+ "exports": {
30
+ ".": {
31
+ "import": "./dist/index.js",
32
+ "types": "./dist/index.d.ts"
33
+ },
34
+ "./bundle-string": {
35
+ "import": "./dist/bundle-string.js",
36
+ "types": "./dist/bundle-string.d.ts"
37
+ }
38
+ },
39
+ "main": "./dist/index.js",
40
+ "module": "./dist/index.js",
41
+ "browser": "./dist/index.js",
42
+ "types": "./dist/index.d.ts",
43
+ "files": [
44
+ "dist"
45
+ ],
46
+ "devDependencies": {
47
+ "@types/node": "^22.15.21",
48
+ "tsup": "^8.4.0",
49
+ "typescript": "^5.8.3",
50
+ "vite": "^7.1.2",
51
+ "vite-plugin-monkey": "^6.0.1"
52
+ },
53
+ "peerDependencies": {
54
+ "@modelcontextprotocol/sdk": "^1.15.0"
55
+ },
56
+ "peerDependenciesMeta": {
57
+ "@modelcontextprotocol/sdk": {
58
+ "optional": true
59
+ }
60
+ },
61
+ "publishConfig": {
62
+ "access": "public",
63
+ "registry": "https://registry.npmjs.org/"
64
+ },
65
+ "scripts": {
66
+ "prebuild": "pnpm build:bundle && node generate-bundle-module.mjs",
67
+ "build": "tsup",
68
+ "build:bundle": "vite build --config vite.config.bundle.ts",
69
+ "bundle:mcp": "pnpm --filter @mcp-b/smart-dom-reader build && pnpm --filter @mcp-b/smart-dom-reader-server bundle",
70
+ "check": "biome check --write .",
71
+ "clean": "rm -rf dist .turbo",
72
+ "format": "biome format --write .",
73
+ "lint": "biome lint --write .",
74
+ "publish:dry": "pnpm publish --access public --dry-run",
75
+ "publish:npm": "pnpm publish --access public",
76
+ "test:local": "node test/local-playwright-runner.mjs",
77
+ "typecheck": "tsc --noEmit",
78
+ "version:major": "pnpm version major --no-git-tag-version",
79
+ "version:minor": "pnpm version minor --no-git-tag-version",
80
+ "version:patch": "pnpm version patch --no-git-tag-version"
81
+ }
82
+ }