@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.
- package/README.md +195 -0
- package/dist/core/detector.d.ts +17 -0
- package/dist/core/detector.d.ts.map +1 -0
- package/dist/core/parser.d.ts +40 -0
- package/dist/core/parser.d.ts.map +1 -0
- package/dist/core/types.d.ts +35 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/index.d.ts +170 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.esm.js +2 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/ai-mode.d.ts +10 -0
- package/dist/providers/ai-mode.d.ts.map +1 -0
- package/dist/providers/ai-overview.d.ts +10 -0
- package/dist/providers/ai-overview.d.ts.map +1 -0
- package/dist/providers/base-provider.d.ts +31 -0
- package/dist/providers/base-provider.d.ts.map +1 -0
- package/dist/providers/chatgpt.d.ts +10 -0
- package/dist/providers/chatgpt.d.ts.map +1 -0
- package/dist/providers/copilot.d.ts +10 -0
- package/dist/providers/copilot.d.ts.map +1 -0
- package/dist/providers/gemini.d.ts +10 -0
- package/dist/providers/gemini.d.ts.map +1 -0
- package/dist/providers/perplexity.d.ts +10 -0
- package/dist/providers/perplexity.d.ts.map +1 -0
- package/dist/react/components/AiResponseRenderer.d.ts +24 -0
- package/dist/react/components/AiResponseRenderer.d.ts.map +1 -0
- package/dist/react/components/IframeRenderer.d.ts +12 -0
- package/dist/react/components/IframeRenderer.d.ts.map +1 -0
- package/dist/react/core/detector.d.ts +17 -0
- package/dist/react/core/detector.d.ts.map +1 -0
- package/dist/react/core/parser.d.ts +40 -0
- package/dist/react/core/parser.d.ts.map +1 -0
- package/dist/react/core/types.d.ts +35 -0
- package/dist/react/core/types.d.ts.map +1 -0
- package/dist/react/hooks/useAiResponse.d.ts +19 -0
- package/dist/react/hooks/useAiResponse.d.ts.map +1 -0
- package/dist/react/index.d.ts +87 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.esm.js +11 -0
- package/dist/react/index.esm.js.map +1 -0
- package/dist/react/index.js +11 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/providers/ai-mode.d.ts +10 -0
- package/dist/react/providers/ai-mode.d.ts.map +1 -0
- package/dist/react/providers/ai-overview.d.ts +10 -0
- package/dist/react/providers/ai-overview.d.ts.map +1 -0
- package/dist/react/providers/base-provider.d.ts +31 -0
- package/dist/react/providers/base-provider.d.ts.map +1 -0
- package/dist/react/providers/chatgpt.d.ts +10 -0
- package/dist/react/providers/chatgpt.d.ts.map +1 -0
- package/dist/react/providers/copilot.d.ts +10 -0
- package/dist/react/providers/copilot.d.ts.map +1 -0
- package/dist/react/providers/gemini.d.ts +10 -0
- package/dist/react/providers/gemini.d.ts.map +1 -0
- package/dist/react/providers/perplexity.d.ts +10 -0
- package/dist/react/providers/perplexity.d.ts.map +1 -0
- package/dist/react/react/components/AiResponseRenderer.d.ts +24 -0
- package/dist/react/react/components/AiResponseRenderer.d.ts.map +1 -0
- package/dist/react/react/components/IframeRenderer.d.ts +12 -0
- package/dist/react/react/components/IframeRenderer.d.ts.map +1 -0
- package/dist/react/react/hooks/useAiResponse.d.ts +19 -0
- package/dist/react/react/hooks/useAiResponse.d.ts.map +1 -0
- package/dist/react/react/index.d.ts +7 -0
- package/dist/react/react/index.d.ts.map +1 -0
- package/dist/react/styles/index.d.ts +1 -0
- package/dist/react/styles/index.d.ts.map +1 -0
- package/dist/react/utils/helpers.d.ts +28 -0
- package/dist/react/utils/helpers.d.ts.map +1 -0
- package/dist/styles/index.d.ts +1 -0
- package/dist/styles/index.d.ts.map +1 -0
- package/dist/utils/helpers.d.ts +28 -0
- package/dist/utils/helpers.d.ts.map +1 -0
- package/package.json +85 -0
package/README.md
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# @cloro/response-parser
|
|
2
|
+
|
|
3
|
+
A powerful TypeScript library for parsing and rendering AI model responses from ChatGPT, Gemini, Perplexity, Copilot, and Google AI Overview/Mode.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🤖 **Multi-Provider Support**: ChatGPT, Gemini, Perplexity, Copilot, AI Overview, AI Mode
|
|
8
|
+
- 🔍 **Auto-Detection**: Automatically detects the AI provider from response structure
|
|
9
|
+
- 🎨 **Theme Support**: Built-in dark and light mode styling
|
|
10
|
+
- ⚡ **React Components**: Ready-to-use React components for rendering
|
|
11
|
+
- 🔒 **Secure**: Sandboxed rendering with script sanitization
|
|
12
|
+
- 📦 **TypeScript**: Full TypeScript support with comprehensive types
|
|
13
|
+
- 🎯 **Lightweight**: No runtime dependencies for core parsing
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @cloro/response-parser
|
|
19
|
+
# or
|
|
20
|
+
yarn add @cloro/response-parser
|
|
21
|
+
# or
|
|
22
|
+
pnpm add @cloro/response-parser
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
### Basic Parsing
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { parseAiResponse, detectProvider } from '@cloro/response-parser';
|
|
31
|
+
|
|
32
|
+
// Auto-detect provider and parse
|
|
33
|
+
const response = await fetchAIResponse();
|
|
34
|
+
const parsed = parseAiResponse(response, { theme: 'dark' });
|
|
35
|
+
|
|
36
|
+
console.log(parsed.provider); // 'CHATGPT' | 'GEMINI' | etc.
|
|
37
|
+
console.log(parsed.html); // Sanitized HTML ready for rendering
|
|
38
|
+
console.log(parsed.text); // Plain text version
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### React Component
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
import { AiResponseRenderer } from '@cloro/response-parser/react';
|
|
45
|
+
|
|
46
|
+
function MyComponent() {
|
|
47
|
+
const [aiResponse, setAiResponse] = useState(null);
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<AiResponseRenderer
|
|
51
|
+
response={aiResponse}
|
|
52
|
+
theme="dark"
|
|
53
|
+
autoDetect
|
|
54
|
+
className="w-full h-96"
|
|
55
|
+
iframeProps={{
|
|
56
|
+
sandbox: 'allow-popups'
|
|
57
|
+
}}
|
|
58
|
+
onProviderDetected={(provider) => console.log('Detected:', provider)}
|
|
59
|
+
/>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## API Reference
|
|
65
|
+
|
|
66
|
+
### Core Functions
|
|
67
|
+
|
|
68
|
+
#### `parseAiResponse(response, options?)`
|
|
69
|
+
|
|
70
|
+
Parse an AI response with auto-detected provider.
|
|
71
|
+
|
|
72
|
+
**Options:**
|
|
73
|
+
- `theme`: `'light' | 'dark'` (default: `'dark'`)
|
|
74
|
+
- `baseUrl`: Base URL for relative links
|
|
75
|
+
- `sanitize`: Remove scripts (default: `true`)
|
|
76
|
+
- `includeStyles`: Inject provider-specific styles (default: `true`)
|
|
77
|
+
|
|
78
|
+
**Returns:** `ParsedResponse | null`
|
|
79
|
+
|
|
80
|
+
#### `detectProvider(response)`
|
|
81
|
+
|
|
82
|
+
Detect the AI provider from a response.
|
|
83
|
+
|
|
84
|
+
**Returns:** `AIProvider | null`
|
|
85
|
+
|
|
86
|
+
### React Components
|
|
87
|
+
|
|
88
|
+
#### `<AiResponseRenderer />`
|
|
89
|
+
|
|
90
|
+
Main React component for rendering AI responses.
|
|
91
|
+
|
|
92
|
+
**Props:**
|
|
93
|
+
- `response`: The AI response object
|
|
94
|
+
- `theme`: Light or dark mode
|
|
95
|
+
- `autoDetect`: Auto-detect provider (default: `true`)
|
|
96
|
+
- `provider`: Explicitly specify provider
|
|
97
|
+
- `className`: CSS class for container
|
|
98
|
+
- `iframeProps`: Additional props for iframe
|
|
99
|
+
- `loadingComponent`: Custom loading component
|
|
100
|
+
- `errorComponent`: Custom error component
|
|
101
|
+
- `onProviderDetected`: Callback when provider is detected
|
|
102
|
+
|
|
103
|
+
### Hooks
|
|
104
|
+
|
|
105
|
+
#### `useAiResponse(response, options?)`
|
|
106
|
+
|
|
107
|
+
React hook for parsing AI responses.
|
|
108
|
+
|
|
109
|
+
**Returns:**
|
|
110
|
+
- `parsed`: Parsed response object
|
|
111
|
+
- `provider`: Detected provider
|
|
112
|
+
- `isLoading`: Loading state
|
|
113
|
+
- `error`: Error object
|
|
114
|
+
- `html`: HTML string
|
|
115
|
+
- `text`: Plain text string
|
|
116
|
+
- `reparse`: Function to re-parse with new options
|
|
117
|
+
|
|
118
|
+
## Supported Providers
|
|
119
|
+
|
|
120
|
+
| Provider | Status | Features |
|
|
121
|
+
|----------|--------|----------|
|
|
122
|
+
| ChatGPT | ✅ | Dark mode, sidebar hiding |
|
|
123
|
+
| Gemini | ✅ | Material Design overrides |
|
|
124
|
+
| Perplexity | ✅ | Color inversion for dark mode |
|
|
125
|
+
| Copilot | ✅ | UI element hiding |
|
|
126
|
+
| AI Overview | ✅ | WIZ data extraction |
|
|
127
|
+
| AI Mode | ✅ | Google UI hiding |
|
|
128
|
+
|
|
129
|
+
## Examples
|
|
130
|
+
|
|
131
|
+
### Manual Provider Specification
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
import { parseAiResponse } from 'ai-response-parser';
|
|
135
|
+
|
|
136
|
+
const parsed = parseAiResponse(response, {
|
|
137
|
+
provider: 'CHATGPT',
|
|
138
|
+
theme: 'dark'
|
|
139
|
+
});
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Advanced Usage with Custom Styles
|
|
143
|
+
|
|
144
|
+
```tsx
|
|
145
|
+
<AiResponseRenderer
|
|
146
|
+
response={response}
|
|
147
|
+
theme="dark"
|
|
148
|
+
onError={(error) => console.error(error)}
|
|
149
|
+
onRenderComplete={(html) => console.log('Rendered', html)}
|
|
150
|
+
iframeProps={{
|
|
151
|
+
className: 'custom-iframe',
|
|
152
|
+
style: { border: 'none', borderRadius: '8px' }
|
|
153
|
+
}}
|
|
154
|
+
/>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Error Handling
|
|
158
|
+
|
|
159
|
+
```tsx
|
|
160
|
+
const ErrorComponent = ({ error, retry }) => (
|
|
161
|
+
<div className="error">
|
|
162
|
+
<p>Failed to load: {error.message}</p>
|
|
163
|
+
<button onClick={retry}>Retry</button>
|
|
164
|
+
</div>
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
<AiResponseRenderer
|
|
168
|
+
response={response}
|
|
169
|
+
errorComponent={ErrorComponent}
|
|
170
|
+
/>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Development
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# Install dependencies
|
|
177
|
+
pnpm install
|
|
178
|
+
|
|
179
|
+
# Build
|
|
180
|
+
pnpm build
|
|
181
|
+
|
|
182
|
+
# Test
|
|
183
|
+
pnpm test
|
|
184
|
+
|
|
185
|
+
# Development mode
|
|
186
|
+
pnpm dev
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Contributing
|
|
190
|
+
|
|
191
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
192
|
+
|
|
193
|
+
## License
|
|
194
|
+
|
|
195
|
+
MIT © [Your Name](https://github.com/yourusername)
|
|
@@ -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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
type AIProvider = 'CHATGPT' | 'GEMINI' | 'PERPLEXITY' | 'COPILOT' | 'AIOVERVIEW' | 'AIMODE';
|
|
2
|
+
interface ParsedResponse {
|
|
3
|
+
provider: AIProvider;
|
|
4
|
+
html: string;
|
|
5
|
+
text?: string;
|
|
6
|
+
sources?: any[];
|
|
7
|
+
metadata?: Record<string, any>;
|
|
8
|
+
}
|
|
9
|
+
interface ParseOptions {
|
|
10
|
+
theme?: 'light' | 'dark';
|
|
11
|
+
baseUrl?: string;
|
|
12
|
+
sanitize?: boolean;
|
|
13
|
+
includeStyles?: boolean;
|
|
14
|
+
}
|
|
15
|
+
interface ProviderConfig {
|
|
16
|
+
name: AIProvider;
|
|
17
|
+
baseUrl: string;
|
|
18
|
+
defaultStyles: string;
|
|
19
|
+
}
|
|
20
|
+
interface DetectedProvider {
|
|
21
|
+
provider: AIProvider;
|
|
22
|
+
confidence: number;
|
|
23
|
+
}
|
|
24
|
+
interface StyleOptions {
|
|
25
|
+
theme?: 'light' | 'dark';
|
|
26
|
+
customCSS?: string;
|
|
27
|
+
hideUI?: boolean;
|
|
28
|
+
baseUrl?: string;
|
|
29
|
+
}
|
|
30
|
+
type ContentExtraction = {
|
|
31
|
+
html?: string;
|
|
32
|
+
text?: string;
|
|
33
|
+
sources?: any[];
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
declare class AIResponseParser {
|
|
37
|
+
private providers;
|
|
38
|
+
constructor();
|
|
39
|
+
/**
|
|
40
|
+
* Parse an AI response with auto-detected provider
|
|
41
|
+
*/
|
|
42
|
+
parse(response: any, options?: ParseOptions): ParsedResponse | null;
|
|
43
|
+
/**
|
|
44
|
+
* Parse with explicit provider specification
|
|
45
|
+
*/
|
|
46
|
+
parseWithProvider(response: any, provider: AIProvider, options?: ParseOptions): ParsedResponse | null;
|
|
47
|
+
/**
|
|
48
|
+
* Detect the provider from a response
|
|
49
|
+
*/
|
|
50
|
+
detectProvider(response: any): AIProvider | null;
|
|
51
|
+
/**
|
|
52
|
+
* Get all possible providers with confidence scores
|
|
53
|
+
*/
|
|
54
|
+
detectAllProviders(response: any): Array<{
|
|
55
|
+
provider: AIProvider;
|
|
56
|
+
confidence: number;
|
|
57
|
+
}>;
|
|
58
|
+
/**
|
|
59
|
+
* Parse as generic HTML when no specific provider is detected
|
|
60
|
+
*/
|
|
61
|
+
private parseGeneric;
|
|
62
|
+
/**
|
|
63
|
+
* Get list of supported providers
|
|
64
|
+
*/
|
|
65
|
+
getSupportedProviders(): AIProvider[];
|
|
66
|
+
/**
|
|
67
|
+
* Register a custom provider
|
|
68
|
+
*/
|
|
69
|
+
registerProvider(provider: AIProvider, instance: any): void;
|
|
70
|
+
}
|
|
71
|
+
declare const parser: AIResponseParser;
|
|
72
|
+
declare const parseAiResponse: (response: any, options?: ParseOptions) => ParsedResponse | null;
|
|
73
|
+
declare const detectProvider: (response: any) => AIProvider | null;
|
|
74
|
+
|
|
75
|
+
declare class ProviderDetector {
|
|
76
|
+
private static readonly PROVIDER_PATTERNS;
|
|
77
|
+
/**
|
|
78
|
+
* Detect the AI provider from the response
|
|
79
|
+
*/
|
|
80
|
+
static detect(response: any): DetectedProvider | null;
|
|
81
|
+
/**
|
|
82
|
+
* Get all possible providers with their confidence scores
|
|
83
|
+
*/
|
|
84
|
+
static getAllProviders(response: any): DetectedProvider[];
|
|
85
|
+
/**
|
|
86
|
+
* Validate if a detected provider is likely correct
|
|
87
|
+
*/
|
|
88
|
+
static validate(response: any, provider: AIProvider): boolean;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
declare abstract class BaseProvider {
|
|
92
|
+
abstract readonly name: AIProvider;
|
|
93
|
+
abstract readonly baseUrl: string;
|
|
94
|
+
abstract readonly defaultStyles: string;
|
|
95
|
+
/**
|
|
96
|
+
* Parse an AI response and return structured content
|
|
97
|
+
*/
|
|
98
|
+
abstract parse(response: any, options?: ParseOptions): ParsedResponse;
|
|
99
|
+
/**
|
|
100
|
+
* Extract content from the response object
|
|
101
|
+
*/
|
|
102
|
+
abstract extractContent(response: any): ContentExtraction;
|
|
103
|
+
/**
|
|
104
|
+
* Inject provider-specific styles into HTML
|
|
105
|
+
*/
|
|
106
|
+
injectStyles(html: string, options?: StyleOptions): string;
|
|
107
|
+
/**
|
|
108
|
+
* Sanitize HTML content
|
|
109
|
+
*/
|
|
110
|
+
sanitizeHtml(html: string): string;
|
|
111
|
+
/**
|
|
112
|
+
* Check if content is a full HTML document
|
|
113
|
+
*/
|
|
114
|
+
isFullDocument(html: string): boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Wrap HTML fragment in a document
|
|
117
|
+
*/
|
|
118
|
+
wrapFragment(html: string): string;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
declare class ChatGPTProvider extends BaseProvider {
|
|
122
|
+
readonly name: AIProvider;
|
|
123
|
+
readonly baseUrl = "https://chatgpt.com";
|
|
124
|
+
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 ";
|
|
125
|
+
extractContent(response: any): ContentExtraction;
|
|
126
|
+
parse(response: any, options?: ParseOptions): ParsedResponse;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
declare class GeminiProvider extends BaseProvider {
|
|
130
|
+
readonly name: AIProvider;
|
|
131
|
+
readonly baseUrl = "https://gemini.google.com";
|
|
132
|
+
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 ";
|
|
133
|
+
extractContent(response: any): ContentExtraction;
|
|
134
|
+
parse(response: any, options?: ParseOptions): ParsedResponse;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
declare class PerplexityProvider extends BaseProvider {
|
|
138
|
+
readonly name: AIProvider;
|
|
139
|
+
readonly baseUrl = "https://www.perplexity.ai";
|
|
140
|
+
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 ";
|
|
141
|
+
extractContent(response: any): ContentExtraction;
|
|
142
|
+
parse(response: any, options?: ParseOptions): ParsedResponse;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
declare class CopilotProvider extends BaseProvider {
|
|
146
|
+
readonly name: AIProvider;
|
|
147
|
+
readonly baseUrl = "https://copilot.microsoft.com";
|
|
148
|
+
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 ";
|
|
149
|
+
extractContent(response: any): ContentExtraction;
|
|
150
|
+
parse(response: any, options?: ParseOptions): ParsedResponse;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
declare class AIOverviewProvider extends BaseProvider {
|
|
154
|
+
readonly name: AIProvider;
|
|
155
|
+
readonly baseUrl = "https://www.google.com";
|
|
156
|
+
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 ";
|
|
157
|
+
extractContent(response: any): ContentExtraction;
|
|
158
|
+
parse(response: any, options?: ParseOptions): ParsedResponse;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
declare class AIModeProvider extends BaseProvider {
|
|
162
|
+
readonly name: AIProvider;
|
|
163
|
+
readonly baseUrl = "https://www.google.com";
|
|
164
|
+
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 ";
|
|
165
|
+
extractContent(response: any): ContentExtraction;
|
|
166
|
+
parse(response: any, options?: ParseOptions): ParsedResponse;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export { AIModeProvider, AIOverviewProvider, AIResponseParser, BaseProvider, ChatGPTProvider, CopilotProvider, GeminiProvider, PerplexityProvider, ProviderDetector, detectProvider, parseAiResponse, parser };
|
|
170
|
+
export type { AIProvider, ContentExtraction, DetectedProvider, ParseOptions, ParsedResponse, ProviderConfig, StyleOptions };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC1F,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGnD,YAAY,EACV,UAAU,EACV,cAAc,EACd,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,GAClB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
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,d=(t,e)=>c.parse(t,e),h=t=>c.detectProvider(t);export{a as AIModeProvider,s as AIOverviewProvider,l as AIResponseParser,e as BaseProvider,n as ChatGPTProvider,i as CopilotProvider,r as GeminiProvider,o as PerplexityProvider,t as ProviderDetector,h as detectProvider,d as parseAiResponse,c as parser};
|
|
2
|
+
//# sourceMappingURL=index.esm.js.map
|