indxel-cli 0.3.1 → 0.4.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/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/detect.ts","../src/store.ts","../src/templates.ts","../src/commands/check.ts","../src/scanner.ts","../src/config.ts","../src/formatter.ts","../src/fixer.ts","../src/commands/crawl.ts","../src/commands/keywords.ts","../src/commands/index.ts","../src/auth.ts","../src/commands/perf.ts","../src/commands/link.ts","../src/bin.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { initCommand } from \"./commands/init.js\";\nimport { checkCommand } from \"./commands/check.js\";\nimport { crawlCommand } from \"./commands/crawl.js\";\nimport { keywordsCommand } from \"./commands/keywords.js\";\nimport { indexCommand } from \"./commands/index.js\";\nimport { perfCommand } from \"./commands/perf.js\";\nimport { linkCommand } from \"./commands/link.js\";\n\nexport function createProgram(): Command {\n const program = new Command();\n\n program\n .name(\"indxel\")\n .description(\"Infrastructure SEO developer-first. ESLint pour le SEO.\")\n .version(\"0.1.0\");\n\n program.addCommand(initCommand);\n program.addCommand(checkCommand);\n program.addCommand(crawlCommand);\n program.addCommand(keywordsCommand);\n program.addCommand(indexCommand);\n program.addCommand(perfCommand);\n program.addCommand(linkCommand);\n\n return program;\n}\n\nexport { initCommand, checkCommand, crawlCommand, keywordsCommand, indexCommand, perfCommand, linkCommand };\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { existsSync } from \"node:fs\";\nimport { writeFile, mkdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { detectProject } from \"../detect.js\";\nimport { generateIndexNowKey, saveIndexNowKey, loadIndexNowKey } from \"../store.js\";\nimport {\n seoConfigTemplate,\n sitemapTemplate,\n robotsTemplate,\n} from \"../templates.js\";\n\nconst PRE_PUSH_HOOK = `#!/bin/sh\n# indxel SEO guard — blocks push if critical SEO errors are found\necho \"\\\\033[36m[indxel]\\\\033[0m Running SEO check before push...\"\nnpx indxel-cli check --ci\nif [ $? -ne 0 ]; then\n echo \"\"\n echo \"\\\\033[31m[indxel] Push blocked — fix SEO errors first.\\\\033[0m\"\n echo \"\\\\033[2m Run 'npx indxel-cli check' for details.\\\\033[0m\"\n exit 1\nfi\n`;\n\nexport const initCommand = new Command(\"init\")\n .description(\"Initialize indxel in your Next.js project\")\n .option(\"--cwd <path>\", \"Project directory\", process.cwd())\n .option(\"--force\", \"Overwrite existing files\", false)\n .option(\"--hook\", \"Install git pre-push hook to block pushes on SEO errors\", false)\n .action(async (opts) => {\n const cwd = opts.cwd;\n const spinner = ora(\"Detecting project...\").start();\n\n // 1. Detect project\n const project = await detectProject(cwd);\n\n if (!project.isNextJs) {\n spinner.fail(\"Not a Next.js project\");\n console.log(\n chalk.dim(\" indxel currently supports Next.js projects only.\"),\n );\n console.log(\n chalk.dim(\" Make sure you're in a directory with a next.config file.\"),\n );\n process.exit(1);\n }\n\n spinner.succeed(\n `Detected Next.js ${project.nextVersion ?? \"\"} (${project.usesAppRouter ? \"App Router\" : \"Pages Router\"})`,\n );\n\n const ext = project.isTypeScript ? \"ts\" : \"js\";\n const filesCreated: string[] = [];\n\n // 2. Generate seo.config.ts\n if (!project.hasSeoConfig || opts.force) {\n const configPath = join(cwd, `seo.config.${ext}`);\n await writeFile(configPath, seoConfigTemplate(project.isTypeScript), \"utf-8\");\n filesCreated.push(`seo.config.${ext}`);\n console.log(chalk.green(\" ✓\") + ` Generated seo.config.${ext}`);\n } else {\n console.log(chalk.dim(` - seo.config.${ext} already exists (skip)`));\n }\n\n // 3. Generate sitemap.ts\n if (!project.hasSitemap || opts.force) {\n const sitemapPath = join(cwd, project.appDir, `sitemap.${ext}`);\n await writeFile(sitemapPath, sitemapTemplate(project.isTypeScript), \"utf-8\");\n filesCreated.push(`${project.appDir}/sitemap.${ext}`);\n console.log(chalk.green(\" ✓\") + ` Generated ${project.appDir}/sitemap.${ext}`);\n } else {\n console.log(chalk.dim(` - sitemap already exists (skip)`));\n }\n\n // 4. Generate robots.ts\n if (!project.hasRobots || opts.force) {\n const robotsPath = join(cwd, project.appDir, `robots.${ext}`);\n await writeFile(robotsPath, robotsTemplate(project.isTypeScript), \"utf-8\");\n filesCreated.push(`${project.appDir}/robots.${ext}`);\n console.log(chalk.green(\" ✓\") + ` Generated ${project.appDir}/robots.${ext}`);\n } else {\n console.log(chalk.dim(` - robots already exists (skip)`));\n }\n\n // 5. Git pre-push hook\n const gitDir = join(cwd, \".git\");\n const hasGit = existsSync(gitDir);\n\n if (opts.hook || opts.force) {\n if (!hasGit) {\n console.log(chalk.yellow(\" ⚠\") + \" No .git directory found — skip hook install\");\n } else {\n const hooksDir = join(gitDir, \"hooks\");\n const hookPath = join(hooksDir, \"pre-push\");\n\n // Check if a pre-push hook already exists\n if (existsSync(hookPath) && !opts.force) {\n const existing = await readFile(hookPath, \"utf-8\");\n if (existing.includes(\"indxel\")) {\n console.log(chalk.dim(\" - pre-push hook already installed (skip)\"));\n } else {\n console.log(chalk.yellow(\" ⚠\") + \" pre-push hook already exists (use --force to overwrite)\");\n }\n } else {\n await mkdir(hooksDir, { recursive: true });\n await writeFile(hookPath, PRE_PUSH_HOOK, { mode: 0o755 });\n filesCreated.push(\".git/hooks/pre-push\");\n console.log(chalk.green(\" ✓\") + \" Installed git pre-push hook\");\n }\n }\n } else if (hasGit) {\n console.log(chalk.dim(\" - Use --hook to install git pre-push guard\"));\n }\n\n // 6. IndexNow — zero-friction setup\n const existingKey = await loadIndexNowKey(cwd);\n if (!existingKey || opts.force) {\n const key = generateIndexNowKey();\n const publicDir = join(cwd, \"public\");\n if (!existsSync(publicDir)) {\n await mkdir(publicDir, { recursive: true });\n }\n await writeFile(join(publicDir, `${key}.txt`), key, \"utf-8\");\n await saveIndexNowKey(cwd, key);\n filesCreated.push(`public/${key}.txt`);\n console.log(chalk.green(\" ✓\") + \" IndexNow ready — Bing, Yandex & Naver will pick up your pages on deploy\");\n } else {\n // Key exists — make sure the public file is there too\n const keyFile = join(cwd, \"public\", `${existingKey}.txt`);\n if (existsSync(keyFile)) {\n console.log(chalk.dim(\" - IndexNow already set up (skip)\"));\n } else {\n const publicDir = join(cwd, \"public\");\n if (!existsSync(publicDir)) {\n await mkdir(publicDir, { recursive: true });\n }\n await writeFile(keyFile, existingKey, \"utf-8\");\n filesCreated.push(`public/${existingKey}.txt`);\n console.log(chalk.green(\" ✓\") + \" IndexNow key file restored\");\n }\n }\n\n // 7. Summary\n console.log(\"\");\n if (filesCreated.length > 0) {\n console.log(\n chalk.bold(` ${filesCreated.length} file${filesCreated.length > 1 ? \"s\" : \"\"} created.`),\n );\n } else {\n console.log(chalk.dim(\" Nothing to create — all files already exist.\"));\n console.log(chalk.dim(\" Use --force to overwrite.\"));\n }\n\n console.log(\"\");\n console.log(chalk.dim(\" Next steps:\"));\n console.log(chalk.dim(` 1. Edit seo.config.${ext} with your site details`));\n console.log(chalk.dim(\" 2. Run \") + chalk.bold(\"npx indxel check\") + chalk.dim(\" to audit your pages\"));\n if (!opts.hook && hasGit) {\n console.log(chalk.dim(\" 3. Run \") + chalk.bold(\"npx indxel init --hook\") + chalk.dim(\" to guard git pushes\"));\n }\n console.log(\"\");\n console.log(chalk.dim(\" Want continuous monitoring?\"));\n console.log(chalk.dim(\" Run \") + chalk.bold(\"npx indxel link\") + chalk.dim(\" to connect your dashboard.\"));\n console.log(\"\");\n });\n","import { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface ProjectInfo {\n /** Root directory of the project */\n root: string;\n /** Whether this is a Next.js project */\n isNextJs: boolean;\n /** Next.js version if detected */\n nextVersion?: string;\n /** Whether it uses App Router (has src/app or app directory) */\n usesAppRouter: boolean;\n /** The app directory path (relative) */\n appDir: string;\n /** Whether TypeScript is used */\n isTypeScript: boolean;\n /** Whether seo.config.ts/js already exists */\n hasSeoConfig: boolean;\n /** Whether sitemap.ts/js exists */\n hasSitemap: boolean;\n /** Whether robots.ts/js exists */\n hasRobots: boolean;\n}\n\n/** Detect project type and configuration from the given directory. */\nexport async function detectProject(cwd: string): Promise<ProjectInfo> {\n const info: ProjectInfo = {\n root: cwd,\n isNextJs: false,\n usesAppRouter: false,\n appDir: \"app\",\n isTypeScript: false,\n hasSeoConfig: false,\n hasSitemap: false,\n hasRobots: false,\n };\n\n // Check for Next.js config files\n const nextConfigs = [\n \"next.config.ts\",\n \"next.config.js\",\n \"next.config.mjs\",\n \"next.config.cjs\",\n ];\n info.isNextJs = nextConfigs.some((f) => existsSync(join(cwd, f)));\n\n // Read Next.js version from package.json\n const pkgPath = join(cwd, \"package.json\");\n if (existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(await readFile(pkgPath, \"utf-8\"));\n const nextDep = pkg.dependencies?.next ?? pkg.devDependencies?.next;\n if (nextDep) {\n info.isNextJs = true;\n info.nextVersion = nextDep.replace(/[\\^~>=<]/g, \"\").trim();\n }\n } catch {\n // Ignore parse errors\n }\n }\n\n // Check for TypeScript\n info.isTypeScript =\n existsSync(join(cwd, \"tsconfig.json\")) ||\n existsSync(join(cwd, \"tsconfig.ts\"));\n\n // Detect App Router directory\n if (existsSync(join(cwd, \"src\", \"app\"))) {\n info.usesAppRouter = true;\n info.appDir = \"src/app\";\n } else if (existsSync(join(cwd, \"app\"))) {\n info.usesAppRouter = true;\n info.appDir = \"app\";\n }\n\n // Check for existing SEO files (check both .ts and .js regardless of project type)\n info.hasSeoConfig =\n existsSync(join(cwd, \"seo.config.ts\")) ||\n existsSync(join(cwd, \"seo.config.js\"));\n\n info.hasSitemap =\n existsSync(join(cwd, info.appDir, \"sitemap.ts\")) ||\n existsSync(join(cwd, info.appDir, \"sitemap.js\")) ||\n existsSync(join(cwd, info.appDir, \"sitemap.xml\"));\n\n info.hasRobots =\n existsSync(join(cwd, info.appDir, \"robots.ts\")) ||\n existsSync(join(cwd, info.appDir, \"robots.js\")) ||\n existsSync(join(cwd, info.appDir, \"robots.txt\"));\n\n return info;\n}\n","import { existsSync } from \"node:fs\";\nimport { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { randomBytes } from \"node:crypto\";\nimport type { CheckSummary } from \"./formatter.js\";\n\nconst STORE_DIR = \".indxel\";\nconst LAST_CHECK_FILE = \"last-check.json\";\nconst INDEXNOW_KEY_FILE = \"indexnow-key.txt\";\nconst CONFIG_FILE = \"config.json\";\n\nexport interface StoredCheck {\n timestamp: string;\n summary: CheckSummary;\n}\n\n/** Save the current check results for future diff comparison */\nexport async function saveCheckResult(\n cwd: string,\n summary: CheckSummary,\n): Promise<void> {\n const storeDir = join(cwd, STORE_DIR);\n\n if (!existsSync(storeDir)) {\n await mkdir(storeDir, { recursive: true });\n }\n\n const stored: StoredCheck = {\n timestamp: new Date().toISOString(),\n summary: {\n ...summary,\n // Serialize results with minimal data needed for diff\n results: summary.results.map((r) => ({\n page: {\n filePath: r.page.filePath,\n route: r.page.route,\n hasMetadata: r.page.hasMetadata,\n hasDynamicMetadata: r.page.hasDynamicMetadata,\n isClientComponent: r.page.isClientComponent,\n titleIsAbsolute: r.page.titleIsAbsolute,\n extractedMetadata: r.page.extractedMetadata,\n },\n validation: r.validation,\n })),\n },\n };\n\n await writeFile(\n join(storeDir, LAST_CHECK_FILE),\n JSON.stringify(stored, null, 2),\n \"utf-8\",\n );\n}\n\n/** Load the previous check result (or null if none exists) */\nexport async function loadPreviousCheck(\n cwd: string,\n): Promise<StoredCheck | null> {\n const filePath = join(cwd, STORE_DIR, LAST_CHECK_FILE);\n\n if (!existsSync(filePath)) {\n return null;\n }\n\n try {\n const data = await readFile(filePath, \"utf-8\");\n return JSON.parse(data) as StoredCheck;\n } catch {\n return null;\n }\n}\n\n/** Get the .indxel directory path */\nexport function getStoreDir(cwd: string): string {\n return join(cwd, STORE_DIR);\n}\n\n/** Generate a 32-character hex IndexNow key */\nexport function generateIndexNowKey(): string {\n return randomBytes(16).toString(\"hex\");\n}\n\n/** Save an IndexNow key to the .indxel store */\nexport async function saveIndexNowKey(cwd: string, key: string): Promise<void> {\n const storeDir = join(cwd, STORE_DIR);\n if (!existsSync(storeDir)) {\n await mkdir(storeDir, { recursive: true });\n }\n await writeFile(join(storeDir, INDEXNOW_KEY_FILE), key, \"utf-8\");\n}\n\n/** Load the IndexNow key from the .indxel store (or null if not set up) */\nexport async function loadIndexNowKey(cwd: string): Promise<string | null> {\n const filePath = join(cwd, STORE_DIR, INDEXNOW_KEY_FILE);\n if (!existsSync(filePath)) return null;\n try {\n const key = (await readFile(filePath, \"utf-8\")).trim();\n return key || null;\n } catch {\n return null;\n }\n}\n\n// --- Project config (set by `npx indxel link`) ---\n\nexport interface ProjectConfig {\n apiKey: string;\n projectId: string;\n projectName: string;\n linkedAt: string;\n}\n\n/** Save project config after linking */\nexport async function saveProjectConfig(\n cwd: string,\n config: ProjectConfig,\n): Promise<void> {\n const storeDir = join(cwd, STORE_DIR);\n if (!existsSync(storeDir)) {\n await mkdir(storeDir, { recursive: true });\n }\n await writeFile(\n join(storeDir, CONFIG_FILE),\n JSON.stringify(config, null, 2),\n \"utf-8\",\n );\n}\n\n/** Load project config (or null if not linked) */\nexport async function loadProjectConfig(\n cwd: string,\n): Promise<ProjectConfig | null> {\n const filePath = join(cwd, STORE_DIR, CONFIG_FILE);\n if (!existsSync(filePath)) return null;\n try {\n const data = await readFile(filePath, \"utf-8\");\n return JSON.parse(data) as ProjectConfig;\n } catch {\n return null;\n }\n}\n\n/**\n * Resolve API key from multiple sources (in priority order):\n * 1. Explicit --api-key flag\n * 2. INDXEL_API_KEY environment variable\n * 3. .indxel/config.json (set by `npx indxel link`)\n */\nexport async function resolveApiKey(\n explicit?: string,\n): Promise<string | null> {\n if (explicit) return explicit;\n if (process.env.INDXEL_API_KEY) return process.env.INDXEL_API_KEY;\n const config = await loadProjectConfig(process.cwd());\n return config?.apiKey ?? null;\n}\n","/** Generate the seo.config.ts template */\nexport function seoConfigTemplate(isTypeScript: boolean): string {\n if (isTypeScript) {\n return `import { defineSEO } from 'indxel'\n\nexport default defineSEO({\n siteName: 'My Site',\n siteUrl: 'https://example.com',\n titleTemplate: '%s | My Site',\n defaultDescription: 'A short description of your site for search engines.',\n defaultOGImage: '/og-image.png',\n locale: 'en_US',\n // twitter: {\n // handle: '@yourhandle',\n // cardType: 'summary_large_image',\n // },\n // organization: {\n // name: 'My Company',\n // logo: '/logo.png',\n // url: 'https://example.com',\n // },\n})\n`;\n }\n\n return `const { defineSEO } = require('indxel')\n\nmodule.exports = defineSEO({\n siteName: 'My Site',\n siteUrl: 'https://example.com',\n titleTemplate: '%s | My Site',\n defaultDescription: 'A short description of your site for search engines.',\n defaultOGImage: '/og-image.png',\n locale: 'en_US',\n})\n`;\n}\n\n/** Generate the sitemap.ts template */\nexport function sitemapTemplate(isTypeScript: boolean): string {\n if (isTypeScript) {\n return `import type { MetadataRoute } from 'next'\n\nexport default function sitemap(): MetadataRoute.Sitemap {\n const baseUrl = 'https://example.com'\n\n return [\n {\n url: baseUrl,\n lastModified: new Date(),\n changeFrequency: 'weekly',\n priority: 1,\n },\n // Add more pages here or generate dynamically:\n //\n // const posts = await getPosts()\n // return posts.map(post => ({\n // url: \\`\\${baseUrl}/blog/\\${post.slug}\\`,\n // lastModified: post.updatedAt,\n // changeFrequency: 'monthly',\n // priority: 0.7,\n // }))\n ]\n}\n`;\n }\n\n return `/** @returns {import('next').MetadataRoute.Sitemap} */\nexport default function sitemap() {\n const baseUrl = 'https://example.com'\n\n return [\n {\n url: baseUrl,\n lastModified: new Date(),\n changeFrequency: 'weekly',\n priority: 1,\n },\n ]\n}\n`;\n}\n\n/** Generate the robots.ts template */\nexport function robotsTemplate(isTypeScript: boolean): string {\n if (isTypeScript) {\n return `import type { MetadataRoute } from 'next'\n\nexport default function robots(): MetadataRoute.Robots {\n const baseUrl = 'https://example.com'\n\n return {\n rules: [\n {\n userAgent: '*',\n allow: '/',\n disallow: ['/api/', '/private/'],\n },\n ],\n sitemap: \\`\\${baseUrl}/sitemap.xml\\`,\n }\n}\n`;\n }\n\n return `/** @returns {import('next').MetadataRoute.Robots} */\nexport default function robots() {\n const baseUrl = 'https://example.com'\n\n return {\n rules: [\n {\n userAgent: '*',\n allow: '/',\n disallow: ['/api/', '/private/'],\n },\n ],\n sitemap: \\`\\${baseUrl}/sitemap.xml\\`,\n }\n}\n`;\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { validateMetadata } from \"indxel\";\nimport { detectProject } from \"../detect.js\";\nimport { scanPages } from \"../scanner.js\";\nimport { loadConfig } from \"../config.js\";\nimport {\n formatPageResult,\n formatSkippedPage,\n formatSummary,\n formatJSON,\n formatDiff,\n computeSummary,\n type CheckResult,\n} from \"../formatter.js\";\nimport { saveCheckResult, loadPreviousCheck } from \"../store.js\";\nimport { generateFixSuggestions } from \"../fixer.js\";\n\nexport const checkCommand = new Command(\"check\")\n .description(\"Audit SEO metadata for all pages in your project\")\n .option(\"--cwd <path>\", \"Project directory\", process.cwd())\n .option(\"--ci\", \"CI/CD mode — strict, exit 1 on any error\", false)\n .option(\"--diff\", \"Compare with previous check run\", false)\n .option(\"--json\", \"Output results as JSON\", false)\n .option(\"--strict\", \"Treat warnings as errors\", false)\n .option(\"--min-score <score>\", \"Minimum score to pass (0-100, default: exit on any error)\")\n .option(\"--fix\", \"Show suggested metadata code to fix errors\", false)\n .action(async (opts) => {\n const cwd = opts.cwd;\n const isCI = opts.ci;\n const isStrict = opts.strict || isCI;\n const showDiff = opts.diff;\n const jsonOutput = opts.json;\n const showFix = opts.fix;\n\n // Load config file (.indxelrc.json, etc.)\n const config = await loadConfig(cwd);\n\n // --min-score flag overrides config, config overrides default\n const minScore = opts.minScore\n ? parseInt(opts.minScore, 10)\n : config.minScore ?? null;\n\n // 1. Detect project\n const spinner = ora(\"Detecting project...\").start();\n const project = await detectProject(cwd);\n\n if (!project.isNextJs) {\n spinner.fail(\"Not a Next.js project\");\n if (!jsonOutput) {\n console.log(chalk.dim(\" Run this command from a Next.js project root.\"));\n }\n process.exit(1);\n }\n\n if (!project.usesAppRouter) {\n spinner.fail(\"App Router not detected\");\n if (!jsonOutput) {\n console.log(chalk.dim(\" indxel requires Next.js App Router (src/app or app directory).\"));\n }\n process.exit(1);\n }\n\n // 2. Scan pages\n spinner.text = \"Scanning pages...\";\n const allPages = await scanPages(cwd, project.appDir);\n\n if (allPages.length === 0) {\n spinner.fail(\"No pages found\");\n if (!jsonOutput) {\n console.log(chalk.dim(` No page.tsx/ts files found in ${project.appDir}/`));\n }\n process.exit(1);\n }\n\n // Filter out ignored routes\n const ignoreRoutes = config.ignoreRoutes ?? [];\n const pages = ignoreRoutes.length > 0\n ? allPages.filter((p) => !ignoreRoutes.some((pattern) => matchRoute(p.route, pattern)))\n : allPages;\n const ignoredCount = allPages.length - pages.length;\n\n spinner.succeed(`Found ${allPages.length} page${allPages.length > 1 ? \"s\" : \"\"}${ignoredCount > 0 ? ` (${ignoredCount} ignored)` : \"\"}`);\n\n // 3. Separate static vs dynamic pages\n const staticPages = pages.filter((p) => !p.hasDynamicMetadata);\n const dynamicPages = pages.filter((p) => p.hasDynamicMetadata);\n\n if (!jsonOutput) {\n console.log(\"\");\n console.log(chalk.bold(` Checking ${staticPages.length} page${staticPages.length !== 1 ? \"s\" : \"\"}...`));\n if (dynamicPages.length > 0) {\n console.log(chalk.dim(` (${dynamicPages.length} dynamic page${dynamicPages.length !== 1 ? \"s\" : \"\"} skipped)`));\n }\n if (ignoredCount > 0) {\n console.log(chalk.dim(` (${ignoredCount} page${ignoredCount !== 1 ? \"s\" : \"\"} excluded by ignoreRoutes)`));\n }\n console.log(\"\");\n }\n\n // 4. Validate static pages only\n const results: CheckResult[] = [];\n\n for (const page of staticPages) {\n const validation = validateMetadata(page.extractedMetadata, {\n strict: isStrict,\n disabledRules: config.disabledRules,\n });\n\n const result: CheckResult = { page, validation };\n results.push(result);\n\n if (!jsonOutput) {\n console.log(formatPageResult(result));\n }\n }\n\n // Show skipped dynamic pages\n if (!jsonOutput && dynamicPages.length > 0) {\n console.log(\"\");\n for (const page of dynamicPages) {\n console.log(formatSkippedPage(page));\n }\n }\n\n // 5. Compute summary (score only counts static pages)\n const summary = computeSummary(results, dynamicPages.length);\n\n // 6. Save results for future diff\n await saveCheckResult(cwd, summary);\n\n // 7. Show diff if requested\n if (showDiff && !jsonOutput) {\n const previous = await loadPreviousCheck(cwd);\n if (previous) {\n console.log(formatDiff(summary, previous.summary));\n } else {\n console.log(chalk.dim(\"\\n No previous check found. Run again to see a diff.\\n\"));\n }\n }\n\n // 8. Output\n if (jsonOutput) {\n console.log(formatJSON(summary));\n } else {\n console.log(formatSummary(summary));\n }\n\n // 9. Show fix suggestions if requested\n if (showFix && !jsonOutput) {\n const fixes = generateFixSuggestions(results, config.baseUrl);\n if (fixes.length > 0) {\n console.log(chalk.bold(\" Suggested fixes:\\n\"));\n for (const fix of fixes) {\n console.log(fix);\n }\n }\n }\n\n // 10. Exit code\n if (minScore !== null) {\n // --min-score mode: fail only if score is below threshold\n if (summary.averageScore < minScore) {\n if (!jsonOutput) {\n console.log(\n chalk.red(` Score ${summary.averageScore} is below minimum ${minScore}.`),\n );\n }\n process.exit(1);\n }\n } else if (summary.criticalErrors > 0) {\n // Default mode: fail on any error\n process.exit(1);\n }\n });\n\n/** Match a route against a pattern with simple glob support.\n * Supports trailing /* for prefix matching (e.g., \"/dashboard/*\" matches \"/dashboard/settings\"). */\nfunction matchRoute(route: string, pattern: string): boolean {\n if (pattern.endsWith(\"/*\")) {\n const prefix = pattern.slice(0, -2);\n return route === prefix || route.startsWith(prefix + \"/\");\n }\n return route === pattern;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join, relative, dirname, sep } from \"node:path\";\nimport { glob } from \"glob\";\nimport type { ResolvedMetadata } from \"indxel\";\n\nexport interface PageInfo {\n /** File path relative to project root */\n filePath: string;\n /** Route path (e.g., \"/blog/[slug]\") */\n route: string;\n /** Whether the page exports metadata or generateMetadata */\n hasMetadata: boolean;\n /** Whether the page exports generateMetadata (dynamic) */\n hasDynamicMetadata: boolean;\n /** Whether the page is a client component ('use client') */\n isClientComponent: boolean;\n /** Whether the title uses absolute: (skip template) */\n titleIsAbsolute: boolean;\n /** Extracted static metadata fields (best effort from source parsing) */\n extractedMetadata: ResolvedMetadata;\n}\n\n/**\n * Scan the app directory for all page files and extract metadata info.\n * This does static analysis of the source code (no build required).\n */\nexport async function scanPages(\n projectRoot: string,\n appDir: string,\n): Promise<PageInfo[]> {\n const appDirFull = join(projectRoot, appDir);\n\n // Find all page.tsx/page.ts/page.jsx/page.js files\n const pageFiles = await glob(\"**/page.{tsx,ts,jsx,js}\", {\n cwd: appDirFull,\n ignore: [\"**/node_modules/**\", \"**/_*/**\"],\n });\n\n const pages: PageInfo[] = [];\n\n for (const file of pageFiles) {\n const fullPath = join(appDirFull, file);\n const content = await readFile(fullPath, \"utf-8\");\n const route = filePathToRoute(file);\n const isClient = isClientComponent(content);\n\n const page: PageInfo = {\n filePath: join(appDir, file),\n route,\n hasMetadata: false,\n hasDynamicMetadata: false,\n isClientComponent: isClient,\n titleIsAbsolute: false,\n extractedMetadata: createEmptyMetadata(),\n };\n\n // Check for metadata exports\n page.hasDynamicMetadata = hasExport(content, \"generateMetadata\");\n page.hasMetadata = page.hasDynamicMetadata || hasExport(content, \"metadata\");\n\n // Extract static metadata (best effort)\n if (page.hasDynamicMetadata) {\n // generateMetadata() pages can't be analyzed statically — regex can't\n // parse function bodies. Leave metadata empty; `indxel crawl` handles these.\n } else if (!isClient || page.hasMetadata) {\n // Skip extraction for client components without metadata export —\n // regex would match JSX content instead of actual metadata\n page.extractedMetadata = extractStaticMetadata(content);\n // Check if the title was from absolute: (no template should be applied)\n const metaBlock = findMetadataBlock(content);\n if (metaBlock && /absolute\\s*:\\s*[\"'`]/.test(metaBlock)) {\n page.titleIsAbsolute = true;\n }\n }\n\n pages.push(page);\n }\n\n // Also check layout files for metadata\n const layoutFiles = await glob(\"**/layout.{tsx,ts,jsx,js}\", {\n cwd: appDirFull,\n ignore: [\"**/node_modules/**\", \"**/_*/**\"],\n });\n\n // Sort layouts by depth descending — deeper layouts get merge priority,\n // root layout fills remaining gaps last\n const sortedLayouts = layoutFiles.sort((a, b) => {\n const depthA = a.split(sep).length;\n const depthB = b.split(sep).length;\n return depthB - depthA;\n });\n\n for (const file of sortedLayouts) {\n const fullPath = join(appDirFull, file);\n const content = await readFile(fullPath, \"utf-8\");\n const route = filePathToRoute(file).replace(/\\/layout$/, \"\") || \"/\";\n\n const hasMetadataExport = hasExport(content, \"metadata\") || hasExport(content, \"generateMetadata\");\n if (hasMetadataExport) {\n const layoutMeta = extractStaticMetadata(content);\n\n // Extract title template from layout for title resolution\n const templateMatch = content.match(/template\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/);\n const titleTemplate = templateMatch?.[1] ?? null;\n\n for (const page of pages) {\n if (page.route.startsWith(route) || route === \"/\") {\n // If the page has its own title (not absolute) and layout has a template, resolve it\n if (page.extractedMetadata.title && titleTemplate && !page.titleIsAbsolute) {\n page.extractedMetadata.title = titleTemplate.replace(\"%s\", page.extractedMetadata.title);\n page.titleIsAbsolute = true; // prevent double-templating from parent layouts\n }\n\n // Merge layout metadata as fallback (page-level takes precedence)\n mergeMetadata(page.extractedMetadata, layoutMeta);\n if (!page.hasMetadata) {\n page.hasMetadata = true;\n }\n }\n }\n }\n }\n\n return pages.sort((a, b) => a.route.localeCompare(b.route));\n}\n\n/** Convert a file path like \"blog/[slug]/page.tsx\" to route \"/blog/[slug]\" */\nfunction filePathToRoute(filePath: string): string {\n const dir = dirname(filePath);\n if (dir === \".\") return \"/\";\n // Normalize separators and add leading slash\n const route = \"/\" + dir.split(sep).join(\"/\");\n // Remove route groups like (marketing)\n return route.replace(/\\/\\([^)]+\\)/g, \"\") || \"/\";\n}\n\n/** Check if the source starts with 'use client' directive */\nfunction isClientComponent(source: string): boolean {\n // Match 'use client' or \"use client\" at the start of the file (ignoring whitespace/comments)\n return /^[\\s]*(['\"])use client\\1/.test(source);\n}\n\n/** Check if source code exports a given name */\nfunction hasExport(source: string, name: string): boolean {\n // Match: export const metadata, export async function generateMetadata, export function generateMetadata\n const patterns = [\n new RegExp(`export\\\\s+(const|let|var)\\\\s+${name}\\\\b`),\n new RegExp(`export\\\\s+(async\\\\s+)?function\\\\s+${name}\\\\b`),\n new RegExp(`export\\\\s+\\\\{[^}]*\\\\b${name}\\\\b[^}]*\\\\}`),\n ];\n return patterns.some((p) => p.test(source));\n}\n\n/**\n * Find the metadata export block in source code using brace-matching.\n * Returns the block content or null if not found.\n */\nfunction findMetadataBlock(source: string): string | null {\n const match = source.match(/export\\s+(const|let|var)\\s+metadata[\\s:]/);\n if (!match || match.index === undefined) return null;\n\n const start = source.indexOf(\"{\", match.index);\n if (start === -1) return null;\n\n let depth = 0;\n for (let i = start; i < source.length; i++) {\n if (source[i] === \"{\") depth++;\n else if (source[i] === \"}\") {\n depth--;\n if (depth === 0) return source.substring(start, i + 1);\n }\n }\n return null;\n}\n\n/**\n * Extract metadata from static `export const metadata = { ... }` patterns.\n * This is best-effort source code parsing (not AST — fast and simple).\n */\nfunction extractStaticMetadata(source: string): ResolvedMetadata {\n const meta = createEmptyMetadata();\n\n // Scope extraction to the metadata export block when possible\n // This prevents matching JSX content or unrelated objects\n const metaBlock = findMetadataBlock(source) ?? source;\n\n // Extract title — handle multiple patterns:\n // 1. title: \"simple string\"\n // 2. title: { absolute: \"...\" }\n // 3. title: { default: \"...\" }\n const absoluteMatch = metaBlock.match(\n /absolute\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/,\n );\n if (absoluteMatch) {\n meta.title = absoluteMatch[1];\n } else {\n const defaultMatch = metaBlock.match(\n /default\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/,\n );\n if (defaultMatch) {\n meta.title = defaultMatch[1];\n } else {\n // Simple title: \"string\" — but only match top-level title, not nested ones\n const titleMatch = metaBlock.match(\n /(?:^|[,{\\n])\\s*title\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/,\n );\n if (titleMatch) {\n meta.title = titleMatch[1];\n }\n }\n }\n\n // Extract description — scope to metadata block\n const descMatch = metaBlock.match(\n /(?:^|[,{\\n])\\s*description\\s*:\\s*\\n?\\s*[\"'`]([^\"'`]+)[\"'`]/,\n );\n if (descMatch) {\n meta.description = descMatch[1];\n }\n\n // Check for openGraph object (scoped to metadata block)\n if (/openGraph\\s*:\\s*\\{/.test(metaBlock)) {\n const ogTitleMatch = metaBlock.match(\n /openGraph\\s*:\\s*\\{[^}]*title\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/s,\n );\n if (ogTitleMatch) meta.ogTitle = ogTitleMatch[1];\n\n const ogDescMatch = metaBlock.match(\n /openGraph\\s*:\\s*\\{[^}]*description\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/s,\n );\n if (ogDescMatch) meta.ogDescription = ogDescMatch[1];\n\n if (/images\\s*:\\s*\\[/.test(metaBlock)) {\n meta.ogImage = \"[detected]\";\n }\n }\n\n // Check for twitter config (scoped to metadata block)\n if (/twitter\\s*:\\s*\\{/.test(metaBlock)) {\n const cardMatch = metaBlock.match(\n /card\\s*:\\s*[\"'`](summary|summary_large_image)[\"'`]/,\n );\n if (cardMatch) meta.twitterCard = cardMatch[1];\n }\n\n // Check for robots (scoped to metadata block)\n if (/robots\\s*:\\s*\\{/.test(metaBlock) || /robots\\s*:\\s*[\"'`]/.test(metaBlock)) {\n const robotsMatch = metaBlock.match(\n /robots\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/,\n );\n if (robotsMatch) meta.robots = robotsMatch[1];\n }\n\n // Check for alternates/canonical (scoped to metadata block)\n if (/alternates\\s*:\\s*\\{/.test(metaBlock)) {\n const canonicalMatch = metaBlock.match(\n /canonical\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/,\n );\n if (canonicalMatch) meta.canonical = canonicalMatch[1];\n\n // Detect hreflang / languages declarations\n if (/languages\\s*:\\s*\\{/.test(metaBlock)) {\n const langs: Record<string, string> = {};\n const langMatches = metaBlock.matchAll(\n /[\"'`](\\w{2}(?:-\\w{2})?)[\"'`]\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/g,\n );\n for (const m of langMatches) {\n if (m[1] && m[2] && m[2].startsWith(\"http\")) {\n langs[m[1]] = m[2];\n }\n }\n if (Object.keys(langs).length > 0) {\n meta.alternates = langs;\n }\n }\n }\n\n // --- Fallback: detect fields set via variable references ---\n // When metadata values come from imported config (e.g., siteConfig.xxx),\n // regex can't extract the string value, but we know the field is present.\n // This is critical for layout-to-page merge to cascade correctly.\n if (!meta.title && /(?:^|[,{\\n])\\s*title\\s*:\\s*(?:\\{|[a-zA-Z_$])/.test(metaBlock)) {\n meta.title = \"[detected]\";\n }\n if (!meta.description && /(?:^|[,{\\n])\\s*description\\s*:\\s*[a-zA-Z_$]/.test(metaBlock)) {\n meta.description = \"[detected]\";\n }\n if (/openGraph\\s*:\\s*\\{/.test(metaBlock)) {\n if (!meta.ogTitle) meta.ogTitle = \"[detected]\";\n if (!meta.ogDescription) meta.ogDescription = \"[detected]\";\n if (!meta.ogImage) meta.ogImage = \"[detected]\";\n }\n if (/twitter\\s*:\\s*\\{/.test(metaBlock)) {\n if (!meta.twitterCard) meta.twitterCard = \"[detected]\";\n }\n if (/alternates\\s*:\\s*\\{/.test(metaBlock) && !meta.canonical) {\n if (/canonical\\s*:/.test(metaBlock)) meta.canonical = \"[detected]\";\n }\n\n // Check for structured data — search full source (JSON-LD can be in JSX, not metadata)\n if (/application\\/ld\\+json/.test(source) || /generateLD/.test(source) || /JsonLD/.test(source)) {\n meta.structuredData = [{ \"@context\": \"https://schema.org\", \"@type\": \"detected\" }];\n }\n\n // Check for viewport — search full source (can be a separate export)\n if (/viewport\\s*[:=]/.test(source)) {\n meta.viewport = \"detected\";\n }\n\n // Check for icons/favicon (scoped to metadata block)\n if (/icons\\s*:\\s*\\{/.test(metaBlock) || /favicon/.test(metaBlock)) {\n meta.favicon = \"detected\";\n }\n\n return meta;\n}\n\nfunction createEmptyMetadata(): ResolvedMetadata {\n return {\n title: null,\n description: null,\n canonical: null,\n ogTitle: null,\n ogDescription: null,\n ogImage: null,\n ogType: null,\n twitterCard: null,\n twitterTitle: null,\n twitterDescription: null,\n robots: null,\n alternates: null,\n structuredData: null,\n viewport: null,\n favicon: null,\n };\n}\n\n/** Merge source metadata into target (target takes precedence if already set) */\nfunction mergeMetadata(target: ResolvedMetadata, source: ResolvedMetadata): void {\n for (const key of Object.keys(source) as (keyof ResolvedMetadata)[]) {\n if (target[key] === null || target[key] === undefined) {\n (target as Record<string, unknown>)[key] = source[key];\n }\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface IndxelConfig {\n /** Minimum score to pass (0-100). Overrides --min-score flag. */\n minScore?: number;\n /** Rule IDs to disable (won't count toward score). */\n disabledRules?: string[];\n /** Base URL for canonical URLs. */\n baseUrl?: string;\n /** Route patterns to exclude from checks (e.g., \"/dashboard/*\", \"/auth/*\"). */\n ignoreRoutes?: string[];\n}\n\nconst CONFIG_FILES = [\".indxelrc.json\", \".indxelrc\", \"indxel.config.json\"];\n\n/**\n * Load indxel config from the project root.\n * Searches for .indxelrc.json, .indxelrc, or indxel.config.json.\n */\nexport async function loadConfig(cwd: string): Promise<IndxelConfig> {\n for (const file of CONFIG_FILES) {\n const path = join(cwd, file);\n if (existsSync(path)) {\n try {\n const content = await readFile(path, \"utf-8\");\n return JSON.parse(content) as IndxelConfig;\n } catch {\n // Invalid JSON — ignore silently\n }\n }\n }\n return {};\n}\n","import chalk from \"chalk\";\nimport type { ValidationResult } from \"indxel\";\nimport type { PageInfo } from \"./scanner.js\";\n\nexport interface CheckResult {\n page: PageInfo;\n validation: ValidationResult;\n}\n\nexport interface CheckSummary {\n results: CheckResult[];\n totalPages: number;\n passedPages: number;\n averageScore: number;\n grade: string;\n /** Errors from critical-severity rules (blocks CI) */\n criticalErrors: number;\n /** Errors from optional-severity rules (score only) */\n optionalErrors: number;\n /** Pages with generateMetadata() skipped from static analysis */\n skippedDynamic: number;\n}\n\n/** Format a single page check result for terminal output */\nexport function formatPageResult(result: CheckResult): string {\n const { page, validation } = result;\n const lines: string[] = [];\n\n const scoreColor = getScoreColor(validation.score);\n const icon = validation.errors.length > 0 ? chalk.red(\"x\") : chalk.green(\"✓\");\n\n lines.push(\n ` ${icon} ${chalk.bold(page.route)} ${scoreColor(`${validation.score}/100`)}`,\n );\n\n // Show errors\n for (const error of validation.errors) {\n lines.push(` ${chalk.red(\"x\")} ${error.message ?? error.name}`);\n }\n\n // Show warnings (only if there are also errors, to reduce noise)\n if (validation.errors.length > 0) {\n for (const warning of validation.warnings) {\n lines.push(` ${chalk.yellow(\"!\")} ${warning.message ?? warning.name}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/** Format the complete check summary for terminal output */\nexport function formatSummary(summary: CheckSummary): string {\n const lines: string[] = [];\n const { totalPages, passedPages, averageScore, criticalErrors } = summary;\n\n lines.push(\"\");\n lines.push(chalk.dim(\" ─────────────────────────────────────\"));\n lines.push(\"\");\n\n // Overall score\n const scoreColor = getScoreColor(averageScore);\n lines.push(\n ` Score: ${scoreColor(chalk.bold(`${averageScore}/100`))} (${summary.grade})`,\n );\n\n // Pages summary\n const pagesColor = passedPages === totalPages ? chalk.green : chalk.yellow;\n lines.push(\n ` Pages: ${pagesColor(`${passedPages}/${totalPages}`)} pass SEO validation`,\n );\n\n // Error count\n if (criticalErrors > 0) {\n lines.push(\"\");\n lines.push(\n chalk.red(` ${criticalErrors} critical issue${criticalErrors > 1 ? \"s\" : \"\"}. Fix before deploying.`),\n );\n if (summary.optionalErrors > 0) {\n lines.push(\n chalk.yellow(` ${summary.optionalErrors} optional issue${summary.optionalErrors > 1 ? \"s\" : \"\"} (won't block CI).`),\n );\n }\n } else if (summary.optionalErrors > 0) {\n lines.push(\"\");\n lines.push(chalk.yellow(` ${summary.optionalErrors} optional issue${summary.optionalErrors > 1 ? \"s\" : \"\"} (won't block CI).`));\n } else {\n lines.push(\"\");\n lines.push(chalk.green(\" All pages pass. Ship it.\"));\n }\n\n // Dynamic pages hint\n if (summary.skippedDynamic > 0) {\n lines.push(\"\");\n lines.push(\n chalk.cyan(\n ` ${summary.skippedDynamic} dynamic page${summary.skippedDynamic > 1 ? \"s\" : \"\"} skipped (generateMetadata).`,\n ),\n );\n lines.push(chalk.dim(\" Run `indxel crawl <url>` for accurate scores on dynamic pages.\"));\n }\n\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n\n/** Format results for --json output */\nexport function formatJSON(summary: CheckSummary): string {\n return JSON.stringify(\n {\n score: summary.averageScore,\n grade: summary.grade,\n totalPages: summary.totalPages,\n passedPages: summary.passedPages,\n criticalErrors: summary.criticalErrors,\n optionalErrors: summary.optionalErrors,\n skippedDynamic: summary.skippedDynamic,\n pages: summary.results.map((r) => ({\n route: r.page.route,\n file: r.page.filePath,\n score: r.validation.score,\n grade: r.validation.grade,\n errors: r.validation.errors.map((e) => ({\n id: e.id,\n message: e.message,\n })),\n warnings: r.validation.warnings.map((w) => ({\n id: w.id,\n message: w.message,\n })),\n })),\n },\n null,\n 2,\n );\n}\n\n/** Format a diff between two check runs */\nexport function formatDiff(\n current: CheckSummary,\n previous: CheckSummary,\n): string {\n const lines: string[] = [];\n\n lines.push(\"\");\n lines.push(chalk.bold(\" SEO Diff:\"));\n lines.push(\"\");\n\n const scoreDelta = current.averageScore - previous.averageScore;\n const scoreArrow = scoreDelta > 0 ? chalk.green(`+${scoreDelta}`) : scoreDelta < 0 ? chalk.red(`${scoreDelta}`) : chalk.dim(\"0\");\n lines.push(\n ` Score: ${previous.averageScore} -> ${current.averageScore} (${scoreArrow})`,\n );\n lines.push(\"\");\n\n // Build route maps\n const prevMap = new Map(previous.results.map((r) => [r.page.route, r]));\n const currMap = new Map(current.results.map((r) => [r.page.route, r]));\n\n // Regressions\n const regressions: string[] = [];\n for (const [route, curr] of currMap) {\n const prev = prevMap.get(route);\n if (!prev) continue;\n if (curr.validation.score < prev.validation.score) {\n regressions.push(\n ` ${chalk.red(\"-\")} ${route} ${prev.validation.score} -> ${curr.validation.score}`,\n );\n }\n }\n\n // Improvements\n const improvements: string[] = [];\n for (const [route, curr] of currMap) {\n const prev = prevMap.get(route);\n if (!prev) continue;\n if (curr.validation.score > prev.validation.score) {\n improvements.push(\n ` ${chalk.green(\"+\")} ${route} ${prev.validation.score} -> ${curr.validation.score}`,\n );\n }\n }\n\n // New pages\n const newPages: string[] = [];\n for (const route of currMap.keys()) {\n if (!prevMap.has(route)) {\n newPages.push(` ${chalk.blue(\"+\")} ${route} ${chalk.dim(\"[new]\")}`);\n }\n }\n\n // Removed pages\n const removed: string[] = [];\n for (const route of prevMap.keys()) {\n if (!currMap.has(route)) {\n removed.push(` ${chalk.dim(\"-\")} ${route} ${chalk.dim(\"[removed]\")}`);\n }\n }\n\n if (regressions.length > 0) {\n lines.push(chalk.red(` REGRESSIONS (${regressions.length}):`));\n lines.push(...regressions);\n lines.push(\"\");\n }\n\n if (improvements.length > 0) {\n lines.push(chalk.green(` IMPROVEMENTS (${improvements.length}):`));\n lines.push(...improvements);\n lines.push(\"\");\n }\n\n if (newPages.length > 0) {\n lines.push(chalk.blue(` NEW PAGES (${newPages.length}):`));\n lines.push(...newPages);\n lines.push(\"\");\n }\n\n if (removed.length > 0) {\n lines.push(chalk.dim(` REMOVED (${removed.length}):`));\n lines.push(...removed);\n lines.push(\"\");\n }\n\n if (regressions.length === 0 && improvements.length === 0 && newPages.length === 0 && removed.length === 0) {\n lines.push(chalk.dim(\" No changes detected.\"));\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\");\n}\n\n/** Format a dynamic page that was skipped from static analysis */\nexport function formatSkippedPage(page: import(\"./scanner.js\").PageInfo): string {\n return ` ${chalk.cyan(\"~\")} ${chalk.bold(page.route)} ${chalk.dim(\"skipped — generateMetadata()\")}`;\n}\n\n/** Color a score value based on its range */\nfunction getScoreColor(score: number): (text: string) => string {\n if (score >= 90) return chalk.green;\n if (score >= 70) return chalk.yellow;\n return chalk.red;\n}\n\n/** Compute summary from results */\nexport function computeSummary(results: CheckResult[], skippedDynamic = 0): CheckSummary {\n const totalPages = results.length + skippedDynamic;\n const passedPages = results.filter((r) => r.validation.errors.length === 0).length;\n const averageScore =\n results.length > 0\n ? Math.round(results.reduce((sum, r) => sum + r.validation.score, 0) / results.length)\n : 0;\n\n let criticalErrors = 0;\n let optionalErrors = 0;\n for (const r of results) {\n for (const e of r.validation.errors) {\n if (e.severity === \"critical\") criticalErrors++;\n else optionalErrors++;\n }\n }\n\n let grade: string;\n if (averageScore >= 90) grade = \"A\";\n else if (averageScore >= 80) grade = \"B\";\n else if (averageScore >= 70) grade = \"C\";\n else if (averageScore >= 60) grade = \"D\";\n else grade = \"F\";\n\n return { results, totalPages, passedPages, averageScore, grade, criticalErrors, optionalErrors, skippedDynamic };\n}\n","import chalk from \"chalk\";\nimport type { CheckResult } from \"./formatter.js\";\n\n/**\n * Generate suggested metadata code snippets for pages with errors.\n * Returns an array of formatted strings ready for terminal output.\n */\nexport function generateFixSuggestions(\n results: CheckResult[],\n baseUrl?: string,\n): string[] {\n const output: string[] = [];\n const siteUrl = baseUrl ?? \"https://yoursite.com\";\n\n for (const { page, validation } of results) {\n if (validation.errors.length === 0 && validation.warnings.length === 0) continue;\n\n const errorIds = new Set(validation.errors.map((e) => e.id));\n const warnIds = new Set(validation.warnings.map((w) => w.id));\n const allIds = new Set([...errorIds, ...warnIds]);\n\n // Build a metadata object suggestion based on what's missing\n const meta: Record<string, unknown> = {};\n const extras: string[] = [];\n\n // Title\n if (allIds.has(\"title-present\")) {\n const suggestion = routeToTitle(page.route);\n meta.title = { absolute: suggestion };\n } else if (allIds.has(\"title-length\")) {\n const current = page.extractedMetadata.title ?? \"\";\n const len = current.length;\n if (len < 50) {\n extras.push(` ${chalk.dim(\"// Title is \" + len + \" chars — expand to 50-60\")}`);\n } else if (len > 60) {\n extras.push(` ${chalk.dim(\"// Title is \" + len + \" chars — shorten to 50-60\")}`);\n }\n }\n\n // Description\n if (allIds.has(\"description-present\")) {\n meta.description = routeToDescription(page.route);\n } else if (allIds.has(\"description-length\")) {\n const current = page.extractedMetadata.description ?? \"\";\n const len = current.length;\n if (len < 120) {\n extras.push(` ${chalk.dim(\"// Description is \" + len + \" chars — expand to 120-160\")}`);\n } else if (len > 160) {\n extras.push(` ${chalk.dim(\"// Description is \" + len + \" chars — shorten to 120-160\")}`);\n }\n }\n\n // Canonical\n if (allIds.has(\"canonical-url\")) {\n const canonical = `${siteUrl}${page.route === \"/\" ? \"\" : page.route}`;\n meta.alternates = { canonical };\n }\n\n // OG Image\n if (allIds.has(\"og-image\")) {\n meta.openGraph = { images: [`${siteUrl}/og-image.png`] };\n }\n\n // Structured data\n if (allIds.has(\"structured-data-present\")) {\n extras.push(` ${chalk.dim(\"// Add JSON-LD structured data (WebPage, Article, FAQ...)\")}`);\n extras.push(` ${chalk.dim(\"// See: https://developers.google.com/search/docs/appearance/structured-data\")}`);\n }\n\n // Twitter\n if (allIds.has(\"twitter-card\")) {\n meta.twitter = { card: \"summary_large_image\" };\n }\n\n // Skip pages with no actionable suggestions\n if (Object.keys(meta).length === 0 && extras.length === 0) continue;\n\n output.push(chalk.bold(` ${chalk.cyan(page.filePath)}`));\n\n if (Object.keys(meta).length > 0) {\n const code = formatMetadataObject(meta);\n output.push(` ${chalk.dim(\"Add/update in your page file:\")}`);\n output.push(\"\");\n for (const line of code.split(\"\\n\")) {\n output.push(` ${chalk.yellow(line)}`);\n }\n }\n\n for (const extra of extras) {\n output.push(extra);\n }\n\n output.push(\"\");\n }\n\n return output;\n}\n\n/** Generate a reasonable title suggestion from a route */\nfunction routeToTitle(route: string): string {\n if (route === \"/\") return \"Your Site — A brief description of what you do\";\n const segments = route.split(\"/\").filter(Boolean);\n const last = segments[segments.length - 1];\n const name = last\n .replace(/\\[.*?\\]/g, \"\")\n .replace(/-/g, \" \")\n .replace(/\\b\\w/g, (c) => c.toUpperCase())\n .trim();\n return `${name || \"Page\"} — Your Site`;\n}\n\n/** Generate a reasonable description suggestion from a route */\nfunction routeToDescription(route: string): string {\n if (route === \"/\") {\n return \"A clear, compelling description of your site in 120-160 characters. Include your main value proposition and a call to action.\";\n }\n const segments = route.split(\"/\").filter(Boolean);\n const last = segments[segments.length - 1];\n const name = last\n .replace(/\\[.*?\\]/g, \"\")\n .replace(/-/g, \" \")\n .trim();\n return `Learn more about ${name || \"this page\"}. Add a compelling 120-160 character description with your key value proposition here.`;\n}\n\n/** Format a metadata object as TypeScript code */\nfunction formatMetadataObject(meta: Record<string, unknown>): string {\n const lines: string[] = [\"export const metadata: Metadata = {\"];\n\n for (const [key, value] of Object.entries(meta)) {\n if (typeof value === \"string\") {\n lines.push(` ${key}: \"${value}\",`);\n } else if (typeof value === \"object\" && value !== null) {\n lines.push(` ${key}: ${JSON.stringify(value, null, 2).replace(/\\n/g, \"\\n \")},`);\n }\n }\n\n lines.push(\"};\");\n return lines.join(\"\\n\");\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport {\n crawlSite,\n fetchSitemap,\n compareSitemap,\n fetchRobots,\n checkUrlsAgainstRobots,\n verifyAssets,\n} from \"indxel\";\nimport type { CrawledPage } from \"indxel\";\nimport { resolveApiKey } from \"../store.js\";\n\nfunction scoreColor(score: number): typeof chalk {\n if (score >= 90) return chalk.green;\n if (score >= 70) return chalk.yellow;\n return chalk.red;\n}\n\nexport const crawlCommand = new Command(\"crawl\")\n .description(\"Crawl a live site, audit every page, check sitemap, robots.txt, and assets\")\n .argument(\"<url>\", \"URL to start crawling (e.g., https://yoursite.com)\")\n .option(\"--max-pages <n>\", \"Maximum pages to crawl\", \"200\")\n .option(\"--max-depth <n>\", \"Maximum link depth\", \"5\")\n .option(\"--delay <ms>\", \"Delay between requests in ms\", \"200\")\n .option(\"--json\", \"Output results as JSON\", false)\n .option(\"--strict\", \"Treat warnings as errors\", false)\n .option(\"--skip-assets\", \"Skip asset verification\", false)\n .option(\"--skip-sitemap\", \"Skip sitemap check\", false)\n .option(\"--skip-robots\", \"Skip robots.txt check\", false)\n .option(\"--ignore <patterns>\", \"Comma-separated path patterns to exclude from analysis (e.g. /app/*,/admin/*)\")\n .option(\"--push\", \"Push results to Indxel dashboard\", false)\n .option(\"--api-key <key>\", \"API key for --push (or set INDXEL_API_KEY env var)\")\n .action(async (url: string, opts) => {\n const jsonOutput = opts.json;\n const maxPages = parseInt(opts.maxPages, 10);\n const maxDepth = parseInt(opts.maxDepth, 10);\n const delay = parseInt(opts.delay, 10);\n\n // Ensure URL has protocol\n if (!url.startsWith(\"http://\") && !url.startsWith(\"https://\")) {\n url = `https://${url}`;\n }\n\n if (!jsonOutput) {\n console.log(\"\");\n console.log(chalk.bold(` indxel crawl`) + chalk.dim(` — ${url}`));\n console.log(\"\");\n }\n\n // 1. Robots.txt\n let robotsResult = null;\n if (!opts.skipRobots) {\n const robotsSpinner = jsonOutput ? null : ora(\"Checking robots.txt...\").start();\n robotsResult = await fetchRobots(url);\n\n if (!jsonOutput) {\n if (robotsResult.found) {\n robotsSpinner!.succeed(\"robots.txt found\");\n for (const w of robotsResult.warnings) {\n console.log(chalk.yellow(` ⚠ ${w}`));\n }\n if (robotsResult.sitemapUrls.length > 0) {\n console.log(chalk.dim(` Sitemap references: ${robotsResult.sitemapUrls.join(\", \")}`));\n }\n } else {\n robotsSpinner!.warn(\"robots.txt not found\");\n for (const e of robotsResult.errors) {\n console.log(chalk.dim(` ${e}`));\n }\n }\n console.log(\"\");\n }\n }\n\n // 2. Crawl\n const crawlSpinner = jsonOutput ? null : ora(\"Crawling...\").start();\n let crawledCount = 0;\n\n // Parse ignore patterns\n const ignorePatterns: string[] = opts.ignore\n ? opts.ignore.split(\",\").map((p: string) => p.trim()).filter(Boolean)\n : [];\n\n const crawlResult = await crawlSite(url, {\n maxPages,\n maxDepth,\n delay,\n strict: opts.strict,\n ignorePatterns,\n onPageCrawled: (page: CrawledPage) => {\n crawledCount++;\n if (crawlSpinner) {\n crawlSpinner.text = `Crawling... ${crawledCount} pages (current: ${page.url})`;\n }\n },\n });\n\n if (!jsonOutput) {\n crawlSpinner!.succeed(`Crawled ${crawlResult.totalPages} pages in ${(crawlResult.durationMs / 1000).toFixed(1)}s`);\n console.log(\"\");\n\n // Page results\n for (const page of crawlResult.pages) {\n if (page.error) {\n console.log(chalk.red(` ✗ ${page.url}`) + chalk.dim(` — ${page.error}`));\n continue;\n }\n\n const pageColor = scoreColor(page.validation.score);\n const icon =\n page.validation.errors.length > 0 ? chalk.red(\"✗\") : chalk.green(\"✓\");\n\n console.log(\n ` ${icon} ${page.url} ${pageColor(`${page.validation.score}/100`)}`,\n );\n\n for (const error of page.validation.errors) {\n console.log(chalk.red(` ✗ ${error.message ?? error.description}`));\n }\n for (const warning of page.validation.warnings) {\n console.log(chalk.yellow(` ⚠ ${warning.message ?? warning.description}`));\n }\n }\n\n console.log(\"\");\n }\n\n // 3. Sitemap check\n let sitemapComparison = null;\n if (!opts.skipSitemap) {\n const sitemapSpinner = jsonOutput ? null : ora(\"Checking sitemap.xml...\").start();\n const sitemapResult = await fetchSitemap(url);\n\n if (!jsonOutput) {\n if (sitemapResult.found) {\n sitemapSpinner!.succeed(`sitemap.xml found — ${sitemapResult.urls.length} URLs`);\n\n // Compare with crawled pages\n const crawledUrls = crawlResult.pages\n .filter((p) => !p.error)\n .map((p) => p.url);\n sitemapComparison = compareSitemap(\n sitemapResult.urls.map((u) => u.loc),\n crawledUrls,\n );\n\n if (sitemapComparison.inCrawlOnly.length > 0) {\n console.log(chalk.yellow(` ⚠ ${sitemapComparison.inCrawlOnly.length} crawled pages missing from sitemap:`));\n for (const u of sitemapComparison.inCrawlOnly.slice(0, 10)) {\n console.log(chalk.dim(` - ${u}`));\n }\n }\n if (sitemapComparison.inSitemapOnly.length > 0) {\n const hitLimit = crawlResult.totalPages >= maxPages;\n const label = hitLimit\n ? `${sitemapComparison.inSitemapOnly.length} sitemap URLs not crawled (limit: ${maxPages} — use --max-pages to increase)`\n : `${sitemapComparison.inSitemapOnly.length} sitemap URLs not reachable`;\n console.log(chalk.yellow(` ⚠ ${label}:`));\n for (const u of sitemapComparison.inSitemapOnly.slice(0, 10)) {\n console.log(chalk.dim(` - ${u}`));\n }\n }\n if (sitemapComparison.issues.length === 0) {\n console.log(chalk.green(` ✓ Sitemap matches crawled pages`));\n }\n } else {\n sitemapSpinner!.warn(\"sitemap.xml not found\");\n for (const e of sitemapResult.errors) {\n console.log(chalk.dim(` ${e}`));\n }\n }\n console.log(\"\");\n }\n }\n\n // 4. Robots.txt URL check\n let robotsBlockedPages = null;\n if (robotsResult?.found && robotsResult.directives.length > 0) {\n const crawledUrls = crawlResult.pages.filter((p) => !p.error).map((p) => p.url);\n robotsBlockedPages = checkUrlsAgainstRobots(\n robotsResult.directives,\n crawledUrls,\n );\n const blocked = robotsBlockedPages.filter((c) => c.blocked);\n\n if (!jsonOutput && blocked.length > 0) {\n console.log(chalk.yellow(` ⚠ ${blocked.length} crawled pages are blocked by robots.txt:`));\n for (const b of blocked) {\n console.log(chalk.dim(` - ${b.path} (${b.blockedBy})`));\n }\n console.log(\"\");\n }\n }\n\n // 5. Asset verification\n let assetResult = null;\n if (!opts.skipAssets) {\n const assetSpinner = jsonOutput ? null : ora(\"Verifying assets (og:image, favicon, ...)...\").start();\n\n const pagesForAssetCheck = crawlResult.pages\n .filter((p) => !p.error)\n .map((p) => ({ url: p.url, metadata: p.metadata }));\n assetResult = await verifyAssets(pagesForAssetCheck);\n\n if (!jsonOutput) {\n assetSpinner!.succeed(`Verified ${assetResult.totalChecked} assets`);\n\n const brokenAssets = assetResult.checks.filter((c) => !c.ok);\n const warningAssets = assetResult.checks.filter((c) => c.warning);\n\n for (const asset of brokenAssets) {\n console.log(\n chalk.red(` ✗ ${asset.type}`) +\n chalk.dim(` ${asset.url}`) +\n chalk.red(` — ${asset.error ?? `HTTP ${asset.status}`}`),\n );\n }\n for (const asset of warningAssets) {\n console.log(\n chalk.yellow(` ⚠ ${asset.type}`) +\n chalk.dim(` ${asset.url}`) +\n chalk.yellow(` — ${asset.warning}`),\n );\n }\n if (brokenAssets.length === 0 && warningAssets.length === 0) {\n console.log(chalk.green(` ✓ All assets respond correctly`));\n }\n console.log(\"\");\n }\n }\n\n // 6. Cross-page analysis\n if (!jsonOutput) {\n const a = crawlResult.analysis;\n\n // Duplicate titles\n if (a.duplicateTitles.length > 0) {\n console.log(chalk.bold(\"- Duplicate titles\"));\n for (const dup of a.duplicateTitles.slice(0, 5)) {\n console.log(chalk.red(` ✗ \"${dup.title.length > 60 ? dup.title.slice(0, 57) + \"...\" : dup.title}\"`) + chalk.dim(` (${dup.urls.length} pages)`));\n for (const u of dup.urls.slice(0, 3)) console.log(chalk.dim(` ${u}`));\n if (dup.urls.length > 3) console.log(chalk.dim(` ...and ${dup.urls.length - 3} more`));\n }\n if (a.duplicateTitles.length > 5) console.log(chalk.dim(` ...and ${a.duplicateTitles.length - 5} more groups`));\n console.log(\"\");\n }\n\n // Duplicate descriptions\n if (a.duplicateDescriptions.length > 0) {\n console.log(chalk.bold(\"- Duplicate descriptions\"));\n for (const dup of a.duplicateDescriptions.slice(0, 5)) {\n const desc = dup.description.length > 60 ? dup.description.slice(0, 57) + \"...\" : dup.description;\n console.log(chalk.red(` ✗ \"${desc}\"`) + chalk.dim(` (${dup.urls.length} pages)`));\n for (const u of dup.urls.slice(0, 3)) console.log(chalk.dim(` ${u}`));\n if (dup.urls.length > 3) console.log(chalk.dim(` ...and ${dup.urls.length - 3} more`));\n }\n if (a.duplicateDescriptions.length > 5) console.log(chalk.dim(` ...and ${a.duplicateDescriptions.length - 5} more groups`));\n console.log(\"\");\n }\n\n // H1 issues\n if (a.h1Issues.length > 0) {\n const missing = a.h1Issues.filter(h => h.issue === \"missing\");\n const multiple = a.h1Issues.filter(h => h.issue === \"multiple\");\n console.log(chalk.bold(\"- H1 heading issues\"));\n if (missing.length > 0) {\n console.log(chalk.red(` ✗ ${missing.length} pages missing H1`));\n for (const h of missing.slice(0, 5)) console.log(chalk.dim(` ${h.url}`));\n if (missing.length > 5) console.log(chalk.dim(` ...and ${missing.length - 5} more`));\n }\n if (multiple.length > 0) {\n console.log(chalk.yellow(` ⚠ ${multiple.length} pages with multiple H1s`));\n for (const h of multiple.slice(0, 5)) console.log(chalk.dim(` ${h.url} (${h.count} H1s)`));\n if (multiple.length > 5) console.log(chalk.dim(` ...and ${multiple.length - 5} more`));\n }\n console.log(\"\");\n }\n\n // Broken internal links\n if (a.brokenInternalLinks.length > 0) {\n console.log(chalk.bold(\"- Broken internal links\"));\n for (const bl of a.brokenInternalLinks.slice(0, 10)) {\n console.log(chalk.red(` ✗ ${bl.to}`) + chalk.dim(` ← linked from ${bl.from} (${bl.status})`));\n }\n if (a.brokenInternalLinks.length > 10) console.log(chalk.dim(` ...and ${a.brokenInternalLinks.length - 10} more`));\n console.log(\"\");\n }\n\n // Broken external links\n if (a.brokenExternalLinks.length > 0) {\n console.log(chalk.bold(\"- Broken external links\"));\n for (const bl of a.brokenExternalLinks.slice(0, 10)) {\n console.log(chalk.red(` ✗ ${bl.to}`) + chalk.dim(` ← linked from ${bl.from} (${bl.status})`));\n }\n if (a.brokenExternalLinks.length > 10) console.log(chalk.dim(` ...and ${a.brokenExternalLinks.length - 10} more`));\n console.log(\"\");\n }\n\n // Redirects\n if (a.redirects.length > 0) {\n console.log(chalk.bold(\"- Redirect chains\"));\n for (const r of a.redirects.slice(0, 10)) {\n console.log(chalk.yellow(` ⚠ ${r.url}`));\n for (const step of r.chain) console.log(chalk.dim(` ${step}`));\n }\n if (a.redirects.length > 10) console.log(chalk.dim(` ...and ${a.redirects.length - 10} more`));\n console.log(\"\");\n }\n\n // Thin content\n if (a.thinContentPages.length > 0) {\n const realThin = a.thinContentPages.filter(tc => !tc.isAppPage);\n const appThin = a.thinContentPages.filter(tc => tc.isAppPage);\n\n if (realThin.length > 0) {\n console.log(chalk.bold(\"- Thin content\") + chalk.dim(\" (< 200 words)\"));\n for (const tc of realThin.slice(0, 10)) {\n console.log(chalk.yellow(` ⚠ ${tc.url}`) + chalk.dim(` — ${tc.wordCount} words`));\n }\n if (realThin.length > 10) console.log(chalk.dim(` ...and ${realThin.length - 10} more`));\n console.log(\"\");\n }\n if (appThin.length > 0) {\n console.log(chalk.bold(\"- App/wizard pages\") + chalk.dim(\" (client-rendered, low word count expected)\"));\n for (const tc of appThin.slice(0, 5)) {\n console.log(chalk.dim(` ℹ ${tc.url} — ${tc.wordCount} words`));\n }\n if (appThin.length > 5) console.log(chalk.dim(` ...and ${appThin.length - 5} more`));\n console.log(\"\");\n }\n }\n\n // Orphan pages\n if (a.orphanPages.length > 0) {\n console.log(chalk.bold(\"- Orphan pages\") + chalk.dim(\" (0 internal links pointing to them)\"));\n for (const o of a.orphanPages.slice(0, 10)) console.log(chalk.yellow(` ⚠ ${o}`));\n if (a.orphanPages.length > 10) console.log(chalk.dim(` ...and ${a.orphanPages.length - 10} more`));\n console.log(\"\");\n }\n\n // Slowest pages\n if (a.slowestPages.length > 0 && a.slowestPages[0].responseTimeMs > 1000) {\n console.log(chalk.bold(\"- Slowest pages\"));\n for (const sp of a.slowestPages.filter(p => p.responseTimeMs > 1000).slice(0, 5)) {\n const color = sp.responseTimeMs > 3000 ? chalk.red : chalk.yellow;\n console.log(color(` ⚠ ${sp.url}`) + chalk.dim(` — ${(sp.responseTimeMs / 1000).toFixed(1)}s`));\n }\n console.log(\"\");\n }\n\n // Structured data summary\n if (a.structuredDataSummary.length > 0) {\n console.log(chalk.bold(\"- Structured data (JSON-LD)\"));\n for (const sd of a.structuredDataSummary) {\n console.log(chalk.green(` ✓ ${sd.type}`) + chalk.dim(` — ${sd.count} page${sd.count > 1 ? \"s\" : \"\"}`));\n }\n const pagesWithSD = crawlResult.pages.filter(p => !p.error && p.structuredDataTypes.length > 0).length;\n const pagesWithout = crawlResult.pages.filter(p => !p.error).length - pagesWithSD;\n if (pagesWithout > 0) {\n console.log(chalk.yellow(` ⚠ ${pagesWithout} pages without any structured data`));\n }\n console.log(\"\");\n } else {\n console.log(chalk.bold(\"- Structured data (JSON-LD)\"));\n console.log(chalk.red(` ✗ No structured data found on any page`));\n console.log(\"\");\n }\n\n // Image alt text issues\n if (a.imageAltIssues.length > 0) {\n console.log(chalk.bold(\"- Image alt text\"));\n for (const img of a.imageAltIssues.slice(0, 10)) {\n const color = img.missingAlt / img.total >= 0.5 ? chalk.red : chalk.yellow;\n const icon = img.missingAlt / img.total >= 0.5 ? \"✗\" : \"⚠\";\n console.log(color(` ${icon} ${img.url}`) + chalk.dim(` — ${img.missingAlt}/${img.total} images missing alt`));\n }\n if (a.imageAltIssues.length > 10) console.log(chalk.dim(` ...and ${a.imageAltIssues.length - 10} more`));\n console.log(\"\");\n }\n\n // Broken images\n if (a.brokenImages.length > 0) {\n console.log(chalk.bold(\"- Broken images\"));\n for (const img of a.brokenImages.slice(0, 10)) {\n const src = img.src.length > 80 ? img.src.slice(0, 77) + \"...\" : img.src;\n console.log(chalk.red(` ✗ ${src}`) + chalk.dim(` (${img.status}) — on ${img.pages.length} page${img.pages.length > 1 ? \"s\" : \"\"}`));\n for (const page of img.pages.slice(0, 3)) console.log(chalk.dim(` ${page}`));\n if (img.pages.length > 3) console.log(chalk.dim(` ...and ${img.pages.length - 3} more`));\n }\n if (a.brokenImages.length > 10) console.log(chalk.dim(` ...and ${a.brokenImages.length - 10} more`));\n console.log(\"\");\n }\n }\n\n // 7. Summary\n if (jsonOutput) {\n console.log(\n JSON.stringify(\n {\n crawl: crawlResult,\n robots: robotsResult,\n sitemap: sitemapComparison,\n assets: assetResult,\n },\n null,\n 2,\n ),\n );\n } else {\n const summaryColor = scoreColor(crawlResult.averageScore);\n\n console.log(chalk.bold(\" ─── Summary ───\"));\n console.log(\"\");\n const hitLimit = crawlResult.totalPages >= maxPages;\n console.log(` Pages crawled: ${chalk.bold(String(crawlResult.totalPages))}${hitLimit ? chalk.dim(` (limit: ${maxPages} — use --max-pages to crawl more)`) : \"\"}`);\n console.log(` Average score: ${summaryColor(chalk.bold(`${crawlResult.averageScore}/100`))} (${crawlResult.grade})`);\n console.log(` Errors: ${crawlResult.totalErrors > 0 ? chalk.red(String(crawlResult.totalErrors)) : chalk.green(\"0\")}`);\n console.log(` Warnings: ${crawlResult.totalWarnings > 0 ? chalk.yellow(String(crawlResult.totalWarnings)) : chalk.green(\"0\")}`);\n if (assetResult) {\n console.log(` Broken assets: ${assetResult.totalBroken > 0 ? chalk.red(String(assetResult.totalBroken)) : chalk.green(\"0\")}`);\n }\n if (crawlResult.skippedUrls.length > 0) {\n console.log(chalk.dim(` Skipped: ${crawlResult.skippedUrls.length} URLs (over limit)`));\n }\n console.log(\"\");\n }\n\n // 8. Push to dashboard\n if (opts.push) {\n const apiKey = await resolveApiKey(opts.apiKey);\n if (!apiKey) {\n if (!jsonOutput) {\n console.log(chalk.yellow(\" ⚠\") + \" To push results to your dashboard, link your project first:\");\n console.log(\"\");\n console.log(chalk.bold(\" npx indxel link\"));\n console.log(\"\");\n console.log(chalk.dim(\" Or use --api-key / set INDXEL_API_KEY.\"));\n console.log(\"\");\n }\n } else {\n const pushSpinner = jsonOutput ? null : ora(\"Pushing results to Indxel...\").start();\n try {\n const pushUrl = process.env.INDXEL_API_URL || \"https://indxel.com\";\n const res = await fetch(`${pushUrl}/api/cli/push`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n crawl: crawlResult,\n robots: robotsResult,\n sitemap: sitemapComparison,\n assets: assetResult,\n }),\n });\n if (res.ok) {\n const data = (await res.json()) as { checkId?: string };\n if (pushSpinner) pushSpinner.succeed(`Pushed to dashboard — check ${data.checkId}`);\n } else {\n const data = (await res.json().catch(() => ({}))) as { error?: string };\n if (pushSpinner) pushSpinner.fail(`Push failed: ${data.error || res.statusText}`);\n }\n } catch (err) {\n if (pushSpinner) pushSpinner.fail(`Push failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n if (!jsonOutput) console.log(\"\");\n }\n }\n\n // Exit code\n if (crawlResult.totalErrors > 0) {\n process.exit(1);\n }\n });\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { researchKeywords, crawlSite, analyzeContentGaps } from \"indxel\";\n\nexport const keywordsCommand = new Command(\"keywords\")\n .description(\"Research keyword opportunities and find content gaps\")\n .argument(\"<seed>\", \"Seed keyword or topic to research\")\n .option(\"--locale <locale>\", \"Language locale\", \"en\")\n .option(\"--country <country>\", \"Country code\", \"us\")\n .option(\"--site <url>\", \"Site URL to analyze content gaps against\")\n .option(\"--max-pages <n>\", \"Maximum pages to crawl for gap analysis\", \"30\")\n .option(\"--json\", \"Output results as JSON\", false)\n .action(async (seed: string, opts) => {\n const jsonOutput = opts.json;\n\n if (!jsonOutput) {\n console.log(\"\");\n console.log(chalk.bold(` indxel keywords`) + chalk.dim(` — \"${seed}\"`));\n console.log(\"\");\n }\n\n // 1. Keyword research\n const kwSpinner = jsonOutput ? null : ora(\"Researching keywords...\").start();\n const kwResult = await researchKeywords(seed, {\n locale: opts.locale,\n country: opts.country,\n });\n\n if (!jsonOutput) {\n kwSpinner!.succeed(`Found ${kwResult.totalKeywords} keywords`);\n console.log(\"\");\n\n if (kwResult.suggestions.length > 0) {\n console.log(chalk.bold(` Direct suggestions (${kwResult.suggestions.length})`));\n for (const s of kwResult.suggestions) {\n console.log(` ${chalk.hex(\"#F4A261\")(s.keyword)}`);\n }\n console.log(\"\");\n }\n\n if (kwResult.questions.length > 0) {\n console.log(chalk.bold(` Questions (${kwResult.questions.length})`));\n for (const q of kwResult.questions.slice(0, 20)) {\n console.log(` ${chalk.cyan(\"?\")} ${q.keyword}`);\n }\n console.log(\"\");\n }\n\n if (kwResult.longTail.length > 0) {\n console.log(chalk.bold(` Long-tail (${kwResult.longTail.length})`));\n for (const lt of kwResult.longTail.slice(0, 20)) {\n console.log(chalk.dim(` ${lt.keyword}`));\n }\n if (kwResult.longTail.length > 20) {\n console.log(chalk.dim(` ... and ${kwResult.longTail.length - 20} more`));\n }\n console.log(\"\");\n }\n }\n\n // 2. Content gap analysis (if site URL provided)\n let gapResult = null;\n if (opts.site) {\n let siteUrl = opts.site;\n if (!siteUrl.startsWith(\"http://\") && !siteUrl.startsWith(\"https://\")) {\n siteUrl = `https://${siteUrl}`;\n }\n\n const crawlSpinner = jsonOutput ? null : ora(`Crawling ${siteUrl} for gap analysis...`).start();\n const crawlResult = await crawlSite(siteUrl, {\n maxPages: parseInt(opts.maxPages, 10),\n delay: 200,\n });\n\n if (!jsonOutput) {\n crawlSpinner!.succeed(`Crawled ${crawlResult.totalPages} pages`);\n }\n\n const allKeywords = [\n ...kwResult.suggestions,\n ...kwResult.questions,\n ...kwResult.longTail,\n ];\n\n const existingPages = crawlResult.pages\n .filter((p) => !p.error)\n .map((p) => ({ url: p.url, metadata: p.metadata }));\n\n gapResult = analyzeContentGaps(allKeywords, existingPages);\n\n if (!jsonOutput) {\n console.log(\"\");\n console.log(\n chalk.bold(` Content coverage: `) +\n `${gapResult.totalCovered}/${gapResult.totalKeywords} keywords (${gapResult.coveragePercent}%)`,\n );\n console.log(\"\");\n\n if (gapResult.gaps.length > 0) {\n const highGaps = gapResult.gaps.filter((g) => g.relevance === \"high\");\n const medGaps = gapResult.gaps.filter((g) => g.relevance === \"medium\");\n\n if (highGaps.length > 0) {\n console.log(chalk.bold.red(` High priority gaps (${highGaps.length})`));\n for (const gap of highGaps.slice(0, 15)) {\n console.log(\n chalk.red(` ✗ `) +\n `\"${gap.keyword}\" → ` +\n chalk.dim(`${gap.suggestedType} at ${gap.suggestedPath}`),\n );\n }\n console.log(\"\");\n }\n\n if (medGaps.length > 0) {\n console.log(chalk.bold.yellow(` Medium priority gaps (${medGaps.length})`));\n for (const gap of medGaps.slice(0, 10)) {\n console.log(\n chalk.yellow(` ⚠ `) +\n `\"${gap.keyword}\" → ` +\n chalk.dim(`${gap.suggestedType} at ${gap.suggestedPath}`),\n );\n }\n console.log(\"\");\n }\n }\n\n if (gapResult.gaps.length === 0) {\n console.log(chalk.green(` ✓ All keyword opportunities are covered`));\n console.log(\"\");\n }\n }\n }\n\n // JSON output\n if (jsonOutput) {\n console.log(\n JSON.stringify(\n { keywords: kwResult, contentGaps: gapResult },\n null,\n 2,\n ),\n );\n }\n });\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { fetchSitemap, fetchRobots } from \"indxel\";\nimport { checkPlan } from \"../auth.js\";\nimport { loadIndexNowKey, resolveApiKey } from \"../store.js\";\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n\nexport const indexCommand = new Command(\"index\")\n .description(\"Submit your pages to search engines and check indexation status\")\n .argument(\"<url>\", \"Site URL (e.g., https://yoursite.com)\")\n .option(\"--check\", \"Check which pages appear indexed (Pro+)\", false)\n .option(\"--indexnow-key <key>\", \"IndexNow key (auto-detected from .indxel/ if not specified)\")\n .option(\"--api-key <key>\", \"Indxel API key (required for --check and IndexNow submission)\")\n .option(\"--json\", \"Output results as JSON\", false)\n .action(async (url: string, opts) => {\n const jsonOutput = opts.json;\n const needsPaid = opts.check;\n\n // Helper: only log in human-readable mode\n function log(...args: unknown[]) {\n if (!jsonOutput) console.log(...args);\n }\n\n // Helper: create spinner only in human-readable mode\n function spin(text: string) {\n return jsonOutput ? null : ora(text).start();\n }\n\n // Ensure URL has protocol\n if (!url.startsWith(\"http://\") && !url.startsWith(\"https://\")) {\n url = `https://${url}`;\n }\n\n let baseUrl: URL;\n try {\n baseUrl = new URL(url);\n } catch {\n console.error(chalk.red(\" Invalid URL.\"));\n process.exit(1);\n }\n\n const origin = baseUrl.origin;\n const host = baseUrl.hostname;\n\n log(\"\");\n log(chalk.bold(\" indxel index\") + chalk.dim(` — ${origin}`));\n log(\"\");\n\n // Gate paid features behind API key + plan check\n if (needsPaid) {\n const apiKey = await resolveApiKey(opts.apiKey);\n if (!apiKey) {\n log(chalk.red(\" ✗ --check requires a linked project (Plus plan).\"));\n log(chalk.dim(\" Run: \") + chalk.bold(\"npx indxel link\"));\n log(chalk.dim(\" Or use --api-key / set INDXEL_API_KEY.\"));\n log(\"\");\n process.exit(1);\n }\n\n const plan = await checkPlan(apiKey);\n if (!plan) {\n log(chalk.red(\" ✗ Invalid API key.\"));\n log(\"\");\n process.exit(1);\n }\n\n if (plan === \"FREE\") {\n log(chalk.red(\" ✗ Indexation check requires a Pro plan.\"));\n log(chalk.dim(\" Upgrade at https://indxel.com/pricing\"));\n log(\"\");\n process.exit(1);\n }\n }\n\n // 1. Fetch sitemap\n const sitemapSpinner = spin(\"Fetching sitemap...\");\n const sitemapResult = await fetchSitemap(origin);\n const sitemapUrl = `${origin}/sitemap.xml`;\n\n if (!sitemapResult.found || sitemapResult.urls.length === 0) {\n sitemapSpinner?.fail(\"No sitemap found\");\n log(chalk.dim(\" Create a sitemap first: \") + chalk.bold(\"npx indxel init\"));\n log(\"\");\n if (jsonOutput) {\n console.log(JSON.stringify({ error: \"No sitemap found\" }, null, 2));\n }\n process.exit(1);\n }\n\n sitemapSpinner?.succeed(`Found sitemap — ${sitemapResult.urls.length} URLs`);\n\n // 2. Check robots.txt references sitemap\n const robotsSpinner = spin(\"Checking robots.txt...\");\n const robotsResult = await fetchRobots(origin);\n let sitemapInRobots = false;\n\n if (robotsResult.found) {\n sitemapInRobots = robotsResult.sitemapUrls.some((s) =>\n s.toLowerCase().includes(\"sitemap\"),\n );\n if (sitemapInRobots) {\n robotsSpinner?.succeed(\"robots.txt references sitemap\");\n } else {\n robotsSpinner?.warn(\"robots.txt found but doesn't reference sitemap\");\n log(chalk.dim(` Add this to your robots.txt:`));\n log(chalk.dim(` Sitemap: ${sitemapUrl}`));\n }\n } else {\n robotsSpinner?.warn(\"No robots.txt found\");\n log(chalk.dim(\" Create one with: \") + chalk.bold(\"npx indxel init\"));\n }\n\n log(\"\");\n\n // 3. IndexNow submission (Bing, Yandex, DuckDuckGo, etc.)\n // IndexNow is an open protocol — one-shot submission works without an account.\n const indexNowKey = opts.indexnowKey || process.env.INDEXNOW_KEY || await loadIndexNowKey(process.cwd());\n const indexNowResult: { submitted: boolean; engine: string; status?: number }[] = [];\n\n if (indexNowKey) {\n const urls = sitemapResult.urls.map((u) => u.loc);\n const indexNowSpinner = spin(\"Submitting via IndexNow...\");\n\n const indexNowEngines = [\n { name: \"Bing/Yandex\", endpoint: \"https://api.indexnow.org/indexnow\" },\n ];\n\n for (const engine of indexNowEngines) {\n try {\n const res = await fetch(engine.endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n host,\n key: indexNowKey,\n keyLocation: `${origin}/${indexNowKey}.txt`,\n urlList: urls.slice(0, 10000), // IndexNow limit\n }),\n signal: AbortSignal.timeout(15000),\n });\n\n if (res.ok || res.status === 202) {\n indexNowResult.push({ submitted: true, engine: engine.name, status: res.status });\n indexNowSpinner?.succeed(`IndexNow — ${urls.length} URLs submitted to ${engine.name}`);\n } else {\n indexNowResult.push({ submitted: false, engine: engine.name, status: res.status });\n indexNowSpinner?.warn(`IndexNow — ${engine.name} returned HTTP ${res.status}`);\n }\n } catch (err) {\n indexNowResult.push({ submitted: false, engine: engine.name });\n indexNowSpinner?.fail(`IndexNow — ${err instanceof Error ? err.message : \"failed\"}`);\n }\n }\n } else {\n log(chalk.bold(\" IndexNow\") + chalk.dim(\" (Bing, Yandex, DuckDuckGo)\"));\n log(chalk.dim(\" Not configured. Run \") + chalk.bold(\"npx indxel init\") + chalk.dim(\" to set it up automatically.\"));\n log(\"\");\n }\n\n log(chalk.bold(\" Google Search Console\"));\n log(chalk.dim(\" Google requires manual setup via Search Console:\"));\n log(chalk.dim(\" 1. Go to \") + chalk.underline(\"https://search.google.com/search-console\"));\n log(chalk.dim(` 2. Add & verify ${host}`));\n log(chalk.dim(\" 3. Submit your sitemap: Sitemaps > Add > sitemap.xml\"));\n log(\"\");\n\n // 4. Check indexation status (optional)\n let indexationResults: Array<{ url: string; indexed: boolean }> | null = null;\n\n if (opts.check) {\n const checkSpinner = spin(\"Checking indexation status...\");\n indexationResults = [];\n const urls = sitemapResult.urls.map((u) => u.loc);\n let indexedCount = 0;\n\n for (let i = 0; i < urls.length; i++) {\n const pageUrl = urls[i];\n if (checkSpinner) {\n checkSpinner.text = `Checking indexation... ${i + 1}/${urls.length}`;\n }\n\n try {\n const cacheUrl = `https://webcache.googleusercontent.com/search?q=cache:${encodeURIComponent(pageUrl)}`;\n const res = await fetch(cacheUrl, {\n method: \"HEAD\",\n signal: AbortSignal.timeout(5000),\n redirect: \"manual\",\n headers: {\n \"User-Agent\": \"Mozilla/5.0 (compatible; Indxel/0.1; +https://indxel.com)\",\n },\n });\n\n const indexed = res.status === 200 || res.status === 301 || res.status === 302;\n indexationResults.push({ url: pageUrl, indexed });\n if (indexed) indexedCount++;\n } catch {\n indexationResults.push({ url: pageUrl, indexed: false });\n }\n\n await delay(300);\n }\n\n checkSpinner?.succeed(`Indexation: ${indexedCount}/${urls.length} pages found in Google cache`);\n\n if (!jsonOutput) {\n console.log(\"\");\n const notIndexed = indexationResults.filter((r) => !r.indexed);\n\n if (notIndexed.length > 0) {\n console.log(chalk.bold(` Not indexed (${notIndexed.length})`));\n for (const r of notIndexed.slice(0, 20)) {\n console.log(chalk.red(\" ✗ \") + r.url);\n }\n if (notIndexed.length > 20) {\n console.log(chalk.dim(` ... and ${notIndexed.length - 20} more`));\n }\n console.log(\"\");\n } else {\n console.log(chalk.green(\" ✓ All pages appear indexed\"));\n console.log(\"\");\n }\n }\n }\n\n // 5. Summary\n if (jsonOutput) {\n console.log(JSON.stringify({\n sitemap: { url: sitemapUrl, urls: sitemapResult.urls.length },\n robotsTxt: { found: robotsResult.found, referencesSitemap: sitemapInRobots },\n indexNow: indexNowResult.length > 0 ? indexNowResult : null,\n indexation: indexationResults,\n }, null, 2));\n } else {\n console.log(chalk.bold(\" ─── Summary ───\"));\n console.log(\"\");\n console.log(` Sitemap: ${sitemapResult.urls.length} URLs`);\n\n let robotsStatus: string;\n if (!robotsResult.found) {\n robotsStatus = chalk.red(\"✗ not found\");\n } else if (sitemapInRobots) {\n robotsStatus = chalk.green(\"✓ references sitemap\");\n } else {\n robotsStatus = chalk.yellow(\"⚠ missing sitemap ref\");\n }\n console.log(` robots.txt: ${robotsStatus}`);\n\n if (indexNowResult.length > 0) {\n for (const r of indexNowResult) {\n const status = r.submitted ? chalk.green(\"✓ submitted\") : chalk.red(\"✗ failed\");\n console.log(` IndexNow: ${status} (${r.engine})`);\n }\n } else {\n console.log(` IndexNow: ${chalk.dim(\"not configured (run npx indxel init)\")}`);\n }\n if (indexationResults) {\n const indexedCount = indexationResults.filter((r) => r.indexed).length;\n console.log(` Google cache: ${indexedCount}/${indexationResults.length} indexed`);\n }\n console.log(\"\");\n }\n });\n","export async function checkPlan(apiKey: string): Promise<string | null> {\n try {\n const apiUrl = process.env.INDXEL_API_URL || \"https://indxel.com\";\n const res = await fetch(`${apiUrl}/api/cli/plan`, {\n headers: { Authorization: `Bearer ${apiKey}` },\n signal: AbortSignal.timeout(10000),\n });\n if (!res.ok) return null;\n const data = (await res.json()) as { plan?: string };\n return data.plan ?? null;\n } catch {\n return null;\n }\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { fetchSitemap } from \"indxel\";\n\n// --- Types ---\n\ninterface PsiMetrics {\n performanceScore: number;\n lcp: number;\n cls: number;\n inp: number;\n fcp: number;\n si: number;\n tbt: number;\n}\n\ninterface PageResult {\n url: string;\n strategy: string;\n metrics: PsiMetrics | null;\n error?: string;\n}\n\n// --- CWV thresholds (Google's) ---\n\nconst THRESHOLDS = {\n lcp: { good: 2500, poor: 4000 },\n cls: { good: 0.1, poor: 0.25 },\n inp: { good: 200, poor: 500 },\n} as const;\n\n// --- Helpers ---\n\nfunction ratingFor(\n metric: \"lcp\" | \"cls\" | \"inp\",\n value: number,\n): \"good\" | \"needs-work\" | \"poor\" {\n const t = THRESHOLDS[metric];\n if (value <= t.good) return \"good\";\n if (value <= t.poor) return \"needs-work\";\n return \"poor\";\n}\n\nfunction colorForRating(rating: \"good\" | \"needs-work\" | \"poor\") {\n if (rating === \"good\") return chalk.green;\n if (rating === \"needs-work\") return chalk.yellow;\n return chalk.red;\n}\n\nfunction iconForRating(rating: \"good\" | \"needs-work\" | \"poor\") {\n if (rating === \"good\") return chalk.green(\"✓\");\n if (rating === \"needs-work\") return chalk.yellow(\"⚠\");\n return chalk.red(\"✗\");\n}\n\nfunction formatMs(ms: number): string {\n if (ms >= 1000) return `${(ms / 1000).toFixed(1)}s`;\n return `${Math.round(ms)}ms`;\n}\n\nfunction formatCls(value: number): string {\n return value.toFixed(2);\n}\n\nfunction scoreColor(score: number) {\n if (score >= 90) return chalk.green;\n if (score >= 50) return chalk.yellow;\n return chalk.red;\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n\n// --- PSI API ---\n\nexport async function fetchPsi(\n url: string,\n strategy: \"mobile\" | \"desktop\",\n): Promise<PsiMetrics> {\n const params = new URLSearchParams({\n url,\n strategy,\n category: \"performance\",\n });\n\n const apiKey = process.env.PSI_API_KEY;\n if (apiKey) params.set(\"key\", apiKey);\n\n const res = await fetch(\n `https://www.googleapis.com/pagespeedonline/v5/runPagespeed?${params}`,\n { signal: AbortSignal.timeout(60000) },\n );\n\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`PSI API returned HTTP ${res.status}: ${body.slice(0, 200)}`);\n }\n\n const data = await res.json();\n return parsePsiResponse(data);\n}\n\nexport function parsePsiResponse(data: any): PsiMetrics {\n const lr = data.lighthouseResult;\n if (!lr) throw new Error(\"No lighthouseResult in PSI response\");\n\n const perfScore = lr.categories?.performance?.score;\n if (perfScore == null) throw new Error(\"No performance score in PSI response\");\n\n return {\n performanceScore: Math.round(perfScore * 100),\n lcp: lr.audits?.[\"largest-contentful-paint\"]?.numericValue ?? 0,\n cls: lr.audits?.[\"cumulative-layout-shift\"]?.numericValue ?? 0,\n inp: lr.audits?.[\"interaction-to-next-paint\"]?.numericValue ?? 0,\n fcp: lr.audits?.[\"first-contentful-paint\"]?.numericValue ?? 0,\n si: lr.audits?.[\"speed-index\"]?.numericValue ?? 0,\n tbt: lr.audits?.[\"total-blocking-time\"]?.numericValue ?? 0,\n };\n}\n\nexport function checkBudgets(\n metrics: PsiMetrics,\n budgets: { lcp?: number; cls?: number; score?: number },\n): string[] {\n const failures: string[] = [];\n\n if (budgets.score != null && metrics.performanceScore < budgets.score) {\n failures.push(\n `Performance score ${metrics.performanceScore} is below budget ${budgets.score}`,\n );\n }\n if (budgets.lcp != null && metrics.lcp > budgets.lcp) {\n failures.push(\n `LCP ${formatMs(metrics.lcp)} exceeds budget ${formatMs(budgets.lcp)}`,\n );\n }\n if (budgets.cls != null && metrics.cls > budgets.cls) {\n failures.push(\n `CLS ${formatCls(metrics.cls)} exceeds budget ${formatCls(budgets.cls)}`,\n );\n }\n\n return failures;\n}\n\n// --- Output formatting ---\n\nfunction printPageResult(result: PageResult) {\n const { url, strategy, metrics, error } = result;\n\n console.log(\n chalk.bold(\" indxel perf\") + chalk.dim(` — ${url} (${strategy})`),\n );\n console.log(\"\");\n\n if (error || !metrics) {\n console.log(chalk.red(` ✗ ${error ?? \"Unknown error\"}`));\n console.log(\"\");\n return;\n }\n\n const sc = scoreColor(metrics.performanceScore);\n const perfIcon =\n metrics.performanceScore >= 90\n ? chalk.green(\"✓\")\n : metrics.performanceScore >= 50\n ? chalk.yellow(\"⚠\")\n : chalk.red(\"✗\");\n console.log(\n ` ${perfIcon} ${chalk.bold(\"Performance\")} ${sc(chalk.bold(`${metrics.performanceScore}/100`))}`,\n );\n console.log(\"\");\n\n // Core Web Vitals\n console.log(chalk.bold(\" Core Web Vitals\"));\n\n const lcpRating = ratingFor(\"lcp\", metrics.lcp);\n const clsRating = ratingFor(\"cls\", metrics.cls);\n const inpRating = ratingFor(\"inp\", metrics.inp);\n\n console.log(\n ` ${iconForRating(lcpRating)} ${colorForRating(lcpRating)(formatMs(metrics.lcp).padEnd(9))} ${chalk.dim(\"LCP Largest Contentful Paint\")}`,\n );\n console.log(\n ` ${iconForRating(clsRating)} ${colorForRating(clsRating)(formatCls(metrics.cls).padEnd(9))} ${chalk.dim(\"CLS Cumulative Layout Shift\")}`,\n );\n console.log(\n ` ${iconForRating(inpRating)} ${colorForRating(inpRating)(formatMs(metrics.inp).padEnd(9))} ${chalk.dim(\"INP Interaction to Next Paint\")}`,\n );\n console.log(\"\");\n\n // Other metrics\n console.log(chalk.bold(\" Other metrics\"));\n console.log(\n ` ${formatMs(metrics.fcp).padEnd(9)} ${chalk.dim(\"FCP First Contentful Paint\")}`,\n );\n console.log(\n ` ${formatMs(metrics.si).padEnd(9)} ${chalk.dim(\"SI Speed Index\")}`,\n );\n console.log(\n ` ${formatMs(metrics.tbt).padEnd(9)} ${chalk.dim(\"TBT Total Blocking Time\")}`,\n );\n console.log(\"\");\n}\n\nfunction printMultiPageSummary(results: PageResult[]) {\n const valid = results.filter((r) => r.metrics);\n if (valid.length === 0) return;\n\n const avgScore = Math.round(\n valid.reduce((s, r) => s + r.metrics!.performanceScore, 0) / valid.length,\n );\n const worstLcp = Math.max(...valid.map((r) => r.metrics!.lcp));\n const worstCls = Math.max(...valid.map((r) => r.metrics!.cls));\n const worstInp = Math.max(...valid.map((r) => r.metrics!.inp));\n\n console.log(chalk.bold(\" ─── Summary ───\"));\n console.log(\"\");\n console.log(` Pages tested: ${chalk.bold(String(results.length))}`);\n console.log(\n ` Avg score: ${scoreColor(avgScore)(chalk.bold(`${avgScore}/100`))}`,\n );\n\n const lcpR = ratingFor(\"lcp\", worstLcp);\n const clsR = ratingFor(\"cls\", worstCls);\n const inpR = ratingFor(\"inp\", worstInp);\n\n console.log(\n ` Worst LCP: ${colorForRating(lcpR)(formatMs(worstLcp))}`,\n );\n console.log(\n ` Worst CLS: ${colorForRating(clsR)(formatCls(worstCls))}`,\n );\n console.log(\n ` Worst INP: ${colorForRating(inpR)(formatMs(worstInp))}`,\n );\n console.log(\"\");\n}\n\n// --- Command ---\n\nexport const perfCommand = new Command(\"perf\")\n .description(\"Test Core Web Vitals and performance via PageSpeed Insights\")\n .argument(\"<url>\", \"URL to test (e.g., https://yoursite.com)\")\n .option(\n \"--strategy <strategy>\",\n \"Testing strategy: mobile or desktop\",\n \"mobile\",\n )\n .option(\n \"--pages <n>\",\n \"Test top N pages from sitemap (default: 1 = just the URL)\",\n \"1\",\n )\n .option(\"--json\", \"Output results as JSON\", false)\n .option(\"--budget-lcp <ms>\", \"Fail if LCP exceeds threshold (ms)\")\n .option(\"--budget-cls <score>\", \"Fail if CLS exceeds threshold\")\n .option(\"--budget-score <n>\", \"Fail if perf score below threshold\")\n .action(async (url: string, opts) => {\n const jsonOutput = opts.json;\n const strategy = opts.strategy as \"mobile\" | \"desktop\";\n const pageCount = parseInt(opts.pages, 10);\n\n if (strategy !== \"mobile\" && strategy !== \"desktop\") {\n console.error(\n chalk.red(\" --strategy must be 'mobile' or 'desktop'\"),\n );\n process.exit(1);\n }\n\n // Ensure URL has protocol\n if (!url.startsWith(\"http://\") && !url.startsWith(\"https://\")) {\n url = `https://${url}`;\n }\n\n try {\n new URL(url);\n } catch {\n console.error(chalk.red(\" Invalid URL.\"));\n process.exit(1);\n }\n\n // Collect URLs to test\n let urls: string[] = [url];\n\n if (pageCount > 1) {\n const sitemapSpinner = jsonOutput ? null : ora(\"Fetching sitemap...\").start();\n const sitemap = await fetchSitemap(url);\n\n if (sitemap.found && sitemap.urls.length > 0) {\n urls = sitemap.urls.slice(0, pageCount).map((u) => u.loc);\n sitemapSpinner?.succeed(\n `Found ${sitemap.urls.length} URLs, testing top ${urls.length}`,\n );\n } else {\n sitemapSpinner?.warn(\"No sitemap found, testing single URL\");\n }\n if (!jsonOutput) console.log(\"\");\n }\n\n // Run PSI for each URL\n const results: PageResult[] = [];\n\n for (let i = 0; i < urls.length; i++) {\n const targetUrl = urls[i];\n const spinner = jsonOutput\n ? null\n : ora(\n urls.length > 1\n ? `Testing ${i + 1}/${urls.length}: ${targetUrl}`\n : `Testing ${targetUrl} (${strategy})...`,\n ).start();\n\n try {\n const metrics = await fetchPsi(targetUrl, strategy);\n spinner?.stop();\n results.push({ url: targetUrl, strategy, metrics });\n\n if (!jsonOutput) {\n printPageResult({ url: targetUrl, strategy, metrics });\n }\n } catch (err) {\n const errMsg = err instanceof Error ? err.message : String(err);\n spinner?.fail(`Failed: ${targetUrl}`);\n results.push({ url: targetUrl, strategy, metrics: null, error: errMsg });\n\n if (!jsonOutput) {\n console.log(chalk.red(` ${errMsg}`));\n console.log(\"\");\n }\n }\n\n // Rate-limit delay between calls\n if (i < urls.length - 1) {\n await delay(2000);\n }\n }\n\n // Multi-page summary\n if (!jsonOutput && results.length > 1) {\n printMultiPageSummary(results);\n }\n\n // JSON output\n if (jsonOutput) {\n const output =\n results.length === 1\n ? {\n url: results[0].url,\n strategy: results[0].strategy,\n ...(results[0].metrics ?? {}),\n error: results[0].error ?? undefined,\n }\n : {\n strategy,\n pages: results.map((r) => ({\n url: r.url,\n ...(r.metrics ?? {}),\n error: r.error ?? undefined,\n })),\n summary: (() => {\n const valid = results.filter((r) => r.metrics);\n if (valid.length === 0) return null;\n return {\n avgScore: Math.round(\n valid.reduce(\n (s, r) => s + r.metrics!.performanceScore,\n 0,\n ) / valid.length,\n ),\n worstLcp: Math.max(\n ...valid.map((r) => r.metrics!.lcp),\n ),\n worstCls: Math.max(\n ...valid.map((r) => r.metrics!.cls),\n ),\n worstInp: Math.max(\n ...valid.map((r) => r.metrics!.inp),\n ),\n };\n })(),\n };\n console.log(JSON.stringify(output, null, 2));\n }\n\n // Budget enforcement\n const budgets = {\n lcp: opts.budgetLcp ? parseFloat(opts.budgetLcp) : undefined,\n cls: opts.budgetCls ? parseFloat(opts.budgetCls) : undefined,\n score: opts.budgetScore ? parseInt(opts.budgetScore, 10) : undefined,\n };\n\n const hasBudgets =\n budgets.lcp != null || budgets.cls != null || budgets.score != null;\n\n if (hasBudgets) {\n const allFailures: string[] = [];\n\n for (const r of results) {\n if (!r.metrics) continue;\n const failures = checkBudgets(r.metrics, budgets);\n if (failures.length > 0) {\n allFailures.push(...failures.map((f) => `${r.url}: ${f}`));\n }\n }\n\n if (allFailures.length > 0) {\n if (!jsonOutput) {\n console.log(chalk.red(chalk.bold(\" Budget exceeded:\")));\n for (const f of allFailures) {\n console.log(chalk.red(` ✗ ${f}`));\n }\n console.log(\"\");\n }\n process.exit(1);\n }\n }\n });\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { loadProjectConfig, saveProjectConfig, loadIndexNowKey } from \"../store.js\";\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n\nasync function openBrowser(url: string): Promise<void> {\n const { platform } = process;\n const { exec } = await import(\"node:child_process\");\n\n const cmd =\n platform === \"darwin\"\n ? \"open\"\n : platform === \"win32\"\n ? \"start\"\n : \"xdg-open\";\n\n exec(`${cmd} ${url}`);\n}\n\nexport const linkCommand = new Command(\"link\")\n .description(\"Link this project to your Indxel dashboard for monitoring\")\n .option(\"--api-key <key>\", \"Link directly with an API key (skip browser flow)\")\n .action(async (opts) => {\n const apiUrl = process.env.INDXEL_API_URL || \"https://indxel.com\";\n const cwd = process.cwd();\n\n console.log(\"\");\n console.log(chalk.bold(\" indxel link\"));\n console.log(\"\");\n\n // Check if already linked\n const existing = await loadProjectConfig(cwd);\n if (existing) {\n console.log(chalk.green(\" ✓\") + ` Already linked to ${chalk.bold(existing.projectName)}`);\n console.log(chalk.dim(` Project ID: ${existing.projectId}`));\n console.log(chalk.dim(` Linked at: ${existing.linkedAt}`));\n console.log(\"\");\n console.log(chalk.dim(\" To re-link, delete .indxel/config.json and run again.\"));\n console.log(\"\");\n return;\n }\n\n // Option 1: Direct API key\n if (opts.apiKey) {\n const spinner = ora(\"Verifying API key...\").start();\n\n try {\n const res = await fetch(`${apiUrl}/api/projects/by-key`, {\n headers: { Authorization: `Bearer ${opts.apiKey}` },\n signal: AbortSignal.timeout(10000),\n });\n\n if (!res.ok) {\n spinner.fail(\"Invalid API key.\");\n console.log(chalk.dim(\" Check your key at https://indxel.com/dashboard/settings\"));\n console.log(\"\");\n process.exit(1);\n }\n\n const body = (await res.json()) as { project: { id: string; name: string } };\n const project = body.project;\n spinner.succeed(`Linked to ${chalk.bold(project.name)}`);\n\n await saveProjectConfig(cwd, {\n apiKey: opts.apiKey,\n projectId: project.id,\n projectName: project.name,\n linkedAt: new Date().toISOString(),\n });\n\n // Sync IndexNow key if available\n await syncIndexNowKey(cwd, apiUrl, opts.apiKey, project.id);\n\n console.log(\"\");\n console.log(chalk.dim(\" Config saved to .indxel/config.json\"));\n console.log(chalk.dim(\" You can now use \") + chalk.bold(\"npx indxel crawl --push\") + chalk.dim(\" without --api-key.\"));\n console.log(\"\");\n return;\n } catch (err) {\n spinner.fail(err instanceof Error ? err.message : \"Connection failed\");\n console.log(\"\");\n process.exit(1);\n }\n }\n\n // Option 2: Device flow (browser-based)\n const initSpinner = ora(\"Starting device flow...\").start();\n\n let deviceCode: string;\n let userCode: string;\n\n try {\n const res = await fetch(`${apiUrl}/api/cli/auth`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n signal: AbortSignal.timeout(10000),\n });\n\n if (!res.ok) {\n initSpinner.fail(\"Could not start device flow.\");\n console.log(chalk.dim(\" You can also link directly: \") + chalk.bold(\"npx indxel link --api-key <your-key>\"));\n console.log(\"\");\n process.exit(1);\n }\n\n const data = (await res.json()) as { deviceCode: string; userCode: string };\n deviceCode = data.deviceCode;\n userCode = data.userCode;\n initSpinner.stop();\n } catch (err) {\n initSpinner.fail(err instanceof Error ? err.message : \"Connection failed\");\n console.log(chalk.dim(\" You can also link directly: \") + chalk.bold(\"npx indxel link --api-key <your-key>\"));\n console.log(\"\");\n process.exit(1);\n return; // unreachable, satisfies TS\n }\n\n const connectUrl = `${apiUrl}/cli/connect?code=${userCode}`;\n\n console.log(chalk.bold(\" Open this URL in your browser:\"));\n console.log(\"\");\n console.log(` ${chalk.underline(connectUrl)}`);\n console.log(\"\");\n console.log(` Your code: ${chalk.bold.cyan(userCode)}`);\n console.log(\"\");\n\n // Try to open browser automatically\n try {\n await openBrowser(connectUrl);\n console.log(chalk.dim(\" Browser opened automatically.\"));\n } catch {\n // Silently fail — user can open manually\n }\n\n // Poll for authorization\n const pollSpinner = ora(\"Waiting for authorization...\").start();\n const maxWait = 5 * 60 * 1000; // 5 minutes\n const pollInterval = 2000; // 2 seconds\n const startTime = Date.now();\n\n while (Date.now() - startTime < maxWait) {\n await delay(pollInterval);\n\n try {\n const res = await fetch(`${apiUrl}/api/cli/auth?code=${deviceCode}`, {\n signal: AbortSignal.timeout(10000),\n });\n\n if (res.status === 202) {\n // Still pending\n continue;\n }\n\n if (res.ok) {\n const data = (await res.json()) as {\n apiKey: string;\n projectId: string;\n projectName: string;\n };\n\n pollSpinner.succeed(`Linked to ${chalk.bold(data.projectName)}`);\n\n await saveProjectConfig(cwd, {\n apiKey: data.apiKey,\n projectId: data.projectId,\n projectName: data.projectName,\n linkedAt: new Date().toISOString(),\n });\n\n // Sync IndexNow key if available\n await syncIndexNowKey(cwd, apiUrl, data.apiKey, data.projectId);\n\n console.log(\"\");\n console.log(chalk.dim(\" Config saved to .indxel/config.json\"));\n console.log(chalk.dim(\" You can now use \") + chalk.bold(\"npx indxel crawl --push\") + chalk.dim(\" without --api-key.\"));\n console.log(\"\");\n return;\n }\n\n // Unexpected status\n pollSpinner.fail(\"Authorization failed.\");\n console.log(\"\");\n process.exit(1);\n } catch {\n // Network error — keep polling\n }\n }\n\n pollSpinner.fail(\"Timed out waiting for authorization (5 minutes).\");\n console.log(chalk.dim(\" Try again: \") + chalk.bold(\"npx indxel link\"));\n console.log(\"\");\n process.exit(1);\n });\n\n/**\n * Sync the local IndexNow key to the linked project on the dashboard.\n * This avoids the \"pending verification\" state in the dashboard UI.\n */\nasync function syncIndexNowKey(\n cwd: string,\n apiUrl: string,\n apiKey: string,\n projectId: string,\n): Promise<void> {\n const indexNowKey = await loadIndexNowKey(cwd);\n if (!indexNowKey) return;\n\n try {\n const res = await fetch(`${apiUrl}/api/projects/${projectId}/indexation/setup`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({ action: \"sync\", key: indexNowKey }),\n signal: AbortSignal.timeout(10000),\n });\n\n if (res.ok) {\n console.log(chalk.green(\" ✓\") + \" IndexNow key synced to dashboard\");\n }\n } catch {\n // Non-critical — skip silently\n }\n}\n","import { createProgram } from \"./index.js\";\n\nconst program = createProgram();\nprogram.parse();\n"],"mappings":";;;AAAA,SAAS,WAAAA,gBAAe;;;ACAxB,SAAS,eAAe;AACxB,OAAO,WAAW;AAClB,OAAO,SAAS;AAChB,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,aAAAC,YAAW,SAAAC,QAAO,YAAAC,iBAAgB;AAC3C,SAAS,QAAAC,aAAY;;;ACLrB,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB;AACzB,SAAS,YAAY;AAwBrB,eAAsB,cAAc,KAAmC;AACrE,QAAM,OAAoB;AAAA,IACxB,MAAM;AAAA,IACN,UAAU;AAAA,IACV,eAAe;AAAA,IACf,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,WAAW;AAAA,EACb;AAGA,QAAM,cAAc;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,OAAK,WAAW,YAAY,KAAK,CAAC,MAAM,WAAW,KAAK,KAAK,CAAC,CAAC,CAAC;AAGhE,QAAM,UAAU,KAAK,KAAK,cAAc;AACxC,MAAI,WAAW,OAAO,GAAG;AACvB,QAAI;AACF,YAAM,MAAM,KAAK,MAAM,MAAM,SAAS,SAAS,OAAO,CAAC;AACvD,YAAM,UAAU,IAAI,cAAc,QAAQ,IAAI,iBAAiB;AAC/D,UAAI,SAAS;AACX,aAAK,WAAW;AAChB,aAAK,cAAc,QAAQ,QAAQ,aAAa,EAAE,EAAE,KAAK;AAAA,MAC3D;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAGA,OAAK,eACH,WAAW,KAAK,KAAK,eAAe,CAAC,KACrC,WAAW,KAAK,KAAK,aAAa,CAAC;AAGrC,MAAI,WAAW,KAAK,KAAK,OAAO,KAAK,CAAC,GAAG;AACvC,SAAK,gBAAgB;AACrB,SAAK,SAAS;AAAA,EAChB,WAAW,WAAW,KAAK,KAAK,KAAK,CAAC,GAAG;AACvC,SAAK,gBAAgB;AACrB,SAAK,SAAS;AAAA,EAChB;AAGA,OAAK,eACH,WAAW,KAAK,KAAK,eAAe,CAAC,KACrC,WAAW,KAAK,KAAK,eAAe,CAAC;AAEvC,OAAK,aACH,WAAW,KAAK,KAAK,KAAK,QAAQ,YAAY,CAAC,KAC/C,WAAW,KAAK,KAAK,KAAK,QAAQ,YAAY,CAAC,KAC/C,WAAW,KAAK,KAAK,KAAK,QAAQ,aAAa,CAAC;AAElD,OAAK,YACH,WAAW,KAAK,KAAK,KAAK,QAAQ,WAAW,CAAC,KAC9C,WAAW,KAAK,KAAK,KAAK,QAAQ,WAAW,CAAC,KAC9C,WAAW,KAAK,KAAK,KAAK,QAAQ,YAAY,CAAC;AAEjD,SAAO;AACT;;;AC5FA,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,YAAAC,WAAU,WAAW,aAAa;AAC3C,SAAS,QAAAC,aAAY;AACrB,SAAS,mBAAmB;AAG5B,IAAM,YAAY;AAClB,IAAM,kBAAkB;AACxB,IAAM,oBAAoB;AAC1B,IAAM,cAAc;AAQpB,eAAsB,gBACpB,KACA,SACe;AACf,QAAM,WAAWA,MAAK,KAAK,SAAS;AAEpC,MAAI,CAACF,YAAW,QAAQ,GAAG;AACzB,UAAM,MAAM,UAAU,EAAE,WAAW,KAAK,CAAC;AAAA,EAC3C;AAEA,QAAM,SAAsB;AAAA,IAC1B,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,SAAS;AAAA,MACP,GAAG;AAAA;AAAA,MAEH,SAAS,QAAQ,QAAQ,IAAI,CAAC,OAAO;AAAA,QACnC,MAAM;AAAA,UACJ,UAAU,EAAE,KAAK;AAAA,UACjB,OAAO,EAAE,KAAK;AAAA,UACd,aAAa,EAAE,KAAK;AAAA,UACpB,oBAAoB,EAAE,KAAK;AAAA,UAC3B,mBAAmB,EAAE,KAAK;AAAA,UAC1B,iBAAiB,EAAE,KAAK;AAAA,UACxB,mBAAmB,EAAE,KAAK;AAAA,QAC5B;AAAA,QACA,YAAY,EAAE;AAAA,MAChB,EAAE;AAAA,IACJ;AAAA,EACF;AAEA,QAAM;AAAA,IACJE,MAAK,UAAU,eAAe;AAAA,IAC9B,KAAK,UAAU,QAAQ,MAAM,CAAC;AAAA,IAC9B;AAAA,EACF;AACF;AAGA,eAAsB,kBACpB,KAC6B;AAC7B,QAAM,WAAWA,MAAK,KAAK,WAAW,eAAe;AAErD,MAAI,CAACF,YAAW,QAAQ,GAAG;AACzB,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,OAAO,MAAMC,UAAS,UAAU,OAAO;AAC7C,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAQO,SAAS,sBAA8B;AAC5C,SAAO,YAAY,EAAE,EAAE,SAAS,KAAK;AACvC;AAGA,eAAsB,gBAAgB,KAAa,KAA4B;AAC7E,QAAM,WAAWE,MAAK,KAAK,SAAS;AACpC,MAAI,CAACC,YAAW,QAAQ,GAAG;AACzB,UAAM,MAAM,UAAU,EAAE,WAAW,KAAK,CAAC;AAAA,EAC3C;AACA,QAAM,UAAUD,MAAK,UAAU,iBAAiB,GAAG,KAAK,OAAO;AACjE;AAGA,eAAsB,gBAAgB,KAAqC;AACzE,QAAM,WAAWA,MAAK,KAAK,WAAW,iBAAiB;AACvD,MAAI,CAACC,YAAW,QAAQ,EAAG,QAAO;AAClC,MAAI;AACF,UAAM,OAAO,MAAMC,UAAS,UAAU,OAAO,GAAG,KAAK;AACrD,WAAO,OAAO;AAAA,EAChB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAYA,eAAsB,kBACpB,KACA,QACe;AACf,QAAM,WAAWF,MAAK,KAAK,SAAS;AACpC,MAAI,CAACC,YAAW,QAAQ,GAAG;AACzB,UAAM,MAAM,UAAU,EAAE,WAAW,KAAK,CAAC;AAAA,EAC3C;AACA,QAAM;AAAA,IACJD,MAAK,UAAU,WAAW;AAAA,IAC1B,KAAK,UAAU,QAAQ,MAAM,CAAC;AAAA,IAC9B;AAAA,EACF;AACF;AAGA,eAAsB,kBACpB,KAC+B;AAC/B,QAAM,WAAWA,MAAK,KAAK,WAAW,WAAW;AACjD,MAAI,CAACC,YAAW,QAAQ,EAAG,QAAO;AAClC,MAAI;AACF,UAAM,OAAO,MAAMC,UAAS,UAAU,OAAO;AAC7C,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAQA,eAAsB,cACpB,UACwB;AACxB,MAAI,SAAU,QAAO;AACrB,MAAI,QAAQ,IAAI,eAAgB,QAAO,QAAQ,IAAI;AACnD,QAAM,SAAS,MAAM,kBAAkB,QAAQ,IAAI,CAAC;AACpD,SAAO,QAAQ,UAAU;AAC3B;;;AC1JO,SAAS,kBAAkB,cAA+B;AAC/D,MAAI,cAAc;AAChB,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBT;AAEA,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWT;AAGO,SAAS,gBAAgB,cAA+B;AAC7D,MAAI,cAAc;AAChB,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBT;AAEA,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAcT;AAGO,SAAS,eAAe,cAA+B;AAC5D,MAAI,cAAc;AAChB,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBT;AAEA,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBT;;;AH3GA,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYf,IAAM,cAAc,IAAI,QAAQ,MAAM,EAC1C,YAAY,2CAA2C,EACvD,OAAO,gBAAgB,qBAAqB,QAAQ,IAAI,CAAC,EACzD,OAAO,WAAW,4BAA4B,KAAK,EACnD,OAAO,UAAU,2DAA2D,KAAK,EACjF,OAAO,OAAO,SAAS;AACtB,QAAM,MAAM,KAAK;AACjB,QAAM,UAAU,IAAI,sBAAsB,EAAE,MAAM;AAGlD,QAAM,UAAU,MAAM,cAAc,GAAG;AAEvC,MAAI,CAAC,QAAQ,UAAU;AACrB,YAAQ,KAAK,uBAAuB;AACpC,YAAQ;AAAA,MACN,MAAM,IAAI,oDAAoD;AAAA,IAChE;AACA,YAAQ;AAAA,MACN,MAAM,IAAI,4DAA4D;AAAA,IACxE;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ;AAAA,IACN,oBAAoB,QAAQ,eAAe,EAAE,KAAK,QAAQ,gBAAgB,eAAe,cAAc;AAAA,EACzG;AAEA,QAAM,MAAM,QAAQ,eAAe,OAAO;AAC1C,QAAM,eAAyB,CAAC;AAGhC,MAAI,CAAC,QAAQ,gBAAgB,KAAK,OAAO;AACvC,UAAM,aAAaC,MAAK,KAAK,cAAc,GAAG,EAAE;AAChD,UAAMC,WAAU,YAAY,kBAAkB,QAAQ,YAAY,GAAG,OAAO;AAC5E,iBAAa,KAAK,cAAc,GAAG,EAAE;AACrC,YAAQ,IAAI,MAAM,MAAM,UAAK,IAAI,yBAAyB,GAAG,EAAE;AAAA,EACjE,OAAO;AACL,YAAQ,IAAI,MAAM,IAAI,kBAAkB,GAAG,wBAAwB,CAAC;AAAA,EACtE;AAGA,MAAI,CAAC,QAAQ,cAAc,KAAK,OAAO;AACrC,UAAM,cAAcD,MAAK,KAAK,QAAQ,QAAQ,WAAW,GAAG,EAAE;AAC9D,UAAMC,WAAU,aAAa,gBAAgB,QAAQ,YAAY,GAAG,OAAO;AAC3E,iBAAa,KAAK,GAAG,QAAQ,MAAM,YAAY,GAAG,EAAE;AACpD,YAAQ,IAAI,MAAM,MAAM,UAAK,IAAI,cAAc,QAAQ,MAAM,YAAY,GAAG,EAAE;AAAA,EAChF,OAAO;AACL,YAAQ,IAAI,MAAM,IAAI,mCAAmC,CAAC;AAAA,EAC5D;AAGA,MAAI,CAAC,QAAQ,aAAa,KAAK,OAAO;AACpC,UAAM,aAAaD,MAAK,KAAK,QAAQ,QAAQ,UAAU,GAAG,EAAE;AAC5D,UAAMC,WAAU,YAAY,eAAe,QAAQ,YAAY,GAAG,OAAO;AACzE,iBAAa,KAAK,GAAG,QAAQ,MAAM,WAAW,GAAG,EAAE;AACnD,YAAQ,IAAI,MAAM,MAAM,UAAK,IAAI,cAAc,QAAQ,MAAM,WAAW,GAAG,EAAE;AAAA,EAC/E,OAAO;AACL,YAAQ,IAAI,MAAM,IAAI,kCAAkC,CAAC;AAAA,EAC3D;AAGA,QAAM,SAASD,MAAK,KAAK,MAAM;AAC/B,QAAM,SAASE,YAAW,MAAM;AAEhC,MAAI,KAAK,QAAQ,KAAK,OAAO;AAC3B,QAAI,CAAC,QAAQ;AACX,cAAQ,IAAI,MAAM,OAAO,UAAK,IAAI,mDAA8C;AAAA,IAClF,OAAO;AACL,YAAM,WAAWF,MAAK,QAAQ,OAAO;AACrC,YAAM,WAAWA,MAAK,UAAU,UAAU;AAG1C,UAAIE,YAAW,QAAQ,KAAK,CAAC,KAAK,OAAO;AACvC,cAAM,WAAW,MAAMC,UAAS,UAAU,OAAO;AACjD,YAAI,SAAS,SAAS,QAAQ,GAAG;AAC/B,kBAAQ,IAAI,MAAM,IAAI,4CAA4C,CAAC;AAAA,QACrE,OAAO;AACL,kBAAQ,IAAI,MAAM,OAAO,UAAK,IAAI,0DAA0D;AAAA,QAC9F;AAAA,MACF,OAAO;AACL,cAAMC,OAAM,UAAU,EAAE,WAAW,KAAK,CAAC;AACzC,cAAMH,WAAU,UAAU,eAAe,EAAE,MAAM,IAAM,CAAC;AACxD,qBAAa,KAAK,qBAAqB;AACvC,gBAAQ,IAAI,MAAM,MAAM,UAAK,IAAI,8BAA8B;AAAA,MACjE;AAAA,IACF;AAAA,EACF,WAAW,QAAQ;AACjB,YAAQ,IAAI,MAAM,IAAI,8CAA8C,CAAC;AAAA,EACvE;AAGA,QAAM,cAAc,MAAM,gBAAgB,GAAG;AAC7C,MAAI,CAAC,eAAe,KAAK,OAAO;AAC9B,UAAM,MAAM,oBAAoB;AAChC,UAAM,YAAYD,MAAK,KAAK,QAAQ;AACpC,QAAI,CAACE,YAAW,SAAS,GAAG;AAC1B,YAAME,OAAM,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,IAC5C;AACA,UAAMH,WAAUD,MAAK,WAAW,GAAG,GAAG,MAAM,GAAG,KAAK,OAAO;AAC3D,UAAM,gBAAgB,KAAK,GAAG;AAC9B,iBAAa,KAAK,UAAU,GAAG,MAAM;AACrC,YAAQ,IAAI,MAAM,MAAM,UAAK,IAAI,+EAA0E;AAAA,EAC7G,OAAO;AAEL,UAAM,UAAUA,MAAK,KAAK,UAAU,GAAG,WAAW,MAAM;AACxD,QAAIE,YAAW,OAAO,GAAG;AACvB,cAAQ,IAAI,MAAM,IAAI,oCAAoC,CAAC;AAAA,IAC7D,OAAO;AACL,YAAM,YAAYF,MAAK,KAAK,QAAQ;AACpC,UAAI,CAACE,YAAW,SAAS,GAAG;AAC1B,cAAME,OAAM,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,MAC5C;AACA,YAAMH,WAAU,SAAS,aAAa,OAAO;AAC7C,mBAAa,KAAK,UAAU,WAAW,MAAM;AAC7C,cAAQ,IAAI,MAAM,MAAM,UAAK,IAAI,6BAA6B;AAAA,IAChE;AAAA,EACF;AAGA,UAAQ,IAAI,EAAE;AACd,MAAI,aAAa,SAAS,GAAG;AAC3B,YAAQ;AAAA,MACN,MAAM,KAAK,KAAK,aAAa,MAAM,QAAQ,aAAa,SAAS,IAAI,MAAM,EAAE,WAAW;AAAA,IAC1F;AAAA,EACF,OAAO;AACL,YAAQ,IAAI,MAAM,IAAI,qDAAgD,CAAC;AACvE,YAAQ,IAAI,MAAM,IAAI,6BAA6B,CAAC;AAAA,EACtD;AAEA,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,MAAM,IAAI,eAAe,CAAC;AACtC,UAAQ,IAAI,MAAM,IAAI,0BAA0B,GAAG,yBAAyB,CAAC;AAC7E,UAAQ,IAAI,MAAM,IAAI,aAAa,IAAI,MAAM,KAAK,kBAAkB,IAAI,MAAM,IAAI,sBAAsB,CAAC;AACzG,MAAI,CAAC,KAAK,QAAQ,QAAQ;AACxB,YAAQ,IAAI,MAAM,IAAI,aAAa,IAAI,MAAM,KAAK,wBAAwB,IAAI,MAAM,IAAI,sBAAsB,CAAC;AAAA,EACjH;AACA,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,MAAM,IAAI,+BAA+B,CAAC;AACtD,UAAQ,IAAI,MAAM,IAAI,UAAU,IAAI,MAAM,KAAK,iBAAiB,IAAI,MAAM,IAAI,6BAA6B,CAAC;AAC5G,UAAQ,IAAI,EAAE;AAChB,CAAC;;;AItKH,SAAS,WAAAI,gBAAe;AACxB,OAAOC,YAAW;AAClB,OAAOC,UAAS;AAChB,SAAS,wBAAwB;;;ACHjC,SAAS,YAAAC,iBAAgB;AACzB,SAAS,QAAAC,OAAgB,SAAS,WAAW;AAC7C,SAAS,YAAY;AAwBrB,eAAsB,UACpB,aACA,QACqB;AACrB,QAAM,aAAaA,MAAK,aAAa,MAAM;AAG3C,QAAM,YAAY,MAAM,KAAK,2BAA2B;AAAA,IACtD,KAAK;AAAA,IACL,QAAQ,CAAC,sBAAsB,UAAU;AAAA,EAC3C,CAAC;AAED,QAAM,QAAoB,CAAC;AAE3B,aAAW,QAAQ,WAAW;AAC5B,UAAM,WAAWA,MAAK,YAAY,IAAI;AACtC,UAAM,UAAU,MAAMD,UAAS,UAAU,OAAO;AAChD,UAAM,QAAQ,gBAAgB,IAAI;AAClC,UAAM,WAAW,kBAAkB,OAAO;AAE1C,UAAM,OAAiB;AAAA,MACrB,UAAUC,MAAK,QAAQ,IAAI;AAAA,MAC3B;AAAA,MACA,aAAa;AAAA,MACb,oBAAoB;AAAA,MACpB,mBAAmB;AAAA,MACnB,iBAAiB;AAAA,MACjB,mBAAmB,oBAAoB;AAAA,IACzC;AAGA,SAAK,qBAAqB,UAAU,SAAS,kBAAkB;AAC/D,SAAK,cAAc,KAAK,sBAAsB,UAAU,SAAS,UAAU;AAG3E,QAAI,KAAK,oBAAoB;AAAA,IAG7B,WAAW,CAAC,YAAY,KAAK,aAAa;AAGxC,WAAK,oBAAoB,sBAAsB,OAAO;AAEtD,YAAM,YAAY,kBAAkB,OAAO;AAC3C,UAAI,aAAa,uBAAuB,KAAK,SAAS,GAAG;AACvD,aAAK,kBAAkB;AAAA,MACzB;AAAA,IACF;AAEA,UAAM,KAAK,IAAI;AAAA,EACjB;AAGA,QAAM,cAAc,MAAM,KAAK,6BAA6B;AAAA,IAC1D,KAAK;AAAA,IACL,QAAQ,CAAC,sBAAsB,UAAU;AAAA,EAC3C,CAAC;AAID,QAAM,gBAAgB,YAAY,KAAK,CAAC,GAAG,MAAM;AAC/C,UAAM,SAAS,EAAE,MAAM,GAAG,EAAE;AAC5B,UAAM,SAAS,EAAE,MAAM,GAAG,EAAE;AAC5B,WAAO,SAAS;AAAA,EAClB,CAAC;AAED,aAAW,QAAQ,eAAe;AAChC,UAAM,WAAWA,MAAK,YAAY,IAAI;AACtC,UAAM,UAAU,MAAMD,UAAS,UAAU,OAAO;AAChD,UAAM,QAAQ,gBAAgB,IAAI,EAAE,QAAQ,aAAa,EAAE,KAAK;AAEhE,UAAM,oBAAoB,UAAU,SAAS,UAAU,KAAK,UAAU,SAAS,kBAAkB;AACjG,QAAI,mBAAmB;AACrB,YAAM,aAAa,sBAAsB,OAAO;AAGhD,YAAM,gBAAgB,QAAQ,MAAM,oCAAoC;AACxE,YAAM,gBAAgB,gBAAgB,CAAC,KAAK;AAE5C,iBAAW,QAAQ,OAAO;AACxB,YAAI,KAAK,MAAM,WAAW,KAAK,KAAK,UAAU,KAAK;AAEjD,cAAI,KAAK,kBAAkB,SAAS,iBAAiB,CAAC,KAAK,iBAAiB;AAC1E,iBAAK,kBAAkB,QAAQ,cAAc,QAAQ,MAAM,KAAK,kBAAkB,KAAK;AACvF,iBAAK,kBAAkB;AAAA,UACzB;AAGA,wBAAc,KAAK,mBAAmB,UAAU;AAChD,cAAI,CAAC,KAAK,aAAa;AACrB,iBAAK,cAAc;AAAA,UACrB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,CAAC,GAAG,MAAM,EAAE,MAAM,cAAc,EAAE,KAAK,CAAC;AAC5D;AAGA,SAAS,gBAAgB,UAA0B;AACjD,QAAM,MAAM,QAAQ,QAAQ;AAC5B,MAAI,QAAQ,IAAK,QAAO;AAExB,QAAM,QAAQ,MAAM,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG;AAE3C,SAAO,MAAM,QAAQ,gBAAgB,EAAE,KAAK;AAC9C;AAGA,SAAS,kBAAkB,QAAyB;AAElD,SAAO,2BAA2B,KAAK,MAAM;AAC/C;AAGA,SAAS,UAAU,QAAgB,MAAuB;AAExD,QAAM,WAAW;AAAA,IACf,IAAI,OAAO,gCAAgC,IAAI,KAAK;AAAA,IACpD,IAAI,OAAO,qCAAqC,IAAI,KAAK;AAAA,IACzD,IAAI,OAAO,wBAAwB,IAAI,aAAa;AAAA,EACtD;AACA,SAAO,SAAS,KAAK,CAAC,MAAM,EAAE,KAAK,MAAM,CAAC;AAC5C;AAMA,SAAS,kBAAkB,QAA+B;AACxD,QAAM,QAAQ,OAAO,MAAM,0CAA0C;AACrE,MAAI,CAAC,SAAS,MAAM,UAAU,OAAW,QAAO;AAEhD,QAAM,QAAQ,OAAO,QAAQ,KAAK,MAAM,KAAK;AAC7C,MAAI,UAAU,GAAI,QAAO;AAEzB,MAAI,QAAQ;AACZ,WAAS,IAAI,OAAO,IAAI,OAAO,QAAQ,KAAK;AAC1C,QAAI,OAAO,CAAC,MAAM,IAAK;AAAA,aACd,OAAO,CAAC,MAAM,KAAK;AAC1B;AACA,UAAI,UAAU,EAAG,QAAO,OAAO,UAAU,OAAO,IAAI,CAAC;AAAA,IACvD;AAAA,EACF;AACA,SAAO;AACT;AAMA,SAAS,sBAAsB,QAAkC;AAC/D,QAAM,OAAO,oBAAoB;AAIjC,QAAM,YAAY,kBAAkB,MAAM,KAAK;AAM/C,QAAM,gBAAgB,UAAU;AAAA,IAC9B;AAAA,EACF;AACA,MAAI,eAAe;AACjB,SAAK,QAAQ,cAAc,CAAC;AAAA,EAC9B,OAAO;AACL,UAAM,eAAe,UAAU;AAAA,MAC7B;AAAA,IACF;AACA,QAAI,cAAc;AAChB,WAAK,QAAQ,aAAa,CAAC;AAAA,IAC7B,OAAO;AAEL,YAAM,aAAa,UAAU;AAAA,QAC3B;AAAA,MACF;AACA,UAAI,YAAY;AACd,aAAK,QAAQ,WAAW,CAAC;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAGA,QAAM,YAAY,UAAU;AAAA,IAC1B;AAAA,EACF;AACA,MAAI,WAAW;AACb,SAAK,cAAc,UAAU,CAAC;AAAA,EAChC;AAGA,MAAI,qBAAqB,KAAK,SAAS,GAAG;AACxC,UAAM,eAAe,UAAU;AAAA,MAC7B;AAAA,IACF;AACA,QAAI,aAAc,MAAK,UAAU,aAAa,CAAC;AAE/C,UAAM,cAAc,UAAU;AAAA,MAC5B;AAAA,IACF;AACA,QAAI,YAAa,MAAK,gBAAgB,YAAY,CAAC;AAEnD,QAAI,kBAAkB,KAAK,SAAS,GAAG;AACrC,WAAK,UAAU;AAAA,IACjB;AAAA,EACF;AAGA,MAAI,mBAAmB,KAAK,SAAS,GAAG;AACtC,UAAM,YAAY,UAAU;AAAA,MAC1B;AAAA,IACF;AACA,QAAI,UAAW,MAAK,cAAc,UAAU,CAAC;AAAA,EAC/C;AAGA,MAAI,kBAAkB,KAAK,SAAS,KAAK,qBAAqB,KAAK,SAAS,GAAG;AAC7E,UAAM,cAAc,UAAU;AAAA,MAC5B;AAAA,IACF;AACA,QAAI,YAAa,MAAK,SAAS,YAAY,CAAC;AAAA,EAC9C;AAGA,MAAI,sBAAsB,KAAK,SAAS,GAAG;AACzC,UAAM,iBAAiB,UAAU;AAAA,MAC/B;AAAA,IACF;AACA,QAAI,eAAgB,MAAK,YAAY,eAAe,CAAC;AAGrD,QAAI,qBAAqB,KAAK,SAAS,GAAG;AACxC,YAAM,QAAgC,CAAC;AACvC,YAAM,cAAc,UAAU;AAAA,QAC5B;AAAA,MACF;AACA,iBAAW,KAAK,aAAa;AAC3B,YAAI,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,WAAW,MAAM,GAAG;AAC3C,gBAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AAAA,QACnB;AAAA,MACF;AACA,UAAI,OAAO,KAAK,KAAK,EAAE,SAAS,GAAG;AACjC,aAAK,aAAa;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AAMA,MAAI,CAAC,KAAK,SAAS,+CAA+C,KAAK,SAAS,GAAG;AACjF,SAAK,QAAQ;AAAA,EACf;AACA,MAAI,CAAC,KAAK,eAAe,8CAA8C,KAAK,SAAS,GAAG;AACtF,SAAK,cAAc;AAAA,EACrB;AACA,MAAI,qBAAqB,KAAK,SAAS,GAAG;AACxC,QAAI,CAAC,KAAK,QAAS,MAAK,UAAU;AAClC,QAAI,CAAC,KAAK,cAAe,MAAK,gBAAgB;AAC9C,QAAI,CAAC,KAAK,QAAS,MAAK,UAAU;AAAA,EACpC;AACA,MAAI,mBAAmB,KAAK,SAAS,GAAG;AACtC,QAAI,CAAC,KAAK,YAAa,MAAK,cAAc;AAAA,EAC5C;AACA,MAAI,sBAAsB,KAAK,SAAS,KAAK,CAAC,KAAK,WAAW;AAC5D,QAAI,gBAAgB,KAAK,SAAS,EAAG,MAAK,YAAY;AAAA,EACxD;AAGA,MAAI,wBAAwB,KAAK,MAAM,KAAK,aAAa,KAAK,MAAM,KAAK,SAAS,KAAK,MAAM,GAAG;AAC9F,SAAK,iBAAiB,CAAC,EAAE,YAAY,sBAAsB,SAAS,WAAW,CAAC;AAAA,EAClF;AAGA,MAAI,kBAAkB,KAAK,MAAM,GAAG;AAClC,SAAK,WAAW;AAAA,EAClB;AAGA,MAAI,iBAAiB,KAAK,SAAS,KAAK,UAAU,KAAK,SAAS,GAAG;AACjE,SAAK,UAAU;AAAA,EACjB;AAEA,SAAO;AACT;AAEA,SAAS,sBAAwC;AAC/C,SAAO;AAAA,IACL,OAAO;AAAA,IACP,aAAa;AAAA,IACb,WAAW;AAAA,IACX,SAAS;AAAA,IACT,eAAe;AAAA,IACf,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,cAAc;AAAA,IACd,oBAAoB;AAAA,IACpB,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,UAAU;AAAA,IACV,SAAS;AAAA,EACX;AACF;AAGA,SAAS,cAAc,QAA0B,QAAgC;AAC/E,aAAW,OAAO,OAAO,KAAK,MAAM,GAAiC;AACnE,QAAI,OAAO,GAAG,MAAM,QAAQ,OAAO,GAAG,MAAM,QAAW;AACrD,MAAC,OAAmC,GAAG,IAAI,OAAO,GAAG;AAAA,IACvD;AAAA,EACF;AACF;;;ACxVA,SAAS,cAAAE,mBAAkB;AAC3B,SAAS,YAAAC,iBAAgB;AACzB,SAAS,QAAAC,aAAY;AAarB,IAAM,eAAe,CAAC,kBAAkB,aAAa,oBAAoB;AAMzE,eAAsB,WAAW,KAAoC;AACnE,aAAW,QAAQ,cAAc;AAC/B,UAAM,OAAOA,MAAK,KAAK,IAAI;AAC3B,QAAIF,YAAW,IAAI,GAAG;AACpB,UAAI;AACF,cAAM,UAAU,MAAMC,UAAS,MAAM,OAAO;AAC5C,eAAO,KAAK,MAAM,OAAO;AAAA,MAC3B,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACA,SAAO,CAAC;AACV;;;AClCA,OAAOE,YAAW;AAwBX,SAAS,iBAAiB,QAA6B;AAC5D,QAAM,EAAE,MAAM,WAAW,IAAI;AAC7B,QAAM,QAAkB,CAAC;AAEzB,QAAMC,cAAa,cAAc,WAAW,KAAK;AACjD,QAAM,OAAO,WAAW,OAAO,SAAS,IAAID,OAAM,IAAI,GAAG,IAAIA,OAAM,MAAM,QAAG;AAE5E,QAAM;AAAA,IACJ,KAAK,IAAI,IAAIA,OAAM,KAAK,KAAK,KAAK,CAAC,KAAKC,YAAW,GAAG,WAAW,KAAK,MAAM,CAAC;AAAA,EAC/E;AAGA,aAAW,SAAS,WAAW,QAAQ;AACrC,UAAM,KAAK,OAAOD,OAAM,IAAI,GAAG,CAAC,IAAI,MAAM,WAAW,MAAM,IAAI,EAAE;AAAA,EACnE;AAGA,MAAI,WAAW,OAAO,SAAS,GAAG;AAChC,eAAW,WAAW,WAAW,UAAU;AACzC,YAAM,KAAK,OAAOA,OAAM,OAAO,GAAG,CAAC,IAAI,QAAQ,WAAW,QAAQ,IAAI,EAAE;AAAA,IAC1E;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAGO,SAAS,cAAc,SAA+B;AAC3D,QAAM,QAAkB,CAAC;AACzB,QAAM,EAAE,YAAY,aAAa,cAAc,eAAe,IAAI;AAElE,QAAM,KAAK,EAAE;AACb,QAAM,KAAKA,OAAM,IAAI,kOAAyC,CAAC;AAC/D,QAAM,KAAK,EAAE;AAGb,QAAMC,cAAa,cAAc,YAAY;AAC7C,QAAM;AAAA,IACJ,YAAYA,YAAWD,OAAM,KAAK,GAAG,YAAY,MAAM,CAAC,CAAC,KAAK,QAAQ,KAAK;AAAA,EAC7E;AAGA,QAAM,aAAa,gBAAgB,aAAaA,OAAM,QAAQA,OAAM;AACpE,QAAM;AAAA,IACJ,YAAY,WAAW,GAAG,WAAW,IAAI,UAAU,EAAE,CAAC;AAAA,EACxD;AAGA,MAAI,iBAAiB,GAAG;AACtB,UAAM,KAAK,EAAE;AACb,UAAM;AAAA,MACJA,OAAM,IAAI,KAAK,cAAc,kBAAkB,iBAAiB,IAAI,MAAM,EAAE,yBAAyB;AAAA,IACvG;AACA,QAAI,QAAQ,iBAAiB,GAAG;AAC9B,YAAM;AAAA,QACJA,OAAM,OAAO,KAAK,QAAQ,cAAc,kBAAkB,QAAQ,iBAAiB,IAAI,MAAM,EAAE,oBAAoB;AAAA,MACrH;AAAA,IACF;AAAA,EACF,WAAW,QAAQ,iBAAiB,GAAG;AACrC,UAAM,KAAK,EAAE;AACb,UAAM,KAAKA,OAAM,OAAO,KAAK,QAAQ,cAAc,kBAAkB,QAAQ,iBAAiB,IAAI,MAAM,EAAE,oBAAoB,CAAC;AAAA,EACjI,OAAO;AACL,UAAM,KAAK,EAAE;AACb,UAAM,KAAKA,OAAM,MAAM,4BAA4B,CAAC;AAAA,EACtD;AAGA,MAAI,QAAQ,iBAAiB,GAAG;AAC9B,UAAM,KAAK,EAAE;AACb,UAAM;AAAA,MACJA,OAAM;AAAA,QACJ,KAAK,QAAQ,cAAc,gBAAgB,QAAQ,iBAAiB,IAAI,MAAM,EAAE;AAAA,MAClF;AAAA,IACF;AACA,UAAM,KAAKA,OAAM,IAAI,kEAAkE,CAAC;AAAA,EAC1F;AAEA,QAAM,KAAK,EAAE;AACb,SAAO,MAAM,KAAK,IAAI;AACxB;AAGO,SAAS,WAAW,SAA+B;AACxD,SAAO,KAAK;AAAA,IACV;AAAA,MACE,OAAO,QAAQ;AAAA,MACf,OAAO,QAAQ;AAAA,MACf,YAAY,QAAQ;AAAA,MACpB,aAAa,QAAQ;AAAA,MACrB,gBAAgB,QAAQ;AAAA,MACxB,gBAAgB,QAAQ;AAAA,MACxB,gBAAgB,QAAQ;AAAA,MACxB,OAAO,QAAQ,QAAQ,IAAI,CAAC,OAAO;AAAA,QACjC,OAAO,EAAE,KAAK;AAAA,QACd,MAAM,EAAE,KAAK;AAAA,QACb,OAAO,EAAE,WAAW;AAAA,QACpB,OAAO,EAAE,WAAW;AAAA,QACpB,QAAQ,EAAE,WAAW,OAAO,IAAI,CAAC,OAAO;AAAA,UACtC,IAAI,EAAE;AAAA,UACN,SAAS,EAAE;AAAA,QACb,EAAE;AAAA,QACF,UAAU,EAAE,WAAW,SAAS,IAAI,CAAC,OAAO;AAAA,UAC1C,IAAI,EAAE;AAAA,UACN,SAAS,EAAE;AAAA,QACb,EAAE;AAAA,MACJ,EAAE;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAGO,SAAS,WACd,SACA,UACQ;AACR,QAAM,QAAkB,CAAC;AAEzB,QAAM,KAAK,EAAE;AACb,QAAM,KAAKA,OAAM,KAAK,aAAa,CAAC;AACpC,QAAM,KAAK,EAAE;AAEb,QAAM,aAAa,QAAQ,eAAe,SAAS;AACnD,QAAM,aAAa,aAAa,IAAIA,OAAM,MAAM,IAAI,UAAU,EAAE,IAAI,aAAa,IAAIA,OAAM,IAAI,GAAG,UAAU,EAAE,IAAIA,OAAM,IAAI,GAAG;AAC/H,QAAM;AAAA,IACJ,YAAY,SAAS,YAAY,OAAO,QAAQ,YAAY,KAAK,UAAU;AAAA,EAC7E;AACA,QAAM,KAAK,EAAE;AAGb,QAAM,UAAU,IAAI,IAAI,SAAS,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC;AACtE,QAAM,UAAU,IAAI,IAAI,QAAQ,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC;AAGrE,QAAM,cAAwB,CAAC;AAC/B,aAAW,CAAC,OAAO,IAAI,KAAK,SAAS;AACnC,UAAM,OAAO,QAAQ,IAAI,KAAK;AAC9B,QAAI,CAAC,KAAM;AACX,QAAI,KAAK,WAAW,QAAQ,KAAK,WAAW,OAAO;AACjD,kBAAY;AAAA,QACV,OAAOA,OAAM,IAAI,GAAG,CAAC,IAAI,KAAK,KAAK,KAAK,WAAW,KAAK,OAAO,KAAK,WAAW,KAAK;AAAA,MACtF;AAAA,IACF;AAAA,EACF;AAGA,QAAM,eAAyB,CAAC;AAChC,aAAW,CAAC,OAAO,IAAI,KAAK,SAAS;AACnC,UAAM,OAAO,QAAQ,IAAI,KAAK;AAC9B,QAAI,CAAC,KAAM;AACX,QAAI,KAAK,WAAW,QAAQ,KAAK,WAAW,OAAO;AACjD,mBAAa;AAAA,QACX,OAAOA,OAAM,MAAM,GAAG,CAAC,IAAI,KAAK,KAAK,KAAK,WAAW,KAAK,OAAO,KAAK,WAAW,KAAK;AAAA,MACxF;AAAA,IACF;AAAA,EACF;AAGA,QAAM,WAAqB,CAAC;AAC5B,aAAW,SAAS,QAAQ,KAAK,GAAG;AAClC,QAAI,CAAC,QAAQ,IAAI,KAAK,GAAG;AACvB,eAAS,KAAK,OAAOA,OAAM,KAAK,GAAG,CAAC,IAAI,KAAK,KAAKA,OAAM,IAAI,OAAO,CAAC,EAAE;AAAA,IACxE;AAAA,EACF;AAGA,QAAM,UAAoB,CAAC;AAC3B,aAAW,SAAS,QAAQ,KAAK,GAAG;AAClC,QAAI,CAAC,QAAQ,IAAI,KAAK,GAAG;AACvB,cAAQ,KAAK,OAAOA,OAAM,IAAI,GAAG,CAAC,IAAI,KAAK,KAAKA,OAAM,IAAI,WAAW,CAAC,EAAE;AAAA,IAC1E;AAAA,EACF;AAEA,MAAI,YAAY,SAAS,GAAG;AAC1B,UAAM,KAAKA,OAAM,IAAI,kBAAkB,YAAY,MAAM,IAAI,CAAC;AAC9D,UAAM,KAAK,GAAG,WAAW;AACzB,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,MAAI,aAAa,SAAS,GAAG;AAC3B,UAAM,KAAKA,OAAM,MAAM,mBAAmB,aAAa,MAAM,IAAI,CAAC;AAClE,UAAM,KAAK,GAAG,YAAY;AAC1B,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,MAAI,SAAS,SAAS,GAAG;AACvB,UAAM,KAAKA,OAAM,KAAK,gBAAgB,SAAS,MAAM,IAAI,CAAC;AAC1D,UAAM,KAAK,GAAG,QAAQ;AACtB,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,MAAI,QAAQ,SAAS,GAAG;AACtB,UAAM,KAAKA,OAAM,IAAI,cAAc,QAAQ,MAAM,IAAI,CAAC;AACtD,UAAM,KAAK,GAAG,OAAO;AACrB,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,MAAI,YAAY,WAAW,KAAK,aAAa,WAAW,KAAK,SAAS,WAAW,KAAK,QAAQ,WAAW,GAAG;AAC1G,UAAM,KAAKA,OAAM,IAAI,wBAAwB,CAAC;AAC9C,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAGO,SAAS,kBAAkB,MAA+C;AAC/E,SAAO,KAAKA,OAAM,KAAK,GAAG,CAAC,IAAIA,OAAM,KAAK,KAAK,KAAK,CAAC,KAAKA,OAAM,IAAI,mCAA8B,CAAC;AACrG;AAGA,SAAS,cAAc,OAAyC;AAC9D,MAAI,SAAS,GAAI,QAAOA,OAAM;AAC9B,MAAI,SAAS,GAAI,QAAOA,OAAM;AAC9B,SAAOA,OAAM;AACf;AAGO,SAAS,eAAe,SAAwB,iBAAiB,GAAiB;AACvF,QAAM,aAAa,QAAQ,SAAS;AACpC,QAAM,cAAc,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,OAAO,WAAW,CAAC,EAAE;AAC5E,QAAM,eACJ,QAAQ,SAAS,IACb,KAAK,MAAM,QAAQ,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,WAAW,OAAO,CAAC,IAAI,QAAQ,MAAM,IACnF;AAEN,MAAI,iBAAiB;AACrB,MAAI,iBAAiB;AACrB,aAAW,KAAK,SAAS;AACvB,eAAW,KAAK,EAAE,WAAW,QAAQ;AACnC,UAAI,EAAE,aAAa,WAAY;AAAA,UAC1B;AAAA,IACP;AAAA,EACF;AAEA,MAAI;AACJ,MAAI,gBAAgB,GAAI,SAAQ;AAAA,WACvB,gBAAgB,GAAI,SAAQ;AAAA,WAC5B,gBAAgB,GAAI,SAAQ;AAAA,WAC5B,gBAAgB,GAAI,SAAQ;AAAA,MAChC,SAAQ;AAEb,SAAO,EAAE,SAAS,YAAY,aAAa,cAAc,OAAO,gBAAgB,gBAAgB,eAAe;AACjH;;;AC5QA,OAAOE,YAAW;AAOX,SAAS,uBACd,SACA,SACU;AACV,QAAM,SAAmB,CAAC;AAC1B,QAAM,UAAU,WAAW;AAE3B,aAAW,EAAE,MAAM,WAAW,KAAK,SAAS;AAC1C,QAAI,WAAW,OAAO,WAAW,KAAK,WAAW,SAAS,WAAW,EAAG;AAExE,UAAM,WAAW,IAAI,IAAI,WAAW,OAAO,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAC3D,UAAM,UAAU,IAAI,IAAI,WAAW,SAAS,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAC5D,UAAM,SAAS,oBAAI,IAAI,CAAC,GAAG,UAAU,GAAG,OAAO,CAAC;AAGhD,UAAM,OAAgC,CAAC;AACvC,UAAM,SAAmB,CAAC;AAG1B,QAAI,OAAO,IAAI,eAAe,GAAG;AAC/B,YAAM,aAAa,aAAa,KAAK,KAAK;AAC1C,WAAK,QAAQ,EAAE,UAAU,WAAW;AAAA,IACtC,WAAW,OAAO,IAAI,cAAc,GAAG;AACrC,YAAM,UAAU,KAAK,kBAAkB,SAAS;AAChD,YAAM,MAAM,QAAQ;AACpB,UAAI,MAAM,IAAI;AACZ,eAAO,KAAK,KAAKA,OAAM,IAAI,iBAAiB,MAAM,+BAA0B,CAAC,EAAE;AAAA,MACjF,WAAW,MAAM,IAAI;AACnB,eAAO,KAAK,KAAKA,OAAM,IAAI,iBAAiB,MAAM,gCAA2B,CAAC,EAAE;AAAA,MAClF;AAAA,IACF;AAGA,QAAI,OAAO,IAAI,qBAAqB,GAAG;AACrC,WAAK,cAAc,mBAAmB,KAAK,KAAK;AAAA,IAClD,WAAW,OAAO,IAAI,oBAAoB,GAAG;AAC3C,YAAM,UAAU,KAAK,kBAAkB,eAAe;AACtD,YAAM,MAAM,QAAQ;AACpB,UAAI,MAAM,KAAK;AACb,eAAO,KAAK,KAAKA,OAAM,IAAI,uBAAuB,MAAM,iCAA4B,CAAC,EAAE;AAAA,MACzF,WAAW,MAAM,KAAK;AACpB,eAAO,KAAK,KAAKA,OAAM,IAAI,uBAAuB,MAAM,kCAA6B,CAAC,EAAE;AAAA,MAC1F;AAAA,IACF;AAGA,QAAI,OAAO,IAAI,eAAe,GAAG;AAC/B,YAAM,YAAY,GAAG,OAAO,GAAG,KAAK,UAAU,MAAM,KAAK,KAAK,KAAK;AACnE,WAAK,aAAa,EAAE,UAAU;AAAA,IAChC;AAGA,QAAI,OAAO,IAAI,UAAU,GAAG;AAC1B,WAAK,YAAY,EAAE,QAAQ,CAAC,GAAG,OAAO,eAAe,EAAE;AAAA,IACzD;AAGA,QAAI,OAAO,IAAI,yBAAyB,GAAG;AACzC,aAAO,KAAK,KAAKA,OAAM,IAAI,2DAA2D,CAAC,EAAE;AACzF,aAAO,KAAK,KAAKA,OAAM,IAAI,8EAA8E,CAAC,EAAE;AAAA,IAC9G;AAGA,QAAI,OAAO,IAAI,cAAc,GAAG;AAC9B,WAAK,UAAU,EAAE,MAAM,sBAAsB;AAAA,IAC/C;AAGA,QAAI,OAAO,KAAK,IAAI,EAAE,WAAW,KAAK,OAAO,WAAW,EAAG;AAE3D,WAAO,KAAKA,OAAM,KAAK,KAAKA,OAAM,KAAK,KAAK,QAAQ,CAAC,EAAE,CAAC;AAExD,QAAI,OAAO,KAAK,IAAI,EAAE,SAAS,GAAG;AAChC,YAAM,OAAO,qBAAqB,IAAI;AACtC,aAAO,KAAK,KAAKA,OAAM,IAAI,+BAA+B,CAAC,EAAE;AAC7D,aAAO,KAAK,EAAE;AACd,iBAAW,QAAQ,KAAK,MAAM,IAAI,GAAG;AACnC,eAAO,KAAK,OAAOA,OAAM,OAAO,IAAI,CAAC,EAAE;AAAA,MACzC;AAAA,IACF;AAEA,eAAW,SAAS,QAAQ;AAC1B,aAAO,KAAK,KAAK;AAAA,IACnB;AAEA,WAAO,KAAK,EAAE;AAAA,EAChB;AAEA,SAAO;AACT;AAGA,SAAS,aAAa,OAAuB;AAC3C,MAAI,UAAU,IAAK,QAAO;AAC1B,QAAM,WAAW,MAAM,MAAM,GAAG,EAAE,OAAO,OAAO;AAChD,QAAM,OAAO,SAAS,SAAS,SAAS,CAAC;AACzC,QAAM,OAAO,KACV,QAAQ,YAAY,EAAE,EACtB,QAAQ,MAAM,GAAG,EACjB,QAAQ,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC,EACvC,KAAK;AACR,SAAO,GAAG,QAAQ,MAAM;AAC1B;AAGA,SAAS,mBAAmB,OAAuB;AACjD,MAAI,UAAU,KAAK;AACjB,WAAO;AAAA,EACT;AACA,QAAM,WAAW,MAAM,MAAM,GAAG,EAAE,OAAO,OAAO;AAChD,QAAM,OAAO,SAAS,SAAS,SAAS,CAAC;AACzC,QAAM,OAAO,KACV,QAAQ,YAAY,EAAE,EACtB,QAAQ,MAAM,GAAG,EACjB,KAAK;AACR,SAAO,oBAAoB,QAAQ,WAAW;AAChD;AAGA,SAAS,qBAAqB,MAAuC;AACnE,QAAM,QAAkB,CAAC,qCAAqC;AAE9D,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC/C,QAAI,OAAO,UAAU,UAAU;AAC7B,YAAM,KAAK,KAAK,GAAG,MAAM,KAAK,IAAI;AAAA,IACpC,WAAW,OAAO,UAAU,YAAY,UAAU,MAAM;AACtD,YAAM,KAAK,KAAK,GAAG,KAAK,KAAK,UAAU,OAAO,MAAM,CAAC,EAAE,QAAQ,OAAO,MAAM,CAAC,GAAG;AAAA,IAClF;AAAA,EACF;AAEA,QAAM,KAAK,IAAI;AACf,SAAO,MAAM,KAAK,IAAI;AACxB;;;AJxHO,IAAM,eAAe,IAAIC,SAAQ,OAAO,EAC5C,YAAY,kDAAkD,EAC9D,OAAO,gBAAgB,qBAAqB,QAAQ,IAAI,CAAC,EACzD,OAAO,QAAQ,iDAA4C,KAAK,EAChE,OAAO,UAAU,mCAAmC,KAAK,EACzD,OAAO,UAAU,0BAA0B,KAAK,EAChD,OAAO,YAAY,4BAA4B,KAAK,EACpD,OAAO,uBAAuB,2DAA2D,EACzF,OAAO,SAAS,8CAA8C,KAAK,EACnE,OAAO,OAAO,SAAS;AACtB,QAAM,MAAM,KAAK;AACjB,QAAM,OAAO,KAAK;AAClB,QAAM,WAAW,KAAK,UAAU;AAChC,QAAM,WAAW,KAAK;AACtB,QAAM,aAAa,KAAK;AACxB,QAAM,UAAU,KAAK;AAGrB,QAAM,SAAS,MAAM,WAAW,GAAG;AAGnC,QAAM,WAAW,KAAK,WAClB,SAAS,KAAK,UAAU,EAAE,IAC1B,OAAO,YAAY;AAGvB,QAAM,UAAUC,KAAI,sBAAsB,EAAE,MAAM;AAClD,QAAM,UAAU,MAAM,cAAc,GAAG;AAEvC,MAAI,CAAC,QAAQ,UAAU;AACrB,YAAQ,KAAK,uBAAuB;AACpC,QAAI,CAAC,YAAY;AACf,cAAQ,IAAIC,OAAM,IAAI,iDAAiD,CAAC;AAAA,IAC1E;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,CAAC,QAAQ,eAAe;AAC1B,YAAQ,KAAK,yBAAyB;AACtC,QAAI,CAAC,YAAY;AACf,cAAQ,IAAIA,OAAM,IAAI,kEAAkE,CAAC;AAAA,IAC3F;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,UAAQ,OAAO;AACf,QAAM,WAAW,MAAM,UAAU,KAAK,QAAQ,MAAM;AAEpD,MAAI,SAAS,WAAW,GAAG;AACzB,YAAQ,KAAK,gBAAgB;AAC7B,QAAI,CAAC,YAAY;AACf,cAAQ,IAAIA,OAAM,IAAI,mCAAmC,QAAQ,MAAM,GAAG,CAAC;AAAA,IAC7E;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,eAAe,OAAO,gBAAgB,CAAC;AAC7C,QAAM,QAAQ,aAAa,SAAS,IAChC,SAAS,OAAO,CAAC,MAAM,CAAC,aAAa,KAAK,CAAC,YAAY,WAAW,EAAE,OAAO,OAAO,CAAC,CAAC,IACpF;AACJ,QAAM,eAAe,SAAS,SAAS,MAAM;AAE7C,UAAQ,QAAQ,SAAS,SAAS,MAAM,QAAQ,SAAS,SAAS,IAAI,MAAM,EAAE,GAAG,eAAe,IAAI,KAAK,YAAY,cAAc,EAAE,EAAE;AAGvI,QAAM,cAAc,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,kBAAkB;AAC7D,QAAM,eAAe,MAAM,OAAO,CAAC,MAAM,EAAE,kBAAkB;AAE7D,MAAI,CAAC,YAAY;AACf,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAIA,OAAM,KAAK,cAAc,YAAY,MAAM,QAAQ,YAAY,WAAW,IAAI,MAAM,EAAE,KAAK,CAAC;AACxG,QAAI,aAAa,SAAS,GAAG;AAC3B,cAAQ,IAAIA,OAAM,IAAI,MAAM,aAAa,MAAM,gBAAgB,aAAa,WAAW,IAAI,MAAM,EAAE,WAAW,CAAC;AAAA,IACjH;AACA,QAAI,eAAe,GAAG;AACpB,cAAQ,IAAIA,OAAM,IAAI,MAAM,YAAY,QAAQ,iBAAiB,IAAI,MAAM,EAAE,4BAA4B,CAAC;AAAA,IAC5G;AACA,YAAQ,IAAI,EAAE;AAAA,EAChB;AAGA,QAAM,UAAyB,CAAC;AAEhC,aAAW,QAAQ,aAAa;AAC9B,UAAM,aAAa,iBAAiB,KAAK,mBAAmB;AAAA,MAC1D,QAAQ;AAAA,MACR,eAAe,OAAO;AAAA,IACxB,CAAC;AAED,UAAM,SAAsB,EAAE,MAAM,WAAW;AAC/C,YAAQ,KAAK,MAAM;AAEnB,QAAI,CAAC,YAAY;AACf,cAAQ,IAAI,iBAAiB,MAAM,CAAC;AAAA,IACtC;AAAA,EACF;AAGA,MAAI,CAAC,cAAc,aAAa,SAAS,GAAG;AAC1C,YAAQ,IAAI,EAAE;AACd,eAAW,QAAQ,cAAc;AAC/B,cAAQ,IAAI,kBAAkB,IAAI,CAAC;AAAA,IACrC;AAAA,EACF;AAGA,QAAM,UAAU,eAAe,SAAS,aAAa,MAAM;AAG3D,QAAM,gBAAgB,KAAK,OAAO;AAGlC,MAAI,YAAY,CAAC,YAAY;AAC3B,UAAM,WAAW,MAAM,kBAAkB,GAAG;AAC5C,QAAI,UAAU;AACZ,cAAQ,IAAI,WAAW,SAAS,SAAS,OAAO,CAAC;AAAA,IACnD,OAAO;AACL,cAAQ,IAAIA,OAAM,IAAI,yDAAyD,CAAC;AAAA,IAClF;AAAA,EACF;AAGA,MAAI,YAAY;AACd,YAAQ,IAAI,WAAW,OAAO,CAAC;AAAA,EACjC,OAAO;AACL,YAAQ,IAAI,cAAc,OAAO,CAAC;AAAA,EACpC;AAGA,MAAI,WAAW,CAAC,YAAY;AAC1B,UAAM,QAAQ,uBAAuB,SAAS,OAAO,OAAO;AAC5D,QAAI,MAAM,SAAS,GAAG;AACpB,cAAQ,IAAIA,OAAM,KAAK,sBAAsB,CAAC;AAC9C,iBAAW,OAAO,OAAO;AACvB,gBAAQ,IAAI,GAAG;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,aAAa,MAAM;AAErB,QAAI,QAAQ,eAAe,UAAU;AACnC,UAAI,CAAC,YAAY;AACf,gBAAQ;AAAA,UACNA,OAAM,IAAI,WAAW,QAAQ,YAAY,qBAAqB,QAAQ,GAAG;AAAA,QAC3E;AAAA,MACF;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,WAAW,QAAQ,iBAAiB,GAAG;AAErC,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAIH,SAAS,WAAW,OAAe,SAA0B;AAC3D,MAAI,QAAQ,SAAS,IAAI,GAAG;AAC1B,UAAM,SAAS,QAAQ,MAAM,GAAG,EAAE;AAClC,WAAO,UAAU,UAAU,MAAM,WAAW,SAAS,GAAG;AAAA,EAC1D;AACA,SAAO,UAAU;AACnB;;;AKzLA,SAAS,WAAAC,gBAAe;AACxB,OAAOC,YAAW;AAClB,OAAOC,UAAS;AAChB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAIP,SAAS,WAAW,OAA6B;AAC/C,MAAI,SAAS,GAAI,QAAOC,OAAM;AAC9B,MAAI,SAAS,GAAI,QAAOA,OAAM;AAC9B,SAAOA,OAAM;AACf;AAEO,IAAM,eAAe,IAAIC,SAAQ,OAAO,EAC5C,YAAY,4EAA4E,EACxF,SAAS,SAAS,oDAAoD,EACtE,OAAO,mBAAmB,0BAA0B,KAAK,EACzD,OAAO,mBAAmB,sBAAsB,GAAG,EACnD,OAAO,gBAAgB,gCAAgC,KAAK,EAC5D,OAAO,UAAU,0BAA0B,KAAK,EAChD,OAAO,YAAY,4BAA4B,KAAK,EACpD,OAAO,iBAAiB,2BAA2B,KAAK,EACxD,OAAO,kBAAkB,sBAAsB,KAAK,EACpD,OAAO,iBAAiB,yBAAyB,KAAK,EACtD,OAAO,uBAAuB,+EAA+E,EAC7G,OAAO,UAAU,oCAAoC,KAAK,EAC1D,OAAO,mBAAmB,oDAAoD,EAC9E,OAAO,OAAO,KAAa,SAAS;AACnC,QAAM,aAAa,KAAK;AACxB,QAAM,WAAW,SAAS,KAAK,UAAU,EAAE;AAC3C,QAAM,WAAW,SAAS,KAAK,UAAU,EAAE;AAC3C,QAAMC,SAAQ,SAAS,KAAK,OAAO,EAAE;AAGrC,MAAI,CAAC,IAAI,WAAW,SAAS,KAAK,CAAC,IAAI,WAAW,UAAU,GAAG;AAC7D,UAAM,WAAW,GAAG;AAAA,EACtB;AAEA,MAAI,CAAC,YAAY;AACf,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAIF,OAAM,KAAK,gBAAgB,IAAIA,OAAM,IAAI,WAAM,GAAG,EAAE,CAAC;AACjE,YAAQ,IAAI,EAAE;AAAA,EAChB;AAGA,MAAI,eAAe;AACnB,MAAI,CAAC,KAAK,YAAY;AACpB,UAAM,gBAAgB,aAAa,OAAOG,KAAI,wBAAwB,EAAE,MAAM;AAC9E,mBAAe,MAAM,YAAY,GAAG;AAEpC,QAAI,CAAC,YAAY;AACf,UAAI,aAAa,OAAO;AACtB,sBAAe,QAAQ,kBAAkB;AACzC,mBAAW,KAAK,aAAa,UAAU;AACrC,kBAAQ,IAAIH,OAAM,OAAO,YAAO,CAAC,EAAE,CAAC;AAAA,QACtC;AACA,YAAI,aAAa,YAAY,SAAS,GAAG;AACvC,kBAAQ,IAAIA,OAAM,IAAI,yBAAyB,aAAa,YAAY,KAAK,IAAI,CAAC,EAAE,CAAC;AAAA,QACvF;AAAA,MACF,OAAO;AACL,sBAAe,KAAK,sBAAsB;AAC1C,mBAAW,KAAK,aAAa,QAAQ;AACnC,kBAAQ,IAAIA,OAAM,IAAI,KAAK,CAAC,EAAE,CAAC;AAAA,QACjC;AAAA,MACF;AACA,cAAQ,IAAI,EAAE;AAAA,IAChB;AAAA,EACF;AAGA,QAAM,eAAe,aAAa,OAAOG,KAAI,aAAa,EAAE,MAAM;AAClE,MAAI,eAAe;AAGnB,QAAM,iBAA2B,KAAK,SAClC,KAAK,OAAO,MAAM,GAAG,EAAE,IAAI,CAAC,MAAc,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO,IAClE,CAAC;AAEL,QAAM,cAAc,MAAM,UAAU,KAAK;AAAA,IACvC;AAAA,IACA;AAAA,IACA,OAAAD;AAAA,IACA,QAAQ,KAAK;AAAA,IACb;AAAA,IACA,eAAe,CAAC,SAAsB;AACpC;AACA,UAAI,cAAc;AAChB,qBAAa,OAAO,eAAe,YAAY,oBAAoB,KAAK,GAAG;AAAA,MAC7E;AAAA,IACF;AAAA,EACF,CAAC;AAED,MAAI,CAAC,YAAY;AACf,iBAAc,QAAQ,WAAW,YAAY,UAAU,cAAc,YAAY,aAAa,KAAM,QAAQ,CAAC,CAAC,GAAG;AACjH,YAAQ,IAAI,EAAE;AAGd,eAAW,QAAQ,YAAY,OAAO;AACpC,UAAI,KAAK,OAAO;AACd,gBAAQ,IAAIF,OAAM,IAAI,YAAO,KAAK,GAAG,EAAE,IAAIA,OAAM,IAAI,WAAM,KAAK,KAAK,EAAE,CAAC;AACxE;AAAA,MACF;AAEA,YAAM,YAAY,WAAW,KAAK,WAAW,KAAK;AAClD,YAAM,OACJ,KAAK,WAAW,OAAO,SAAS,IAAIA,OAAM,IAAI,QAAG,IAAIA,OAAM,MAAM,QAAG;AAEtE,cAAQ;AAAA,QACN,KAAK,IAAI,IAAI,KAAK,GAAG,IAAI,UAAU,GAAG,KAAK,WAAW,KAAK,MAAM,CAAC;AAAA,MACpE;AAEA,iBAAW,SAAS,KAAK,WAAW,QAAQ;AAC1C,gBAAQ,IAAIA,OAAM,IAAI,cAAS,MAAM,WAAW,MAAM,WAAW,EAAE,CAAC;AAAA,MACtE;AACA,iBAAW,WAAW,KAAK,WAAW,UAAU;AAC9C,gBAAQ,IAAIA,OAAM,OAAO,cAAS,QAAQ,WAAW,QAAQ,WAAW,EAAE,CAAC;AAAA,MAC7E;AAAA,IACF;AAEA,YAAQ,IAAI,EAAE;AAAA,EAChB;AAGA,MAAI,oBAAoB;AACxB,MAAI,CAAC,KAAK,aAAa;AACrB,UAAM,iBAAiB,aAAa,OAAOG,KAAI,yBAAyB,EAAE,MAAM;AAChF,UAAM,gBAAgB,MAAM,aAAa,GAAG;AAE5C,QAAI,CAAC,YAAY;AACf,UAAI,cAAc,OAAO;AACvB,uBAAgB,QAAQ,4BAAuB,cAAc,KAAK,MAAM,OAAO;AAG/E,cAAM,cAAc,YAAY,MAC7B,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,EACtB,IAAI,CAAC,MAAM,EAAE,GAAG;AACnB,4BAAoB;AAAA,UAClB,cAAc,KAAK,IAAI,CAAC,MAAM,EAAE,GAAG;AAAA,UACnC;AAAA,QACF;AAEA,YAAI,kBAAkB,YAAY,SAAS,GAAG;AAC5C,kBAAQ,IAAIH,OAAM,OAAO,YAAO,kBAAkB,YAAY,MAAM,sCAAsC,CAAC;AAC3G,qBAAW,KAAK,kBAAkB,YAAY,MAAM,GAAG,EAAE,GAAG;AAC1D,oBAAQ,IAAIA,OAAM,IAAI,SAAS,CAAC,EAAE,CAAC;AAAA,UACrC;AAAA,QACF;AACA,YAAI,kBAAkB,cAAc,SAAS,GAAG;AAC9C,gBAAM,WAAW,YAAY,cAAc;AAC3C,gBAAM,QAAQ,WACV,GAAG,kBAAkB,cAAc,MAAM,qCAAqC,QAAQ,yCACtF,GAAG,kBAAkB,cAAc,MAAM;AAC7C,kBAAQ,IAAIA,OAAM,OAAO,YAAO,KAAK,GAAG,CAAC;AACzC,qBAAW,KAAK,kBAAkB,cAAc,MAAM,GAAG,EAAE,GAAG;AAC5D,oBAAQ,IAAIA,OAAM,IAAI,SAAS,CAAC,EAAE,CAAC;AAAA,UACrC;AAAA,QACF;AACA,YAAI,kBAAkB,OAAO,WAAW,GAAG;AACzC,kBAAQ,IAAIA,OAAM,MAAM,wCAAmC,CAAC;AAAA,QAC9D;AAAA,MACF,OAAO;AACL,uBAAgB,KAAK,uBAAuB;AAC5C,mBAAW,KAAK,cAAc,QAAQ;AACpC,kBAAQ,IAAIA,OAAM,IAAI,KAAK,CAAC,EAAE,CAAC;AAAA,QACjC;AAAA,MACF;AACA,cAAQ,IAAI,EAAE;AAAA,IAChB;AAAA,EACF;AAGA,MAAI,qBAAqB;AACzB,MAAI,cAAc,SAAS,aAAa,WAAW,SAAS,GAAG;AAC7D,UAAM,cAAc,YAAY,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG;AAC9E,yBAAqB;AAAA,MACnB,aAAa;AAAA,MACb;AAAA,IACF;AACA,UAAM,UAAU,mBAAmB,OAAO,CAAC,MAAM,EAAE,OAAO;AAE1D,QAAI,CAAC,cAAc,QAAQ,SAAS,GAAG;AACrC,cAAQ,IAAIA,OAAM,OAAO,YAAO,QAAQ,MAAM,2CAA2C,CAAC;AAC1F,iBAAW,KAAK,SAAS;AACvB,gBAAQ,IAAIA,OAAM,IAAI,SAAS,EAAE,IAAI,KAAK,EAAE,SAAS,GAAG,CAAC;AAAA,MAC3D;AACA,cAAQ,IAAI,EAAE;AAAA,IAChB;AAAA,EACF;AAGA,MAAI,cAAc;AAClB,MAAI,CAAC,KAAK,YAAY;AACpB,UAAM,eAAe,aAAa,OAAOG,KAAI,8CAA8C,EAAE,MAAM;AAEnG,UAAM,qBAAqB,YAAY,MACpC,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,EACtB,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,UAAU,EAAE,SAAS,EAAE;AACpD,kBAAc,MAAM,aAAa,kBAAkB;AAEnD,QAAI,CAAC,YAAY;AACf,mBAAc,QAAQ,YAAY,YAAY,YAAY,SAAS;AAEnE,YAAM,eAAe,YAAY,OAAO,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE;AAC3D,YAAM,gBAAgB,YAAY,OAAO,OAAO,CAAC,MAAM,EAAE,OAAO;AAEhE,iBAAW,SAAS,cAAc;AAChC,gBAAQ;AAAA,UACNH,OAAM,IAAI,YAAO,MAAM,IAAI,EAAE,IAC7BA,OAAM,IAAI,IAAI,MAAM,GAAG,EAAE,IACzBA,OAAM,IAAI,WAAM,MAAM,SAAS,QAAQ,MAAM,MAAM,EAAE,EAAE;AAAA,QACzD;AAAA,MACF;AACA,iBAAW,SAAS,eAAe;AACjC,gBAAQ;AAAA,UACNA,OAAM,OAAO,YAAO,MAAM,IAAI,EAAE,IAChCA,OAAM,IAAI,IAAI,MAAM,GAAG,EAAE,IACzBA,OAAM,OAAO,WAAM,MAAM,OAAO,EAAE;AAAA,QACpC;AAAA,MACF;AACA,UAAI,aAAa,WAAW,KAAK,cAAc,WAAW,GAAG;AAC3D,gBAAQ,IAAIA,OAAM,MAAM,uCAAkC,CAAC;AAAA,MAC7D;AACA,cAAQ,IAAI,EAAE;AAAA,IAChB;AAAA,EACF;AAGA,MAAI,CAAC,YAAY;AACf,UAAM,IAAI,YAAY;AAGtB,QAAI,EAAE,gBAAgB,SAAS,GAAG;AAChC,cAAQ,IAAIA,OAAM,KAAK,oBAAoB,CAAC;AAC5C,iBAAW,OAAO,EAAE,gBAAgB,MAAM,GAAG,CAAC,GAAG;AAC/C,gBAAQ,IAAIA,OAAM,IAAI,aAAQ,IAAI,MAAM,SAAS,KAAK,IAAI,MAAM,MAAM,GAAG,EAAE,IAAI,QAAQ,IAAI,KAAK,GAAG,IAAIA,OAAM,IAAI,KAAK,IAAI,KAAK,MAAM,SAAS,CAAC;AAC/I,mBAAW,KAAK,IAAI,KAAK,MAAM,GAAG,CAAC,EAAG,SAAQ,IAAIA,OAAM,IAAI,OAAO,CAAC,EAAE,CAAC;AACvE,YAAI,IAAI,KAAK,SAAS,EAAG,SAAQ,IAAIA,OAAM,IAAI,cAAc,IAAI,KAAK,SAAS,CAAC,OAAO,CAAC;AAAA,MAC1F;AACA,UAAI,EAAE,gBAAgB,SAAS,EAAG,SAAQ,IAAIA,OAAM,IAAI,YAAY,EAAE,gBAAgB,SAAS,CAAC,cAAc,CAAC;AAC/G,cAAQ,IAAI,EAAE;AAAA,IAChB;AAGA,QAAI,EAAE,sBAAsB,SAAS,GAAG;AACtC,cAAQ,IAAIA,OAAM,KAAK,0BAA0B,CAAC;AAClD,iBAAW,OAAO,EAAE,sBAAsB,MAAM,GAAG,CAAC,GAAG;AACrD,cAAM,OAAO,IAAI,YAAY,SAAS,KAAK,IAAI,YAAY,MAAM,GAAG,EAAE,IAAI,QAAQ,IAAI;AACtF,gBAAQ,IAAIA,OAAM,IAAI,aAAQ,IAAI,GAAG,IAAIA,OAAM,IAAI,KAAK,IAAI,KAAK,MAAM,SAAS,CAAC;AACjF,mBAAW,KAAK,IAAI,KAAK,MAAM,GAAG,CAAC,EAAG,SAAQ,IAAIA,OAAM,IAAI,OAAO,CAAC,EAAE,CAAC;AACvE,YAAI,IAAI,KAAK,SAAS,EAAG,SAAQ,IAAIA,OAAM,IAAI,cAAc,IAAI,KAAK,SAAS,CAAC,OAAO,CAAC;AAAA,MAC1F;AACA,UAAI,EAAE,sBAAsB,SAAS,EAAG,SAAQ,IAAIA,OAAM,IAAI,YAAY,EAAE,sBAAsB,SAAS,CAAC,cAAc,CAAC;AAC3H,cAAQ,IAAI,EAAE;AAAA,IAChB;AAGA,QAAI,EAAE,SAAS,SAAS,GAAG;AACzB,YAAM,UAAU,EAAE,SAAS,OAAO,OAAK,EAAE,UAAU,SAAS;AAC5D,YAAM,WAAW,EAAE,SAAS,OAAO,OAAK,EAAE,UAAU,UAAU;AAC9D,cAAQ,IAAIA,OAAM,KAAK,qBAAqB,CAAC;AAC7C,UAAI,QAAQ,SAAS,GAAG;AACtB,gBAAQ,IAAIA,OAAM,IAAI,YAAO,QAAQ,MAAM,mBAAmB,CAAC;AAC/D,mBAAW,KAAK,QAAQ,MAAM,GAAG,CAAC,EAAG,SAAQ,IAAIA,OAAM,IAAI,OAAO,EAAE,GAAG,EAAE,CAAC;AAC1E,YAAI,QAAQ,SAAS,EAAG,SAAQ,IAAIA,OAAM,IAAI,cAAc,QAAQ,SAAS,CAAC,OAAO,CAAC;AAAA,MACxF;AACA,UAAI,SAAS,SAAS,GAAG;AACvB,gBAAQ,IAAIA,OAAM,OAAO,YAAO,SAAS,MAAM,0BAA0B,CAAC;AAC1E,mBAAW,KAAK,SAAS,MAAM,GAAG,CAAC,EAAG,SAAQ,IAAIA,OAAM,IAAI,OAAO,EAAE,GAAG,KAAK,EAAE,KAAK,OAAO,CAAC;AAC5F,YAAI,SAAS,SAAS,EAAG,SAAQ,IAAIA,OAAM,IAAI,cAAc,SAAS,SAAS,CAAC,OAAO,CAAC;AAAA,MAC1F;AACA,cAAQ,IAAI,EAAE;AAAA,IAChB;AAGA,QAAI,EAAE,oBAAoB,SAAS,GAAG;AACpC,cAAQ,IAAIA,OAAM,KAAK,yBAAyB,CAAC;AACjD,iBAAW,MAAM,EAAE,oBAAoB,MAAM,GAAG,EAAE,GAAG;AACnD,gBAAQ,IAAIA,OAAM,IAAI,YAAO,GAAG,EAAE,EAAE,IAAIA,OAAM,IAAI,uBAAkB,GAAG,IAAI,KAAK,GAAG,MAAM,GAAG,CAAC;AAAA,MAC/F;AACA,UAAI,EAAE,oBAAoB,SAAS,GAAI,SAAQ,IAAIA,OAAM,IAAI,YAAY,EAAE,oBAAoB,SAAS,EAAE,OAAO,CAAC;AAClH,cAAQ,IAAI,EAAE;AAAA,IAChB;AAGA,QAAI,EAAE,oBAAoB,SAAS,GAAG;AACpC,cAAQ,IAAIA,OAAM,KAAK,yBAAyB,CAAC;AACjD,iBAAW,MAAM,EAAE,oBAAoB,MAAM,GAAG,EAAE,GAAG;AACnD,gBAAQ,IAAIA,OAAM,IAAI,YAAO,GAAG,EAAE,EAAE,IAAIA,OAAM,IAAI,uBAAkB,GAAG,IAAI,KAAK,GAAG,MAAM,GAAG,CAAC;AAAA,MAC/F;AACA,UAAI,EAAE,oBAAoB,SAAS,GAAI,SAAQ,IAAIA,OAAM,IAAI,YAAY,EAAE,oBAAoB,SAAS,EAAE,OAAO,CAAC;AAClH,cAAQ,IAAI,EAAE;AAAA,IAChB;AAGA,QAAI,EAAE,UAAU,SAAS,GAAG;AAC1B,cAAQ,IAAIA,OAAM,KAAK,mBAAmB,CAAC;AAC3C,iBAAW,KAAK,EAAE,UAAU,MAAM,GAAG,EAAE,GAAG;AACxC,gBAAQ,IAAIA,OAAM,OAAO,YAAO,EAAE,GAAG,EAAE,CAAC;AACxC,mBAAW,QAAQ,EAAE,MAAO,SAAQ,IAAIA,OAAM,IAAI,OAAO,IAAI,EAAE,CAAC;AAAA,MAClE;AACA,UAAI,EAAE,UAAU,SAAS,GAAI,SAAQ,IAAIA,OAAM,IAAI,YAAY,EAAE,UAAU,SAAS,EAAE,OAAO,CAAC;AAC9F,cAAQ,IAAI,EAAE;AAAA,IAChB;AAGA,QAAI,EAAE,iBAAiB,SAAS,GAAG;AACjC,YAAM,WAAW,EAAE,iBAAiB,OAAO,QAAM,CAAC,GAAG,SAAS;AAC9D,YAAM,UAAU,EAAE,iBAAiB,OAAO,QAAM,GAAG,SAAS;AAE5D,UAAI,SAAS,SAAS,GAAG;AACvB,gBAAQ,IAAIA,OAAM,KAAK,gBAAgB,IAAIA,OAAM,IAAI,gBAAgB,CAAC;AACtE,mBAAW,MAAM,SAAS,MAAM,GAAG,EAAE,GAAG;AACtC,kBAAQ,IAAIA,OAAM,OAAO,YAAO,GAAG,GAAG,EAAE,IAAIA,OAAM,IAAI,WAAM,GAAG,SAAS,QAAQ,CAAC;AAAA,QACnF;AACA,YAAI,SAAS,SAAS,GAAI,SAAQ,IAAIA,OAAM,IAAI,YAAY,SAAS,SAAS,EAAE,OAAO,CAAC;AACxF,gBAAQ,IAAI,EAAE;AAAA,MAChB;AACA,UAAI,QAAQ,SAAS,GAAG;AACtB,gBAAQ,IAAIA,OAAM,KAAK,oBAAoB,IAAIA,OAAM,IAAI,6CAA6C,CAAC;AACvG,mBAAW,MAAM,QAAQ,MAAM,GAAG,CAAC,GAAG;AACpC,kBAAQ,IAAIA,OAAM,IAAI,YAAO,GAAG,GAAG,WAAM,GAAG,SAAS,QAAQ,CAAC;AAAA,QAChE;AACA,YAAI,QAAQ,SAAS,EAAG,SAAQ,IAAIA,OAAM,IAAI,YAAY,QAAQ,SAAS,CAAC,OAAO,CAAC;AACpF,gBAAQ,IAAI,EAAE;AAAA,MAChB;AAAA,IACF;AAGA,QAAI,EAAE,YAAY,SAAS,GAAG;AAC5B,cAAQ,IAAIA,OAAM,KAAK,gBAAgB,IAAIA,OAAM,IAAI,sCAAsC,CAAC;AAC5F,iBAAW,KAAK,EAAE,YAAY,MAAM,GAAG,EAAE,EAAG,SAAQ,IAAIA,OAAM,OAAO,YAAO,CAAC,EAAE,CAAC;AAChF,UAAI,EAAE,YAAY,SAAS,GAAI,SAAQ,IAAIA,OAAM,IAAI,YAAY,EAAE,YAAY,SAAS,EAAE,OAAO,CAAC;AAClG,cAAQ,IAAI,EAAE;AAAA,IAChB;AAGA,QAAI,EAAE,aAAa,SAAS,KAAK,EAAE,aAAa,CAAC,EAAE,iBAAiB,KAAM;AACxE,cAAQ,IAAIA,OAAM,KAAK,iBAAiB,CAAC;AACzC,iBAAW,MAAM,EAAE,aAAa,OAAO,OAAK,EAAE,iBAAiB,GAAI,EAAE,MAAM,GAAG,CAAC,GAAG;AAChF,cAAM,QAAQ,GAAG,iBAAiB,MAAOA,OAAM,MAAMA,OAAM;AAC3D,gBAAQ,IAAI,MAAM,YAAO,GAAG,GAAG,EAAE,IAAIA,OAAM,IAAI,YAAO,GAAG,iBAAiB,KAAM,QAAQ,CAAC,CAAC,GAAG,CAAC;AAAA,MAChG;AACA,cAAQ,IAAI,EAAE;AAAA,IAChB;AAGA,QAAI,EAAE,sBAAsB,SAAS,GAAG;AACtC,cAAQ,IAAIA,OAAM,KAAK,6BAA6B,CAAC;AACrD,iBAAW,MAAM,EAAE,uBAAuB;AACxC,gBAAQ,IAAIA,OAAM,MAAM,YAAO,GAAG,IAAI,EAAE,IAAIA,OAAM,IAAI,WAAM,GAAG,KAAK,QAAQ,GAAG,QAAQ,IAAI,MAAM,EAAE,EAAE,CAAC;AAAA,MACxG;AACA,YAAM,cAAc,YAAY,MAAM,OAAO,OAAK,CAAC,EAAE,SAAS,EAAE,oBAAoB,SAAS,CAAC,EAAE;AAChG,YAAM,eAAe,YAAY,MAAM,OAAO,OAAK,CAAC,EAAE,KAAK,EAAE,SAAS;AACtE,UAAI,eAAe,GAAG;AACpB,gBAAQ,IAAIA,OAAM,OAAO,YAAO,YAAY,oCAAoC,CAAC;AAAA,MACnF;AACA,cAAQ,IAAI,EAAE;AAAA,IAChB,OAAO;AACL,cAAQ,IAAIA,OAAM,KAAK,6BAA6B,CAAC;AACrD,cAAQ,IAAIA,OAAM,IAAI,+CAA0C,CAAC;AACjE,cAAQ,IAAI,EAAE;AAAA,IAChB;AAGA,QAAI,EAAE,eAAe,SAAS,GAAG;AAC/B,cAAQ,IAAIA,OAAM,KAAK,kBAAkB,CAAC;AAC1C,iBAAW,OAAO,EAAE,eAAe,MAAM,GAAG,EAAE,GAAG;AAC/C,cAAM,QAAQ,IAAI,aAAa,IAAI,SAAS,MAAMA,OAAM,MAAMA,OAAM;AACpE,cAAM,OAAO,IAAI,aAAa,IAAI,SAAS,MAAM,WAAM;AACvD,gBAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,IAAI,GAAG,EAAE,IAAIA,OAAM,IAAI,WAAM,IAAI,UAAU,IAAI,IAAI,KAAK,qBAAqB,CAAC;AAAA,MAC/G;AACA,UAAI,EAAE,eAAe,SAAS,GAAI,SAAQ,IAAIA,OAAM,IAAI,YAAY,EAAE,eAAe,SAAS,EAAE,OAAO,CAAC;AACxG,cAAQ,IAAI,EAAE;AAAA,IAChB;AAGA,QAAI,EAAE,aAAa,SAAS,GAAG;AAC7B,cAAQ,IAAIA,OAAM,KAAK,iBAAiB,CAAC;AACzC,iBAAW,OAAO,EAAE,aAAa,MAAM,GAAG,EAAE,GAAG;AAC7C,cAAM,MAAM,IAAI,IAAI,SAAS,KAAK,IAAI,IAAI,MAAM,GAAG,EAAE,IAAI,QAAQ,IAAI;AACrE,gBAAQ,IAAIA,OAAM,IAAI,YAAO,GAAG,EAAE,IAAIA,OAAM,IAAI,KAAK,IAAI,MAAM,eAAU,IAAI,MAAM,MAAM,QAAQ,IAAI,MAAM,SAAS,IAAI,MAAM,EAAE,EAAE,CAAC;AACnI,mBAAW,QAAQ,IAAI,MAAM,MAAM,GAAG,CAAC,EAAG,SAAQ,IAAIA,OAAM,IAAI,OAAO,IAAI,EAAE,CAAC;AAC9E,YAAI,IAAI,MAAM,SAAS,EAAG,SAAQ,IAAIA,OAAM,IAAI,cAAc,IAAI,MAAM,SAAS,CAAC,OAAO,CAAC;AAAA,MAC5F;AACA,UAAI,EAAE,aAAa,SAAS,GAAI,SAAQ,IAAIA,OAAM,IAAI,YAAY,EAAE,aAAa,SAAS,EAAE,OAAO,CAAC;AACpG,cAAQ,IAAI,EAAE;AAAA,IAChB;AAAA,EACF;AAGA,MAAI,YAAY;AACd,YAAQ;AAAA,MACN,KAAK;AAAA,QACH;AAAA,UACE,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,QAAQ;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF,OAAO;AACL,UAAM,eAAe,WAAW,YAAY,YAAY;AAExD,YAAQ,IAAIA,OAAM,KAAK,iDAAmB,CAAC;AAC3C,YAAQ,IAAI,EAAE;AACd,UAAM,WAAW,YAAY,cAAc;AAC3C,YAAQ,IAAI,qBAAqBA,OAAM,KAAK,OAAO,YAAY,UAAU,CAAC,CAAC,GAAG,WAAWA,OAAM,IAAI,YAAY,QAAQ,wCAAmC,IAAI,EAAE,EAAE;AAClK,YAAQ,IAAI,qBAAqB,aAAaA,OAAM,KAAK,GAAG,YAAY,YAAY,MAAM,CAAC,CAAC,KAAK,YAAY,KAAK,GAAG;AACrH,YAAQ,IAAI,qBAAqB,YAAY,cAAc,IAAIA,OAAM,IAAI,OAAO,YAAY,WAAW,CAAC,IAAIA,OAAM,MAAM,GAAG,CAAC,EAAE;AAC9H,YAAQ,IAAI,qBAAqB,YAAY,gBAAgB,IAAIA,OAAM,OAAO,OAAO,YAAY,aAAa,CAAC,IAAIA,OAAM,MAAM,GAAG,CAAC,EAAE;AACrI,QAAI,aAAa;AACf,cAAQ,IAAI,qBAAqB,YAAY,cAAc,IAAIA,OAAM,IAAI,OAAO,YAAY,WAAW,CAAC,IAAIA,OAAM,MAAM,GAAG,CAAC,EAAE;AAAA,IAChI;AACA,QAAI,YAAY,YAAY,SAAS,GAAG;AACtC,cAAQ,IAAIA,OAAM,IAAI,qBAAqB,YAAY,YAAY,MAAM,oBAAoB,CAAC;AAAA,IAChG;AACA,YAAQ,IAAI,EAAE;AAAA,EAChB;AAGA,MAAI,KAAK,MAAM;AACb,UAAM,SAAS,MAAM,cAAc,KAAK,MAAM;AAC9C,QAAI,CAAC,QAAQ;AACX,UAAI,CAAC,YAAY;AACf,gBAAQ,IAAIA,OAAM,OAAO,UAAK,IAAI,8DAA8D;AAChG,gBAAQ,IAAI,EAAE;AACd,gBAAQ,IAAIA,OAAM,KAAK,qBAAqB,CAAC;AAC7C,gBAAQ,IAAI,EAAE;AACd,gBAAQ,IAAIA,OAAM,IAAI,0CAA0C,CAAC;AACjE,gBAAQ,IAAI,EAAE;AAAA,MAChB;AAAA,IACF,OAAO;AACL,YAAM,cAAc,aAAa,OAAOG,KAAI,8BAA8B,EAAE,MAAM;AAClF,UAAI;AACF,cAAM,UAAU,QAAQ,IAAI,kBAAkB;AAC9C,cAAM,MAAM,MAAM,MAAM,GAAG,OAAO,iBAAiB;AAAA,UACjD,QAAQ;AAAA,UACR,SAAS;AAAA,YACP,gBAAgB;AAAA,YAChB,eAAe,UAAU,MAAM;AAAA,UACjC;AAAA,UACA,MAAM,KAAK,UAAU;AAAA,YACnB,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,SAAS;AAAA,YACT,QAAQ;AAAA,UACV,CAAC;AAAA,QACH,CAAC;AACD,YAAI,IAAI,IAAI;AACV,gBAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,cAAI,YAAa,aAAY,QAAQ,oCAA+B,KAAK,OAAO,EAAE;AAAA,QACpF,OAAO;AACL,gBAAM,OAAQ,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAC/C,cAAI,YAAa,aAAY,KAAK,gBAAgB,KAAK,SAAS,IAAI,UAAU,EAAE;AAAA,QAClF;AAAA,MACF,SAAS,KAAK;AACZ,YAAI,YAAa,aAAY,KAAK,gBAAgB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,MACtG;AACA,UAAI,CAAC,WAAY,SAAQ,IAAI,EAAE;AAAA,IACjC;AAAA,EACF;AAGA,MAAI,YAAY,cAAc,GAAG;AAC/B,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;;;AC5dH,SAAS,WAAAC,gBAAe;AACxB,OAAOC,YAAW;AAClB,OAAOC,UAAS;AAChB,SAAS,kBAAkB,aAAAC,YAAW,0BAA0B;AAEzD,IAAM,kBAAkB,IAAIH,SAAQ,UAAU,EAClD,YAAY,sDAAsD,EAClE,SAAS,UAAU,mCAAmC,EACtD,OAAO,qBAAqB,mBAAmB,IAAI,EACnD,OAAO,uBAAuB,gBAAgB,IAAI,EAClD,OAAO,gBAAgB,0CAA0C,EACjE,OAAO,mBAAmB,2CAA2C,IAAI,EACzE,OAAO,UAAU,0BAA0B,KAAK,EAChD,OAAO,OAAO,MAAc,SAAS;AACpC,QAAM,aAAa,KAAK;AAExB,MAAI,CAAC,YAAY;AACf,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAIC,OAAM,KAAK,mBAAmB,IAAIA,OAAM,IAAI,YAAO,IAAI,GAAG,CAAC;AACvE,YAAQ,IAAI,EAAE;AAAA,EAChB;AAGA,QAAM,YAAY,aAAa,OAAOC,KAAI,yBAAyB,EAAE,MAAM;AAC3E,QAAM,WAAW,MAAM,iBAAiB,MAAM;AAAA,IAC5C,QAAQ,KAAK;AAAA,IACb,SAAS,KAAK;AAAA,EAChB,CAAC;AAED,MAAI,CAAC,YAAY;AACf,cAAW,QAAQ,SAAS,SAAS,aAAa,WAAW;AAC7D,YAAQ,IAAI,EAAE;AAEd,QAAI,SAAS,YAAY,SAAS,GAAG;AACnC,cAAQ,IAAID,OAAM,KAAK,yBAAyB,SAAS,YAAY,MAAM,GAAG,CAAC;AAC/E,iBAAW,KAAK,SAAS,aAAa;AACpC,gBAAQ,IAAI,KAAKA,OAAM,IAAI,SAAS,EAAE,EAAE,OAAO,CAAC,EAAE;AAAA,MACpD;AACA,cAAQ,IAAI,EAAE;AAAA,IAChB;AAEA,QAAI,SAAS,UAAU,SAAS,GAAG;AACjC,cAAQ,IAAIA,OAAM,KAAK,gBAAgB,SAAS,UAAU,MAAM,GAAG,CAAC;AACpE,iBAAW,KAAK,SAAS,UAAU,MAAM,GAAG,EAAE,GAAG;AAC/C,gBAAQ,IAAI,KAAKA,OAAM,KAAK,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE;AAAA,MACjD;AACA,cAAQ,IAAI,EAAE;AAAA,IAChB;AAEA,QAAI,SAAS,SAAS,SAAS,GAAG;AAChC,cAAQ,IAAIA,OAAM,KAAK,gBAAgB,SAAS,SAAS,MAAM,GAAG,CAAC;AACnE,iBAAW,MAAM,SAAS,SAAS,MAAM,GAAG,EAAE,GAAG;AAC/C,gBAAQ,IAAIA,OAAM,IAAI,KAAK,GAAG,OAAO,EAAE,CAAC;AAAA,MAC1C;AACA,UAAI,SAAS,SAAS,SAAS,IAAI;AACjC,gBAAQ,IAAIA,OAAM,IAAI,aAAa,SAAS,SAAS,SAAS,EAAE,OAAO,CAAC;AAAA,MAC1E;AACA,cAAQ,IAAI,EAAE;AAAA,IAChB;AAAA,EACF;AAGA,MAAI,YAAY;AAChB,MAAI,KAAK,MAAM;AACb,QAAI,UAAU,KAAK;AACnB,QAAI,CAAC,QAAQ,WAAW,SAAS,KAAK,CAAC,QAAQ,WAAW,UAAU,GAAG;AACrE,gBAAU,WAAW,OAAO;AAAA,IAC9B;AAEA,UAAM,eAAe,aAAa,OAAOC,KAAI,YAAY,OAAO,sBAAsB,EAAE,MAAM;AAC9F,UAAM,cAAc,MAAMC,WAAU,SAAS;AAAA,MAC3C,UAAU,SAAS,KAAK,UAAU,EAAE;AAAA,MACpC,OAAO;AAAA,IACT,CAAC;AAED,QAAI,CAAC,YAAY;AACf,mBAAc,QAAQ,WAAW,YAAY,UAAU,QAAQ;AAAA,IACjE;AAEA,UAAM,cAAc;AAAA,MAClB,GAAG,SAAS;AAAA,MACZ,GAAG,SAAS;AAAA,MACZ,GAAG,SAAS;AAAA,IACd;AAEA,UAAM,gBAAgB,YAAY,MAC/B,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,EACtB,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,UAAU,EAAE,SAAS,EAAE;AAEpD,gBAAY,mBAAmB,aAAa,aAAa;AAEzD,QAAI,CAAC,YAAY;AACf,cAAQ,IAAI,EAAE;AACd,cAAQ;AAAA,QACNF,OAAM,KAAK,sBAAsB,IAC/B,GAAG,UAAU,YAAY,IAAI,UAAU,aAAa,cAAc,UAAU,eAAe;AAAA,MAC/F;AACA,cAAQ,IAAI,EAAE;AAEd,UAAI,UAAU,KAAK,SAAS,GAAG;AAC7B,cAAM,WAAW,UAAU,KAAK,OAAO,CAAC,MAAM,EAAE,cAAc,MAAM;AACpE,cAAM,UAAU,UAAU,KAAK,OAAO,CAAC,MAAM,EAAE,cAAc,QAAQ;AAErE,YAAI,SAAS,SAAS,GAAG;AACvB,kBAAQ,IAAIA,OAAM,KAAK,IAAI,yBAAyB,SAAS,MAAM,GAAG,CAAC;AACvE,qBAAW,OAAO,SAAS,MAAM,GAAG,EAAE,GAAG;AACvC,oBAAQ;AAAA,cACNA,OAAM,IAAI,WAAM,IACd,IAAI,IAAI,OAAO,cACfA,OAAM,IAAI,GAAG,IAAI,aAAa,OAAO,IAAI,aAAa,EAAE;AAAA,YAC5D;AAAA,UACF;AACA,kBAAQ,IAAI,EAAE;AAAA,QAChB;AAEA,YAAI,QAAQ,SAAS,GAAG;AACtB,kBAAQ,IAAIA,OAAM,KAAK,OAAO,2BAA2B,QAAQ,MAAM,GAAG,CAAC;AAC3E,qBAAW,OAAO,QAAQ,MAAM,GAAG,EAAE,GAAG;AACtC,oBAAQ;AAAA,cACNA,OAAM,OAAO,WAAM,IACjB,IAAI,IAAI,OAAO,cACfA,OAAM,IAAI,GAAG,IAAI,aAAa,OAAO,IAAI,aAAa,EAAE;AAAA,YAC5D;AAAA,UACF;AACA,kBAAQ,IAAI,EAAE;AAAA,QAChB;AAAA,MACF;AAEA,UAAI,UAAU,KAAK,WAAW,GAAG;AAC/B,gBAAQ,IAAIA,OAAM,MAAM,gDAA2C,CAAC;AACpE,gBAAQ,IAAI,EAAE;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,YAAY;AACd,YAAQ;AAAA,MACN,KAAK;AAAA,QACH,EAAE,UAAU,UAAU,aAAa,UAAU;AAAA,QAC7C;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF,CAAC;;;ACjJH,SAAS,WAAAG,gBAAe;AACxB,OAAOC,YAAW;AAClB,OAAOC,UAAS;AAChB,SAAS,gBAAAC,eAAc,eAAAC,oBAAmB;;;ACH1C,eAAsB,UAAU,QAAwC;AACtE,MAAI;AACF,UAAM,SAAS,QAAQ,IAAI,kBAAkB;AAC7C,UAAM,MAAM,MAAM,MAAM,GAAG,MAAM,iBAAiB;AAAA,MAChD,SAAS,EAAE,eAAe,UAAU,MAAM,GAAG;AAAA,MAC7C,QAAQ,YAAY,QAAQ,GAAK;AAAA,IACnC,CAAC;AACD,QAAI,CAAC,IAAI,GAAI,QAAO;AACpB,UAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,WAAO,KAAK,QAAQ;AAAA,EACtB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;ADNA,SAAS,MAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC;AAC7C;AAEO,IAAM,eAAe,IAAIC,SAAQ,OAAO,EAC5C,YAAY,iEAAiE,EAC7E,SAAS,SAAS,uCAAuC,EACzD,OAAO,WAAW,2CAA2C,KAAK,EAClE,OAAO,wBAAwB,6DAA6D,EAC5F,OAAO,mBAAmB,+DAA+D,EACzF,OAAO,UAAU,0BAA0B,KAAK,EAChD,OAAO,OAAO,KAAa,SAAS;AACnC,QAAM,aAAa,KAAK;AACxB,QAAM,YAAY,KAAK;AAGvB,WAAS,OAAO,MAAiB;AAC/B,QAAI,CAAC,WAAY,SAAQ,IAAI,GAAG,IAAI;AAAA,EACtC;AAGA,WAAS,KAAK,MAAc;AAC1B,WAAO,aAAa,OAAOC,KAAI,IAAI,EAAE,MAAM;AAAA,EAC7C;AAGA,MAAI,CAAC,IAAI,WAAW,SAAS,KAAK,CAAC,IAAI,WAAW,UAAU,GAAG;AAC7D,UAAM,WAAW,GAAG;AAAA,EACtB;AAEA,MAAI;AACJ,MAAI;AACF,cAAU,IAAI,IAAI,GAAG;AAAA,EACvB,QAAQ;AACN,YAAQ,MAAMC,OAAM,IAAI,gBAAgB,CAAC;AACzC,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,SAAS,QAAQ;AACvB,QAAM,OAAO,QAAQ;AAErB,MAAI,EAAE;AACN,MAAIA,OAAM,KAAK,gBAAgB,IAAIA,OAAM,IAAI,WAAM,MAAM,EAAE,CAAC;AAC5D,MAAI,EAAE;AAGN,MAAI,WAAW;AACb,UAAM,SAAS,MAAM,cAAc,KAAK,MAAM;AAC9C,QAAI,CAAC,QAAQ;AACX,UAAIA,OAAM,IAAI,yDAAoD,CAAC;AACnE,UAAIA,OAAM,IAAI,WAAW,IAAIA,OAAM,KAAK,iBAAiB,CAAC;AAC1D,UAAIA,OAAM,IAAI,4CAA4C,CAAC;AAC3D,UAAI,EAAE;AACN,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,OAAO,MAAM,UAAU,MAAM;AACnC,QAAI,CAAC,MAAM;AACT,UAAIA,OAAM,IAAI,2BAAsB,CAAC;AACrC,UAAI,EAAE;AACN,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,QAAI,SAAS,QAAQ;AACnB,UAAIA,OAAM,IAAI,gDAA2C,CAAC;AAC1D,UAAIA,OAAM,IAAI,2CAA2C,CAAC;AAC1D,UAAI,EAAE;AACN,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAGA,QAAM,iBAAiB,KAAK,qBAAqB;AACjD,QAAM,gBAAgB,MAAMC,cAAa,MAAM;AAC/C,QAAM,aAAa,GAAG,MAAM;AAE5B,MAAI,CAAC,cAAc,SAAS,cAAc,KAAK,WAAW,GAAG;AAC3D,oBAAgB,KAAK,kBAAkB;AACvC,QAAID,OAAM,IAAI,4BAA4B,IAAIA,OAAM,KAAK,iBAAiB,CAAC;AAC3E,QAAI,EAAE;AACN,QAAI,YAAY;AACd,cAAQ,IAAI,KAAK,UAAU,EAAE,OAAO,mBAAmB,GAAG,MAAM,CAAC,CAAC;AAAA,IACpE;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,kBAAgB,QAAQ,wBAAmB,cAAc,KAAK,MAAM,OAAO;AAG3E,QAAM,gBAAgB,KAAK,wBAAwB;AACnD,QAAM,eAAe,MAAME,aAAY,MAAM;AAC7C,MAAI,kBAAkB;AAEtB,MAAI,aAAa,OAAO;AACtB,sBAAkB,aAAa,YAAY;AAAA,MAAK,CAAC,MAC/C,EAAE,YAAY,EAAE,SAAS,SAAS;AAAA,IACpC;AACA,QAAI,iBAAiB;AACnB,qBAAe,QAAQ,+BAA+B;AAAA,IACxD,OAAO;AACL,qBAAe,KAAK,gDAAgD;AACpE,UAAIF,OAAM,IAAI,gCAAgC,CAAC;AAC/C,UAAIA,OAAM,IAAI,cAAc,UAAU,EAAE,CAAC;AAAA,IAC3C;AAAA,EACF,OAAO;AACL,mBAAe,KAAK,qBAAqB;AACzC,QAAIA,OAAM,IAAI,qBAAqB,IAAIA,OAAM,KAAK,iBAAiB,CAAC;AAAA,EACtE;AAEA,MAAI,EAAE;AAIN,QAAM,cAAc,KAAK,eAAe,QAAQ,IAAI,gBAAgB,MAAM,gBAAgB,QAAQ,IAAI,CAAC;AACvG,QAAM,iBAA4E,CAAC;AAEnF,MAAI,aAAa;AACf,UAAM,OAAO,cAAc,KAAK,IAAI,CAAC,MAAM,EAAE,GAAG;AAChD,UAAM,kBAAkB,KAAK,4BAA4B;AAEzD,UAAM,kBAAkB;AAAA,MACtB,EAAE,MAAM,eAAe,UAAU,oCAAoC;AAAA,IACvE;AAEA,eAAW,UAAU,iBAAiB;AACpC,UAAI;AACF,cAAM,MAAM,MAAM,MAAM,OAAO,UAAU;AAAA,UACvC,QAAQ;AAAA,UACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,UAC9C,MAAM,KAAK,UAAU;AAAA,YACnB;AAAA,YACA,KAAK;AAAA,YACL,aAAa,GAAG,MAAM,IAAI,WAAW;AAAA,YACrC,SAAS,KAAK,MAAM,GAAG,GAAK;AAAA;AAAA,UAC9B,CAAC;AAAA,UACD,QAAQ,YAAY,QAAQ,IAAK;AAAA,QACnC,CAAC;AAED,YAAI,IAAI,MAAM,IAAI,WAAW,KAAK;AAChC,yBAAe,KAAK,EAAE,WAAW,MAAM,QAAQ,OAAO,MAAM,QAAQ,IAAI,OAAO,CAAC;AAChF,2BAAiB,QAAQ,mBAAc,KAAK,MAAM,sBAAsB,OAAO,IAAI,EAAE;AAAA,QACvF,OAAO;AACL,yBAAe,KAAK,EAAE,WAAW,OAAO,QAAQ,OAAO,MAAM,QAAQ,IAAI,OAAO,CAAC;AACjF,2BAAiB,KAAK,mBAAc,OAAO,IAAI,kBAAkB,IAAI,MAAM,EAAE;AAAA,QAC/E;AAAA,MACF,SAAS,KAAK;AACZ,uBAAe,KAAK,EAAE,WAAW,OAAO,QAAQ,OAAO,KAAK,CAAC;AAC7D,yBAAiB,KAAK,mBAAc,eAAe,QAAQ,IAAI,UAAU,QAAQ,EAAE;AAAA,MACrF;AAAA,IACF;AAAA,EACF,OAAO;AACL,QAAIA,OAAM,KAAK,YAAY,IAAIA,OAAM,IAAI,6BAA6B,CAAC;AACvE,QAAIA,OAAM,IAAI,wBAAwB,IAAIA,OAAM,KAAK,iBAAiB,IAAIA,OAAM,IAAI,8BAA8B,CAAC;AACnH,QAAI,EAAE;AAAA,EACR;AAEA,MAAIA,OAAM,KAAK,yBAAyB,CAAC;AACzC,MAAIA,OAAM,IAAI,oDAAoD,CAAC;AACnE,MAAIA,OAAM,IAAI,eAAe,IAAIA,OAAM,UAAU,0CAA0C,CAAC;AAC5F,MAAIA,OAAM,IAAI,uBAAuB,IAAI,EAAE,CAAC;AAC5C,MAAIA,OAAM,IAAI,0DAA0D,CAAC;AACzE,MAAI,EAAE;AAGN,MAAI,oBAAqE;AAEzE,MAAI,KAAK,OAAO;AACd,UAAM,eAAe,KAAK,+BAA+B;AACzD,wBAAoB,CAAC;AACrB,UAAM,OAAO,cAAc,KAAK,IAAI,CAAC,MAAM,EAAE,GAAG;AAChD,QAAI,eAAe;AAEnB,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,YAAM,UAAU,KAAK,CAAC;AACtB,UAAI,cAAc;AAChB,qBAAa,OAAO,0BAA0B,IAAI,CAAC,IAAI,KAAK,MAAM;AAAA,MACpE;AAEA,UAAI;AACF,cAAM,WAAW,yDAAyD,mBAAmB,OAAO,CAAC;AACrG,cAAM,MAAM,MAAM,MAAM,UAAU;AAAA,UAChC,QAAQ;AAAA,UACR,QAAQ,YAAY,QAAQ,GAAI;AAAA,UAChC,UAAU;AAAA,UACV,SAAS;AAAA,YACP,cAAc;AAAA,UAChB;AAAA,QACF,CAAC;AAED,cAAM,UAAU,IAAI,WAAW,OAAO,IAAI,WAAW,OAAO,IAAI,WAAW;AAC3E,0BAAkB,KAAK,EAAE,KAAK,SAAS,QAAQ,CAAC;AAChD,YAAI,QAAS;AAAA,MACf,QAAQ;AACN,0BAAkB,KAAK,EAAE,KAAK,SAAS,SAAS,MAAM,CAAC;AAAA,MACzD;AAEA,YAAM,MAAM,GAAG;AAAA,IACjB;AAEA,kBAAc,QAAQ,eAAe,YAAY,IAAI,KAAK,MAAM,8BAA8B;AAE9F,QAAI,CAAC,YAAY;AACf,cAAQ,IAAI,EAAE;AACd,YAAM,aAAa,kBAAkB,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO;AAE7D,UAAI,WAAW,SAAS,GAAG;AACzB,gBAAQ,IAAIA,OAAM,KAAK,kBAAkB,WAAW,MAAM,GAAG,CAAC;AAC9D,mBAAW,KAAK,WAAW,MAAM,GAAG,EAAE,GAAG;AACvC,kBAAQ,IAAIA,OAAM,IAAI,WAAM,IAAI,EAAE,GAAG;AAAA,QACvC;AACA,YAAI,WAAW,SAAS,IAAI;AAC1B,kBAAQ,IAAIA,OAAM,IAAI,aAAa,WAAW,SAAS,EAAE,OAAO,CAAC;AAAA,QACnE;AACA,gBAAQ,IAAI,EAAE;AAAA,MAChB,OAAO;AACL,gBAAQ,IAAIA,OAAM,MAAM,mCAA8B,CAAC;AACvD,gBAAQ,IAAI,EAAE;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,YAAY;AACd,YAAQ,IAAI,KAAK,UAAU;AAAA,MACzB,SAAS,EAAE,KAAK,YAAY,MAAM,cAAc,KAAK,OAAO;AAAA,MAC5D,WAAW,EAAE,OAAO,aAAa,OAAO,mBAAmB,gBAAgB;AAAA,MAC3E,UAAU,eAAe,SAAS,IAAI,iBAAiB;AAAA,MACvD,YAAY;AAAA,IACd,GAAG,MAAM,CAAC,CAAC;AAAA,EACb,OAAO;AACL,YAAQ,IAAIA,OAAM,KAAK,iDAAmB,CAAC;AAC3C,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,qBAAqB,cAAc,KAAK,MAAM,OAAO;AAEjE,QAAI;AACJ,QAAI,CAAC,aAAa,OAAO;AACvB,qBAAeA,OAAM,IAAI,kBAAa;AAAA,IACxC,WAAW,iBAAiB;AAC1B,qBAAeA,OAAM,MAAM,2BAAsB;AAAA,IACnD,OAAO;AACL,qBAAeA,OAAM,OAAO,4BAAuB;AAAA,IACrD;AACA,YAAQ,IAAI,qBAAqB,YAAY,EAAE;AAE/C,QAAI,eAAe,SAAS,GAAG;AAC7B,iBAAW,KAAK,gBAAgB;AAC9B,cAAM,SAAS,EAAE,YAAYA,OAAM,MAAM,kBAAa,IAAIA,OAAM,IAAI,eAAU;AAC9E,gBAAQ,IAAI,qBAAqB,MAAM,KAAK,EAAE,MAAM,GAAG;AAAA,MACzD;AAAA,IACF,OAAO;AACL,cAAQ,IAAI,qBAAqBA,OAAM,IAAI,sCAAsC,CAAC,EAAE;AAAA,IACtF;AACA,QAAI,mBAAmB;AACrB,YAAM,eAAe,kBAAkB,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE;AAChE,cAAQ,IAAI,qBAAqB,YAAY,IAAI,kBAAkB,MAAM,UAAU;AAAA,IACrF;AACA,YAAQ,IAAI,EAAE;AAAA,EAChB;AACF,CAAC;;;AEzQH,SAAS,WAAAG,gBAAe;AACxB,OAAOC,YAAW;AAClB,OAAOC,UAAS;AAChB,SAAS,gBAAAC,qBAAoB;AAuB7B,IAAM,aAAa;AAAA,EACjB,KAAK,EAAE,MAAM,MAAM,MAAM,IAAK;AAAA,EAC9B,KAAK,EAAE,MAAM,KAAK,MAAM,KAAK;AAAA,EAC7B,KAAK,EAAE,MAAM,KAAK,MAAM,IAAI;AAC9B;AAIA,SAAS,UACP,QACA,OACgC;AAChC,QAAM,IAAI,WAAW,MAAM;AAC3B,MAAI,SAAS,EAAE,KAAM,QAAO;AAC5B,MAAI,SAAS,EAAE,KAAM,QAAO;AAC5B,SAAO;AACT;AAEA,SAAS,eAAe,QAAwC;AAC9D,MAAI,WAAW,OAAQ,QAAOF,OAAM;AACpC,MAAI,WAAW,aAAc,QAAOA,OAAM;AAC1C,SAAOA,OAAM;AACf;AAEA,SAAS,cAAc,QAAwC;AAC7D,MAAI,WAAW,OAAQ,QAAOA,OAAM,MAAM,QAAG;AAC7C,MAAI,WAAW,aAAc,QAAOA,OAAM,OAAO,QAAG;AACpD,SAAOA,OAAM,IAAI,QAAG;AACtB;AAEA,SAAS,SAAS,IAAoB;AACpC,MAAI,MAAM,IAAM,QAAO,IAAI,KAAK,KAAM,QAAQ,CAAC,CAAC;AAChD,SAAO,GAAG,KAAK,MAAM,EAAE,CAAC;AAC1B;AAEA,SAAS,UAAU,OAAuB;AACxC,SAAO,MAAM,QAAQ,CAAC;AACxB;AAEA,SAASG,YAAW,OAAe;AACjC,MAAI,SAAS,GAAI,QAAOH,OAAM;AAC9B,MAAI,SAAS,GAAI,QAAOA,OAAM;AAC9B,SAAOA,OAAM;AACf;AAEA,SAASI,OAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC;AAC7C;AAIA,eAAsB,SACpB,KACA,UACqB;AACrB,QAAM,SAAS,IAAI,gBAAgB;AAAA,IACjC;AAAA,IACA;AAAA,IACA,UAAU;AAAA,EACZ,CAAC;AAED,QAAM,SAAS,QAAQ,IAAI;AAC3B,MAAI,OAAQ,QAAO,IAAI,OAAO,MAAM;AAEpC,QAAM,MAAM,MAAM;AAAA,IAChB,8DAA8D,MAAM;AAAA,IACpE,EAAE,QAAQ,YAAY,QAAQ,GAAK,EAAE;AAAA,EACvC;AAEA,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,EAAE;AAC5C,UAAM,IAAI,MAAM,yBAAyB,IAAI,MAAM,KAAK,KAAK,MAAM,GAAG,GAAG,CAAC,EAAE;AAAA,EAC9E;AAEA,QAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,SAAO,iBAAiB,IAAI;AAC9B;AAEO,SAAS,iBAAiB,MAAuB;AACtD,QAAM,KAAK,KAAK;AAChB,MAAI,CAAC,GAAI,OAAM,IAAI,MAAM,qCAAqC;AAE9D,QAAM,YAAY,GAAG,YAAY,aAAa;AAC9C,MAAI,aAAa,KAAM,OAAM,IAAI,MAAM,sCAAsC;AAE7E,SAAO;AAAA,IACL,kBAAkB,KAAK,MAAM,YAAY,GAAG;AAAA,IAC5C,KAAK,GAAG,SAAS,0BAA0B,GAAG,gBAAgB;AAAA,IAC9D,KAAK,GAAG,SAAS,yBAAyB,GAAG,gBAAgB;AAAA,IAC7D,KAAK,GAAG,SAAS,2BAA2B,GAAG,gBAAgB;AAAA,IAC/D,KAAK,GAAG,SAAS,wBAAwB,GAAG,gBAAgB;AAAA,IAC5D,IAAI,GAAG,SAAS,aAAa,GAAG,gBAAgB;AAAA,IAChD,KAAK,GAAG,SAAS,qBAAqB,GAAG,gBAAgB;AAAA,EAC3D;AACF;AAEO,SAAS,aACd,SACA,SACU;AACV,QAAM,WAAqB,CAAC;AAE5B,MAAI,QAAQ,SAAS,QAAQ,QAAQ,mBAAmB,QAAQ,OAAO;AACrE,aAAS;AAAA,MACP,qBAAqB,QAAQ,gBAAgB,oBAAoB,QAAQ,KAAK;AAAA,IAChF;AAAA,EACF;AACA,MAAI,QAAQ,OAAO,QAAQ,QAAQ,MAAM,QAAQ,KAAK;AACpD,aAAS;AAAA,MACP,OAAO,SAAS,QAAQ,GAAG,CAAC,mBAAmB,SAAS,QAAQ,GAAG,CAAC;AAAA,IACtE;AAAA,EACF;AACA,MAAI,QAAQ,OAAO,QAAQ,QAAQ,MAAM,QAAQ,KAAK;AACpD,aAAS;AAAA,MACP,OAAO,UAAU,QAAQ,GAAG,CAAC,mBAAmB,UAAU,QAAQ,GAAG,CAAC;AAAA,IACxE;AAAA,EACF;AAEA,SAAO;AACT;AAIA,SAAS,gBAAgB,QAAoB;AAC3C,QAAM,EAAE,KAAK,UAAU,SAAS,MAAM,IAAI;AAE1C,UAAQ;AAAA,IACNJ,OAAM,KAAK,eAAe,IAAIA,OAAM,IAAI,WAAM,GAAG,KAAK,QAAQ,GAAG;AAAA,EACnE;AACA,UAAQ,IAAI,EAAE;AAEd,MAAI,SAAS,CAAC,SAAS;AACrB,YAAQ,IAAIA,OAAM,IAAI,YAAO,SAAS,eAAe,EAAE,CAAC;AACxD,YAAQ,IAAI,EAAE;AACd;AAAA,EACF;AAEA,QAAM,KAAKG,YAAW,QAAQ,gBAAgB;AAC9C,QAAM,WACJ,QAAQ,oBAAoB,KACxBH,OAAM,MAAM,QAAG,IACf,QAAQ,oBAAoB,KAC1BA,OAAM,OAAO,QAAG,IAChBA,OAAM,IAAI,QAAG;AACrB,UAAQ;AAAA,IACN,KAAK,QAAQ,IAAIA,OAAM,KAAK,aAAa,CAAC,KAAK,GAAGA,OAAM,KAAK,GAAG,QAAQ,gBAAgB,MAAM,CAAC,CAAC;AAAA,EAClG;AACA,UAAQ,IAAI,EAAE;AAGd,UAAQ,IAAIA,OAAM,KAAK,mBAAmB,CAAC;AAE3C,QAAM,YAAY,UAAU,OAAO,QAAQ,GAAG;AAC9C,QAAM,YAAY,UAAU,OAAO,QAAQ,GAAG;AAC9C,QAAM,YAAY,UAAU,OAAO,QAAQ,GAAG;AAE9C,UAAQ;AAAA,IACN,KAAK,cAAc,SAAS,CAAC,IAAI,eAAe,SAAS,EAAE,SAAS,QAAQ,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,IAAIA,OAAM,IAAI,+BAA+B,CAAC;AAAA,EAC3I;AACA,UAAQ;AAAA,IACN,KAAK,cAAc,SAAS,CAAC,IAAI,eAAe,SAAS,EAAE,UAAU,QAAQ,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,IAAIA,OAAM,IAAI,8BAA8B,CAAC;AAAA,EAC3I;AACA,UAAQ;AAAA,IACN,KAAK,cAAc,SAAS,CAAC,IAAI,eAAe,SAAS,EAAE,SAAS,QAAQ,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,IAAIA,OAAM,IAAI,gCAAgC,CAAC;AAAA,EAC5I;AACA,UAAQ,IAAI,EAAE;AAGd,UAAQ,IAAIA,OAAM,KAAK,iBAAiB,CAAC;AACzC,UAAQ;AAAA,IACN,OAAO,SAAS,QAAQ,GAAG,EAAE,OAAO,CAAC,CAAC,IAAIA,OAAM,IAAI,6BAA6B,CAAC;AAAA,EACpF;AACA,UAAQ;AAAA,IACN,OAAO,SAAS,QAAQ,EAAE,EAAE,OAAO,CAAC,CAAC,IAAIA,OAAM,IAAI,kBAAkB,CAAC;AAAA,EACxE;AACA,UAAQ;AAAA,IACN,OAAO,SAAS,QAAQ,GAAG,EAAE,OAAO,CAAC,CAAC,IAAIA,OAAM,IAAI,0BAA0B,CAAC;AAAA,EACjF;AACA,UAAQ,IAAI,EAAE;AAChB;AAEA,SAAS,sBAAsB,SAAuB;AACpD,QAAM,QAAQ,QAAQ,OAAO,CAAC,MAAM,EAAE,OAAO;AAC7C,MAAI,MAAM,WAAW,EAAG;AAExB,QAAM,WAAW,KAAK;AAAA,IACpB,MAAM,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,QAAS,kBAAkB,CAAC,IAAI,MAAM;AAAA,EACrE;AACA,QAAM,WAAW,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,QAAS,GAAG,CAAC;AAC7D,QAAM,WAAW,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,QAAS,GAAG,CAAC;AAC7D,QAAM,WAAW,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,QAAS,GAAG,CAAC;AAE7D,UAAQ,IAAIA,OAAM,KAAK,iDAAmB,CAAC;AAC3C,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,qBAAqBA,OAAM,KAAK,OAAO,QAAQ,MAAM,CAAC,CAAC,EAAE;AACrE,UAAQ;AAAA,IACN,qBAAqBG,YAAW,QAAQ,EAAEH,OAAM,KAAK,GAAG,QAAQ,MAAM,CAAC,CAAC;AAAA,EAC1E;AAEA,QAAM,OAAO,UAAU,OAAO,QAAQ;AACtC,QAAM,OAAO,UAAU,OAAO,QAAQ;AACtC,QAAM,OAAO,UAAU,OAAO,QAAQ;AAEtC,UAAQ;AAAA,IACN,qBAAqB,eAAe,IAAI,EAAE,SAAS,QAAQ,CAAC,CAAC;AAAA,EAC/D;AACA,UAAQ;AAAA,IACN,qBAAqB,eAAe,IAAI,EAAE,UAAU,QAAQ,CAAC,CAAC;AAAA,EAChE;AACA,UAAQ;AAAA,IACN,qBAAqB,eAAe,IAAI,EAAE,SAAS,QAAQ,CAAC,CAAC;AAAA,EAC/D;AACA,UAAQ,IAAI,EAAE;AAChB;AAIO,IAAM,cAAc,IAAID,SAAQ,MAAM,EAC1C,YAAY,6DAA6D,EACzE,SAAS,SAAS,0CAA0C,EAC5D;AAAA,EACC;AAAA,EACA;AAAA,EACA;AACF,EACC;AAAA,EACC;AAAA,EACA;AAAA,EACA;AACF,EACC,OAAO,UAAU,0BAA0B,KAAK,EAChD,OAAO,qBAAqB,oCAAoC,EAChE,OAAO,wBAAwB,+BAA+B,EAC9D,OAAO,sBAAsB,oCAAoC,EACjE,OAAO,OAAO,KAAa,SAAS;AACnC,QAAM,aAAa,KAAK;AACxB,QAAM,WAAW,KAAK;AACtB,QAAM,YAAY,SAAS,KAAK,OAAO,EAAE;AAEzC,MAAI,aAAa,YAAY,aAAa,WAAW;AACnD,YAAQ;AAAA,MACNC,OAAM,IAAI,4CAA4C;AAAA,IACxD;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,MAAI,CAAC,IAAI,WAAW,SAAS,KAAK,CAAC,IAAI,WAAW,UAAU,GAAG;AAC7D,UAAM,WAAW,GAAG;AAAA,EACtB;AAEA,MAAI;AACF,QAAI,IAAI,GAAG;AAAA,EACb,QAAQ;AACN,YAAQ,MAAMA,OAAM,IAAI,gBAAgB,CAAC;AACzC,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,MAAI,OAAiB,CAAC,GAAG;AAEzB,MAAI,YAAY,GAAG;AACjB,UAAM,iBAAiB,aAAa,OAAOC,KAAI,qBAAqB,EAAE,MAAM;AAC5E,UAAM,UAAU,MAAMC,cAAa,GAAG;AAEtC,QAAI,QAAQ,SAAS,QAAQ,KAAK,SAAS,GAAG;AAC5C,aAAO,QAAQ,KAAK,MAAM,GAAG,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG;AACxD,sBAAgB;AAAA,QACd,SAAS,QAAQ,KAAK,MAAM,sBAAsB,KAAK,MAAM;AAAA,MAC/D;AAAA,IACF,OAAO;AACL,sBAAgB,KAAK,sCAAsC;AAAA,IAC7D;AACA,QAAI,CAAC,WAAY,SAAQ,IAAI,EAAE;AAAA,EACjC;AAGA,QAAM,UAAwB,CAAC;AAE/B,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,YAAY,KAAK,CAAC;AACxB,UAAM,UAAU,aACZ,OACAD;AAAA,MACE,KAAK,SAAS,IACV,WAAW,IAAI,CAAC,IAAI,KAAK,MAAM,KAAK,SAAS,KAC7C,WAAW,SAAS,KAAK,QAAQ;AAAA,IACvC,EAAE,MAAM;AAEZ,QAAI;AACF,YAAM,UAAU,MAAM,SAAS,WAAW,QAAQ;AAClD,eAAS,KAAK;AACd,cAAQ,KAAK,EAAE,KAAK,WAAW,UAAU,QAAQ,CAAC;AAElD,UAAI,CAAC,YAAY;AACf,wBAAgB,EAAE,KAAK,WAAW,UAAU,QAAQ,CAAC;AAAA,MACvD;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC9D,eAAS,KAAK,WAAW,SAAS,EAAE;AACpC,cAAQ,KAAK,EAAE,KAAK,WAAW,UAAU,SAAS,MAAM,OAAO,OAAO,CAAC;AAEvE,UAAI,CAAC,YAAY;AACf,gBAAQ,IAAID,OAAM,IAAI,KAAK,MAAM,EAAE,CAAC;AACpC,gBAAQ,IAAI,EAAE;AAAA,MAChB;AAAA,IACF;AAGA,QAAI,IAAI,KAAK,SAAS,GAAG;AACvB,YAAMI,OAAM,GAAI;AAAA,IAClB;AAAA,EACF;AAGA,MAAI,CAAC,cAAc,QAAQ,SAAS,GAAG;AACrC,0BAAsB,OAAO;AAAA,EAC/B;AAGA,MAAI,YAAY;AACd,UAAM,SACJ,QAAQ,WAAW,IACf;AAAA,MACE,KAAK,QAAQ,CAAC,EAAE;AAAA,MAChB,UAAU,QAAQ,CAAC,EAAE;AAAA,MACrB,GAAI,QAAQ,CAAC,EAAE,WAAW,CAAC;AAAA,MAC3B,OAAO,QAAQ,CAAC,EAAE,SAAS;AAAA,IAC7B,IACA;AAAA,MACE;AAAA,MACA,OAAO,QAAQ,IAAI,CAAC,OAAO;AAAA,QACzB,KAAK,EAAE;AAAA,QACP,GAAI,EAAE,WAAW,CAAC;AAAA,QAClB,OAAO,EAAE,SAAS;AAAA,MACpB,EAAE;AAAA,MACF,UAAU,MAAM;AACd,cAAM,QAAQ,QAAQ,OAAO,CAAC,MAAM,EAAE,OAAO;AAC7C,YAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,eAAO;AAAA,UACL,UAAU,KAAK;AAAA,YACb,MAAM;AAAA,cACJ,CAAC,GAAG,MAAM,IAAI,EAAE,QAAS;AAAA,cACzB;AAAA,YACF,IAAI,MAAM;AAAA,UACZ;AAAA,UACA,UAAU,KAAK;AAAA,YACb,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,QAAS,GAAG;AAAA,UACpC;AAAA,UACA,UAAU,KAAK;AAAA,YACb,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,QAAS,GAAG;AAAA,UACpC;AAAA,UACA,UAAU,KAAK;AAAA,YACb,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,QAAS,GAAG;AAAA,UACpC;AAAA,QACF;AAAA,MACF,GAAG;AAAA,IACL;AACN,YAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,EAC7C;AAGA,QAAM,UAAU;AAAA,IACd,KAAK,KAAK,YAAY,WAAW,KAAK,SAAS,IAAI;AAAA,IACnD,KAAK,KAAK,YAAY,WAAW,KAAK,SAAS,IAAI;AAAA,IACnD,OAAO,KAAK,cAAc,SAAS,KAAK,aAAa,EAAE,IAAI;AAAA,EAC7D;AAEA,QAAM,aACJ,QAAQ,OAAO,QAAQ,QAAQ,OAAO,QAAQ,QAAQ,SAAS;AAEjE,MAAI,YAAY;AACd,UAAM,cAAwB,CAAC;AAE/B,eAAW,KAAK,SAAS;AACvB,UAAI,CAAC,EAAE,QAAS;AAChB,YAAM,WAAW,aAAa,EAAE,SAAS,OAAO;AAChD,UAAI,SAAS,SAAS,GAAG;AACvB,oBAAY,KAAK,GAAG,SAAS,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;AAAA,MAC3D;AAAA,IACF;AAEA,QAAI,YAAY,SAAS,GAAG;AAC1B,UAAI,CAAC,YAAY;AACf,gBAAQ,IAAIJ,OAAM,IAAIA,OAAM,KAAK,oBAAoB,CAAC,CAAC;AACvD,mBAAW,KAAK,aAAa;AAC3B,kBAAQ,IAAIA,OAAM,IAAI,YAAO,CAAC,EAAE,CAAC;AAAA,QACnC;AACA,gBAAQ,IAAI,EAAE;AAAA,MAChB;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AACF,CAAC;;;ACnaH,SAAS,WAAAK,gBAAe;AACxB,OAAOC,YAAW;AAClB,OAAOC,UAAS;AAGhB,SAASC,OAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC;AAC7C;AAEA,eAAe,YAAY,KAA4B;AACrD,QAAM,EAAE,SAAS,IAAI;AACrB,QAAM,EAAE,KAAK,IAAI,MAAM,OAAO,eAAoB;AAElD,QAAM,MACJ,aAAa,WACT,SACA,aAAa,UACX,UACA;AAER,OAAK,GAAG,GAAG,IAAI,GAAG,EAAE;AACtB;AAEO,IAAM,cAAc,IAAIC,SAAQ,MAAM,EAC1C,YAAY,2DAA2D,EACvE,OAAO,mBAAmB,mDAAmD,EAC7E,OAAO,OAAO,SAAS;AACtB,QAAM,SAAS,QAAQ,IAAI,kBAAkB;AAC7C,QAAM,MAAM,QAAQ,IAAI;AAExB,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAIC,OAAM,KAAK,eAAe,CAAC;AACvC,UAAQ,IAAI,EAAE;AAGd,QAAM,WAAW,MAAM,kBAAkB,GAAG;AAC5C,MAAI,UAAU;AACZ,YAAQ,IAAIA,OAAM,MAAM,UAAK,IAAI,sBAAsBA,OAAM,KAAK,SAAS,WAAW,CAAC,EAAE;AACzF,YAAQ,IAAIA,OAAM,IAAI,mBAAmB,SAAS,SAAS,EAAE,CAAC;AAC9D,YAAQ,IAAIA,OAAM,IAAI,kBAAkB,SAAS,QAAQ,EAAE,CAAC;AAC5D,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAIA,OAAM,IAAI,yDAAyD,CAAC;AAChF,YAAQ,IAAI,EAAE;AACd;AAAA,EACF;AAGA,MAAI,KAAK,QAAQ;AACf,UAAM,UAAUC,KAAI,sBAAsB,EAAE,MAAM;AAElD,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,GAAG,MAAM,wBAAwB;AAAA,QACvD,SAAS,EAAE,eAAe,UAAU,KAAK,MAAM,GAAG;AAAA,QAClD,QAAQ,YAAY,QAAQ,GAAK;AAAA,MACnC,CAAC;AAED,UAAI,CAAC,IAAI,IAAI;AACX,gBAAQ,KAAK,kBAAkB;AAC/B,gBAAQ,IAAID,OAAM,IAAI,2DAA2D,CAAC;AAClF,gBAAQ,IAAI,EAAE;AACd,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,YAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,YAAM,UAAU,KAAK;AACrB,cAAQ,QAAQ,aAAaA,OAAM,KAAK,QAAQ,IAAI,CAAC,EAAE;AAEvD,YAAM,kBAAkB,KAAK;AAAA,QAC3B,QAAQ,KAAK;AAAA,QACb,WAAW,QAAQ;AAAA,QACnB,aAAa,QAAQ;AAAA,QACrB,WAAU,oBAAI,KAAK,GAAE,YAAY;AAAA,MACnC,CAAC;AAGD,YAAM,gBAAgB,KAAK,QAAQ,KAAK,QAAQ,QAAQ,EAAE;AAE1D,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAIA,OAAM,IAAI,uCAAuC,CAAC;AAC9D,cAAQ,IAAIA,OAAM,IAAI,oBAAoB,IAAIA,OAAM,KAAK,yBAAyB,IAAIA,OAAM,IAAI,qBAAqB,CAAC;AACtH,cAAQ,IAAI,EAAE;AACd;AAAA,IACF,SAAS,KAAK;AACZ,cAAQ,KAAK,eAAe,QAAQ,IAAI,UAAU,mBAAmB;AACrE,cAAQ,IAAI,EAAE;AACd,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAGA,QAAM,cAAcC,KAAI,yBAAyB,EAAE,MAAM;AAEzD,MAAI;AACJ,MAAI;AAEJ,MAAI;AACF,UAAM,MAAM,MAAM,MAAM,GAAG,MAAM,iBAAiB;AAAA,MAChD,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,QAAQ,YAAY,QAAQ,GAAK;AAAA,IACnC,CAAC;AAED,QAAI,CAAC,IAAI,IAAI;AACX,kBAAY,KAAK,8BAA8B;AAC/C,cAAQ,IAAID,OAAM,IAAI,gCAAgC,IAAIA,OAAM,KAAK,sCAAsC,CAAC;AAC5G,cAAQ,IAAI,EAAE;AACd,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,iBAAa,KAAK;AAClB,eAAW,KAAK;AAChB,gBAAY,KAAK;AAAA,EACnB,SAAS,KAAK;AACZ,gBAAY,KAAK,eAAe,QAAQ,IAAI,UAAU,mBAAmB;AACzE,YAAQ,IAAIA,OAAM,IAAI,gCAAgC,IAAIA,OAAM,KAAK,sCAAsC,CAAC;AAC5G,YAAQ,IAAI,EAAE;AACd,YAAQ,KAAK,CAAC;AACd;AAAA,EACF;AAEA,QAAM,aAAa,GAAG,MAAM,qBAAqB,QAAQ;AAEzD,UAAQ,IAAIA,OAAM,KAAK,kCAAkC,CAAC;AAC1D,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,KAAKA,OAAM,UAAU,UAAU,CAAC,EAAE;AAC9C,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,gBAAgBA,OAAM,KAAK,KAAK,QAAQ,CAAC,EAAE;AACvD,UAAQ,IAAI,EAAE;AAGd,MAAI;AACF,UAAM,YAAY,UAAU;AAC5B,YAAQ,IAAIA,OAAM,IAAI,iCAAiC,CAAC;AAAA,EAC1D,QAAQ;AAAA,EAER;AAGA,QAAM,cAAcC,KAAI,8BAA8B,EAAE,MAAM;AAC9D,QAAM,UAAU,IAAI,KAAK;AACzB,QAAM,eAAe;AACrB,QAAM,YAAY,KAAK,IAAI;AAE3B,SAAO,KAAK,IAAI,IAAI,YAAY,SAAS;AACvC,UAAMH,OAAM,YAAY;AAExB,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,GAAG,MAAM,sBAAsB,UAAU,IAAI;AAAA,QACnE,QAAQ,YAAY,QAAQ,GAAK;AAAA,MACnC,CAAC;AAED,UAAI,IAAI,WAAW,KAAK;AAEtB;AAAA,MACF;AAEA,UAAI,IAAI,IAAI;AACV,cAAM,OAAQ,MAAM,IAAI,KAAK;AAM7B,oBAAY,QAAQ,aAAaE,OAAM,KAAK,KAAK,WAAW,CAAC,EAAE;AAE/D,cAAM,kBAAkB,KAAK;AAAA,UAC3B,QAAQ,KAAK;AAAA,UACb,WAAW,KAAK;AAAA,UAChB,aAAa,KAAK;AAAA,UAClB,WAAU,oBAAI,KAAK,GAAE,YAAY;AAAA,QACnC,CAAC;AAGD,cAAM,gBAAgB,KAAK,QAAQ,KAAK,QAAQ,KAAK,SAAS;AAE9D,gBAAQ,IAAI,EAAE;AACd,gBAAQ,IAAIA,OAAM,IAAI,uCAAuC,CAAC;AAC9D,gBAAQ,IAAIA,OAAM,IAAI,oBAAoB,IAAIA,OAAM,KAAK,yBAAyB,IAAIA,OAAM,IAAI,qBAAqB,CAAC;AACtH,gBAAQ,IAAI,EAAE;AACd;AAAA,MACF;AAGA,kBAAY,KAAK,uBAAuB;AACxC,cAAQ,IAAI,EAAE;AACd,cAAQ,KAAK,CAAC;AAAA,IAChB,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,cAAY,KAAK,kDAAkD;AACnE,UAAQ,IAAIA,OAAM,IAAI,eAAe,IAAIA,OAAM,KAAK,iBAAiB,CAAC;AACtE,UAAQ,IAAI,EAAE;AACd,UAAQ,KAAK,CAAC;AAChB,CAAC;AAMH,eAAe,gBACb,KACA,QACA,QACA,WACe;AACf,QAAM,cAAc,MAAM,gBAAgB,GAAG;AAC7C,MAAI,CAAC,YAAa;AAElB,MAAI;AACF,UAAM,MAAM,MAAM,MAAM,GAAG,MAAM,iBAAiB,SAAS,qBAAqB;AAAA,MAC9E,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,eAAe,UAAU,MAAM;AAAA,MACjC;AAAA,MACA,MAAM,KAAK,UAAU,EAAE,QAAQ,QAAQ,KAAK,YAAY,CAAC;AAAA,MACzD,QAAQ,YAAY,QAAQ,GAAK;AAAA,IACnC,CAAC;AAED,QAAI,IAAI,IAAI;AACV,cAAQ,IAAIA,OAAM,MAAM,UAAK,IAAI,mCAAmC;AAAA,IACtE;AAAA,EACF,QAAQ;AAAA,EAER;AACF;;;Af3NO,SAAS,gBAAyB;AACvC,QAAME,WAAU,IAAIC,SAAQ;AAE5B,EAAAD,SACG,KAAK,QAAQ,EACb,YAAY,yDAAyD,EACrE,QAAQ,OAAO;AAElB,EAAAA,SAAQ,WAAW,WAAW;AAC9B,EAAAA,SAAQ,WAAW,YAAY;AAC/B,EAAAA,SAAQ,WAAW,YAAY;AAC/B,EAAAA,SAAQ,WAAW,eAAe;AAClC,EAAAA,SAAQ,WAAW,YAAY;AAC/B,EAAAA,SAAQ,WAAW,WAAW;AAC9B,EAAAA,SAAQ,WAAW,WAAW;AAE9B,SAAOA;AACT;;;AgBxBA,IAAM,UAAU,cAAc;AAC9B,QAAQ,MAAM;","names":["Command","existsSync","writeFile","mkdir","readFile","join","existsSync","readFile","join","join","existsSync","readFile","join","writeFile","existsSync","readFile","mkdir","Command","chalk","ora","readFile","join","existsSync","readFile","join","chalk","scoreColor","chalk","Command","ora","chalk","Command","chalk","ora","chalk","Command","delay","ora","Command","chalk","ora","crawlSite","Command","chalk","ora","fetchSitemap","fetchRobots","Command","ora","chalk","fetchSitemap","fetchRobots","Command","chalk","ora","fetchSitemap","scoreColor","delay","Command","chalk","ora","delay","Command","chalk","ora","program","Command"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/detect.ts","../src/store.ts","../src/templates.ts","../src/config.ts","../src/commands/check.ts","../src/scanner.ts","../src/scanner-nuxt.ts","../src/scanner-remix.ts","../src/scanner-astro.ts","../src/scanner-sveltekit.ts","../src/scan.ts","../src/formatter.ts","../src/fixer.ts","../src/commands/crawl.ts","../src/commands/keywords.ts","../src/commands/index.ts","../src/auth.ts","../src/commands/perf.ts","../src/commands/link.ts","../src/bin.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { initCommand } from \"./commands/init.js\";\nimport { checkCommand } from \"./commands/check.js\";\nimport { crawlCommand } from \"./commands/crawl.js\";\nimport { keywordsCommand } from \"./commands/keywords.js\";\nimport { indexCommand } from \"./commands/index.js\";\nimport { perfCommand } from \"./commands/perf.js\";\nimport { linkCommand } from \"./commands/link.js\";\n\n// Injected at build time by tsup define\ndeclare const __CLI_VERSION__: string;\nconst cliVersion = typeof __CLI_VERSION__ !== \"undefined\" ? __CLI_VERSION__ : \"0.3.1\";\n\nexport function createProgram(): Command {\n const program = new Command();\n\n program\n .name(\"indxel\")\n .description(\"Infrastructure SEO developer-first. ESLint pour le SEO.\")\n .version(cliVersion);\n\n program.addCommand(initCommand);\n program.addCommand(checkCommand);\n program.addCommand(crawlCommand);\n program.addCommand(keywordsCommand);\n program.addCommand(indexCommand);\n program.addCommand(perfCommand);\n program.addCommand(linkCommand);\n\n return program;\n}\n\nexport { initCommand, checkCommand, crawlCommand, keywordsCommand, indexCommand, perfCommand, linkCommand };\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { existsSync } from \"node:fs\";\nimport { writeFile, mkdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { createInterface } from \"node:readline\";\nimport { detectProject, frameworkLabel } from \"../detect.js\";\nimport { generateIndexNowKey, saveIndexNowKey, loadIndexNowKey } from \"../store.js\";\nimport {\n seoConfigTemplate,\n sitemapTemplate,\n robotsTemplate,\n} from \"../templates.js\";\nimport { detectProjectUrl } from \"../config.js\";\n\nfunction ask(question: string): Promise<string> {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\nconst PRE_PUSH_HOOK = `#!/bin/sh\n# indxel SEO guard — blocks push if critical SEO errors are found\necho \"\\\\033[36m[indxel]\\\\033[0m Running SEO check before push...\"\nnpx indxel-cli check --ci\nif [ $? -ne 0 ]; then\n echo \"\"\n echo \"\\\\033[31m[indxel] Push blocked — fix SEO errors first.\\\\033[0m\"\n echo \"\\\\033[2m Run 'npx indxel-cli check' for details.\\\\033[0m\"\n exit 1\nfi\n`;\n\nexport const initCommand = new Command(\"init\")\n .description(\"Initialize indxel in your project\")\n .option(\"--cwd <path>\", \"Project directory\", process.cwd())\n .option(\"--force\", \"Overwrite existing files\", false)\n .option(\"--hook\", \"Install git pre-push hook to block pushes on SEO errors\", false)\n .action(async (opts) => {\n const cwd = opts.cwd;\n const spinner = ora(\"Detecting project...\").start();\n\n // 1. Detect project\n const project = await detectProject(cwd);\n\n if (project.framework === \"unknown\") {\n spinner.fail(\"No supported framework detected\");\n console.log(\n chalk.dim(\" Supported: Next.js, Nuxt, Remix, Astro, SvelteKit.\"),\n );\n console.log(\n chalk.dim(\" Make sure you're in a project directory with a config file and package.json.\"),\n );\n process.exit(1);\n }\n\n const label = frameworkLabel(project.framework);\n const version = project.frameworkVersion ? ` ${project.frameworkVersion}` : \"\";\n spinner.succeed(`Detected ${label}${version}`);\n\n const ext = project.isTypeScript ? \"ts\" : \"js\";\n const filesCreated: string[] = [];\n\n // 2. Detect or ask for site URL, then generate seo.config.ts\n let siteUrl = \"https://example.com\";\n if (!project.hasSeoConfig || opts.force) {\n const detection = await detectProjectUrl(cwd, project.framework);\n\n if (detection.url && detection.confident) {\n // Multiple sources agree or explicit config — use it directly\n siteUrl = detection.url;\n console.log(chalk.green(\" ✓\") + ` Detected URL: ${chalk.bold(siteUrl)}` + chalk.dim(` (${detection.source})`));\n } else if (detection.url) {\n // Single source / low confidence — ask for confirmation\n const answer = await ask(\n chalk.bold(\" Site URL\") + chalk.dim(` [${detection.url}] `) + chalk.bold(\": \")\n );\n siteUrl = answer && answer !== \"\"\n ? (answer.startsWith(\"http\") ? answer : `https://${answer}`)\n : detection.url;\n } else {\n // Nothing found — ask\n const answer = await ask(chalk.bold(\" Site URL: \") + chalk.dim(\"(e.g., https://mysite.com) \"));\n if (answer && answer !== \"\") {\n siteUrl = answer.startsWith(\"http\") ? answer : `https://${answer}`;\n }\n }\n const configPath = join(cwd, `seo.config.${ext}`);\n await writeFile(configPath, seoConfigTemplate(project.isTypeScript, siteUrl), \"utf-8\");\n filesCreated.push(`seo.config.${ext}`);\n console.log(chalk.green(\" ✓\") + ` Generated seo.config.${ext}` + chalk.dim(` (${siteUrl})`));\n } else {\n console.log(chalk.dim(` - seo.config.${ext} already exists (skip)`));\n }\n\n // 3. Generate sitemap.ts (Next.js-specific template)\n if (project.framework === \"nextjs\") {\n if (!project.hasSitemap || opts.force) {\n const sitemapPath = join(cwd, project.appDir, `sitemap.${ext}`);\n await writeFile(sitemapPath, sitemapTemplate(project.isTypeScript, siteUrl), \"utf-8\");\n filesCreated.push(`${project.appDir}/sitemap.${ext}`);\n console.log(chalk.green(\" ✓\") + ` Generated ${project.appDir}/sitemap.${ext}`);\n } else {\n console.log(chalk.dim(` - sitemap already exists (skip)`));\n }\n\n // 4. Generate robots.ts (Next.js-specific template)\n if (!project.hasRobots || opts.force) {\n const robotsPath = join(cwd, project.appDir, `robots.${ext}`);\n await writeFile(robotsPath, robotsTemplate(project.isTypeScript, siteUrl), \"utf-8\");\n filesCreated.push(`${project.appDir}/robots.${ext}`);\n console.log(chalk.green(\" ✓\") + ` Generated ${project.appDir}/robots.${ext}`);\n } else {\n console.log(chalk.dim(` - robots already exists (skip)`));\n }\n } else {\n // Non-Next.js: check for sitemap/robots and advise\n if (!project.hasSitemap) {\n console.log(chalk.yellow(\" ⚠\") + \" No sitemap detected — add a public/sitemap.xml or generate one with your framework\");\n }\n if (!project.hasRobots) {\n console.log(chalk.yellow(\" ⚠\") + \" No robots.txt detected — add a public/robots.txt\");\n }\n }\n\n // 5. Git pre-push hook\n const gitDir = join(cwd, \".git\");\n const hasGit = existsSync(gitDir);\n\n if (opts.hook || opts.force) {\n if (!hasGit) {\n console.log(chalk.yellow(\" ⚠\") + \" No .git directory found — skip hook install\");\n } else {\n const hooksDir = join(gitDir, \"hooks\");\n const hookPath = join(hooksDir, \"pre-push\");\n\n // Check if a pre-push hook already exists\n if (existsSync(hookPath) && !opts.force) {\n const existing = await readFile(hookPath, \"utf-8\");\n if (existing.includes(\"indxel\")) {\n console.log(chalk.dim(\" - pre-push hook already installed (skip)\"));\n } else {\n console.log(chalk.yellow(\" ⚠\") + \" pre-push hook already exists (use --force to overwrite)\");\n }\n } else {\n await mkdir(hooksDir, { recursive: true });\n await writeFile(hookPath, PRE_PUSH_HOOK, { mode: 0o755 });\n filesCreated.push(\".git/hooks/pre-push\");\n console.log(chalk.green(\" ✓\") + \" Installed git pre-push hook\");\n }\n }\n } else if (hasGit) {\n console.log(chalk.dim(\" - Use --hook to install git pre-push guard\"));\n }\n\n // 6. Ensure .indxel/ is in .gitignore (contains API key)\n const gitignorePath = join(cwd, \".gitignore\");\n if (existsSync(gitignorePath)) {\n const gitignoreContent = await readFile(gitignorePath, \"utf-8\");\n if (!gitignoreContent.includes(\".indxel\")) {\n await writeFile(gitignorePath, gitignoreContent.trimEnd() + \"\\n\\n# Indxel local config (contains API key)\\n.indxel/\\n\", \"utf-8\");\n console.log(chalk.green(\" ✓\") + \" Added .indxel/ to .gitignore\");\n }\n }\n\n // 7. IndexNow — zero-friction setup\n // SvelteKit uses static/, everyone else uses public/\n const staticDirName = project.framework === \"sveltekit\" ? \"static\" : \"public\";\n const existingKey = await loadIndexNowKey(cwd);\n if (!existingKey || opts.force) {\n const key = generateIndexNowKey();\n const publicDir = join(cwd, staticDirName);\n if (!existsSync(publicDir)) {\n await mkdir(publicDir, { recursive: true });\n }\n await writeFile(join(publicDir, `${key}.txt`), key, \"utf-8\");\n await saveIndexNowKey(cwd, key);\n filesCreated.push(`${staticDirName}/${key}.txt`);\n console.log(chalk.green(\" ✓\") + \" IndexNow ready — Bing, Yandex & Naver will pick up your pages on deploy\");\n } else {\n // Key exists — make sure the file is there too\n const keyFile = join(cwd, staticDirName, `${existingKey}.txt`);\n if (existsSync(keyFile)) {\n console.log(chalk.dim(\" - IndexNow already set up (skip)\"));\n } else {\n const publicDir = join(cwd, staticDirName);\n if (!existsSync(publicDir)) {\n await mkdir(publicDir, { recursive: true });\n }\n await writeFile(keyFile, existingKey, \"utf-8\");\n filesCreated.push(`${staticDirName}/${existingKey}.txt`);\n console.log(chalk.green(\" ✓\") + \" IndexNow key file restored\");\n }\n }\n\n // 8. Summary\n console.log(\"\");\n if (filesCreated.length > 0) {\n console.log(\n chalk.bold(` ${filesCreated.length} file${filesCreated.length > 1 ? \"s\" : \"\"} created.`),\n );\n } else {\n console.log(chalk.dim(\" Nothing to create — all files already exist.\"));\n console.log(chalk.dim(\" Use --force to overwrite.\"));\n }\n\n console.log(\"\");\n console.log(chalk.dim(\" Next steps:\"));\n console.log(chalk.dim(\" 1. Run \") + chalk.bold(\"npx indxel check\") + chalk.dim(\" to audit your pages\"));\n console.log(chalk.dim(\" 2. Run \") + chalk.bold(\"npx indxel crawl\") + chalk.dim(\" to crawl your live site\"));\n if (!opts.hook && hasGit) {\n console.log(chalk.dim(\" 3. Run \") + chalk.bold(\"npx indxel init --hook\") + chalk.dim(\" to guard git pushes\"));\n }\n console.log(\"\");\n console.log(chalk.dim(\" Want continuous monitoring?\"));\n console.log(chalk.dim(\" Run \") + chalk.bold(\"npx indxel link\") + chalk.dim(\" to connect your dashboard.\"));\n console.log(\"\");\n });\n","import { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport type Framework = \"nextjs\" | \"nuxt\" | \"remix\" | \"astro\" | \"sveltekit\" | \"unknown\";\n\nexport interface ProjectInfo {\n /** Root directory of the project */\n root: string;\n /** Detected framework */\n framework: Framework;\n /** Framework version if detected */\n frameworkVersion?: string;\n /** Whether this is a Next.js project */\n isNextJs: boolean;\n /** Next.js version if detected */\n nextVersion?: string;\n /** Whether it uses App Router (has src/app or app directory) */\n usesAppRouter: boolean;\n /** The app directory path (relative) — framework-specific pages/routes directory */\n appDir: string;\n /** Whether TypeScript is used */\n isTypeScript: boolean;\n /** Whether seo.config.ts/js already exists */\n hasSeoConfig: boolean;\n /** Whether sitemap.ts/js exists */\n hasSitemap: boolean;\n /** Whether robots.ts/js exists */\n hasRobots: boolean;\n}\n\n/** Detect project type and configuration from the given directory. */\nexport async function detectProject(cwd: string): Promise<ProjectInfo> {\n const info: ProjectInfo = {\n root: cwd,\n framework: \"unknown\",\n isNextJs: false,\n usesAppRouter: false,\n appDir: \"app\",\n isTypeScript: false,\n hasSeoConfig: false,\n hasSitemap: false,\n hasRobots: false,\n };\n\n // Check for TypeScript\n info.isTypeScript =\n existsSync(join(cwd, \"tsconfig.json\")) ||\n existsSync(join(cwd, \"tsconfig.ts\"));\n\n // Read package.json once for all framework detection\n let pkg: Record<string, unknown> | null = null;\n const pkgPath = join(cwd, \"package.json\");\n if (existsSync(pkgPath)) {\n try {\n pkg = JSON.parse(await readFile(pkgPath, \"utf-8\"));\n } catch {\n // Ignore parse errors\n }\n }\n\n const deps = {\n ...(pkg?.dependencies as Record<string, string> | undefined),\n ...(pkg?.devDependencies as Record<string, string> | undefined),\n };\n\n // -- Next.js --\n const nextConfigs = [\n \"next.config.ts\",\n \"next.config.js\",\n \"next.config.mjs\",\n \"next.config.cjs\",\n ];\n info.isNextJs = nextConfigs.some((f) => existsSync(join(cwd, f)));\n\n if (deps.next) {\n info.isNextJs = true;\n info.nextVersion = deps.next.replace(/[\\^~>=<]/g, \"\").trim();\n }\n\n if (info.isNextJs) {\n info.framework = \"nextjs\";\n info.frameworkVersion = info.nextVersion;\n\n // Detect App Router directory\n if (existsSync(join(cwd, \"src\", \"app\"))) {\n info.usesAppRouter = true;\n info.appDir = \"src/app\";\n } else if (existsSync(join(cwd, \"app\"))) {\n info.usesAppRouter = true;\n info.appDir = \"app\";\n }\n }\n\n // -- Nuxt 3 --\n if (!info.isNextJs) {\n const nuxtConfigs = [\"nuxt.config.ts\", \"nuxt.config.js\"];\n const hasNuxtConfig = nuxtConfigs.some((f) => existsSync(join(cwd, f)));\n if (hasNuxtConfig || deps.nuxt) {\n info.framework = \"nuxt\";\n info.frameworkVersion = deps.nuxt?.replace(/[\\^~>=<]/g, \"\").trim();\n // Nuxt uses pages/ for file-based routing\n if (existsSync(join(cwd, \"pages\"))) {\n info.usesAppRouter = true;\n info.appDir = \"pages\";\n }\n }\n }\n\n // -- Remix --\n if (info.framework === \"unknown\") {\n const remixDep = deps[\"@remix-run/react\"] ?? deps[\"@remix-run/node\"] ?? deps[\"@remix-run/cloudflare\"];\n const hasRemixConfig = existsSync(join(cwd, \"remix.config.js\")) || existsSync(join(cwd, \"remix.config.ts\"));\n if (hasRemixConfig || remixDep) {\n info.framework = \"remix\";\n info.frameworkVersion = remixDep?.replace(/[\\^~>=<]/g, \"\").trim();\n // Remix uses app/routes/\n if (existsSync(join(cwd, \"app\", \"routes\"))) {\n info.usesAppRouter = true;\n info.appDir = \"app/routes\";\n } else if (existsSync(join(cwd, \"app\"))) {\n info.usesAppRouter = true;\n info.appDir = \"app\";\n }\n }\n }\n\n // -- Astro --\n if (info.framework === \"unknown\") {\n const astroConfigs = [\"astro.config.mjs\", \"astro.config.ts\", \"astro.config.js\"];\n const hasAstroConfig = astroConfigs.some((f) => existsSync(join(cwd, f)));\n if (hasAstroConfig || deps.astro) {\n info.framework = \"astro\";\n info.frameworkVersion = deps.astro?.replace(/[\\^~>=<]/g, \"\").trim();\n // Astro uses src/pages/\n if (existsSync(join(cwd, \"src\", \"pages\"))) {\n info.usesAppRouter = true;\n info.appDir = \"src/pages\";\n }\n }\n }\n\n // -- SvelteKit --\n if (info.framework === \"unknown\") {\n const hasSvelteConfig = existsSync(join(cwd, \"svelte.config.js\")) || existsSync(join(cwd, \"svelte.config.ts\"));\n if ((hasSvelteConfig && deps[\"@sveltejs/kit\"]) || deps[\"@sveltejs/kit\"]) {\n info.framework = \"sveltekit\";\n info.frameworkVersion = deps[\"@sveltejs/kit\"]?.replace(/[\\^~>=<]/g, \"\").trim();\n // SvelteKit uses src/routes/\n if (existsSync(join(cwd, \"src\", \"routes\"))) {\n info.usesAppRouter = true;\n info.appDir = \"src/routes\";\n }\n }\n }\n\n // Check for existing SEO files (check both .ts and .js regardless of project type)\n info.hasSeoConfig =\n existsSync(join(cwd, \"seo.config.ts\")) ||\n existsSync(join(cwd, \"seo.config.js\"));\n\n // Sitemap/robots detection adapts to framework\n const sitemapDirs = info.framework === \"nextjs\" ? [info.appDir] : [info.appDir, \"public\", \".\"];\n const robotsDirs = info.framework === \"nextjs\" ? [info.appDir] : [info.appDir, \"public\", \".\"];\n\n info.hasSitemap = sitemapDirs.some((dir) =>\n existsSync(join(cwd, dir, \"sitemap.ts\")) ||\n existsSync(join(cwd, dir, \"sitemap.js\")) ||\n existsSync(join(cwd, dir, \"sitemap.xml\")),\n );\n\n info.hasRobots = robotsDirs.some((dir) =>\n existsSync(join(cwd, dir, \"robots.ts\")) ||\n existsSync(join(cwd, dir, \"robots.js\")) ||\n existsSync(join(cwd, dir, \"robots.txt\")),\n );\n\n return info;\n}\n\n/** Human-readable framework name */\nexport function frameworkLabel(fw: Framework): string {\n const labels: Record<Framework, string> = {\n nextjs: \"Next.js\",\n nuxt: \"Nuxt\",\n remix: \"Remix\",\n astro: \"Astro\",\n sveltekit: \"SvelteKit\",\n unknown: \"Unknown\",\n };\n return labels[fw];\n}\n","import { existsSync } from \"node:fs\";\nimport { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { randomBytes } from \"node:crypto\";\nimport type { CheckSummary } from \"./formatter.js\";\n\nconst STORE_DIR = \".indxel\";\nconst LAST_CHECK_FILE = \"last-check.json\";\nconst INDEXNOW_KEY_FILE = \"indexnow-key.txt\";\nconst CONFIG_FILE = \"config.json\";\n\nexport interface StoredCheck {\n timestamp: string;\n summary: CheckSummary;\n}\n\n/** Save the current check results for future diff comparison */\nexport async function saveCheckResult(\n cwd: string,\n summary: CheckSummary,\n): Promise<void> {\n const storeDir = join(cwd, STORE_DIR);\n\n if (!existsSync(storeDir)) {\n await mkdir(storeDir, { recursive: true });\n }\n\n const stored: StoredCheck = {\n timestamp: new Date().toISOString(),\n summary: {\n ...summary,\n // Serialize results with minimal data needed for diff\n results: summary.results.map((r) => ({\n page: {\n filePath: r.page.filePath,\n route: r.page.route,\n hasMetadata: r.page.hasMetadata,\n hasDynamicMetadata: r.page.hasDynamicMetadata,\n isClientComponent: r.page.isClientComponent,\n titleIsAbsolute: r.page.titleIsAbsolute,\n extractedMetadata: r.page.extractedMetadata,\n },\n validation: r.validation,\n })),\n },\n };\n\n await writeFile(\n join(storeDir, LAST_CHECK_FILE),\n JSON.stringify(stored, null, 2),\n \"utf-8\",\n );\n}\n\n/** Load the previous check result (or null if none exists) */\nexport async function loadPreviousCheck(\n cwd: string,\n): Promise<StoredCheck | null> {\n const filePath = join(cwd, STORE_DIR, LAST_CHECK_FILE);\n\n if (!existsSync(filePath)) {\n return null;\n }\n\n try {\n const data = await readFile(filePath, \"utf-8\");\n return JSON.parse(data) as StoredCheck;\n } catch {\n return null;\n }\n}\n\n/** Get the .indxel directory path */\nexport function getStoreDir(cwd: string): string {\n return join(cwd, STORE_DIR);\n}\n\n/** Generate a 32-character hex IndexNow key */\nexport function generateIndexNowKey(): string {\n return randomBytes(16).toString(\"hex\");\n}\n\n/** Save an IndexNow key to the .indxel store */\nexport async function saveIndexNowKey(cwd: string, key: string): Promise<void> {\n const storeDir = join(cwd, STORE_DIR);\n if (!existsSync(storeDir)) {\n await mkdir(storeDir, { recursive: true });\n }\n await writeFile(join(storeDir, INDEXNOW_KEY_FILE), key, \"utf-8\");\n}\n\n/** Load the IndexNow key from the .indxel store (or null if not set up) */\nexport async function loadIndexNowKey(cwd: string): Promise<string | null> {\n const filePath = join(cwd, STORE_DIR, INDEXNOW_KEY_FILE);\n if (!existsSync(filePath)) return null;\n try {\n const key = (await readFile(filePath, \"utf-8\")).trim();\n return key || null;\n } catch {\n return null;\n }\n}\n\n// --- Project config (set by `npx indxel link`) ---\n\nexport interface ProjectConfig {\n apiKey: string;\n projectId: string;\n projectName: string;\n linkedAt: string;\n}\n\n/** Save project config after linking */\nexport async function saveProjectConfig(\n cwd: string,\n config: ProjectConfig,\n): Promise<void> {\n const storeDir = join(cwd, STORE_DIR);\n if (!existsSync(storeDir)) {\n await mkdir(storeDir, { recursive: true });\n }\n await writeFile(\n join(storeDir, CONFIG_FILE),\n JSON.stringify(config, null, 2),\n \"utf-8\",\n );\n}\n\n/** Load project config (or null if not linked) */\nexport async function loadProjectConfig(\n cwd: string,\n): Promise<ProjectConfig | null> {\n const filePath = join(cwd, STORE_DIR, CONFIG_FILE);\n if (!existsSync(filePath)) return null;\n try {\n const data = await readFile(filePath, \"utf-8\");\n return JSON.parse(data) as ProjectConfig;\n } catch {\n return null;\n }\n}\n\n/**\n * Resolve API key from multiple sources (in priority order):\n * 1. Explicit --api-key flag\n * 2. INDXEL_API_KEY environment variable\n * 3. .indxel/config.json (set by `npx indxel link`)\n */\nexport async function resolveApiKey(\n explicit?: string,\n): Promise<string | null> {\n if (explicit) return explicit;\n if (process.env.INDXEL_API_KEY) return process.env.INDXEL_API_KEY;\n const config = await loadProjectConfig(process.cwd());\n return config?.apiKey ?? null;\n}\n","/** Generate the seo.config.ts template */\nexport function seoConfigTemplate(isTypeScript: boolean, siteUrl = \"https://example.com\"): string {\n if (isTypeScript) {\n return `import { defineSEO } from 'indxel'\n\nexport default defineSEO({\n siteName: 'My Site',\n siteUrl: '${siteUrl}',\n titleTemplate: '%s | My Site',\n defaultDescription: 'A short description of your site for search engines.',\n defaultOGImage: '/og-image.png',\n locale: 'en_US',\n // twitter: {\n // handle: '@yourhandle',\n // cardType: 'summary_large_image',\n // },\n // organization: {\n // name: 'My Company',\n // logo: '/logo.png',\n // url: '${siteUrl}',\n // },\n})\n`;\n }\n\n return `const { defineSEO } = require('indxel')\n\nmodule.exports = defineSEO({\n siteName: 'My Site',\n siteUrl: '${siteUrl}',\n titleTemplate: '%s | My Site',\n defaultDescription: 'A short description of your site for search engines.',\n defaultOGImage: '/og-image.png',\n locale: 'en_US',\n})\n`;\n}\n\n/** Generate the sitemap.ts template */\nexport function sitemapTemplate(isTypeScript: boolean, siteUrl = \"https://example.com\"): string {\n if (isTypeScript) {\n return `import type { MetadataRoute } from 'next'\n\nexport default function sitemap(): MetadataRoute.Sitemap {\n const baseUrl = '${siteUrl}'\n\n return [\n {\n url: baseUrl,\n lastModified: new Date(),\n changeFrequency: 'weekly',\n priority: 1,\n },\n // Add more pages here or generate dynamically:\n //\n // const posts = await getPosts()\n // return posts.map(post => ({\n // url: \\`\\${baseUrl}/blog/\\${post.slug}\\`,\n // lastModified: post.updatedAt,\n // changeFrequency: 'monthly',\n // priority: 0.7,\n // }))\n ]\n}\n`;\n }\n\n return `/** @returns {import('next').MetadataRoute.Sitemap} */\nexport default function sitemap() {\n const baseUrl = '${siteUrl}'\n\n return [\n {\n url: baseUrl,\n lastModified: new Date(),\n changeFrequency: 'weekly',\n priority: 1,\n },\n ]\n}\n`;\n}\n\n/** Generate the robots.ts template */\nexport function robotsTemplate(isTypeScript: boolean, siteUrl = \"https://example.com\"): string {\n if (isTypeScript) {\n return `import type { MetadataRoute } from 'next'\n\nexport default function robots(): MetadataRoute.Robots {\n const baseUrl = '${siteUrl}'\n\n return {\n rules: [\n {\n userAgent: '*',\n allow: '/',\n disallow: ['/api/', '/private/'],\n },\n ],\n sitemap: \\`\\${baseUrl}/sitemap.xml\\`,\n }\n}\n`;\n }\n\n return `/** @returns {import('next').MetadataRoute.Robots} */\nexport default function robots() {\n const baseUrl = '${siteUrl}'\n\n return {\n rules: [\n {\n userAgent: '*',\n allow: '/',\n disallow: ['/api/', '/private/'],\n },\n ],\n sitemap: \\`\\${baseUrl}/sitemap.xml\\`,\n }\n}\n`;\n}\n","import { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface IndxelConfig {\n /** Minimum score to pass (0-100). Overrides --min-score flag. */\n minScore?: number;\n /** Rule IDs to disable (won't count toward score). */\n disabledRules?: string[];\n /** Base URL for canonical URLs. */\n baseUrl?: string;\n /** Route patterns to exclude from checks (e.g., \"/dashboard/*\", \"/auth/*\"). */\n ignoreRoutes?: string[];\n}\n\nconst CONFIG_FILES = [\".indxelrc.json\", \".indxelrc\", \"indxel.config.json\"];\n\n/**\n * Load indxel config from the project root.\n * Searches for .indxelrc.json, .indxelrc, or indxel.config.json.\n */\nexport async function loadConfig(cwd: string): Promise<IndxelConfig> {\n for (const file of CONFIG_FILES) {\n const path = join(cwd, file);\n if (existsSync(path)) {\n try {\n const content = await readFile(path, \"utf-8\");\n return JSON.parse(content) as IndxelConfig;\n } catch {\n // Invalid JSON — ignore silently\n }\n }\n }\n return {};\n}\n\n// --- URL Detection ---\n\ninterface DetectedUrl {\n url: string;\n source: string;\n /** Higher = more trustworthy. Explicit config > env > inferred. */\n weight: number;\n}\n\nexport interface UrlDetectionResult {\n /** Best URL candidate (null if nothing found) */\n url: string | null;\n /** Where it came from */\n source: string;\n /** High confidence = multiple sources agree or explicit config. No confirmation needed. */\n confident: boolean;\n /** All detected URLs with sources (for debugging / displaying alternatives) */\n all: DetectedUrl[];\n}\n\n/** Env var names per framework that typically hold the production URL */\nconst URL_ENV_VARS: Record<string, string[]> = {\n // Framework-specific\n nextjs: [\"NEXT_PUBLIC_APP_URL\", \"NEXT_PUBLIC_SITE_URL\", \"NEXT_PUBLIC_BASE_URL\", \"NEXT_PUBLIC_URL\"],\n nuxt: [\"NUXT_PUBLIC_SITE_URL\", \"NUXT_PUBLIC_APP_URL\", \"NUXT_SITE_URL\"],\n remix: [\"APP_URL\", \"BASE_URL\"],\n astro: [\"SITE_URL\", \"PUBLIC_SITE_URL\", \"ASTRO_SITE\"],\n sveltekit: [\"PUBLIC_SITE_URL\", \"VITE_SITE_URL\"],\n // Generic (works for all)\n generic: [\"SITE_URL\", \"BASE_URL\", \"APP_URL\", \"DEPLOY_URL\", \"URL\"],\n};\n\n/**\n * Detect all possible URLs from every source, with confidence scoring.\n * Use this for `init` — returns all candidates + confidence level.\n */\nexport async function detectProjectUrl(cwd: string, framework?: string): Promise<UrlDetectionResult> {\n const candidates: DetectedUrl[] = [];\n\n // 1. Explicit indxel config (highest trust)\n const config = await loadConfig(cwd);\n if (config.baseUrl) {\n candidates.push({ url: normalize(config.baseUrl), source: \".indxelrc.json\", weight: 10 });\n }\n\n // 2. seo.config.ts/js (explicit user config)\n for (const ext of [\"ts\", \"js\"]) {\n const configPath = join(cwd, `seo.config.${ext}`);\n if (existsSync(configPath)) {\n try {\n const content = await readFile(configPath, \"utf-8\");\n const match = content.match(/siteUrl\\s*:\\s*['\"`]([^'\"`]+)['\"`]/);\n if (match?.[1] && match[1] !== \"https://example.com\") {\n candidates.push({ url: normalize(match[1]), source: `seo.config.${ext}`, weight: 10 });\n }\n } catch { /* ignore */ }\n }\n }\n\n // 3. Env files — framework-specific + generic vars\n const envVars = [\n ...(framework && URL_ENV_VARS[framework] ? URL_ENV_VARS[framework] : []),\n ...URL_ENV_VARS.generic,\n ];\n // Deduplicate\n const uniqueVars = [...new Set(envVars)];\n const envFiles = [\".env.production\", \".env.production.local\", \".env.local\", \".env\"];\n\n for (const file of envFiles) {\n const envPath = join(cwd, file);\n if (!existsSync(envPath)) continue;\n try {\n const content = await readFile(envPath, \"utf-8\");\n for (const varName of uniqueVars) {\n const match = content.match(new RegExp(`^${varName}\\\\s*=\\\\s*['\"]?([^'\"\\n]+)['\"]?`, \"m\"));\n if (match?.[1]) {\n const url = match[1].trim();\n if (isProductionUrl(url)) {\n // .env.production gets higher weight\n const weight = file.includes(\"production\") ? 7 : 5;\n candidates.push({ url: normalize(url), source: `${file} (${varName})`, weight });\n }\n }\n }\n } catch { /* ignore */ }\n }\n\n // 4. Framework-specific config files\n const fwUrl = await detectFromFrameworkConfig(cwd, framework);\n if (fwUrl) {\n candidates.push(fwUrl);\n }\n\n // 5. Vercel project config\n const vercelUrl = await detectFromVercel(cwd);\n if (vercelUrl) {\n candidates.push(vercelUrl);\n }\n\n // 6. Netlify config\n const netlifyUrl = await detectFromNetlify(cwd);\n if (netlifyUrl) {\n candidates.push(netlifyUrl);\n }\n\n // 7. package.json homepage\n try {\n const pkg = JSON.parse(await readFile(join(cwd, \"package.json\"), \"utf-8\"));\n if (pkg.homepage && isProductionUrl(pkg.homepage)) {\n candidates.push({ url: normalize(pkg.homepage), source: \"package.json (homepage)\", weight: 4 });\n }\n } catch { /* ignore */ }\n\n if (candidates.length === 0) {\n return { url: null, source: \"\", confident: false, all: [] };\n }\n\n // Cross-reference: count how many sources agree on the same origin\n const originCounts = new Map<string, { count: number; best: DetectedUrl }>();\n for (const c of candidates) {\n const origin = new URL(c.url).origin;\n const existing = originCounts.get(origin);\n if (!existing || c.weight > existing.best.weight) {\n originCounts.set(origin, {\n count: (existing?.count ?? 0) + 1,\n best: c,\n });\n } else {\n existing.count++;\n }\n }\n\n // Pick the origin with highest (count * best weight)\n let best: { origin: string; count: number; best: DetectedUrl } | null = null;\n for (const [origin, data] of originCounts) {\n const score = data.count * data.best.weight;\n if (!best || score > best.count * best.best.weight) {\n best = { origin, ...data };\n }\n }\n\n const result = best!.best;\n // Confident if: explicit config (weight >= 10) OR multiple sources agree\n const confident = result.weight >= 10 || best!.count >= 2;\n\n return {\n url: result.url,\n source: result.source,\n confident,\n all: candidates,\n };\n}\n\n/**\n * Simple resolve for CLI commands (perf, crawl, index).\n * Returns the best URL or null. No confidence info needed.\n */\nexport async function resolveProjectUrl(cwd: string): Promise<string | null> {\n const result = await detectProjectUrl(cwd);\n return result.url;\n}\n\n// --- Detection helpers ---\n\nfunction normalize(url: string): string {\n if (!url.startsWith(\"http\")) url = `https://${url}`;\n // Remove trailing slash\n return url.replace(/\\/+$/, \"\");\n}\n\nfunction isProductionUrl(url: string): boolean {\n if (!url || !url.startsWith(\"http\")) return false;\n if (url.includes(\"localhost\")) return false;\n if (url.includes(\"127.0.0.1\")) return false;\n if (url.includes(\"0.0.0.0\")) return false;\n return true;\n}\n\n/** Read framework-specific config files (next.config, nuxt.config, astro.config, etc.) */\nasync function detectFromFrameworkConfig(cwd: string, framework?: string): Promise<DetectedUrl | null> {\n // Astro: site field in astro.config.mjs\n if (!framework || framework === \"astro\") {\n for (const file of [\"astro.config.mjs\", \"astro.config.ts\", \"astro.config.js\"]) {\n const configPath = join(cwd, file);\n if (existsSync(configPath)) {\n try {\n const content = await readFile(configPath, \"utf-8\");\n const match = content.match(/site\\s*:\\s*['\"`]([^'\"`]+)['\"`]/);\n if (match?.[1] && isProductionUrl(match[1])) {\n return { url: normalize(match[1]), source: `${file} (site)`, weight: 8 };\n }\n } catch { /* ignore */ }\n }\n }\n }\n\n // Nuxt: app.baseURL or site.url in nuxt.config\n if (!framework || framework === \"nuxt\") {\n for (const file of [\"nuxt.config.ts\", \"nuxt.config.js\"]) {\n const configPath = join(cwd, file);\n if (existsSync(configPath)) {\n try {\n const content = await readFile(configPath, \"utf-8\");\n const match = content.match(/url\\s*:\\s*['\"`]([^'\"`]+)['\"`]/);\n if (match?.[1] && isProductionUrl(match[1])) {\n return { url: normalize(match[1]), source: `${file} (site.url)`, weight: 8 };\n }\n } catch { /* ignore */ }\n }\n }\n }\n\n return null;\n}\n\n/** Detect from .vercel/project.json */\nasync function detectFromVercel(cwd: string): Promise<DetectedUrl | null> {\n const vercelPath = join(cwd, \".vercel\", \"project.json\");\n if (!existsSync(vercelPath)) return null;\n try {\n const content = JSON.parse(await readFile(vercelPath, \"utf-8\"));\n if (content.projectName) {\n return {\n url: `https://${content.projectName}.vercel.app`,\n source: \".vercel/project.json\",\n weight: 3, // Low weight — *.vercel.app is often not the real domain\n };\n }\n } catch { /* ignore */ }\n return null;\n}\n\n/** Detect from netlify.toml or .netlify/state.json */\nasync function detectFromNetlify(cwd: string): Promise<DetectedUrl | null> {\n // netlify.toml — may have [context.production] environment URL\n const tomlPath = join(cwd, \"netlify.toml\");\n if (existsSync(tomlPath)) {\n try {\n const content = await readFile(tomlPath, \"utf-8\");\n const match = content.match(/URL\\s*=\\s*['\"]([^'\"]+)['\"]/i);\n if (match?.[1] && isProductionUrl(match[1])) {\n return { url: normalize(match[1]), source: \"netlify.toml\", weight: 6 };\n }\n } catch { /* ignore */ }\n }\n\n // .netlify/state.json — siteId can map to *.netlify.app\n const statePath = join(cwd, \".netlify\", \"state.json\");\n if (existsSync(statePath)) {\n try {\n const content = JSON.parse(await readFile(statePath, \"utf-8\"));\n if (content.siteId) {\n // Can't resolve real domain without Netlify API, but name maps to *.netlify.app\n // Low weight — probably not the production domain\n return {\n url: `https://${content.siteId}.netlify.app`,\n source: \".netlify/state.json\",\n weight: 2,\n };\n }\n } catch { /* ignore */ }\n }\n\n return null;\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { validateMetadata } from \"indxel\";\nimport { detectProject, frameworkLabel } from \"../detect.js\";\nimport { scanProject } from \"../scan.js\";\nimport { loadConfig } from \"../config.js\";\nimport {\n formatPageResult,\n formatSkippedPage,\n formatSummary,\n formatJSON,\n formatDiff,\n computeSummary,\n type CheckResult,\n} from \"../formatter.js\";\nimport { saveCheckResult, loadPreviousCheck, resolveApiKey } from \"../store.js\";\nimport { generateFixSuggestions } from \"../fixer.js\";\n\nexport const checkCommand = new Command(\"check\")\n .description(\"Audit SEO metadata for all pages in your project\")\n .option(\"--cwd <path>\", \"Project directory\", process.cwd())\n .option(\"--ci\", \"CI/CD mode — strict, exit 1 on any error\", false)\n .option(\"--diff\", \"Compare with previous check run\", false)\n .option(\"--json\", \"Output results as JSON\", false)\n .option(\"--strict\", \"Treat warnings as errors\", false)\n .option(\"--min-score <score>\", \"Minimum score to pass (0-100, default: exit on any error)\")\n .option(\"--fix\", \"Show suggested metadata code to fix errors\", false)\n .option(\"--push\", \"Push results to Indxel dashboard\", false)\n .option(\"--api-key <key>\", \"API key for --push (or set INDXEL_API_KEY env var)\")\n .action(async (opts) => {\n const cwd = opts.cwd;\n const isCI = opts.ci;\n const isStrict = opts.strict || isCI;\n const showDiff = opts.diff;\n const jsonOutput = opts.json;\n const showFix = opts.fix;\n\n // Load config file (.indxelrc.json, etc.)\n const config = await loadConfig(cwd);\n\n // --min-score flag overrides config, config overrides default\n const minScore = opts.minScore\n ? parseInt(opts.minScore, 10)\n : config.minScore ?? null;\n\n // 1. Detect project\n const spinner = ora(\"Detecting project...\").start();\n const project = await detectProject(cwd);\n\n if (project.framework === \"unknown\") {\n spinner.fail(\"No supported framework detected\");\n if (!jsonOutput) {\n console.log(chalk.dim(\" Supported: Next.js, Nuxt, Remix, Astro, SvelteKit.\"));\n console.log(chalk.dim(\" For any live site, use: npx indxel crawl <url>\"));\n }\n process.exit(1);\n }\n\n if (!project.usesAppRouter) {\n spinner.fail(`No pages directory detected for ${frameworkLabel(project.framework)}`);\n if (!jsonOutput) {\n const hints: Record<string, string> = {\n nextjs: \"indxel requires Next.js App Router (src/app or app directory).\",\n nuxt: \"indxel requires a pages/ directory for Nuxt.\",\n remix: \"indxel requires an app/routes/ directory for Remix.\",\n astro: \"indxel requires a src/pages/ directory for Astro.\",\n sveltekit: \"indxel requires a src/routes/ directory for SvelteKit.\",\n unknown: \"\",\n };\n console.log(chalk.dim(` ${hints[project.framework]}`));\n }\n process.exit(1);\n }\n\n const label = frameworkLabel(project.framework);\n const version = project.frameworkVersion ? ` ${project.frameworkVersion}` : \"\";\n spinner.succeed(`Detected ${label}${version}`);\n\n // 2. Scan pages\n const scanSpinner = ora(\"Scanning pages...\").start();\n const allPages = await scanProject(project.framework, cwd, project.appDir);\n\n if (allPages.length === 0) {\n scanSpinner.fail(\"No pages found\");\n if (!jsonOutput) {\n console.log(chalk.dim(` No page files found in ${project.appDir}/`));\n }\n process.exit(1);\n }\n\n // Filter out ignored routes\n const ignoreRoutes = config.ignoreRoutes ?? [];\n const pages = ignoreRoutes.length > 0\n ? allPages.filter((p) => !ignoreRoutes.some((pattern) => matchRoute(p.route, pattern)))\n : allPages;\n const ignoredCount = allPages.length - pages.length;\n\n scanSpinner.succeed(`Found ${allPages.length} page${allPages.length > 1 ? \"s\" : \"\"}${ignoredCount > 0 ? ` (${ignoredCount} ignored)` : \"\"}`);\n\n // 3. Separate static vs dynamic pages\n const staticPages = pages.filter((p) => !p.hasDynamicMetadata);\n const dynamicPages = pages.filter((p) => p.hasDynamicMetadata);\n\n if (!jsonOutput) {\n console.log(\"\");\n console.log(chalk.bold(` Checking ${staticPages.length} page${staticPages.length !== 1 ? \"s\" : \"\"}...`));\n if (dynamicPages.length > 0) {\n console.log(chalk.dim(` (${dynamicPages.length} dynamic page${dynamicPages.length !== 1 ? \"s\" : \"\"} skipped)`));\n }\n if (ignoredCount > 0) {\n console.log(chalk.dim(` (${ignoredCount} page${ignoredCount !== 1 ? \"s\" : \"\"} excluded by ignoreRoutes)`));\n }\n console.log(\"\");\n }\n\n // 4. Validate static pages only\n const results: CheckResult[] = [];\n\n for (const page of staticPages) {\n const validation = validateMetadata(page.extractedMetadata, {\n strict: isStrict,\n disabledRules: config.disabledRules,\n });\n\n const result: CheckResult = { page, validation };\n results.push(result);\n\n if (!jsonOutput) {\n console.log(formatPageResult(result));\n }\n }\n\n // Show skipped dynamic pages\n if (!jsonOutput && dynamicPages.length > 0) {\n console.log(\"\");\n for (const page of dynamicPages) {\n console.log(formatSkippedPage(page));\n }\n }\n\n // 5. Compute summary (score only counts static pages)\n const summary = computeSummary(results, dynamicPages.length);\n\n // 6. Save results for future diff\n await saveCheckResult(cwd, summary);\n\n // 7. Show diff if requested\n if (showDiff && !jsonOutput) {\n const previous = await loadPreviousCheck(cwd);\n if (previous) {\n console.log(formatDiff(summary, previous.summary));\n } else {\n console.log(chalk.dim(\"\\n No previous check found. Run again to see a diff.\\n\"));\n }\n }\n\n // 8. Output\n if (jsonOutput) {\n console.log(formatJSON(summary));\n } else {\n console.log(formatSummary(summary));\n }\n\n // 9. Show fix suggestions if requested\n if (showFix && !jsonOutput) {\n const fixes = generateFixSuggestions(results, config.baseUrl);\n if (fixes.length > 0) {\n console.log(chalk.bold(\" Suggested fixes:\\n\"));\n for (const fix of fixes) {\n console.log(fix);\n }\n }\n }\n\n // 10. Push to dashboard\n if (opts.push) {\n const apiKey = await resolveApiKey(opts.apiKey);\n if (!apiKey) {\n if (!jsonOutput) {\n console.log(chalk.yellow(\" ⚠\") + \" To push results to your dashboard, link your project first:\");\n console.log(\"\");\n console.log(chalk.bold(\" npx indxel link\"));\n console.log(\"\");\n console.log(chalk.dim(\" Or use --api-key / set INDXEL_API_KEY.\"));\n console.log(\"\");\n }\n } else {\n const pushSpinner = jsonOutput ? null : ora(\"Pushing results to Indxel...\").start();\n try {\n const pushUrl = process.env.INDXEL_API_URL || \"https://indxel.com\";\n const res = await fetch(`${pushUrl}/api/cli/push`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n type: \"check\",\n check: {\n score: summary.averageScore,\n grade: summary.grade,\n totalPages: summary.totalPages,\n passedPages: summary.passedPages,\n criticalErrors: summary.criticalErrors,\n optionalErrors: summary.optionalErrors,\n pages: summary.results.map((r) => ({\n route: r.page.route,\n score: r.validation.score,\n errors: r.validation.errors.length,\n warnings: r.validation.warnings.length,\n })),\n },\n }),\n });\n if (res.ok) {\n const data = (await res.json()) as { checkId?: string; usage?: { used: number; limit: number } };\n if (pushSpinner) pushSpinner.succeed(`Pushed to dashboard — check ${data.checkId}`);\n if (data.usage && !jsonOutput) {\n const pct = Math.round((data.usage.used / data.usage.limit) * 100);\n const usageColor = pct >= 80 ? chalk.yellow : chalk.dim;\n console.log(usageColor(` Usage: ${data.usage.used}/${data.usage.limit} checks this month (${pct}%)`));\n }\n } else {\n const data = (await res.json().catch(() => ({}))) as { error?: string };\n if (pushSpinner) pushSpinner.fail(`Push failed: ${data.error || res.statusText}`);\n }\n } catch (err) {\n if (pushSpinner) pushSpinner.fail(`Push failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n if (!jsonOutput) console.log(\"\");\n }\n }\n\n // 11. Nudge toward continuous monitoring (interactive mode only, not CI)\n if (!jsonOutput && !isCI) {\n if (!opts.push) {\n console.log(chalk.dim(\" Save to dashboard → \") + chalk.bold(\"npx indxel check --push\"));\n }\n console.log(chalk.dim(\" Guard deploys → \") + chalk.bold(\"npx indxel init --hook\"));\n console.log(\"\");\n }\n\n // 11. Exit code\n if (minScore !== null) {\n // --min-score mode: fail only if score is below threshold\n if (summary.averageScore < minScore) {\n if (!jsonOutput) {\n console.log(\n chalk.red(` Score ${summary.averageScore} is below minimum ${minScore}.`),\n );\n }\n process.exit(1);\n }\n } else if (summary.criticalErrors > 0) {\n // Default mode: fail on any error\n process.exit(1);\n }\n });\n\n/** Match a route against a pattern with simple glob support.\n * Supports trailing /* for prefix matching (e.g., \"/dashboard/*\" matches \"/dashboard/settings\"). */\nfunction matchRoute(route: string, pattern: string): boolean {\n if (pattern.endsWith(\"/*\")) {\n const prefix = pattern.slice(0, -2);\n return route === prefix || route.startsWith(prefix + \"/\");\n }\n return route === pattern;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join, relative, dirname, sep } from \"node:path\";\nimport { glob } from \"glob\";\nimport type { ResolvedMetadata } from \"indxel\";\n\nexport interface PageInfo {\n /** File path relative to project root */\n filePath: string;\n /** Route path (e.g., \"/blog/[slug]\") */\n route: string;\n /** Whether the page exports metadata or generateMetadata */\n hasMetadata: boolean;\n /** Whether the page exports generateMetadata (dynamic) */\n hasDynamicMetadata: boolean;\n /** Whether the page is a client component ('use client') */\n isClientComponent: boolean;\n /** Whether the title uses absolute: (skip template) */\n titleIsAbsolute: boolean;\n /** Extracted static metadata fields (best effort from source parsing) */\n extractedMetadata: ResolvedMetadata;\n}\n\n/**\n * Scan the app directory for all page files and extract metadata info.\n * This does static analysis of the source code (no build required).\n */\nexport async function scanPages(\n projectRoot: string,\n appDir: string,\n): Promise<PageInfo[]> {\n const appDirFull = join(projectRoot, appDir);\n\n // Find all page.tsx/page.ts/page.jsx/page.js files\n const pageFiles = await glob(\"**/page.{tsx,ts,jsx,js}\", {\n cwd: appDirFull,\n ignore: [\"**/node_modules/**\", \"**/_*/**\"],\n });\n\n const pages: PageInfo[] = [];\n\n for (const file of pageFiles) {\n const fullPath = join(appDirFull, file);\n const content = await readFile(fullPath, \"utf-8\");\n const route = filePathToRoute(file);\n const isClient = isClientComponent(content);\n\n const page: PageInfo = {\n filePath: join(appDir, file),\n route,\n hasMetadata: false,\n hasDynamicMetadata: false,\n isClientComponent: isClient,\n titleIsAbsolute: false,\n extractedMetadata: createEmptyMetadata(),\n };\n\n // Check for metadata exports\n page.hasDynamicMetadata = hasExport(content, \"generateMetadata\");\n page.hasMetadata = page.hasDynamicMetadata || hasExport(content, \"metadata\");\n\n // Extract static metadata (best effort)\n if (page.hasDynamicMetadata) {\n // generateMetadata() pages can't be analyzed statically — regex can't\n // parse function bodies. Leave metadata empty; `indxel crawl` handles these.\n } else if (!isClient || page.hasMetadata) {\n // Skip extraction for client components without metadata export —\n // regex would match JSX content instead of actual metadata\n page.extractedMetadata = extractStaticMetadata(content);\n // Check if the title was from absolute: (no template should be applied)\n const metaBlock = findMetadataBlock(content);\n if (metaBlock && /absolute\\s*:\\s*[\"'`]/.test(metaBlock)) {\n page.titleIsAbsolute = true;\n }\n }\n\n pages.push(page);\n }\n\n // Also check layout files for metadata\n const layoutFiles = await glob(\"**/layout.{tsx,ts,jsx,js}\", {\n cwd: appDirFull,\n ignore: [\"**/node_modules/**\", \"**/_*/**\"],\n });\n\n // Sort layouts by depth descending — deeper layouts get merge priority,\n // root layout fills remaining gaps last\n const sortedLayouts = layoutFiles.sort((a, b) => {\n const depthA = a.split(sep).length;\n const depthB = b.split(sep).length;\n return depthB - depthA;\n });\n\n for (const file of sortedLayouts) {\n const fullPath = join(appDirFull, file);\n const content = await readFile(fullPath, \"utf-8\");\n const route = filePathToRoute(file).replace(/\\/layout$/, \"\") || \"/\";\n\n const hasMetadataExport = hasExport(content, \"metadata\") || hasExport(content, \"generateMetadata\");\n if (hasMetadataExport) {\n const layoutMeta = extractStaticMetadata(content);\n\n // Extract title template from layout for title resolution\n const templateMatch = content.match(/template\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/);\n const titleTemplate = templateMatch?.[1] ?? null;\n\n for (const page of pages) {\n if (page.route.startsWith(route) || route === \"/\") {\n // If the page has its own title (not absolute) and layout has a template, resolve it\n if (page.extractedMetadata.title && titleTemplate && !page.titleIsAbsolute) {\n page.extractedMetadata.title = titleTemplate.replace(\"%s\", page.extractedMetadata.title);\n page.titleIsAbsolute = true; // prevent double-templating from parent layouts\n }\n\n // Merge layout metadata as fallback (page-level takes precedence)\n mergeMetadata(page.extractedMetadata, layoutMeta);\n if (!page.hasMetadata) {\n page.hasMetadata = true;\n }\n }\n }\n }\n }\n\n return pages.sort((a, b) => a.route.localeCompare(b.route));\n}\n\n/** Convert a file path like \"blog/[slug]/page.tsx\" to route \"/blog/[slug]\" */\nfunction filePathToRoute(filePath: string): string {\n const dir = dirname(filePath);\n if (dir === \".\") return \"/\";\n // Normalize separators and add leading slash\n const route = \"/\" + dir.split(sep).join(\"/\");\n // Remove route groups like (marketing)\n return route.replace(/\\/\\([^)]+\\)/g, \"\") || \"/\";\n}\n\n/** Check if the source starts with 'use client' directive */\nfunction isClientComponent(source: string): boolean {\n // Match 'use client' or \"use client\" at the start of the file (ignoring whitespace/comments)\n return /^[\\s]*(['\"])use client\\1/.test(source);\n}\n\n/** Check if source code exports a given name */\nfunction hasExport(source: string, name: string): boolean {\n // Match: export const metadata, export async function generateMetadata, export function generateMetadata\n const patterns = [\n new RegExp(`export\\\\s+(const|let|var)\\\\s+${name}\\\\b`),\n new RegExp(`export\\\\s+(async\\\\s+)?function\\\\s+${name}\\\\b`),\n new RegExp(`export\\\\s+\\\\{[^}]*\\\\b${name}\\\\b[^}]*\\\\}`),\n ];\n return patterns.some((p) => p.test(source));\n}\n\n/**\n * Find the metadata export block in source code using brace-matching.\n * Returns the block content or null if not found.\n */\nfunction findMetadataBlock(source: string): string | null {\n const match = source.match(/export\\s+(const|let|var)\\s+metadata[\\s:]/);\n if (!match || match.index === undefined) return null;\n\n const start = source.indexOf(\"{\", match.index);\n if (start === -1) return null;\n\n let depth = 0;\n for (let i = start; i < source.length; i++) {\n if (source[i] === \"{\") depth++;\n else if (source[i] === \"}\") {\n depth--;\n if (depth === 0) return source.substring(start, i + 1);\n }\n }\n return null;\n}\n\n/**\n * Detect if `export const metadata` is assigned via a helper function call\n * (e.g., `export const metadata = generatePageMetadata({ ... })`).\n * Returns true if a wrapper function is used.\n */\nfunction isMetadataFromWrapper(source: string): boolean {\n return /export\\s+(const|let|var)\\s+metadata\\s*=\\s*[a-zA-Z_$]\\w*\\s*\\(/.test(source);\n}\n\n/**\n * Extract metadata from static `export const metadata = { ... }` patterns.\n * This is best-effort source code parsing (not AST — fast and simple).\n */\nfunction extractStaticMetadata(source: string): ResolvedMetadata {\n const meta = createEmptyMetadata();\n\n const usesWrapper = isMetadataFromWrapper(source);\n\n // Scope extraction to the metadata export block when possible\n // This prevents matching JSX content or unrelated objects\n const metaBlock = findMetadataBlock(source) ?? source;\n\n // Extract title — handle multiple patterns:\n // 1. title: \"simple string\"\n // 2. title: { absolute: \"...\" }\n // 3. title: { default: \"...\" }\n // Use backreference to match same quote type (handles apostrophes in content)\n const absoluteMatch = metaBlock.match(\n /absolute\\s*:\\s*([\"'`])(.*?)\\1/s,\n );\n if (absoluteMatch) {\n meta.title = absoluteMatch[2];\n } else {\n const defaultMatch = metaBlock.match(\n /default\\s*:\\s*([\"'`])(.*?)\\1/s,\n );\n if (defaultMatch) {\n meta.title = defaultMatch[2];\n } else {\n // Simple title: \"string\" — but only match top-level title, not nested ones\n const titleMatch = metaBlock.match(\n /(?:^|[,{\\n])\\s*title\\s*:\\s*([\"'`])(.*?)\\1/s,\n );\n if (titleMatch) {\n meta.title = titleMatch[2];\n }\n }\n }\n\n // Extract description — scope to metadata block\n // Use backreference to match the same quote type (handles apostrophes in content)\n const descMatch = metaBlock.match(\n /(?:^|[,{\\n])\\s*description\\s*:\\s*\\n?\\s*([\"'`])(.*?)\\1/s,\n );\n if (descMatch) {\n meta.description = descMatch[2];\n }\n\n // Check for openGraph object (scoped to metadata block)\n if (/openGraph\\s*:\\s*\\{/.test(metaBlock)) {\n const ogTitleMatch = metaBlock.match(\n /openGraph\\s*:\\s*\\{[^}]*title\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/s,\n );\n meta.ogTitle = ogTitleMatch ? ogTitleMatch[1] : \"[detected]\";\n\n const ogDescMatch = metaBlock.match(\n /openGraph\\s*:\\s*\\{[^}]*description\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/s,\n );\n meta.ogDescription = ogDescMatch ? ogDescMatch[1] : \"[detected]\";\n\n if (!meta.ogImage) meta.ogImage = \"[detected]\";\n if (/images\\s*:\\s*\\[/.test(metaBlock)) {\n meta.ogImage = \"[detected]\";\n }\n }\n\n // Check for twitter config (scoped to metadata block)\n if (/twitter\\s*:\\s*\\{/.test(metaBlock)) {\n const cardMatch = metaBlock.match(\n /card\\s*:\\s*[\"'`](summary|summary_large_image)[\"'`]/,\n );\n meta.twitterCard = cardMatch ? cardMatch[1] : \"[detected]\";\n }\n\n // Check for robots (scoped to metadata block)\n if (/robots\\s*:\\s*\\{/.test(metaBlock) || /robots\\s*:\\s*[\"'`]/.test(metaBlock)) {\n const robotsMatch = metaBlock.match(\n /robots\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/,\n );\n if (robotsMatch) meta.robots = robotsMatch[1];\n }\n\n // Check for alternates/canonical (scoped to metadata block)\n if (/alternates\\s*:\\s*\\{/.test(metaBlock)) {\n const canonicalMatch = metaBlock.match(\n /canonical\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/,\n );\n if (canonicalMatch) {\n meta.canonical = canonicalMatch[1];\n } else if (/canonical\\s*:/.test(metaBlock)) {\n meta.canonical = \"[detected]\";\n }\n\n // Detect hreflang / languages declarations\n if (/languages\\s*:\\s*\\{/.test(metaBlock)) {\n const langs: Record<string, string> = {};\n const langMatches = metaBlock.matchAll(\n /[\"'`](\\w{2}(?:-\\w{2})?)[\"'`]\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/g,\n );\n for (const m of langMatches) {\n if (m[1] && m[2] && m[2].startsWith(\"http\")) {\n langs[m[1]] = m[2];\n }\n }\n if (Object.keys(langs).length > 0) {\n meta.alternates = langs;\n }\n }\n }\n\n // --- Fallback: detect fields set via variable references ---\n // When metadata values come from imported config (e.g., siteConfig.xxx),\n // regex can't extract the string value, but we know the field is present.\n // This is critical for layout-to-page merge to cascade correctly.\n if (!meta.title && /(?:^|[,{\\n])\\s*title\\s*:\\s*(?:\\{|[a-zA-Z_$])/.test(metaBlock)) {\n meta.title = \"[detected]\";\n }\n if (!meta.description && /(?:^|[,{\\n])\\s*description\\s*:\\s*[a-zA-Z_$]/.test(metaBlock)) {\n meta.description = \"[detected]\";\n }\n\n // --- Wrapper function inference ---\n // When metadata is assigned via a helper (e.g., generatePageMetadata({ title, description })),\n // the wrapper typically generates openGraph, twitter, canonical, and robots from the args.\n // Mark these as [detected] so the validator doesn't penalize missing fields.\n if (usesWrapper && (meta.title || meta.description)) {\n if (!meta.ogTitle) meta.ogTitle = \"[detected]\";\n if (!meta.ogDescription) meta.ogDescription = \"[detected]\";\n if (!meta.ogImage) meta.ogImage = \"[detected]\";\n if (!meta.twitterCard) meta.twitterCard = \"[detected]\";\n if (!meta.canonical) meta.canonical = \"[detected]\";\n if (!meta.robots) meta.robots = \"[detected]\";\n }\n\n // Check for structured data — search full source (JSON-LD can be in JSX, not metadata)\n if (/application\\/ld\\+json/.test(source) || /generateLD/.test(source) || /JsonLD/.test(source)) {\n meta.structuredData = [{ \"@context\": \"https://schema.org\", \"@type\": \"detected\" }];\n }\n\n // Check for viewport — search full source (can be a separate export)\n if (/viewport\\s*[:=]/.test(source)) {\n meta.viewport = \"detected\";\n }\n\n // Check for icons/favicon (scoped to metadata block)\n if (/icons\\s*:\\s*\\{/.test(metaBlock) || /favicon/.test(metaBlock)) {\n meta.favicon = \"detected\";\n }\n\n return meta;\n}\n\nfunction createEmptyMetadata(): ResolvedMetadata {\n return {\n title: null,\n description: null,\n canonical: null,\n ogTitle: null,\n ogDescription: null,\n ogImage: null,\n ogType: null,\n twitterCard: null,\n twitterTitle: null,\n twitterDescription: null,\n robots: null,\n alternates: null,\n structuredData: null,\n viewport: null,\n favicon: null,\n };\n}\n\n/** Merge source metadata into target (target takes precedence if already set) */\nfunction mergeMetadata(target: ResolvedMetadata, source: ResolvedMetadata): void {\n for (const key of Object.keys(source) as (keyof ResolvedMetadata)[]) {\n if (target[key] === null || target[key] === undefined) {\n (target as Record<string, unknown>)[key] = source[key];\n }\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join, dirname, sep } from \"node:path\";\nimport { glob } from \"glob\";\nimport type { ResolvedMetadata } from \"indxel\";\nimport type { PageInfo } from \"./scanner.js\";\n\n/**\n * Scan a Nuxt 3 project's pages/ directory for SEO metadata.\n * Looks for useSeoMeta(), useHead(), and definePageMeta() in .vue files.\n */\nexport async function scanNuxtPages(\n projectRoot: string,\n appDir: string,\n): Promise<PageInfo[]> {\n const appDirFull = join(projectRoot, appDir);\n\n // Find all .vue page files\n const pageFiles = await glob(\"**/*.vue\", {\n cwd: appDirFull,\n ignore: [\"**/node_modules/**\", \"**/components/**\", \"**/_*/**\"],\n });\n\n const pages: PageInfo[] = [];\n\n for (const file of pageFiles) {\n const fullPath = join(appDirFull, file);\n const content = await readFile(fullPath, \"utf-8\");\n const route = vueFilePathToRoute(file);\n\n const page: PageInfo = {\n filePath: join(appDir, file),\n route,\n hasMetadata: false,\n hasDynamicMetadata: false,\n isClientComponent: false,\n titleIsAbsolute: false,\n extractedMetadata: createEmptyMetadata(),\n };\n\n // Detect useSeoMeta() — Nuxt 3 composable\n const hasUseSeoMeta = /useSeoMeta\\s*\\(/.test(content);\n // Detect useHead() — Nuxt 3 composable\n const hasUseHead = /useHead\\s*\\(/.test(content);\n // Detect definePageMeta() — Nuxt 3 macro\n const hasDefinePageMeta = /definePageMeta\\s*\\(/.test(content);\n\n page.hasMetadata = hasUseSeoMeta || hasUseHead || hasDefinePageMeta;\n\n // If useSeoMeta/useHead depend on computed/ref values, treat as dynamic\n if (page.hasMetadata) {\n const hasComputed = /computed\\s*\\(/.test(content) || /useAsyncData/.test(content) || /useFetch/.test(content);\n page.hasDynamicMetadata = hasComputed;\n }\n\n // Extract static metadata from useSeoMeta()\n if (hasUseSeoMeta) {\n page.extractedMetadata = extractNuxtSeoMeta(content);\n } else if (hasUseHead) {\n page.extractedMetadata = extractNuxtUseHead(content);\n }\n\n pages.push(page);\n }\n\n // Check app.vue + layouts/ directory for shared metadata\n // Nuxt resolves: app.vue → layouts/default.vue → pages/*.vue\n const layoutSources: Array<{ content: string; scope: \"global\" }> = [];\n\n // 1. app.vue (root wrapper)\n try {\n const appVueContent = await readFile(join(projectRoot, \"app.vue\"), \"utf-8\");\n layoutSources.push({ content: appVueContent, scope: \"global\" });\n } catch { /* no app.vue */ }\n\n // 2. layouts/ directory\n const layoutDir = join(projectRoot, \"layouts\");\n try {\n const layoutFiles = await glob(\"**/*.vue\", {\n cwd: layoutDir,\n ignore: [\"**/node_modules/**\"],\n });\n for (const file of layoutFiles) {\n try {\n const content = await readFile(join(layoutDir, file), \"utf-8\");\n layoutSources.push({ content, scope: \"global\" });\n } catch { /* skip unreadable */ }\n }\n } catch { /* no layouts/ directory */ }\n\n // Apply layout metadata + titleTemplate as fallback\n for (const layout of layoutSources) {\n const hasUseSeoMeta = /useSeoMeta\\s*\\(/.test(layout.content);\n const hasUseHead = /useHead\\s*\\(/.test(layout.content);\n\n if (!hasUseSeoMeta && !hasUseHead) continue;\n\n const layoutMeta = hasUseSeoMeta\n ? extractNuxtSeoMeta(layout.content)\n : extractNuxtUseHead(layout.content);\n\n // Extract titleTemplate from useHead (Nuxt pattern: titleTemplate: '%s | My Site')\n const templateMatch = layout.content.match(/titleTemplate\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/);\n const titleTemplate = templateMatch?.[1] ?? null;\n\n for (const page of pages) {\n // Apply titleTemplate if page has a raw title\n if (page.extractedMetadata.title && titleTemplate && !page.titleIsAbsolute\n && page.extractedMetadata.title !== \"[detected]\") {\n page.extractedMetadata.title = titleTemplate.replace(\"%s\", page.extractedMetadata.title);\n page.titleIsAbsolute = true;\n }\n\n mergeMetadata(page.extractedMetadata, layoutMeta);\n if (!page.hasMetadata) page.hasMetadata = true;\n }\n }\n\n return pages.sort((a, b) => a.route.localeCompare(b.route));\n}\n\n/** Convert Nuxt page file path to route (e.g., \"blog/[slug].vue\" → \"/blog/[slug]\") */\nfunction vueFilePathToRoute(filePath: string): string {\n // Remove .vue extension\n let route = filePath.replace(/\\.vue$/, \"\");\n // index → /\n route = route.replace(/\\/index$/, \"\").replace(/^index$/, \"\");\n // Normalize separators\n route = \"/\" + route.split(sep).join(\"/\");\n // Remove route groups\n route = route.replace(/\\/\\([^)]+\\)/g, \"\") || \"/\";\n return route;\n}\n\n/** Extract metadata from useSeoMeta({ ... }) */\nfunction extractNuxtSeoMeta(source: string): ResolvedMetadata {\n const meta = createEmptyMetadata();\n\n const block = findCallBlock(source, \"useSeoMeta\");\n if (!block) return meta;\n\n // useSeoMeta uses flat keys: title, description, ogTitle, ogDescription, ogImage, etc.\n // IMPORTANT: use word boundary or negative lookbehind to avoid ogDescription matching description\n const titleMatch = block.match(/(?<![a-zA-Z])title\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/);\n if (titleMatch) meta.title = titleMatch[1];\n\n // Match \"description\" but NOT \"ogDescription\" or \"twitterDescription\"\n const descMatch = block.match(/(?<![a-zA-Z])description\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/);\n if (descMatch) meta.description = descMatch[1];\n\n const ogTitleMatch = block.match(/ogTitle\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/);\n if (ogTitleMatch) meta.ogTitle = ogTitleMatch[1];\n\n const ogDescMatch = block.match(/ogDescription\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/);\n if (ogDescMatch) meta.ogDescription = ogDescMatch[1];\n\n const ogImageMatch = block.match(/ogImage\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/);\n if (ogImageMatch) meta.ogImage = ogImageMatch[1];\n\n const twitterCardMatch = block.match(/twitterCard\\s*:\\s*[\"'`](summary|summary_large_image)[\"'`]/);\n if (twitterCardMatch) meta.twitterCard = twitterCardMatch[1];\n\n const robotsMatch = block.match(/(?<![a-zA-Z])robots\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/);\n if (robotsMatch) meta.robots = robotsMatch[1];\n\n // Detect variable references as [detected]\n if (!meta.title && /(?<![a-zA-Z])title\\s*:\\s*[a-zA-Z_$]/.test(block)) meta.title = \"[detected]\";\n if (!meta.description && /(?<![a-zA-Z])description\\s*:\\s*[a-zA-Z_$]/.test(block)) meta.description = \"[detected]\";\n if (!meta.ogTitle && /ogTitle\\s*:\\s*[a-zA-Z_$]/.test(block)) meta.ogTitle = \"[detected]\";\n if (!meta.ogDescription && /ogDescription\\s*:\\s*[a-zA-Z_$]/.test(block)) meta.ogDescription = \"[detected]\";\n if (!meta.ogImage && /ogImage\\s*:\\s*[a-zA-Z_$]/.test(block)) meta.ogImage = \"[detected]\";\n\n return meta;\n}\n\n/** Extract metadata from useHead({ ... }) */\nfunction extractNuxtUseHead(source: string): ResolvedMetadata {\n const meta = createEmptyMetadata();\n\n const block = findCallBlock(source, \"useHead\");\n if (!block) return meta;\n\n // title\n const titleMatch = block.match(/title\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/);\n if (titleMatch) meta.title = titleMatch[1];\n\n // meta tags within useHead\n const descMatch = block.match(/name\\s*:\\s*[\"'`]description[\"'`]\\s*,\\s*content\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/);\n if (descMatch) meta.description = descMatch[1];\n\n const ogTitleMatch = block.match(/property\\s*:\\s*[\"'`]og:title[\"'`]\\s*,\\s*content\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/);\n if (ogTitleMatch) meta.ogTitle = ogTitleMatch[1];\n\n const ogDescMatch = block.match(/property\\s*:\\s*[\"'`]og:description[\"'`]\\s*,\\s*content\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/);\n if (ogDescMatch) meta.ogDescription = ogDescMatch[1];\n\n const ogImageMatch = block.match(/property\\s*:\\s*[\"'`]og:image[\"'`]\\s*,\\s*content\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/);\n if (ogImageMatch) meta.ogImage = ogImageMatch[1];\n\n // Detect variable references\n if (!meta.title && /title\\s*:\\s*[a-zA-Z_$]/.test(block)) meta.title = \"[detected]\";\n\n // JSON-LD\n if (/application\\/ld\\+json/.test(source)) {\n meta.structuredData = [{ \"@context\": \"https://schema.org\", \"@type\": \"detected\" }];\n }\n\n return meta;\n}\n\n/** Find the argument block of a function call (brace-matching) */\nfunction findCallBlock(source: string, funcName: string): string | null {\n const regex = new RegExp(`${funcName}\\\\s*\\\\(`);\n const match = source.match(regex);\n if (!match || match.index === undefined) return null;\n\n const start = source.indexOf(\"(\", match.index);\n if (start === -1) return null;\n\n let depth = 0;\n for (let i = start; i < source.length; i++) {\n if (source[i] === \"(\") depth++;\n else if (source[i] === \")\") {\n depth--;\n if (depth === 0) return source.substring(start, i + 1);\n }\n }\n return null;\n}\n\nfunction createEmptyMetadata(): ResolvedMetadata {\n return {\n title: null, description: null, canonical: null,\n ogTitle: null, ogDescription: null, ogImage: null, ogType: null,\n twitterCard: null, twitterTitle: null, twitterDescription: null,\n robots: null, alternates: null, structuredData: null,\n viewport: null, favicon: null,\n };\n}\n\nfunction mergeMetadata(target: ResolvedMetadata, source: ResolvedMetadata): void {\n for (const key of Object.keys(source) as (keyof ResolvedMetadata)[]) {\n if (target[key] === null || target[key] === undefined) {\n (target as Record<string, unknown>)[key] = source[key];\n }\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join, dirname, sep } from \"node:path\";\nimport { glob } from \"glob\";\nimport type { ResolvedMetadata } from \"indxel\";\nimport type { PageInfo } from \"./scanner.js\";\n\n/**\n * Scan a Remix project's routes/ directory for SEO metadata.\n * Looks for export const meta / export function meta in route files.\n */\nexport async function scanRemixPages(\n projectRoot: string,\n appDir: string,\n): Promise<PageInfo[]> {\n const appDirFull = join(projectRoot, appDir);\n\n // Remix route files: .tsx, .ts, .jsx, .js\n const routeFiles = await glob(\"**/*.{tsx,ts,jsx,js}\", {\n cwd: appDirFull,\n ignore: [\"**/node_modules/**\", \"**/__*/**\", \"**/*.server.*\", \"**/*.client.*\"],\n });\n\n const pages: PageInfo[] = [];\n\n for (const file of routeFiles) {\n const fullPath = join(appDirFull, file);\n const content = await readFile(fullPath, \"utf-8\");\n const route = remixFilePathToRoute(file);\n\n const page: PageInfo = {\n filePath: join(appDir, file),\n route,\n hasMetadata: false,\n hasDynamicMetadata: false,\n isClientComponent: false,\n titleIsAbsolute: false,\n extractedMetadata: createEmptyMetadata(),\n };\n\n // Remix v2: export const meta = () => [...]\n // Remix v1: export const meta = () => ({...})\n const hasMetaExport = hasExport(content, \"meta\");\n page.hasMetadata = hasMetaExport;\n\n // Check if meta actually uses loader data in its body (not just the signature).\n // In Remix v2, `({ data })` is the standard signature even when unused.\n // Only mark as dynamic if the meta body references `data.` or uses matches/params.\n if (hasMetaExport) {\n const metaBody = extractMetaBody(content);\n if (metaBody) {\n const usesData = /\\bdata\\./.test(metaBody) || /\\bdata\\[/.test(metaBody);\n const usesMatches = /\\bmatches\\b/.test(metaBody);\n const usesParams = /\\bparams\\./.test(metaBody);\n page.hasDynamicMetadata = usesData || usesMatches || usesParams;\n }\n }\n\n // Always try to extract what we can, even for dynamic pages\n if (hasMetaExport) {\n page.extractedMetadata = extractRemixMeta(content);\n }\n\n // JSON-LD detection\n if (/application\\/ld\\+json/.test(content)) {\n page.extractedMetadata.structuredData = [{ \"@context\": \"https://schema.org\", \"@type\": \"detected\" }];\n }\n\n pages.push(page);\n }\n\n // Check root.tsx for layout-level meta\n for (const rootFile of [\"root.tsx\", \"root.jsx\", \"root.ts\", \"root.js\"]) {\n const rootPath = join(projectRoot, \"app\", rootFile);\n try {\n const rootContent = await readFile(rootPath, \"utf-8\");\n if (hasExport(rootContent, \"meta\")) {\n const rootMeta = extractRemixMeta(rootContent);\n for (const page of pages) {\n mergeMetadata(page.extractedMetadata, rootMeta);\n if (!page.hasMetadata) page.hasMetadata = true;\n }\n }\n } catch {\n // No root file — continue\n }\n }\n\n return pages.sort((a, b) => a.route.localeCompare(b.route));\n}\n\n/**\n * Convert Remix route file path to route.\n * Remix v2 flat routes: \"blog.$slug.tsx\" → \"/blog/:slug\"\n * Nested routes: \"blog/index.tsx\" → \"/blog\"\n */\nfunction remixFilePathToRoute(filePath: string): string {\n let route = filePath\n .replace(/\\.(tsx|ts|jsx|js)$/, \"\")\n .replace(/\\/index$/, \"\")\n .replace(/^index$/, \"\");\n\n // Remix v2 flat route convention: dots become slashes\n // but _index stays as index route\n route = route.replace(/\\._index$/, \"\");\n // $param → :param (but we keep [] for consistency with other scanners)\n route = route.replace(/\\$/g, \"[\").replace(/\\./g, \"/\");\n\n // Fix bracket matching for params\n route = route.replace(/\\[([^/]+)/g, (_, name) => `[${name}]`);\n\n // Normalize\n route = \"/\" + route.split(sep).join(\"/\");\n // Remove layout prefix _\n route = route.replace(/\\/_[^/]+/g, \"\");\n\n return route || \"/\";\n}\n\n/** Extract metadata from Remix v2 meta export: export const meta = () => [...] */\nfunction extractRemixMeta(source: string): ResolvedMetadata {\n const meta = createEmptyMetadata();\n\n // Find the meta export block\n const metaMatch = source.match(/export\\s+(?:const|function)\\s+meta\\s*=?\\s*(?:\\([^)]*\\)\\s*(?:=>)?\\s*)?[\\[({]/);\n if (!metaMatch || metaMatch.index === undefined) return meta;\n\n // Get a reasonable chunk after the match for parsing\n const startIdx = metaMatch.index;\n const block = source.substring(startIdx, Math.min(startIdx + 2000, source.length));\n\n // Remix v2 meta returns an array of objects: [{ title: \"...\" }, { name: \"description\", content: \"...\" }]\n const titleMatch = block.match(/\\{\\s*title\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/);\n if (titleMatch) meta.title = titleMatch[1];\n\n const descMatch = block.match(/name\\s*:\\s*[\"'`]description[\"'`]\\s*,\\s*content\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/);\n if (descMatch) meta.description = descMatch[1];\n\n const ogTitleMatch = block.match(/property\\s*:\\s*[\"'`]og:title[\"'`]\\s*,\\s*content\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/);\n if (ogTitleMatch) meta.ogTitle = ogTitleMatch[1];\n\n const ogDescMatch = block.match(/property\\s*:\\s*[\"'`]og:description[\"'`]\\s*,\\s*content\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/);\n if (ogDescMatch) meta.ogDescription = ogDescMatch[1];\n\n const ogImageMatch = block.match(/property\\s*:\\s*[\"'`]og:image[\"'`]\\s*,\\s*content\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/);\n if (ogImageMatch) meta.ogImage = ogImageMatch[1];\n\n // Detect variable references\n if (!meta.title && /title\\s*:\\s*[a-zA-Z_$]/.test(block)) meta.title = \"[detected]\";\n\n return meta;\n}\n\n/** Extract the body of the meta function (after the arrow/opening brace) */\nfunction extractMetaBody(source: string): string | null {\n // Match: export const meta = (...) => { ... } or export const meta = (...) => [...]\n const arrowMatch = source.match(/export\\s+(?:const|let|var)\\s+meta\\s*=\\s*\\([^)]*\\)\\s*(?::\\s*[^=]*?)?\\s*=>\\s*/);\n if (arrowMatch && arrowMatch.index !== undefined) {\n const bodyStart = arrowMatch.index + arrowMatch[0].length;\n return source.substring(bodyStart, Math.min(bodyStart + 3000, source.length));\n }\n // Match: export function meta(...) { ... }\n const funcMatch = source.match(/export\\s+function\\s+meta\\s*\\([^)]*\\)\\s*(?::\\s*[^{]*)?\\s*\\{/);\n if (funcMatch && funcMatch.index !== undefined) {\n const bodyStart = funcMatch.index + funcMatch[0].length;\n return source.substring(bodyStart, Math.min(bodyStart + 3000, source.length));\n }\n return null;\n}\n\nfunction hasExport(source: string, name: string): boolean {\n const patterns = [\n new RegExp(`export\\\\s+(const|let|var)\\\\s+${name}\\\\b`),\n new RegExp(`export\\\\s+(async\\\\s+)?function\\\\s+${name}\\\\b`),\n new RegExp(`export\\\\s+\\\\{[^}]*\\\\b${name}\\\\b[^}]*\\\\}`),\n ];\n return patterns.some((p) => p.test(source));\n}\n\nfunction createEmptyMetadata(): ResolvedMetadata {\n return {\n title: null, description: null, canonical: null,\n ogTitle: null, ogDescription: null, ogImage: null, ogType: null,\n twitterCard: null, twitterTitle: null, twitterDescription: null,\n robots: null, alternates: null, structuredData: null,\n viewport: null, favicon: null,\n };\n}\n\nfunction mergeMetadata(target: ResolvedMetadata, source: ResolvedMetadata): void {\n for (const key of Object.keys(source) as (keyof ResolvedMetadata)[]) {\n if (target[key] === null || target[key] === undefined) {\n (target as Record<string, unknown>)[key] = source[key];\n }\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join, dirname, sep } from \"node:path\";\nimport { glob } from \"glob\";\nimport type { ResolvedMetadata } from \"indxel\";\nimport type { PageInfo } from \"./scanner.js\";\n\n/**\n * Scan an Astro project's src/pages/ directory for SEO metadata.\n * Looks for <head> content in .astro files and frontmatter SEO props.\n */\nexport async function scanAstroPages(\n projectRoot: string,\n appDir: string,\n): Promise<PageInfo[]> {\n const appDirFull = join(projectRoot, appDir);\n\n // Astro pages: .astro, .md, .mdx files in src/pages/\n const pageFiles = await glob(\"**/*.{astro,md,mdx}\", {\n cwd: appDirFull,\n ignore: [\"**/node_modules/**\", \"**/_*/**\", \"**/components/**\"],\n });\n\n const pages: PageInfo[] = [];\n\n for (const file of pageFiles) {\n const fullPath = join(appDirFull, file);\n const content = await readFile(fullPath, \"utf-8\");\n const route = astroFilePathToRoute(file);\n\n const page: PageInfo = {\n filePath: join(appDir, file),\n route,\n hasMetadata: false,\n hasDynamicMetadata: false,\n isClientComponent: false,\n titleIsAbsolute: false,\n extractedMetadata: createEmptyMetadata(),\n };\n\n if (file.endsWith(\".md\") || file.endsWith(\".mdx\")) {\n // Markdown/MDX: extract frontmatter\n page.extractedMetadata = extractMarkdownMeta(content);\n page.hasMetadata = page.extractedMetadata.title !== null || page.extractedMetadata.description !== null;\n } else {\n // .astro file: check for <head> tags or SEO component usage\n page.extractedMetadata = extractAstroMeta(content);\n page.hasMetadata = hasAstroSeoSetup(content);\n\n // Dynamic if using Astro.props or getStaticPaths with spread\n page.hasDynamicMetadata = /Astro\\.props/.test(content) || /getStaticPaths/.test(content);\n }\n\n // JSON-LD detection\n if (/application\\/ld\\+json/.test(content)) {\n page.extractedMetadata.structuredData = [{ \"@context\": \"https://schema.org\", \"@type\": \"detected\" }];\n }\n\n pages.push(page);\n }\n\n // Check for Layout components that accept SEO props (the most common Astro pattern).\n // If a layout has <title>{Astro.props.title}</title>, and a page uses that layout,\n // check if the page passes title/description as props via the layout component.\n const layoutFiles = await glob(\"**/layouts/**/*.astro\", {\n cwd: join(projectRoot, \"src\"),\n ignore: [\"**/node_modules/**\"],\n });\n\n const layoutNames = new Set<string>();\n for (const file of layoutFiles) {\n try {\n const content = await readFile(join(projectRoot, \"src\", file), \"utf-8\");\n // If the layout has any SEO setup (even via props), record it\n if (hasAstroSeoSetup(content) || /Astro\\.props/.test(content)) {\n // Extract layout component name from filename (e.g., \"layouts/Layout.astro\" → \"Layout\")\n const name = file.replace(/.*\\//, \"\").replace(/\\.astro$/, \"\");\n layoutNames.add(name);\n\n const layoutMeta = extractAstroMeta(content);\n // Only merge static values (not [detected] from props) as fallback\n const staticLayoutMeta = { ...layoutMeta };\n if (staticLayoutMeta.title === \"[detected]\") staticLayoutMeta.title = null;\n if (staticLayoutMeta.description === \"[detected]\") staticLayoutMeta.description = null;\n\n for (const page of pages) {\n mergeMetadata(page.extractedMetadata, staticLayoutMeta as ResolvedMetadata);\n }\n }\n } catch {\n // Skip unreadable layouts\n }\n }\n\n // Now check if pages pass SEO props to known layout components.\n // Pattern: <Layout title=\"Page Title\" description=\"Page desc\" />\n if (layoutNames.size > 0) {\n const layoutPattern = new RegExp(\n `<(?:${[...layoutNames].join(\"|\")})\\\\s([^>]*)`,\n \"g\",\n );\n\n for (const page of pages) {\n const fullPath = join(appDirFull, page.filePath.replace(appDir + \"/\", \"\"));\n try {\n const content = await readFile(fullPath, \"utf-8\");\n const matches = content.matchAll(layoutPattern);\n for (const m of matches) {\n const attrs = m[1];\n if (!page.extractedMetadata.title) {\n const titleProp = attrs.match(/title=[\"']([^\"']+)[\"']/);\n if (titleProp) page.extractedMetadata.title = titleProp[1];\n else if (/title=\\{/.test(attrs)) page.extractedMetadata.title = \"[detected]\";\n }\n if (!page.extractedMetadata.description) {\n const descProp = attrs.match(/description=[\"']([^\"']+)[\"']/);\n if (descProp) page.extractedMetadata.description = descProp[1];\n else if (/description=\\{/.test(attrs)) page.extractedMetadata.description = \"[detected]\";\n }\n if (page.extractedMetadata.title || page.extractedMetadata.description) {\n page.hasMetadata = true;\n }\n }\n } catch {\n // Skip unreadable pages\n }\n }\n }\n\n return pages.sort((a, b) => a.route.localeCompare(b.route));\n}\n\n/** Convert Astro page path to route (e.g., \"blog/[slug].astro\" → \"/blog/[slug]\") */\nfunction astroFilePathToRoute(filePath: string): string {\n let route = filePath\n .replace(/\\.(astro|md|mdx)$/, \"\")\n .replace(/\\/index$/, \"\")\n .replace(/^index$/, \"\");\n\n route = \"/\" + route.split(sep).join(\"/\");\n // [...slug] → Astro catch-all\n return route || \"/\";\n}\n\n/** Check if .astro file has any SEO-specific setup (not just <meta charset>) */\nfunction hasAstroSeoSetup(source: string): boolean {\n // Match only SEO-relevant meta tags, not charset/viewport/etc.\n const hasSeoMeta =\n /<meta\\s[^>]*name=[\"']description[\"']/.test(source) ||\n /<meta\\s[^>]*property=[\"']og:/.test(source) ||\n /<meta\\s[^>]*name=[\"']robots[\"']/.test(source) ||\n /<meta\\s[^>]*name=[\"']twitter:/.test(source) ||\n /<meta\\s[^>]*content=[\"'][^\"']*[\"'][^>]*name=[\"']description[\"']/.test(source) ||\n /<meta\\s[^>]*content=[\"'][^\"']*[\"'][^>]*property=[\"']og:/.test(source);\n\n return (\n /<title[\\s>]/.test(source) ||\n hasSeoMeta ||\n /<SEO[\\s/>]/.test(source) || // Common Astro SEO component\n /<BaseHead[\\s/>]/.test(source) || // Common Astro pattern\n /@astrojs\\/seo/.test(source) ||\n /astro-seo/.test(source) ||\n /Astro\\.props\\.title/.test(source)\n );\n}\n\n/**\n * Extract a meta tag value, handling both attribute orders:\n * <meta name=\"description\" content=\"...\">\n * <meta content=\"...\" name=\"description\">\n */\nfunction extractMetaTag(source: string, attr: \"name\" | \"property\", name: string): string | null {\n // Order 1: name/property first, content second\n const r1 = new RegExp(`<meta\\\\s[^>]*${attr}=[\"']${name}[\"'][^>]*content=[\"']([^\"']+)[\"']`, \"i\");\n const m1 = source.match(r1);\n if (m1) return m1[1];\n // Order 2: content first, name/property second\n const r2 = new RegExp(`<meta\\\\s[^>]*content=[\"']([^\"']+)[\"'][^>]*${attr}=[\"']${name}[\"']`, \"i\");\n const m2 = source.match(r2);\n if (m2) return m2[1];\n return null;\n}\n\n/** Check if a meta tag exists with a dynamic value ({variable}) */\nfunction hasMetaTagDynamic(source: string, attr: \"name\" | \"property\", name: string): boolean {\n const r1 = new RegExp(`<meta\\\\s[^>]*${attr}=[\"']${name}[\"'][^>]*content=\\\\{`);\n const r2 = new RegExp(`<meta\\\\s[^>]*content=\\\\{[^}]*\\\\}[^>]*${attr}=[\"']${name}[\"']`);\n return r1.test(source) || r2.test(source);\n}\n\n/** Extract metadata from .astro files (frontmatter + <head> content) */\nfunction extractAstroMeta(source: string): ResolvedMetadata {\n const meta = createEmptyMetadata();\n\n // Extract from <title> tag\n const titleTagMatch = source.match(/<title[^>]*>([^<{]+)<\\/title>/);\n if (titleTagMatch) meta.title = titleTagMatch[1].trim();\n\n // Extract from <meta> tags (handles both attribute orders)\n meta.description = extractMetaTag(source, \"name\", \"description\");\n meta.ogTitle = extractMetaTag(source, \"property\", \"og:title\");\n meta.ogDescription = extractMetaTag(source, \"property\", \"og:description\");\n meta.ogImage = extractMetaTag(source, \"property\", \"og:image\");\n meta.robots = extractMetaTag(source, \"name\", \"robots\");\n\n // <link rel=\"canonical\">\n const canonicalMatch = source.match(/<link\\s[^>]*rel=[\"']canonical[\"'][^>]*href=[\"']([^\"']+)[\"']/)\n || source.match(/<link\\s[^>]*href=[\"']([^\"']+)[\"'][^>]*rel=[\"']canonical[\"']/);\n if (canonicalMatch) meta.canonical = canonicalMatch[1];\n\n // Detect dynamic title: <title>{title}</title> or <title>{Astro.props.title}</title>\n if (!meta.title) {\n const titleContent = source.match(/<title[^>]*>([\\s\\S]*?)<\\/title>/)?.[1] ?? \"\";\n if (/\\{/.test(titleContent)) meta.title = \"[detected]\";\n }\n\n // Detect dynamic meta tags → [detected]\n if (!meta.description && hasMetaTagDynamic(source, \"name\", \"description\")) meta.description = \"[detected]\";\n if (!meta.ogTitle && hasMetaTagDynamic(source, \"property\", \"og:title\")) meta.ogTitle = \"[detected]\";\n if (!meta.ogDescription && hasMetaTagDynamic(source, \"property\", \"og:description\")) meta.ogDescription = \"[detected]\";\n if (!meta.ogImage && hasMetaTagDynamic(source, \"property\", \"og:image\")) meta.ogImage = \"[detected]\";\n\n // Check for SEO component usage: <SEO title=\"...\" />, <BaseHead title=\"...\" />\n if (!meta.title) {\n const seoComponentMatch = source.match(/<(?:SEO|BaseHead|Head)\\s[^>]*title=[\"']([^\"']+)[\"']/);\n if (seoComponentMatch) meta.title = seoComponentMatch[1];\n }\n if (!meta.title) {\n // Dynamic SEO component: <SEO title={title} />\n if (/<(?:SEO|BaseHead|Head)\\s[^>]*title=\\{/.test(source)) meta.title = \"[detected]\";\n }\n if (!meta.description) {\n const seoDescMatch = source.match(/<(?:SEO|BaseHead|Head)\\s[^>]*description=[\"']([^\"']+)[\"']/);\n if (seoDescMatch) meta.description = seoDescMatch[1];\n else if (/<(?:SEO|BaseHead|Head)\\s[^>]*description=\\{/.test(source)) meta.description = \"[detected]\";\n }\n\n // JSON-LD\n if (/application\\/ld\\+json/.test(source)) {\n meta.structuredData = [{ \"@context\": \"https://schema.org\", \"@type\": \"detected\" }];\n }\n\n return meta;\n}\n\n/** Extract metadata from Markdown/MDX frontmatter */\nfunction extractMarkdownMeta(source: string): ResolvedMetadata {\n const meta = createEmptyMetadata();\n\n // Extract YAML frontmatter between ---\n const fmMatch = source.match(/^---\\s*\\n([\\s\\S]*?)\\n---/);\n if (!fmMatch) return meta;\n\n const fm = fmMatch[1];\n\n const titleMatch = fm.match(/^title\\s*:\\s*[\"']?(.+?)[\"']?\\s*$/m);\n if (titleMatch) meta.title = titleMatch[1];\n\n const descMatch = fm.match(/^description\\s*:\\s*[\"']?(.+?)[\"']?\\s*$/m);\n if (descMatch) meta.description = descMatch[1];\n\n const ogImageMatch = fm.match(/^(?:ogImage|image|og_image)\\s*:\\s*[\"']?(.+?)[\"']?\\s*$/m);\n if (ogImageMatch) meta.ogImage = ogImageMatch[1];\n\n return meta;\n}\n\nfunction createEmptyMetadata(): ResolvedMetadata {\n return {\n title: null, description: null, canonical: null,\n ogTitle: null, ogDescription: null, ogImage: null, ogType: null,\n twitterCard: null, twitterTitle: null, twitterDescription: null,\n robots: null, alternates: null, structuredData: null,\n viewport: null, favicon: null,\n };\n}\n\nfunction mergeMetadata(target: ResolvedMetadata, source: ResolvedMetadata): void {\n for (const key of Object.keys(source) as (keyof ResolvedMetadata)[]) {\n if (target[key] === null || target[key] === undefined) {\n (target as Record<string, unknown>)[key] = source[key];\n }\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join, dirname, sep } from \"node:path\";\nimport { glob } from \"glob\";\nimport type { ResolvedMetadata } from \"indxel\";\nimport type { PageInfo } from \"./scanner.js\";\n\n/**\n * Scan a SvelteKit project's src/routes/ directory for SEO metadata.\n * Looks for <svelte:head> in +page.svelte and +layout.svelte files.\n */\nexport async function scanSvelteKitPages(\n projectRoot: string,\n appDir: string,\n): Promise<PageInfo[]> {\n const appDirFull = join(projectRoot, appDir);\n\n // SvelteKit page files: +page.svelte\n const pageFiles = await glob(\"**/+page.svelte\", {\n cwd: appDirFull,\n ignore: [\"**/node_modules/**\"],\n });\n\n const pages: PageInfo[] = [];\n\n for (const file of pageFiles) {\n const fullPath = join(appDirFull, file);\n const content = await readFile(fullPath, \"utf-8\");\n const route = svelteKitFilePathToRoute(file);\n\n const page: PageInfo = {\n filePath: join(appDir, file),\n route,\n hasMetadata: false,\n hasDynamicMetadata: false,\n isClientComponent: false,\n titleIsAbsolute: false,\n extractedMetadata: createEmptyMetadata(),\n };\n\n // Check for <svelte:head> block\n const hasSvelteHead = /<svelte:head[\\s>]/.test(content);\n page.hasMetadata = hasSvelteHead;\n\n // Only mark as dynamic if the <svelte:head> actually uses `data.` from the load function.\n // A page can have a load function for list data while having static <svelte:head>.\n if (hasSvelteHead) {\n page.extractedMetadata = extractSvelteHeadMeta(content);\n\n // Check if the head block references reactive data (data.xxx, $page, etc.)\n const headBlock = content.match(/<svelte:head[\\s>]([\\s\\S]*?)<\\/svelte:head>/)?.[1] ?? \"\";\n const headUsesData = /\\bdata\\./.test(headBlock) || /\\$page/.test(headBlock) || /\\{#each/.test(headBlock);\n page.hasDynamicMetadata = headUsesData;\n }\n\n // JSON-LD detection\n if (/application\\/ld\\+json/.test(content)) {\n page.extractedMetadata.structuredData = [{ \"@context\": \"https://schema.org\", \"@type\": \"detected\" }];\n }\n\n pages.push(page);\n }\n\n // Check +layout.svelte files for shared <svelte:head>\n const layoutFiles = await glob(\"**/+layout.svelte\", {\n cwd: appDirFull,\n ignore: [\"**/node_modules/**\"],\n });\n\n // Sort layouts by depth descending (deeper layouts first)\n const sortedLayouts = layoutFiles.sort((a, b) => {\n const depthA = a.split(sep).length;\n const depthB = b.split(sep).length;\n return depthB - depthA;\n });\n\n for (const file of sortedLayouts) {\n try {\n const content = await readFile(join(appDirFull, file), \"utf-8\");\n if (!/<svelte:head[\\s>]/.test(content)) continue;\n\n const layoutMeta = extractSvelteHeadMeta(content);\n const layoutRoute = svelteKitFilePathToRoute(file).replace(/\\/\\+layout$/, \"\") || \"/\";\n\n for (const page of pages) {\n if (page.route.startsWith(layoutRoute) || layoutRoute === \"/\") {\n mergeMetadata(page.extractedMetadata, layoutMeta);\n if (!page.hasMetadata) page.hasMetadata = true;\n }\n }\n } catch {\n // Skip unreadable layouts\n }\n }\n\n return pages.sort((a, b) => a.route.localeCompare(b.route));\n}\n\n/** Convert SvelteKit file path to route (e.g., \"blog/[slug]/+page.svelte\" → \"/blog/[slug]\") */\nfunction svelteKitFilePathToRoute(filePath: string): string {\n const dir = dirname(filePath);\n if (dir === \".\") return \"/\";\n let route = \"/\" + dir.split(sep).join(\"/\");\n // Remove route groups like (marketing)\n route = route.replace(/\\/\\([^)]+\\)/g, \"\") || \"/\";\n return route;\n}\n\n/** Extract metadata from <svelte:head> block */\nfunction extractSvelteHeadMeta(source: string): ResolvedMetadata {\n const meta = createEmptyMetadata();\n\n // Extract <svelte:head>...</svelte:head> block\n const headMatch = source.match(/<svelte:head[\\s>]([\\s\\S]*?)<\\/svelte:head>/);\n if (!headMatch) return meta;\n\n const head = headMatch[1];\n\n // <title>\n const titleMatch = head.match(/<title[^>]*>([^<{]+)<\\/title>/);\n if (titleMatch) meta.title = titleMatch[1].trim();\n\n // Detect dynamic title: <title>{data.title}</title>\n if (!meta.title && /<title[^>]*>\\{/.test(head)) meta.title = \"[detected]\";\n\n // <meta> tags — handle both attribute orders (name/property before or after content)\n meta.description = extractMetaTag(head, \"name\", \"description\");\n meta.ogTitle = extractMetaTag(head, \"property\", \"og:title\");\n meta.ogDescription = extractMetaTag(head, \"property\", \"og:description\");\n meta.ogImage = extractMetaTag(head, \"property\", \"og:image\");\n meta.robots = extractMetaTag(head, \"name\", \"robots\");\n\n const canonicalMatch = head.match(/<link\\s[^>]*rel=[\"']canonical[\"'][^>]*href=[\"']([^\"']+)[\"']/)\n || head.match(/<link\\s[^>]*href=[\"']([^\"']+)[\"'][^>]*rel=[\"']canonical[\"']/);\n if (canonicalMatch) meta.canonical = canonicalMatch[1];\n\n // Detect dynamic values ({variable}) for all SEO-relevant meta tags\n if (!meta.description && hasDynamicMeta(head, \"name\", \"description\")) meta.description = \"[detected]\";\n if (!meta.ogTitle && hasDynamicMeta(head, \"property\", \"og:title\")) meta.ogTitle = \"[detected]\";\n if (!meta.ogDescription && hasDynamicMeta(head, \"property\", \"og:description\")) meta.ogDescription = \"[detected]\";\n if (!meta.ogImage && hasDynamicMeta(head, \"property\", \"og:image\")) meta.ogImage = \"[detected]\";\n if (!meta.robots && hasDynamicMeta(head, \"name\", \"robots\")) meta.robots = \"[detected]\";\n\n // JSON-LD\n if (/application\\/ld\\+json/.test(head)) {\n meta.structuredData = [{ \"@context\": \"https://schema.org\", \"@type\": \"detected\" }];\n }\n\n return meta;\n}\n\n/** Extract a meta tag value, handling both attribute orders */\nfunction extractMetaTag(html: string, attr: \"name\" | \"property\", name: string): string | null {\n const r1 = new RegExp(`<meta\\\\s[^>]*${attr}=[\"']${name}[\"'][^>]*content=[\"']([^\"']+)[\"']`);\n const m1 = html.match(r1);\n if (m1) return m1[1];\n const r2 = new RegExp(`<meta\\\\s[^>]*content=[\"']([^\"']+)[\"'][^>]*${attr}=[\"']${name}[\"']`);\n const m2 = html.match(r2);\n if (m2) return m2[1];\n return null;\n}\n\n/** Check if a meta tag has a dynamic {value} for the given attr/name combo */\nfunction hasDynamicMeta(html: string, attr: \"name\" | \"property\", name: string): boolean {\n // content={var} with name/property before or after\n const r1 = new RegExp(`<meta\\\\s[^>]*${attr}=[\"']${name}[\"'][^>]*content=\\\\{`);\n const r2 = new RegExp(`<meta\\\\s[^>]*content=\\\\{[^}]*\\\\}[^>]*${attr}=[\"']${name}[\"']`);\n return r1.test(html) || r2.test(html);\n}\n\nfunction createEmptyMetadata(): ResolvedMetadata {\n return {\n title: null, description: null, canonical: null,\n ogTitle: null, ogDescription: null, ogImage: null, ogType: null,\n twitterCard: null, twitterTitle: null, twitterDescription: null,\n robots: null, alternates: null, structuredData: null,\n viewport: null, favicon: null,\n };\n}\n\nfunction mergeMetadata(target: ResolvedMetadata, source: ResolvedMetadata): void {\n for (const key of Object.keys(source) as (keyof ResolvedMetadata)[]) {\n if (target[key] === null || target[key] === undefined) {\n (target as Record<string, unknown>)[key] = source[key];\n }\n }\n}\n","import type { Framework } from \"./detect.js\";\nimport type { PageInfo } from \"./scanner.js\";\nimport { scanPages } from \"./scanner.js\";\nimport { scanNuxtPages } from \"./scanner-nuxt.js\";\nimport { scanRemixPages } from \"./scanner-remix.js\";\nimport { scanAstroPages } from \"./scanner-astro.js\";\nimport { scanSvelteKitPages } from \"./scanner-sveltekit.js\";\n\n/**\n * Dispatch to the correct scanner based on detected framework.\n * All scanners return the same PageInfo[] interface.\n */\nexport async function scanProject(\n framework: Framework,\n projectRoot: string,\n appDir: string,\n): Promise<PageInfo[]> {\n switch (framework) {\n case \"nextjs\":\n return scanPages(projectRoot, appDir);\n case \"nuxt\":\n return scanNuxtPages(projectRoot, appDir);\n case \"remix\":\n return scanRemixPages(projectRoot, appDir);\n case \"astro\":\n return scanAstroPages(projectRoot, appDir);\n case \"sveltekit\":\n return scanSvelteKitPages(projectRoot, appDir);\n default:\n return [];\n }\n}\n","import chalk from \"chalk\";\nimport type { ValidationResult } from \"indxel\";\nimport type { PageInfo } from \"./scanner.js\";\n\nexport interface CheckResult {\n page: PageInfo;\n validation: ValidationResult;\n}\n\nexport interface CheckSummary {\n results: CheckResult[];\n totalPages: number;\n passedPages: number;\n averageScore: number;\n grade: string;\n /** Errors from critical-severity rules (blocks CI) */\n criticalErrors: number;\n /** Errors from optional-severity rules (score only) */\n optionalErrors: number;\n /** Pages with generateMetadata() skipped from static analysis */\n skippedDynamic: number;\n}\n\n/** Format a single page check result for terminal output */\nexport function formatPageResult(result: CheckResult): string {\n const { page, validation } = result;\n const lines: string[] = [];\n\n const scoreColor = getScoreColor(validation.score);\n const icon = validation.errors.length > 0 ? chalk.red(\"x\") : chalk.green(\"✓\");\n\n lines.push(\n ` ${icon} ${chalk.bold(page.route)} ${scoreColor(`${validation.score}/100`)}`,\n );\n\n // Show errors\n for (const error of validation.errors) {\n lines.push(` ${chalk.red(\"x\")} ${error.message ?? error.name}`);\n }\n\n // Show warnings (only if there are also errors, to reduce noise)\n if (validation.errors.length > 0) {\n for (const warning of validation.warnings) {\n lines.push(` ${chalk.yellow(\"!\")} ${warning.message ?? warning.name}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/** Format the complete check summary for terminal output */\nexport function formatSummary(summary: CheckSummary): string {\n const lines: string[] = [];\n const { totalPages, passedPages, averageScore, criticalErrors } = summary;\n\n lines.push(\"\");\n lines.push(chalk.dim(\" ─────────────────────────────────────\"));\n lines.push(\"\");\n\n // Overall score\n const scoreColor = getScoreColor(averageScore);\n lines.push(\n ` Score: ${scoreColor(chalk.bold(`${averageScore}/100`))} (${summary.grade})`,\n );\n\n // Pages summary\n const pagesColor = passedPages === totalPages ? chalk.green : chalk.yellow;\n lines.push(\n ` Pages: ${pagesColor(`${passedPages}/${totalPages}`)} pass SEO validation`,\n );\n\n // Error count\n if (criticalErrors > 0) {\n lines.push(\"\");\n lines.push(\n chalk.red(` ${criticalErrors} critical issue${criticalErrors > 1 ? \"s\" : \"\"}. Fix before deploying.`),\n );\n if (summary.optionalErrors > 0) {\n lines.push(\n chalk.yellow(` ${summary.optionalErrors} optional issue${summary.optionalErrors > 1 ? \"s\" : \"\"} (won't block CI).`),\n );\n }\n } else if (summary.optionalErrors > 0) {\n lines.push(\"\");\n lines.push(chalk.yellow(` ${summary.optionalErrors} optional issue${summary.optionalErrors > 1 ? \"s\" : \"\"} (won't block CI).`));\n } else {\n lines.push(\"\");\n lines.push(chalk.green(\" All pages pass. Ship it.\"));\n }\n\n // Dynamic pages hint\n if (summary.skippedDynamic > 0) {\n lines.push(\"\");\n lines.push(\n chalk.cyan(\n ` ${summary.skippedDynamic} dynamic page${summary.skippedDynamic > 1 ? \"s\" : \"\"} skipped (generateMetadata).`,\n ),\n );\n lines.push(chalk.dim(\" Run `indxel crawl <url>` for accurate scores on dynamic pages.\"));\n }\n\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n\n/** Format results for --json output */\nexport function formatJSON(summary: CheckSummary): string {\n return JSON.stringify(\n {\n score: summary.averageScore,\n grade: summary.grade,\n totalPages: summary.totalPages,\n passedPages: summary.passedPages,\n criticalErrors: summary.criticalErrors,\n optionalErrors: summary.optionalErrors,\n skippedDynamic: summary.skippedDynamic,\n pages: summary.results.map((r) => ({\n route: r.page.route,\n file: r.page.filePath,\n score: r.validation.score,\n grade: r.validation.grade,\n errors: r.validation.errors.map((e) => ({\n id: e.id,\n message: e.message,\n })),\n warnings: r.validation.warnings.map((w) => ({\n id: w.id,\n message: w.message,\n })),\n })),\n },\n null,\n 2,\n );\n}\n\n/** Format a diff between two check runs */\nexport function formatDiff(\n current: CheckSummary,\n previous: CheckSummary,\n): string {\n const lines: string[] = [];\n\n lines.push(\"\");\n lines.push(chalk.bold(\" SEO Diff:\"));\n lines.push(\"\");\n\n const scoreDelta = current.averageScore - previous.averageScore;\n const scoreArrow = scoreDelta > 0 ? chalk.green(`+${scoreDelta}`) : scoreDelta < 0 ? chalk.red(`${scoreDelta}`) : chalk.dim(\"0\");\n lines.push(\n ` Score: ${previous.averageScore} -> ${current.averageScore} (${scoreArrow})`,\n );\n lines.push(\"\");\n\n // Build route maps\n const prevMap = new Map(previous.results.map((r) => [r.page.route, r]));\n const currMap = new Map(current.results.map((r) => [r.page.route, r]));\n\n // Regressions\n const regressions: string[] = [];\n for (const [route, curr] of currMap) {\n const prev = prevMap.get(route);\n if (!prev) continue;\n if (curr.validation.score < prev.validation.score) {\n regressions.push(\n ` ${chalk.red(\"-\")} ${route} ${prev.validation.score} -> ${curr.validation.score}`,\n );\n }\n }\n\n // Improvements\n const improvements: string[] = [];\n for (const [route, curr] of currMap) {\n const prev = prevMap.get(route);\n if (!prev) continue;\n if (curr.validation.score > prev.validation.score) {\n improvements.push(\n ` ${chalk.green(\"+\")} ${route} ${prev.validation.score} -> ${curr.validation.score}`,\n );\n }\n }\n\n // New pages\n const newPages: string[] = [];\n for (const route of currMap.keys()) {\n if (!prevMap.has(route)) {\n newPages.push(` ${chalk.blue(\"+\")} ${route} ${chalk.dim(\"[new]\")}`);\n }\n }\n\n // Removed pages\n const removed: string[] = [];\n for (const route of prevMap.keys()) {\n if (!currMap.has(route)) {\n removed.push(` ${chalk.dim(\"-\")} ${route} ${chalk.dim(\"[removed]\")}`);\n }\n }\n\n if (regressions.length > 0) {\n lines.push(chalk.red(` REGRESSIONS (${regressions.length}):`));\n lines.push(...regressions);\n lines.push(\"\");\n }\n\n if (improvements.length > 0) {\n lines.push(chalk.green(` IMPROVEMENTS (${improvements.length}):`));\n lines.push(...improvements);\n lines.push(\"\");\n }\n\n if (newPages.length > 0) {\n lines.push(chalk.blue(` NEW PAGES (${newPages.length}):`));\n lines.push(...newPages);\n lines.push(\"\");\n }\n\n if (removed.length > 0) {\n lines.push(chalk.dim(` REMOVED (${removed.length}):`));\n lines.push(...removed);\n lines.push(\"\");\n }\n\n if (regressions.length === 0 && improvements.length === 0 && newPages.length === 0 && removed.length === 0) {\n lines.push(chalk.dim(\" No changes detected.\"));\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\");\n}\n\n/** Format a dynamic page that was skipped from static analysis */\nexport function formatSkippedPage(page: import(\"./scanner.js\").PageInfo): string {\n return ` ${chalk.cyan(\"~\")} ${chalk.bold(page.route)} ${chalk.dim(\"skipped — generateMetadata()\")}`;\n}\n\n/** Color a score value based on its range */\nfunction getScoreColor(score: number): (text: string) => string {\n if (score >= 90) return chalk.green;\n if (score >= 70) return chalk.yellow;\n return chalk.red;\n}\n\n/** Compute summary from results */\nexport function computeSummary(results: CheckResult[], skippedDynamic = 0): CheckSummary {\n const totalPages = results.length + skippedDynamic;\n const passedPages = results.filter((r) => r.validation.errors.length === 0).length;\n const averageScore =\n results.length > 0\n ? Math.round(results.reduce((sum, r) => sum + r.validation.score, 0) / results.length)\n : 0;\n\n let criticalErrors = 0;\n let optionalErrors = 0;\n for (const r of results) {\n for (const e of r.validation.errors) {\n if (e.severity === \"critical\") criticalErrors++;\n else optionalErrors++;\n }\n }\n\n let grade: string;\n if (averageScore >= 90) grade = \"A\";\n else if (averageScore >= 80) grade = \"B\";\n else if (averageScore >= 70) grade = \"C\";\n else if (averageScore >= 60) grade = \"D\";\n else grade = \"F\";\n\n return { results, totalPages, passedPages, averageScore, grade, criticalErrors, optionalErrors, skippedDynamic };\n}\n","import chalk from \"chalk\";\nimport type { CheckResult } from \"./formatter.js\";\n\n/**\n * Generate suggested metadata code snippets for pages with errors.\n * Returns an array of formatted strings ready for terminal output.\n */\nexport function generateFixSuggestions(\n results: CheckResult[],\n baseUrl?: string,\n): string[] {\n const output: string[] = [];\n const siteUrl = baseUrl ?? \"https://yoursite.com\";\n\n for (const { page, validation } of results) {\n if (validation.errors.length === 0 && validation.warnings.length === 0) continue;\n\n const errorIds = new Set(validation.errors.map((e) => e.id));\n const warnIds = new Set(validation.warnings.map((w) => w.id));\n const allIds = new Set([...errorIds, ...warnIds]);\n\n // Build a metadata object suggestion based on what's missing\n const meta: Record<string, unknown> = {};\n const extras: string[] = [];\n\n // Title\n if (allIds.has(\"title-present\")) {\n const suggestion = routeToTitle(page.route);\n meta.title = { absolute: suggestion };\n } else if (allIds.has(\"title-length\")) {\n const current = page.extractedMetadata.title ?? \"\";\n const len = current.length;\n if (len < 50) {\n extras.push(` ${chalk.dim(\"// Title is \" + len + \" chars — expand to 50-60\")}`);\n } else if (len > 60) {\n extras.push(` ${chalk.dim(\"// Title is \" + len + \" chars — shorten to 50-60\")}`);\n }\n }\n\n // Description\n if (allIds.has(\"description-present\")) {\n meta.description = routeToDescription(page.route);\n } else if (allIds.has(\"description-length\")) {\n const current = page.extractedMetadata.description ?? \"\";\n const len = current.length;\n if (len < 120) {\n extras.push(` ${chalk.dim(\"// Description is \" + len + \" chars — expand to 120-160\")}`);\n } else if (len > 160) {\n extras.push(` ${chalk.dim(\"// Description is \" + len + \" chars — shorten to 120-160\")}`);\n }\n }\n\n // Canonical\n if (allIds.has(\"canonical-url\")) {\n const canonical = `${siteUrl}${page.route === \"/\" ? \"\" : page.route}`;\n meta.alternates = { canonical };\n }\n\n // OG Image\n if (allIds.has(\"og-image\")) {\n meta.openGraph = { images: [`${siteUrl}/og-image.png`] };\n }\n\n // Structured data\n if (allIds.has(\"structured-data-present\")) {\n extras.push(` ${chalk.dim(\"// Add JSON-LD structured data (WebPage, Article, FAQ...)\")}`);\n extras.push(` ${chalk.dim(\"// See: https://developers.google.com/search/docs/appearance/structured-data\")}`);\n }\n\n // Twitter\n if (allIds.has(\"twitter-card\")) {\n meta.twitter = { card: \"summary_large_image\" };\n }\n\n // Skip pages with no actionable suggestions\n if (Object.keys(meta).length === 0 && extras.length === 0) continue;\n\n output.push(chalk.bold(` ${chalk.cyan(page.filePath)}`));\n\n if (Object.keys(meta).length > 0) {\n const code = formatMetadataObject(meta);\n output.push(` ${chalk.dim(\"Add/update in your page file:\")}`);\n output.push(\"\");\n for (const line of code.split(\"\\n\")) {\n output.push(` ${chalk.yellow(line)}`);\n }\n }\n\n for (const extra of extras) {\n output.push(extra);\n }\n\n output.push(\"\");\n }\n\n return output;\n}\n\n/** Generate a reasonable title suggestion from a route */\nfunction routeToTitle(route: string): string {\n if (route === \"/\") return \"Your Site — A brief description of what you do\";\n const segments = route.split(\"/\").filter(Boolean);\n const last = segments[segments.length - 1];\n const name = last\n .replace(/\\[.*?\\]/g, \"\")\n .replace(/-/g, \" \")\n .replace(/\\b\\w/g, (c) => c.toUpperCase())\n .trim();\n return `${name || \"Page\"} — Your Site`;\n}\n\n/** Generate a reasonable description suggestion from a route */\nfunction routeToDescription(route: string): string {\n if (route === \"/\") {\n return \"A clear, compelling description of your site in 120-160 characters. Include your main value proposition and a call to action.\";\n }\n const segments = route.split(\"/\").filter(Boolean);\n const last = segments[segments.length - 1];\n const name = last\n .replace(/\\[.*?\\]/g, \"\")\n .replace(/-/g, \" \")\n .trim();\n return `Learn more about ${name || \"this page\"}. Add a compelling 120-160 character description with your key value proposition here.`;\n}\n\n/** Format a metadata object as TypeScript code */\nfunction formatMetadataObject(meta: Record<string, unknown>): string {\n const lines: string[] = [\"export const metadata: Metadata = {\"];\n\n for (const [key, value] of Object.entries(meta)) {\n if (typeof value === \"string\") {\n lines.push(` ${key}: \"${value}\",`);\n } else if (typeof value === \"object\" && value !== null) {\n lines.push(` ${key}: ${JSON.stringify(value, null, 2).replace(/\\n/g, \"\\n \")},`);\n }\n }\n\n lines.push(\"};\");\n return lines.join(\"\\n\");\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport {\n crawlSite,\n fetchSitemap,\n compareSitemap,\n fetchRobots,\n checkUrlsAgainstRobots,\n verifyAssets,\n} from \"indxel\";\nimport type { CrawledPage } from \"indxel\";\nimport { resolveApiKey } from \"../store.js\";\nimport { resolveProjectUrl } from \"../config.js\";\n\nfunction scoreColor(score: number): typeof chalk {\n if (score >= 90) return chalk.green;\n if (score >= 70) return chalk.yellow;\n return chalk.red;\n}\n\nexport const crawlCommand = new Command(\"crawl\")\n .description(\"Crawl a live site, audit every page, check sitemap, robots.txt, and assets\")\n .argument(\"[url]\", \"URL to start crawling (auto-detected from seo.config if omitted)\")\n .option(\"--max-pages <n>\", \"Maximum pages to crawl\", \"500\")\n .option(\"--max-depth <n>\", \"Maximum link depth\", \"5\")\n .option(\"--delay <ms>\", \"Delay between requests in ms\", \"200\")\n .option(\"--json\", \"Output results as JSON\", false)\n .option(\"--strict\", \"Treat warnings as errors\", false)\n .option(\"--skip-assets\", \"Skip asset verification\", false)\n .option(\"--skip-sitemap\", \"Skip sitemap check\", false)\n .option(\"--skip-robots\", \"Skip robots.txt check\", false)\n .option(\"--ignore <patterns>\", \"Comma-separated path patterns to exclude from analysis (e.g. /app/*,/admin/*)\")\n .option(\"--push\", \"Push results to Indxel dashboard\", false)\n .option(\"--api-key <key>\", \"API key for --push (or set INDXEL_API_KEY env var)\")\n .action(async (urlArg: string | undefined, opts) => {\n const jsonOutput = opts.json;\n const maxDepth = parseInt(opts.maxDepth, 10);\n const delay = parseInt(opts.delay, 10);\n\n const maxPages = parseInt(opts.maxPages, 10);\n\n // Resolve URL: argument > seo.config > .indxelrc > package.json\n let url = urlArg;\n if (!url) {\n const detected = await resolveProjectUrl(process.cwd());\n if (detected) {\n url = detected;\n if (!jsonOutput) {\n console.log(chalk.dim(` Using URL from project config: ${url}`));\n }\n } else {\n console.error(chalk.red(\" No URL provided and none found in seo.config or .indxelrc.json.\"));\n console.error(chalk.dim(\" Usage: npx indxel crawl [url]\"));\n process.exit(1);\n }\n }\n\n // Ensure URL has protocol\n if (!url.startsWith(\"http://\") && !url.startsWith(\"https://\")) {\n url = `https://${url}`;\n }\n\n if (!jsonOutput) {\n console.log(\"\");\n console.log(chalk.bold(` indxel crawl`) + chalk.dim(` — ${url}`));\n console.log(\"\");\n }\n\n // 1. Robots.txt\n let robotsResult = null;\n if (!opts.skipRobots) {\n const robotsSpinner = jsonOutput ? null : ora(\"Checking robots.txt...\").start();\n robotsResult = await fetchRobots(url);\n\n if (!jsonOutput) {\n if (robotsResult.found) {\n robotsSpinner!.succeed(\"robots.txt found\");\n for (const w of robotsResult.warnings) {\n console.log(chalk.yellow(` ⚠ ${w}`));\n }\n if (robotsResult.sitemapUrls.length > 0) {\n console.log(chalk.dim(` Sitemap references: ${robotsResult.sitemapUrls.join(\", \")}`));\n }\n } else {\n robotsSpinner!.warn(\"robots.txt not found\");\n for (const e of robotsResult.errors) {\n console.log(chalk.dim(` ${e}`));\n }\n }\n console.log(\"\");\n }\n }\n\n // 2. Crawl\n const crawlSpinner = jsonOutput ? null : ora(\"Crawling...\").start();\n let crawledCount = 0;\n\n // Parse ignore patterns\n const ignorePatterns: string[] = opts.ignore\n ? opts.ignore.split(\",\").map((p: string) => p.trim()).filter(Boolean)\n : [];\n\n const crawlResult = await crawlSite(url, {\n maxPages,\n maxDepth,\n delay,\n strict: opts.strict,\n ignorePatterns,\n onPageCrawled: (page: CrawledPage) => {\n crawledCount++;\n if (crawlSpinner) {\n crawlSpinner.text = `Crawling... ${crawledCount} pages (current: ${page.url})`;\n }\n },\n });\n\n if (!jsonOutput) {\n crawlSpinner!.succeed(`Crawled ${crawlResult.totalPages} pages in ${(crawlResult.durationMs / 1000).toFixed(1)}s`);\n console.log(\"\");\n\n // Page results\n for (const page of crawlResult.pages) {\n if (page.error) {\n console.log(chalk.red(` ✗ ${page.url}`) + chalk.dim(` — ${page.error}`));\n continue;\n }\n\n const pageColor = scoreColor(page.validation.score);\n const icon =\n page.validation.errors.length > 0 ? chalk.red(\"✗\") : chalk.green(\"✓\");\n\n console.log(\n ` ${icon} ${page.url} ${pageColor(`${page.validation.score}/100`)}`,\n );\n\n for (const error of page.validation.errors) {\n console.log(chalk.red(` ✗ ${error.message ?? error.description}`));\n }\n for (const warning of page.validation.warnings) {\n console.log(chalk.yellow(` ⚠ ${warning.message ?? warning.description}`));\n }\n }\n\n console.log(\"\");\n }\n\n // 3. Sitemap check\n let sitemapComparison = null;\n if (!opts.skipSitemap) {\n const sitemapSpinner = jsonOutput ? null : ora(\"Checking sitemap.xml...\").start();\n const sitemapResult = await fetchSitemap(url);\n\n if (!jsonOutput) {\n if (sitemapResult.found) {\n sitemapSpinner!.succeed(`sitemap.xml found — ${sitemapResult.urls.length} URLs`);\n\n // Compare with crawled pages\n const crawledUrls = crawlResult.pages\n .filter((p) => !p.error)\n .map((p) => p.url);\n sitemapComparison = compareSitemap(\n sitemapResult.urls.map((u) => u.loc),\n crawledUrls,\n );\n\n if (sitemapComparison.inCrawlOnly.length > 0) {\n console.log(chalk.yellow(` ⚠ ${sitemapComparison.inCrawlOnly.length} crawled pages missing from sitemap:`));\n for (const u of sitemapComparison.inCrawlOnly.slice(0, 10)) {\n console.log(chalk.dim(` - ${u}`));\n }\n }\n if (sitemapComparison.inSitemapOnly.length > 0) {\n const hitLimit = crawlResult.totalPages >= maxPages;\n const label = hitLimit\n ? `${sitemapComparison.inSitemapOnly.length} sitemap URLs not crawled (limit: ${maxPages} — use --max-pages to increase)`\n : `${sitemapComparison.inSitemapOnly.length} sitemap URLs not reachable`;\n console.log(chalk.yellow(` ⚠ ${label}:`));\n for (const u of sitemapComparison.inSitemapOnly.slice(0, 10)) {\n console.log(chalk.dim(` - ${u}`));\n }\n }\n if (sitemapComparison.issues.length === 0) {\n console.log(chalk.green(` ✓ Sitemap matches crawled pages`));\n }\n } else {\n sitemapSpinner!.warn(\"sitemap.xml not found\");\n for (const e of sitemapResult.errors) {\n console.log(chalk.dim(` ${e}`));\n }\n }\n console.log(\"\");\n }\n }\n\n // 4. Robots.txt URL check\n let robotsBlockedPages = null;\n if (robotsResult?.found && robotsResult.directives.length > 0) {\n const crawledUrls = crawlResult.pages.filter((p) => !p.error).map((p) => p.url);\n robotsBlockedPages = checkUrlsAgainstRobots(\n robotsResult.directives,\n crawledUrls,\n );\n const blocked = robotsBlockedPages.filter((c) => c.blocked);\n\n if (!jsonOutput && blocked.length > 0) {\n console.log(chalk.yellow(` ⚠ ${blocked.length} crawled pages are blocked by robots.txt:`));\n for (const b of blocked) {\n console.log(chalk.dim(` - ${b.path} (${b.blockedBy})`));\n }\n console.log(\"\");\n }\n }\n\n // 5. Asset verification\n let assetResult = null;\n if (!opts.skipAssets) {\n const assetSpinner = jsonOutput ? null : ora(\"Verifying assets (og:image, favicon, ...)...\").start();\n\n const pagesForAssetCheck = crawlResult.pages\n .filter((p) => !p.error)\n .map((p) => ({ url: p.url, metadata: p.metadata }));\n assetResult = await verifyAssets(pagesForAssetCheck);\n\n if (!jsonOutput) {\n assetSpinner!.succeed(`Verified ${assetResult.totalChecked} assets`);\n\n const brokenAssets = assetResult.checks.filter((c) => !c.ok);\n const warningAssets = assetResult.checks.filter((c) => c.warning);\n\n for (const asset of brokenAssets) {\n console.log(\n chalk.red(` ✗ ${asset.type}`) +\n chalk.dim(` ${asset.url}`) +\n chalk.red(` — ${asset.error ?? `HTTP ${asset.status}`}`),\n );\n }\n for (const asset of warningAssets) {\n console.log(\n chalk.yellow(` ⚠ ${asset.type}`) +\n chalk.dim(` ${asset.url}`) +\n chalk.yellow(` — ${asset.warning}`),\n );\n }\n if (brokenAssets.length === 0 && warningAssets.length === 0) {\n console.log(chalk.green(` ✓ All assets respond correctly`));\n }\n console.log(\"\");\n }\n }\n\n // 6. Cross-page analysis\n if (!jsonOutput) {\n const a = crawlResult.analysis;\n\n // Duplicate titles\n if (a.duplicateTitles.length > 0) {\n console.log(chalk.bold(\"- Duplicate titles\"));\n for (const dup of a.duplicateTitles.slice(0, 5)) {\n console.log(chalk.red(` ✗ \"${dup.title.length > 60 ? dup.title.slice(0, 57) + \"...\" : dup.title}\"`) + chalk.dim(` (${dup.urls.length} pages)`));\n for (const u of dup.urls.slice(0, 3)) console.log(chalk.dim(` ${u}`));\n if (dup.urls.length > 3) console.log(chalk.dim(` ...and ${dup.urls.length - 3} more`));\n }\n if (a.duplicateTitles.length > 5) console.log(chalk.dim(` ...and ${a.duplicateTitles.length - 5} more groups`));\n console.log(\"\");\n }\n\n // Duplicate descriptions\n if (a.duplicateDescriptions.length > 0) {\n console.log(chalk.bold(\"- Duplicate descriptions\"));\n for (const dup of a.duplicateDescriptions.slice(0, 5)) {\n const desc = dup.description.length > 60 ? dup.description.slice(0, 57) + \"...\" : dup.description;\n console.log(chalk.red(` ✗ \"${desc}\"`) + chalk.dim(` (${dup.urls.length} pages)`));\n for (const u of dup.urls.slice(0, 3)) console.log(chalk.dim(` ${u}`));\n if (dup.urls.length > 3) console.log(chalk.dim(` ...and ${dup.urls.length - 3} more`));\n }\n if (a.duplicateDescriptions.length > 5) console.log(chalk.dim(` ...and ${a.duplicateDescriptions.length - 5} more groups`));\n console.log(\"\");\n }\n\n // H1 issues\n if (a.h1Issues.length > 0) {\n const missing = a.h1Issues.filter(h => h.issue === \"missing\");\n const multiple = a.h1Issues.filter(h => h.issue === \"multiple\");\n console.log(chalk.bold(\"- H1 heading issues\"));\n if (missing.length > 0) {\n console.log(chalk.red(` ✗ ${missing.length} pages missing H1`));\n for (const h of missing.slice(0, 5)) console.log(chalk.dim(` ${h.url}`));\n if (missing.length > 5) console.log(chalk.dim(` ...and ${missing.length - 5} more`));\n }\n if (multiple.length > 0) {\n console.log(chalk.yellow(` ⚠ ${multiple.length} pages with multiple H1s`));\n for (const h of multiple.slice(0, 5)) console.log(chalk.dim(` ${h.url} (${h.count} H1s)`));\n if (multiple.length > 5) console.log(chalk.dim(` ...and ${multiple.length - 5} more`));\n }\n console.log(\"\");\n }\n\n // Broken internal links\n if (a.brokenInternalLinks.length > 0) {\n console.log(chalk.bold(\"- Broken internal links\"));\n for (const bl of a.brokenInternalLinks.slice(0, 10)) {\n console.log(chalk.red(` ✗ ${bl.to}`) + chalk.dim(` ← linked from ${bl.from} (${bl.status})`));\n }\n if (a.brokenInternalLinks.length > 10) console.log(chalk.dim(` ...and ${a.brokenInternalLinks.length - 10} more`));\n console.log(\"\");\n }\n\n // Broken external links\n if (a.brokenExternalLinks.length > 0) {\n console.log(chalk.bold(\"- Broken external links\"));\n for (const bl of a.brokenExternalLinks.slice(0, 10)) {\n console.log(chalk.red(` ✗ ${bl.to}`) + chalk.dim(` ← linked from ${bl.from} (${bl.status})`));\n }\n if (a.brokenExternalLinks.length > 10) console.log(chalk.dim(` ...and ${a.brokenExternalLinks.length - 10} more`));\n console.log(\"\");\n }\n\n // Redirects\n if (a.redirects.length > 0) {\n console.log(chalk.bold(\"- Redirect chains\"));\n for (const r of a.redirects.slice(0, 10)) {\n console.log(chalk.yellow(` ⚠ ${r.url}`));\n for (const step of r.chain) console.log(chalk.dim(` ${step}`));\n }\n if (a.redirects.length > 10) console.log(chalk.dim(` ...and ${a.redirects.length - 10} more`));\n console.log(\"\");\n }\n\n // Thin content\n if (a.thinContentPages.length > 0) {\n const realThin = a.thinContentPages.filter(tc => !tc.isAppPage);\n const appThin = a.thinContentPages.filter(tc => tc.isAppPage);\n\n if (realThin.length > 0) {\n console.log(chalk.bold(\"- Thin content\") + chalk.dim(\" (< 200 words)\"));\n for (const tc of realThin.slice(0, 10)) {\n console.log(chalk.yellow(` ⚠ ${tc.url}`) + chalk.dim(` — ${tc.wordCount} words`));\n }\n if (realThin.length > 10) console.log(chalk.dim(` ...and ${realThin.length - 10} more`));\n console.log(\"\");\n }\n if (appThin.length > 0) {\n console.log(chalk.bold(\"- App/wizard pages\") + chalk.dim(\" (client-rendered, low word count expected)\"));\n for (const tc of appThin.slice(0, 5)) {\n console.log(chalk.dim(` ℹ ${tc.url} — ${tc.wordCount} words`));\n }\n if (appThin.length > 5) console.log(chalk.dim(` ...and ${appThin.length - 5} more`));\n console.log(\"\");\n }\n }\n\n // Orphan pages\n if (a.orphanPages.length > 0) {\n console.log(chalk.bold(\"- Orphan pages\") + chalk.dim(\" (0 internal links pointing to them)\"));\n for (const o of a.orphanPages.slice(0, 10)) console.log(chalk.yellow(` ⚠ ${o}`));\n if (a.orphanPages.length > 10) console.log(chalk.dim(` ...and ${a.orphanPages.length - 10} more`));\n console.log(\"\");\n }\n\n // Slowest pages\n if (a.slowestPages.length > 0 && a.slowestPages[0].responseTimeMs > 1000) {\n console.log(chalk.bold(\"- Slowest pages\"));\n for (const sp of a.slowestPages.filter(p => p.responseTimeMs > 1000).slice(0, 5)) {\n const color = sp.responseTimeMs > 3000 ? chalk.red : chalk.yellow;\n console.log(color(` ⚠ ${sp.url}`) + chalk.dim(` — ${(sp.responseTimeMs / 1000).toFixed(1)}s`));\n }\n console.log(\"\");\n }\n\n // Structured data summary\n if (a.structuredDataSummary.length > 0) {\n console.log(chalk.bold(\"- Structured data (JSON-LD)\"));\n for (const sd of a.structuredDataSummary) {\n console.log(chalk.green(` ✓ ${sd.type}`) + chalk.dim(` — ${sd.count} page${sd.count > 1 ? \"s\" : \"\"}`));\n }\n const pagesWithSD = crawlResult.pages.filter(p => !p.error && p.structuredDataTypes.length > 0).length;\n const pagesWithout = crawlResult.pages.filter(p => !p.error).length - pagesWithSD;\n if (pagesWithout > 0) {\n console.log(chalk.yellow(` ⚠ ${pagesWithout} pages without any structured data`));\n }\n console.log(\"\");\n } else {\n console.log(chalk.bold(\"- Structured data (JSON-LD)\"));\n console.log(chalk.red(` ✗ No structured data found on any page`));\n console.log(\"\");\n }\n\n // Image alt text issues\n if (a.imageAltIssues.length > 0) {\n console.log(chalk.bold(\"- Image alt text\"));\n for (const img of a.imageAltIssues.slice(0, 10)) {\n const color = img.missingAlt / img.total >= 0.5 ? chalk.red : chalk.yellow;\n const icon = img.missingAlt / img.total >= 0.5 ? \"✗\" : \"⚠\";\n console.log(color(` ${icon} ${img.url}`) + chalk.dim(` — ${img.missingAlt}/${img.total} images missing alt`));\n }\n if (a.imageAltIssues.length > 10) console.log(chalk.dim(` ...and ${a.imageAltIssues.length - 10} more`));\n console.log(\"\");\n }\n\n // Broken images\n if (a.brokenImages.length > 0) {\n console.log(chalk.bold(\"- Broken images\"));\n for (const img of a.brokenImages.slice(0, 10)) {\n const src = img.src.length > 80 ? img.src.slice(0, 77) + \"...\" : img.src;\n console.log(chalk.red(` ✗ ${src}`) + chalk.dim(` (${img.status}) — on ${img.pages.length} page${img.pages.length > 1 ? \"s\" : \"\"}`));\n for (const page of img.pages.slice(0, 3)) console.log(chalk.dim(` ${page}`));\n if (img.pages.length > 3) console.log(chalk.dim(` ...and ${img.pages.length - 3} more`));\n }\n if (a.brokenImages.length > 10) console.log(chalk.dim(` ...and ${a.brokenImages.length - 10} more`));\n console.log(\"\");\n }\n }\n\n // 7. Summary\n if (jsonOutput) {\n console.log(\n JSON.stringify(\n {\n crawl: crawlResult,\n robots: robotsResult,\n sitemap: sitemapComparison,\n assets: assetResult,\n },\n null,\n 2,\n ),\n );\n } else {\n const summaryColor = scoreColor(crawlResult.averageScore);\n\n console.log(chalk.bold(\" ─── Summary ───\"));\n console.log(\"\");\n const hitLimit = crawlResult.totalPages >= maxPages;\n console.log(` Pages crawled: ${chalk.bold(String(crawlResult.totalPages))}${hitLimit ? chalk.dim(` (limit: ${maxPages} — use --max-pages to crawl more)`) : \"\"}`);\n console.log(` Average score: ${summaryColor(chalk.bold(`${crawlResult.averageScore}/100`))} (${crawlResult.grade})`);\n console.log(` Errors: ${crawlResult.totalErrors > 0 ? chalk.red(String(crawlResult.totalErrors)) : chalk.green(\"0\")}`);\n console.log(` Warnings: ${crawlResult.totalWarnings > 0 ? chalk.yellow(String(crawlResult.totalWarnings)) : chalk.green(\"0\")}`);\n if (assetResult) {\n console.log(` Broken assets: ${assetResult.totalBroken > 0 ? chalk.red(String(assetResult.totalBroken)) : chalk.green(\"0\")}`);\n }\n if (crawlResult.skippedUrls.length > 0) {\n console.log(chalk.dim(` Skipped: ${crawlResult.skippedUrls.length} URLs (over limit)`));\n }\n console.log(\"\");\n }\n\n // 8. Push to dashboard\n if (opts.push) {\n const apiKey = await resolveApiKey(opts.apiKey);\n if (!apiKey) {\n if (!jsonOutput) {\n console.log(chalk.yellow(\" ⚠\") + \" To push results to your dashboard, link your project first:\");\n console.log(\"\");\n console.log(chalk.bold(\" npx indxel link\"));\n console.log(\"\");\n console.log(chalk.dim(\" Or use --api-key / set INDXEL_API_KEY.\"));\n console.log(\"\");\n }\n } else {\n const pushSpinner = jsonOutput ? null : ora(\"Pushing results to Indxel...\").start();\n try {\n const pushUrl = process.env.INDXEL_API_URL || \"https://indxel.com\";\n const res = await fetch(`${pushUrl}/api/cli/push`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n url,\n crawl: crawlResult,\n robots: robotsResult,\n sitemap: sitemapComparison,\n assets: assetResult,\n }),\n });\n if (res.ok) {\n const data = (await res.json()) as { checkId?: string };\n if (pushSpinner) pushSpinner.succeed(`Pushed to dashboard — check ${data.checkId}`);\n } else {\n const data = (await res.json().catch(() => ({}))) as { error?: string };\n if (pushSpinner) pushSpinner.fail(`Push failed: ${data.error || res.statusText}`);\n }\n } catch (err) {\n if (pushSpinner) pushSpinner.fail(`Push failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n if (!jsonOutput) console.log(\"\");\n }\n }\n\n // Nudge: save results to dashboard (only if --push was NOT used)\n if (!opts.push && !jsonOutput) {\n console.log(chalk.dim(\" Save & compare crawls → \") + chalk.bold(\"npx indxel crawl --push\"));\n console.log(chalk.dim(\" Submit to Google → \") + chalk.bold(\"npx indxel index\"));\n console.log(\"\");\n }\n\n // Exit code\n if (crawlResult.totalErrors > 0) {\n process.exit(1);\n }\n });\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { researchKeywords, crawlSite, analyzeContentGaps } from \"indxel\";\nimport { resolveApiKey } from \"../store.js\";\n\nexport const keywordsCommand = new Command(\"keywords\")\n .description(\"Research keyword opportunities and find content gaps\")\n .argument(\"<seed>\", \"Seed keyword or topic to research\")\n .option(\"--locale <locale>\", \"Language locale\", \"en\")\n .option(\"--country <country>\", \"Country code\", \"us\")\n .option(\"--site <url>\", \"Site URL to analyze content gaps against\")\n .option(\"--max-pages <n>\", \"Maximum pages to crawl for gap analysis\", \"30\")\n .option(\"--api-key <key>\", \"Indxel API key (or set INDXEL_API_KEY / run npx indxel link)\")\n .option(\"--json\", \"Output results as JSON\", false)\n .action(async (seed: string, opts) => {\n const jsonOutput = opts.json;\n\n // Gate: keyword research requires a linked project (free account)\n const apiKey = await resolveApiKey(opts.apiKey);\n if (!apiKey) {\n console.log(\"\");\n console.log(chalk.bold(\" indxel keywords\") + chalk.dim(\" — requires a free account\"));\n console.log(\"\");\n console.log(chalk.dim(\" Keyword research is free but requires a linked project.\"));\n console.log(chalk.dim(\" Create a free account in 30 seconds:\"));\n console.log(\"\");\n console.log(chalk.bold(\" npx indxel link\"));\n console.log(\"\");\n process.exit(1);\n }\n\n if (!jsonOutput) {\n console.log(\"\");\n console.log(chalk.bold(` indxel keywords`) + chalk.dim(` — \"${seed}\"`));\n console.log(\"\");\n }\n\n // 1. Keyword research\n const kwSpinner = jsonOutput ? null : ora(\"Researching keywords...\").start();\n const kwResult = await researchKeywords(seed, {\n locale: opts.locale,\n country: opts.country,\n });\n\n if (!jsonOutput) {\n kwSpinner!.succeed(`Found ${kwResult.totalKeywords} keywords`);\n console.log(\"\");\n\n if (kwResult.suggestions.length > 0) {\n console.log(chalk.bold(` Direct suggestions (${kwResult.suggestions.length})`));\n for (const s of kwResult.suggestions) {\n console.log(` ${chalk.hex(\"#F4A261\")(s.keyword)}`);\n }\n console.log(\"\");\n }\n\n if (kwResult.questions.length > 0) {\n console.log(chalk.bold(` Questions (${kwResult.questions.length})`));\n for (const q of kwResult.questions.slice(0, 20)) {\n console.log(` ${chalk.cyan(\"?\")} ${q.keyword}`);\n }\n console.log(\"\");\n }\n\n if (kwResult.longTail.length > 0) {\n console.log(chalk.bold(` Long-tail (${kwResult.longTail.length})`));\n for (const lt of kwResult.longTail.slice(0, 20)) {\n console.log(chalk.dim(` ${lt.keyword}`));\n }\n if (kwResult.longTail.length > 20) {\n console.log(chalk.dim(` ... and ${kwResult.longTail.length - 20} more`));\n }\n console.log(\"\");\n }\n }\n\n // 2. Content gap analysis (if site URL provided)\n let gapResult = null;\n if (opts.site) {\n let siteUrl = opts.site;\n if (!siteUrl.startsWith(\"http://\") && !siteUrl.startsWith(\"https://\")) {\n siteUrl = `https://${siteUrl}`;\n }\n\n const crawlSpinner = jsonOutput ? null : ora(`Crawling ${siteUrl} for gap analysis...`).start();\n const crawlResult = await crawlSite(siteUrl, {\n maxPages: parseInt(opts.maxPages, 10),\n delay: 200,\n });\n\n if (!jsonOutput) {\n crawlSpinner!.succeed(`Crawled ${crawlResult.totalPages} pages`);\n }\n\n const allKeywords = [\n ...kwResult.suggestions,\n ...kwResult.questions,\n ...kwResult.longTail,\n ];\n\n const existingPages = crawlResult.pages\n .filter((p) => !p.error)\n .map((p) => ({ url: p.url, metadata: p.metadata }));\n\n gapResult = analyzeContentGaps(allKeywords, existingPages);\n\n if (!jsonOutput) {\n console.log(\"\");\n console.log(\n chalk.bold(` Content coverage: `) +\n `${gapResult.totalCovered}/${gapResult.totalKeywords} keywords (${gapResult.coveragePercent}%)`,\n );\n console.log(\"\");\n\n if (gapResult.gaps.length > 0) {\n const highGaps = gapResult.gaps.filter((g) => g.relevance === \"high\");\n const medGaps = gapResult.gaps.filter((g) => g.relevance === \"medium\");\n\n if (highGaps.length > 0) {\n console.log(chalk.bold.red(` High priority gaps (${highGaps.length})`));\n for (const gap of highGaps.slice(0, 15)) {\n console.log(\n chalk.red(` ✗ `) +\n `\"${gap.keyword}\" → ` +\n chalk.dim(`${gap.suggestedType} at ${gap.suggestedPath}`),\n );\n }\n console.log(\"\");\n }\n\n if (medGaps.length > 0) {\n console.log(chalk.bold.yellow(` Medium priority gaps (${medGaps.length})`));\n for (const gap of medGaps.slice(0, 10)) {\n console.log(\n chalk.yellow(` ⚠ `) +\n `\"${gap.keyword}\" → ` +\n chalk.dim(`${gap.suggestedType} at ${gap.suggestedPath}`),\n );\n }\n console.log(\"\");\n }\n }\n\n if (gapResult.gaps.length === 0) {\n console.log(chalk.green(` ✓ All keyword opportunities are covered`));\n console.log(\"\");\n }\n }\n }\n\n // Nudge: content gap analysis if --site wasn't used\n if (!jsonOutput && !opts.site) {\n console.log(chalk.dim(\" Find content gaps → \") + chalk.bold(`npx indxel keywords \"${seed}\" --site yoursite.com`));\n console.log(\"\");\n }\n\n // JSON output\n if (jsonOutput) {\n console.log(\n JSON.stringify(\n { keywords: kwResult, contentGaps: gapResult },\n null,\n 2,\n ),\n );\n }\n });\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { fetchSitemap, fetchRobots } from \"indxel\";\nimport { checkPlan } from \"../auth.js\";\nimport { loadIndexNowKey, resolveApiKey } from \"../store.js\";\nimport { resolveProjectUrl } from \"../config.js\";\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n\nexport const indexCommand = new Command(\"index\")\n .description(\"Submit your pages to search engines and check indexation status\")\n .argument(\"[url]\", \"Site URL (auto-detected from seo.config if omitted)\")\n .option(\"--check\", \"Check which pages appear indexed (Pro+)\", false)\n .option(\"--indexnow-key <key>\", \"IndexNow key (auto-detected from .indxel/ if not specified)\")\n .option(\"--api-key <key>\", \"Indxel API key (required for --check and IndexNow submission)\")\n .option(\"--json\", \"Output results as JSON\", false)\n .action(async (urlArg: string | undefined, opts) => {\n const jsonOutput = opts.json;\n const needsPaid = opts.check;\n\n // Helper: only log in human-readable mode\n function log(...args: unknown[]) {\n if (!jsonOutput) console.log(...args);\n }\n\n // Helper: create spinner only in human-readable mode\n function spin(text: string) {\n return jsonOutput ? null : ora(text).start();\n }\n\n // Resolve URL: argument > seo.config > .indxelrc > package.json\n let url = urlArg;\n if (!url) {\n const detected = await resolveProjectUrl(process.cwd());\n if (detected) {\n url = detected;\n log(chalk.dim(` Using URL from project config: ${url}`));\n } else {\n console.error(chalk.red(\" No URL provided and none found in seo.config or .indxelrc.json.\"));\n console.error(chalk.dim(\" Usage: npx indxel index [url]\"));\n process.exit(1);\n }\n }\n\n // Ensure URL has protocol\n if (!url.startsWith(\"http://\") && !url.startsWith(\"https://\")) {\n url = `https://${url}`;\n }\n\n let baseUrl: URL;\n try {\n baseUrl = new URL(url);\n } catch {\n console.error(chalk.red(\" Invalid URL.\"));\n process.exit(1);\n }\n\n const origin = baseUrl.origin;\n const host = baseUrl.hostname;\n\n log(\"\");\n log(chalk.bold(\" indxel index\") + chalk.dim(` — ${origin}`));\n log(\"\");\n\n // Gate paid features behind API key + plan check\n if (needsPaid) {\n const apiKey = await resolveApiKey(opts.apiKey);\n if (!apiKey) {\n log(chalk.red(\" ✗ --check requires a linked project (Plus plan).\"));\n log(chalk.dim(\" Run: \") + chalk.bold(\"npx indxel link\"));\n log(chalk.dim(\" Or use --api-key / set INDXEL_API_KEY.\"));\n log(\"\");\n process.exit(1);\n }\n\n const plan = await checkPlan(apiKey);\n if (!plan) {\n log(chalk.red(\" ✗ Invalid API key.\"));\n log(\"\");\n process.exit(1);\n }\n\n if (plan === \"FREE\") {\n log(chalk.red(\" ✗ Indexation check requires a Pro plan.\"));\n log(chalk.dim(\" Upgrade at https://indxel.com/pricing\"));\n log(\"\");\n process.exit(1);\n }\n }\n\n // 1. Fetch sitemap\n const sitemapSpinner = spin(\"Fetching sitemap...\");\n const sitemapResult = await fetchSitemap(origin);\n const sitemapUrl = `${origin}/sitemap.xml`;\n\n if (!sitemapResult.found || sitemapResult.urls.length === 0) {\n sitemapSpinner?.fail(\"No sitemap found\");\n log(chalk.dim(\" Create a sitemap first: \") + chalk.bold(\"npx indxel init\"));\n log(\"\");\n if (jsonOutput) {\n console.log(JSON.stringify({ error: \"No sitemap found\" }, null, 2));\n }\n process.exit(1);\n }\n\n sitemapSpinner?.succeed(`Found sitemap — ${sitemapResult.urls.length} URLs`);\n\n // 2. Check robots.txt references sitemap\n const robotsSpinner = spin(\"Checking robots.txt...\");\n const robotsResult = await fetchRobots(origin);\n let sitemapInRobots = false;\n\n if (robotsResult.found) {\n sitemapInRobots = robotsResult.sitemapUrls.some((s) =>\n s.toLowerCase().includes(\"sitemap\"),\n );\n if (sitemapInRobots) {\n robotsSpinner?.succeed(\"robots.txt references sitemap\");\n } else {\n robotsSpinner?.warn(\"robots.txt found but doesn't reference sitemap\");\n log(chalk.dim(` Add this to your robots.txt:`));\n log(chalk.dim(` Sitemap: ${sitemapUrl}`));\n }\n } else {\n robotsSpinner?.warn(\"No robots.txt found\");\n log(chalk.dim(\" Create one with: \") + chalk.bold(\"npx indxel init\"));\n }\n\n log(\"\");\n\n // 3. IndexNow submission (Bing, Yandex, DuckDuckGo, etc.)\n // IndexNow is an open protocol — one-shot submission works without an account.\n const indexNowKey = opts.indexnowKey || process.env.INDEXNOW_KEY || await loadIndexNowKey(process.cwd());\n const indexNowResult: { submitted: boolean; engine: string; status?: number }[] = [];\n\n if (indexNowKey) {\n const urls = sitemapResult.urls.map((u) => u.loc);\n const indexNowSpinner = spin(\"Submitting via IndexNow...\");\n\n const indexNowEngines = [\n { name: \"Bing/Yandex\", endpoint: \"https://api.indexnow.org/indexnow\" },\n ];\n\n for (const engine of indexNowEngines) {\n try {\n const res = await fetch(engine.endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n host,\n key: indexNowKey,\n keyLocation: `${origin}/${indexNowKey}.txt`,\n urlList: urls.slice(0, 10000), // IndexNow limit\n }),\n signal: AbortSignal.timeout(15000),\n });\n\n if (res.ok || res.status === 202) {\n indexNowResult.push({ submitted: true, engine: engine.name, status: res.status });\n indexNowSpinner?.succeed(`IndexNow — ${urls.length} URLs submitted to ${engine.name}`);\n } else {\n indexNowResult.push({ submitted: false, engine: engine.name, status: res.status });\n indexNowSpinner?.warn(`IndexNow — ${engine.name} returned HTTP ${res.status}`);\n }\n } catch (err) {\n indexNowResult.push({ submitted: false, engine: engine.name });\n indexNowSpinner?.fail(`IndexNow — ${err instanceof Error ? err.message : \"failed\"}`);\n }\n }\n } else {\n log(chalk.bold(\" IndexNow\") + chalk.dim(\" (Bing, Yandex, DuckDuckGo)\"));\n log(chalk.dim(\" Not configured. Run \") + chalk.bold(\"npx indxel init\") + chalk.dim(\" to set it up automatically.\"));\n log(\"\");\n }\n\n log(chalk.bold(\" Google Search Console\"));\n log(chalk.dim(\" Google requires manual setup via Search Console:\"));\n log(chalk.dim(\" 1. Go to \") + chalk.underline(\"https://search.google.com/search-console\"));\n log(chalk.dim(` 2. Add & verify ${host}`));\n log(chalk.dim(\" 3. Submit your sitemap: Sitemaps > Add > sitemap.xml\"));\n log(\"\");\n\n // 4. Check indexation status (optional)\n let indexationResults: Array<{ url: string; indexed: boolean }> | null = null;\n\n if (opts.check) {\n const checkSpinner = spin(\"Checking indexation status...\");\n indexationResults = [];\n const urls = sitemapResult.urls.map((u) => u.loc);\n let indexedCount = 0;\n\n for (let i = 0; i < urls.length; i++) {\n const pageUrl = urls[i];\n if (checkSpinner) {\n checkSpinner.text = `Checking indexation... ${i + 1}/${urls.length}`;\n }\n\n try {\n const cacheUrl = `https://webcache.googleusercontent.com/search?q=cache:${encodeURIComponent(pageUrl)}`;\n const res = await fetch(cacheUrl, {\n method: \"HEAD\",\n signal: AbortSignal.timeout(5000),\n redirect: \"manual\",\n headers: {\n \"User-Agent\": \"Mozilla/5.0 (compatible; Indxel/0.1; +https://indxel.com)\",\n },\n });\n\n const indexed = res.status === 200 || res.status === 301 || res.status === 302;\n indexationResults.push({ url: pageUrl, indexed });\n if (indexed) indexedCount++;\n } catch {\n indexationResults.push({ url: pageUrl, indexed: false });\n }\n\n await delay(300);\n }\n\n checkSpinner?.succeed(`Indexation: ${indexedCount}/${urls.length} pages found in Google cache`);\n\n if (!jsonOutput) {\n console.log(\"\");\n const notIndexed = indexationResults.filter((r) => !r.indexed);\n\n if (notIndexed.length > 0) {\n console.log(chalk.bold(` Not indexed (${notIndexed.length})`));\n for (const r of notIndexed.slice(0, 20)) {\n console.log(chalk.red(\" ✗ \") + r.url);\n }\n if (notIndexed.length > 20) {\n console.log(chalk.dim(` ... and ${notIndexed.length - 20} more`));\n }\n console.log(\"\");\n } else {\n console.log(chalk.green(\" ✓ All pages appear indexed\"));\n console.log(\"\");\n }\n }\n }\n\n // 5. Summary\n if (jsonOutput) {\n console.log(JSON.stringify({\n sitemap: { url: sitemapUrl, urls: sitemapResult.urls.length },\n robotsTxt: { found: robotsResult.found, referencesSitemap: sitemapInRobots },\n indexNow: indexNowResult.length > 0 ? indexNowResult : null,\n indexation: indexationResults,\n }, null, 2));\n } else {\n console.log(chalk.bold(\" ─── Summary ───\"));\n console.log(\"\");\n console.log(` Sitemap: ${sitemapResult.urls.length} URLs`);\n\n let robotsStatus: string;\n if (!robotsResult.found) {\n robotsStatus = chalk.red(\"✗ not found\");\n } else if (sitemapInRobots) {\n robotsStatus = chalk.green(\"✓ references sitemap\");\n } else {\n robotsStatus = chalk.yellow(\"⚠ missing sitemap ref\");\n }\n console.log(` robots.txt: ${robotsStatus}`);\n\n if (indexNowResult.length > 0) {\n for (const r of indexNowResult) {\n const status = r.submitted ? chalk.green(\"✓ submitted\") : chalk.red(\"✗ failed\");\n console.log(` IndexNow: ${status} (${r.engine})`);\n }\n } else {\n console.log(` IndexNow: ${chalk.dim(\"not configured (run npx indxel init)\")}`);\n }\n if (indexationResults) {\n const indexedCount = indexationResults.filter((r) => r.indexed).length;\n console.log(` Google cache: ${indexedCount}/${indexationResults.length} indexed`);\n }\n console.log(\"\");\n }\n });\n","export async function checkPlan(apiKey: string): Promise<string | null> {\n try {\n const apiUrl = process.env.INDXEL_API_URL || \"https://indxel.com\";\n const res = await fetch(`${apiUrl}/api/cli/plan`, {\n headers: { Authorization: `Bearer ${apiKey}` },\n signal: AbortSignal.timeout(10000),\n });\n if (!res.ok) return null;\n const data = (await res.json()) as { plan?: string };\n return data.plan ?? null;\n } catch {\n return null;\n }\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { fetchSitemap } from \"indxel\";\nimport { resolveProjectUrl } from \"../config.js\";\nimport { resolveApiKey } from \"../store.js\";\n\n// --- Types ---\n\ninterface PsiDiagnostic {\n id: string;\n title: string;\n displayValue?: string;\n savingsMs?: number;\n}\n\ninterface PsiMetrics {\n performanceScore: number;\n lcp: number;\n cls: number;\n inp: number;\n fcp: number;\n si: number;\n tbt: number;\n diagnostics: PsiDiagnostic[];\n}\n\ninterface PageResult {\n url: string;\n strategy: string;\n metrics: PsiMetrics | null;\n error?: string;\n}\n\n// --- CWV thresholds (Google's) ---\n\nconst THRESHOLDS = {\n lcp: { good: 2500, poor: 4000 },\n cls: { good: 0.1, poor: 0.25 },\n inp: { good: 200, poor: 500 },\n} as const;\n\n// --- Helpers ---\n\nfunction ratingFor(\n metric: \"lcp\" | \"cls\" | \"inp\",\n value: number,\n): \"good\" | \"needs-work\" | \"poor\" {\n const t = THRESHOLDS[metric];\n if (value <= t.good) return \"good\";\n if (value <= t.poor) return \"needs-work\";\n return \"poor\";\n}\n\nfunction colorForRating(rating: \"good\" | \"needs-work\" | \"poor\") {\n if (rating === \"good\") return chalk.green;\n if (rating === \"needs-work\") return chalk.yellow;\n return chalk.red;\n}\n\nfunction iconForRating(rating: \"good\" | \"needs-work\" | \"poor\") {\n if (rating === \"good\") return chalk.green(\"✓\");\n if (rating === \"needs-work\") return chalk.yellow(\"⚠\");\n return chalk.red(\"✗\");\n}\n\nfunction formatMs(ms: number): string {\n if (ms >= 1000) return `${(ms / 1000).toFixed(1)}s`;\n return `${Math.round(ms)}ms`;\n}\n\nfunction formatCls(value: number): string {\n return value.toFixed(2);\n}\n\nfunction scoreColor(score: number) {\n if (score >= 90) return chalk.green;\n if (score >= 50) return chalk.yellow;\n return chalk.red;\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n\n// --- PSI API ---\n\n/**\n * Fetch PSI metrics. Tries indxel backend first (uses our API key),\n * falls back to direct Google PSI API if no indxel API key.\n */\nexport async function fetchPsi(\n url: string,\n strategy: \"mobile\" | \"desktop\",\n apiKey?: string | null,\n): Promise<PsiMetrics> {\n // 1. Try via indxel backend (proxied, no user API key needed for Google)\n if (apiKey) {\n const backendUrl = process.env.INDXEL_API_URL || \"https://indxel.com\";\n const res = await fetch(`${backendUrl}/api/cli/perf`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({ url, strategy }),\n signal: AbortSignal.timeout(60000),\n });\n\n if (res.ok) {\n return await res.json() as PsiMetrics;\n }\n\n // If backend fails with auth error, don't fallback\n if (res.status === 401 || res.status === 403) {\n const data = await res.json().catch(() => ({ error: \"Auth failed\" })) as { error?: string };\n throw new Error(data.error || `Backend returned ${res.status}`);\n }\n // Other errors (502, etc.) → fallback to direct\n }\n\n // 2. Fallback: direct Google PSI API\n return fetchPsiDirect(url, strategy);\n}\n\n/** Direct call to Google PSI API (rate-limited by IP or user's own key) */\nexport async function fetchPsiDirect(\n url: string,\n strategy: \"mobile\" | \"desktop\",\n): Promise<PsiMetrics> {\n const params = new URLSearchParams({\n url,\n strategy,\n category: \"performance\",\n });\n\n const apiKey = process.env.PSI_API_KEY;\n if (apiKey) params.set(\"key\", apiKey);\n\n const res = await fetch(\n `https://www.googleapis.com/pagespeedonline/v5/runPagespeed?${params}`,\n { signal: AbortSignal.timeout(60000) },\n );\n\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new Error(`PSI API returned HTTP ${res.status}: ${body.slice(0, 200)}`);\n }\n\n const data = await res.json();\n return parsePsiResponse(data);\n}\n\nexport function parsePsiResponse(data: any): PsiMetrics {\n const lr = data.lighthouseResult;\n if (!lr) throw new Error(\"No lighthouseResult in PSI response\");\n\n const perfScore = lr.categories?.performance?.score;\n if (perfScore == null) throw new Error(\"No performance score in PSI response\");\n\n // Extract opportunities & diagnostics\n const diagnostics: PsiDiagnostic[] = [];\n const auditRefs: Array<{ id: string; group?: string }> =\n lr.categories?.performance?.auditRefs ?? [];\n const metricIds = new Set([\n \"largest-contentful-paint\", \"cumulative-layout-shift\", \"interaction-to-next-paint\",\n \"first-contentful-paint\", \"speed-index\", \"total-blocking-time\",\n ]);\n\n for (const ref of auditRefs) {\n if (metricIds.has(ref.id)) continue;\n if (ref.group !== \"diagnostics\" && ref.group !== \"load-opportunities\" && ref.group !== \"budgets\") continue;\n const audit = lr.audits?.[ref.id];\n if (!audit || audit.score === 1 || audit.scoreDisplayMode === \"notApplicable\") continue;\n\n diagnostics.push({\n id: ref.id,\n title: audit.title ?? ref.id,\n displayValue: audit.displayValue || undefined,\n savingsMs: audit.details?.overallSavingsMs as number | undefined,\n });\n }\n\n diagnostics.sort((a, b) => (b.savingsMs ?? 0) - (a.savingsMs ?? 0));\n\n return {\n performanceScore: Math.round(perfScore * 100),\n lcp: lr.audits?.[\"largest-contentful-paint\"]?.numericValue ?? 0,\n cls: lr.audits?.[\"cumulative-layout-shift\"]?.numericValue ?? 0,\n inp: lr.audits?.[\"interaction-to-next-paint\"]?.numericValue ?? 0,\n fcp: lr.audits?.[\"first-contentful-paint\"]?.numericValue ?? 0,\n si: lr.audits?.[\"speed-index\"]?.numericValue ?? 0,\n tbt: lr.audits?.[\"total-blocking-time\"]?.numericValue ?? 0,\n diagnostics,\n };\n}\n\nexport function checkBudgets(\n metrics: PsiMetrics,\n budgets: { lcp?: number; cls?: number; score?: number },\n): string[] {\n const failures: string[] = [];\n\n if (budgets.score != null && metrics.performanceScore < budgets.score) {\n failures.push(\n `Performance score ${metrics.performanceScore} is below budget ${budgets.score}`,\n );\n }\n if (budgets.lcp != null && metrics.lcp > budgets.lcp) {\n failures.push(\n `LCP ${formatMs(metrics.lcp)} exceeds budget ${formatMs(budgets.lcp)}`,\n );\n }\n if (budgets.cls != null && metrics.cls > budgets.cls) {\n failures.push(\n `CLS ${formatCls(metrics.cls)} exceeds budget ${formatCls(budgets.cls)}`,\n );\n }\n\n return failures;\n}\n\n// --- Output formatting ---\n\nfunction printPageResult(result: PageResult) {\n const { url, strategy, metrics, error } = result;\n\n console.log(\n chalk.bold(\" indxel perf\") + chalk.dim(` — ${url} (${strategy})`),\n );\n console.log(\"\");\n\n if (error || !metrics) {\n console.log(chalk.red(` ✗ ${error ?? \"Unknown error\"}`));\n console.log(\"\");\n return;\n }\n\n const sc = scoreColor(metrics.performanceScore);\n const perfIcon =\n metrics.performanceScore >= 90\n ? chalk.green(\"✓\")\n : metrics.performanceScore >= 50\n ? chalk.yellow(\"⚠\")\n : chalk.red(\"✗\");\n console.log(\n ` ${perfIcon} ${chalk.bold(\"Performance\")} ${sc(chalk.bold(`${metrics.performanceScore}/100`))}`,\n );\n console.log(\"\");\n\n // Core Web Vitals\n console.log(chalk.bold(\" Core Web Vitals\"));\n\n const lcpRating = ratingFor(\"lcp\", metrics.lcp);\n const clsRating = ratingFor(\"cls\", metrics.cls);\n const inpRating = ratingFor(\"inp\", metrics.inp);\n\n console.log(\n ` ${iconForRating(lcpRating)} ${colorForRating(lcpRating)(formatMs(metrics.lcp).padEnd(9))} ${chalk.dim(\"LCP Largest Contentful Paint\")}`,\n );\n console.log(\n ` ${iconForRating(clsRating)} ${colorForRating(clsRating)(formatCls(metrics.cls).padEnd(9))} ${chalk.dim(\"CLS Cumulative Layout Shift\")}`,\n );\n console.log(\n ` ${iconForRating(inpRating)} ${colorForRating(inpRating)(formatMs(metrics.inp).padEnd(9))} ${chalk.dim(\"INP Interaction to Next Paint\")}`,\n );\n console.log(\"\");\n\n // Other metrics\n console.log(chalk.bold(\" Other metrics\"));\n console.log(\n ` ${formatMs(metrics.fcp).padEnd(9)} ${chalk.dim(\"FCP First Contentful Paint\")}`,\n );\n console.log(\n ` ${formatMs(metrics.si).padEnd(9)} ${chalk.dim(\"SI Speed Index\")}`,\n );\n console.log(\n ` ${formatMs(metrics.tbt).padEnd(9)} ${chalk.dim(\"TBT Total Blocking Time\")}`,\n );\n console.log(\"\");\n\n // Diagnostics\n if (metrics.diagnostics.length > 0) {\n console.log(chalk.bold(\" Diagnostics\"));\n for (const d of metrics.diagnostics) {\n const icon = d.savingsMs != null && d.savingsMs > 0\n ? chalk.yellow(\"⚡\")\n : chalk.dim(\"ℹ\");\n const savings = d.savingsMs != null && d.savingsMs > 0\n ? chalk.yellow(` -${formatMs(d.savingsMs)}`)\n : \"\";\n const display = d.displayValue ? chalk.dim(` (${d.displayValue})`) : \"\";\n console.log(` ${icon} ${d.title}${display}${savings}`);\n }\n console.log(\"\");\n }\n}\n\nfunction printMultiPageSummary(results: PageResult[]) {\n const valid = results.filter((r) => r.metrics);\n if (valid.length === 0) return;\n\n const avgScore = Math.round(\n valid.reduce((s, r) => s + r.metrics!.performanceScore, 0) / valid.length,\n );\n const worstLcp = Math.max(...valid.map((r) => r.metrics!.lcp));\n const worstCls = Math.max(...valid.map((r) => r.metrics!.cls));\n const worstInp = Math.max(...valid.map((r) => r.metrics!.inp));\n\n console.log(chalk.bold(\" ─── Summary ───\"));\n console.log(\"\");\n console.log(` Pages tested: ${chalk.bold(String(results.length))}`);\n console.log(\n ` Avg score: ${scoreColor(avgScore)(chalk.bold(`${avgScore}/100`))}`,\n );\n\n const lcpR = ratingFor(\"lcp\", worstLcp);\n const clsR = ratingFor(\"cls\", worstCls);\n const inpR = ratingFor(\"inp\", worstInp);\n\n console.log(\n ` Worst LCP: ${colorForRating(lcpR)(formatMs(worstLcp))}`,\n );\n console.log(\n ` Worst CLS: ${colorForRating(clsR)(formatCls(worstCls))}`,\n );\n console.log(\n ` Worst INP: ${colorForRating(inpR)(formatMs(worstInp))}`,\n );\n console.log(\"\");\n}\n\n// --- Command ---\n\nexport const perfCommand = new Command(\"perf\")\n .description(\"Test Core Web Vitals and performance via PageSpeed Insights\")\n .argument(\"[url]\", \"URL to test (auto-detected from seo.config if omitted)\")\n .option(\n \"--strategy <strategy>\",\n \"Testing strategy: mobile or desktop\",\n \"mobile\",\n )\n .option(\n \"--pages <n>\",\n \"Test top N pages from sitemap (default: 1 = just the URL)\",\n \"1\",\n )\n .option(\"--json\", \"Output results as JSON\", false)\n .option(\"--budget-lcp <ms>\", \"Fail if LCP exceeds threshold (ms)\")\n .option(\"--budget-cls <score>\", \"Fail if CLS exceeds threshold\")\n .option(\"--budget-score <n>\", \"Fail if perf score below threshold\")\n .option(\"--api-key <key>\", \"Indxel API key (uses our backend for PSI, or set INDXEL_API_KEY)\")\n .action(async (urlArg: string | undefined, opts) => {\n const jsonOutput = opts.json;\n const strategy = opts.strategy as \"mobile\" | \"desktop\";\n const pageCount = parseInt(opts.pages, 10);\n\n // Resolve API key for proxied PSI calls\n const apiKey = await resolveApiKey(opts.apiKey);\n\n if (strategy !== \"mobile\" && strategy !== \"desktop\") {\n console.error(\n chalk.red(\" --strategy must be 'mobile' or 'desktop'\"),\n );\n process.exit(1);\n }\n\n // Resolve URL: argument > seo.config > .indxelrc > package.json\n let url = urlArg;\n if (!url) {\n const detected = await resolveProjectUrl(process.cwd());\n if (detected) {\n url = detected;\n if (!jsonOutput) {\n console.log(chalk.dim(` Using URL from project config: ${url}`));\n console.log(\"\");\n }\n } else {\n console.error(chalk.red(\" No URL provided and none found in seo.config or .indxelrc.json.\"));\n console.error(chalk.dim(\" Usage: npx indxel perf [url]\"));\n process.exit(1);\n }\n }\n\n // Ensure URL has protocol\n if (!url.startsWith(\"http://\") && !url.startsWith(\"https://\")) {\n url = `https://${url}`;\n }\n\n try {\n new URL(url);\n } catch {\n console.error(chalk.red(\" Invalid URL.\"));\n process.exit(1);\n }\n\n // Collect URLs to test\n let urls: string[] = [url];\n\n if (pageCount > 1) {\n const sitemapSpinner = jsonOutput ? null : ora(\"Fetching sitemap...\").start();\n const sitemap = await fetchSitemap(url);\n\n if (sitemap.found && sitemap.urls.length > 0) {\n urls = sitemap.urls.slice(0, pageCount).map((u) => u.loc);\n sitemapSpinner?.succeed(\n `Found ${sitemap.urls.length} URLs, testing top ${urls.length}`,\n );\n } else {\n sitemapSpinner?.warn(\"No sitemap found, testing single URL\");\n }\n if (!jsonOutput) console.log(\"\");\n }\n\n // Run PSI for each URL\n const results: PageResult[] = [];\n\n for (let i = 0; i < urls.length; i++) {\n const targetUrl = urls[i];\n const spinner = jsonOutput\n ? null\n : ora(\n urls.length > 1\n ? `Testing ${i + 1}/${urls.length}: ${targetUrl}`\n : `Testing ${targetUrl} (${strategy})...`,\n ).start();\n\n try {\n const metrics = await fetchPsi(targetUrl, strategy, apiKey);\n spinner?.stop();\n results.push({ url: targetUrl, strategy, metrics });\n\n if (!jsonOutput) {\n printPageResult({ url: targetUrl, strategy, metrics });\n }\n } catch (err) {\n const errMsg = err instanceof Error ? err.message : String(err);\n spinner?.fail(`Failed: ${targetUrl}`);\n results.push({ url: targetUrl, strategy, metrics: null, error: errMsg });\n\n if (!jsonOutput) {\n console.log(chalk.red(` ${errMsg}`));\n console.log(\"\");\n }\n }\n\n // Rate-limit delay between calls\n if (i < urls.length - 1) {\n await delay(2000);\n }\n }\n\n // Multi-page summary\n if (!jsonOutput && results.length > 1) {\n printMultiPageSummary(results);\n }\n\n // JSON output\n if (jsonOutput) {\n const output =\n results.length === 1\n ? {\n url: results[0].url,\n strategy: results[0].strategy,\n ...(results[0].metrics ?? {}),\n error: results[0].error ?? undefined,\n }\n : {\n strategy,\n pages: results.map((r) => ({\n url: r.url,\n ...(r.metrics ?? {}),\n error: r.error ?? undefined,\n })),\n summary: (() => {\n const valid = results.filter((r) => r.metrics);\n if (valid.length === 0) return null;\n return {\n avgScore: Math.round(\n valid.reduce(\n (s, r) => s + r.metrics!.performanceScore,\n 0,\n ) / valid.length,\n ),\n worstLcp: Math.max(\n ...valid.map((r) => r.metrics!.lcp),\n ),\n worstCls: Math.max(\n ...valid.map((r) => r.metrics!.cls),\n ),\n worstInp: Math.max(\n ...valid.map((r) => r.metrics!.inp),\n ),\n };\n })(),\n };\n console.log(JSON.stringify(output, null, 2));\n }\n\n // Budget enforcement\n const budgets = {\n lcp: opts.budgetLcp ? parseFloat(opts.budgetLcp) : undefined,\n cls: opts.budgetCls ? parseFloat(opts.budgetCls) : undefined,\n score: opts.budgetScore ? parseInt(opts.budgetScore, 10) : undefined,\n };\n\n const hasBudgets =\n budgets.lcp != null || budgets.cls != null || budgets.score != null;\n\n if (hasBudgets) {\n const allFailures: string[] = [];\n\n for (const r of results) {\n if (!r.metrics) continue;\n const failures = checkBudgets(r.metrics, budgets);\n if (failures.length > 0) {\n allFailures.push(...failures.map((f) => `${r.url}: ${f}`));\n }\n }\n\n if (allFailures.length > 0) {\n if (!jsonOutput) {\n console.log(chalk.red(chalk.bold(\" Budget exceeded:\")));\n for (const f of allFailures) {\n console.log(chalk.red(` ✗ ${f}`));\n }\n console.log(\"\");\n }\n process.exit(1);\n }\n }\n\n // Nudge: CI guard for performance budgets\n if (!jsonOutput && !hasBudgets) {\n console.log(chalk.dim(\" Enforce budgets in CI → \") + chalk.bold(\"npx indxel perf --budget-score 80 --budget-lcp 2500\"));\n console.log(chalk.dim(\" Full SEO + perf audit → \") + chalk.bold(\"npx indxel crawl\"));\n console.log(\"\");\n }\n });\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { loadProjectConfig, saveProjectConfig, loadIndexNowKey } from \"../store.js\";\nimport { resolveProjectUrl } from \"../config.js\";\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n\nasync function openBrowser(url: string): Promise<void> {\n const { platform } = process;\n const { execFile } = await import(\"node:child_process\");\n\n const cmd =\n platform === \"darwin\"\n ? \"open\"\n : platform === \"win32\"\n ? \"cmd\"\n : \"xdg-open\";\n\n if (platform === \"win32\") {\n execFile(cmd, [\"/c\", \"start\", \"\", url]);\n } else {\n execFile(cmd, [url]);\n }\n}\n\nexport const linkCommand = new Command(\"link\")\n .description(\"Link this project to your Indxel dashboard for monitoring\")\n .option(\"--api-key <key>\", \"Link directly with an account API key (skip browser flow)\")\n .action(async (opts) => {\n const apiUrl = process.env.INDXEL_API_URL || \"https://indxel.com\";\n const cwd = process.cwd();\n\n console.log(\"\");\n console.log(chalk.bold(\" indxel link\"));\n console.log(\"\");\n\n // Check if already linked\n const existing = await loadProjectConfig(cwd);\n if (existing) {\n console.log(chalk.green(\" ✓\") + ` Already linked to ${chalk.bold(existing.projectName)}`);\n console.log(chalk.dim(` Project ID: ${existing.projectId}`));\n console.log(chalk.dim(` Linked at: ${existing.linkedAt}`));\n console.log(\"\");\n console.log(chalk.dim(\" To re-link, delete .indxel/config.json and run again.\"));\n console.log(\"\");\n return;\n }\n\n // Option 1: Direct API key\n if (opts.apiKey) {\n const spinner = ora(\"Fetching projects...\").start();\n\n try {\n const res = await fetch(`${apiUrl}/api/projects/by-key`, {\n headers: { Authorization: `Bearer ${opts.apiKey}` },\n signal: AbortSignal.timeout(10000),\n });\n\n if (!res.ok) {\n spinner.fail(\"Invalid API key.\");\n console.log(chalk.dim(\" Check your key at https://indxel.com/dashboard/settings\"));\n console.log(\"\");\n process.exit(1);\n }\n\n const body = (await res.json()) as { projects: Array<{ id: string; name: string; url: string }> };\n const projects = body.projects;\n\n if (projects.length === 0) {\n spinner.fail(\"No projects found. Create one at https://indxel.com/dashboard first.\");\n console.log(\"\");\n process.exit(1);\n }\n\n // Try to auto-match by URL\n const detectedUrl = await resolveProjectUrl(cwd);\n let matched = detectedUrl\n ? projects.find(p => normalizeUrl(p.url) === normalizeUrl(detectedUrl))\n : null;\n\n // If only one project, use it\n if (!matched && projects.length === 1) {\n matched = projects[0];\n }\n\n if (matched) {\n spinner.succeed(`Linked to ${chalk.bold(matched.name)}`);\n\n await saveProjectConfig(cwd, {\n apiKey: opts.apiKey,\n projectId: matched.id,\n projectName: matched.name,\n linkedAt: new Date().toISOString(),\n });\n\n await syncIndexNowKey(cwd, apiUrl, opts.apiKey, matched.id);\n } else {\n // Multiple projects, no auto-match — show list\n spinner.stop();\n console.log(chalk.bold(\" Multiple projects found. Pick one:\"));\n console.log(\"\");\n projects.forEach((p, i) => {\n console.log(` ${chalk.bold(`${i + 1}.`)} ${p.name} ${chalk.dim(`(${p.url})`)}`);\n });\n console.log(\"\");\n console.log(chalk.dim(\" Re-run with the project URL matching your codebase,\"));\n console.log(chalk.dim(\" or add a seo.config.ts with your site URL.\"));\n console.log(\"\");\n\n // Default to first project\n const project = projects[0];\n const linkSpinner = ora(`Linking to ${project.name}...`).start();\n\n await saveProjectConfig(cwd, {\n apiKey: opts.apiKey,\n projectId: project.id,\n projectName: project.name,\n linkedAt: new Date().toISOString(),\n });\n\n await syncIndexNowKey(cwd, apiUrl, opts.apiKey, project.id);\n linkSpinner.succeed(`Linked to ${chalk.bold(project.name)}`);\n }\n\n console.log(\"\");\n console.log(chalk.dim(\" Config saved to .indxel/config.json\"));\n console.log(chalk.dim(\" You can now use \") + chalk.bold(\"npx indxel crawl --push\") + chalk.dim(\" without --api-key.\"));\n console.log(\"\");\n return;\n } catch (err) {\n spinner.fail(err instanceof Error ? err.message : \"Connection failed\");\n console.log(\"\");\n process.exit(1);\n }\n }\n\n // Option 2: Device flow (browser-based)\n const initSpinner = ora(\"Starting device flow...\").start();\n\n let deviceCode: string;\n let userCode: string;\n\n try {\n const res = await fetch(`${apiUrl}/api/cli/auth`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n signal: AbortSignal.timeout(10000),\n });\n\n if (!res.ok) {\n initSpinner.fail(\"Could not start device flow.\");\n console.log(chalk.dim(\" You can also link directly: \") + chalk.bold(\"npx indxel link --api-key <your-key>\"));\n console.log(\"\");\n process.exit(1);\n }\n\n const data = (await res.json()) as { deviceCode: string; userCode: string };\n deviceCode = data.deviceCode;\n userCode = data.userCode;\n initSpinner.stop();\n } catch (err) {\n initSpinner.fail(err instanceof Error ? err.message : \"Connection failed\");\n console.log(chalk.dim(\" You can also link directly: \") + chalk.bold(\"npx indxel link --api-key <your-key>\"));\n console.log(\"\");\n process.exit(1);\n return; // unreachable, satisfies TS\n }\n\n const connectUrl = `${apiUrl}/cli/connect?code=${userCode}`;\n\n console.log(chalk.bold(\" Open this URL in your browser:\"));\n console.log(\"\");\n console.log(` ${chalk.underline(connectUrl)}`);\n console.log(\"\");\n console.log(` Your code: ${chalk.bold.cyan(userCode)}`);\n console.log(\"\");\n\n // Try to open browser automatically\n try {\n await openBrowser(connectUrl);\n console.log(chalk.dim(\" Browser opened automatically.\"));\n } catch {\n // Silently fail — user can open manually\n }\n\n // Poll for authorization\n const pollSpinner = ora(\"Waiting for authorization...\").start();\n const maxWait = 5 * 60 * 1000; // 5 minutes\n const pollInterval = 2000; // 2 seconds\n const startTime = Date.now();\n\n while (Date.now() - startTime < maxWait) {\n await delay(pollInterval);\n\n try {\n const res = await fetch(`${apiUrl}/api/cli/auth?code=${deviceCode}`, {\n signal: AbortSignal.timeout(10000),\n });\n\n if (res.status === 202) {\n // Still pending\n continue;\n }\n\n if (res.ok) {\n const data = (await res.json()) as {\n apiKey: string;\n projectId: string;\n projectName: string;\n };\n\n pollSpinner.succeed(`Linked to ${chalk.bold(data.projectName)}`);\n\n await saveProjectConfig(cwd, {\n apiKey: data.apiKey,\n projectId: data.projectId,\n projectName: data.projectName,\n linkedAt: new Date().toISOString(),\n });\n\n // Sync IndexNow key if available\n await syncIndexNowKey(cwd, apiUrl, data.apiKey, data.projectId);\n\n console.log(\"\");\n console.log(chalk.dim(\" Config saved to .indxel/config.json\"));\n console.log(chalk.dim(\" You can now use \") + chalk.bold(\"npx indxel crawl --push\") + chalk.dim(\" without --api-key.\"));\n console.log(\"\");\n return;\n }\n\n // Unexpected status\n pollSpinner.fail(\"Authorization failed.\");\n console.log(\"\");\n process.exit(1);\n } catch {\n // Network error — keep polling\n }\n }\n\n pollSpinner.fail(\"Timed out waiting for authorization (5 minutes).\");\n console.log(chalk.dim(\" Try again: \") + chalk.bold(\"npx indxel link\"));\n console.log(\"\");\n process.exit(1);\n });\n\n/** Normalize URL for matching: strip protocol, trailing slash, www */\nfunction normalizeUrl(url: string): string {\n return url\n .replace(/^https?:\\/\\//, '')\n .replace(/^www\\./, '')\n .replace(/\\/+$/, '')\n .toLowerCase();\n}\n\n/**\n * Sync the local IndexNow key to the linked project on the dashboard.\n */\nasync function syncIndexNowKey(\n cwd: string,\n apiUrl: string,\n apiKey: string,\n projectId: string,\n): Promise<void> {\n const indexNowKey = await loadIndexNowKey(cwd);\n if (!indexNowKey) return;\n\n try {\n const res = await fetch(`${apiUrl}/api/projects/${projectId}/indexation/setup`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({ action: \"sync\", key: indexNowKey }),\n signal: AbortSignal.timeout(10000),\n });\n\n if (res.ok) {\n console.log(chalk.green(\" ✓\") + \" IndexNow key synced to dashboard\");\n }\n } catch {\n // Non-critical — skip silently\n }\n}\n","import { createProgram } from \"./index.js\";\n\nconst program = createProgram();\nprogram.parse();\n"],"mappings":"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","names":["Command","existsSync","writeFile","mkdir","readFile","join","existsSync","readFile","join","join","existsSync","readFile","existsSync","readFile","join","join","writeFile","existsSync","readFile","mkdir","Command","chalk","ora","readFile","join","readFile","join","sep","glob","createEmptyMetadata","mergeMetadata","readFile","join","sep","glob","createEmptyMetadata","hasExport","mergeMetadata","readFile","join","sep","glob","createEmptyMetadata","mergeMetadata","readFile","join","dirname","sep","glob","createEmptyMetadata","mergeMetadata","extractMetaTag","chalk","scoreColor","chalk","Command","ora","chalk","Command","chalk","ora","chalk","Command","delay","ora","Command","chalk","ora","crawlSite","Command","chalk","ora","crawlSite","Command","chalk","ora","fetchSitemap","fetchRobots","Command","ora","chalk","fetchSitemap","fetchRobots","Command","chalk","ora","fetchSitemap","chalk","scoreColor","delay","Command","ora","fetchSitemap","Command","chalk","ora","delay","Command","chalk","ora","program","Command"]}