@happyalienai/vite-plugin-llm-spider 0.1.0 → 0.2.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 +38 -4
- package/dist/index.cjs +260 -166
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +260 -166
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.js"],"sourcesContent":["import { preview } from \"vite\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport * as cheerio from \"cheerio\";\nimport TurndownService from \"turndown\";\nimport { gfm } from \"turndown-plugin-gfm\";\nimport puppeteer from \"puppeteer\";\n\n/**\n * @typedef {{ path: string, title?: string, section?: string, optional?: boolean, notes?: string }} RouteDef\n */\n\n/**\n * Vite Plugin: LLM Spider\n * - Generates Markdown snapshots + dist/llms.txt\n * - Spec-aligned default output: \".md appended\" / \"index.html.md\" for directory URLs.\n */\nexport default function llmSpiderPlugin(userOptions = {}) {\n /** @type {import('vite').ResolvedConfig | undefined} */\n let resolvedConfig;\n\n // Deep merge helper\n function deepMerge(target, source) {\n const result = { ...target };\n for (const key of Object.keys(source)) {\n if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key]) && !(source[key] instanceof RegExp)) {\n result[key] = deepMerge(target[key] || {}, source[key]);\n } else {\n result[key] = source[key];\n }\n }\n return result;\n }\n\n const defaults = {\n enabled: true,\n\n // Recommended: explicit list\n routes: /** @type {RouteDef[] | undefined} */ (undefined),\n\n // Optional crawl mode (off by default)\n crawl: {\n enabled: false,\n seeds: [\"/\"],\n maxDepth: 2,\n maxPages: 50,\n concurrency: 3,\n stripQuery: true,\n },\n\n exclude: [\"/login\", \"/admin\", \"/account\"],\n\n render: {\n waitUntil: \"networkidle2\", // more forgiving than networkidle0 for SPAs\n timeoutMs: 30_000,\n waitForSelector: null, // e.g. \"main\" or \"#app main\"\n postLoadDelayMs: 0,\n blockRequests: [\n /google-analytics\\.com/i,\n /googletagmanager\\.com/i,\n /segment\\.com/i,\n /hotjar\\.com/i,\n ],\n launchOptions: {\n headless: \"new\",\n // For CI containers you may need:\n // args: [\"--no-sandbox\", \"--disable-setuid-sandbox\"],\n },\n /**\n * @param {import('puppeteer').Page} _page\n * @param {{ route: string }} _ctx\n */\n beforeGoto: async (_page, _ctx) => {},\n /**\n * @param {import('puppeteer').Page} _page\n * @param {{ route: string }} _ctx\n */\n beforeExtract: async (_page, _ctx) => {},\n },\n\n extract: {\n mainSelector: [\"main\", \"#main-content\", \"[data-main]\"],\n removeSelectors: [\n \"script\",\n \"style\",\n \"noscript\",\n \"nav\",\n \"header\",\n \"footer\",\n \"svg\",\n \"iframe\",\n \"[role='alert']\",\n \".cookie\",\n \".cookie-banner\",\n \".modal\",\n ],\n },\n\n markdown: {\n addFrontmatter: true,\n turndown: {\n headingStyle: \"atx\",\n codeBlockStyle: \"fenced\",\n emDelimiter: \"_\",\n },\n },\n\n output: {\n // \"sibling\" => /pricing -> pricing.md ; /docs/ -> docs/index.html.md ; / -> index.html.md\n mode: \"sibling\",\n subdir: \"ai\", // used only when mode === \"subdir\"\n llmsTxtFileName: \"llms.txt\",\n llmsTitle: null, // defaults to package name or project dir\n llmsSummary:\n \"LLM-friendly index of important pages and their Markdown equivalents.\",\n sort: true,\n },\n\n logLevel: \"info\", // \"silent\" | \"info\" | \"debug\"\n };\n\n const options = deepMerge(defaults, userOptions);\n\n const log = {\n info: (...args) =>\n options.logLevel === \"info\" || options.logLevel === \"debug\"\n ? console.log(...args)\n : undefined,\n debug: (...args) =>\n options.logLevel === \"debug\" ? console.log(...args) : undefined,\n warn: (...args) =>\n options.logLevel !== \"silent\" ? console.warn(...args) : undefined,\n };\n\n function isExcluded(route) {\n return (options.exclude || []).some((p) => {\n if (p instanceof RegExp) return p.test(route);\n return route.includes(p);\n });\n }\n\n function normalizeRoute(input, { stripQuery = true } = {}) {\n if (!input) return null;\n\n // Ignore non-page links\n if (\n input.startsWith(\"mailto:\") ||\n input.startsWith(\"tel:\") ||\n input.startsWith(\"javascript:\")\n )\n return null;\n\n // Convert relative -> absolute-ish (we only keep paths)\n // If input is like \"./about\" or \"about\", normalize to \"/about\"\n let s = input.trim();\n\n // Remove protocol absolute links\n if (s.startsWith(\"http://\") || s.startsWith(\"https://\")) return null;\n\n // Drop hash/query\n const hashIdx = s.indexOf(\"#\");\n if (hashIdx >= 0) s = s.slice(0, hashIdx);\n\n if (stripQuery) {\n const qIdx = s.indexOf(\"?\");\n if (qIdx >= 0) s = s.slice(0, qIdx);\n }\n\n // Ignore empty after stripping\n if (!s) return null;\n\n // Normalize relative paths\n if (!s.startsWith(\"/\")) {\n if (s.startsWith(\"./\"))\n s = s.slice(1); // \"./x\" -> \"/x\"\n else s = \"/\" + s;\n }\n\n // Collapse multiple slashes\n s = s.replace(/\\/{2,}/g, \"/\");\n\n return s;\n }\n\n function routeToMdWebPath(route) {\n // route is base-relative and starts with \"/\"\n if (route === \"/\") return \"index.html.md\";\n if (route.endsWith(\"/\")) return route.slice(1) + \"index.html.md\"; // \"docs/\" -> \"docs/index.html.md\"\n return route.slice(1) + \".md\"; // \"pricing\" -> \"pricing.md\"\n }\n\n function routeToMdFsPath(distDir, route) {\n const rel = routeToMdWebPath(route); // already relative\n if (options.output.mode === \"subdir\") {\n return path.join(distDir, options.output.subdir, rel);\n }\n return path.join(distDir, rel);\n }\n\n function makeLlmsLink(relMdPath) {\n // Use relative links (no leading slash) so it works in subpath deployments.\n // If subdir mode: links should include \"ai/...\"\n return relMdPath.replace(/\\\\/g, \"/\");\n }\n\n async function safeCloseHttpServer(server) {\n await new Promise((resolve, reject) => {\n server.close((err) => (err ? reject(err) : resolve()));\n });\n }\n\n return {\n name: \"vite-plugin-llm-spider\",\n apply: \"build\",\n\n configResolved(rc) {\n resolvedConfig = rc;\n },\n\n async closeBundle() {\n if (!options.enabled) return;\n if (!resolvedConfig)\n throw new Error(\"LLM Spider: missing resolved Vite config\");\n\n const distDir = resolvedConfig.build.outDir || \"dist\";\n const basePath = (resolvedConfig.base || \"/\").replace(/\\\\/g, \"/\");\n\n // ---- Resolve route list ----\n /** @type {RouteDef[]} */\n let routeDefs = [];\n\n if (Array.isArray(options.routes) && options.routes.length) {\n routeDefs = options.routes.map((r) => ({\n path: normalizeRoute(r.path, { stripQuery: true }) || \"/\",\n title: r.title,\n section: r.section || \"Pages\",\n optional: !!r.optional,\n notes: r.notes,\n }));\n } else if (options.crawl?.enabled) {\n // Crawl mode: route defs will be created as discovered.\n routeDefs = [];\n } else {\n // Default minimal route\n routeDefs = [{ path: \"/\", section: \"Pages\" }];\n }\n\n log.info(\"\\nLLM Spider: generating markdown + llms.txt\");\n log.debug(\"distDir:\", distDir, \"base:\", basePath);\n\n // ---- Start preview server for built output ----\n // Vite preview API returns a PreviewServer with httpServer + resolvedUrls.\n const previewServer = await preview({\n root: resolvedConfig.root,\n base: resolvedConfig.base,\n build: { outDir: distDir },\n preview: { port: 0, open: false, host: '127.0.0.1' },\n configFile: false,\n plugins: [], // avoid loading user plugins again\n logLevel: \"silent\",\n });\n\n // Wait for server to be fully listening\n await new Promise((resolve, reject) => {\n const server = previewServer.httpServer;\n if (server.listening) {\n resolve();\n } else {\n server.once('listening', resolve);\n server.once('error', reject);\n // Timeout after 5s\n setTimeout(() => reject(new Error('Preview server failed to start')), 5000);\n }\n });\n\n const addr = previewServer.httpServer.address();\n if (!addr || typeof addr === \"string\") {\n await safeCloseHttpServer(previewServer.httpServer);\n throw new Error(\"LLM Spider: could not determine preview server port\");\n }\n\n // Build a base URL that respects Vite's base path\n // Example: http://127.0.0.1:4173/app/ (if base=\"/app/\")\n const normalizedBase = basePath.endsWith(\"/\") ? basePath : basePath + \"/\";\n const baseUrl = `http://127.0.0.1:${addr.port}${normalizedBase}`;\n \n log.debug(\"Preview server at:\", baseUrl);\n\n const browser = await puppeteer.launch(options.render.launchOptions);\n const turndown = new TurndownService(options.markdown.turndown);\n turndown.use(gfm);\n\n /** @type {Set<string>} */\n const visited = new Set();\n\n /** @type {{ route: string, title?: string, section: string, optional: boolean, notes?: string, mdRelPath: string }[]} */\n const captured = [];\n\n // Crawl queue stores base-relative routes (no base prefix)\n /** @type {{ route: string, depth: number }[]} */\n const queue = [];\n\n // Seed queue\n if (options.crawl?.enabled) {\n for (const seed of options.crawl.seeds || [\"/\"]) {\n const nr = normalizeRoute(seed, {\n stripQuery: options.crawl.stripQuery,\n });\n if (nr) queue.push({ route: nr, depth: 0 });\n }\n } else {\n for (const rd of routeDefs) queue.push({ route: rd.path, depth: 0 });\n }\n\n const maxDepth = options.crawl?.enabled ? options.crawl.maxDepth : 0;\n const maxPages = options.crawl?.enabled\n ? options.crawl.maxPages\n : queue.length;\n const concurrency = options.crawl?.enabled\n ? options.crawl.concurrency\n : 3;\n\n async function captureOne(route) {\n if (visited.has(route)) return;\n if (isExcluded(route)) return;\n if (captured.length >= maxPages) return;\n\n visited.add(route);\n\n const page = await browser.newPage();\n\n // Request blocking (best effort)\n if (options.render.blockRequests?.length) {\n await page.setRequestInterception(true);\n page.on(\"request\", (req) => {\n const url = req.url();\n const blocked = options.render.blockRequests.some((p) =>\n p instanceof RegExp ? p.test(url) : url.includes(p),\n );\n if (blocked) req.abort();\n else req.continue();\n });\n }\n\n try {\n const pageUrl =\n route === \"/\" ? baseUrl : baseUrl + route.replace(/^\\//, \"\");\n await options.render.beforeGoto(page, { route });\n\n await page.goto(pageUrl, {\n waitUntil: options.render.waitUntil,\n timeout: options.render.timeoutMs,\n });\n\n if (options.render.waitForSelector) {\n await page.waitForSelector(options.render.waitForSelector, {\n timeout: options.render.timeoutMs,\n });\n }\n\n if (options.render.postLoadDelayMs > 0) {\n await new Promise((r) =>\n setTimeout(r, options.render.postLoadDelayMs),\n );\n }\n\n await options.render.beforeExtract(page, { route });\n\n const html = await page.content();\n const $ = cheerio.load(html);\n\n // Harvest links BEFORE removing nav elements (for crawl mode)\n let harvestedHrefs = [];\n if (options.crawl?.enabled) {\n harvestedHrefs = $(\"a[href]\")\n .map((_, a) => $(a).attr(\"href\"))\n .get();\n log.debug(` Found ${harvestedHrefs.length} links on ${route}:`, harvestedHrefs.slice(0, 15));\n }\n\n // Remove noisy elements (CSS selectors)\n for (const sel of options.extract.removeSelectors || [])\n $(sel).remove();\n\n // Pick main content\n const mainSelectors = Array.isArray(options.extract.mainSelector)\n ? options.extract.mainSelector\n : [options.extract.mainSelector];\n\n let mainHtml = null;\n for (const sel of mainSelectors) {\n if (!sel) continue;\n const node = $(sel).first();\n if (node && node.length) {\n mainHtml = node.html();\n break;\n }\n }\n if (!mainHtml) {\n const main = $(\"main\").first();\n mainHtml = main.length ? main.html() : $(\"body\").html();\n }\n\n const title = ($(\"title\").text() || \"\").trim() || route;\n\n // Convert to Markdown\n const markdownBody = turndown.turndown(mainHtml || \"\");\n\n // Write file\n const mdRelPath =\n options.output.mode === \"subdir\"\n ? path.posix.join(options.output.subdir, routeToMdWebPath(route))\n : routeToMdWebPath(route);\n\n const fsPath = routeToMdFsPath(distDir, route);\n await fs.mkdir(path.dirname(fsPath), { recursive: true });\n\n const frontmatter = options.markdown.addFrontmatter\n ? `---\\nsource: ${route}\\ntitle: ${title}\\ngenerated_at: ${new Date().toISOString()}\\n---\\n\\n`\n : \"\";\n\n await fs.writeFile(fsPath, frontmatter + markdownBody, \"utf8\");\n\n // Map metadata\n const meta = routeDefs.find((r) => r.path === route);\n captured.push({\n route,\n title: meta?.title || title,\n section: meta?.section || \"Pages\",\n optional: !!meta?.optional,\n notes: meta?.notes,\n mdRelPath,\n });\n\n log.info(` ✅ ${route} -> ${mdRelPath}`);\n\n // Harvest links (crawl mode only) - using pre-harvested links from before cleanup\n if (options.crawl?.enabled) {\n for (const href of harvestedHrefs) {\n const n = normalizeRoute(href, {\n stripQuery: options.crawl.stripQuery,\n });\n if (!n) continue;\n\n // If site is deployed under a base like \"/app/\", router-links usually include \"/app/...\"\n // Strip base prefix when present so our internal route stays base-relative.\n let baseRelative = n;\n if (\n normalizedBase !== \"/\" &&\n baseRelative.startsWith(normalizedBase)\n ) {\n baseRelative = \"/\" + baseRelative.slice(normalizedBase.length);\n baseRelative =\n baseRelative === \"//\"\n ? \"/\"\n : baseRelative.replace(/\\/{2,}/g, \"/\");\n }\n\n if (!visited.has(baseRelative) && !isExcluded(baseRelative)) {\n // Depth tracking is handled by the outer loop (we store depth in queue entries)\n // so just push; caller will attach depth.\n queue.push({ route: baseRelative, depth: -1 }); // placeholder depth; will be overwritten\n }\n }\n }\n } catch (err) {\n log.warn(` ⚠️ failed ${route}: ${err?.message || err}`);\n } finally {\n await page.close();\n }\n }\n\n try {\n // BFS: process queue in batches\n while (queue.length && captured.length < maxPages) {\n // Fix up crawl depths if needed\n // If we're in crawl mode, queue items may have depth=-1 from harvested links.\n // We'll conservatively treat them as depth=1 unless they were explicitly set.\n const batch = queue.splice(0, concurrency).map((item) => {\n const depth = item.depth >= 0 ? item.depth : 1;\n return { route: item.route, depth };\n });\n\n await Promise.all(\n batch.map(async ({ route, depth }) => {\n if (options.crawl?.enabled && depth > maxDepth) return;\n await captureOne(route);\n\n // If crawl mode, increase depth for any newly harvested links\n if (options.crawl?.enabled) {\n // Patch any depth=-1 entries added during captureOne\n for (let i = 0; i < queue.length; i++) {\n if (queue[i].depth === -1) queue[i].depth = depth + 1;\n }\n }\n }),\n );\n }\n\n // ---- Generate llms.txt ----\n const llmsTitle =\n options.output.llmsTitle || resolvedConfig?.env?.mode || \"Site\";\n\n // Deterministic ordering\n const items = options.output.sort\n ? [...captured].sort((a, b) => a.route.localeCompare(b.route))\n : captured;\n\n // Group by section, with Optional special handling\n /** @type {Map<string, typeof items>} */\n const bySection = new Map();\n /** @type {typeof items} */\n const optionalItems = [];\n\n for (const item of items) {\n if (item.optional) optionalItems.push(item);\n else {\n const s = item.section || \"Pages\";\n bySection.set(s, [...(bySection.get(s) || []), item]);\n }\n }\n\n let llms = `# ${llmsTitle}\\n\\n> ${options.output.llmsSummary}\\n\\n`;\n\n for (const [section, sectionItems] of bySection.entries()) {\n llms += `## ${section}\\n\\n`;\n for (const it of sectionItems) {\n const link = makeLlmsLink(it.mdRelPath);\n const label = it.title || it.route;\n const notes = it.notes ? `: ${it.notes}` : \"\";\n llms += `- [${label}](${link})${notes}\\n`;\n }\n llms += `\\n`;\n }\n\n if (optionalItems.length) {\n llms += `## Optional\\n\\n`;\n for (const it of optionalItems) {\n const link = makeLlmsLink(it.mdRelPath);\n const label = it.title || it.route;\n const notes = it.notes ? `: ${it.notes}` : \"\";\n llms += `- [${label}](${link})${notes}\\n`;\n }\n llms += `\\n`;\n }\n\n const llmsPath = path.join(distDir, options.output.llmsTxtFileName);\n await fs.writeFile(llmsPath, llms, \"utf8\");\n\n log.info(\n `\\nLLM Spider: wrote ${captured.length} markdown pages + ${options.output.llmsTxtFileName}\\n`,\n );\n } finally {\n await browser.close();\n await safeCloseHttpServer(previewServer.httpServer);\n }\n },\n };\n}\n\n// Named export for CJS compatibility\nexport { llmSpiderPlugin };\n"],"mappings":"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","names":["_a","_b","_c"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.js"],"sourcesContent":["import { preview } from \"vite\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport * as cheerio from \"cheerio\";\nimport TurndownService from \"turndown\";\nimport { gfm } from \"turndown-plugin-gfm\";\n\n// Lazy-load puppeteer only when needed\nlet puppeteer = null;\nasync function loadPuppeteer() {\n if (!puppeteer) {\n puppeteer = await import(\"puppeteer\");\n }\n return puppeteer.default || puppeteer;\n}\n\n/**\n * @typedef {{ path: string, title?: string, section?: string, optional?: boolean, notes?: string }} RouteDef\n */\n\n/**\n * Vite Plugin: LLM Spider\n * - Generates Markdown snapshots + dist/llms.txt\n * - Spec-aligned default output: \".md appended\" / \"index.html.md\" for directory URLs.\n */\nexport default function llmSpiderPlugin(userOptions = {}) {\n /** @type {import('vite').ResolvedConfig | undefined} */\n let resolvedConfig;\n\n // Deep merge helper\n function deepMerge(target, source) {\n const result = { ...target };\n for (const key of Object.keys(source)) {\n if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key]) && !(source[key] instanceof RegExp)) {\n result[key] = deepMerge(target[key] || {}, source[key]);\n } else {\n result[key] = source[key];\n }\n }\n return result;\n }\n\n const defaults = {\n enabled: true,\n\n // Static mode: read HTML files directly from dist/ without browser\n // - true: always use static mode (no Puppeteer)\n // - false: always use browser rendering\n // - \"auto\" (default): use static when crawl is disabled, browser when crawl is enabled\n static: \"auto\",\n\n // Recommended: explicit list\n routes: /** @type {RouteDef[] | undefined} */ (undefined),\n\n // Optional crawl mode (off by default)\n crawl: {\n enabled: false,\n seeds: [\"/\"],\n maxDepth: 2,\n maxPages: 50,\n concurrency: 3,\n stripQuery: true,\n },\n\n exclude: [\"/login\", \"/admin\", \"/account\"],\n\n render: {\n waitUntil: \"networkidle2\", // more forgiving than networkidle0 for SPAs\n timeoutMs: 30_000,\n waitForSelector: null, // e.g. \"main\" or \"#app main\"\n postLoadDelayMs: 0,\n blockRequests: [\n /google-analytics\\.com/i,\n /googletagmanager\\.com/i,\n /segment\\.com/i,\n /hotjar\\.com/i,\n ],\n launchOptions: {\n headless: \"new\",\n // For CI containers you may need:\n // args: [\"--no-sandbox\", \"--disable-setuid-sandbox\"],\n },\n /**\n * @param {import('puppeteer').Page} _page\n * @param {{ route: string }} _ctx\n */\n beforeGoto: async (_page, _ctx) => {},\n /**\n * @param {import('puppeteer').Page} _page\n * @param {{ route: string }} _ctx\n */\n beforeExtract: async (_page, _ctx) => {},\n },\n\n extract: {\n mainSelector: [\"main\", \"#main-content\", \"[data-main]\"],\n removeSelectors: [\n \"script\",\n \"style\",\n \"noscript\",\n \"nav\",\n \"header\",\n \"footer\",\n \"svg\",\n \"iframe\",\n \"[role='alert']\",\n \".cookie\",\n \".cookie-banner\",\n \".modal\",\n ],\n },\n\n markdown: {\n addFrontmatter: true,\n turndown: {\n headingStyle: \"atx\",\n codeBlockStyle: \"fenced\",\n emDelimiter: \"_\",\n },\n },\n\n output: {\n // \"sibling\" => /pricing -> pricing.md ; /docs/ -> docs/index.html.md ; / -> index.html.md\n mode: \"sibling\",\n subdir: \"ai\", // used only when mode === \"subdir\"\n llmsTxtFileName: \"llms.txt\",\n llmsTitle: null, // defaults to package name or project dir\n llmsSummary:\n \"LLM-friendly index of important pages and their Markdown equivalents.\",\n sort: true,\n },\n\n logLevel: \"info\", // \"silent\" | \"info\" | \"debug\"\n };\n\n const options = deepMerge(defaults, userOptions);\n\n const log = {\n info: (...args) =>\n options.logLevel === \"info\" || options.logLevel === \"debug\"\n ? console.log(...args)\n : undefined,\n debug: (...args) =>\n options.logLevel === \"debug\" ? console.log(...args) : undefined,\n warn: (...args) =>\n options.logLevel !== \"silent\" ? console.warn(...args) : undefined,\n };\n\n function isExcluded(route) {\n return (options.exclude || []).some((p) => {\n if (p instanceof RegExp) return p.test(route);\n return route.includes(p);\n });\n }\n\n function normalizeRoute(input, { stripQuery = true } = {}) {\n if (!input) return null;\n\n // Ignore non-page links\n if (\n input.startsWith(\"mailto:\") ||\n input.startsWith(\"tel:\") ||\n input.startsWith(\"javascript:\")\n )\n return null;\n\n // Convert relative -> absolute-ish (we only keep paths)\n // If input is like \"./about\" or \"about\", normalize to \"/about\"\n let s = input.trim();\n\n // Remove protocol absolute links\n if (s.startsWith(\"http://\") || s.startsWith(\"https://\")) return null;\n\n // Drop hash/query\n const hashIdx = s.indexOf(\"#\");\n if (hashIdx >= 0) s = s.slice(0, hashIdx);\n\n if (stripQuery) {\n const qIdx = s.indexOf(\"?\");\n if (qIdx >= 0) s = s.slice(0, qIdx);\n }\n\n // Ignore empty after stripping\n if (!s) return null;\n\n // Normalize relative paths\n if (!s.startsWith(\"/\")) {\n if (s.startsWith(\"./\"))\n s = s.slice(1); // \"./x\" -> \"/x\"\n else s = \"/\" + s;\n }\n\n // Collapse multiple slashes\n s = s.replace(/\\/{2,}/g, \"/\");\n\n return s;\n }\n\n function routeToMdWebPath(route) {\n // route is base-relative and starts with \"/\"\n if (route === \"/\") return \"index.html.md\";\n if (route.endsWith(\"/\")) return route.slice(1) + \"index.html.md\"; // \"docs/\" -> \"docs/index.html.md\"\n return route.slice(1) + \".md\"; // \"pricing\" -> \"pricing.md\"\n }\n\n function routeToMdFsPath(distDir, route) {\n const rel = routeToMdWebPath(route); // already relative\n if (options.output.mode === \"subdir\") {\n return path.join(distDir, options.output.subdir, rel);\n }\n return path.join(distDir, rel);\n }\n\n /** Convert a route to its expected HTML file path in dist */\n function routeToHtmlFsPath(distDir, route) {\n if (route === \"/\") return path.join(distDir, \"index.html\");\n if (route.endsWith(\"/\")) return path.join(distDir, route.slice(1), \"index.html\");\n // Try both /route.html and /route/index.html\n return path.join(distDir, route.slice(1) + \".html\");\n }\n\n function makeLlmsLink(relMdPath) {\n // Use relative links (no leading slash) so it works in subpath deployments.\n // If subdir mode: links should include \"ai/...\"\n return relMdPath.replace(/\\\\/g, \"/\");\n }\n\n async function safeCloseHttpServer(server) {\n await new Promise((resolve, reject) => {\n server.close((err) => (err ? reject(err) : resolve()));\n });\n }\n\n /** Determine if we should use static mode */\n function shouldUseStaticMode() {\n if (options.static === true) return true;\n if (options.static === false) return false;\n // \"auto\" mode: use static when crawl is disabled\n return !options.crawl?.enabled;\n }\n\n return {\n name: \"vite-plugin-llm-spider\",\n apply: \"build\",\n\n configResolved(rc) {\n resolvedConfig = rc;\n },\n\n async closeBundle() {\n if (!options.enabled) return;\n if (!resolvedConfig)\n throw new Error(\"LLM Spider: missing resolved Vite config\");\n\n const distDir = resolvedConfig.build.outDir || \"dist\";\n const basePath = (resolvedConfig.base || \"/\").replace(/\\\\/g, \"/\");\n const useStaticMode = shouldUseStaticMode();\n\n // ---- Resolve route list ----\n /** @type {RouteDef[]} */\n let routeDefs = [];\n\n if (Array.isArray(options.routes) && options.routes.length) {\n routeDefs = options.routes.map((r) => ({\n path: normalizeRoute(r.path, { stripQuery: true }) || \"/\",\n title: r.title,\n section: r.section || \"Pages\",\n optional: !!r.optional,\n notes: r.notes,\n }));\n } else if (options.crawl?.enabled) {\n // Crawl mode: route defs will be created as discovered.\n routeDefs = [];\n } else {\n // Default minimal route\n routeDefs = [{ path: \"/\", section: \"Pages\" }];\n }\n\n log.info(`\\nLLM Spider: generating markdown + llms.txt (${useStaticMode ? 'static' : 'browser'} mode)`);\n log.debug(\"distDir:\", distDir, \"base:\", basePath);\n\n const turndown = new TurndownService(options.markdown.turndown);\n turndown.use(gfm);\n\n /** @type {{ route: string, title?: string, section: string, optional: boolean, notes?: string, mdRelPath: string }[]} */\n const captured = [];\n\n // ============================================\n // STATIC MODE: Read HTML files directly\n // ============================================\n if (useStaticMode) {\n log.debug(\"Using static mode - reading HTML files directly from dist/\");\n\n for (const rd of routeDefs) {\n const route = rd.path;\n if (isExcluded(route)) continue;\n\n // Try to find the HTML file\n let htmlPath = routeToHtmlFsPath(distDir, route);\n let htmlContent = null;\n\n try {\n htmlContent = await fs.readFile(htmlPath, \"utf8\");\n } catch {\n // Try alternate path: /route/index.html\n if (!route.endsWith(\"/\") && route !== \"/\") {\n const altPath = path.join(distDir, route.slice(1), \"index.html\");\n try {\n htmlContent = await fs.readFile(altPath, \"utf8\");\n htmlPath = altPath;\n } catch {\n // Fall back to SPA: all routes serve index.html\n try {\n htmlContent = await fs.readFile(path.join(distDir, \"index.html\"), \"utf8\");\n htmlPath = path.join(distDir, \"index.html\");\n log.debug(` Using SPA fallback index.html for ${route}`);\n } catch {\n log.warn(` ⚠️ No HTML found for ${route}`);\n continue;\n }\n }\n }\n }\n\n if (!htmlContent) continue;\n\n const $ = cheerio.load(htmlContent);\n\n // Remove noisy elements\n for (const sel of options.extract.removeSelectors || [])\n $(sel).remove();\n\n // Pick main content\n const mainSelectors = Array.isArray(options.extract.mainSelector)\n ? options.extract.mainSelector\n : [options.extract.mainSelector];\n\n let mainHtml = null;\n for (const sel of mainSelectors) {\n if (!sel) continue;\n const node = $(sel).first();\n if (node && node.length) {\n mainHtml = node.html();\n break;\n }\n }\n if (!mainHtml) {\n const main = $(\"main\").first();\n mainHtml = main.length ? main.html() : $(\"body\").html();\n }\n\n const title = ($(\"title\").text() || \"\").trim() || route;\n\n // Convert to Markdown\n const markdownBody = turndown.turndown(mainHtml || \"\");\n\n // Write file\n const mdRelPath =\n options.output.mode === \"subdir\"\n ? path.posix.join(options.output.subdir, routeToMdWebPath(route))\n : routeToMdWebPath(route);\n\n const fsPath = routeToMdFsPath(distDir, route);\n await fs.mkdir(path.dirname(fsPath), { recursive: true });\n\n const frontmatter = options.markdown.addFrontmatter\n ? `---\\nsource: ${route}\\ntitle: ${title}\\ngenerated_at: ${new Date().toISOString()}\\n---\\n\\n`\n : \"\";\n\n await fs.writeFile(fsPath, frontmatter + markdownBody, \"utf8\");\n\n captured.push({\n route,\n title: rd.title || title,\n section: rd.section || \"Pages\",\n optional: !!rd.optional,\n notes: rd.notes,\n mdRelPath,\n });\n\n log.info(` ✅ ${route} -> ${mdRelPath}`);\n }\n }\n // ============================================\n // BROWSER MODE: Use Puppeteer for rendering\n // ============================================\n else {\n // ---- Start preview server for built output ----\n const previewServer = await preview({\n root: resolvedConfig.root,\n base: resolvedConfig.base,\n build: { outDir: distDir },\n preview: { port: 0, open: false, host: '127.0.0.1' },\n configFile: false,\n plugins: [],\n logLevel: \"silent\",\n });\n\n // Wait for server to be fully listening\n await new Promise((resolve, reject) => {\n const server = previewServer.httpServer;\n if (server.listening) {\n resolve();\n } else {\n server.once('listening', resolve);\n server.once('error', reject);\n setTimeout(() => reject(new Error('Preview server failed to start')), 5000);\n }\n });\n\n const addr = previewServer.httpServer.address();\n if (!addr || typeof addr === \"string\") {\n await safeCloseHttpServer(previewServer.httpServer);\n throw new Error(\"LLM Spider: could not determine preview server port\");\n }\n\n const normalizedBase = basePath.endsWith(\"/\") ? basePath : basePath + \"/\";\n const baseUrl = `http://127.0.0.1:${addr.port}${normalizedBase}`;\n\n log.debug(\"Preview server at:\", baseUrl);\n\n const pup = await loadPuppeteer();\n const browser = await pup.launch(options.render.launchOptions);\n\n /** @type {Set<string>} */\n const visited = new Set();\n\n // Crawl queue stores base-relative routes (no base prefix)\n /** @type {{ route: string, depth: number }[]} */\n const queue = [];\n\n // Seed queue\n if (options.crawl?.enabled) {\n for (const seed of options.crawl.seeds || [\"/\"]) {\n const nr = normalizeRoute(seed, {\n stripQuery: options.crawl.stripQuery,\n });\n if (nr) queue.push({ route: nr, depth: 0 });\n }\n } else {\n for (const rd of routeDefs) queue.push({ route: rd.path, depth: 0 });\n }\n\n const maxDepth = options.crawl?.enabled ? options.crawl.maxDepth : 0;\n const maxPages = options.crawl?.enabled\n ? options.crawl.maxPages\n : queue.length;\n const concurrency = options.crawl?.enabled\n ? options.crawl.concurrency\n : 3;\n\n async function captureOne(route) {\n if (visited.has(route)) return;\n if (isExcluded(route)) return;\n if (captured.length >= maxPages) return;\n\n visited.add(route);\n\n const page = await browser.newPage();\n\n // Request blocking (best effort)\n if (options.render.blockRequests?.length) {\n await page.setRequestInterception(true);\n page.on(\"request\", (req) => {\n const url = req.url();\n const blocked = options.render.blockRequests.some((p) =>\n p instanceof RegExp ? p.test(url) : url.includes(p),\n );\n if (blocked) req.abort();\n else req.continue();\n });\n }\n\n try {\n const pageUrl =\n route === \"/\" ? baseUrl : baseUrl + route.replace(/^\\//, \"\");\n await options.render.beforeGoto(page, { route });\n\n await page.goto(pageUrl, {\n waitUntil: options.render.waitUntil,\n timeout: options.render.timeoutMs,\n });\n\n if (options.render.waitForSelector) {\n await page.waitForSelector(options.render.waitForSelector, {\n timeout: options.render.timeoutMs,\n });\n }\n\n if (options.render.postLoadDelayMs > 0) {\n await new Promise((r) =>\n setTimeout(r, options.render.postLoadDelayMs),\n );\n }\n\n await options.render.beforeExtract(page, { route });\n\n const html = await page.content();\n const $ = cheerio.load(html);\n\n // Harvest links BEFORE removing nav elements (for crawl mode)\n let harvestedHrefs = [];\n if (options.crawl?.enabled) {\n harvestedHrefs = $(\"a[href]\")\n .map((_, a) => $(a).attr(\"href\"))\n .get();\n log.debug(` Found ${harvestedHrefs.length} links on ${route}:`, harvestedHrefs.slice(0, 15));\n }\n\n // Remove noisy elements (CSS selectors)\n for (const sel of options.extract.removeSelectors || [])\n $(sel).remove();\n\n // Pick main content\n const mainSelectors = Array.isArray(options.extract.mainSelector)\n ? options.extract.mainSelector\n : [options.extract.mainSelector];\n\n let mainHtml = null;\n for (const sel of mainSelectors) {\n if (!sel) continue;\n const node = $(sel).first();\n if (node && node.length) {\n mainHtml = node.html();\n break;\n }\n }\n if (!mainHtml) {\n const main = $(\"main\").first();\n mainHtml = main.length ? main.html() : $(\"body\").html();\n }\n\n const title = ($(\"title\").text() || \"\").trim() || route;\n\n // Convert to Markdown\n const markdownBody = turndown.turndown(mainHtml || \"\");\n\n // Write file\n const mdRelPath =\n options.output.mode === \"subdir\"\n ? path.posix.join(options.output.subdir, routeToMdWebPath(route))\n : routeToMdWebPath(route);\n\n const fsPath = routeToMdFsPath(distDir, route);\n await fs.mkdir(path.dirname(fsPath), { recursive: true });\n\n const frontmatter = options.markdown.addFrontmatter\n ? `---\\nsource: ${route}\\ntitle: ${title}\\ngenerated_at: ${new Date().toISOString()}\\n---\\n\\n`\n : \"\";\n\n await fs.writeFile(fsPath, frontmatter + markdownBody, \"utf8\");\n\n // Map metadata\n const meta = routeDefs.find((r) => r.path === route);\n captured.push({\n route,\n title: meta?.title || title,\n section: meta?.section || \"Pages\",\n optional: !!meta?.optional,\n notes: meta?.notes,\n mdRelPath,\n });\n\n log.info(` ✅ ${route} -> ${mdRelPath}`);\n\n // Harvest links (crawl mode only)\n if (options.crawl?.enabled) {\n for (const href of harvestedHrefs) {\n const n = normalizeRoute(href, {\n stripQuery: options.crawl.stripQuery,\n });\n if (!n) continue;\n\n let baseRelative = n;\n if (\n normalizedBase !== \"/\" &&\n baseRelative.startsWith(normalizedBase)\n ) {\n baseRelative = \"/\" + baseRelative.slice(normalizedBase.length);\n baseRelative =\n baseRelative === \"//\"\n ? \"/\"\n : baseRelative.replace(/\\/{2,}/g, \"/\");\n }\n\n if (!visited.has(baseRelative) && !isExcluded(baseRelative)) {\n queue.push({ route: baseRelative, depth: -1 });\n }\n }\n }\n } catch (err) {\n log.warn(` ⚠️ failed ${route}: ${err?.message || err}`);\n } finally {\n await page.close();\n }\n }\n\n try {\n // BFS: process queue in batches\n while (queue.length && captured.length < maxPages) {\n const batch = queue.splice(0, concurrency).map((item) => {\n const depth = item.depth >= 0 ? item.depth : 1;\n return { route: item.route, depth };\n });\n\n await Promise.all(\n batch.map(async ({ route, depth }) => {\n if (options.crawl?.enabled && depth > maxDepth) return;\n await captureOne(route);\n\n if (options.crawl?.enabled) {\n for (let i = 0; i < queue.length; i++) {\n if (queue[i].depth === -1) queue[i].depth = depth + 1;\n }\n }\n }),\n );\n }\n } finally {\n await browser.close();\n await safeCloseHttpServer(previewServer.httpServer);\n }\n }\n\n // ---- Generate llms.txt ----\n const llmsTitle =\n options.output.llmsTitle || resolvedConfig?.env?.mode || \"Site\";\n\n // Deterministic ordering\n const items = options.output.sort\n ? [...captured].sort((a, b) => a.route.localeCompare(b.route))\n : captured;\n\n // Group by section\n /** @type {Map<string, typeof items>} */\n const bySection = new Map();\n /** @type {typeof items} */\n const optionalItems = [];\n\n for (const item of items) {\n if (item.optional) optionalItems.push(item);\n else {\n const s = item.section || \"Pages\";\n bySection.set(s, [...(bySection.get(s) || []), item]);\n }\n }\n\n let llms = `# ${llmsTitle}\\n\\n> ${options.output.llmsSummary}\\n\\n`;\n\n for (const [section, sectionItems] of bySection.entries()) {\n llms += `## ${section}\\n\\n`;\n for (const it of sectionItems) {\n const link = makeLlmsLink(it.mdRelPath);\n const label = it.title || it.route;\n const notes = it.notes ? `: ${it.notes}` : \"\";\n llms += `- [${label}](${link})${notes}\\n`;\n }\n llms += `\\n`;\n }\n\n if (optionalItems.length) {\n llms += `## Optional\\n\\n`;\n for (const it of optionalItems) {\n const link = makeLlmsLink(it.mdRelPath);\n const label = it.title || it.route;\n const notes = it.notes ? `: ${it.notes}` : \"\";\n llms += `- [${label}](${link})${notes}\\n`;\n }\n llms += `\\n`;\n }\n\n const llmsPath = path.join(distDir, options.output.llmsTxtFileName);\n await fs.writeFile(llmsPath, llms, \"utf8\");\n\n log.info(\n `\\nLLM Spider: wrote ${captured.length} markdown pages + ${options.output.llmsTxtFileName}\\n`,\n );\n },\n };\n}\n\n// Named export for CJS compatibility\nexport { llmSpiderPlugin };\n"],"mappings":"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","names":["_a","_b","_c"]}
|
package/package.json
CHANGED