/**
* Lightweight Renderer - JS-capable HTML renderer without full browser overhead
*
* This module provides a middle ground between static HTML parsing (like justjshtml)
* and full browser automation (Playwright). It can execute JavaScript in a sandboxed
* environment using linkedom for DOM and Node's vm module for script execution.
*
* Use cases:
* - Sites that need basic JS execution to render content
* - Server-rendered pages with light client hydration
* - Pages that fetch data via API and inject into DOM
*
* Does NOT handle:
* - Heavy anti-bot protection (Cloudflare, reCAPTCHA)
* - Complex user interactions (hover states, drag-drop)
* - WebGL/Canvas rendering
* - WebSocket connections
*/
import { Cookie } from 'tough-cookie';
export interface LightweightRenderOptions {
timeout?: number;
scriptTimeout?: number;
executeScripts?: boolean;
asyncWaitTime?: number;
headers?: Record;
userAgent?: string;
followRedirects?: boolean;
maxRedirects?: number;
skipScriptPatterns?: RegExp[];
cookies?: Cookie[];
simulateScroll?: boolean;
maxScrolls?: number;
scrollDelay?: number;
scrollDistance?: number;
}
export interface LightweightRenderResult {
html: string;
finalUrl: string;
jsExecuted: boolean;
scriptsExecuted: number;
scriptsSkipped: number;
scriptErrors: Array<{
src?: string;
error: string;
}>;
networkRequests: Array<{
url: string;
method: string;
status?: number;
contentType?: string;
requestHeaders?: Record;
responseHeaders?: Record;
responseBody?: unknown;
timestamp: number;
duration?: number;
}>;
cookies: Cookie[];
timing: {
fetchTime: number;
parseTime: number;
scriptTime: number;
totalTime: number;
scrollTime?: number;
};
detection: {
isJSHeavy: boolean;
hasAsyncContent: boolean;
needsFullBrowser: boolean;
reason?: string;
lazyLoad?: {
detected: boolean;
patterns: string[];
confidence: 'low' | 'medium' | 'high';
};
};
scrollSimulation?: {
enabled: boolean;
scrollsPerformed: number;
contentGrowth: number;
reachedBottom: boolean;
};
}
export declare class LightweightRenderer {
private cookieJar;
private options;
constructor(options?: Partial);
/**
* Render a URL with optional JavaScript execution
*/
render(url: string, options?: Partial): Promise;
/**
* Quick static render without JS execution (fastest)
*/
renderStatic(url: string, options?: Partial): Promise;
/**
* Fetch URL with cookie handling and redirects
*/
private fetchWithCookies;
/**
* Create a sandboxed execution context for JavaScript
*/
private createExecutionContext;
/**
* Execute a script with timeout
*/
private executeScript;
/**
* Wait for async content to settle - OWL-008 enhancement
*
* Replaces fixed timeout with smart content stabilization detection.
* Waits for DOM changes to stabilize (500ms no changes) with 5s max timeout.
*/
private waitForAsyncContent;
/**
* OWL-010: Simulate scrolling to trigger lazy-loaded content
*
* Scrolls the page incrementally, waiting for new content to load after each scroll.
* Stops when no new content appears or max scrolls reached.
*
* Returns metrics about the scrolling session.
*/
private simulateScrolling;
/**
* Check if a script should be skipped
*/
private shouldSkipScript;
/**
* Detect page characteristics to determine if full browser is needed
*/
private detectPageCharacteristics;
/**
* OWL-009: Detect lazy-loading patterns that require scroll simulation
*
* Returns object with:
* - hasLazyLoad: boolean indicating if lazy loading detected
* - patterns: array of detected pattern types
* - confidence: 'low' | 'medium' | 'high'
*/
private detectLazyLoadPatterns;
/**
* Check if the page looks like a challenge/verification page rather than
* a normal page that happens to have a captcha widget
*/
private looksLikeChallengePage;
/**
* Get cookies for a domain
*/
getCookies(url: string): Promise;
/**
* Set cookies for a domain
*/
setCookies(cookies: Cookie[], url: string): Promise;
/**
* Clear all cookies
*/
clearCookies(): Promise;
}
export declare const lightweightRenderer: LightweightRenderer;
//# sourceMappingURL=lightweight-renderer.d.ts.map