import { Readability } from "@mozilla/readability"; import { parseHTML } from "linkedom"; import TurndownService from "turndown"; import type { ExtractedContent } from "./utils"; import { errorMessage } from "./utils"; const DEFAULT_TIMEOUT_MS = 30000; const MAX_RESPONSE_SIZE = 5 * 1024 * 1024; // 5MB const JINA_READER_BASE = "https://r.jina.ai/"; const JINA_TIMEOUT_MS = 30000; const MIN_USEFUL_CONTENT = 500; const turndown = new TurndownService({ headingStyle: "atx", codeBlockStyle: "fenced", }); const REJECTED_TYPES = [ "application/octet-stream", "image/", "audio/", "video/", "application/zip", "application/gzip", "application/x-tar", "application/x-rar-compressed", ]; const isRejectedContentType = (contentType: string): boolean => { const lower = contentType.toLowerCase(); return REJECTED_TYPES.some((t) => lower.includes(t)); }; const isLikelyJSRendered = (html: string): boolean => { const bodyMatch = html.match(/
]*>([\s\S]*?)<\/body>/i); if (!bodyMatch) return false; const textContent = bodyMatch[1] .replace(/