@pas7/llm-seo 0.1.6

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/normalize/url.ts","../../src/core/normalize/sort.ts","../../src/core/normalize/text.ts","../../src/core/canonical/locale.ts","../../src/core/canonical/canonical-from-manifest.ts","../../src/core/generate/llms-txt.ts","../../src/core/generate/llms-full-txt.ts","../../src/core/generate/citations.ts","../../src/core/check/issues.ts","../../src/core/check/rules-linter.ts","../../src/core/check/checker.ts"],"names":["getHubLabel","formatHubLabel"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * URL normalization utilities for deterministic SEO processing.\n */\n\n/**\n * Options for URL normalization.\n */\nexport interface NormalizeUrlOptions {\n /** Base URL e.g., \"https://example.com\" */\n baseUrl: string;\n /** Path e.g., \"/blog/my-post\" */\n path: string;\n /** Trailing slash policy */\n trailingSlash: 'always' | 'never' | 'preserve';\n /** Strip query string (default: true) */\n stripQuery?: boolean;\n /** Strip hash/fragment (default: true) */\n stripHash?: boolean;\n}\n\n/**\n * Normalizes a path by removing double slashes and normalizing dots.\n * @param path - The path to normalize\n * @param preserveTrailingSlash - Whether to preserve trailing slash (default: false)\n * @returns The normalized path\n */\nexport function normalizePath(path: string, preserveTrailingSlash = false): string {\n // Handle empty path\n if (!path || path === '/') {\n return '/';\n }\n\n // Track if original path had trailing slash\n const hadTrailingSlash = path.endsWith('/') && path !== '/';\n\n // Ensure path starts with /\n let normalized = path.startsWith('/') ? path : `/${path}`;\n\n // Collapse multiple consecutive slashes into one\n normalized = normalized.replace(/\\/{2,}/g, '/');\n\n // Handle . and .. segments\n const segments: string[] = [];\n const parts = normalized.split('/');\n\n for (const part of parts) {\n if (part === '.' || part === '') {\n // Skip current directory references and empty parts\n continue;\n } else if (part === '..') {\n // Go up one directory\n if (segments.length > 0) {\n segments.pop();\n }\n } else {\n segments.push(part);\n }\n }\n\n // Reconstruct path\n let result = '/' + segments.join('/');\n \n // Restore trailing slash if needed\n if (preserveTrailingSlash && hadTrailingSlash && result !== '/') {\n result += '/';\n }\n \n return result;\n}\n\n/**\n * Joins URL parts safely, handling slashes between parts.\n * @param parts - URL parts to join\n * @returns Joined path string\n */\nexport function joinUrlParts(...parts: string[]): string {\n if (parts.length === 0) {\n return '/';\n }\n\n // Filter out empty parts\n const filteredParts = parts.filter((part) => part.length > 0);\n\n if (filteredParts.length === 0) {\n return '/';\n }\n\n // Join parts, ensuring single slashes between them\n const joined = filteredParts\n .map((part) => {\n // Remove leading slash from all parts\n let p = part.replace(/^\\/+/, '');\n // Remove trailing slash from all parts except we'll add at the end if needed\n p = p.replace(/\\/+$/, '');\n return p;\n })\n .filter((p) => p.length > 0)\n .join('/');\n\n return joined.length > 0 ? `/${joined}` : '/';\n}\n\n/**\n * Validates that a URL is absolute with http/https protocol.\n * @param url - The URL string to validate\n * @returns True if the URL is a valid absolute http/https URL\n */\nexport function isValidAbsoluteUrl(url: string): boolean {\n if (!url || typeof url !== 'string') {\n return false;\n }\n\n try {\n const parsed = new URL(url);\n return parsed.protocol === 'http:' || parsed.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\n/**\n * Normalizes URL according to policy:\n * - No // in path (collapse to single /)\n * - Strip query and hash by default\n * - Apply trailing slash policy\n * - Lowercase hostname\n * - Remove default ports (80, 443)\n * @param options - Normalization options\n * @returns The normalized URL string\n */\nexport function normalizeUrl(options: NormalizeUrlOptions): string {\n const { baseUrl, path, trailingSlash, stripQuery = true, stripHash = true } = options;\n\n // Parse base URL\n let parsedBase: URL;\n try {\n parsedBase = new URL(baseUrl);\n } catch {\n throw new TypeError(`Invalid baseUrl: ${baseUrl}`);\n }\n\n // Normalize the path with trailing slash preservation flag\n const shouldPreserveTrailingSlash = trailingSlash === 'preserve';\n const normalizedPath = normalizePath(path, shouldPreserveTrailingSlash);\n\n // Apply trailing slash policy\n let finalPath = normalizedPath;\n if (trailingSlash === 'always') {\n // Always add trailing slash (except for root which already has it)\n if (!finalPath.endsWith('/')) {\n finalPath = `${finalPath}/`;\n }\n } else if (trailingSlash === 'never') {\n // Remove trailing slash (except for root)\n if (finalPath !== '/' && finalPath.endsWith('/')) {\n finalPath = finalPath.slice(0, -1);\n }\n }\n // 'preserve' - already handled by normalizePath\n\n // Build the full URL\n const protocol = parsedBase.protocol.toLowerCase();\n let hostname = parsedBase.hostname.toLowerCase();\n\n // Handle port - remove default ports\n let port = parsedBase.port;\n if (port) {\n const isDefaultPort =\n (protocol === 'http:' && port === '80') ||\n (protocol === 'https:' && port === '443');\n if (!isDefaultPort) {\n hostname = `${hostname}:${port}`;\n }\n }\n\n // Build the final URL\n let fullUrl = `${protocol}//${hostname}${finalPath}`;\n\n // Add query string if not stripped\n if (!stripQuery && parsedBase.search) {\n fullUrl += parsedBase.search;\n }\n\n // Add hash if not stripped\n if (!stripHash && parsedBase.hash) {\n fullUrl += parsedBase.hash;\n }\n\n return fullUrl;\n}\n\n/**\n * Sorts URLs deterministically for consistent output ordering.\n * @param urls - Array of URLs to sort\n * @returns Sorted array of URLs\n */\nexport function sortUrls(urls: readonly string[]): string[] {\n return [...urls].sort((a, b) => a.localeCompare(b));\n}\n","/**\n * Deterministic sorting utilities for SEO artifacts.\n */\n\n/**\n * Comparator function type for sorting operations.\n */\nexport type Comparator<T> = (a: T, b: T) => number;\n\n/**\n * Creates a deterministic string comparator for consistent ordering.\n * Uses localeCompare with specific locale for reproducibility.\n * @param a - First string to compare\n * @param b - Second string to compare\n * @returns Negative if a < b, positive if a > b, zero if equal\n */\nexport function compareStrings(a: string, b: string): number {\n return a.localeCompare(b, 'en', { sensitivity: 'case', numeric: true });\n}\n\n/**\n * Sorts an array of strings deterministically.\n * @param items - Array of strings to sort\n * @returns New sorted array\n */\nexport function sortStrings(items: readonly string[]): string[] {\n return [...items].sort(compareStrings);\n}\n\n/**\n * Sorts an array of objects by a string key deterministically.\n * @param items - Array of objects to sort\n * @param keyFn - Function to extract the comparison key\n * @returns New sorted array\n */\nexport function sortBy<T>(items: readonly T[], keyFn: (item: T) => string): T[] {\n return [...items].sort((a, b) => compareStrings(keyFn(a), keyFn(b)));\n}\n\n/**\n * Sorts strings in a deterministic way (localeCompare with numeric).\n * Alias for sortStrings for API consistency.\n * @param items - Array of strings to sort\n * @returns New sorted array\n */\nexport function stableSortStrings(items: string[]): string[] {\n return [...items].sort((a, b) => a.localeCompare(b, 'en', { sensitivity: 'case', numeric: true }));\n}\n\n/**\n * Sorts objects by key in a deterministic way.\n * @param items - Array of objects to sort\n * @param keyFn - Function to extract the comparison key\n * @returns New sorted array\n */\nexport function stableSortBy<T>(items: T[], keyFn: (item: T) => string): T[] {\n return [...items].sort((a, b) => {\n const keyA = keyFn(a);\n const keyB = keyFn(b);\n return keyA.localeCompare(keyB, 'en', { sensitivity: 'case', numeric: true });\n });\n}\n\n/**\n * Counts the number of path segments in a URL.\n * @param url - The URL to count segments for\n * @returns Number of path segments\n */\nfunction countPathSegments(url: string): number {\n try {\n const parsed = new URL(url);\n const path = parsed.pathname.replace(/^\\/+/, '').replace(/\\/+$/, '');\n if (!path) return 0;\n return path.split('/').length;\n } catch {\n // If not a valid URL, count slashes in the string\n const cleaned = url.replace(/^\\/+/, '').replace(/\\/+$/, '');\n if (!cleaned) return 0;\n return cleaned.split('/').length;\n }\n}\n\n/**\n * Sorts URLs by path segments (shorter first, then alphabetically).\n * This ensures deterministic ordering with root paths first.\n * @param urls - Array of URLs to sort\n * @returns New sorted array\n */\nexport function sortUrlsByPath(urls: string[]): string[] {\n return [...urls].sort((a, b) => {\n const segmentsA = countPathSegments(a);\n const segmentsB = countPathSegments(b);\n\n // First sort by number of segments (shorter paths first)\n if (segmentsA !== segmentsB) {\n return segmentsA - segmentsB;\n }\n\n // Then sort alphabetically\n return a.localeCompare(b, 'en', { sensitivity: 'case', numeric: true });\n });\n}\n","/**\n * Text normalization utilities for deterministic SEO processing.\n */\n\n/**\n * Normalizes whitespace in text by collapsing multiple spaces and trimming.\n * @param text - The text to normalize\n * @returns Normalized text with single spaces\n */\nexport function normalizeWhitespace(text: string): string {\n return text.replace(/\\s+/g, ' ').trim();\n}\n\n/**\n * Normalizes line endings to the specified format.\n * @param text - The text to normalize\n * @param lineEndings - Target line endings format ('lf' or 'crlf')\n * @returns Text with normalized line endings\n */\nexport function normalizeLineEndings(text: string, lineEndings: 'lf' | 'crlf'): string {\n // First normalize all line endings to \\n\n const normalized = text.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\n // Then convert to target format\n return lineEndings === 'crlf' ? normalized.replace(/\\n/g, '\\r\\n') : normalized;\n}\n\n/**\n * Normalizes whitespace in lines - trims trailing whitespace and removes multiple consecutive spaces.\n * @param text - The text to normalize\n * @returns Text with normalized line whitespace\n */\nexport function normalizeLineWhitespace(text: string): string {\n const lines = text.split(/\\r?\\n/);\n return lines\n .map((line) => line.trimEnd().replace(/[ \\t]+/g, (match) => ' '.repeat(match.length === 0 ? 0 : match.length)))\n .map((line) => line.replace(/ +/g, ' '))\n .join('\\n');\n}\n\n/**\n * Normalizes text for use in SEO meta descriptions or titles.\n * Collapses whitespace and truncates to a maximum length.\n * @param text - The text to normalize\n * @param maxLength - Maximum allowed length\n * @returns Normalized text\n */\nexport function normalizeSeoText(text: string, maxLength: number): string {\n const normalized = normalizeWhitespace(text);\n if (normalized.length <= maxLength) {\n return normalized;\n }\n // Truncate at word boundary\n const truncated = normalized.slice(0, maxLength);\n const lastSpace = truncated.lastIndexOf(' ');\n return lastSpace > 0 ? `${truncated.slice(0, lastSpace)}…` : `${truncated.slice(0, -1)}…`;\n}\n","/**\n * Locale handling utilities for canonical URL generation.\n */\n\nimport type { ManifestItem } from '../../schema/manifest.schema.js';\nimport { stableSortStrings } from '../normalize/sort.js';\n\n/**\n * Represents a locale configuration for a site.\n */\nexport interface LocaleConfig {\n /** Default locale code (e.g., 'en') */\n default: string;\n /** Supported locale codes */\n supported: readonly string[];\n /** URL strategy for locales */\n strategy: 'subdirectory' | 'subdomain' | 'domain';\n}\n\n/**\n * Options for selecting canonical locale.\n */\nexport interface SelectCanonicalLocaleOptions {\n /** Default locale code (e.g., 'en') */\n defaultLocale: string;\n /** Available locale codes for the item */\n availableLocales: string[];\n}\n\n/**\n * Selects canonical locale using deterministic algorithm:\n * 1. If defaultLocale is in availableLocales → return defaultLocale\n * 2. Otherwise, sort availableLocales and return first\n * 3. If no locales available → return null\n * @param options - Selection options\n * @returns The canonical locale or null if none available\n */\nexport function selectCanonicalLocale(options: SelectCanonicalLocaleOptions): string | null {\n const { defaultLocale, availableLocales } = options;\n\n // Handle empty/null cases\n if (!availableLocales || availableLocales.length === 0) {\n return null;\n }\n\n // Filter out any null/undefined/empty values\n const validLocales = availableLocales.filter(\n (locale): locale is string => typeof locale === 'string' && locale.length > 0\n );\n\n if (validLocales.length === 0) {\n return null;\n }\n\n // If defaultLocale is available, use it\n if (defaultLocale && validLocales.includes(defaultLocale)) {\n return defaultLocale;\n }\n\n // Otherwise, sort and return first (deterministic)\n const sorted = stableSortStrings(validLocales);\n return sorted[0] ?? null;\n}\n\n/**\n * Determines if a locale is available for an item.\n * @param locale - The locale to check\n * @param availableLocales - Array of available locales\n * @returns True if the locale is available\n */\nexport function isLocaleAvailable(locale: string, availableLocales: string[]): boolean {\n if (!locale || !availableLocales || availableLocales.length === 0) {\n return false;\n }\n return availableLocales.includes(locale);\n}\n\n/**\n * Gets all unique locales from manifest items.\n * @param items - Array of manifest items\n * @returns Array of unique locale codes\n */\nexport function extractAllLocales(items: ManifestItem[]): string[] {\n const localeSet = new Set<string>();\n\n for (const item of items) {\n if (item.locales && Array.isArray(item.locales)) {\n for (const locale of item.locales) {\n if (typeof locale === 'string' && locale.length > 0) {\n localeSet.add(locale);\n }\n }\n }\n }\n\n return stableSortStrings([...localeSet]);\n}\n\n/**\n * Generates locale-prefixed path.\n * @param path - The base path\n * @param locale - The locale code\n * @param config - Locale configuration\n * @returns Path with locale prefix if applicable\n */\nexport function localizePath(\n path: string,\n locale: string,\n config: LocaleConfig\n): string {\n const normalizedPath = path.startsWith('/') ? path : `/${path}`;\n \n // Default locale may not need prefix\n if (locale === config.default && config.strategy === 'subdirectory') {\n return normalizedPath;\n }\n \n if (config.strategy === 'subdirectory') {\n return `/${locale}${normalizedPath === '/' ? '' : normalizedPath}`;\n }\n \n return normalizedPath;\n}\n\n/**\n * Extracts locale from a path.\n * @param path - The path to extract locale from\n * @param config - Locale configuration\n * @returns Tuple of [locale, pathWithoutLocale]\n */\nexport function extractLocaleFromPath(\n path: string,\n config: LocaleConfig\n): readonly [string, string] {\n if (config.strategy !== 'subdirectory') {\n return [config.default, path];\n }\n \n const match = path.match(/^\\/([a-z]{2}(?:-[A-Z]{2})?)(\\/|$)/);\n \n if (match?.[1] && config.supported.includes(match[1])) {\n const locale = match[1];\n const remainingPath = path.slice(locale.length + 1) || '/';\n return [locale, remainingPath] as const;\n }\n \n return [config.default, path];\n}\n\n/**\n * Generates alternate locale URLs for a page.\n * @param baseUrl - Base URL of the site\n * @param path - Page path\n * @param config - Locale configuration\n * @returns Map of locale to full URL\n */\nexport function generateAlternateUrls(\n baseUrl: string,\n path: string,\n config: LocaleConfig\n): Map<string, string> {\n const urlMap = new Map<string, string>();\n \n for (const locale of config.supported) {\n const localePath = localizePath(path, locale, config);\n const fullUrl = `${baseUrl}${localePath}`;\n urlMap.set(locale, fullUrl);\n }\n \n return urlMap;\n}\n","/**\n * Canonical URL generation from site manifests.\n */\n\nimport type { SiteManifest, ManifestItem } from '../../schema/manifest.schema.js';\nimport { normalizeUrl, joinUrlParts } from '../normalize/url.js';\nimport { sortUrlsByPath } from '../normalize/sort.js';\nimport { selectCanonicalLocale } from './locale.js';\n\n/**\n * Options for canonical URL generation.\n */\nexport interface CanonicalOptions {\n /** Whether to include trailing slash (default: false) */\n trailingSlash?: boolean;\n /** Whether to use lowercase (default: true) */\n lowercase?: boolean;\n}\n\n/**\n * Locale strategy for URL generation.\n */\nexport type LocaleStrategy = 'prefix' | 'subdomain' | 'none';\n\n/**\n * Trailing slash policy.\n */\nexport type TrailingSlashPolicy = 'always' | 'never' | 'preserve';\n\n/**\n * Options for creating canonical URLs from manifest.\n */\nexport interface CreateCanonicalUrlsOptions {\n /** Array of manifest items */\n items: ManifestItem[];\n /** Base URL e.g., \"https://example.com\" */\n baseUrl: string;\n /** Route prefix e.g., \"/blog\" for blog posts */\n routePrefix?: string;\n /** Default locale code */\n defaultLocale: string;\n /** Trailing slash policy */\n trailingSlash: TrailingSlashPolicy;\n /** Locale URL strategy */\n localeStrategy: LocaleStrategy;\n}\n\n/**\n * Generates a canonical URL for a given path from the site manifest.\n * @param manifest - The site manifest containing base URL information\n * @param path - The path to generate canonical URL for\n * @param options - Canonical URL options\n * @returns The canonical URL\n */\nexport function generateCanonicalUrl(\n manifest: SiteManifest,\n path: string,\n options: CanonicalOptions = {}\n): string {\n const { trailingSlash = false, lowercase = true } = options;\n const basePath = path.startsWith('/') ? path : `/${path}`;\n const normalizedPath = trailingSlash\n ? `${basePath}${basePath.endsWith('/') ? '' : '/'}`\n : basePath.replace(/\\/+$/, '') || '/';\n const fullUrl = `${manifest.baseUrl}${normalizedPath}`;\n return lowercase ? fullUrl.toLowerCase() : fullUrl;\n}\n\n/**\n * Extracts all canonical URLs from a site manifest.\n * @param manifest - The site manifest\n * @param options - Canonical URL options\n * @returns Array of canonical URLs\n */\nexport function extractCanonicalUrls(\n manifest: SiteManifest,\n options: CanonicalOptions = {}\n): string[] {\n return manifest.pages.map((page) => generateCanonicalUrl(manifest, page.path, options));\n}\n\n/**\n * Deduplicates URLs by converting to Set and back.\n * @param urls - Array of URLs to deduplicate\n * @returns Array of unique URLs\n */\nexport function dedupeUrls(urls: string[]): string[] {\n return [...new Set(urls)];\n}\n\n/**\n * Builds locale prefix based on strategy.\n * @param locale - The locale code\n * @param strategy - The locale strategy\n * @param defaultLocale - The default locale code\n * @returns Locale prefix string or empty string\n */\nfunction buildLocalePrefix(\n locale: string,\n strategy: LocaleStrategy,\n defaultLocale: string\n): string {\n // No prefix for 'none' strategy\n if (strategy === 'none') {\n return '';\n }\n\n // Subdomain strategy doesn't add path prefix\n if (strategy === 'subdomain') {\n return '';\n }\n\n // For prefix strategy, don't prefix default locale\n if (strategy === 'prefix' && locale === defaultLocale) {\n return '';\n }\n\n return `/${locale}`;\n}\n\n/**\n * Builds base URL with subdomain if needed.\n * @param baseUrl - The base URL\n * @param locale - The locale code\n * @param strategy - The locale strategy\n * @param defaultLocale - The default locale code\n * @returns Base URL with subdomain if applicable\n */\nfunction buildBaseUrlWithSubdomain(\n baseUrl: string,\n locale: string,\n strategy: LocaleStrategy,\n defaultLocale: string\n): string {\n if (strategy !== 'subdomain' || locale === defaultLocale) {\n return baseUrl;\n }\n\n try {\n const parsed = new URL(baseUrl);\n return `${parsed.protocol}//${locale}.${parsed.host}`;\n } catch {\n return baseUrl;\n }\n}\n\n/**\n * Creates a single canonical URL for a manifest item.\n * @param item - The manifest item\n * @param options - Options for URL creation (without items array)\n * @returns The canonical URL string\n */\nexport function createCanonicalUrlForItem(\n item: ManifestItem,\n options: Omit<CreateCanonicalUrlsOptions, 'items'>\n): string {\n const { baseUrl, routePrefix, defaultLocale, trailingSlash, localeStrategy } = options;\n\n // If item has canonicalOverride, use it directly\n if (item.canonicalOverride && typeof item.canonicalOverride === 'string') {\n return item.canonicalOverride;\n }\n\n // Select canonical locale for this item\n const availableLocales = item.locales ?? [defaultLocale];\n const canonicalLocale = selectCanonicalLocale({\n defaultLocale,\n availableLocales,\n });\n\n // If no locale available, use default\n const locale = canonicalLocale ?? defaultLocale;\n\n // Build URL parts\n const localePrefix = buildLocalePrefix(locale, localeStrategy, defaultLocale);\n const effectiveBaseUrl = buildBaseUrlWithSubdomain(baseUrl, locale, localeStrategy, defaultLocale);\n\n // Build the path\n const parts: string[] = [];\n if (localePrefix) {\n parts.push(localePrefix);\n }\n if (routePrefix) {\n parts.push(routePrefix);\n }\n parts.push(item.slug);\n\n const fullPath = joinUrlParts(...parts);\n\n // Normalize the URL\n return normalizeUrl({\n baseUrl: effectiveBaseUrl,\n path: fullPath,\n trailingSlash,\n stripQuery: true,\n stripHash: true,\n });\n}\n\n/**\n * Creates canonical URLs from manifest items:\n * 1. For each item, select canonical locale\n * 2. Build URL: baseUrl + localePrefix (if strategy=prefix) + routePrefix + slug\n * 3. Apply trailing slash policy\n * 4. Normalize URL\n * 5. Dedupe (by URL string)\n * 6. Sort stably\n * @param options - Options for URL creation\n * @returns Sorted array of canonical URLs\n */\nexport function createCanonicalUrlsFromManifest(options: CreateCanonicalUrlsOptions): string[] {\n const { items } = options;\n\n // Handle empty items\n if (!items || items.length === 0) {\n return [];\n }\n\n // Create URLs for each item\n const urls = items.map((item) => createCanonicalUrlForItem(item, options));\n\n // Deduplicate\n const deduped = dedupeUrls(urls);\n\n // Sort stably by path\n return sortUrlsByPath(deduped);\n}\n","/**\n * llms.txt generator for LLM-optimized site documentation.\n * Generates a short brand profile with sections, URLs, policies, and contact info.\n */\n\nimport type { LlmsSeoConfig } from '../../schema/config.schema.js';\nimport { sortStrings } from '../normalize/sort.js';\nimport { normalizeLineEndings, normalizeLineWhitespace } from '../normalize/text.js';\n\n/**\n * Options for llms.txt generation.\n */\nexport interface CreateLlmsTxtOptions {\n /** Full LLM SEO configuration */\n config: LlmsSeoConfig;\n /** Pre-built canonical URLs from manifests */\n canonicalUrls: string[];\n}\n\n/**\n * Result of llms.txt generation.\n */\nexport interface CreateLlmsTxtResult {\n /** Generated llms.txt content */\n content: string;\n /** Size in bytes */\n byteSize: number;\n /** Number of lines */\n lineCount: number;\n}\n\n/**\n * Creates llms.txt content with deterministic output.\n * - Deterministic ordering of all sections\n * - Handles missing optional fields gracefully\n * - EOL controlled by config.format.lineEndings\n * @param options - Generation options\n * @returns Generated content with metadata\n */\nexport function createLlmsTxt(options: CreateLlmsTxtOptions): CreateLlmsTxtResult {\n const { config, canonicalUrls } = options;\n const lineEndings = config.format?.lineEndings ?? 'lf';\n const lines: string[] = [];\n\n // Header: Brand name and tagline\n lines.push(`# ${config.brand.name}`);\n lines.push('');\n\n if (config.brand.tagline) {\n lines.push(`> ${config.brand.tagline}`);\n lines.push('');\n }\n\n // Brand description\n if (config.brand.description) {\n lines.push(config.brand.description);\n lines.push('');\n }\n\n // Sections\n const hubs = config.sections?.hubs ?? [];\n if (hubs.length > 0) {\n lines.push('## Sections');\n lines.push('');\n const sortedHubs = sortStrings(hubs);\n for (const hub of sortedHubs) {\n const hubLabel = getHubLabel(hub);\n lines.push(`- [${hub}](${hub}) - ${hubLabel}`);\n }\n lines.push('');\n }\n\n // URLs\n if (canonicalUrls.length > 0) {\n lines.push('## URLs');\n lines.push('');\n const sortedUrls = sortStrings(canonicalUrls);\n for (const url of sortedUrls) {\n lines.push(`- ${url}`);\n }\n lines.push('');\n }\n\n // Policies\n const hasPolicies = config.policy?.geoPolicy || config.policy?.citationRules || config.policy?.restrictedClaims;\n if (hasPolicies) {\n lines.push('## Policies');\n lines.push('');\n\n if (config.policy?.geoPolicy) {\n lines.push(`- GEO: ${config.policy.geoPolicy}`);\n }\n\n if (config.policy?.citationRules) {\n lines.push(`- Citations: ${config.policy.citationRules}`);\n }\n\n if (config.policy?.restrictedClaims) {\n const status = config.policy.restrictedClaims.enable ? 'Enabled' : 'Disabled';\n lines.push(`- Restricted Claims: ${status}`);\n }\n\n lines.push('');\n }\n\n // Contact\n const hasContact = config.contact?.email || config.contact?.social || config.contact?.phone;\n const hasBooking = config.booking?.url;\n if (hasContact || hasBooking) {\n lines.push('## Contact');\n lines.push('');\n\n if (config.contact?.email) {\n lines.push(`- Email: ${config.contact.email}`);\n }\n\n if (config.contact?.phone) {\n lines.push(`- Phone: ${config.contact.phone}`);\n }\n\n if (config.contact?.social) {\n if (config.contact.social.twitter) {\n lines.push(`- Twitter: ${config.contact.social.twitter}`);\n }\n if (config.contact.social.linkedin) {\n lines.push(`- LinkedIn: ${config.contact.social.linkedin}`);\n }\n if (config.contact.social.github) {\n lines.push(`- GitHub: ${config.contact.social.github}`);\n }\n }\n\n if (config.booking?.url) {\n const label = config.booking.label ?? 'Book consultation';\n lines.push(`- Booking: ${config.booking.url} (${label})`);\n }\n\n lines.push('');\n }\n\n // Machine Hints\n const hasMachineHints = config.machineHints?.robots || \n config.machineHints?.sitemap || \n config.machineHints?.llmsTxt || \n config.machineHints?.llmsFullTxt;\n \n if (hasMachineHints) {\n lines.push('## Machine Hints');\n lines.push('');\n\n if (config.machineHints?.robots) {\n lines.push(`- robots.txt: ${config.machineHints.robots}`);\n }\n\n if (config.machineHints?.sitemap) {\n lines.push(`- sitemap.xml: ${config.machineHints.sitemap}`);\n }\n\n if (config.machineHints?.llmsTxt) {\n lines.push(`- llms.txt: ${config.machineHints.llmsTxt}`);\n }\n\n if (config.machineHints?.llmsFullTxt) {\n lines.push(`- llms-full.txt: ${config.machineHints.llmsFullTxt}`);\n }\n\n lines.push('');\n }\n\n // Build final content\n let content = lines.join('\\n');\n \n // Normalize whitespace\n content = normalizeLineWhitespace(content);\n \n // Apply line endings\n content = normalizeLineEndings(content, lineEndings);\n\n // Calculate metadata\n const finalLines = content.split(lineEndings === 'crlf' ? '\\r\\n' : '\\n');\n\n return {\n content,\n byteSize: Buffer.byteLength(content, 'utf-8'),\n lineCount: finalLines.length,\n };\n}\n\n/**\n * Gets a human-readable label for a hub path.\n */\nfunction getHubLabel(hub: string): string {\n const labels: Record<string, string> = {\n '/services': 'Services overview',\n '/blog': 'Blog posts',\n '/projects': 'Our projects',\n '/cases': 'Case studies',\n '/contact': 'Contact us',\n '/about': 'About us',\n '/products': 'Products',\n '/docs': 'Documentation',\n '/faq': 'Frequently asked questions',\n '/pricing': 'Pricing information',\n '/team': 'Our team',\n '/careers': 'Career opportunities',\n '/news': 'News and updates',\n '/resources': 'Resources',\n '/support': 'Support center',\n };\n\n return labels[hub] ?? formatHubLabel(hub);\n}\n\n/**\n * Formats a hub path into a human-readable label.\n */\nfunction formatHubLabel(hub: string): string {\n // Remove leading slash and format\n const clean = hub.replace(/^\\//, '');\n // Replace hyphens and underscores with spaces, capitalize words\n return clean\n .replace(/[-_]/g, ' ')\n .replace(/\\b\\w/g, (char) => char.toUpperCase());\n}\n\n// Legacy exports for backwards compatibility\nexport interface LlmsTxtOptions {\n /** Whether to include optional sections */\n includeOptionalSections?: boolean;\n}\n\n/**\n * @deprecated Use createLlmsTxt instead\n */\nexport function generateLlmsTxt(\n manifest: { baseUrl: string; title: string; description?: string | undefined; pages: Array<{ path: string; title?: string | undefined; description?: string | undefined }> },\n _options?: LlmsTxtOptions\n): string {\n const canonicalUrls = manifest.pages.map((page) => `${manifest.baseUrl}${page.path}`);\n \n const config: LlmsSeoConfig = {\n site: { baseUrl: manifest.baseUrl },\n brand: {\n name: manifest.title,\n locales: ['en'],\n ...(manifest.description && { description: manifest.description }),\n },\n manifests: {},\n output: {\n paths: {\n llmsTxt: 'public/llms.txt',\n llmsFullTxt: 'public/llms-full.txt',\n },\n },\n };\n\n return createLlmsTxt({ config, canonicalUrls }).content;\n}\n","/**\n * llms-full.txt generator with complete context for LLMs.\n * Generates full brand context with all URLs, detailed policies, social/booking, and machine hints.\n */\n\nimport type { LlmsSeoConfig } from '../../schema/config.schema.js';\nimport type { ManifestItem } from '../../schema/manifest.schema.js';\nimport { sortStrings, sortBy } from '../normalize/sort.js';\nimport { normalizeLineEndings, normalizeLineWhitespace } from '../normalize/text.js';\n\n/**\n * Options for llms-full.txt generation.\n */\nexport interface CreateLlmsFullTxtOptions {\n /** Full LLM SEO configuration */\n config: LlmsSeoConfig;\n /** Pre-built canonical URLs from manifests */\n canonicalUrls: string[];\n /** Manifest items for detailed URL listing */\n manifestItems: ManifestItem[];\n}\n\n/**\n * Result of llms-full.txt generation.\n */\nexport interface CreateLlmsFullTxtResult {\n /** Generated llms-full.txt content */\n content: string;\n /** Size in bytes */\n byteSize: number;\n /** Number of lines */\n lineCount: number;\n}\n\n/**\n * Creates llms-full.txt content with deterministic output.\n * - Complete context with all URLs\n * - Detailed policy sections\n * - Social and booking info\n * - EOL controlled by config.format.lineEndings\n * @param options - Generation options\n * @returns Generated content with metadata\n */\nexport function createLlmsFullTxt(options: CreateLlmsFullTxtOptions): CreateLlmsFullTxtResult {\n const { config, canonicalUrls, manifestItems } = options;\n const lineEndings = config.format?.lineEndings ?? 'lf';\n const lines: string[] = [];\n\n // Header\n lines.push(`# ${config.brand.name} - Full LLM Context`);\n lines.push('');\n\n if (config.brand.tagline) {\n lines.push(`> ${config.brand.tagline}`);\n lines.push('');\n }\n\n // Brand description\n if (config.brand.description) {\n lines.push(config.brand.description);\n lines.push('');\n }\n\n // Organization and locales\n if (config.brand.org) {\n lines.push(`Organization: ${config.brand.org}`);\n }\n lines.push(`Locales: ${config.brand.locales.join(', ')}`);\n lines.push('');\n\n // All Canonical URLs\n if (canonicalUrls.length > 0) {\n lines.push('## All Canonical URLs');\n lines.push('');\n const sortedUrls = sortStrings(canonicalUrls);\n for (const url of sortedUrls) {\n lines.push(`- ${url}`);\n }\n lines.push('');\n }\n\n // Policies\n const hasPolicies = config.policy?.geoPolicy || config.policy?.citationRules || config.policy?.restrictedClaims;\n if (hasPolicies) {\n lines.push('## Policies');\n lines.push('');\n\n // GEO Policy\n if (config.policy?.geoPolicy) {\n lines.push('### GEO Policy');\n lines.push(config.policy.geoPolicy);\n lines.push('');\n }\n\n // Citation Rules\n if (config.policy?.citationRules) {\n lines.push('### Citation Rules');\n lines.push(config.policy.citationRules);\n lines.push('');\n }\n\n // Restricted Claims\n if (config.policy?.restrictedClaims) {\n lines.push('### Restricted Claims');\n const status = config.policy.restrictedClaims.enable ? 'Enabled' : 'Disabled';\n lines.push(`Status: ${status}`);\n \n if (config.policy.restrictedClaims.forbidden && config.policy.restrictedClaims.forbidden.length > 0) {\n lines.push(`Forbidden terms: ${config.policy.restrictedClaims.forbidden.join(', ')}`);\n }\n \n if (config.policy.restrictedClaims.whitelist && config.policy.restrictedClaims.whitelist.length > 0) {\n lines.push(`Exceptions: ${config.policy.restrictedClaims.whitelist.join(', ')}`);\n }\n \n lines.push('');\n }\n }\n\n // Social & Booking\n const hasSocial = config.contact?.social?.twitter || \n config.contact?.social?.linkedin || \n config.contact?.social?.github;\n const hasBooking = config.booking?.url;\n \n if (hasSocial || hasBooking) {\n lines.push('## Social & Booking');\n lines.push('');\n\n if (config.contact?.social?.twitter) {\n lines.push(`- Twitter: ${config.contact.social.twitter}`);\n }\n\n if (config.contact?.social?.linkedin) {\n lines.push(`- LinkedIn: ${config.contact.social.linkedin}`);\n }\n\n if (config.contact?.social?.github) {\n lines.push(`- GitHub: ${config.contact.social.github}`);\n }\n\n if (config.booking?.url) {\n const label = config.booking.label ?? 'Book consultation';\n lines.push(`- Booking: ${config.booking.url} (${label})`);\n }\n\n lines.push('');\n }\n\n // Machine Hints\n const hasMachineHints = config.machineHints?.robots || \n config.machineHints?.sitemap || \n config.machineHints?.llmsTxt || \n config.machineHints?.llmsFullTxt;\n \n if (hasMachineHints) {\n lines.push('## Machine Hints');\n lines.push('');\n\n if (config.machineHints?.robots) {\n lines.push(`- robots.txt: ${config.machineHints.robots}`);\n }\n\n if (config.machineHints?.sitemap) {\n lines.push(`- sitemap.xml: ${config.machineHints.sitemap}`);\n }\n\n if (config.machineHints?.llmsTxt) {\n lines.push(`- llms.txt: ${config.machineHints.llmsTxt}`);\n }\n\n if (config.machineHints?.llmsFullTxt) {\n lines.push(`- llms-full.txt: ${config.machineHints.llmsFullTxt}`);\n }\n\n lines.push('');\n }\n\n // Sitemap\n const hubs = config.sections?.hubs ?? [];\n if (hubs.length > 0 || manifestItems.length > 0) {\n lines.push('## Sitemap');\n lines.push('');\n\n // Add section hubs first\n if (hubs.length > 0) {\n const sortedHubs = sortStrings(hubs);\n for (const hub of sortedHubs) {\n lines.push(`- [${hub}](${hub}) - ${getHubLabel(hub)}`);\n }\n }\n\n // Add all manifest URLs\n if (manifestItems.length > 0) {\n const sortedItems = sortBy(manifestItems, (item) => item.slug);\n for (const item of sortedItems) {\n const url = item.canonicalOverride ?? `${config.site.baseUrl}${item.slug}`;\n const title = item.title ?? item.slug;\n const locales = item.locales?.join(', ') ?? config.brand.locales[0] ?? 'en';\n lines.push(`- [${title}](${url}) (${locales})`);\n }\n }\n\n lines.push('');\n }\n\n // Build final content\n let content = lines.join('\\n');\n \n // Normalize whitespace\n content = normalizeLineWhitespace(content);\n \n // Apply line endings\n content = normalizeLineEndings(content, lineEndings);\n\n // Calculate metadata\n const finalLines = content.split(lineEndings === 'crlf' ? '\\r\\n' : '\\n');\n\n return {\n content,\n byteSize: Buffer.byteLength(content, 'utf-8'),\n lineCount: finalLines.length,\n };\n}\n\n/**\n * Gets a human-readable label for a hub path.\n */\nfunction getHubLabel(hub: string): string {\n const labels: Record<string, string> = {\n '/services': 'Services overview',\n '/blog': 'Blog posts',\n '/projects': 'Our projects',\n '/cases': 'Case studies',\n '/contact': 'Contact us',\n '/about': 'About us',\n '/products': 'Products',\n '/docs': 'Documentation',\n '/faq': 'Frequently asked questions',\n '/pricing': 'Pricing information',\n '/team': 'Our team',\n '/careers': 'Career opportunities',\n '/news': 'News and updates',\n '/resources': 'Resources',\n '/support': 'Support center',\n };\n\n return labels[hub] ?? formatHubLabel(hub);\n}\n\n/**\n * Formats a hub path into a human-readable label.\n */\nfunction formatHubLabel(hub: string): string {\n // Remove leading slash and format\n const clean = hub.replace(/^\\//, '');\n // Replace hyphens and underscores with spaces, capitalize words\n return clean\n .replace(/[-_]/g, ' ')\n .replace(/\\b\\w/g, (char) => char.toUpperCase());\n}\n\n// Legacy exports for backwards compatibility\nexport interface LlmsFullTxtOptions {\n /** Maximum content length per page (0 = no limit) */\n maxContentLength?: number;\n}\n\n/**\n * Generates full page content for llms-full.txt.\n * @deprecated Use createLlmsFullTxt instead\n */\nexport function generatePageContent(\n page: { path: string; title?: string; description?: string; content?: string },\n manifest: { baseUrl: string },\n _options?: LlmsFullTxtOptions\n): string {\n const maxContentLength = _options?.maxContentLength ?? 0;\n const lines: string[] = [];\n const url = `${manifest.baseUrl}${page.path}`;\n lines.push(`## ${page.title ?? page.path}`);\n lines.push(`URL: ${url}`);\n lines.push('');\n \n if (page.description) {\n lines.push(page.description);\n lines.push('');\n }\n \n if (page.content) {\n let content = page.content;\n if (maxContentLength > 0 && content.length > maxContentLength) {\n content = `${content.slice(0, maxContentLength)}...`;\n }\n lines.push(content);\n lines.push('');\n }\n \n return lines.join('\\n');\n}\n\n/**\n /**\n * @deprecated Use createLlmsFullTxt instead\n */\n export function generateLlmsFullTxt(\n manifest: { baseUrl: string; title: string; description?: string | undefined; pages: Array<{ path: string; title?: string | undefined; description?: string | undefined; content?: string | undefined }> },\n _options?: LlmsFullTxtOptions\n ): string {\n const canonicalUrls = manifest.pages.map((page) => `${manifest.baseUrl}${page.path}`);\n const manifestItems: ManifestItem[] = manifest.pages.map((page) => ({\n slug: page.path,\n title: page.title,\n description: page.description,\n }));\n \n const config: LlmsSeoConfig = {\n site: { baseUrl: manifest.baseUrl },\n brand: {\n name: manifest.title,\n locales: ['en'],\n ...(manifest.description && { description: manifest.description }),\n },\n manifests: {},\n output: {\n paths: {\n llmsTxt: 'public/llms.txt',\n llmsFullTxt: 'public/llms-full.txt',\n },\n },\n };\n \n return createLlmsFullTxt({ config, canonicalUrls, manifestItems }).content;\n }","/**\n * Citation generation utilities for LLM-optimized content.\n * Creates machine-readable citations.json for CI validation.\n */\n\nimport type { LlmsSeoConfig } from '../../schema/config.schema.js';\nimport type { ManifestItem } from '../../schema/manifest.schema.js';\n\n/**\n * Citation source entry.\n */\nexport interface CitationSource {\n /** Canonical URL */\n url: string;\n /** Priority (0-100) */\n priority: number;\n /** Section name */\n section: string;\n /** Locale code */\n locale: string;\n /** Publication date (ISO 8601) */\n publishedAt?: string;\n /** Last update date (ISO 8601) */\n updatedAt?: string;\n /** Page title */\n title?: string;\n}\n\n/**\n * Site information in citations.json.\n */\nexport interface CitationsSite {\n /** Base URL */\n baseUrl: string;\n /** Site name */\n name: string;\n}\n\n/**\n * Policy information in citations.json.\n */\nexport interface CitationsPolicy {\n /** Geographic policy */\n geoPolicy?: string;\n /** Citation rules */\n citationRules?: string;\n /** Whether restricted claims are enabled */\n restrictedClaimsEnabled: boolean;\n}\n\n/**\n * Complete citations.json structure.\n */\nexport interface CitationsJson {\n /** Schema version */\n version: string;\n /** Generation timestamp (ISO 8601) */\n generated: string;\n /** Site information */\n site: CitationsSite;\n /** Sorted citation sources */\n sources: CitationSource[];\n /** Policy information */\n policy: CitationsPolicy;\n}\n\n/**\n * Options for citations.json generation.\n */\nexport interface CreateCitationsJsonOptions {\n /** Full LLM SEO configuration */\n config: LlmsSeoConfig;\n /** Manifest items to include */\n manifestItems: ManifestItem[];\n /** Section name for these items */\n sectionName: string;\n /** Optional fixed timestamp for deterministic output (tests) */\n fixedTimestamp?: string;\n}\n\n/**\n * Creates citations.json object with deterministic output.\n * - Sorted by priority (descending), then by URL\n * - Includes all manifest items with their metadata\n * @param options - Generation options\n * @returns Citations JSON object\n */\nexport function createCitationsJson(options: CreateCitationsJsonOptions): CitationsJson {\n const { config, manifestItems, sectionName, fixedTimestamp } = options;\n\n // Build sources from manifest items\n const sources: CitationSource[] = manifestItems.map((item) => {\n const url = item.canonicalOverride ?? `${config.site.baseUrl}${item.slug}`;\n const defaultLocale = config.site.defaultLocale ?? config.brand.locales[0] ?? 'en';\n \n return {\n url,\n priority: item.priority ?? 50,\n section: sectionName,\n locale: item.locales?.[0] ?? defaultLocale,\n ...(item.publishedAt && { publishedAt: item.publishedAt }),\n ...(item.updatedAt && { updatedAt: item.updatedAt }),\n ...(item.title && { title: item.title }),\n };\n });\n\n // Sort by priority (descending), then by URL (ascending)\n const sortedSources = sources.sort((a, b) => {\n // First by priority descending\n if (a.priority !== b.priority) {\n return b.priority - a.priority;\n }\n // Then by URL ascending\n return a.url.localeCompare(b.url, 'en', { sensitivity: 'case', numeric: true });\n });\n\n // Build policy\n const policy: CitationsPolicy = {\n restrictedClaimsEnabled: config.policy?.restrictedClaims?.enable ?? false,\n ...(config.policy?.geoPolicy && { geoPolicy: config.policy.geoPolicy }),\n ...(config.policy?.citationRules && { citationRules: config.policy.citationRules }),\n };\n\n return {\n version: '1.0',\n generated: fixedTimestamp ?? new Date().toISOString(),\n site: {\n baseUrl: config.site.baseUrl,\n name: config.brand.name,\n },\n sources: sortedSources,\n policy,\n };\n}\n\n/**\n * Creates citations.json as a formatted string.\n * @param options - Generation options\n * @returns JSON string with 2-space indentation\n */\nexport function createCitationsJsonString(options: CreateCitationsJsonOptions): string {\n const citations = createCitationsJson(options);\n return JSON.stringify(citations, null, 2);\n}\n\n// Legacy exports for backwards compatibility\n\n/**\n * Represents a citation for a page.\n * @deprecated Use CitationSource instead\n */\nexport interface Citation {\n /** The URL being cited */\n url: string;\n /** The title of the cited page */\n title: string;\n /** Optional description */\n description?: string;\n}\n\n/**\n * Generates a citation object for a page.\n * @deprecated Use createCitationsJson instead\n */\nexport function createCitation(\n page: { path: string; title?: string; description?: string },\n manifest: { baseUrl: string }\n): Citation {\n const citation: Citation = {\n url: `${manifest.baseUrl}${page.path}`,\n title: page.title ?? page.path,\n };\n \n if (page.description) {\n citation.description = page.description;\n }\n \n return citation;\n}\n\n/**\n * Generates a citation in markdown format.\n * @deprecated\n */\nexport function citationToMarkdown(citation: Citation): string {\n if (citation.description) {\n return `[${citation.title}](${citation.url}) - ${citation.description}`;\n }\n return `[${citation.title}](${citation.url})`;\n}\n\n/**\n * Generates a citation in JSON-LD format.\n * @deprecated\n */\nexport function citationToJsonLd(citation: Citation): Record<string, string> {\n const jsonLd: Record<string, string> = {\n '@type': 'WebPage',\n name: citation.title,\n url: citation.url,\n };\n \n if (citation.description) {\n jsonLd.description = citation.description;\n }\n \n return jsonLd;\n}\n\n/**\n * Generates a reference list from multiple citations.\n * @deprecated\n */\nexport function generateReferenceList(citations: readonly Citation[]): string {\n const lines: string[] = ['## References', ''];\n \n for (let i = 0; i < citations.length; i++) {\n const citation = citations[i];\n if (citation) {\n const num = i + 1;\n lines.push(`${num}. ${citationToMarkdown(citation)}`);\n }\n }\n \n lines.push('');\n return lines.join('\\n');\n}\n","/**\n * Issue types and utilities for SEO checking.\n */\n\n/**\n * Severity levels for issues.\n */\nexport type IssueSeverity = 'error' | 'warning' | 'info';\n\n/**\n * Categories of SEO issues.\n */\nexport type IssueCategory = \n | 'content'\n | 'structure'\n | 'accessibility'\n | 'performance'\n | 'metadata';\n\n/**\n * Represents a check issue found during file verification.\n */\nexport interface CheckIssue {\n /** File path or config path */\n path: string;\n /** Issue code e.g., 'file_mismatch', 'missing_file' */\n code: CheckIssueCode;\n /** Human-readable message describing the issue */\n message: string;\n /** Severity of the issue */\n severity: IssueSeverity;\n /** Optional line number where the issue was found */\n line?: number;\n /** Context snippet (first N lines or relevant content) */\n context?: string;\n}\n\n/**\n * Issue codes for check issues.\n */\nexport type CheckIssueCode =\n // File issues\n | 'file_missing'\n | 'file_mismatch'\n | 'file_empty'\n // Content issues\n | 'forbidden_term'\n | 'empty_section'\n | 'duplicate_url'\n | 'invalid_url'\n // Config issues\n | 'config_invalid';\n\n/**\n * Legacy Issue interface for backwards compatibility.\n */\nexport interface Issue {\n /** Unique identifier for the issue type */\n id: string;\n /** The page or resource this issue applies to */\n pageId: string;\n /** Severity of the issue */\n severity: IssueSeverity;\n /** Human-readable message describing the issue */\n message: string;\n /** Optional category for grouping */\n category?: IssueCategory;\n /** Optional suggestion for fixing the issue */\n suggestion?: string;\n /** Optional line number where the issue was found */\n line?: number;\n /** Optional column number where the issue was found */\n column?: number;\n}\n\n/**\n * Creates a CheckIssue.\n * @param severity - Issue severity\n * @param code - Issue code\n * @param message - Human-readable message\n * @param path - File path (optional, defaults to empty string)\n * @param context - Context snippet (optional)\n * @returns A CheckIssue object\n */\nexport function createCheckIssue(\n severity: IssueSeverity,\n code: CheckIssueCode,\n message: string,\n path = '',\n context?: string\n): CheckIssue {\n const issue: CheckIssue = {\n path,\n code,\n message,\n severity,\n };\n \n if (context !== undefined) {\n issue.context = context;\n }\n \n return issue;\n}\n\n/**\n * Creates a legacy Issue with default values.\n * @param overrides - Partial issue to override defaults\n * @returns A complete issue object\n */\nexport function createIssue(overrides: Partial<Issue> & Pick<Issue, 'id' | 'pageId' | 'severity' | 'message'>): Issue {\n return {\n category: 'content',\n ...overrides,\n };\n}\n\n/**\n * Converts legacy Issue to CheckIssue.\n * @param issue - Legacy issue\n * @param path - File path\n * @returns CheckIssue object\n */\nexport function issueToCheckIssue(issue: Issue, path: string): CheckIssue {\n const checkIssue: CheckIssue = {\n path,\n code: issue.id as CheckIssueCode,\n message: issue.message,\n severity: issue.severity,\n };\n \n if (issue.line !== undefined) {\n checkIssue.line = issue.line;\n }\n \n if (issue.suggestion !== undefined) {\n checkIssue.context = issue.suggestion;\n }\n \n return checkIssue;\n}\n\n/**\n * Groups check issues by severity.\n * @param issues - List of issues\n * @returns Map of severity to issues\n */\nexport function groupCheckIssuesBySeverity(issues: readonly CheckIssue[]): Map<IssueSeverity, CheckIssue[]> {\n const grouped = new Map<IssueSeverity, CheckIssue[]>();\n \n for (const issue of issues) {\n const existing = grouped.get(issue.severity) ?? [];\n existing.push(issue);\n grouped.set(issue.severity, existing);\n }\n \n return grouped;\n}\n\n/**\n * Groups issues by severity (legacy).\n * @param issues - List of issues\n * @returns Map of severity to issues\n */\nexport function groupBySeverity(issues: readonly Issue[]): Map<IssueSeverity, Issue[]> {\n const grouped = new Map<IssueSeverity, Issue[]>();\n \n for (const issue of issues) {\n const existing = grouped.get(issue.severity) ?? [];\n existing.push(issue);\n grouped.set(issue.severity, existing);\n }\n \n return grouped;\n}\n\n/**\n * Groups issues by page.\n * @param issues - List of issues\n * @returns Map of pageId to issues\n */\nexport function groupByPage(issues: readonly Issue[]): Map<string, Issue[]> {\n const grouped = new Map<string, Issue[]>();\n \n for (const issue of issues) {\n const existing = grouped.get(issue.pageId) ?? [];\n existing.push(issue);\n grouped.set(issue.pageId, existing);\n }\n \n return grouped;\n}\n\n/**\n * Filters issues by minimum severity.\n * @param issues - List of issues\n * @param minSeverity - Minimum severity to include\n * @returns Filtered list of issues\n */\nexport function filterBySeverity(issues: readonly Issue[], minSeverity: IssueSeverity): Issue[] {\n const severityOrder: IssueSeverity[] = ['error', 'warning', 'info'];\n const minIndex = severityOrder.indexOf(minSeverity);\n \n return issues.filter((issue) => {\n const issueIndex = severityOrder.indexOf(issue.severity);\n return issueIndex <= minIndex;\n });\n}\n\n/**\n * Counts issues by severity.\n * @param issues - List of check issues\n * @returns Counts for each severity level\n */\nexport function countSeverities(issues: readonly CheckIssue[]): Record<IssueSeverity, number> {\n const counts: Record<IssueSeverity, number> = {\n error: 0,\n warning: 0,\n info: 0,\n };\n \n for (const issue of issues) {\n counts[issue.severity]++;\n }\n \n return counts;\n}\n\n/**\n * Formats a check issue for display.\n * @param issue - Check issue to format\n * @returns Formatted string\n */\nexport function formatCheckIssue(issue: CheckIssue): string {\n const severityLabel = issue.severity.charAt(0).toUpperCase() + issue.severity.slice(1);\n let output = `${severityLabel}: ${issue.code}\\n`;\n output += ` File: ${issue.path}\\n`;\n \n if (issue.line !== undefined) {\n output += ` Line: ${issue.line}\\n`;\n }\n \n output += ` Message: ${issue.message}`;\n \n if (issue.context) {\n output += `\\n Context: \"${issue.context}\"`;\n }\n \n return output;\n}\n\n/**\n * Formats multiple check issues for display.\n * @param issues - Check issues to format\n * @returns Formatted string\n */\nexport function formatCheckIssues(issues: CheckIssue[]): string {\n return issues.map(formatCheckIssue).join('\\n\\n');\n}\n","/**\n * Rules linter for llms.txt and related files.\n */\n\nimport type { Issue } from './issues.js';\nimport type { LlmsSeoConfig } from '../../schema/config.schema.js';\nimport { createIssue } from './issues.js';\nimport type { CheckIssue } from './issues.js';\n\n/**\n * Rule definition for linting.\n */\nexport interface LintRule {\n /** Unique rule identifier */\n id: string;\n /** Human-readable description */\n description: string;\n /** Whether the rule is enabled by default */\n enabled: boolean;\n /** The lint function */\n lint: (content: string, filePath: string) => Issue[];\n}\n\n/**\n * Options for linting content.\n */\nexport interface LintOptions {\n /** llms.txt or llms-full.txt content */\n content: string;\n /** LLM-SEO configuration */\n config: LlmsSeoConfig;\n}\n\n/**\n * Result of linting content.\n */\nexport interface LintResult {\n /** Issues found during linting */\n issues: CheckIssue[];\n}\n\n/**\n * Available lint rules.\n */\nexport const LINT_RULES: readonly LintRule[] = [\n {\n id: 'heading-structure',\n description: 'Ensures proper heading structure (h1 -> h2 -> h3)',\n enabled: true,\n lint: lintHeadingStructure,\n },\n {\n id: 'url-format',\n description: 'Validates URL format in links',\n enabled: true,\n lint: lintUrlFormat,\n },\n {\n id: 'trailing-whitespace',\n description: 'Checks for trailing whitespace on lines',\n enabled: true,\n lint: lintTrailingWhitespace,\n },\n {\n id: 'consistent-list-markers',\n description: 'Ensures consistent list marker usage',\n enabled: true,\n lint: lintListMarkers,\n },\n];\n\n/**\n * Lints content against provided rules.\n * @param content - The content to lint\n * @param filePath - Path to the file being linted\n * @param rules - Rules to apply (defaults to all enabled rules)\n * @returns Lint result with issues\n */\nexport function lintContent(\n content: string,\n filePath: string,\n rules: readonly LintRule[] = LINT_RULES.filter((r) => r.enabled)\n): LintResultLegacy {\n const issues: Issue[] = [];\n \n for (const rule of rules) {\n const ruleIssues = rule.lint(content, filePath);\n issues.push(...ruleIssues);\n }\n \n return {\n filePath,\n issues,\n passed: issues.filter((i) => i.severity === 'error').length === 0,\n };\n}\n\n/**\n * Legacy lint result interface.\n */\nexport interface LintResultLegacy {\n /** File path that was linted */\n filePath: string;\n /** Issues found during linting */\n issues: Issue[];\n /** Whether the file passed all rules */\n passed: boolean;\n}\n\n/**\n * Lints content against policy rules:\n * - Forbidden terms (if restrictedClaims.enable)\n * - Empty sections\n * - Duplicate URLs in priority lists\n * - Locale consistency between sections\n * \n * @param options - Lint options\n * @returns Lint result with issues\n */\nexport function lintContentWithConfig(options: LintOptions): LintResult {\n const { content, config } = options;\n const issues: CheckIssue[] = [];\n \n // Check forbidden terms if policy is configured\n if (config.policy?.restrictedClaims?.enable) {\n const forbidden = config.policy.restrictedClaims.forbidden ?? [];\n const whitelist = config.policy.restrictedClaims.whitelist ?? [];\n const forbiddenIssues = checkForbiddenTerms(content, forbidden, whitelist);\n issues.push(...forbiddenIssues);\n }\n \n // Check for empty sections\n const emptySectionIssues = checkEmptySections(content);\n issues.push(...emptySectionIssues);\n \n // Check for duplicate URLs\n const duplicateUrlIssues = checkDuplicateUrls(content);\n issues.push(...duplicateUrlIssues);\n \n return { issues };\n}\n\n/**\n * Checks for forbidden terms in content.\n * @param content - Content to check\n * @param forbidden - List of forbidden terms\n * @param whitelist - List of whitelisted terms (case-insensitive)\n * @returns Array of check issues\n */\nexport function checkForbiddenTerms(\n content: string,\n forbidden: string[],\n whitelist: string[] = []\n): CheckIssue[] {\n const issues: CheckIssue[] = [];\n const lines = content.split('\\n');\n const whitelistLower = whitelist.map((w) => w.toLowerCase());\n \n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (line === undefined) continue;\n const trimmed = line.trim();\n const loweredTrimmed = trimmed.toLowerCase();\n\n // Do not lint policy definition lines that explicitly list forbidden/allowed terms.\n if (\n loweredTrimmed.startsWith('forbidden terms:') ||\n loweredTrimmed.startsWith('exceptions:')\n ) {\n continue;\n }\n \n for (const term of forbidden) {\n const termLower = term.toLowerCase();\n const lineLower = line.toLowerCase();\n \n // Check if term exists in line\n if (lineLower.includes(termLower)) {\n // Check if it's whitelisted\n const isWhitelisted = whitelistLower.some((w) => \n lineLower.includes(w) && w.includes(termLower)\n );\n \n if (!isWhitelisted) {\n issues.push({\n path: '',\n code: 'forbidden_term',\n message: `Term \"${term}\" is forbidden by policy`,\n severity: 'warning',\n line: i + 1,\n context: trimmed.substring(0, 100),\n });\n }\n }\n }\n }\n \n return issues;\n}\n\n/**\n * Checks for empty sections in content.\n * An empty section is a heading followed only by whitespace/blank lines\n * until the next heading or end of file.\n * Note: The first heading (typically h1 document title) is not checked\n * as it's common to have the title without immediate content.\n * @param content - Content to check\n * @returns Array of check issues\n */\nexport function checkEmptySections(content: string): CheckIssue[] {\n const issues: CheckIssue[] = [];\n const lines = content.split('\\n');\n \n let currentSection: string | null = null;\n let sectionStartLine = 0;\n let sectionHeadingLevel = 0;\n let sectionHasContent = false;\n let sectionWasFirst = false;\n let isFirstHeading = true;\n \n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (line === undefined) continue;\n \n // Check for markdown heading\n const headingMatch = line.match(/^(#{1,6})\\s+(.+)$/);\n \n if (headingMatch?.[2]) {\n const nextHeadingLevel = headingMatch[1]?.length ?? 0;\n\n // A subsection counts as content for its parent section.\n if (currentSection !== null && nextHeadingLevel > sectionHeadingLevel) {\n sectionHasContent = true;\n }\n\n // Check if previous section was empty (had heading but no content)\n // Skip check for the first heading (document title)\n if (currentSection !== null && !sectionHasContent && !sectionWasFirst) {\n issues.push({\n path: '',\n code: 'empty_section',\n message: `Section \"${currentSection}\" has no content`,\n severity: 'info',\n line: sectionStartLine,\n });\n }\n \n // Start new section\n currentSection = headingMatch[2].trim();\n sectionStartLine = i + 1;\n sectionHeadingLevel = nextHeadingLevel;\n sectionHasContent = false;\n sectionWasFirst = isFirstHeading;\n isFirstHeading = false;\n } else if (currentSection !== null) {\n // Non-heading line - check if it has actual content\n if (line.trim().length > 0) {\n sectionHasContent = true;\n }\n }\n }\n \n // Check last section (skip if it's the only/first heading)\n if (currentSection !== null && !sectionHasContent && !sectionWasFirst) {\n issues.push({\n path: '',\n code: 'empty_section',\n message: `Section \"${currentSection}\" has no content`,\n severity: 'info',\n line: sectionStartLine,\n });\n }\n \n return issues;\n}\n\n/**\n * Checks for duplicate URLs in content.\n * @param content - Content to check\n * @returns Array of check issues\n */\nexport function checkDuplicateUrls(content: string): CheckIssue[] {\n const issues: CheckIssue[] = [];\n const lines = content.split('\\n');\n const seenUrls = new Map<string, number>();\n \n // Pattern to match markdown links\n const urlPattern = /\\[([^\\]]*)\\]\\(([^)]+)\\)/g;\n \n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (line === undefined) continue;\n \n let match: RegExpExecArray | null = urlPattern.exec(line);\n while (match !== null) {\n const url = match[2];\n if (url !== undefined) {\n const firstOccurrence = seenUrls.get(url);\n if (firstOccurrence !== undefined) {\n issues.push({\n path: '',\n code: 'duplicate_url',\n message: `URL \"${url}\" appears multiple times (first at line ${firstOccurrence})`,\n severity: 'warning',\n line: i + 1,\n context: url,\n });\n } else {\n seenUrls.set(url, i + 1);\n }\n }\n match = urlPattern.exec(line);\n }\n \n // Reset regex state for next line\n urlPattern.lastIndex = 0;\n }\n \n return issues;\n}\n\n/**\n * Lints heading structure in markdown content.\n */\nfunction lintHeadingStructure(content: string, filePath: string): Issue[] {\n const issues: Issue[] = [];\n const lines = content.split('\\n');\n let prevLevel = 0;\n \n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (line === undefined) continue;\n const match = line.match(/^(#{1,6})\\s/);\n if (match?.[1]) {\n const level = match[1].length;\n if (level > prevLevel + 1 && prevLevel > 0) {\n issues.push(createIssue({\n id: 'heading-skip',\n pageId: filePath,\n severity: 'warning',\n message: `Heading level skipped: h${prevLevel} to h${level}`,\n line: i + 1,\n }));\n }\n prevLevel = level;\n }\n }\n \n return issues;\n}\n\n/**\n * Lints URL format in markdown content.\n */\nfunction lintUrlFormat(content: string, filePath: string): Issue[] {\n const issues: Issue[] = [];\n const lines = content.split('\\n');\n const urlPattern = /\\[([^\\]]*)\\]\\(([^)]+)\\)/g;\n \n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (line === undefined) continue;\n let match: RegExpExecArray | null = urlPattern.exec(line);\n while (match !== null) {\n const url = match[2];\n if (url && !url.startsWith('/') && !url.startsWith('http') && !url.startsWith('#')) {\n issues.push(createIssue({\n id: 'invalid-url',\n pageId: filePath,\n severity: 'warning',\n message: `Invalid URL format: ${url}`,\n line: i + 1,\n column: match.index + 1,\n }));\n }\n match = urlPattern.exec(line);\n }\n }\n \n return issues;\n}\n\n/**\n * Lints trailing whitespace in content.\n */\nfunction lintTrailingWhitespace(content: string, filePath: string): Issue[] {\n const issues: Issue[] = [];\n const lines = content.split('\\n');\n \n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (line !== undefined && line.endsWith(' ')) {\n issues.push(createIssue({\n id: 'trailing-whitespace',\n pageId: filePath,\n severity: 'info',\n message: 'Line has trailing whitespace',\n line: i + 1,\n }));\n }\n }\n \n return issues;\n}\n\n/**\n * Lints list marker consistency in content.\n */\nfunction lintListMarkers(content: string, filePath: string): Issue[] {\n const issues: Issue[] = [];\n const lines = content.split('\\n');\n const dashCount = lines.filter((l) => /^\\s*-\\s/.test(l)).length;\n const asteriskCount = lines.filter((l) => /^\\s*\\*\\s/.test(l)).length;\n \n if (dashCount > 0 && asteriskCount > 0) {\n issues.push(createIssue({\n id: 'inconsistent-list-markers',\n pageId: filePath,\n severity: 'info',\n message: 'Mix of - and * list markers detected',\n }));\n }\n \n return issues;\n}\n","/**\n * SEO checker for LLM-optimized content validation.\n */\n\nimport * as fs from 'node:fs/promises';\nimport type { LlmsSeoConfig } from '../../schema/config.schema.js';\nimport type { SiteManifest } from '../../schema/manifest.schema.js';\nimport type { Issue, IssueSeverity } from './issues.js';\nimport type { CheckIssue, CheckIssueCode } from './issues.js';\nimport { createCheckIssue, countSeverities } from './issues.js';\nimport { lintContent as lintWithRules, checkForbiddenTerms, checkEmptySections, checkDuplicateUrls } from './rules-linter.js';\nimport { ExitCode } from '../../cli/exit-codes.js';\n\n/**\n * Configuration for the SEO checker.\n */\nexport interface CheckerConfig {\n /** Enable strict mode for additional checks */\n strict?: boolean;\n /** Maximum allowed title length */\n maxTitleLength?: number;\n /** Maximum allowed description length */\n maxDescriptionLength?: number;\n}\n\n/**\n * Options for checking generated files.\n */\nexport interface CheckOptions {\n /** LLM-SEO configuration */\n config: LlmsSeoConfig;\n /** Path to llms.txt (default from config) */\n llmsTxtPath?: string;\n /** Path to llms-full.txt (default from config) */\n llmsFullTxtPath?: string;\n /** Path to citations.json (optional) */\n citationsPath?: string;\n /** Fail threshold */\n failOn: 'warn' | 'error';\n}\n\n/**\n * Result of running the SEO checker.\n */\nexport interface CheckerResult {\n /** Whether all checks passed */\n passed: boolean;\n /** List of issues found */\n issues: Issue[];\n /** Number of pages checked */\n pagesChecked: number;\n /** Summary of issues by severity */\n summary: Record<IssueSeverity, number>;\n}\n\n/**\n * Result of checking generated files.\n */\nexport interface CheckResult {\n /** List of issues found */\n issues: CheckIssue[];\n /** Summary counts */\n summary: {\n errors: number;\n warnings: number;\n info: number;\n filesChecked: number;\n filesMissing: number;\n filesMismatch: number;\n };\n /** Exit code for CI */\n exitCode: ExitCode;\n}\n\n/**\n * Result of content comparison.\n */\nexport interface CompareResult {\n /** Whether content matches */\n match: boolean;\n /** Context showing differences */\n context: string;\n}\n\n/**\n * Default checker configuration.\n */\nexport const DEFAULT_CHECKER_CONFIG: Required<CheckerConfig> = {\n strict: false,\n maxTitleLength: 60,\n maxDescriptionLength: 160,\n};\n\n/**\n * Runs SEO checks on a site manifest.\n * @param manifest - The site manifest to check\n * @param config - Checker configuration\n * @returns Checker result with issues and summary\n */\nexport function checkManifest(\n manifest: SiteManifest,\n config: CheckerConfig = {}\n): CheckerResult {\n const fullConfig = { ...DEFAULT_CHECKER_CONFIG, ...config };\n const issues: Issue[] = [];\n \n // Check each page\n for (const page of manifest.pages) {\n const pageIssues = checkPage(page, fullConfig);\n issues.push(...pageIssues);\n }\n \n // Calculate summary\n const summary: Record<IssueSeverity, number> = {\n error: 0,\n warning: 0,\n info: 0,\n };\n \n for (const issue of issues) {\n summary[issue.severity]++;\n }\n \n return {\n passed: summary.error === 0,\n issues,\n pagesChecked: manifest.pages.length,\n summary,\n };\n}\n\n/**\n * Checks a single page for SEO issues.\n * @param page - The page to check\n * @param config - Checker configuration\n * @returns List of issues found\n */\nfunction checkPage(\n page: { path: string; title?: string | undefined; description?: string | undefined },\n config: Required<CheckerConfig>\n): Issue[] {\n const issues: Issue[] = [];\n const pageId = page.path;\n \n // Check title\n if (!page.title) {\n issues.push({\n id: 'missing-title',\n pageId,\n severity: 'warning',\n message: 'Page is missing a title',\n });\n } else if (page.title.length > config.maxTitleLength) {\n issues.push({\n id: 'title-too-long',\n pageId,\n severity: 'warning',\n message: `Title exceeds ${config.maxTitleLength} characters (${page.title.length})`,\n });\n }\n \n // Check description\n if (!page.description) {\n issues.push({\n id: 'missing-description',\n pageId,\n severity: 'warning',\n message: 'Page is missing a description',\n });\n } else if (page.description.length > config.maxDescriptionLength) {\n issues.push({\n id: 'description-too-long',\n pageId,\n severity: 'info',\n message: `Description exceeds ${config.maxDescriptionLength} characters (${page.description.length})`,\n });\n }\n \n return issues;\n}\n\n/**\n * Main check function:\n * 1. Validates config\n * 2. Reads existing files from disk\n * 3. Compares expected vs actual (if expected content provided)\n * 4. Runs linting rules\n * 5. Returns issues with summary\n * \n * @param options - Check options\n * @returns Check result with issues and exit code\n */\nexport async function checkGeneratedFiles(options: CheckOptions): Promise<CheckResult> {\n const issues: CheckIssue[] = [];\n let filesChecked = 0;\n let filesMissing = 0;\n let filesMismatch = 0;\n \n const { config, failOn } = options;\n \n // Get file paths from config\n const llmsTxtPath = options.llmsTxtPath ?? config.output.paths.llmsTxt;\n const llmsFullTxtPath = options.llmsFullTxtPath ?? config.output.paths.llmsFullTxt;\n const citationsPath = options.citationsPath ?? config.output.paths.citations;\n \n // Check llms.txt\n const llmsTxtResult = await checkFile(llmsTxtPath);\n if (!llmsTxtResult.exists) {\n issues.push(createCheckIssue(\n 'error',\n 'file_missing',\n `Required file does not exist: ${llmsTxtPath}`,\n llmsTxtPath\n ));\n filesMissing++;\n } else if (llmsTxtResult.content === '') {\n issues.push(createCheckIssue(\n 'warning',\n 'file_empty',\n `File is empty: ${llmsTxtPath}`,\n llmsTxtPath\n ));\n filesChecked++;\n } else {\n filesChecked++;\n // Run content linter on llms.txt\n const lintIssues = await lintFile(llmsTxtPath, llmsTxtResult.content, config);\n issues.push(...lintIssues);\n }\n \n // Check llms-full.txt\n const llmsFullTxtResult = await checkFile(llmsFullTxtPath);\n if (!llmsFullTxtResult.exists) {\n issues.push(createCheckIssue(\n 'error',\n 'file_missing',\n `Required file does not exist: ${llmsFullTxtPath}`,\n llmsFullTxtPath\n ));\n filesMissing++;\n } else if (llmsFullTxtResult.content === '') {\n issues.push(createCheckIssue(\n 'warning',\n 'file_empty',\n `File is empty: ${llmsFullTxtPath}`,\n llmsFullTxtPath\n ));\n filesChecked++;\n } else {\n filesChecked++;\n // Run content linter on llms-full.txt\n const lintIssues = await lintFile(llmsFullTxtPath, llmsFullTxtResult.content, config);\n issues.push(...lintIssues);\n }\n \n // Check citations.json (optional)\n if (citationsPath) {\n const citationsResult = await checkFile(citationsPath);\n if (!citationsResult.exists) {\n issues.push(createCheckIssue(\n 'warning',\n 'file_missing',\n `Optional citations file does not exist: ${citationsPath}`,\n citationsPath\n ));\n filesMissing++;\n } else {\n filesChecked++;\n }\n }\n \n // Calculate summary\n const severityCounts = countSeverities(issues);\n \n // Determine exit code\n let exitCode: ExitCode;\n if (severityCounts.error > 0) {\n exitCode = 2; // ERROR\n } else if (failOn === 'warn' && severityCounts.warning > 0) {\n exitCode = 1; // WARN\n } else {\n exitCode = 0; // OK\n }\n \n return {\n issues,\n summary: {\n errors: severityCounts.error,\n warnings: severityCounts.warning,\n info: severityCounts.info,\n filesChecked,\n filesMissing,\n filesMismatch,\n },\n exitCode,\n };\n}\n\n/**\n * Checks if a file exists.\n * @param filePath - Path to the file\n * @returns Promise resolving to true if file exists\n */\nexport async function checkFileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Checks a file and returns its content.\n * @param filePath - Path to the file\n * @returns Object with exists flag and content\n */\nasync function checkFile(filePath: string): Promise<{ exists: boolean; content: string }> {\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n return { exists: true, content };\n } catch {\n return { exists: false, content: '' };\n }\n}\n\n/**\n * Reads file content safely.\n * @param filePath - Path to the file\n * @returns File content or null if file doesn't exist\n */\nexport async function readFileContent(filePath: string): Promise<string | null> {\n try {\n return await fs.readFile(filePath, 'utf-8');\n } catch {\n return null;\n }\n}\n\n/**\n * Compares two strings and returns diff context.\n * @param expected - Expected content\n * @param actual - Actual content\n * @param maxContextLines - Maximum number of diff lines to show (default: 5)\n * @returns CompareResult with match status and context\n */\nexport function compareContent(\n expected: string,\n actual: string,\n maxContextLines = 5\n): CompareResult {\n if (expected === actual) {\n return { match: true, context: '' };\n }\n \n const expectedLines = expected.split('\\n');\n const actualLines = actual.split('\\n');\n const contextLines: string[] = [];\n let diffCount = 0;\n \n const maxLines = Math.max(expectedLines.length, actualLines.length);\n \n for (let i = 0; i < maxLines && diffCount < maxContextLines; i++) {\n const expectedLine = expectedLines[i];\n const actualLine = actualLines[i];\n \n if (expectedLine !== actualLine) {\n diffCount++;\n const lineNum = i + 1;\n \n if (expectedLine !== undefined) {\n contextLines.push(`Expected line ${lineNum}: \"${expectedLine}\"`);\n }\n if (actualLine !== undefined) {\n contextLines.push(`Actual line ${lineNum}: \"${actualLine}\"`);\n }\n }\n }\n \n return {\n match: false,\n context: contextLines.join('\\n'),\n };\n}\n\n/**\n * Lints a file content against policy rules.\n * @param filePath - Path to the file\n * @param content - File content\n * @param config - LLM-SEO configuration\n * @returns Array of check issues\n */\nasync function lintFile(\n filePath: string,\n content: string,\n config: LlmsSeoConfig\n): Promise<CheckIssue[]> {\n const issues: CheckIssue[] = [];\n \n // Run basic linting rules\n const lintResult = lintWithRules(content, filePath);\n for (const issue of lintResult.issues) {\n const checkIssue: CheckIssue = {\n path: filePath,\n code: issue.id as CheckIssueCode,\n message: issue.message,\n severity: issue.severity,\n };\n if (issue.line !== undefined) {\n checkIssue.line = issue.line;\n }\n if (issue.suggestion !== undefined) {\n checkIssue.context = issue.suggestion;\n }\n issues.push(checkIssue);\n }\n \n // Check forbidden terms if policy is configured\n if (config.policy?.restrictedClaims?.enable) {\n const forbidden = config.policy.restrictedClaims.forbidden ?? [];\n const whitelist = config.policy.restrictedClaims.whitelist ?? [];\n const forbiddenIssues = checkForbiddenTerms(content, forbidden, whitelist);\n \n for (const issue of forbiddenIssues) {\n const checkIssue: CheckIssue = {\n path: filePath,\n code: 'forbidden_term',\n message: issue.message,\n severity: issue.severity,\n };\n if (issue.line !== undefined) {\n checkIssue.line = issue.line;\n }\n if (issue.context !== undefined) {\n checkIssue.context = issue.context;\n }\n issues.push(checkIssue);\n }\n }\n \n // Check for empty sections\n const emptySectionIssues = checkEmptySections(content);\n for (const issue of emptySectionIssues) {\n const checkIssue: CheckIssue = {\n path: filePath,\n code: 'empty_section',\n message: issue.message,\n severity: issue.severity,\n };\n if (issue.line !== undefined) {\n checkIssue.line = issue.line;\n }\n if (issue.context !== undefined) {\n checkIssue.context = issue.context;\n }\n issues.push(checkIssue);\n }\n \n // Check for duplicate URLs\n const duplicateUrlIssues = checkDuplicateUrls(content);\n for (const issue of duplicateUrlIssues) {\n const checkIssue: CheckIssue = {\n path: filePath,\n code: 'duplicate_url',\n message: issue.message,\n severity: issue.severity,\n };\n if (issue.line !== undefined) {\n checkIssue.line = issue.line;\n }\n if (issue.context !== undefined) {\n checkIssue.context = issue.context;\n }\n issues.push(checkIssue);\n }\n \n return issues;\n}\n\n/**\n * Checks generated files against expected content.\n * @param llmsTxtPath - Path to llms.txt\n * @param expectedLlmsTxt - Expected llms.txt content\n * @param llmsFullTxtPath - Path to llms-full.txt\n * @param expectedLlmsFullTxt - Expected llms-full.txt content\n * @param maxContextLines - Maximum context lines for diff\n * @returns Array of check issues\n */\nexport async function checkFilesAgainstExpected(\n llmsTxtPath: string,\n expectedLlmsTxt: string,\n llmsFullTxtPath: string,\n expectedLlmsFullTxt: string,\n maxContextLines = 5\n): Promise<CheckIssue[]> {\n const issues: CheckIssue[] = [];\n \n // Check llms.txt\n const llmsTxtContent = await readFileContent(llmsTxtPath);\n if (llmsTxtContent === null) {\n issues.push(createCheckIssue(\n 'error',\n 'file_missing',\n `Required file does not exist: ${llmsTxtPath}`,\n llmsTxtPath\n ));\n } else if (llmsTxtContent === '') {\n issues.push(createCheckIssue(\n 'warning',\n 'file_empty',\n `File is empty: ${llmsTxtPath}`,\n llmsTxtPath\n ));\n } else {\n const compareResult = compareContent(expectedLlmsTxt, llmsTxtContent, maxContextLines);\n if (!compareResult.match) {\n issues.push(createCheckIssue(\n 'error',\n 'file_mismatch',\n `Content differs from expected output`,\n llmsTxtPath,\n compareResult.context\n ));\n }\n }\n \n // Check llms-full.txt\n const llmsFullTxtContent = await readFileContent(llmsFullTxtPath);\n if (llmsFullTxtContent === null) {\n issues.push(createCheckIssue(\n 'error',\n 'file_missing',\n `Required file does not exist: ${llmsFullTxtPath}`,\n llmsFullTxtPath\n ));\n } else if (llmsFullTxtContent === '') {\n issues.push(createCheckIssue(\n 'warning',\n 'file_empty',\n `File is empty: ${llmsFullTxtPath}`,\n llmsFullTxtPath\n ));\n } else {\n const compareResult = compareContent(expectedLlmsFullTxt, llmsFullTxtContent, maxContextLines);\n if (!compareResult.match) {\n issues.push(createCheckIssue(\n 'error',\n 'file_mismatch',\n `Content differs from expected output`,\n llmsFullTxtPath,\n compareResult.context\n ));\n }\n }\n \n return issues;\n}\n"]}
@@ -0,0 +1,6 @@
1
+ export { CanonicalOptions, CheckOptions, CheckResult, CheckerConfig, CheckerResult, Citation, CitationSource, CitationsJson, CitationsPolicy, CitationsSite, Comparator, CompareResult, CreateCanonicalUrlsOptions, CreateCitationsJsonOptions, CreateLlmsFullTxtOptions, CreateLlmsFullTxtResult, CreateLlmsTxtOptions, CreateLlmsTxtResult, DEFAULT_CHECKER_CONFIG, Issue, IssueCategory, IssueSeverity, LINT_RULES, LintResult, LintRule, LlmsFullTxtOptions, LlmsTxtOptions, LocaleConfig, LocaleStrategy, TrailingSlashPolicy, checkFileExists, checkFilesAgainstExpected, checkGeneratedFiles, checkManifest, citationToJsonLd, citationToMarkdown, compareContent, compareStrings, createCanonicalUrlForItem, createCanonicalUrlsFromManifest, createCitation, createCitationsJson, createCitationsJsonString, createIssue, createLlmsFullTxt, createLlmsTxt, dedupeUrls, extractCanonicalUrls, extractLocaleFromPath, filterBySeverity, generateAlternateUrls, generateCanonicalUrl, generateLlmsFullTxt, generateLlmsTxt, generatePageContent, generateReferenceList, groupByPage, groupBySeverity, lintContent, localizePath, normalizeLineEndings, normalizeLineWhitespace, normalizeSeoText, normalizeUrl, normalizeWhitespace, readFileContent, sortBy, sortStrings, sortUrls } from './core/index.js';
2
+ export { C as CheckConfig, a as CheckConfigSchema, b as Config, c as ConfigSchema, F as FullConfig, d as FullConfigSchema } from './config.schema-DCnBx3Gm.js';
3
+ export { B as BuildManifest, a as BuildManifestSchema, O as OptionalSection, b as OptionalSectionSchema, P as PageManifest, c as PageManifestSchema, S as SiteManifest, d as SiteManifestSchema } from './manifest.schema-B_z3rxRV.js';
4
+ export { ValidationError, ValidationResult, formatValidationErrors, validate, validateOrThrow } from './schema/index.js';
5
+ export { BuildHookOptions, BuildHookResult, BuildScriptsResult, CreateManifestFromDataOptions, CreateManifestFromPagesDirOptions, CreateNextConfigOptions, CreateRobotsLlmsPolicySnippetOptions, FromNextContentManifestOptions, GenerateBuildScriptsOptions, NextConfigResult, NextContentManifest, NextManifestOptions, createManifestFromData, createManifestFromPagesDir, createNextConfig, createNextPlugin, createRobotsLlmsPolicySnippet, extractPagePaths, fromNextContentManifest, generateBuildScripts, generateNextManifest, postBuildHook } from './adapters/next/index.js';
6
+ import 'zod';