@cloro-dev/response-parser 0.1.0

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.
Files changed (76) hide show
  1. package/README.md +195 -0
  2. package/dist/core/detector.d.ts +17 -0
  3. package/dist/core/detector.d.ts.map +1 -0
  4. package/dist/core/parser.d.ts +40 -0
  5. package/dist/core/parser.d.ts.map +1 -0
  6. package/dist/core/types.d.ts +35 -0
  7. package/dist/core/types.d.ts.map +1 -0
  8. package/dist/index.d.ts +170 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.esm.js +2 -0
  11. package/dist/index.esm.js.map +1 -0
  12. package/dist/index.js +2 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/providers/ai-mode.d.ts +10 -0
  15. package/dist/providers/ai-mode.d.ts.map +1 -0
  16. package/dist/providers/ai-overview.d.ts +10 -0
  17. package/dist/providers/ai-overview.d.ts.map +1 -0
  18. package/dist/providers/base-provider.d.ts +31 -0
  19. package/dist/providers/base-provider.d.ts.map +1 -0
  20. package/dist/providers/chatgpt.d.ts +10 -0
  21. package/dist/providers/chatgpt.d.ts.map +1 -0
  22. package/dist/providers/copilot.d.ts +10 -0
  23. package/dist/providers/copilot.d.ts.map +1 -0
  24. package/dist/providers/gemini.d.ts +10 -0
  25. package/dist/providers/gemini.d.ts.map +1 -0
  26. package/dist/providers/perplexity.d.ts +10 -0
  27. package/dist/providers/perplexity.d.ts.map +1 -0
  28. package/dist/react/components/AiResponseRenderer.d.ts +24 -0
  29. package/dist/react/components/AiResponseRenderer.d.ts.map +1 -0
  30. package/dist/react/components/IframeRenderer.d.ts +12 -0
  31. package/dist/react/components/IframeRenderer.d.ts.map +1 -0
  32. package/dist/react/core/detector.d.ts +17 -0
  33. package/dist/react/core/detector.d.ts.map +1 -0
  34. package/dist/react/core/parser.d.ts +40 -0
  35. package/dist/react/core/parser.d.ts.map +1 -0
  36. package/dist/react/core/types.d.ts +35 -0
  37. package/dist/react/core/types.d.ts.map +1 -0
  38. package/dist/react/hooks/useAiResponse.d.ts +19 -0
  39. package/dist/react/hooks/useAiResponse.d.ts.map +1 -0
  40. package/dist/react/index.d.ts +87 -0
  41. package/dist/react/index.d.ts.map +1 -0
  42. package/dist/react/index.esm.js +11 -0
  43. package/dist/react/index.esm.js.map +1 -0
  44. package/dist/react/index.js +11 -0
  45. package/dist/react/index.js.map +1 -0
  46. package/dist/react/providers/ai-mode.d.ts +10 -0
  47. package/dist/react/providers/ai-mode.d.ts.map +1 -0
  48. package/dist/react/providers/ai-overview.d.ts +10 -0
  49. package/dist/react/providers/ai-overview.d.ts.map +1 -0
  50. package/dist/react/providers/base-provider.d.ts +31 -0
  51. package/dist/react/providers/base-provider.d.ts.map +1 -0
  52. package/dist/react/providers/chatgpt.d.ts +10 -0
  53. package/dist/react/providers/chatgpt.d.ts.map +1 -0
  54. package/dist/react/providers/copilot.d.ts +10 -0
  55. package/dist/react/providers/copilot.d.ts.map +1 -0
  56. package/dist/react/providers/gemini.d.ts +10 -0
  57. package/dist/react/providers/gemini.d.ts.map +1 -0
  58. package/dist/react/providers/perplexity.d.ts +10 -0
  59. package/dist/react/providers/perplexity.d.ts.map +1 -0
  60. package/dist/react/react/components/AiResponseRenderer.d.ts +24 -0
  61. package/dist/react/react/components/AiResponseRenderer.d.ts.map +1 -0
  62. package/dist/react/react/components/IframeRenderer.d.ts +12 -0
  63. package/dist/react/react/components/IframeRenderer.d.ts.map +1 -0
  64. package/dist/react/react/hooks/useAiResponse.d.ts +19 -0
  65. package/dist/react/react/hooks/useAiResponse.d.ts.map +1 -0
  66. package/dist/react/react/index.d.ts +7 -0
  67. package/dist/react/react/index.d.ts.map +1 -0
  68. package/dist/react/styles/index.d.ts +1 -0
  69. package/dist/react/styles/index.d.ts.map +1 -0
  70. package/dist/react/utils/helpers.d.ts +28 -0
  71. package/dist/react/utils/helpers.d.ts.map +1 -0
  72. package/dist/styles/index.d.ts +1 -0
  73. package/dist/styles/index.d.ts.map +1 -0
  74. package/dist/utils/helpers.d.ts +28 -0
  75. package/dist/utils/helpers.d.ts.map +1 -0
  76. package/package.json +85 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":["../src/core/detector.ts","../src/providers/base-provider.ts","../src/providers/chatgpt.ts","../src/providers/gemini.ts","../src/providers/perplexity.ts","../src/providers/copilot.ts","../src/providers/ai-overview.ts","../src/providers/ai-mode.ts","../src/core/parser.ts"],"sourcesContent":["import { AIProvider, DetectedProvider } from './types';\n\nexport class ProviderDetector {\n private static readonly PROVIDER_PATTERNS = {\n CHATGPT: [\n // Check for token-based CSS classes\n (response: any) => {\n const html = response?.result?.html || response?.html || '';\n return html.includes('bg-token-bg-primary') || html.includes('text-token-text-secondary');\n },\n // Check for OpenAI-specific patterns\n (response: any) => {\n const html = response?.result?.html || response?.html || '';\n return html.includes('chatgpt.com') || html.includes('openai.com');\n },\n ],\n GEMINI: [\n // Check for Material Design components\n (response: any) => {\n const html = response?.result?.html || response?.html || '';\n return html.includes('bard-sidenav') || html.includes('mat-sidenav');\n },\n // Check for Gemini-specific classes\n (response: any) => {\n const html = response?.result?.html || response?.html || '';\n return html.includes('gemini.google.com') || html.includes('gem-sys-color');\n },\n ],\n PERPLEXITY: [\n // Check for Perplexity-specific structure\n (response: any) => {\n const html = response?.result?.html || response?.html || '';\n return html.includes('perplexity.ai') || html.includes('prose');\n },\n ],\n COPILOT: [\n // Check for Copilot-specific elements\n (response: any) => {\n const html = response?.result?.html || response?.html || '';\n return html.includes('copilot.microsoft.com') || html.includes('data-testid=\"sidebar-container\"');\n },\n ],\n AIOVERVIEW: [\n // Check for AI Overview specific structure\n (response: any) => {\n // Check for aioverview nested structure\n if (response?.result?.aioverview?.text) return true;\n if (response?.aioverview?.text) return true;\n\n // Check for WIZ_global_data (AI Overview specific)\n const html = response?.result?.html || response?.html || '';\n return html.includes('WIZ_global_data') || html.includes('DnVkpd');\n },\n ],\n AIMODE: [\n // Check for AI Mode specific elements\n (response: any) => {\n const html = response?.result?.html || response?.html || '';\n return html.includes('DZ13He') || html.includes('wYq63b') || html.includes('AI Mode');\n },\n ],\n };\n\n /**\n * Detect the AI provider from the response\n */\n static detect(response: any): DetectedProvider | null {\n const scores: Record<AIProvider, number> = {\n CHATGPT: 0,\n GEMINI: 0,\n PERPLEXITY: 0,\n COPILOT: 0,\n AIOVERVIEW: 0,\n AIMODE: 0,\n };\n\n // Score each provider based on pattern matches\n for (const [provider, patterns] of Object.entries(this.PROVIDER_PATTERNS)) {\n for (const pattern of patterns) {\n try {\n if (pattern(response)) {\n scores[provider as AIProvider]++;\n }\n } catch (error) {\n // Ignore pattern errors\n }\n }\n }\n\n // Find the provider with the highest score\n let maxScore = 0;\n let detectedProvider: AIProvider | null = null;\n\n for (const [provider, score] of Object.entries(scores)) {\n if (score > maxScore) {\n maxScore = score;\n detectedProvider = provider as AIProvider;\n }\n }\n\n // Return null if no patterns matched\n if (maxScore === 0) return null;\n\n return {\n provider: detectedProvider!,\n confidence: maxScore / Object.values(scores).reduce((a, b) => Math.max(a, b), 1),\n };\n }\n\n /**\n * Get all possible providers with their confidence scores\n */\n static getAllProviders(response: any): DetectedProvider[] {\n const providers: DetectedProvider[] = [];\n\n for (const [provider, patterns] of Object.entries(this.PROVIDER_PATTERNS)) {\n let matches = 0;\n for (const pattern of patterns) {\n try {\n if (pattern(response)) {\n matches++;\n }\n } catch (error) {\n // Ignore pattern errors\n }\n }\n\n if (matches > 0) {\n providers.push({\n provider: provider as AIProvider,\n confidence: matches / patterns.length,\n });\n }\n }\n\n // Sort by confidence (highest first)\n return providers.sort((a, b) => b.confidence - a.confidence);\n }\n\n /**\n * Validate if a detected provider is likely correct\n */\n static validate(response: any, provider: AIProvider): boolean {\n const detected = this.detect(response);\n return detected?.provider === provider && detected.confidence > 0.5;\n }\n}","import { AIProvider, ParsedResponse, ParseOptions, StyleOptions, ContentExtraction } from '../core/types';\n\nexport abstract class BaseProvider {\n abstract readonly name: AIProvider;\n abstract readonly baseUrl: string;\n abstract readonly defaultStyles: string;\n\n /**\n * Parse an AI response and return structured content\n */\n abstract parse(response: any, options?: ParseOptions): ParsedResponse;\n\n /**\n * Extract content from the response object\n */\n abstract extractContent(response: any): ContentExtraction;\n\n /**\n * Inject provider-specific styles into HTML\n */\n injectStyles(html: string, options?: StyleOptions): string {\n let styledHtml = html;\n\n // Inject base URL if not already present\n if (options?.baseUrl && !html.includes('<base ')) {\n if (styledHtml.includes('<head>')) {\n styledHtml = styledHtml.replace(\n '<head>',\n `<head><base href=\"${options.baseUrl}\">`,\n );\n } else {\n styledHtml = styledHtml.replace(\n /(<html[^>]*>)/i,\n `$1<head><base href=\"${options.baseUrl}\"></head>`,\n );\n }\n }\n\n // Inject styles\n const styles = options?.customCSS\n ? this.defaultStyles + '\\n' + options.customCSS\n : this.defaultStyles;\n\n if (styledHtml.includes('<head>')) {\n styledHtml = styledHtml.replace('<head>', `<head><style>${styles}</style>`);\n } else {\n styledHtml = styledHtml.replace(\n /(<html[^>]*>)/i,\n `$1<head><style>${styles}</style></head>`,\n );\n }\n\n return styledHtml;\n }\n\n /**\n * Sanitize HTML content\n */\n sanitizeHtml(html: string): string {\n // Remove scripts\n let sanitized = html.replace(/<script\\b[^>]*>[\\s\\S]*?<\\/script>/gim, '');\n\n // Remove noscript tags\n sanitized = sanitized.replace(/<noscript[\\s\\S]*?<\\/noscript>/gi, '');\n\n return sanitized;\n }\n\n /**\n * Check if content is a full HTML document\n */\n isFullDocument(html: string): boolean {\n return /^\\s*(<html|<!DOCTYPE)/i.test(html);\n }\n\n /**\n * Wrap HTML fragment in a document\n */\n wrapFragment(html: string): string {\n return `<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <meta http-equiv=\"Content-Security-Policy\" content=\"default-src 'none'; script-src 'none'; style-src 'unsafe-inline';\">\n <style>\n body {\n margin: 0;\n padding: 16px;\n font-family: system-ui, -apple-system, sans-serif;\n white-space: pre-wrap;\n word-wrap: break-word;\n }\n img { max-width: 100%; height: auto; }\n body {\n pointer-events: none;\n user-select: none;\n }\n </style>\n</head>\n<body>\n ${html}\n</body>\n</html>`;\n }\n}","import { BaseProvider } from './base-provider';\nimport { AIProvider, ParsedResponse, ParseOptions, ContentExtraction } from '../core/types';\n\nexport class ChatGPTProvider extends BaseProvider {\n readonly name: AIProvider = 'CHATGPT';\n readonly baseUrl = 'https://chatgpt.com';\n\n readonly defaultStyles = `\n /* Force Dark Background on main containers and wrappers */\n html, body, main, article, footer, form,\n [class*=\"bg-\"], [class*=\"footer\"], [class*=\"bottom\"],\n div[class*=\"border-t\"],\n #thread-bottom-container, #thread-bottom,\n #thread, .composer-parent, [class*=\"group\\\\/thread\"] {\n background-color: #131314 !important;\n color: #e3e3e3 !important;\n border-color: #2a2b36 !important;\n }\n\n /* Force background on specific white artifacts in the footer */\n #thread-bottom-container .bg-clip-padding,\n #thread-bottom-container .content-fade,\n #thread-bottom-container .absolute {\n background-color: transparent !important;\n }\n\n /* Specific targeting for the composer/input box (was white) */\n form .bg-token-bg-primary, form .shadow-short {\n background-color: #2a2b36 !important;\n border-color: #3e3f4b !important;\n box-shadow: none !important;\n }\n\n /* Disclaimer Footer - Force Dark Background */\n div[class*=\"text-token-text-secondary\"] {\n color: #9ca3af !important;\n background-color: #131314 !important;\n }\n\n /* Force Text Color to Light */\n p, h1, h2, h3, h4, h5, h6, li, span, div, td, th, textarea, button {\n color: #e3e3e3 !important;\n }\n\n /* Links - Light Blue */\n a, a span {\n color: #8ab4f8 !important;\n }\n\n /* Code Blocks */\n pre, code, pre div, code span {\n background-color: #2a2b36 !important;\n color: #e3e3e3 !important;\n text-shadow: none !important;\n }\n\n /* Inputs/Textareas */\n input, textarea {\n background-color: transparent !important;\n color: #e3e3e3 !important;\n border-color: #3e3f4b !important;\n }\n\n /* Placeholder text */\n textarea::placeholder {\n color: #9ca3af !important;\n }\n\n /* Hide Sidebar */\n nav, [class*=\"sidebar\"] {\n display: none !important;\n }\n\n /* Media visibility */\n img, video {\n opacity: 1 !important;\n }\n `;\n\n extractContent(response: any): ContentExtraction {\n let html = '';\n let text = '';\n\n // Handle nested structure\n let dataToCheck = response;\n if (response.result) {\n dataToCheck = response.result;\n }\n\n // Extract content\n if (typeof dataToCheck === 'string') {\n if (dataToCheck.trim().startsWith('<') && dataToCheck.includes('>')) {\n html = dataToCheck;\n } else {\n text = dataToCheck;\n }\n } else if (typeof dataToCheck === 'object' && dataToCheck !== null) {\n if (dataToCheck.html) {\n html = dataToCheck.html;\n } else if (dataToCheck.content) {\n if (dataToCheck.content.trim().startsWith('<')) {\n html = dataToCheck.content;\n } else {\n text = dataToCheck.content;\n }\n } else if (dataToCheck.text) {\n text = dataToCheck.text;\n }\n }\n\n return { html, text };\n }\n\n parse(response: any, options?: ParseOptions): ParsedResponse {\n const { html, text } = this.extractContent(response);\n\n if (!html && !text) {\n throw new Error('No content found in ChatGPT response');\n }\n\n let finalHtml = html || '';\n\n // If we only have text, create simple HTML\n if (!finalHtml && text) {\n finalHtml = `<div>${text.replace(/\\n/g, '<br>')}</div>`;\n }\n\n // Sanitize HTML\n finalHtml = this.sanitizeHtml(finalHtml);\n\n // Inject styles\n finalHtml = this.injectStyles(finalHtml, {\n theme: options?.theme || 'dark',\n baseUrl: options?.baseUrl || this.baseUrl,\n });\n\n return {\n provider: this.name,\n html: finalHtml,\n text,\n metadata: {\n isFullDocument: this.isFullDocument(finalHtml),\n },\n };\n }\n}","import { BaseProvider } from './base-provider';\nimport { AIProvider, ParsedResponse, ParseOptions, ContentExtraction } from '../core/types';\n\nexport class GeminiProvider extends BaseProvider {\n readonly name: AIProvider = 'GEMINI';\n readonly baseUrl = 'https://gemini.google.com';\n\n readonly defaultStyles = `\n /* Gemini Dark Mode Variable Overrides */\n :root {\n --gem-sys-color--surface: #131314 !important;\n --gem-sys-color--surface-container: #1e1f20 !important;\n --gem-sys-color--on-surface: #e3e3e3 !important;\n --bard-color-synthetic--chat-window-surface: #131314 !important;\n --bard-color-surface-dim-tmp: #131314 !important;\n }\n\n /* UI hiding - Gemini */\n bard-sidenav, mat-sidenav, .mat-drawer-backdrop, .side-nav-menu-button,\n\n /* Gemini \"About Gemini\" footer/navigation block */\n .gb_5a, .gb_5c, .gb_5d, .gb_5e,\n .gb_Uc, .gb_Vc, .gb_Wc,\n a[href*=\"about\"],\n a[href*=\"subscriptions\"],\n a[href*=\"business\"],\n div[class*=\"gb_5\"],\n .gb_Pd, .gb_Qd, .gb_Rd,\n .gb_Sd, .gb_Td, .gb_Ud, .gb_Vd,\n [aria-label*=\"About\"],\n [aria-label*=\"Gemini App\"],\n [aria-label*=\"Subscriptions\"],\n [aria-label*=\"For Business\"],\n *:contains(\"About Gemini\"),\n *:contains(\"Gemini App\"),\n *:contains(\"Subscriptions\"),\n *:contains(\"For Business\") {\n display: none !important;\n }\n\n /* General Layout */\n main { width: 100% !important; max-width: 100% !important; margin: 0 !important; }\n\n /* Force Dark Mode on Body and Gemini Containers */\n body, .content-container, chat-app, .main-content, .chat-container {\n background-color: #131314 !important;\n color: #e3e3e3 !important;\n }\n `;\n\n extractContent(response: any): ContentExtraction {\n let html = '';\n let text = '';\n let sources: any[] = [];\n\n // Handle nested structure\n let dataToCheck = response;\n if (response.result) {\n dataToCheck = response.result;\n }\n\n // Extract content\n if (typeof dataToCheck === 'string') {\n if (dataToCheck.trim().startsWith('<') && dataToCheck.includes('>')) {\n html = dataToCheck;\n } else {\n text = dataToCheck;\n }\n } else if (typeof dataToCheck === 'object' && dataToCheck !== null) {\n if (dataToCheck.html) {\n html = dataToCheck.html;\n } else if (dataToCheck.content) {\n if (dataToCheck.content.trim().startsWith('<')) {\n html = dataToCheck.content;\n } else {\n text = dataToCheck.content;\n }\n } else if (dataToCheck.text) {\n text = dataToCheck.text;\n }\n\n // Check for aioverview nested structure\n if (dataToCheck.aioverview) {\n if (dataToCheck.aioverview.text) text = dataToCheck.aioverview.text;\n if (dataToCheck.aioverview.sources) sources = dataToCheck.aioverview.sources;\n }\n }\n\n return { html, text, sources };\n }\n\n parse(response: any, options?: ParseOptions): ParsedResponse {\n const { html, text, sources } = this.extractContent(response);\n\n if (!html && !text) {\n throw new Error('No content found in Gemini response');\n }\n\n let finalHtml = html || '';\n\n // If we only have text, create simple HTML\n if (!finalHtml && text) {\n finalHtml = `<div>${text.replace(/\\n/g, '<br>')}</div>`;\n }\n\n // Sanitize HTML (remove scripts and noscript)\n finalHtml = this.sanitizeHtml(finalHtml);\n\n // For Gemini, we need to extract content from WIZ_global_data for AI Overview/Mode\n // But for regular Gemini, we just inject styles\n finalHtml = this.injectStyles(finalHtml, {\n theme: options?.theme || 'dark',\n baseUrl: options?.baseUrl || this.baseUrl,\n });\n\n return {\n provider: this.name,\n html: finalHtml,\n text,\n sources,\n metadata: {\n isFullDocument: this.isFullDocument(finalHtml),\n },\n };\n }\n}","import { BaseProvider } from './base-provider';\nimport { AIProvider, ParsedResponse, ParseOptions, ContentExtraction } from '../core/types';\n\nexport class PerplexityProvider extends BaseProvider {\n readonly name: AIProvider = 'PERPLEXITY';\n readonly baseUrl = 'https://www.perplexity.ai';\n\n readonly defaultStyles = `\n html {\n filter: invert(1) hue-rotate(180deg);\n background-color: white !important;\n }\n img, video, iframe, svg {\n filter: invert(1) hue-rotate(180deg);\n }\n `;\n\n extractContent(response: any): ContentExtraction {\n let html = '';\n let text = '';\n\n // Handle nested structure\n let dataToCheck = response;\n if (response.result) {\n dataToCheck = response.result;\n }\n\n // Extract content\n if (typeof dataToCheck === 'string') {\n if (dataToCheck.trim().startsWith('<') && dataToCheck.includes('>')) {\n html = dataToCheck;\n } else {\n text = dataToCheck;\n }\n } else if (typeof dataToCheck === 'object' && dataToCheck !== null) {\n if (dataToCheck.html) {\n html = dataToCheck.html;\n } else if (dataToCheck.content) {\n if (dataToCheck.content.trim().startsWith('<')) {\n html = dataToCheck.content;\n } else {\n text = dataToCheck.content;\n }\n } else if (dataToCheck.text) {\n text = dataToCheck.text;\n }\n }\n\n return { html, text };\n }\n\n parse(response: any, options?: ParseOptions): ParsedResponse {\n const { html, text } = this.extractContent(response);\n\n if (!html && !text) {\n throw new Error('No content found in Perplexity response');\n }\n\n let finalHtml = html || '';\n\n // If we only have text, create simple HTML\n if (!finalHtml && text) {\n finalHtml = `<div>${text.replace(/\\n/g, '<br>')}</div>`;\n }\n\n // For Perplexity, we apply color inversion for dark mode\n // Don't sanitize scripts as Perplexity might need them for functionality\n finalHtml = this.injectStyles(finalHtml, {\n theme: options?.theme || 'dark',\n baseUrl: options?.baseUrl || this.baseUrl,\n customCSS: options?.theme === 'light' ? '' : this.defaultStyles,\n });\n\n return {\n provider: this.name,\n html: finalHtml,\n text,\n metadata: {\n isFullDocument: this.isFullDocument(finalHtml),\n },\n };\n }\n}","import { BaseProvider } from './base-provider';\nimport { AIProvider, ParsedResponse, ParseOptions, ContentExtraction } from '../core/types';\n\nexport class CopilotProvider extends BaseProvider {\n readonly name: AIProvider = 'COPILOT';\n readonly baseUrl = 'https://copilot.microsoft.com';\n\n readonly defaultStyles = `\n /* Copilot Sidebar & Header */\n div:has(> [data-testid=\"sidebar-container\"]),\n [data-testid=\"sidebar-container\"],\n [data-testid=\"sticky-header\"],\n .side-nav-menu-button {\n display: none !important;\n }\n\n /* General Layout Fixes */\n main {\n width: 100% !important;\n max-width: 100% !important;\n margin: 0 !important;\n }\n `;\n\n extractContent(response: any): ContentExtraction {\n let html = '';\n let text = '';\n\n // Handle nested structure\n let dataToCheck = response;\n if (response.result) {\n dataToCheck = response.result;\n }\n\n // Extract content\n if (typeof dataToCheck === 'string') {\n if (dataToCheck.trim().startsWith('<') && dataToCheck.includes('>')) {\n html = dataToCheck;\n } else {\n text = dataToCheck;\n }\n } else if (typeof dataToCheck === 'object' && dataToCheck !== null) {\n if (dataToCheck.html) {\n html = dataToCheck.html;\n } else if (dataToCheck.content) {\n if (dataToCheck.content.trim().startsWith('<')) {\n html = dataToCheck.content;\n } else {\n text = dataToCheck.content;\n }\n } else if (dataToCheck.text) {\n text = dataToCheck.text;\n }\n }\n\n return { html, text };\n }\n\n parse(response: any, options?: ParseOptions): ParsedResponse {\n const { html, text } = this.extractContent(response);\n\n if (!html && !text) {\n throw new Error('No content found in Copilot response');\n }\n\n let finalHtml = html || '';\n\n // If we only have text, create simple HTML\n if (!finalHtml && text) {\n finalHtml = `<div>${text.replace(/\\n/g, '<br>')}</div>`;\n }\n\n // Remove noscript tags\n finalHtml = finalHtml.replace(/<noscript[\\s\\S]*?<\\/noscript>/gi, '');\n\n // Inject styles\n finalHtml = this.injectStyles(finalHtml, {\n theme: options?.theme || 'dark',\n baseUrl: options?.baseUrl || this.baseUrl,\n });\n\n return {\n provider: this.name,\n html: finalHtml,\n text,\n metadata: {\n isFullDocument: this.isFullDocument(finalHtml),\n },\n };\n }\n}","import { BaseProvider } from './base-provider';\nimport { AIProvider, ParsedResponse, ParseOptions, ContentExtraction } from '../core/types';\n\nexport class AIOverviewProvider extends BaseProvider {\n readonly name: AIProvider = 'AIOVERVIEW';\n readonly baseUrl = 'https://www.google.com';\n\n readonly defaultStyles = `\n /* UI hiding - Google Search (AI Overview) */\n header, #header, #searchform, .sfbg, #appbar,\n div[role=\"navigation\"], #leftnav, #sidetogether,\n [role=\"banner\"], .Fgvgjc, #hdtb, .hdtb-msb,\n footer, #footer, .fbar,\n .pdp-nav, [aria-label=\"Main menu\"], .gb_Td, .gb_L,\n\n /* Specific AI Mode Selectors */\n .DZ13He,\n .wYq63b,\n .eT9Cje,\n .bNg8Rb,\n .S6VXfe,\n .Lu57id {\n display: none !important;\n }\n\n /* General Layout */\n main { width: 100% !important; max-width: 100% !important; margin: 0 !important; }\n `;\n\n extractContent(response: any): ContentExtraction {\n let html = '';\n let text = '';\n let sources: any[] = [];\n\n // Handle nested structure\n let dataToCheck = response;\n if (response.result) {\n dataToCheck = response.result;\n }\n\n // For AI Overview, check for aioverview structure first\n if (dataToCheck.aioverview) {\n if (dataToCheck.aioverview.text) {\n text = dataToCheck.aioverview.text;\n }\n if (dataToCheck.aioverview.sources) {\n sources = dataToCheck.aioverview.sources;\n }\n }\n\n // Check for standard content fields\n if (typeof dataToCheck === 'string') {\n if (dataToCheck.trim().startsWith('<') && dataToCheck.includes('>')) {\n html = dataToCheck;\n } else {\n text = text || dataToCheck;\n }\n } else if (typeof dataToCheck === 'object' && dataToCheck !== null) {\n if (dataToCheck.html && !text) {\n html = dataToCheck.html;\n } else if (dataToCheck.content && !text) {\n if (dataToCheck.content.trim().startsWith('<')) {\n html = dataToCheck.content;\n } else {\n text = dataToCheck.content;\n }\n } else if (dataToCheck.text && !text) {\n text = dataToCheck.text;\n }\n }\n\n // If we have HTML, try to extract WIZ_global_data\n if (html) {\n const wizDataMatch = html.match(/\"DnVkpd\"\\s*:\\s*\"((?:[^\"\\\\]|\\\\.)*)\"/);\n if (wizDataMatch && wizDataMatch[1]) {\n try {\n // Decode the JSON string to get the actual content\n let extractedContent = JSON.parse(`\"${wizDataMatch[1]}\"`);\n\n // Format specific delimiters used by AI Overview\n // ∰ seems to separate turns/sections\n extractedContent = extractedContent.replace(\n /∰/g,\n '<hr class=\"gemini-separator\">',\n );\n\n // ∞ seems to separate prompts/images/responses. Often precedes URLs.\n // We'll try to detect image URLs following this and turn them into tags.\n extractedContent = extractedContent.replace(\n /∞(https:\\/\\/[^ ]+\\.(?:jpg|png|webp|gif|jpeg)(?:\\?[^ ]*)?)/gi,\n '<br><img src=\"$1\" class=\"gemini-image\" alt=\"Generated Image\"><br>',\n );\n\n // Handle remaining ∞\n extractedContent = extractedContent.replace(/∞/g, '<br>');\n\n // Handle newlines\n extractedContent = extractedContent.replace(/\\n/g, '<br>');\n\n text = extractedContent;\n } catch (e) {\n console.error('Failed to parse AI Overview WIZ data', e);\n // Keep original HTML if parsing fails\n }\n }\n }\n\n return { html, text, sources };\n }\n\n parse(response: any, options?: ParseOptions): ParsedResponse {\n const { html, text, sources } = this.extractContent(response);\n\n if (!html && !text) {\n throw new Error('No content found in AI Overview response');\n }\n\n let finalHtml = '';\n\n // If we have extracted text from WIZ data, build HTML from it\n if (text && !html) {\n const googleStyles = `\n body {\n font-family: 'Google Sans', Roboto, sans-serif;\n line-height: 1.5;\n padding: 20px;\n color: #e3e3e3;\n background-color: #131314;\n }\n .gemini-separator {\n border: 0;\n border-top: 1px solid #444;\n margin: 24px 0;\n }\n .gemini-image {\n max-width: 100%;\n border-radius: 8px;\n margin: 12px 0;\n border: 1px solid #333;\n }\n a { color: #8ab4f8; }\n table { border-collapse: collapse; width: 100%; margin: 16px 0; }\n th, td { border: 1px solid #444; padding: 8px; text-align: left; }\n th { background-color: #1f1f1f; }\n `;\n\n finalHtml = `<!DOCTYPE html>\n <html>\n <head>\n <base href=\"${options?.baseUrl || this.baseUrl}\">\n <style>${googleStyles}</style>\n </head>\n <body>\n ${text}\n </body>\n </html>`;\n } else {\n // Use the original HTML but clean it\n finalHtml = html || '';\n finalHtml = this.sanitizeHtml(finalHtml);\n\n // Inject base URL and styles\n finalHtml = this.injectStyles(finalHtml, {\n theme: options?.theme || 'dark',\n baseUrl: options?.baseUrl || this.baseUrl,\n hideUI: true,\n });\n }\n\n return {\n provider: this.name,\n html: finalHtml,\n text,\n sources,\n metadata: {\n isFullDocument: this.isFullDocument(finalHtml),\n hasWizData: !!text && !html,\n },\n };\n }\n}","import { BaseProvider } from './base-provider';\nimport { AIProvider, ParsedResponse, ParseOptions, ContentExtraction } from '../core/types';\n\nexport class AIModeProvider extends BaseProvider {\n readonly name: AIProvider = 'AIMODE';\n readonly baseUrl = 'https://www.google.com';\n\n readonly defaultStyles = `\n /* UI hiding - Google Search (AI Mode) */\n header, #header, #searchform, .sfbg, #appbar,\n div[role=\"navigation\"], #leftnav, #sidetogether,\n [role=\"banner\"], .Fgvgjc, #hdtb, .hdtb-msb,\n footer, #footer, .fbar,\n .pdp-nav, [aria-label=\"Main menu\"], .gb_Td, .gb_L,\n\n /* Specific AI Mode Selectors found in analysis */\n .DZ13He, /* Main sticky top bar */\n .wYq63b, /* Accessibility links bar */\n .eT9Cje, /* History/New Search buttons */\n .bNg8Rb, /* Hidden H1 headers */\n .S6VXfe, /* Accessibility container */\n .Lu57id /* Potential other top bar */ {\n display: none !important;\n }\n\n /* General Layout */\n main { width: 100% !important; max-width: 100% !important; margin: 0 !important; }\n `;\n\n extractContent(response: any): ContentExtraction {\n let html = '';\n let text = '';\n\n // Handle nested structure\n let dataToCheck = response;\n if (response.result) {\n dataToCheck = response.result;\n }\n\n // Extract content\n if (typeof dataToCheck === 'string') {\n if (dataToCheck.trim().startsWith('<') && dataToCheck.includes('>')) {\n html = dataToCheck;\n } else {\n text = dataToCheck;\n }\n } else if (typeof dataToCheck === 'object' && dataToCheck !== null) {\n if (dataToCheck.html) {\n html = dataToCheck.html;\n } else if (dataToCheck.content) {\n if (dataToCheck.content.trim().startsWith('<')) {\n html = dataToCheck.content;\n } else {\n text = dataToCheck.content;\n }\n } else if (dataToCheck.text) {\n text = dataToCheck.text;\n }\n }\n\n return { html, text };\n }\n\n parse(response: any, options?: ParseOptions): ParsedResponse {\n const { html, text } = this.extractContent(response);\n\n if (!html && !text) {\n throw new Error('No content found in AI Mode response');\n }\n\n let finalHtml = html || '';\n\n // If we only have text, create simple HTML\n if (!finalHtml && text) {\n finalHtml = `<div>${text.replace(/\\n/g, '<br>')}</div>`;\n }\n\n // Sanitize HTML\n finalHtml = this.sanitizeHtml(finalHtml);\n\n // Inject styles to hide UI elements\n finalHtml = this.injectStyles(finalHtml, {\n theme: options?.theme || 'dark',\n baseUrl: options?.baseUrl || this.baseUrl,\n hideUI: true,\n });\n\n return {\n provider: this.name,\n html: finalHtml,\n text,\n metadata: {\n isFullDocument: this.isFullDocument(finalHtml),\n },\n };\n }\n}","import { AIProvider, ParsedResponse, ParseOptions } from './types';\nimport { ProviderDetector } from './detector';\nimport { ChatGPTProvider } from '../providers/chatgpt';\nimport { GeminiProvider } from '../providers/gemini';\nimport { PerplexityProvider } from '../providers/perplexity';\nimport { CopilotProvider } from '../providers/copilot';\nimport { AIOverviewProvider } from '../providers/ai-overview';\nimport { AIModeProvider } from '../providers/ai-mode';\n\nexport class AIResponseParser {\n private providers: Map<AIProvider, any> = new Map();\n\n constructor() {\n this.providers.set('CHATGPT', new ChatGPTProvider());\n this.providers.set('GEMINI', new GeminiProvider());\n this.providers.set('PERPLEXITY', new PerplexityProvider());\n this.providers.set('COPILOT', new CopilotProvider());\n this.providers.set('AIOVERVIEW', new AIOverviewProvider());\n this.providers.set('AIMODE', new AIModeProvider());\n }\n\n /**\n * Parse an AI response with auto-detected provider\n */\n parse(response: any, options?: ParseOptions): ParsedResponse | null {\n const detection = ProviderDetector.detect(response);\n\n if (!detection) {\n // Try to parse as generic HTML if no provider detected\n return this.parseGeneric(response, options);\n }\n\n const provider = this.providers.get(detection.provider);\n if (!provider) {\n return null;\n }\n\n try {\n const parsed = provider.parse(response, options);\n return {\n ...parsed,\n metadata: {\n ...parsed.metadata,\n detectionConfidence: detection.confidence,\n },\n };\n } catch (error) {\n console.error(`Failed to parse response with ${detection.provider}:`, error);\n return null;\n }\n }\n\n /**\n * Parse with explicit provider specification\n */\n parseWithProvider(\n response: any,\n provider: AIProvider,\n options?: ParseOptions\n ): ParsedResponse | null {\n const providerInstance = this.providers.get(provider);\n if (!providerInstance) {\n throw new Error(`Unknown provider: ${provider}`);\n }\n\n try {\n return providerInstance.parse(response, options);\n } catch (error) {\n console.error(`Failed to parse response with ${provider}:`, error);\n return null;\n }\n }\n\n /**\n * Detect the provider from a response\n */\n detectProvider(response: any): AIProvider | null {\n const detection = ProviderDetector.detect(response);\n return detection?.provider || null;\n }\n\n /**\n * Get all possible providers with confidence scores\n */\n detectAllProviders(response: any): Array<{ provider: AIProvider; confidence: number }> {\n return ProviderDetector.getAllProviders(response);\n }\n\n /**\n * Parse as generic HTML when no specific provider is detected\n */\n private parseGeneric(response: any, options?: ParseOptions): ParsedResponse | null {\n // Extract HTML or text from response\n let html = '';\n let text = '';\n\n const checkContent = (obj: any) => {\n if (typeof obj === 'string') {\n if (obj.trim().startsWith('<') && obj.includes('>')) {\n html = obj;\n } else {\n text = obj;\n }\n } else if (typeof obj === 'object' && obj !== null) {\n if (obj.html) {\n html = obj.html;\n } else if (obj.content) {\n if (obj.content.trim().startsWith('<')) {\n html = obj.content;\n } else {\n text = obj.content;\n }\n } else if (obj.text) {\n text = obj.text;\n }\n }\n };\n\n // Check nested structure\n let dataToCheck = response;\n if (response.result) {\n dataToCheck = response.result;\n }\n\n checkContent(dataToCheck);\n\n if (!html && !text) {\n return null;\n }\n\n // Basic sanitization\n if (html) {\n html = html.replace(/<script\\b[^>]*>[\\s\\S]*?<\\/script>/gim, '');\n html = html.replace(/<noscript[\\s\\S]*?<\\/noscript>/gi, '');\n }\n\n return {\n provider: 'CHATGPT' as AIProvider, // Default to ChatGPT for unknown\n html,\n text,\n metadata: {\n isGeneric: true,\n },\n };\n }\n\n /**\n * Get list of supported providers\n */\n getSupportedProviders(): AIProvider[] {\n return Array.from(this.providers.keys());\n }\n\n /**\n * Register a custom provider\n */\n registerProvider(provider: AIProvider, instance: any): void {\n this.providers.set(provider, instance);\n }\n}\n\n// Export a singleton instance\nexport const parser = new AIResponseParser();\n\n// Convenience functions\nexport const parseAiResponse = (response: any, options?: ParseOptions) =>\n parser.parse(response, options);\n\nexport const detectProvider = (response: any) =>\n parser.detectProvider(response);"],"names":["ProviderDetector","detect","response","scores","CHATGPT","GEMINI","PERPLEXITY","COPILOT","AIOVERVIEW","AIMODE","provider","patterns","Object","entries","this","PROVIDER_PATTERNS","pattern","error","maxScore","detectedProvider","score","confidence","values","reduce","a","b","Math","max","getAllProviders","providers","matches","push","length","sort","validate","detected","html","_a","result","includes","_b","aioverview","text","_c","_d","BaseProvider","injectStyles","options","styledHtml","baseUrl","replace","styles","customCSS","defaultStyles","sanitizeHtml","sanitized","isFullDocument","test","wrapFragment","ChatGPTProvider","constructor","name","extractContent","dataToCheck","trim","startsWith","content","parse","Error","finalHtml","theme","metadata","GeminiProvider","sources","PerplexityProvider","CopilotProvider","AIOverviewProvider","wizDataMatch","match","extractedContent","JSON","e","console","googleStyles","hideUI","hasWizData","AIModeProvider","AIResponseParser","Map","set","detection","parseGeneric","get","parsed","detectionConfidence","parseWithProvider","providerInstance","detectProvider","detectAllProviders","obj","isGeneric","getSupportedProviders","Array","from","keys","registerProvider","instance","parser","parseAiResponse"],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";class t{static detect(t){const e={CHATGPT:0,GEMINI:0,PERPLEXITY:0,COPILOT:0,AIOVERVIEW:0,AIMODE:0};for(const[n,r]of Object.entries(this.PROVIDER_PATTERNS))for(const o of r)try{o(t)&&e[n]++}catch(t){}let n=0,r=null;for(const[t,o]of Object.entries(e))o>n&&(n=o,r=t);return 0===n?null:{provider:r,confidence:n/Object.values(e).reduce((t,e)=>Math.max(t,e),1)}}static getAllProviders(t){const e=[];for(const[n,r]of Object.entries(this.PROVIDER_PATTERNS)){let o=0;for(const e of r)try{e(t)&&o++}catch(t){}o>0&&e.push({provider:n,confidence:o/r.length})}return e.sort((t,e)=>e.confidence-t.confidence)}static validate(t,e){const n=this.detect(t);return(null==n?void 0:n.provider)===e&&n.confidence>.5}}t.PROVIDER_PATTERNS={CHATGPT:[t=>{var e;const n=(null===(e=null==t?void 0:t.result)||void 0===e?void 0:e.html)||(null==t?void 0:t.html)||"";return n.includes("bg-token-bg-primary")||n.includes("text-token-text-secondary")},t=>{var e;const n=(null===(e=null==t?void 0:t.result)||void 0===e?void 0:e.html)||(null==t?void 0:t.html)||"";return n.includes("chatgpt.com")||n.includes("openai.com")}],GEMINI:[t=>{var e;const n=(null===(e=null==t?void 0:t.result)||void 0===e?void 0:e.html)||(null==t?void 0:t.html)||"";return n.includes("bard-sidenav")||n.includes("mat-sidenav")},t=>{var e;const n=(null===(e=null==t?void 0:t.result)||void 0===e?void 0:e.html)||(null==t?void 0:t.html)||"";return n.includes("gemini.google.com")||n.includes("gem-sys-color")}],PERPLEXITY:[t=>{var e;const n=(null===(e=null==t?void 0:t.result)||void 0===e?void 0:e.html)||(null==t?void 0:t.html)||"";return n.includes("perplexity.ai")||n.includes("prose")}],COPILOT:[t=>{var e;const n=(null===(e=null==t?void 0:t.result)||void 0===e?void 0:e.html)||(null==t?void 0:t.html)||"";return n.includes("copilot.microsoft.com")||n.includes('data-testid="sidebar-container"')}],AIOVERVIEW:[t=>{var e,n,r,o;if(null===(n=null===(e=null==t?void 0:t.result)||void 0===e?void 0:e.aioverview)||void 0===n?void 0:n.text)return!0;if(null===(r=null==t?void 0:t.aioverview)||void 0===r?void 0:r.text)return!0;const i=(null===(o=null==t?void 0:t.result)||void 0===o?void 0:o.html)||(null==t?void 0:t.html)||"";return i.includes("WIZ_global_data")||i.includes("DnVkpd")}],AIMODE:[t=>{var e;const n=(null===(e=null==t?void 0:t.result)||void 0===e?void 0:e.html)||(null==t?void 0:t.html)||"";return n.includes("DZ13He")||n.includes("wYq63b")||n.includes("AI Mode")}]};class e{injectStyles(t,e){let n=t;(null==e?void 0:e.baseUrl)&&!t.includes("<base ")&&(n=n.includes("<head>")?n.replace("<head>",`<head><base href="${e.baseUrl}">`):n.replace(/(<html[^>]*>)/i,`$1<head><base href="${e.baseUrl}"></head>`));const r=(null==e?void 0:e.customCSS)?this.defaultStyles+"\n"+e.customCSS:this.defaultStyles;return n=n.includes("<head>")?n.replace("<head>",`<head><style>${r}</style>`):n.replace(/(<html[^>]*>)/i,`$1<head><style>${r}</style></head>`),n}sanitizeHtml(t){let e=t.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gim,"");return e=e.replace(/<noscript[\s\S]*?<\/noscript>/gi,""),e}isFullDocument(t){return/^\s*(<html|<!DOCTYPE)/i.test(t)}wrapFragment(t){return`<!DOCTYPE html>\n<html>\n<head>\n <meta charset="utf-8">\n <meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'none'; style-src 'unsafe-inline';">\n <style>\n body {\n margin: 0;\n padding: 16px;\n font-family: system-ui, -apple-system, sans-serif;\n white-space: pre-wrap;\n word-wrap: break-word;\n }\n img { max-width: 100%; height: auto; }\n body {\n pointer-events: none;\n user-select: none;\n }\n </style>\n</head>\n<body>\n ${t}\n</body>\n</html>`}}class n extends e{constructor(){super(...arguments),this.name="CHATGPT",this.baseUrl="https://chatgpt.com",this.defaultStyles='\n /* Force Dark Background on main containers and wrappers */\n html, body, main, article, footer, form,\n [class*="bg-"], [class*="footer"], [class*="bottom"],\n div[class*="border-t"],\n #thread-bottom-container, #thread-bottom,\n #thread, .composer-parent, [class*="group\\/thread"] {\n background-color: #131314 !important;\n color: #e3e3e3 !important;\n border-color: #2a2b36 !important;\n }\n\n /* Force background on specific white artifacts in the footer */\n #thread-bottom-container .bg-clip-padding,\n #thread-bottom-container .content-fade,\n #thread-bottom-container .absolute {\n background-color: transparent !important;\n }\n\n /* Specific targeting for the composer/input box (was white) */\n form .bg-token-bg-primary, form .shadow-short {\n background-color: #2a2b36 !important;\n border-color: #3e3f4b !important;\n box-shadow: none !important;\n }\n\n /* Disclaimer Footer - Force Dark Background */\n div[class*="text-token-text-secondary"] {\n color: #9ca3af !important;\n background-color: #131314 !important;\n }\n\n /* Force Text Color to Light */\n p, h1, h2, h3, h4, h5, h6, li, span, div, td, th, textarea, button {\n color: #e3e3e3 !important;\n }\n\n /* Links - Light Blue */\n a, a span {\n color: #8ab4f8 !important;\n }\n\n /* Code Blocks */\n pre, code, pre div, code span {\n background-color: #2a2b36 !important;\n color: #e3e3e3 !important;\n text-shadow: none !important;\n }\n\n /* Inputs/Textareas */\n input, textarea {\n background-color: transparent !important;\n color: #e3e3e3 !important;\n border-color: #3e3f4b !important;\n }\n\n /* Placeholder text */\n textarea::placeholder {\n color: #9ca3af !important;\n }\n\n /* Hide Sidebar */\n nav, [class*="sidebar"] {\n display: none !important;\n }\n\n /* Media visibility */\n img, video {\n opacity: 1 !important;\n }\n '}extractContent(t){let e="",n="",r=t;return t.result&&(r=t.result),"string"==typeof r?r.trim().startsWith("<")&&r.includes(">")?e=r:n=r:"object"==typeof r&&null!==r&&(r.html?e=r.html:r.content?r.content.trim().startsWith("<")?e=r.content:n=r.content:r.text&&(n=r.text)),{html:e,text:n}}parse(t,e){const{html:n,text:r}=this.extractContent(t);if(!n&&!r)throw new Error("No content found in ChatGPT response");let o=n||"";return!o&&r&&(o=`<div>${r.replace(/\n/g,"<br>")}</div>`),o=this.sanitizeHtml(o),o=this.injectStyles(o,{theme:(null==e?void 0:e.theme)||"dark",baseUrl:(null==e?void 0:e.baseUrl)||this.baseUrl}),{provider:this.name,html:o,text:r,metadata:{isFullDocument:this.isFullDocument(o)}}}}class r extends e{constructor(){super(...arguments),this.name="GEMINI",this.baseUrl="https://gemini.google.com",this.defaultStyles='\n /* Gemini Dark Mode Variable Overrides */\n :root {\n --gem-sys-color--surface: #131314 !important;\n --gem-sys-color--surface-container: #1e1f20 !important;\n --gem-sys-color--on-surface: #e3e3e3 !important;\n --bard-color-synthetic--chat-window-surface: #131314 !important;\n --bard-color-surface-dim-tmp: #131314 !important;\n }\n\n /* UI hiding - Gemini */\n bard-sidenav, mat-sidenav, .mat-drawer-backdrop, .side-nav-menu-button,\n\n /* Gemini "About Gemini" footer/navigation block */\n .gb_5a, .gb_5c, .gb_5d, .gb_5e,\n .gb_Uc, .gb_Vc, .gb_Wc,\n a[href*="about"],\n a[href*="subscriptions"],\n a[href*="business"],\n div[class*="gb_5"],\n .gb_Pd, .gb_Qd, .gb_Rd,\n .gb_Sd, .gb_Td, .gb_Ud, .gb_Vd,\n [aria-label*="About"],\n [aria-label*="Gemini App"],\n [aria-label*="Subscriptions"],\n [aria-label*="For Business"],\n *:contains("About Gemini"),\n *:contains("Gemini App"),\n *:contains("Subscriptions"),\n *:contains("For Business") {\n display: none !important;\n }\n\n /* General Layout */\n main { width: 100% !important; max-width: 100% !important; margin: 0 !important; }\n\n /* Force Dark Mode on Body and Gemini Containers */\n body, .content-container, chat-app, .main-content, .chat-container {\n background-color: #131314 !important;\n color: #e3e3e3 !important;\n }\n '}extractContent(t){let e="",n="",r=[],o=t;return t.result&&(o=t.result),"string"==typeof o?o.trim().startsWith("<")&&o.includes(">")?e=o:n=o:"object"==typeof o&&null!==o&&(o.html?e=o.html:o.content?o.content.trim().startsWith("<")?e=o.content:n=o.content:o.text&&(n=o.text),o.aioverview&&(o.aioverview.text&&(n=o.aioverview.text),o.aioverview.sources&&(r=o.aioverview.sources))),{html:e,text:n,sources:r}}parse(t,e){const{html:n,text:r,sources:o}=this.extractContent(t);if(!n&&!r)throw new Error("No content found in Gemini response");let i=n||"";return!i&&r&&(i=`<div>${r.replace(/\n/g,"<br>")}</div>`),i=this.sanitizeHtml(i),i=this.injectStyles(i,{theme:(null==e?void 0:e.theme)||"dark",baseUrl:(null==e?void 0:e.baseUrl)||this.baseUrl}),{provider:this.name,html:i,text:r,sources:o,metadata:{isFullDocument:this.isFullDocument(i)}}}}class o extends e{constructor(){super(...arguments),this.name="PERPLEXITY",this.baseUrl="https://www.perplexity.ai",this.defaultStyles="\n html {\n filter: invert(1) hue-rotate(180deg);\n background-color: white !important;\n }\n img, video, iframe, svg {\n filter: invert(1) hue-rotate(180deg);\n }\n "}extractContent(t){let e="",n="",r=t;return t.result&&(r=t.result),"string"==typeof r?r.trim().startsWith("<")&&r.includes(">")?e=r:n=r:"object"==typeof r&&null!==r&&(r.html?e=r.html:r.content?r.content.trim().startsWith("<")?e=r.content:n=r.content:r.text&&(n=r.text)),{html:e,text:n}}parse(t,e){const{html:n,text:r}=this.extractContent(t);if(!n&&!r)throw new Error("No content found in Perplexity response");let o=n||"";return!o&&r&&(o=`<div>${r.replace(/\n/g,"<br>")}</div>`),o=this.injectStyles(o,{theme:(null==e?void 0:e.theme)||"dark",baseUrl:(null==e?void 0:e.baseUrl)||this.baseUrl,customCSS:"light"===(null==e?void 0:e.theme)?"":this.defaultStyles}),{provider:this.name,html:o,text:r,metadata:{isFullDocument:this.isFullDocument(o)}}}}class i extends e{constructor(){super(...arguments),this.name="COPILOT",this.baseUrl="https://copilot.microsoft.com",this.defaultStyles='\n /* Copilot Sidebar & Header */\n div:has(> [data-testid="sidebar-container"]),\n [data-testid="sidebar-container"],\n [data-testid="sticky-header"],\n .side-nav-menu-button {\n display: none !important;\n }\n\n /* General Layout Fixes */\n main {\n width: 100% !important;\n max-width: 100% !important;\n margin: 0 !important;\n }\n '}extractContent(t){let e="",n="",r=t;return t.result&&(r=t.result),"string"==typeof r?r.trim().startsWith("<")&&r.includes(">")?e=r:n=r:"object"==typeof r&&null!==r&&(r.html?e=r.html:r.content?r.content.trim().startsWith("<")?e=r.content:n=r.content:r.text&&(n=r.text)),{html:e,text:n}}parse(t,e){const{html:n,text:r}=this.extractContent(t);if(!n&&!r)throw new Error("No content found in Copilot response");let o=n||"";return!o&&r&&(o=`<div>${r.replace(/\n/g,"<br>")}</div>`),o=o.replace(/<noscript[\s\S]*?<\/noscript>/gi,""),o=this.injectStyles(o,{theme:(null==e?void 0:e.theme)||"dark",baseUrl:(null==e?void 0:e.baseUrl)||this.baseUrl}),{provider:this.name,html:o,text:r,metadata:{isFullDocument:this.isFullDocument(o)}}}}class s extends e{constructor(){super(...arguments),this.name="AIOVERVIEW",this.baseUrl="https://www.google.com",this.defaultStyles='\n /* UI hiding - Google Search (AI Overview) */\n header, #header, #searchform, .sfbg, #appbar,\n div[role="navigation"], #leftnav, #sidetogether,\n [role="banner"], .Fgvgjc, #hdtb, .hdtb-msb,\n footer, #footer, .fbar,\n .pdp-nav, [aria-label="Main menu"], .gb_Td, .gb_L,\n\n /* Specific AI Mode Selectors */\n .DZ13He,\n .wYq63b,\n .eT9Cje,\n .bNg8Rb,\n .S6VXfe,\n .Lu57id {\n display: none !important;\n }\n\n /* General Layout */\n main { width: 100% !important; max-width: 100% !important; margin: 0 !important; }\n '}extractContent(t){let e="",n="",r=[],o=t;if(t.result&&(o=t.result),o.aioverview&&(o.aioverview.text&&(n=o.aioverview.text),o.aioverview.sources&&(r=o.aioverview.sources)),"string"==typeof o?o.trim().startsWith("<")&&o.includes(">")?e=o:n=n||o:"object"==typeof o&&null!==o&&(o.html&&!n?e=o.html:o.content&&!n?o.content.trim().startsWith("<")?e=o.content:n=o.content:o.text&&!n&&(n=o.text)),e){const t=e.match(/"DnVkpd"\s*:\s*"((?:[^"\\]|\\.)*)"/);if(t&&t[1])try{let e=JSON.parse(`"${t[1]}"`);e=e.replace(/∰/g,'<hr class="gemini-separator">'),e=e.replace(/∞(https:\/\/[^ ]+\.(?:jpg|png|webp|gif|jpeg)(?:\?[^ ]*)?)/gi,'<br><img src="$1" class="gemini-image" alt="Generated Image"><br>'),e=e.replace(/∞/g,"<br>"),e=e.replace(/\n/g,"<br>"),n=e}catch(t){console.error("Failed to parse AI Overview WIZ data",t)}}return{html:e,text:n,sources:r}}parse(t,e){const{html:n,text:r,sources:o}=this.extractContent(t);if(!n&&!r)throw new Error("No content found in AI Overview response");let i="";if(r&&!n){const t="\n body {\n font-family: 'Google Sans', Roboto, sans-serif;\n line-height: 1.5;\n padding: 20px;\n color: #e3e3e3;\n background-color: #131314;\n }\n .gemini-separator {\n border: 0;\n border-top: 1px solid #444;\n margin: 24px 0;\n }\n .gemini-image {\n max-width: 100%;\n border-radius: 8px;\n margin: 12px 0;\n border: 1px solid #333;\n }\n a { color: #8ab4f8; }\n table { border-collapse: collapse; width: 100%; margin: 16px 0; }\n th, td { border: 1px solid #444; padding: 8px; text-align: left; }\n th { background-color: #1f1f1f; }\n ";i=`<!DOCTYPE html>\n <html>\n <head>\n <base href="${(null==e?void 0:e.baseUrl)||this.baseUrl}">\n <style>${t}</style>\n </head>\n <body>\n ${r}\n </body>\n </html>`}else i=n||"",i=this.sanitizeHtml(i),i=this.injectStyles(i,{theme:(null==e?void 0:e.theme)||"dark",baseUrl:(null==e?void 0:e.baseUrl)||this.baseUrl,hideUI:!0});return{provider:this.name,html:i,text:r,sources:o,metadata:{isFullDocument:this.isFullDocument(i),hasWizData:!!r&&!n}}}}class a extends e{constructor(){super(...arguments),this.name="AIMODE",this.baseUrl="https://www.google.com",this.defaultStyles='\n /* UI hiding - Google Search (AI Mode) */\n header, #header, #searchform, .sfbg, #appbar,\n div[role="navigation"], #leftnav, #sidetogether,\n [role="banner"], .Fgvgjc, #hdtb, .hdtb-msb,\n footer, #footer, .fbar,\n .pdp-nav, [aria-label="Main menu"], .gb_Td, .gb_L,\n\n /* Specific AI Mode Selectors found in analysis */\n .DZ13He, /* Main sticky top bar */\n .wYq63b, /* Accessibility links bar */\n .eT9Cje, /* History/New Search buttons */\n .bNg8Rb, /* Hidden H1 headers */\n .S6VXfe, /* Accessibility container */\n .Lu57id /* Potential other top bar */ {\n display: none !important;\n }\n\n /* General Layout */\n main { width: 100% !important; max-width: 100% !important; margin: 0 !important; }\n '}extractContent(t){let e="",n="",r=t;return t.result&&(r=t.result),"string"==typeof r?r.trim().startsWith("<")&&r.includes(">")?e=r:n=r:"object"==typeof r&&null!==r&&(r.html?e=r.html:r.content?r.content.trim().startsWith("<")?e=r.content:n=r.content:r.text&&(n=r.text)),{html:e,text:n}}parse(t,e){const{html:n,text:r}=this.extractContent(t);if(!n&&!r)throw new Error("No content found in AI Mode response");let o=n||"";return!o&&r&&(o=`<div>${r.replace(/\n/g,"<br>")}</div>`),o=this.sanitizeHtml(o),o=this.injectStyles(o,{theme:(null==e?void 0:e.theme)||"dark",baseUrl:(null==e?void 0:e.baseUrl)||this.baseUrl,hideUI:!0}),{provider:this.name,html:o,text:r,metadata:{isFullDocument:this.isFullDocument(o)}}}}class l{constructor(){this.providers=new Map,this.providers.set("CHATGPT",new n),this.providers.set("GEMINI",new r),this.providers.set("PERPLEXITY",new o),this.providers.set("COPILOT",new i),this.providers.set("AIOVERVIEW",new s),this.providers.set("AIMODE",new a)}parse(e,n){const r=t.detect(e);if(!r)return this.parseGeneric(e,n);const o=this.providers.get(r.provider);if(!o)return null;try{const t=o.parse(e,n);return{...t,metadata:{...t.metadata,detectionConfidence:r.confidence}}}catch(t){return console.error(`Failed to parse response with ${r.provider}:`,t),null}}parseWithProvider(t,e,n){const r=this.providers.get(e);if(!r)throw new Error(`Unknown provider: ${e}`);try{return r.parse(t,n)}catch(t){return console.error(`Failed to parse response with ${e}:`,t),null}}detectProvider(e){const n=t.detect(e);return(null==n?void 0:n.provider)||null}detectAllProviders(e){return t.getAllProviders(e)}parseGeneric(t,e){let n="",r="";let o=t;var i;return t.result&&(o=t.result),"string"==typeof(i=o)?i.trim().startsWith("<")&&i.includes(">")?n=i:r=i:"object"==typeof i&&null!==i&&(i.html?n=i.html:i.content?i.content.trim().startsWith("<")?n=i.content:r=i.content:i.text&&(r=i.text)),n||r?(n&&(n=n.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gim,""),n=n.replace(/<noscript[\s\S]*?<\/noscript>/gi,"")),{provider:"CHATGPT",html:n,text:r,metadata:{isGeneric:!0}}):null}getSupportedProviders(){return Array.from(this.providers.keys())}registerProvider(t,e){this.providers.set(t,e)}}const c=new l;exports.AIModeProvider=a,exports.AIOverviewProvider=s,exports.AIResponseParser=l,exports.BaseProvider=e,exports.ChatGPTProvider=n,exports.CopilotProvider=i,exports.GeminiProvider=r,exports.PerplexityProvider=o,exports.ProviderDetector=t,exports.detectProvider=t=>c.detectProvider(t),exports.parseAiResponse=(t,e)=>c.parse(t,e),exports.parser=c;
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/core/detector.ts","../src/providers/base-provider.ts","../src/providers/chatgpt.ts","../src/providers/gemini.ts","../src/providers/perplexity.ts","../src/providers/copilot.ts","../src/providers/ai-overview.ts","../src/providers/ai-mode.ts","../src/core/parser.ts"],"sourcesContent":["import { AIProvider, DetectedProvider } from './types';\n\nexport class ProviderDetector {\n private static readonly PROVIDER_PATTERNS = {\n CHATGPT: [\n // Check for token-based CSS classes\n (response: any) => {\n const html = response?.result?.html || response?.html || '';\n return html.includes('bg-token-bg-primary') || html.includes('text-token-text-secondary');\n },\n // Check for OpenAI-specific patterns\n (response: any) => {\n const html = response?.result?.html || response?.html || '';\n return html.includes('chatgpt.com') || html.includes('openai.com');\n },\n ],\n GEMINI: [\n // Check for Material Design components\n (response: any) => {\n const html = response?.result?.html || response?.html || '';\n return html.includes('bard-sidenav') || html.includes('mat-sidenav');\n },\n // Check for Gemini-specific classes\n (response: any) => {\n const html = response?.result?.html || response?.html || '';\n return html.includes('gemini.google.com') || html.includes('gem-sys-color');\n },\n ],\n PERPLEXITY: [\n // Check for Perplexity-specific structure\n (response: any) => {\n const html = response?.result?.html || response?.html || '';\n return html.includes('perplexity.ai') || html.includes('prose');\n },\n ],\n COPILOT: [\n // Check for Copilot-specific elements\n (response: any) => {\n const html = response?.result?.html || response?.html || '';\n return html.includes('copilot.microsoft.com') || html.includes('data-testid=\"sidebar-container\"');\n },\n ],\n AIOVERVIEW: [\n // Check for AI Overview specific structure\n (response: any) => {\n // Check for aioverview nested structure\n if (response?.result?.aioverview?.text) return true;\n if (response?.aioverview?.text) return true;\n\n // Check for WIZ_global_data (AI Overview specific)\n const html = response?.result?.html || response?.html || '';\n return html.includes('WIZ_global_data') || html.includes('DnVkpd');\n },\n ],\n AIMODE: [\n // Check for AI Mode specific elements\n (response: any) => {\n const html = response?.result?.html || response?.html || '';\n return html.includes('DZ13He') || html.includes('wYq63b') || html.includes('AI Mode');\n },\n ],\n };\n\n /**\n * Detect the AI provider from the response\n */\n static detect(response: any): DetectedProvider | null {\n const scores: Record<AIProvider, number> = {\n CHATGPT: 0,\n GEMINI: 0,\n PERPLEXITY: 0,\n COPILOT: 0,\n AIOVERVIEW: 0,\n AIMODE: 0,\n };\n\n // Score each provider based on pattern matches\n for (const [provider, patterns] of Object.entries(this.PROVIDER_PATTERNS)) {\n for (const pattern of patterns) {\n try {\n if (pattern(response)) {\n scores[provider as AIProvider]++;\n }\n } catch (error) {\n // Ignore pattern errors\n }\n }\n }\n\n // Find the provider with the highest score\n let maxScore = 0;\n let detectedProvider: AIProvider | null = null;\n\n for (const [provider, score] of Object.entries(scores)) {\n if (score > maxScore) {\n maxScore = score;\n detectedProvider = provider as AIProvider;\n }\n }\n\n // Return null if no patterns matched\n if (maxScore === 0) return null;\n\n return {\n provider: detectedProvider!,\n confidence: maxScore / Object.values(scores).reduce((a, b) => Math.max(a, b), 1),\n };\n }\n\n /**\n * Get all possible providers with their confidence scores\n */\n static getAllProviders(response: any): DetectedProvider[] {\n const providers: DetectedProvider[] = [];\n\n for (const [provider, patterns] of Object.entries(this.PROVIDER_PATTERNS)) {\n let matches = 0;\n for (const pattern of patterns) {\n try {\n if (pattern(response)) {\n matches++;\n }\n } catch (error) {\n // Ignore pattern errors\n }\n }\n\n if (matches > 0) {\n providers.push({\n provider: provider as AIProvider,\n confidence: matches / patterns.length,\n });\n }\n }\n\n // Sort by confidence (highest first)\n return providers.sort((a, b) => b.confidence - a.confidence);\n }\n\n /**\n * Validate if a detected provider is likely correct\n */\n static validate(response: any, provider: AIProvider): boolean {\n const detected = this.detect(response);\n return detected?.provider === provider && detected.confidence > 0.5;\n }\n}","import { AIProvider, ParsedResponse, ParseOptions, StyleOptions, ContentExtraction } from '../core/types';\n\nexport abstract class BaseProvider {\n abstract readonly name: AIProvider;\n abstract readonly baseUrl: string;\n abstract readonly defaultStyles: string;\n\n /**\n * Parse an AI response and return structured content\n */\n abstract parse(response: any, options?: ParseOptions): ParsedResponse;\n\n /**\n * Extract content from the response object\n */\n abstract extractContent(response: any): ContentExtraction;\n\n /**\n * Inject provider-specific styles into HTML\n */\n injectStyles(html: string, options?: StyleOptions): string {\n let styledHtml = html;\n\n // Inject base URL if not already present\n if (options?.baseUrl && !html.includes('<base ')) {\n if (styledHtml.includes('<head>')) {\n styledHtml = styledHtml.replace(\n '<head>',\n `<head><base href=\"${options.baseUrl}\">`,\n );\n } else {\n styledHtml = styledHtml.replace(\n /(<html[^>]*>)/i,\n `$1<head><base href=\"${options.baseUrl}\"></head>`,\n );\n }\n }\n\n // Inject styles\n const styles = options?.customCSS\n ? this.defaultStyles + '\\n' + options.customCSS\n : this.defaultStyles;\n\n if (styledHtml.includes('<head>')) {\n styledHtml = styledHtml.replace('<head>', `<head><style>${styles}</style>`);\n } else {\n styledHtml = styledHtml.replace(\n /(<html[^>]*>)/i,\n `$1<head><style>${styles}</style></head>`,\n );\n }\n\n return styledHtml;\n }\n\n /**\n * Sanitize HTML content\n */\n sanitizeHtml(html: string): string {\n // Remove scripts\n let sanitized = html.replace(/<script\\b[^>]*>[\\s\\S]*?<\\/script>/gim, '');\n\n // Remove noscript tags\n sanitized = sanitized.replace(/<noscript[\\s\\S]*?<\\/noscript>/gi, '');\n\n return sanitized;\n }\n\n /**\n * Check if content is a full HTML document\n */\n isFullDocument(html: string): boolean {\n return /^\\s*(<html|<!DOCTYPE)/i.test(html);\n }\n\n /**\n * Wrap HTML fragment in a document\n */\n wrapFragment(html: string): string {\n return `<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <meta http-equiv=\"Content-Security-Policy\" content=\"default-src 'none'; script-src 'none'; style-src 'unsafe-inline';\">\n <style>\n body {\n margin: 0;\n padding: 16px;\n font-family: system-ui, -apple-system, sans-serif;\n white-space: pre-wrap;\n word-wrap: break-word;\n }\n img { max-width: 100%; height: auto; }\n body {\n pointer-events: none;\n user-select: none;\n }\n </style>\n</head>\n<body>\n ${html}\n</body>\n</html>`;\n }\n}","import { BaseProvider } from './base-provider';\nimport { AIProvider, ParsedResponse, ParseOptions, ContentExtraction } from '../core/types';\n\nexport class ChatGPTProvider extends BaseProvider {\n readonly name: AIProvider = 'CHATGPT';\n readonly baseUrl = 'https://chatgpt.com';\n\n readonly defaultStyles = `\n /* Force Dark Background on main containers and wrappers */\n html, body, main, article, footer, form,\n [class*=\"bg-\"], [class*=\"footer\"], [class*=\"bottom\"],\n div[class*=\"border-t\"],\n #thread-bottom-container, #thread-bottom,\n #thread, .composer-parent, [class*=\"group\\\\/thread\"] {\n background-color: #131314 !important;\n color: #e3e3e3 !important;\n border-color: #2a2b36 !important;\n }\n\n /* Force background on specific white artifacts in the footer */\n #thread-bottom-container .bg-clip-padding,\n #thread-bottom-container .content-fade,\n #thread-bottom-container .absolute {\n background-color: transparent !important;\n }\n\n /* Specific targeting for the composer/input box (was white) */\n form .bg-token-bg-primary, form .shadow-short {\n background-color: #2a2b36 !important;\n border-color: #3e3f4b !important;\n box-shadow: none !important;\n }\n\n /* Disclaimer Footer - Force Dark Background */\n div[class*=\"text-token-text-secondary\"] {\n color: #9ca3af !important;\n background-color: #131314 !important;\n }\n\n /* Force Text Color to Light */\n p, h1, h2, h3, h4, h5, h6, li, span, div, td, th, textarea, button {\n color: #e3e3e3 !important;\n }\n\n /* Links - Light Blue */\n a, a span {\n color: #8ab4f8 !important;\n }\n\n /* Code Blocks */\n pre, code, pre div, code span {\n background-color: #2a2b36 !important;\n color: #e3e3e3 !important;\n text-shadow: none !important;\n }\n\n /* Inputs/Textareas */\n input, textarea {\n background-color: transparent !important;\n color: #e3e3e3 !important;\n border-color: #3e3f4b !important;\n }\n\n /* Placeholder text */\n textarea::placeholder {\n color: #9ca3af !important;\n }\n\n /* Hide Sidebar */\n nav, [class*=\"sidebar\"] {\n display: none !important;\n }\n\n /* Media visibility */\n img, video {\n opacity: 1 !important;\n }\n `;\n\n extractContent(response: any): ContentExtraction {\n let html = '';\n let text = '';\n\n // Handle nested structure\n let dataToCheck = response;\n if (response.result) {\n dataToCheck = response.result;\n }\n\n // Extract content\n if (typeof dataToCheck === 'string') {\n if (dataToCheck.trim().startsWith('<') && dataToCheck.includes('>')) {\n html = dataToCheck;\n } else {\n text = dataToCheck;\n }\n } else if (typeof dataToCheck === 'object' && dataToCheck !== null) {\n if (dataToCheck.html) {\n html = dataToCheck.html;\n } else if (dataToCheck.content) {\n if (dataToCheck.content.trim().startsWith('<')) {\n html = dataToCheck.content;\n } else {\n text = dataToCheck.content;\n }\n } else if (dataToCheck.text) {\n text = dataToCheck.text;\n }\n }\n\n return { html, text };\n }\n\n parse(response: any, options?: ParseOptions): ParsedResponse {\n const { html, text } = this.extractContent(response);\n\n if (!html && !text) {\n throw new Error('No content found in ChatGPT response');\n }\n\n let finalHtml = html || '';\n\n // If we only have text, create simple HTML\n if (!finalHtml && text) {\n finalHtml = `<div>${text.replace(/\\n/g, '<br>')}</div>`;\n }\n\n // Sanitize HTML\n finalHtml = this.sanitizeHtml(finalHtml);\n\n // Inject styles\n finalHtml = this.injectStyles(finalHtml, {\n theme: options?.theme || 'dark',\n baseUrl: options?.baseUrl || this.baseUrl,\n });\n\n return {\n provider: this.name,\n html: finalHtml,\n text,\n metadata: {\n isFullDocument: this.isFullDocument(finalHtml),\n },\n };\n }\n}","import { BaseProvider } from './base-provider';\nimport { AIProvider, ParsedResponse, ParseOptions, ContentExtraction } from '../core/types';\n\nexport class GeminiProvider extends BaseProvider {\n readonly name: AIProvider = 'GEMINI';\n readonly baseUrl = 'https://gemini.google.com';\n\n readonly defaultStyles = `\n /* Gemini Dark Mode Variable Overrides */\n :root {\n --gem-sys-color--surface: #131314 !important;\n --gem-sys-color--surface-container: #1e1f20 !important;\n --gem-sys-color--on-surface: #e3e3e3 !important;\n --bard-color-synthetic--chat-window-surface: #131314 !important;\n --bard-color-surface-dim-tmp: #131314 !important;\n }\n\n /* UI hiding - Gemini */\n bard-sidenav, mat-sidenav, .mat-drawer-backdrop, .side-nav-menu-button,\n\n /* Gemini \"About Gemini\" footer/navigation block */\n .gb_5a, .gb_5c, .gb_5d, .gb_5e,\n .gb_Uc, .gb_Vc, .gb_Wc,\n a[href*=\"about\"],\n a[href*=\"subscriptions\"],\n a[href*=\"business\"],\n div[class*=\"gb_5\"],\n .gb_Pd, .gb_Qd, .gb_Rd,\n .gb_Sd, .gb_Td, .gb_Ud, .gb_Vd,\n [aria-label*=\"About\"],\n [aria-label*=\"Gemini App\"],\n [aria-label*=\"Subscriptions\"],\n [aria-label*=\"For Business\"],\n *:contains(\"About Gemini\"),\n *:contains(\"Gemini App\"),\n *:contains(\"Subscriptions\"),\n *:contains(\"For Business\") {\n display: none !important;\n }\n\n /* General Layout */\n main { width: 100% !important; max-width: 100% !important; margin: 0 !important; }\n\n /* Force Dark Mode on Body and Gemini Containers */\n body, .content-container, chat-app, .main-content, .chat-container {\n background-color: #131314 !important;\n color: #e3e3e3 !important;\n }\n `;\n\n extractContent(response: any): ContentExtraction {\n let html = '';\n let text = '';\n let sources: any[] = [];\n\n // Handle nested structure\n let dataToCheck = response;\n if (response.result) {\n dataToCheck = response.result;\n }\n\n // Extract content\n if (typeof dataToCheck === 'string') {\n if (dataToCheck.trim().startsWith('<') && dataToCheck.includes('>')) {\n html = dataToCheck;\n } else {\n text = dataToCheck;\n }\n } else if (typeof dataToCheck === 'object' && dataToCheck !== null) {\n if (dataToCheck.html) {\n html = dataToCheck.html;\n } else if (dataToCheck.content) {\n if (dataToCheck.content.trim().startsWith('<')) {\n html = dataToCheck.content;\n } else {\n text = dataToCheck.content;\n }\n } else if (dataToCheck.text) {\n text = dataToCheck.text;\n }\n\n // Check for aioverview nested structure\n if (dataToCheck.aioverview) {\n if (dataToCheck.aioverview.text) text = dataToCheck.aioverview.text;\n if (dataToCheck.aioverview.sources) sources = dataToCheck.aioverview.sources;\n }\n }\n\n return { html, text, sources };\n }\n\n parse(response: any, options?: ParseOptions): ParsedResponse {\n const { html, text, sources } = this.extractContent(response);\n\n if (!html && !text) {\n throw new Error('No content found in Gemini response');\n }\n\n let finalHtml = html || '';\n\n // If we only have text, create simple HTML\n if (!finalHtml && text) {\n finalHtml = `<div>${text.replace(/\\n/g, '<br>')}</div>`;\n }\n\n // Sanitize HTML (remove scripts and noscript)\n finalHtml = this.sanitizeHtml(finalHtml);\n\n // For Gemini, we need to extract content from WIZ_global_data for AI Overview/Mode\n // But for regular Gemini, we just inject styles\n finalHtml = this.injectStyles(finalHtml, {\n theme: options?.theme || 'dark',\n baseUrl: options?.baseUrl || this.baseUrl,\n });\n\n return {\n provider: this.name,\n html: finalHtml,\n text,\n sources,\n metadata: {\n isFullDocument: this.isFullDocument(finalHtml),\n },\n };\n }\n}","import { BaseProvider } from './base-provider';\nimport { AIProvider, ParsedResponse, ParseOptions, ContentExtraction } from '../core/types';\n\nexport class PerplexityProvider extends BaseProvider {\n readonly name: AIProvider = 'PERPLEXITY';\n readonly baseUrl = 'https://www.perplexity.ai';\n\n readonly defaultStyles = `\n html {\n filter: invert(1) hue-rotate(180deg);\n background-color: white !important;\n }\n img, video, iframe, svg {\n filter: invert(1) hue-rotate(180deg);\n }\n `;\n\n extractContent(response: any): ContentExtraction {\n let html = '';\n let text = '';\n\n // Handle nested structure\n let dataToCheck = response;\n if (response.result) {\n dataToCheck = response.result;\n }\n\n // Extract content\n if (typeof dataToCheck === 'string') {\n if (dataToCheck.trim().startsWith('<') && dataToCheck.includes('>')) {\n html = dataToCheck;\n } else {\n text = dataToCheck;\n }\n } else if (typeof dataToCheck === 'object' && dataToCheck !== null) {\n if (dataToCheck.html) {\n html = dataToCheck.html;\n } else if (dataToCheck.content) {\n if (dataToCheck.content.trim().startsWith('<')) {\n html = dataToCheck.content;\n } else {\n text = dataToCheck.content;\n }\n } else if (dataToCheck.text) {\n text = dataToCheck.text;\n }\n }\n\n return { html, text };\n }\n\n parse(response: any, options?: ParseOptions): ParsedResponse {\n const { html, text } = this.extractContent(response);\n\n if (!html && !text) {\n throw new Error('No content found in Perplexity response');\n }\n\n let finalHtml = html || '';\n\n // If we only have text, create simple HTML\n if (!finalHtml && text) {\n finalHtml = `<div>${text.replace(/\\n/g, '<br>')}</div>`;\n }\n\n // For Perplexity, we apply color inversion for dark mode\n // Don't sanitize scripts as Perplexity might need them for functionality\n finalHtml = this.injectStyles(finalHtml, {\n theme: options?.theme || 'dark',\n baseUrl: options?.baseUrl || this.baseUrl,\n customCSS: options?.theme === 'light' ? '' : this.defaultStyles,\n });\n\n return {\n provider: this.name,\n html: finalHtml,\n text,\n metadata: {\n isFullDocument: this.isFullDocument(finalHtml),\n },\n };\n }\n}","import { BaseProvider } from './base-provider';\nimport { AIProvider, ParsedResponse, ParseOptions, ContentExtraction } from '../core/types';\n\nexport class CopilotProvider extends BaseProvider {\n readonly name: AIProvider = 'COPILOT';\n readonly baseUrl = 'https://copilot.microsoft.com';\n\n readonly defaultStyles = `\n /* Copilot Sidebar & Header */\n div:has(> [data-testid=\"sidebar-container\"]),\n [data-testid=\"sidebar-container\"],\n [data-testid=\"sticky-header\"],\n .side-nav-menu-button {\n display: none !important;\n }\n\n /* General Layout Fixes */\n main {\n width: 100% !important;\n max-width: 100% !important;\n margin: 0 !important;\n }\n `;\n\n extractContent(response: any): ContentExtraction {\n let html = '';\n let text = '';\n\n // Handle nested structure\n let dataToCheck = response;\n if (response.result) {\n dataToCheck = response.result;\n }\n\n // Extract content\n if (typeof dataToCheck === 'string') {\n if (dataToCheck.trim().startsWith('<') && dataToCheck.includes('>')) {\n html = dataToCheck;\n } else {\n text = dataToCheck;\n }\n } else if (typeof dataToCheck === 'object' && dataToCheck !== null) {\n if (dataToCheck.html) {\n html = dataToCheck.html;\n } else if (dataToCheck.content) {\n if (dataToCheck.content.trim().startsWith('<')) {\n html = dataToCheck.content;\n } else {\n text = dataToCheck.content;\n }\n } else if (dataToCheck.text) {\n text = dataToCheck.text;\n }\n }\n\n return { html, text };\n }\n\n parse(response: any, options?: ParseOptions): ParsedResponse {\n const { html, text } = this.extractContent(response);\n\n if (!html && !text) {\n throw new Error('No content found in Copilot response');\n }\n\n let finalHtml = html || '';\n\n // If we only have text, create simple HTML\n if (!finalHtml && text) {\n finalHtml = `<div>${text.replace(/\\n/g, '<br>')}</div>`;\n }\n\n // Remove noscript tags\n finalHtml = finalHtml.replace(/<noscript[\\s\\S]*?<\\/noscript>/gi, '');\n\n // Inject styles\n finalHtml = this.injectStyles(finalHtml, {\n theme: options?.theme || 'dark',\n baseUrl: options?.baseUrl || this.baseUrl,\n });\n\n return {\n provider: this.name,\n html: finalHtml,\n text,\n metadata: {\n isFullDocument: this.isFullDocument(finalHtml),\n },\n };\n }\n}","import { BaseProvider } from './base-provider';\nimport { AIProvider, ParsedResponse, ParseOptions, ContentExtraction } from '../core/types';\n\nexport class AIOverviewProvider extends BaseProvider {\n readonly name: AIProvider = 'AIOVERVIEW';\n readonly baseUrl = 'https://www.google.com';\n\n readonly defaultStyles = `\n /* UI hiding - Google Search (AI Overview) */\n header, #header, #searchform, .sfbg, #appbar,\n div[role=\"navigation\"], #leftnav, #sidetogether,\n [role=\"banner\"], .Fgvgjc, #hdtb, .hdtb-msb,\n footer, #footer, .fbar,\n .pdp-nav, [aria-label=\"Main menu\"], .gb_Td, .gb_L,\n\n /* Specific AI Mode Selectors */\n .DZ13He,\n .wYq63b,\n .eT9Cje,\n .bNg8Rb,\n .S6VXfe,\n .Lu57id {\n display: none !important;\n }\n\n /* General Layout */\n main { width: 100% !important; max-width: 100% !important; margin: 0 !important; }\n `;\n\n extractContent(response: any): ContentExtraction {\n let html = '';\n let text = '';\n let sources: any[] = [];\n\n // Handle nested structure\n let dataToCheck = response;\n if (response.result) {\n dataToCheck = response.result;\n }\n\n // For AI Overview, check for aioverview structure first\n if (dataToCheck.aioverview) {\n if (dataToCheck.aioverview.text) {\n text = dataToCheck.aioverview.text;\n }\n if (dataToCheck.aioverview.sources) {\n sources = dataToCheck.aioverview.sources;\n }\n }\n\n // Check for standard content fields\n if (typeof dataToCheck === 'string') {\n if (dataToCheck.trim().startsWith('<') && dataToCheck.includes('>')) {\n html = dataToCheck;\n } else {\n text = text || dataToCheck;\n }\n } else if (typeof dataToCheck === 'object' && dataToCheck !== null) {\n if (dataToCheck.html && !text) {\n html = dataToCheck.html;\n } else if (dataToCheck.content && !text) {\n if (dataToCheck.content.trim().startsWith('<')) {\n html = dataToCheck.content;\n } else {\n text = dataToCheck.content;\n }\n } else if (dataToCheck.text && !text) {\n text = dataToCheck.text;\n }\n }\n\n // If we have HTML, try to extract WIZ_global_data\n if (html) {\n const wizDataMatch = html.match(/\"DnVkpd\"\\s*:\\s*\"((?:[^\"\\\\]|\\\\.)*)\"/);\n if (wizDataMatch && wizDataMatch[1]) {\n try {\n // Decode the JSON string to get the actual content\n let extractedContent = JSON.parse(`\"${wizDataMatch[1]}\"`);\n\n // Format specific delimiters used by AI Overview\n // ∰ seems to separate turns/sections\n extractedContent = extractedContent.replace(\n /∰/g,\n '<hr class=\"gemini-separator\">',\n );\n\n // ∞ seems to separate prompts/images/responses. Often precedes URLs.\n // We'll try to detect image URLs following this and turn them into tags.\n extractedContent = extractedContent.replace(\n /∞(https:\\/\\/[^ ]+\\.(?:jpg|png|webp|gif|jpeg)(?:\\?[^ ]*)?)/gi,\n '<br><img src=\"$1\" class=\"gemini-image\" alt=\"Generated Image\"><br>',\n );\n\n // Handle remaining ∞\n extractedContent = extractedContent.replace(/∞/g, '<br>');\n\n // Handle newlines\n extractedContent = extractedContent.replace(/\\n/g, '<br>');\n\n text = extractedContent;\n } catch (e) {\n console.error('Failed to parse AI Overview WIZ data', e);\n // Keep original HTML if parsing fails\n }\n }\n }\n\n return { html, text, sources };\n }\n\n parse(response: any, options?: ParseOptions): ParsedResponse {\n const { html, text, sources } = this.extractContent(response);\n\n if (!html && !text) {\n throw new Error('No content found in AI Overview response');\n }\n\n let finalHtml = '';\n\n // If we have extracted text from WIZ data, build HTML from it\n if (text && !html) {\n const googleStyles = `\n body {\n font-family: 'Google Sans', Roboto, sans-serif;\n line-height: 1.5;\n padding: 20px;\n color: #e3e3e3;\n background-color: #131314;\n }\n .gemini-separator {\n border: 0;\n border-top: 1px solid #444;\n margin: 24px 0;\n }\n .gemini-image {\n max-width: 100%;\n border-radius: 8px;\n margin: 12px 0;\n border: 1px solid #333;\n }\n a { color: #8ab4f8; }\n table { border-collapse: collapse; width: 100%; margin: 16px 0; }\n th, td { border: 1px solid #444; padding: 8px; text-align: left; }\n th { background-color: #1f1f1f; }\n `;\n\n finalHtml = `<!DOCTYPE html>\n <html>\n <head>\n <base href=\"${options?.baseUrl || this.baseUrl}\">\n <style>${googleStyles}</style>\n </head>\n <body>\n ${text}\n </body>\n </html>`;\n } else {\n // Use the original HTML but clean it\n finalHtml = html || '';\n finalHtml = this.sanitizeHtml(finalHtml);\n\n // Inject base URL and styles\n finalHtml = this.injectStyles(finalHtml, {\n theme: options?.theme || 'dark',\n baseUrl: options?.baseUrl || this.baseUrl,\n hideUI: true,\n });\n }\n\n return {\n provider: this.name,\n html: finalHtml,\n text,\n sources,\n metadata: {\n isFullDocument: this.isFullDocument(finalHtml),\n hasWizData: !!text && !html,\n },\n };\n }\n}","import { BaseProvider } from './base-provider';\nimport { AIProvider, ParsedResponse, ParseOptions, ContentExtraction } from '../core/types';\n\nexport class AIModeProvider extends BaseProvider {\n readonly name: AIProvider = 'AIMODE';\n readonly baseUrl = 'https://www.google.com';\n\n readonly defaultStyles = `\n /* UI hiding - Google Search (AI Mode) */\n header, #header, #searchform, .sfbg, #appbar,\n div[role=\"navigation\"], #leftnav, #sidetogether,\n [role=\"banner\"], .Fgvgjc, #hdtb, .hdtb-msb,\n footer, #footer, .fbar,\n .pdp-nav, [aria-label=\"Main menu\"], .gb_Td, .gb_L,\n\n /* Specific AI Mode Selectors found in analysis */\n .DZ13He, /* Main sticky top bar */\n .wYq63b, /* Accessibility links bar */\n .eT9Cje, /* History/New Search buttons */\n .bNg8Rb, /* Hidden H1 headers */\n .S6VXfe, /* Accessibility container */\n .Lu57id /* Potential other top bar */ {\n display: none !important;\n }\n\n /* General Layout */\n main { width: 100% !important; max-width: 100% !important; margin: 0 !important; }\n `;\n\n extractContent(response: any): ContentExtraction {\n let html = '';\n let text = '';\n\n // Handle nested structure\n let dataToCheck = response;\n if (response.result) {\n dataToCheck = response.result;\n }\n\n // Extract content\n if (typeof dataToCheck === 'string') {\n if (dataToCheck.trim().startsWith('<') && dataToCheck.includes('>')) {\n html = dataToCheck;\n } else {\n text = dataToCheck;\n }\n } else if (typeof dataToCheck === 'object' && dataToCheck !== null) {\n if (dataToCheck.html) {\n html = dataToCheck.html;\n } else if (dataToCheck.content) {\n if (dataToCheck.content.trim().startsWith('<')) {\n html = dataToCheck.content;\n } else {\n text = dataToCheck.content;\n }\n } else if (dataToCheck.text) {\n text = dataToCheck.text;\n }\n }\n\n return { html, text };\n }\n\n parse(response: any, options?: ParseOptions): ParsedResponse {\n const { html, text } = this.extractContent(response);\n\n if (!html && !text) {\n throw new Error('No content found in AI Mode response');\n }\n\n let finalHtml = html || '';\n\n // If we only have text, create simple HTML\n if (!finalHtml && text) {\n finalHtml = `<div>${text.replace(/\\n/g, '<br>')}</div>`;\n }\n\n // Sanitize HTML\n finalHtml = this.sanitizeHtml(finalHtml);\n\n // Inject styles to hide UI elements\n finalHtml = this.injectStyles(finalHtml, {\n theme: options?.theme || 'dark',\n baseUrl: options?.baseUrl || this.baseUrl,\n hideUI: true,\n });\n\n return {\n provider: this.name,\n html: finalHtml,\n text,\n metadata: {\n isFullDocument: this.isFullDocument(finalHtml),\n },\n };\n }\n}","import { AIProvider, ParsedResponse, ParseOptions } from './types';\nimport { ProviderDetector } from './detector';\nimport { ChatGPTProvider } from '../providers/chatgpt';\nimport { GeminiProvider } from '../providers/gemini';\nimport { PerplexityProvider } from '../providers/perplexity';\nimport { CopilotProvider } from '../providers/copilot';\nimport { AIOverviewProvider } from '../providers/ai-overview';\nimport { AIModeProvider } from '../providers/ai-mode';\n\nexport class AIResponseParser {\n private providers: Map<AIProvider, any> = new Map();\n\n constructor() {\n this.providers.set('CHATGPT', new ChatGPTProvider());\n this.providers.set('GEMINI', new GeminiProvider());\n this.providers.set('PERPLEXITY', new PerplexityProvider());\n this.providers.set('COPILOT', new CopilotProvider());\n this.providers.set('AIOVERVIEW', new AIOverviewProvider());\n this.providers.set('AIMODE', new AIModeProvider());\n }\n\n /**\n * Parse an AI response with auto-detected provider\n */\n parse(response: any, options?: ParseOptions): ParsedResponse | null {\n const detection = ProviderDetector.detect(response);\n\n if (!detection) {\n // Try to parse as generic HTML if no provider detected\n return this.parseGeneric(response, options);\n }\n\n const provider = this.providers.get(detection.provider);\n if (!provider) {\n return null;\n }\n\n try {\n const parsed = provider.parse(response, options);\n return {\n ...parsed,\n metadata: {\n ...parsed.metadata,\n detectionConfidence: detection.confidence,\n },\n };\n } catch (error) {\n console.error(`Failed to parse response with ${detection.provider}:`, error);\n return null;\n }\n }\n\n /**\n * Parse with explicit provider specification\n */\n parseWithProvider(\n response: any,\n provider: AIProvider,\n options?: ParseOptions\n ): ParsedResponse | null {\n const providerInstance = this.providers.get(provider);\n if (!providerInstance) {\n throw new Error(`Unknown provider: ${provider}`);\n }\n\n try {\n return providerInstance.parse(response, options);\n } catch (error) {\n console.error(`Failed to parse response with ${provider}:`, error);\n return null;\n }\n }\n\n /**\n * Detect the provider from a response\n */\n detectProvider(response: any): AIProvider | null {\n const detection = ProviderDetector.detect(response);\n return detection?.provider || null;\n }\n\n /**\n * Get all possible providers with confidence scores\n */\n detectAllProviders(response: any): Array<{ provider: AIProvider; confidence: number }> {\n return ProviderDetector.getAllProviders(response);\n }\n\n /**\n * Parse as generic HTML when no specific provider is detected\n */\n private parseGeneric(response: any, options?: ParseOptions): ParsedResponse | null {\n // Extract HTML or text from response\n let html = '';\n let text = '';\n\n const checkContent = (obj: any) => {\n if (typeof obj === 'string') {\n if (obj.trim().startsWith('<') && obj.includes('>')) {\n html = obj;\n } else {\n text = obj;\n }\n } else if (typeof obj === 'object' && obj !== null) {\n if (obj.html) {\n html = obj.html;\n } else if (obj.content) {\n if (obj.content.trim().startsWith('<')) {\n html = obj.content;\n } else {\n text = obj.content;\n }\n } else if (obj.text) {\n text = obj.text;\n }\n }\n };\n\n // Check nested structure\n let dataToCheck = response;\n if (response.result) {\n dataToCheck = response.result;\n }\n\n checkContent(dataToCheck);\n\n if (!html && !text) {\n return null;\n }\n\n // Basic sanitization\n if (html) {\n html = html.replace(/<script\\b[^>]*>[\\s\\S]*?<\\/script>/gim, '');\n html = html.replace(/<noscript[\\s\\S]*?<\\/noscript>/gi, '');\n }\n\n return {\n provider: 'CHATGPT' as AIProvider, // Default to ChatGPT for unknown\n html,\n text,\n metadata: {\n isGeneric: true,\n },\n };\n }\n\n /**\n * Get list of supported providers\n */\n getSupportedProviders(): AIProvider[] {\n return Array.from(this.providers.keys());\n }\n\n /**\n * Register a custom provider\n */\n registerProvider(provider: AIProvider, instance: any): void {\n this.providers.set(provider, instance);\n }\n}\n\n// Export a singleton instance\nexport const parser = new AIResponseParser();\n\n// Convenience functions\nexport const parseAiResponse = (response: any, options?: ParseOptions) =>\n parser.parse(response, options);\n\nexport const detectProvider = (response: any) =>\n parser.detectProvider(response);"],"names":["ProviderDetector","detect","response","scores","CHATGPT","GEMINI","PERPLEXITY","COPILOT","AIOVERVIEW","AIMODE","provider","patterns","Object","entries","this","PROVIDER_PATTERNS","pattern","error","maxScore","detectedProvider","score","confidence","values","reduce","a","b","Math","max","getAllProviders","providers","matches","push","length","sort","validate","detected","html","_a","result","includes","_b","aioverview","text","_c","_d","BaseProvider","injectStyles","options","styledHtml","baseUrl","replace","styles","customCSS","defaultStyles","sanitizeHtml","sanitized","isFullDocument","test","wrapFragment","ChatGPTProvider","constructor","name","extractContent","dataToCheck","trim","startsWith","content","parse","Error","finalHtml","theme","metadata","GeminiProvider","sources","PerplexityProvider","CopilotProvider","AIOverviewProvider","wizDataMatch","match","extractedContent","JSON","e","console","googleStyles","hideUI","hasWizData","AIModeProvider","AIResponseParser","Map","set","detection","parseGeneric","get","parsed","detectionConfidence","parseWithProvider","providerInstance","detectProvider","detectAllProviders","obj","isGeneric","getSupportedProviders","Array","from","keys","registerProvider","instance","parser"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { BaseProvider } from './base-provider';
2
+ import { AIProvider, ParsedResponse, ParseOptions, ContentExtraction } from '../core/types';
3
+ export declare class AIModeProvider extends BaseProvider {
4
+ readonly name: AIProvider;
5
+ readonly baseUrl = "https://www.google.com";
6
+ readonly defaultStyles = "\n /* UI hiding - Google Search (AI Mode) */\n header, #header, #searchform, .sfbg, #appbar,\n div[role=\"navigation\"], #leftnav, #sidetogether,\n [role=\"banner\"], .Fgvgjc, #hdtb, .hdtb-msb,\n footer, #footer, .fbar,\n .pdp-nav, [aria-label=\"Main menu\"], .gb_Td, .gb_L,\n\n /* Specific AI Mode Selectors found in analysis */\n .DZ13He, /* Main sticky top bar */\n .wYq63b, /* Accessibility links bar */\n .eT9Cje, /* History/New Search buttons */\n .bNg8Rb, /* Hidden H1 headers */\n .S6VXfe, /* Accessibility container */\n .Lu57id /* Potential other top bar */ {\n display: none !important;\n }\n\n /* General Layout */\n main { width: 100% !important; max-width: 100% !important; margin: 0 !important; }\n ";
7
+ extractContent(response: any): ContentExtraction;
8
+ parse(response: any, options?: ParseOptions): ParsedResponse;
9
+ }
10
+ //# sourceMappingURL=ai-mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-mode.d.ts","sourceRoot":"","sources":["../../src/providers/ai-mode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE5F,qBAAa,cAAe,SAAQ,YAAY;IAC9C,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAY;IACrC,QAAQ,CAAC,OAAO,4BAA4B;IAE5C,QAAQ,CAAC,aAAa,uwBAoBpB;IAEF,cAAc,CAAC,QAAQ,EAAE,GAAG,GAAG,iBAAiB;IAkChD,KAAK,CAAC,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,cAAc;CAiC7D"}
@@ -0,0 +1,10 @@
1
+ import { BaseProvider } from './base-provider';
2
+ import { AIProvider, ParsedResponse, ParseOptions, ContentExtraction } from '../core/types';
3
+ export declare class AIOverviewProvider extends BaseProvider {
4
+ readonly name: AIProvider;
5
+ readonly baseUrl = "https://www.google.com";
6
+ readonly defaultStyles = "\n /* UI hiding - Google Search (AI Overview) */\n header, #header, #searchform, .sfbg, #appbar,\n div[role=\"navigation\"], #leftnav, #sidetogether,\n [role=\"banner\"], .Fgvgjc, #hdtb, .hdtb-msb,\n footer, #footer, .fbar,\n .pdp-nav, [aria-label=\"Main menu\"], .gb_Td, .gb_L,\n\n /* Specific AI Mode Selectors */\n .DZ13He,\n .wYq63b,\n .eT9Cje,\n .bNg8Rb,\n .S6VXfe,\n .Lu57id {\n display: none !important;\n }\n\n /* General Layout */\n main { width: 100% !important; max-width: 100% !important; margin: 0 !important; }\n ";
7
+ extractContent(response: any): ContentExtraction;
8
+ parse(response: any, options?: ParseOptions): ParsedResponse;
9
+ }
10
+ //# sourceMappingURL=ai-overview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-overview.d.ts","sourceRoot":"","sources":["../../src/providers/ai-overview.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE5F,qBAAa,kBAAmB,SAAQ,YAAY;IAClD,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAgB;IACzC,QAAQ,CAAC,OAAO,4BAA4B;IAE5C,QAAQ,CAAC,aAAa,2kBAoBpB;IAEF,cAAc,CAAC,QAAQ,EAAE,GAAG,GAAG,iBAAiB;IAiFhD,KAAK,CAAC,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,cAAc;CAsE7D"}
@@ -0,0 +1,31 @@
1
+ import { AIProvider, ParsedResponse, ParseOptions, StyleOptions, ContentExtraction } from '../core/types';
2
+ export declare abstract class BaseProvider {
3
+ abstract readonly name: AIProvider;
4
+ abstract readonly baseUrl: string;
5
+ abstract readonly defaultStyles: string;
6
+ /**
7
+ * Parse an AI response and return structured content
8
+ */
9
+ abstract parse(response: any, options?: ParseOptions): ParsedResponse;
10
+ /**
11
+ * Extract content from the response object
12
+ */
13
+ abstract extractContent(response: any): ContentExtraction;
14
+ /**
15
+ * Inject provider-specific styles into HTML
16
+ */
17
+ injectStyles(html: string, options?: StyleOptions): string;
18
+ /**
19
+ * Sanitize HTML content
20
+ */
21
+ sanitizeHtml(html: string): string;
22
+ /**
23
+ * Check if content is a full HTML document
24
+ */
25
+ isFullDocument(html: string): boolean;
26
+ /**
27
+ * Wrap HTML fragment in a document
28
+ */
29
+ wrapFragment(html: string): string;
30
+ }
31
+ //# sourceMappingURL=base-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-provider.d.ts","sourceRoot":"","sources":["../../src/providers/base-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE1G,8BAAsB,YAAY;IAChC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IACnC,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAExC;;OAEG;IACH,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,cAAc;IAErE;;OAEG;IACH,QAAQ,CAAC,cAAc,CAAC,QAAQ,EAAE,GAAG,GAAG,iBAAiB;IAEzD;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM;IAmC1D;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAUlC;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIrC;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CA0BnC"}
@@ -0,0 +1,10 @@
1
+ import { BaseProvider } from './base-provider';
2
+ import { AIProvider, ParsedResponse, ParseOptions, ContentExtraction } from '../core/types';
3
+ export declare class ChatGPTProvider extends BaseProvider {
4
+ readonly name: AIProvider;
5
+ readonly baseUrl = "https://chatgpt.com";
6
+ readonly defaultStyles = "\n /* Force Dark Background on main containers and wrappers */\n html, body, main, article, footer, form,\n [class*=\"bg-\"], [class*=\"footer\"], [class*=\"bottom\"],\n div[class*=\"border-t\"],\n #thread-bottom-container, #thread-bottom,\n #thread, .composer-parent, [class*=\"group\\/thread\"] {\n background-color: #131314 !important;\n color: #e3e3e3 !important;\n border-color: #2a2b36 !important;\n }\n\n /* Force background on specific white artifacts in the footer */\n #thread-bottom-container .bg-clip-padding,\n #thread-bottom-container .content-fade,\n #thread-bottom-container .absolute {\n background-color: transparent !important;\n }\n\n /* Specific targeting for the composer/input box (was white) */\n form .bg-token-bg-primary, form .shadow-short {\n background-color: #2a2b36 !important;\n border-color: #3e3f4b !important;\n box-shadow: none !important;\n }\n\n /* Disclaimer Footer - Force Dark Background */\n div[class*=\"text-token-text-secondary\"] {\n color: #9ca3af !important;\n background-color: #131314 !important;\n }\n\n /* Force Text Color to Light */\n p, h1, h2, h3, h4, h5, h6, li, span, div, td, th, textarea, button {\n color: #e3e3e3 !important;\n }\n\n /* Links - Light Blue */\n a, a span {\n color: #8ab4f8 !important;\n }\n\n /* Code Blocks */\n pre, code, pre div, code span {\n background-color: #2a2b36 !important;\n color: #e3e3e3 !important;\n text-shadow: none !important;\n }\n\n /* Inputs/Textareas */\n input, textarea {\n background-color: transparent !important;\n color: #e3e3e3 !important;\n border-color: #3e3f4b !important;\n }\n\n /* Placeholder text */\n textarea::placeholder {\n color: #9ca3af !important;\n }\n\n /* Hide Sidebar */\n nav, [class*=\"sidebar\"] {\n display: none !important;\n }\n\n /* Media visibility */\n img, video {\n opacity: 1 !important;\n }\n ";
7
+ extractContent(response: any): ContentExtraction;
8
+ parse(response: any, options?: ParseOptions): ParsedResponse;
9
+ }
10
+ //# sourceMappingURL=chatgpt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chatgpt.d.ts","sourceRoot":"","sources":["../../src/providers/chatgpt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE5F,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAa;IACtC,QAAQ,CAAC,OAAO,yBAAyB;IAEzC,QAAQ,CAAC,aAAa,ygEAsEpB;IAEF,cAAc,CAAC,QAAQ,EAAE,GAAG,GAAG,iBAAiB;IAkChD,KAAK,CAAC,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,cAAc;CAgC7D"}
@@ -0,0 +1,10 @@
1
+ import { BaseProvider } from './base-provider';
2
+ import { AIProvider, ParsedResponse, ParseOptions, ContentExtraction } from '../core/types';
3
+ export declare class CopilotProvider extends BaseProvider {
4
+ readonly name: AIProvider;
5
+ readonly baseUrl = "https://copilot.microsoft.com";
6
+ readonly defaultStyles = "\n /* Copilot Sidebar & Header */\n div:has(> [data-testid=\"sidebar-container\"]),\n [data-testid=\"sidebar-container\"],\n [data-testid=\"sticky-header\"],\n .side-nav-menu-button {\n display: none !important;\n }\n\n /* General Layout Fixes */\n main {\n width: 100% !important;\n max-width: 100% !important;\n margin: 0 !important;\n }\n ";
7
+ extractContent(response: any): ContentExtraction;
8
+ parse(response: any, options?: ParseOptions): ParsedResponse;
9
+ }
10
+ //# sourceMappingURL=copilot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copilot.d.ts","sourceRoot":"","sources":["../../src/providers/copilot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE5F,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAa;IACtC,QAAQ,CAAC,OAAO,mCAAmC;IAEnD,QAAQ,CAAC,aAAa,4YAepB;IAEF,cAAc,CAAC,QAAQ,EAAE,GAAG,GAAG,iBAAiB;IAkChD,KAAK,CAAC,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,cAAc;CAgC7D"}
@@ -0,0 +1,10 @@
1
+ import { BaseProvider } from './base-provider';
2
+ import { AIProvider, ParsedResponse, ParseOptions, ContentExtraction } from '../core/types';
3
+ export declare class GeminiProvider extends BaseProvider {
4
+ readonly name: AIProvider;
5
+ readonly baseUrl = "https://gemini.google.com";
6
+ readonly defaultStyles = "\n /* Gemini Dark Mode Variable Overrides */\n :root {\n --gem-sys-color--surface: #131314 !important;\n --gem-sys-color--surface-container: #1e1f20 !important;\n --gem-sys-color--on-surface: #e3e3e3 !important;\n --bard-color-synthetic--chat-window-surface: #131314 !important;\n --bard-color-surface-dim-tmp: #131314 !important;\n }\n\n /* UI hiding - Gemini */\n bard-sidenav, mat-sidenav, .mat-drawer-backdrop, .side-nav-menu-button,\n\n /* Gemini \"About Gemini\" footer/navigation block */\n .gb_5a, .gb_5c, .gb_5d, .gb_5e,\n .gb_Uc, .gb_Vc, .gb_Wc,\n a[href*=\"about\"],\n a[href*=\"subscriptions\"],\n a[href*=\"business\"],\n div[class*=\"gb_5\"],\n .gb_Pd, .gb_Qd, .gb_Rd,\n .gb_Sd, .gb_Td, .gb_Ud, .gb_Vd,\n [aria-label*=\"About\"],\n [aria-label*=\"Gemini App\"],\n [aria-label*=\"Subscriptions\"],\n [aria-label*=\"For Business\"],\n *:contains(\"About Gemini\"),\n *:contains(\"Gemini App\"),\n *:contains(\"Subscriptions\"),\n *:contains(\"For Business\") {\n display: none !important;\n }\n\n /* General Layout */\n main { width: 100% !important; max-width: 100% !important; margin: 0 !important; }\n\n /* Force Dark Mode on Body and Gemini Containers */\n body, .content-container, chat-app, .main-content, .chat-container {\n background-color: #131314 !important;\n color: #e3e3e3 !important;\n }\n ";
7
+ extractContent(response: any): ContentExtraction;
8
+ parse(response: any, options?: ParseOptions): ParsedResponse;
9
+ }
10
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/providers/gemini.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE5F,qBAAa,cAAe,SAAQ,YAAY;IAC9C,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAY;IACrC,QAAQ,CAAC,OAAO,+BAA+B;IAE/C,QAAQ,CAAC,aAAa,w6CAyCpB;IAEF,cAAc,CAAC,QAAQ,EAAE,GAAG,GAAG,iBAAiB;IAyChD,KAAK,CAAC,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,cAAc;CAkC7D"}
@@ -0,0 +1,10 @@
1
+ import { BaseProvider } from './base-provider';
2
+ import { AIProvider, ParsedResponse, ParseOptions, ContentExtraction } from '../core/types';
3
+ export declare class PerplexityProvider extends BaseProvider {
4
+ readonly name: AIProvider;
5
+ readonly baseUrl = "https://www.perplexity.ai";
6
+ readonly defaultStyles = "\n html {\n filter: invert(1) hue-rotate(180deg);\n background-color: white !important;\n }\n img, video, iframe, svg {\n filter: invert(1) hue-rotate(180deg);\n }\n ";
7
+ extractContent(response: any): ContentExtraction;
8
+ parse(response: any, options?: ParseOptions): ParsedResponse;
9
+ }
10
+ //# sourceMappingURL=perplexity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"perplexity.d.ts","sourceRoot":"","sources":["../../src/providers/perplexity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE5F,qBAAa,kBAAmB,SAAQ,YAAY;IAClD,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAgB;IACzC,QAAQ,CAAC,OAAO,+BAA+B;IAE/C,QAAQ,CAAC,aAAa,wMAQpB;IAEF,cAAc,CAAC,QAAQ,EAAE,GAAG,GAAG,iBAAiB;IAkChD,KAAK,CAAC,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,cAAc;CA+B7D"}
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ import { UseAiResponseOptions } from '../hooks/useAiResponse';
3
+ import { IframeRendererProps } from './IframeRenderer';
4
+ export interface AiResponseRendererProps extends Omit<UseAiResponseOptions, 'onError'> {
5
+ response: any;
6
+ className?: string;
7
+ style?: React.CSSProperties;
8
+ iframeProps?: Partial<IframeRendererProps>;
9
+ loadingComponent?: React.ComponentType<{
10
+ isLoading: boolean;
11
+ }>;
12
+ errorComponent?: React.ComponentType<{
13
+ error: Error | null;
14
+ retry: () => void;
15
+ }>;
16
+ fallbackComponent?: React.ComponentType<{
17
+ provider: string | null;
18
+ }>;
19
+ onRenderComplete?: (html: string) => void;
20
+ }
21
+ export declare const AiResponseRenderer: React.FC<AiResponseRendererProps>;
22
+ export { IframeRenderer } from './IframeRenderer';
23
+ export { useAiResponse } from '../hooks/useAiResponse';
24
+ //# sourceMappingURL=AiResponseRenderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AiResponseRenderer.d.ts","sourceRoot":"","sources":["../../../src/react/components/AiResponseRenderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAiB,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAkB,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvE,MAAM,WAAW,uBAAwB,SAAQ,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC;IACpF,QAAQ,EAAE,GAAG,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC3C,gBAAgB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC/D,cAAc,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC,CAAC;IACjF,iBAAiB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IACrE,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C;AAED,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAgHhE,CAAC;AAGF,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ export interface IframeRendererProps {
3
+ html: string;
4
+ className?: string;
5
+ style?: React.CSSProperties;
6
+ sandbox?: string;
7
+ title?: string;
8
+ onLoad?: () => void;
9
+ onError?: () => void;
10
+ }
11
+ export declare const IframeRenderer: React.ForwardRefExoticComponent<IframeRendererProps & React.RefAttributes<HTMLIFrameElement>>;
12
+ //# sourceMappingURL=IframeRenderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IframeRenderer.d.ts","sourceRoot":"","sources":["../../../src/react/components/IframeRenderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAE1C,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,cAAc,+FAmD1B,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { AIProvider, DetectedProvider } from './types';
2
+ export declare class ProviderDetector {
3
+ private static readonly PROVIDER_PATTERNS;
4
+ /**
5
+ * Detect the AI provider from the response
6
+ */
7
+ static detect(response: any): DetectedProvider | null;
8
+ /**
9
+ * Get all possible providers with their confidence scores
10
+ */
11
+ static getAllProviders(response: any): DetectedProvider[];
12
+ /**
13
+ * Validate if a detected provider is likely correct
14
+ */
15
+ static validate(response: any, provider: AIProvider): boolean;
16
+ }
17
+ //# sourceMappingURL=detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../../src/core/detector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEvD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CA0DvC;IAEF;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,GAAG,gBAAgB,GAAG,IAAI;IA2CrD;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,QAAQ,EAAE,GAAG,GAAG,gBAAgB,EAAE;IA2BzD;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,UAAU,GAAG,OAAO;CAI9D"}
@@ -0,0 +1,40 @@
1
+ import { AIProvider, ParsedResponse, ParseOptions } from './types';
2
+ export declare class AIResponseParser {
3
+ private providers;
4
+ constructor();
5
+ /**
6
+ * Parse an AI response with auto-detected provider
7
+ */
8
+ parse(response: any, options?: ParseOptions): ParsedResponse | null;
9
+ /**
10
+ * Parse with explicit provider specification
11
+ */
12
+ parseWithProvider(response: any, provider: AIProvider, options?: ParseOptions): ParsedResponse | null;
13
+ /**
14
+ * Detect the provider from a response
15
+ */
16
+ detectProvider(response: any): AIProvider | null;
17
+ /**
18
+ * Get all possible providers with confidence scores
19
+ */
20
+ detectAllProviders(response: any): Array<{
21
+ provider: AIProvider;
22
+ confidence: number;
23
+ }>;
24
+ /**
25
+ * Parse as generic HTML when no specific provider is detected
26
+ */
27
+ private parseGeneric;
28
+ /**
29
+ * Get list of supported providers
30
+ */
31
+ getSupportedProviders(): AIProvider[];
32
+ /**
33
+ * Register a custom provider
34
+ */
35
+ registerProvider(provider: AIProvider, instance: any): void;
36
+ }
37
+ export declare const parser: AIResponseParser;
38
+ export declare const parseAiResponse: (response: any, options?: ParseOptions) => ParsedResponse | null;
39
+ export declare const detectProvider: (response: any) => AIProvider | null;
40
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/core/parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AASnE,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,SAAS,CAAmC;;IAWpD;;OAEG;IACH,KAAK,CAAC,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,cAAc,GAAG,IAAI;IA4BnE;;OAEG;IACH,iBAAiB,CACf,QAAQ,EAAE,GAAG,EACb,QAAQ,EAAE,UAAU,EACpB,OAAO,CAAC,EAAE,YAAY,GACrB,cAAc,GAAG,IAAI;IAcxB;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,GAAG,GAAG,UAAU,GAAG,IAAI;IAKhD;;OAEG;IACH,kBAAkB,CAAC,QAAQ,EAAE,GAAG,GAAG,KAAK,CAAC;QAAE,QAAQ,EAAE,UAAU,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAItF;;OAEG;IACH,OAAO,CAAC,YAAY;IAuDpB;;OAEG;IACH,qBAAqB,IAAI,UAAU,EAAE;IAIrC;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,GAAG,IAAI;CAG5D;AAGD,eAAO,MAAM,MAAM,kBAAyB,CAAC;AAG7C,eAAO,MAAM,eAAe,GAAI,UAAU,GAAG,EAAE,UAAU,YAAY,0BACpC,CAAC;AAElC,eAAO,MAAM,cAAc,GAAI,UAAU,GAAG,sBACX,CAAC"}
@@ -0,0 +1,35 @@
1
+ export type AIProvider = 'CHATGPT' | 'GEMINI' | 'PERPLEXITY' | 'COPILOT' | 'AIOVERVIEW' | 'AIMODE';
2
+ export interface ParsedResponse {
3
+ provider: AIProvider;
4
+ html: string;
5
+ text?: string;
6
+ sources?: any[];
7
+ metadata?: Record<string, any>;
8
+ }
9
+ export interface ParseOptions {
10
+ theme?: 'light' | 'dark';
11
+ baseUrl?: string;
12
+ sanitize?: boolean;
13
+ includeStyles?: boolean;
14
+ }
15
+ export interface ProviderConfig {
16
+ name: AIProvider;
17
+ baseUrl: string;
18
+ defaultStyles: string;
19
+ }
20
+ export interface DetectedProvider {
21
+ provider: AIProvider;
22
+ confidence: number;
23
+ }
24
+ export interface StyleOptions {
25
+ theme?: 'light' | 'dark';
26
+ customCSS?: string;
27
+ hideUI?: boolean;
28
+ baseUrl?: string;
29
+ }
30
+ export type ContentExtraction = {
31
+ html?: string;
32
+ text?: string;
33
+ sources?: any[];
34
+ };
35
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAClB,SAAS,GACT,QAAQ,GACR,YAAY,GACZ,SAAS,GACT,YAAY,GACZ,QAAQ,CAAC;AAEb,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,UAAU,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,UAAU,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;CACjB,CAAC"}