@pas7/llm-seo 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/adapters/index.d.ts +3 -2
- package/dist/adapters/index.js +351 -12
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/next/index.d.ts +67 -2
- package/dist/adapters/next/index.js +351 -12
- package/dist/adapters/next/index.js.map +1 -1
- package/dist/canonical-from-manifest-BKpEmouS.d.ts +109 -0
- package/dist/cli/bin.js +58 -2
- package/dist/cli/bin.js.map +1 -1
- package/dist/{config.schema-Dj2VTdnD.d.ts → config.schema-CI5OBbhQ.d.ts} +382 -2
- package/dist/core/index.d.ts +4 -110
- package/dist/index.d.ts +4 -4
- package/dist/index.js +127 -1
- package/dist/index.js.map +1 -1
- package/dist/schema/index.d.ts +2 -3
- package/package.json +1 -1
- package/dist/manifest.schema-B_z3rxRV.d.ts +0 -384
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/adapters/next/manifest.ts","../../../src/core/normalize/sort.ts","../../../src/core/normalize/text.ts","../../../src/core/generate/llms-txt.ts","../../../src/core/generate/llms-full-txt.ts","../../../src/adapters/next/build-hooks.ts"],"names":["getHubLabel","formatHubLabel"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Manifest generation for Next.js static exports.\n */\n\nimport { existsSync } from 'node:fs';\nimport { readdir, readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { ManifestItem, SiteManifest, PageManifest, BuildManifest } from '../../schema/manifest.schema.js';\n\n/**\n * Next.js content manifest structure for fromNextContentManifest.\n */\nexport interface NextContentManifest {\n items: Array<{\n slug: string;\n locales?: string[];\n publishedAt?: string;\n updatedAt?: string;\n title?: string;\n description?: string;\n priority?: number;\n canonicalOverride?: string;\n [key: string]: unknown;\n }>;\n}\n\n/**\n * Options for fromNextContentManifest.\n */\nexport interface FromNextContentManifestOptions {\n /** Prefix to add to all slugs */\n slugPrefix?: string;\n /** Default locale if not specified */\n defaultLocale?: string;\n}\n\n/**\n * Converts Next.js content manifest to llm-seo ManifestItem[].\n *\n * @param manifest - Next.js content manifest\n * @param options - Conversion options\n * @returns Normalized ManifestItem[] for use in config\n */\nexport function fromNextContentManifest(\n manifest: NextContentManifest,\n options: FromNextContentManifestOptions = {}\n): ManifestItem[] {\n const { slugPrefix = '', defaultLocale } = options;\n\n return manifest.items.map((item): ManifestItem => {\n const result: ManifestItem = {\n slug: slugPrefix + item.slug,\n };\n\n if (item.locales !== undefined) {\n result.locales = item.locales;\n } else if (defaultLocale !== undefined) {\n result.locales = [defaultLocale];\n }\n\n if (item.publishedAt !== undefined) {\n result.publishedAt = item.publishedAt;\n }\n\n if (item.updatedAt !== undefined) {\n result.updatedAt = item.updatedAt;\n }\n\n if (item.title !== undefined) {\n result.title = item.title;\n }\n\n if (item.description !== undefined) {\n result.description = item.description;\n }\n\n if (item.priority !== undefined) {\n result.priority = item.priority;\n }\n\n if (item.canonicalOverride !== undefined) {\n result.canonicalOverride = item.canonicalOverride;\n }\n\n return result;\n });\n}\n\n/**\n * Options for createManifestFromPagesDir.\n */\nexport interface CreateManifestFromPagesDirOptions {\n /** Path to pages directory */\n pagesDir: string;\n /** Prefix to add to all routes */\n routePrefix?: string;\n /** Default locale for items */\n defaultLocale?: string;\n /** File extensions to include */\n extensions?: string[];\n}\n\n/**\n * Parsed frontmatter from a file.\n */\ninterface ParsedFrontmatter {\n title?: string;\n description?: string;\n date?: string;\n updated?: string;\n locale?: string;\n locales?: string[];\n priority?: number;\n [key: string]: unknown;\n}\n\n/**\n * Parses YAML-like frontmatter from content.\n * Simple implementation for basic frontmatter extraction.\n *\n * @param content - File content with potential frontmatter\n * @returns Parsed frontmatter and body content\n */\nfunction parseFrontmatter(content: string): { frontmatter: ParsedFrontmatter; body: string } {\n const frontmatterRegex = /^---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n([\\s\\S]*)$/;\n const match = content.match(frontmatterRegex);\n\n if (!match) {\n return { frontmatter: {}, body: content };\n }\n\n const frontmatterText = match[1] ?? '';\n const body = match[2] ?? content;\n const frontmatter: ParsedFrontmatter = {};\n\n // Simple YAML-like parsing\n const lines = frontmatterText.split('\\n');\n for (const line of lines) {\n const colonIndex = line.indexOf(':');\n if (colonIndex === -1) continue;\n\n const key = line.slice(0, colonIndex).trim();\n let value: string | string[] = line.slice(colonIndex + 1).trim();\n\n // Handle arrays in format [item1, item2]\n if (value.startsWith('[') && value.endsWith(']')) {\n value = value\n .slice(1, -1)\n .split(',')\n .map((item) => item.trim().replace(/^['\"]|['\"]$/g, ''))\n .filter((item) => item.length > 0);\n } else {\n // Remove quotes\n value = value.replace(/^['\"]|['\"]$/g, '');\n }\n\n // Map to frontmatter fields\n if (key === 'title') frontmatter.title = value as string;\n else if (key === 'description') frontmatter.description = value as string;\n else if (key === 'date' || key === 'publishedAt') frontmatter.date = value as string;\n else if (key === 'updated' || key === 'updatedAt') frontmatter.updated = value as string;\n else if (key === 'locale') frontmatter.locale = value as string;\n else if (key === 'locales') frontmatter.locales = value as string[];\n else if (key === 'priority') frontmatter.priority = parseInt(value as string, 10);\n else frontmatter[key] = value;\n }\n\n return { frontmatter, body };\n}\n\n/**\n * Converts file path to URL slug.\n *\n * @param filePath - File path relative to pages dir\n * @param extensions - File extensions to strip\n * @returns URL slug\n */\nfunction filePathToSlug(filePath: string, extensions: string[]): string {\n let slug = filePath;\n\n // Remove extension\n for (const ext of extensions) {\n if (slug.endsWith(ext)) {\n slug = slug.slice(0, -ext.length);\n break;\n }\n }\n\n // Handle index files\n if (slug.endsWith('/index')) {\n slug = slug.slice(0, -6);\n }\n if (slug === 'index') {\n slug = '';\n }\n\n // Ensure leading slash\n if (!slug.startsWith('/')) {\n slug = '/' + slug;\n }\n\n return slug || '/';\n}\n\n/**\n * Recursively scans directory for content files.\n *\n * @param dir - Directory to scan\n * @param extensions - File extensions to include\n * @param basePath - Base path for relative paths\n * @returns Array of relative file paths\n */\nasync function scanDirectory(\n dir: string,\n extensions: string[],\n basePath: string = ''\n): Promise<string[]> {\n const files: string[] = [];\n\n if (!existsSync(dir)) {\n return files;\n }\n\n const entries = await readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n const relativePath = basePath ? join(basePath, entry.name) : entry.name;\n\n if (entry.isDirectory()) {\n const subFiles = await scanDirectory(fullPath, extensions, relativePath);\n files.push(...subFiles);\n } else if (entry.isFile()) {\n const hasValidExtension = extensions.some((ext) => entry.name.endsWith(ext));\n if (hasValidExtension) {\n files.push(relativePath);\n }\n }\n }\n\n return files;\n}\n\n/**\n * Creates manifest from Next.js pages directory.\n * Scans for .mdx, .md files and extracts frontmatter.\n *\n * @param options - Options for manifest creation\n * @returns Promise resolving to ManifestItem[]\n */\nexport async function createManifestFromPagesDir(\n options: CreateManifestFromPagesDirOptions\n): Promise<ManifestItem[]> {\n const {\n pagesDir,\n routePrefix = '',\n defaultLocale,\n extensions = ['.mdx', '.md'],\n } = options;\n\n const files = await scanDirectory(pagesDir, extensions);\n const items: ManifestItem[] = [];\n\n for (const file of files) {\n const fullPath = join(pagesDir, file);\n const content = await readFile(fullPath, 'utf-8');\n const { frontmatter } = parseFrontmatter(content);\n\n const slug = routePrefix + filePathToSlug(file, extensions);\n\n const item: ManifestItem = {\n slug,\n };\n\n if (frontmatter.locales !== undefined) {\n item.locales = frontmatter.locales;\n } else if (frontmatter.locale !== undefined) {\n item.locales = [frontmatter.locale];\n } else if (defaultLocale !== undefined) {\n item.locales = [defaultLocale];\n }\n\n if (frontmatter.date !== undefined) {\n item.publishedAt = frontmatter.date;\n }\n\n if (frontmatter.updated !== undefined) {\n item.updatedAt = frontmatter.updated;\n }\n\n if (frontmatter.title !== undefined) {\n item.title = frontmatter.title;\n }\n\n if (frontmatter.description !== undefined) {\n item.description = frontmatter.description;\n }\n\n if (frontmatter.priority !== undefined) {\n item.priority = frontmatter.priority;\n }\n\n items.push(item);\n }\n\n // Sort by slug for deterministic output\n return items.sort((a, b) => a.slug.localeCompare(b.slug));\n}\n\n/**\n * Options for createManifestFromData.\n */\nexport interface CreateManifestFromDataOptions {\n /** Prefix to add to all slugs */\n slugPrefix?: string;\n /** Default locale if not specified */\n defaultLocale?: string;\n}\n\n/**\n * Creates manifest from Next.js data (getStaticProps data).\n *\n * @param items - Array of items from getStaticProps\n * @param options - Options for manifest creation\n * @returns ManifestItem[]\n */\nexport function createManifestFromData(\n items: Array<{\n params: { slug: string | string[] };\n locale?: string;\n publishedAt?: string;\n updatedAt?: string;\n title?: string;\n description?: string;\n priority?: number;\n [key: string]: unknown;\n }>,\n options: CreateManifestFromDataOptions = {}\n): ManifestItem[] {\n const { slugPrefix = '', defaultLocale } = options;\n\n return items.map((item): ManifestItem => {\n // Convert slug array or string to path\n const slugPath = Array.isArray(item.params.slug)\n ? '/' + item.params.slug.join('/')\n : item.params.slug.startsWith('/')\n ? item.params.slug\n : '/' + item.params.slug;\n\n const result: ManifestItem = {\n slug: slugPrefix + slugPath,\n };\n\n if (item.locale !== undefined) {\n result.locales = [item.locale];\n } else if (defaultLocale !== undefined) {\n result.locales = [defaultLocale];\n }\n\n if (item.publishedAt !== undefined) {\n result.publishedAt = item.publishedAt;\n }\n\n if (item.updatedAt !== undefined) {\n result.updatedAt = item.updatedAt;\n }\n\n if (item.title !== undefined) {\n result.title = item.title;\n }\n\n if (item.description !== undefined) {\n result.description = item.description;\n }\n\n if (item.priority !== undefined) {\n result.priority = item.priority;\n }\n\n return result;\n });\n}\n\n// ============================================================================\n// Legacy functions - kept for backwards compatibility\n// ============================================================================\n\n/**\n * Options for Next.js manifest generation.\n */\nexport interface NextManifestOptions {\n /** Base URL for the site */\n baseUrl: string;\n /** Site title */\n title: string;\n /** Site description */\n description?: string;\n /** Path to the Next.js build manifest */\n buildManifestPath?: string;\n}\n\n/**\n * Extracts page paths from Next.js build manifest.\n * @param buildManifest - The Next.js build manifest\n * @returns Array of page paths\n */\nexport function extractPagePaths(buildManifest: BuildManifest): string[] {\n const pages: string[] = [];\n\n // Extract from static pages\n for (const pagePath of Object.keys(buildManifest.pages)) {\n // Skip Next.js internal routes\n if (pagePath.startsWith('/_')) {\n continue;\n }\n\n // Normalize the path\n const normalizedPath = normalizeNextPath(pagePath);\n pages.push(normalizedPath);\n }\n\n // Sort for deterministic output\n return pages.sort((a, b) => a.localeCompare(b));\n}\n\n/**\n * Normalizes a Next.js page path.\n * @param path - The page path\n * @returns Normalized path\n */\nfunction normalizeNextPath(path: string): string {\n // Remove file extension if present\n let normalized = path.replace(/\\.(html|json)$/, '');\n\n // Handle index pages\n if (normalized === '/index' || normalized === '') {\n normalized = '/';\n }\n\n // Ensure leading slash\n if (!normalized.startsWith('/')) {\n normalized = `/${normalized}`;\n }\n\n return normalized;\n}\n\n/**\n * Generates a site manifest from Next.js build output.\n * @param options - Manifest generation options\n * @param buildManifest - Optional build manifest\n * @returns Generated site manifest\n */\nexport function generateNextManifest(\n options: NextManifestOptions,\n buildManifest?: BuildManifest\n): SiteManifest {\n const pages: PageManifest[] = [];\n\n if (buildManifest) {\n const pagePaths = extractPagePaths(buildManifest);\n\n for (const path of pagePaths) {\n pages.push({\n path,\n title: undefined, // Will be filled by crawler or manually\n description: undefined,\n optional: false,\n });\n }\n }\n\n return {\n baseUrl: options.baseUrl,\n title: options.title,\n description: options.description,\n pages,\n };\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 * 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 /** Optional manifest entries with canonical URLs per item */\n manifestEntries?: ReadonlyArray<{\n item: ManifestItem;\n canonicalUrl: string;\n sectionName: string;\n }>;\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, manifestEntries } = 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\n const lastUpdated = getLastUpdatedDate(manifestItems);\n if (lastUpdated) {\n lines.push(`Last Updated: ${lastUpdated}`);\n }\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 // Contact\n const hasContact = config.contact?.email ||\n config.contact?.phone ||\n config.contact?.social?.twitter ||\n config.contact?.social?.linkedin ||\n config.contact?.social?.github ||\n config.booking?.url;\n if (hasContact) {\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?.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 (manifestEntries && manifestEntries.length > 0) {\n const sortedEntries = sortBy(manifestEntries, (entry) => {\n return `${entry.item.slug}|${entry.canonicalUrl}`;\n });\n for (const entry of sortedEntries) {\n const title = entry.item.title ?? entry.item.slug;\n const locales = entry.item.locales?.join(', ') ?? config.brand.locales[0] ?? 'en';\n lines.push(`- [${title}](${entry.canonicalUrl}) (${locales})`);\n }\n } else 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\nfunction getLastUpdatedDate(items: ManifestItem[]): string | null {\n const timestamps: string[] = [];\n for (const item of items) {\n if (item.updatedAt) {\n timestamps.push(item.updatedAt);\n } else if (item.publishedAt) {\n timestamps.push(item.publishedAt);\n }\n }\n\n if (timestamps.length === 0) {\n return null;\n }\n\n const latest = timestamps\n .map((value) => new Date(value))\n .filter((value) => !Number.isNaN(value.getTime()))\n .sort((a, b) => b.getTime() - a.getTime())[0];\n\n if (!latest) {\n return null;\n }\n\n return latest.toISOString().slice(0, 10);\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","/**\n * Build hooks for Next.js integration.\n */\n\nimport type { SiteManifest } from '../../schema/manifest.schema.js';\nimport { generateLlmsTxt } from '../../core/generate/llms-txt.js';\nimport { generateLlmsFullTxt } from '../../core/generate/llms-full-txt.js';\n\n// ============================================================================\n// Build Scripts Generation\n// ============================================================================\n\n/**\n * Options for generateBuildScripts.\n */\nexport interface GenerateBuildScriptsOptions {\n /** Path to config file */\n configPath?: string;\n /** Output directory for generated files */\n outputPath?: string;\n /** Whether to emit citations.json */\n emitCitations?: boolean;\n /** Package manager to use */\n packageManager?: 'npm' | 'yarn' | 'pnpm';\n}\n\n/**\n * Result of generateBuildScripts.\n */\nexport interface BuildScriptsResult {\n /** Script for building SEO artifacts */\n 'build:seo': string;\n /** Post-build hook script */\n postbuild: string;\n /** Script for checking SEO artifacts */\n 'check:seo': string;\n}\n\n/**\n * Generates package.json scripts for llm-seo integration.\n *\n * @param options - Options for script generation\n * @returns Object with script names as keys and commands as values\n *\n * @example\n * ```typescript\n * const scripts = generateBuildScripts({\n * configPath: 'llm-seo.config.ts',\n * emitCitations: true,\n * });\n * // Returns:\n * // {\n * // \"build:seo\": \"llm-seo generate --config llm-seo.config.ts\",\n * // \"postbuild\": \"pnpm build:seo && llm-seo check --fail-on error\",\n * // \"check:seo\": \"llm-seo check --fail-on warn\"\n * // }\n * ```\n */\nexport function generateBuildScripts(\n options: GenerateBuildScriptsOptions = {}\n): BuildScriptsResult {\n const {\n configPath = 'llm-seo.config.ts',\n emitCitations = false,\n packageManager = 'pnpm',\n } = options;\n\n const configFlag = `--config ${configPath}`;\n const citationsFlag = emitCitations ? ' --emit-citations' : '';\n\n const runCommand = packageManager === 'npm' ? 'npm run' : packageManager;\n\n return {\n 'build:seo': `llm-seo generate ${configFlag}${citationsFlag}`,\n postbuild: `${runCommand} build:seo && llm-seo check --fail-on error`,\n 'check:seo': 'llm-seo check --fail-on warn',\n };\n}\n\n// ============================================================================\n// Robots.txt LLM Policy\n// ============================================================================\n\n/**\n * Options for createRobotsLlmsPolicySnippet.\n */\nexport interface CreateRobotsLlmsPolicySnippetOptions {\n /** Base URL of the site */\n baseUrl: string;\n /** Whether to allow llms.txt */\n allowLlmsTxt?: boolean;\n /** Whether to allow llms-full.txt */\n allowLlmsFullTxt?: boolean;\n /** Whether to allow sitemap.xml */\n allowSitemap?: boolean;\n /** Additional paths to allow */\n additionalPaths?: string[];\n /** User agent to target (default: *) */\n userAgent?: string;\n}\n\n/**\n * Creates robots.txt LLM policy snippet.\n *\n * @param options - Options for snippet generation\n * @returns robots.txt snippet string\n *\n * @example\n * ```typescript\n * const snippet = createRobotsLlmsPolicySnippet({\n * baseUrl: 'https://example.com',\n * allowLlmsTxt: true,\n * allowLlmsFullTxt: true,\n * });\n * // Returns:\n * // # LLM SEO\n * // User-agent: *\n * // Allow: /llms.txt\n * // Allow: /llms-full.txt\n * // Allow: /sitemap.xml\n * ```\n */\nexport function createRobotsLlmsPolicySnippet(\n options: CreateRobotsLlmsPolicySnippetOptions\n): string {\n const {\n baseUrl,\n allowLlmsTxt = true,\n allowLlmsFullTxt = true,\n allowSitemap = true,\n additionalPaths = [],\n userAgent = '*',\n } = options;\n\n const lines: string[] = ['# LLM SEO'];\n\n // Extract host from baseUrl\n try {\n const url = new URL(baseUrl);\n lines.push(`Host: ${url.host}`);\n } catch {\n // Invalid URL, skip host\n }\n\n lines.push(`User-agent: ${userAgent}`);\n\n if (allowLlmsTxt) {\n lines.push('Allow: /llms.txt');\n }\n\n if (allowLlmsFullTxt) {\n lines.push('Allow: /llms-full.txt');\n }\n\n if (allowSitemap) {\n lines.push('Allow: /sitemap.xml');\n }\n\n for (const path of additionalPaths) {\n lines.push(`Allow: ${path}`);\n }\n\n return lines.join('\\n');\n}\n\n// ============================================================================\n// Next.js Config Helper\n// ============================================================================\n\n/**\n * Options for createNextConfig.\n */\nexport interface CreateNextConfigOptions {\n /** Supported locales */\n locales?: string[];\n /** Default locale */\n defaultLocale?: string;\n /** Whether to use trailing slash */\n trailingSlash?: boolean;\n /** Whether to disable images optimization (for static export) */\n unoptimizedImages?: boolean;\n}\n\n/**\n * Next.js config object returned by createNextConfig.\n */\nexport interface NextConfigResult {\n /** Output mode */\n output: 'export';\n /** Trailing slash configuration */\n trailingSlash: boolean;\n /** Images configuration */\n images: { unoptimized: boolean };\n /** i18n configuration (only if locales provided) */\n i18n?: {\n locales: string[];\n defaultLocale: string;\n };\n}\n\n/**\n * Creates Next.js config object for static export with locales.\n *\n * @param options - Options for config generation\n * @returns Next.js config object\n *\n * @example\n * ```typescript\n * const nextConfig = createNextConfig({\n * locales: ['en', 'uk'],\n * defaultLocale: 'en',\n * trailingSlash: false,\n * });\n *\n * module.exports = nextConfig;\n * ```\n */\nexport function createNextConfig(\n options: CreateNextConfigOptions\n): NextConfigResult {\n const {\n locales = [],\n defaultLocale = 'en',\n trailingSlash = false,\n unoptimizedImages = true,\n } = options;\n\n const config: NextConfigResult = {\n output: 'export',\n trailingSlash,\n images: {\n unoptimized: unoptimizedImages,\n },\n };\n\n // Add i18n config only if locales are provided\n // Note: i18n is not supported with static export in Next.js 13+\n // This is kept for documentation/reference purposes\n if (locales.length > 0) {\n config.i18n = {\n locales,\n defaultLocale,\n };\n }\n\n return config;\n}\n\n// ============================================================================\n// Legacy Build Hooks\n// ============================================================================\n\n/**\n * Options for build hooks.\n */\nexport interface BuildHookOptions {\n /** Output directory for generated files */\n outputDir: string;\n /** Site manifest */\n manifest: SiteManifest;\n /** Whether to generate llms-full.txt */\n generateFull?: boolean;\n}\n\n/**\n * Result of running build hooks.\n */\nexport interface BuildHookResult {\n /** Generated files */\n files: string[];\n /** Whether the hook succeeded */\n success: boolean;\n /** Error message if failed */\n error?: string;\n}\n\n/**\n * Post-build hook that generates llms.txt files.\n * Call this after Next.js static export completes.\n * @param options - Hook options\n * @returns Hook result\n */\nexport async function postBuildHook(\n options: BuildHookOptions\n): Promise<BuildHookResult> {\n const { outputDir, manifest, generateFull = false } = options;\n const files: string[] = [];\n\n try {\n // Generate llms.txt\n generateLlmsTxt(manifest);\n const llmsTxtPath = `${outputDir}/llms.txt`;\n files.push(llmsTxtPath);\n\n // In a real implementation, we would write the file\n // await writeTextFile(llmsTxtPath, llmsTxt);\n\n // Generate llms-full.txt if requested\n if (generateFull) {\n generateLlmsFullTxt(manifest);\n const llmsFullTxtPath = `${outputDir}/llms-full.txt`;\n files.push(llmsFullTxtPath);\n\n // In a real implementation, we would write the file\n // await writeTextFile(llmsFullTxtPath, llmsFullTxt);\n }\n\n return {\n files,\n success: true,\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n return {\n files,\n success: false,\n error: message,\n };\n }\n}\n\n/**\n * Creates a plugin function for Next.js integration.\n * @returns Plugin object with hooks\n */\nexport function createNextPlugin(): {\n name: string;\n postBuild: (options: BuildHookOptions) => Promise<BuildHookResult>;\n} {\n return {\n name: 'llm-seo',\n postBuild: postBuildHook,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/core/normalize/url.ts","../../../src/core/normalize/sort.ts","../../../src/core/canonical/locale.ts","../../../src/core/canonical/canonical-from-manifest.ts","../../../src/adapters/next/manifest.ts","../../../src/core/normalize/text.ts","../../../src/core/generate/llms-txt.ts","../../../src/core/generate/llms-full-txt.ts","../../../src/adapters/next/build-hooks.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 * 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 * Section-level route style for canonical path generation.\n */\nexport type RouteStyle = 'prefix' | 'suffix' | 'locale-segment' | 'custom';\n\n/**\n * Arguments for custom pathname generation.\n */\nexport interface CanonicalPathnameArgs {\n item: ManifestItem;\n sectionName: string;\n slug: string;\n locale: string;\n defaultLocale: string;\n sectionPath: string;\n}\n\n/**\n * Custom path function used when routeStyle=\"custom\".\n */\nexport type CanonicalPathnameFor = (args: CanonicalPathnameArgs) => string;\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 /** Route style for this manifest block */\n routeStyle?: RouteStyle;\n /** Optional section name (used in custom pathname args) */\n sectionName?: string;\n /** Optional section path prefix */\n sectionPath?: string;\n /** Optional custom pathname override for routeStyle=\"custom\" */\n pathnameFor?: CanonicalPathnameFor;\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 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 {\n baseUrl,\n routePrefix,\n defaultLocale,\n trailingSlash,\n localeStrategy,\n routeStyle,\n sectionName,\n sectionPath,\n pathnameFor,\n } = 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 const sectionBase = normalizeSectionPath(sectionPath ?? routePrefix ?? '');\n const effectiveRouteStyle = routeStyle ?? inferRouteStyleFromLocaleStrategy(localeStrategy);\n const normalizedSlug = normalizeItemSlug(item.slug, sectionBase);\n\n const customPath = effectiveRouteStyle === 'custom'\n ? pathnameFor?.({\n item,\n sectionName: sectionName ?? '',\n slug: normalizedSlug,\n locale,\n defaultLocale,\n sectionPath: sectionBase,\n })\n : undefined;\n\n const resolvedPath = customPath ?? buildPathFromRouteStyle({\n routeStyle: effectiveRouteStyle,\n sectionPath: sectionBase,\n slug: normalizedSlug,\n locale,\n defaultLocale,\n });\n\n // Keep existing subdomain support from localeStrategy.\n const effectiveBaseUrl = buildBaseUrlWithSubdomain(baseUrl, locale, localeStrategy, defaultLocale);\n\n // Normalize the URL\n return normalizeUrl({\n baseUrl: effectiveBaseUrl,\n path: resolvedPath,\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\nfunction inferRouteStyleFromLocaleStrategy(strategy: LocaleStrategy): RouteStyle {\n if (strategy !== 'prefix') {\n return 'custom';\n }\n return 'prefix';\n}\n\nfunction buildPathFromRouteStyle(args: {\n routeStyle: RouteStyle;\n sectionPath: string;\n slug: string;\n locale: string;\n defaultLocale: string;\n}): string {\n const { routeStyle, sectionPath, slug, locale, defaultLocale } = args;\n const includeLocale = locale !== defaultLocale;\n\n if (routeStyle === 'locale-segment') {\n return joinUrlParts(sectionPath, locale, slug);\n }\n\n if (routeStyle === 'suffix') {\n if (includeLocale) {\n return joinUrlParts(sectionPath, slug, locale);\n }\n return joinUrlParts(sectionPath, slug);\n }\n\n if (routeStyle === 'custom') {\n // Legacy localeStrategy=\"none\" fallback when custom builder is not provided.\n return joinUrlParts(sectionPath, slug);\n }\n\n // \"prefix\"\n if (includeLocale) {\n return joinUrlParts(locale, sectionPath, slug);\n }\n return joinUrlParts(sectionPath, slug);\n}\n\nfunction normalizeSectionPath(sectionPath: string): string {\n if (!sectionPath || sectionPath === '/') {\n return '';\n }\n return sectionPath.startsWith('/') ? sectionPath : `/${sectionPath}`;\n}\n\nfunction normalizeItemSlug(slug: string, sectionPath: string): string {\n const normalizedSlug = slug.startsWith('/') ? slug : `/${slug}`;\n if (!sectionPath) {\n return normalizedSlug;\n }\n\n if (normalizedSlug === sectionPath) {\n return '/';\n }\n\n const withSlash = `${sectionPath}/`;\n if (normalizedSlug.startsWith(withSlash)) {\n const relative = normalizedSlug.slice(withSlash.length);\n return relative ? `/${relative}` : '/';\n }\n\n return normalizedSlug;\n}\n","/**\n * Manifest generation for Next.js static exports.\n */\n\nimport { existsSync } from 'node:fs';\nimport { readdir, readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { ManifestItem, SiteManifest, PageManifest, BuildManifest } from '../../schema/manifest.schema.js';\nimport type {\n ManifestPathnameFor,\n ManifestSectionConfig,\n RouteStyle,\n} from '../../schema/config.schema.js';\nimport {\n createCanonicalUrlForItem,\n type LocaleStrategy,\n type TrailingSlashPolicy,\n} from '../../core/canonical/canonical-from-manifest.js';\nimport { sortBy } from '../../core/normalize/sort.js';\n\n/**\n * Next.js content manifest structure for fromNextContentManifest.\n */\nexport interface NextContentManifest {\n items: Array<{\n slug: string;\n locales?: string[];\n publishedAt?: string;\n updatedAt?: string;\n title?: string;\n description?: string;\n priority?: number;\n canonicalOverride?: string;\n [key: string]: unknown;\n }>;\n}\n\n/**\n * Options for fromNextContentManifest.\n */\nexport interface FromNextContentManifestOptions {\n /** Prefix to add to all slugs */\n slugPrefix?: string;\n /** Default locale if not specified */\n defaultLocale?: string;\n}\n\n/**\n * Common field mapper for section manifest adapter.\n */\nexport type SectionFieldMapper<TItem> = keyof TItem | ((item: TItem) => string | undefined);\n\n/**\n * Options for createSectionManifest.\n */\nexport interface CreateSectionManifestOptions<TItem extends Record<string, unknown>> {\n /** Source items from a Next.js manifest/data file */\n items: readonly TItem[];\n /** Optional section display name */\n sectionName?: string;\n /** Optional section path, e.g. \"/blog\" */\n sectionPath?: string;\n /** Route style for this section */\n routeStyle?: RouteStyle;\n /** Optional per-section default locale */\n defaultLocale?: string;\n /** Optional per-section locale override */\n defaultLocaleOverride?: string;\n /** Optional custom pathname builder when routeStyle=\"custom\" */\n pathnameFor?: ManifestPathnameFor;\n /** Slug field key */\n slugKey?: keyof TItem;\n /** Locales field key */\n localesKey?: keyof TItem;\n /** Updated date field key */\n updatedAtKey?: keyof TItem;\n /** Published date field key */\n publishedAtKey?: keyof TItem;\n /** Optional priority field key */\n priorityKey?: keyof TItem;\n /** Optional canonical override field key */\n canonicalOverrideKey?: keyof TItem;\n /** Optional title field key/function */\n titleFrom?: SectionFieldMapper<TItem>;\n /** Optional description field key/function */\n descriptionFrom?: SectionFieldMapper<TItem>;\n}\n\n/**\n * Options for applySectionCanonicalOverrides helper.\n */\nexport interface ApplySectionCanonicalOverridesOptions {\n /** Section manifest generated by createSectionManifest */\n section: ManifestSectionConfig;\n /** Site base URL */\n baseUrl: string;\n /** Default locale */\n defaultLocale: string;\n /** Trailing slash strategy */\n trailingSlash?: TrailingSlashPolicy;\n /** Locale strategy */\n localeStrategy?: LocaleStrategy;\n}\n\n/**\n * Converts Next.js content manifest to llm-seo ManifestItem[].\n *\n * @param manifest - Next.js content manifest\n * @param options - Conversion options\n * @returns Normalized ManifestItem[] for use in config\n */\nexport function fromNextContentManifest(\n manifest: NextContentManifest,\n options: FromNextContentManifestOptions = {}\n): ManifestItem[] {\n const { slugPrefix = '', defaultLocale } = options;\n\n return manifest.items.map((item): ManifestItem => {\n const result: ManifestItem = {\n slug: slugPrefix + item.slug,\n };\n\n if (item.locales !== undefined) {\n result.locales = item.locales;\n } else if (defaultLocale !== undefined) {\n result.locales = [defaultLocale];\n }\n\n if (item.publishedAt !== undefined) {\n result.publishedAt = item.publishedAt;\n }\n\n if (item.updatedAt !== undefined) {\n result.updatedAt = item.updatedAt;\n }\n\n if (item.title !== undefined) {\n result.title = item.title;\n }\n\n if (item.description !== undefined) {\n result.description = item.description;\n }\n\n if (item.priority !== undefined) {\n result.priority = item.priority;\n }\n\n if (item.canonicalOverride !== undefined) {\n result.canonicalOverride = item.canonicalOverride;\n }\n\n return result;\n });\n}\n\n/**\n * Creates a section-level manifest config from arbitrary Next.js content arrays.\n * Output is ready to assign into config.manifests.<section>.\n */\nexport function createSectionManifest<TItem extends Record<string, unknown>>(\n options: CreateSectionManifestOptions<TItem>\n): ManifestSectionConfig {\n const {\n items,\n sectionName,\n sectionPath,\n routeStyle,\n defaultLocale,\n defaultLocaleOverride,\n pathnameFor,\n slugKey = 'slug' as keyof TItem,\n localesKey = 'locales' as keyof TItem,\n updatedAtKey = 'updatedAt' as keyof TItem,\n publishedAtKey = 'publishedAt' as keyof TItem,\n priorityKey = 'priority' as keyof TItem,\n canonicalOverrideKey = 'canonicalOverride' as keyof TItem,\n titleFrom = 'title' as keyof TItem,\n descriptionFrom = 'description' as keyof TItem,\n } = options;\n\n const normalizedItems: ManifestItem[] = items\n .map((item) => {\n const rawSlug = readStringField(item, slugKey);\n if (!rawSlug) {\n return null;\n }\n\n const normalized: ManifestItem = {\n slug: rawSlug.startsWith('/') ? rawSlug : `/${rawSlug}`,\n };\n\n const locales = readStringArrayField(item, localesKey);\n if (locales.length > 0) {\n normalized.locales = locales;\n } else if (defaultLocale) {\n normalized.locales = [defaultLocale];\n }\n\n const updatedAt = readStringField(item, updatedAtKey);\n if (updatedAt) {\n normalized.updatedAt = updatedAt;\n }\n\n const publishedAt = readStringField(item, publishedAtKey);\n if (publishedAt) {\n normalized.publishedAt = publishedAt;\n }\n\n const priority = readNumberField(item, priorityKey);\n if (priority !== undefined) {\n normalized.priority = priority;\n }\n\n const canonicalOverride = readStringField(item, canonicalOverrideKey);\n if (canonicalOverride) {\n normalized.canonicalOverride = canonicalOverride;\n }\n\n const title = readMappedString(item, titleFrom);\n if (title) {\n normalized.title = title;\n }\n\n const description = readMappedString(item, descriptionFrom);\n if (description) {\n normalized.description = description;\n }\n\n return normalized;\n })\n .filter((item): item is ManifestItem => item !== null);\n\n const sortedItems = sortBy(normalizedItems, (item) => {\n const locales = item.locales?.join(',') ?? '';\n return `${item.slug}|${locales}`;\n });\n\n return {\n items: sortedItems,\n ...(sectionName && { sectionName }),\n ...(sectionPath && { sectionPath }),\n ...(routeStyle && { routeStyle }),\n ...(defaultLocaleOverride && { defaultLocaleOverride }),\n ...(pathnameFor && { pathnameFor }),\n };\n}\n\n/**\n * Applies canonicalOverride values to each item in a section\n * based on the section routing strategy and base URL.\n */\nexport function applySectionCanonicalOverrides(\n options: ApplySectionCanonicalOverridesOptions\n): ManifestSectionConfig {\n const {\n section,\n baseUrl,\n defaultLocale,\n trailingSlash = 'never',\n localeStrategy = 'prefix',\n } = options;\n\n const mappedItems = section.items.map((item) => {\n const canonicalOptions = {\n baseUrl,\n defaultLocale: section.defaultLocaleOverride ?? defaultLocale,\n trailingSlash,\n localeStrategy,\n ...(section.routeStyle && { routeStyle: section.routeStyle }),\n ...(section.sectionPath && {\n sectionPath: section.sectionPath,\n routePrefix: section.sectionPath,\n }),\n ...(section.sectionName && { sectionName: section.sectionName }),\n ...(section.pathnameFor && { pathnameFor: section.pathnameFor }),\n };\n const canonicalOverride = createCanonicalUrlForItem(item, canonicalOptions);\n return {\n ...item,\n canonicalOverride,\n };\n });\n\n return {\n ...section,\n items: mappedItems,\n };\n}\n\nfunction readStringField<TItem extends Record<string, unknown>>(\n item: TItem,\n key: keyof TItem\n): string | undefined {\n const value = item[key];\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction readNumberField<TItem extends Record<string, unknown>>(\n item: TItem,\n key: keyof TItem\n): number | undefined {\n const value = item[key];\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction readStringArrayField<TItem extends Record<string, unknown>>(\n item: TItem,\n key: keyof TItem\n): string[] {\n const value = item[key];\n if (!Array.isArray(value)) {\n return [];\n }\n return value.filter((entry): entry is string => typeof entry === 'string' && entry.length > 0);\n}\n\nfunction readMappedString<TItem extends Record<string, unknown>>(\n item: TItem,\n mapper: SectionFieldMapper<TItem>\n): string | undefined {\n if (typeof mapper === 'function') {\n const value = mapper(item);\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n }\n return readStringField(item, mapper);\n}\n\n/**\n * Options for createManifestFromPagesDir.\n */\nexport interface CreateManifestFromPagesDirOptions {\n /** Path to pages directory */\n pagesDir: string;\n /** Prefix to add to all routes */\n routePrefix?: string;\n /** Default locale for items */\n defaultLocale?: string;\n /** File extensions to include */\n extensions?: string[];\n}\n\n/**\n * Parsed frontmatter from a file.\n */\ninterface ParsedFrontmatter {\n title?: string;\n description?: string;\n date?: string;\n updated?: string;\n locale?: string;\n locales?: string[];\n priority?: number;\n [key: string]: unknown;\n}\n\n/**\n * Parses YAML-like frontmatter from content.\n * Simple implementation for basic frontmatter extraction.\n *\n * @param content - File content with potential frontmatter\n * @returns Parsed frontmatter and body content\n */\nfunction parseFrontmatter(content: string): { frontmatter: ParsedFrontmatter; body: string } {\n const frontmatterRegex = /^---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n([\\s\\S]*)$/;\n const match = content.match(frontmatterRegex);\n\n if (!match) {\n return { frontmatter: {}, body: content };\n }\n\n const frontmatterText = match[1] ?? '';\n const body = match[2] ?? content;\n const frontmatter: ParsedFrontmatter = {};\n\n // Simple YAML-like parsing\n const lines = frontmatterText.split('\\n');\n for (const line of lines) {\n const colonIndex = line.indexOf(':');\n if (colonIndex === -1) continue;\n\n const key = line.slice(0, colonIndex).trim();\n let value: string | string[] = line.slice(colonIndex + 1).trim();\n\n // Handle arrays in format [item1, item2]\n if (value.startsWith('[') && value.endsWith(']')) {\n value = value\n .slice(1, -1)\n .split(',')\n .map((item) => item.trim().replace(/^['\"]|['\"]$/g, ''))\n .filter((item) => item.length > 0);\n } else {\n // Remove quotes\n value = value.replace(/^['\"]|['\"]$/g, '');\n }\n\n // Map to frontmatter fields\n if (key === 'title') frontmatter.title = value as string;\n else if (key === 'description') frontmatter.description = value as string;\n else if (key === 'date' || key === 'publishedAt') frontmatter.date = value as string;\n else if (key === 'updated' || key === 'updatedAt') frontmatter.updated = value as string;\n else if (key === 'locale') frontmatter.locale = value as string;\n else if (key === 'locales') frontmatter.locales = value as string[];\n else if (key === 'priority') frontmatter.priority = parseInt(value as string, 10);\n else frontmatter[key] = value;\n }\n\n return { frontmatter, body };\n}\n\n/**\n * Converts file path to URL slug.\n *\n * @param filePath - File path relative to pages dir\n * @param extensions - File extensions to strip\n * @returns URL slug\n */\nfunction filePathToSlug(filePath: string, extensions: string[]): string {\n let slug = filePath;\n\n // Remove extension\n for (const ext of extensions) {\n if (slug.endsWith(ext)) {\n slug = slug.slice(0, -ext.length);\n break;\n }\n }\n\n // Handle index files\n if (slug.endsWith('/index')) {\n slug = slug.slice(0, -6);\n }\n if (slug === 'index') {\n slug = '';\n }\n\n // Ensure leading slash\n if (!slug.startsWith('/')) {\n slug = '/' + slug;\n }\n\n return slug || '/';\n}\n\n/**\n * Recursively scans directory for content files.\n *\n * @param dir - Directory to scan\n * @param extensions - File extensions to include\n * @param basePath - Base path for relative paths\n * @returns Array of relative file paths\n */\nasync function scanDirectory(\n dir: string,\n extensions: string[],\n basePath: string = ''\n): Promise<string[]> {\n const files: string[] = [];\n\n if (!existsSync(dir)) {\n return files;\n }\n\n const entries = await readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n const relativePath = basePath ? join(basePath, entry.name) : entry.name;\n\n if (entry.isDirectory()) {\n const subFiles = await scanDirectory(fullPath, extensions, relativePath);\n files.push(...subFiles);\n } else if (entry.isFile()) {\n const hasValidExtension = extensions.some((ext) => entry.name.endsWith(ext));\n if (hasValidExtension) {\n files.push(relativePath);\n }\n }\n }\n\n return files;\n}\n\n/**\n * Creates manifest from Next.js pages directory.\n * Scans for .mdx, .md files and extracts frontmatter.\n *\n * @param options - Options for manifest creation\n * @returns Promise resolving to ManifestItem[]\n */\nexport async function createManifestFromPagesDir(\n options: CreateManifestFromPagesDirOptions\n): Promise<ManifestItem[]> {\n const {\n pagesDir,\n routePrefix = '',\n defaultLocale,\n extensions = ['.mdx', '.md'],\n } = options;\n\n const files = await scanDirectory(pagesDir, extensions);\n const items: ManifestItem[] = [];\n\n for (const file of files) {\n const fullPath = join(pagesDir, file);\n const content = await readFile(fullPath, 'utf-8');\n const { frontmatter } = parseFrontmatter(content);\n\n const slug = routePrefix + filePathToSlug(file, extensions);\n\n const item: ManifestItem = {\n slug,\n };\n\n if (frontmatter.locales !== undefined) {\n item.locales = frontmatter.locales;\n } else if (frontmatter.locale !== undefined) {\n item.locales = [frontmatter.locale];\n } else if (defaultLocale !== undefined) {\n item.locales = [defaultLocale];\n }\n\n if (frontmatter.date !== undefined) {\n item.publishedAt = frontmatter.date;\n }\n\n if (frontmatter.updated !== undefined) {\n item.updatedAt = frontmatter.updated;\n }\n\n if (frontmatter.title !== undefined) {\n item.title = frontmatter.title;\n }\n\n if (frontmatter.description !== undefined) {\n item.description = frontmatter.description;\n }\n\n if (frontmatter.priority !== undefined) {\n item.priority = frontmatter.priority;\n }\n\n items.push(item);\n }\n\n // Sort by slug for deterministic output\n return items.sort((a, b) => a.slug.localeCompare(b.slug));\n}\n\n/**\n * Options for createManifestFromData.\n */\nexport interface CreateManifestFromDataOptions {\n /** Prefix to add to all slugs */\n slugPrefix?: string;\n /** Default locale if not specified */\n defaultLocale?: string;\n}\n\n/**\n * Creates manifest from Next.js data (getStaticProps data).\n *\n * @param items - Array of items from getStaticProps\n * @param options - Options for manifest creation\n * @returns ManifestItem[]\n */\nexport function createManifestFromData(\n items: Array<{\n params: { slug: string | string[] };\n locale?: string;\n publishedAt?: string;\n updatedAt?: string;\n title?: string;\n description?: string;\n priority?: number;\n [key: string]: unknown;\n }>,\n options: CreateManifestFromDataOptions = {}\n): ManifestItem[] {\n const { slugPrefix = '', defaultLocale } = options;\n\n return items.map((item): ManifestItem => {\n // Convert slug array or string to path\n const slugPath = Array.isArray(item.params.slug)\n ? '/' + item.params.slug.join('/')\n : item.params.slug.startsWith('/')\n ? item.params.slug\n : '/' + item.params.slug;\n\n const result: ManifestItem = {\n slug: slugPrefix + slugPath,\n };\n\n if (item.locale !== undefined) {\n result.locales = [item.locale];\n } else if (defaultLocale !== undefined) {\n result.locales = [defaultLocale];\n }\n\n if (item.publishedAt !== undefined) {\n result.publishedAt = item.publishedAt;\n }\n\n if (item.updatedAt !== undefined) {\n result.updatedAt = item.updatedAt;\n }\n\n if (item.title !== undefined) {\n result.title = item.title;\n }\n\n if (item.description !== undefined) {\n result.description = item.description;\n }\n\n if (item.priority !== undefined) {\n result.priority = item.priority;\n }\n\n return result;\n });\n}\n\n// ============================================================================\n// Legacy functions - kept for backwards compatibility\n// ============================================================================\n\n/**\n * Options for Next.js manifest generation.\n */\nexport interface NextManifestOptions {\n /** Base URL for the site */\n baseUrl: string;\n /** Site title */\n title: string;\n /** Site description */\n description?: string;\n /** Path to the Next.js build manifest */\n buildManifestPath?: string;\n}\n\n/**\n * Extracts page paths from Next.js build manifest.\n * @param buildManifest - The Next.js build manifest\n * @returns Array of page paths\n */\nexport function extractPagePaths(buildManifest: BuildManifest): string[] {\n const pages: string[] = [];\n\n // Extract from static pages\n for (const pagePath of Object.keys(buildManifest.pages)) {\n // Skip Next.js internal routes\n if (pagePath.startsWith('/_')) {\n continue;\n }\n\n // Normalize the path\n const normalizedPath = normalizeNextPath(pagePath);\n pages.push(normalizedPath);\n }\n\n // Sort for deterministic output\n return pages.sort((a, b) => a.localeCompare(b));\n}\n\n/**\n * Normalizes a Next.js page path.\n * @param path - The page path\n * @returns Normalized path\n */\nfunction normalizeNextPath(path: string): string {\n // Remove file extension if present\n let normalized = path.replace(/\\.(html|json)$/, '');\n\n // Handle index pages\n if (normalized === '/index' || normalized === '') {\n normalized = '/';\n }\n\n // Ensure leading slash\n if (!normalized.startsWith('/')) {\n normalized = `/${normalized}`;\n }\n\n return normalized;\n}\n\n/**\n * Generates a site manifest from Next.js build output.\n * @param options - Manifest generation options\n * @param buildManifest - Optional build manifest\n * @returns Generated site manifest\n */\nexport function generateNextManifest(\n options: NextManifestOptions,\n buildManifest?: BuildManifest\n): SiteManifest {\n const pages: PageManifest[] = [];\n\n if (buildManifest) {\n const pagePaths = extractPagePaths(buildManifest);\n\n for (const path of pagePaths) {\n pages.push({\n path,\n title: undefined, // Will be filled by crawler or manually\n description: undefined,\n optional: false,\n });\n }\n }\n\n return {\n baseUrl: options.baseUrl,\n title: options.title,\n description: options.description,\n pages,\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 * 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 /** Optional manifest entries with canonical URLs per item */\n manifestEntries?: ReadonlyArray<{\n item: ManifestItem;\n canonicalUrl: string;\n sectionName: string;\n }>;\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, manifestEntries } = 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\n const lastUpdated = getLastUpdatedDate(manifestItems);\n if (lastUpdated) {\n lines.push(`Last Updated: ${lastUpdated}`);\n }\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 // Contact\n const hasContact = config.contact?.email ||\n config.contact?.phone ||\n config.contact?.social?.twitter ||\n config.contact?.social?.linkedin ||\n config.contact?.social?.github ||\n config.booking?.url;\n if (hasContact) {\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?.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 (manifestEntries && manifestEntries.length > 0) {\n const sortedEntries = sortBy(manifestEntries, (entry) => {\n return `${entry.item.slug}|${entry.canonicalUrl}`;\n });\n for (const entry of sortedEntries) {\n const title = entry.item.title ?? entry.item.slug;\n const locales = entry.item.locales?.join(', ') ?? config.brand.locales[0] ?? 'en';\n lines.push(`- [${title}](${entry.canonicalUrl}) (${locales})`);\n }\n } else 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\nfunction getLastUpdatedDate(items: ManifestItem[]): string | null {\n const timestamps: string[] = [];\n for (const item of items) {\n if (item.updatedAt) {\n timestamps.push(item.updatedAt);\n } else if (item.publishedAt) {\n timestamps.push(item.publishedAt);\n }\n }\n\n if (timestamps.length === 0) {\n return null;\n }\n\n const latest = timestamps\n .map((value) => new Date(value))\n .filter((value) => !Number.isNaN(value.getTime()))\n .sort((a, b) => b.getTime() - a.getTime())[0];\n\n if (!latest) {\n return null;\n }\n\n return latest.toISOString().slice(0, 10);\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","/**\n * Build hooks for Next.js integration.\n */\n\nimport type { SiteManifest } from '../../schema/manifest.schema.js';\nimport { generateLlmsTxt } from '../../core/generate/llms-txt.js';\nimport { generateLlmsFullTxt } from '../../core/generate/llms-full-txt.js';\n\n// ============================================================================\n// Build Scripts Generation\n// ============================================================================\n\n/**\n * Options for generateBuildScripts.\n */\nexport interface GenerateBuildScriptsOptions {\n /** Path to config file */\n configPath?: string;\n /** Output directory for generated files */\n outputPath?: string;\n /** Whether to emit citations.json */\n emitCitations?: boolean;\n /** Package manager to use */\n packageManager?: 'npm' | 'yarn' | 'pnpm';\n}\n\n/**\n * Result of generateBuildScripts.\n */\nexport interface BuildScriptsResult {\n /** Script for building SEO artifacts */\n 'build:seo': string;\n /** Post-build hook script */\n postbuild: string;\n /** Script for checking SEO artifacts */\n 'check:seo': string;\n}\n\n/**\n * Generates package.json scripts for llm-seo integration.\n *\n * @param options - Options for script generation\n * @returns Object with script names as keys and commands as values\n *\n * @example\n * ```typescript\n * const scripts = generateBuildScripts({\n * configPath: 'llm-seo.config.ts',\n * emitCitations: true,\n * });\n * // Returns:\n * // {\n * // \"build:seo\": \"llm-seo generate --config llm-seo.config.ts\",\n * // \"postbuild\": \"pnpm build:seo && llm-seo check --fail-on error\",\n * // \"check:seo\": \"llm-seo check --fail-on warn\"\n * // }\n * ```\n */\nexport function generateBuildScripts(\n options: GenerateBuildScriptsOptions = {}\n): BuildScriptsResult {\n const {\n configPath = 'llm-seo.config.ts',\n emitCitations = false,\n packageManager = 'pnpm',\n } = options;\n\n const configFlag = `--config ${configPath}`;\n const citationsFlag = emitCitations ? ' --emit-citations' : '';\n\n const runCommand = packageManager === 'npm' ? 'npm run' : packageManager;\n\n return {\n 'build:seo': `llm-seo generate ${configFlag}${citationsFlag}`,\n postbuild: `${runCommand} build:seo && llm-seo check --fail-on error`,\n 'check:seo': 'llm-seo check --fail-on warn',\n };\n}\n\n// ============================================================================\n// Robots.txt LLM Policy\n// ============================================================================\n\n/**\n * Options for createRobotsLlmsPolicySnippet.\n */\nexport interface CreateRobotsLlmsPolicySnippetOptions {\n /** Base URL of the site */\n baseUrl: string;\n /** Whether to allow llms.txt */\n allowLlmsTxt?: boolean;\n /** Whether to allow llms-full.txt */\n allowLlmsFullTxt?: boolean;\n /** Whether to allow sitemap.xml */\n allowSitemap?: boolean;\n /** Additional paths to allow */\n additionalPaths?: string[];\n /** User agent to target (default: *) */\n userAgent?: string;\n}\n\n/**\n * Creates robots.txt LLM policy snippet.\n *\n * @param options - Options for snippet generation\n * @returns robots.txt snippet string\n *\n * @example\n * ```typescript\n * const snippet = createRobotsLlmsPolicySnippet({\n * baseUrl: 'https://example.com',\n * allowLlmsTxt: true,\n * allowLlmsFullTxt: true,\n * });\n * // Returns:\n * // # LLM SEO\n * // User-agent: *\n * // Allow: /llms.txt\n * // Allow: /llms-full.txt\n * // Allow: /sitemap.xml\n * ```\n */\nexport function createRobotsLlmsPolicySnippet(\n options: CreateRobotsLlmsPolicySnippetOptions\n): string {\n const {\n baseUrl,\n allowLlmsTxt = true,\n allowLlmsFullTxt = true,\n allowSitemap = true,\n additionalPaths = [],\n userAgent = '*',\n } = options;\n\n const lines: string[] = ['# LLM SEO'];\n\n // Extract host from baseUrl\n try {\n const url = new URL(baseUrl);\n lines.push(`Host: ${url.host}`);\n } catch {\n // Invalid URL, skip host\n }\n\n lines.push(`User-agent: ${userAgent}`);\n\n if (allowLlmsTxt) {\n lines.push('Allow: /llms.txt');\n }\n\n if (allowLlmsFullTxt) {\n lines.push('Allow: /llms-full.txt');\n }\n\n if (allowSitemap) {\n lines.push('Allow: /sitemap.xml');\n }\n\n for (const path of additionalPaths) {\n lines.push(`Allow: ${path}`);\n }\n\n return lines.join('\\n');\n}\n\n// ============================================================================\n// Next.js Config Helper\n// ============================================================================\n\n/**\n * Options for createNextConfig.\n */\nexport interface CreateNextConfigOptions {\n /** Supported locales */\n locales?: string[];\n /** Default locale */\n defaultLocale?: string;\n /** Whether to use trailing slash */\n trailingSlash?: boolean;\n /** Whether to disable images optimization (for static export) */\n unoptimizedImages?: boolean;\n}\n\n/**\n * Next.js config object returned by createNextConfig.\n */\nexport interface NextConfigResult {\n /** Output mode */\n output: 'export';\n /** Trailing slash configuration */\n trailingSlash: boolean;\n /** Images configuration */\n images: { unoptimized: boolean };\n /** i18n configuration (only if locales provided) */\n i18n?: {\n locales: string[];\n defaultLocale: string;\n };\n}\n\n/**\n * Creates Next.js config object for static export with locales.\n *\n * @param options - Options for config generation\n * @returns Next.js config object\n *\n * @example\n * ```typescript\n * const nextConfig = createNextConfig({\n * locales: ['en', 'uk'],\n * defaultLocale: 'en',\n * trailingSlash: false,\n * });\n *\n * module.exports = nextConfig;\n * ```\n */\nexport function createNextConfig(\n options: CreateNextConfigOptions\n): NextConfigResult {\n const {\n locales = [],\n defaultLocale = 'en',\n trailingSlash = false,\n unoptimizedImages = true,\n } = options;\n\n const config: NextConfigResult = {\n output: 'export',\n trailingSlash,\n images: {\n unoptimized: unoptimizedImages,\n },\n };\n\n // Add i18n config only if locales are provided\n // Note: i18n is not supported with static export in Next.js 13+\n // This is kept for documentation/reference purposes\n if (locales.length > 0) {\n config.i18n = {\n locales,\n defaultLocale,\n };\n }\n\n return config;\n}\n\n// ============================================================================\n// Legacy Build Hooks\n// ============================================================================\n\n/**\n * Options for build hooks.\n */\nexport interface BuildHookOptions {\n /** Output directory for generated files */\n outputDir: string;\n /** Site manifest */\n manifest: SiteManifest;\n /** Whether to generate llms-full.txt */\n generateFull?: boolean;\n}\n\n/**\n * Result of running build hooks.\n */\nexport interface BuildHookResult {\n /** Generated files */\n files: string[];\n /** Whether the hook succeeded */\n success: boolean;\n /** Error message if failed */\n error?: string;\n}\n\n/**\n * Post-build hook that generates llms.txt files.\n * Call this after Next.js static export completes.\n * @param options - Hook options\n * @returns Hook result\n */\nexport async function postBuildHook(\n options: BuildHookOptions\n): Promise<BuildHookResult> {\n const { outputDir, manifest, generateFull = false } = options;\n const files: string[] = [];\n\n try {\n // Generate llms.txt\n generateLlmsTxt(manifest);\n const llmsTxtPath = `${outputDir}/llms.txt`;\n files.push(llmsTxtPath);\n\n // In a real implementation, we would write the file\n // await writeTextFile(llmsTxtPath, llmsTxt);\n\n // Generate llms-full.txt if requested\n if (generateFull) {\n generateLlmsFullTxt(manifest);\n const llmsFullTxtPath = `${outputDir}/llms-full.txt`;\n files.push(llmsFullTxtPath);\n\n // In a real implementation, we would write the file\n // await writeTextFile(llmsFullTxtPath, llmsFullTxt);\n }\n\n return {\n files,\n success: true,\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n return {\n files,\n success: false,\n error: message,\n };\n }\n}\n\n/**\n * Creates a plugin function for Next.js integration.\n * @returns Plugin object with hooks\n */\nexport function createNextPlugin(): {\n name: string;\n postBuild: (options: BuildHookOptions) => Promise<BuildHookResult>;\n} {\n return {\n name: 'llm-seo',\n postBuild: postBuildHook,\n };\n}\n"]}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { q as ManifestItem, S as SiteManifest } from './config.schema-CI5OBbhQ.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Canonical URL generation from site manifests.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Options for canonical URL generation.
|
|
9
|
+
*/
|
|
10
|
+
interface CanonicalOptions {
|
|
11
|
+
/** Whether to include trailing slash (default: false) */
|
|
12
|
+
trailingSlash?: boolean;
|
|
13
|
+
/** Whether to use lowercase (default: true) */
|
|
14
|
+
lowercase?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Locale strategy for URL generation.
|
|
18
|
+
*/
|
|
19
|
+
type LocaleStrategy = 'prefix' | 'subdomain' | 'none';
|
|
20
|
+
/**
|
|
21
|
+
* Trailing slash policy.
|
|
22
|
+
*/
|
|
23
|
+
type TrailingSlashPolicy = 'always' | 'never' | 'preserve';
|
|
24
|
+
/**
|
|
25
|
+
* Section-level route style for canonical path generation.
|
|
26
|
+
*/
|
|
27
|
+
type RouteStyle = 'prefix' | 'suffix' | 'locale-segment' | 'custom';
|
|
28
|
+
/**
|
|
29
|
+
* Arguments for custom pathname generation.
|
|
30
|
+
*/
|
|
31
|
+
interface CanonicalPathnameArgs {
|
|
32
|
+
item: ManifestItem;
|
|
33
|
+
sectionName: string;
|
|
34
|
+
slug: string;
|
|
35
|
+
locale: string;
|
|
36
|
+
defaultLocale: string;
|
|
37
|
+
sectionPath: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Custom path function used when routeStyle="custom".
|
|
41
|
+
*/
|
|
42
|
+
type CanonicalPathnameFor = (args: CanonicalPathnameArgs) => string;
|
|
43
|
+
/**
|
|
44
|
+
* Options for creating canonical URLs from manifest.
|
|
45
|
+
*/
|
|
46
|
+
interface CreateCanonicalUrlsOptions {
|
|
47
|
+
/** Array of manifest items */
|
|
48
|
+
items: ManifestItem[];
|
|
49
|
+
/** Base URL e.g., "https://example.com" */
|
|
50
|
+
baseUrl: string;
|
|
51
|
+
/** Route prefix e.g., "/blog" for blog posts */
|
|
52
|
+
routePrefix?: string;
|
|
53
|
+
/** Default locale code */
|
|
54
|
+
defaultLocale: string;
|
|
55
|
+
/** Trailing slash policy */
|
|
56
|
+
trailingSlash: TrailingSlashPolicy;
|
|
57
|
+
/** Locale URL strategy */
|
|
58
|
+
localeStrategy: LocaleStrategy;
|
|
59
|
+
/** Route style for this manifest block */
|
|
60
|
+
routeStyle?: RouteStyle;
|
|
61
|
+
/** Optional section name (used in custom pathname args) */
|
|
62
|
+
sectionName?: string;
|
|
63
|
+
/** Optional section path prefix */
|
|
64
|
+
sectionPath?: string;
|
|
65
|
+
/** Optional custom pathname override for routeStyle="custom" */
|
|
66
|
+
pathnameFor?: CanonicalPathnameFor;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Generates a canonical URL for a given path from the site manifest.
|
|
70
|
+
* @param manifest - The site manifest containing base URL information
|
|
71
|
+
* @param path - The path to generate canonical URL for
|
|
72
|
+
* @param options - Canonical URL options
|
|
73
|
+
* @returns The canonical URL
|
|
74
|
+
*/
|
|
75
|
+
declare function generateCanonicalUrl(manifest: SiteManifest, path: string, options?: CanonicalOptions): string;
|
|
76
|
+
/**
|
|
77
|
+
* Extracts all canonical URLs from a site manifest.
|
|
78
|
+
* @param manifest - The site manifest
|
|
79
|
+
* @param options - Canonical URL options
|
|
80
|
+
* @returns Array of canonical URLs
|
|
81
|
+
*/
|
|
82
|
+
declare function extractCanonicalUrls(manifest: SiteManifest, options?: CanonicalOptions): string[];
|
|
83
|
+
/**
|
|
84
|
+
* Deduplicates URLs by converting to Set and back.
|
|
85
|
+
* @param urls - Array of URLs to deduplicate
|
|
86
|
+
* @returns Array of unique URLs
|
|
87
|
+
*/
|
|
88
|
+
declare function dedupeUrls(urls: string[]): string[];
|
|
89
|
+
/**
|
|
90
|
+
* Creates a single canonical URL for a manifest item.
|
|
91
|
+
* @param item - The manifest item
|
|
92
|
+
* @param options - Options for URL creation (without items array)
|
|
93
|
+
* @returns The canonical URL string
|
|
94
|
+
*/
|
|
95
|
+
declare function createCanonicalUrlForItem(item: ManifestItem, options: Omit<CreateCanonicalUrlsOptions, 'items'>): string;
|
|
96
|
+
/**
|
|
97
|
+
* Creates canonical URLs from manifest items:
|
|
98
|
+
* 1. For each item, select canonical locale
|
|
99
|
+
* 2. Build URL: baseUrl + localePrefix (if strategy=prefix) + routePrefix + slug
|
|
100
|
+
* 3. Apply trailing slash policy
|
|
101
|
+
* 4. Normalize URL
|
|
102
|
+
* 5. Dedupe (by URL string)
|
|
103
|
+
* 6. Sort stably
|
|
104
|
+
* @param options - Options for URL creation
|
|
105
|
+
* @returns Sorted array of canonical URLs
|
|
106
|
+
*/
|
|
107
|
+
declare function createCanonicalUrlsFromManifest(options: CreateCanonicalUrlsOptions): string[];
|
|
108
|
+
|
|
109
|
+
export { type CanonicalOptions as C, type LocaleStrategy as L, type RouteStyle as R, type TrailingSlashPolicy as T, type CanonicalPathnameArgs as a, type CanonicalPathnameFor as b, type CreateCanonicalUrlsOptions as c, createCanonicalUrlForItem as d, createCanonicalUrlsFromManifest as e, dedupeUrls as f, extractCanonicalUrls as g, generateCanonicalUrl as h };
|