@pas7/llm-seo 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +164 -0
- package/dist/adapters/index.d.ts +3 -0
- package/dist/adapters/index.js +673 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/next/index.d.ts +292 -0
- package/dist/adapters/next/index.js +673 -0
- package/dist/adapters/next/index.js.map +1 -0
- package/dist/cli/bin.d.ts +1 -0
- package/dist/cli/bin.js +2232 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/config.schema-DCnBx3Gm.d.ts +824 -0
- package/dist/core/index.d.ts +752 -0
- package/dist/core/index.js +1330 -0
- package/dist/core/index.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +1909 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.schema-B_z3rxRV.d.ts +384 -0
- package/dist/schema/index.d.ts +72 -0
- package/dist/schema/index.js +422 -0
- package/dist/schema/index.js.map +1 -0
- package/package.json +83 -0
|
@@ -0,0 +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}\n\n/**\n * Result of llms-full.txt generation.\n */\nexport interface CreateLlmsFullTxtResult {\n /** Generated llms-full.txt content */\n content: string;\n /** Size in bytes */\n byteSize: number;\n /** Number of lines */\n lineCount: number;\n}\n\n/**\n * Creates llms-full.txt content with deterministic output.\n * - Complete context with all URLs\n * - Detailed policy sections\n * - Social and booking info\n * - EOL controlled by config.format.lineEndings\n * @param options - Generation options\n * @returns Generated content with metadata\n */\nexport function createLlmsFullTxt(options: CreateLlmsFullTxtOptions): CreateLlmsFullTxtResult {\n const { config, canonicalUrls, manifestItems } = options;\n const lineEndings = config.format?.lineEndings ?? 'lf';\n const lines: string[] = [];\n\n // Header\n lines.push(`# ${config.brand.name} - Full LLM Context`);\n lines.push('');\n\n if (config.brand.tagline) {\n lines.push(`> ${config.brand.tagline}`);\n lines.push('');\n }\n\n // Brand description\n if (config.brand.description) {\n lines.push(config.brand.description);\n lines.push('');\n }\n\n // Organization and locales\n if (config.brand.org) {\n lines.push(`Organization: ${config.brand.org}`);\n }\n lines.push(`Locales: ${config.brand.locales.join(', ')}`);\n lines.push('');\n\n // All Canonical URLs\n if (canonicalUrls.length > 0) {\n lines.push('## All Canonical URLs');\n lines.push('');\n const sortedUrls = sortStrings(canonicalUrls);\n for (const url of sortedUrls) {\n lines.push(`- ${url}`);\n }\n lines.push('');\n }\n\n // Policies\n const hasPolicies = config.policy?.geoPolicy || config.policy?.citationRules || config.policy?.restrictedClaims;\n if (hasPolicies) {\n lines.push('## Policies');\n lines.push('');\n\n // GEO Policy\n if (config.policy?.geoPolicy) {\n lines.push('### GEO Policy');\n lines.push(config.policy.geoPolicy);\n lines.push('');\n }\n\n // Citation Rules\n if (config.policy?.citationRules) {\n lines.push('### Citation Rules');\n lines.push(config.policy.citationRules);\n lines.push('');\n }\n\n // Restricted Claims\n if (config.policy?.restrictedClaims) {\n lines.push('### Restricted Claims');\n const status = config.policy.restrictedClaims.enable ? 'Enabled' : 'Disabled';\n lines.push(`Status: ${status}`);\n \n if (config.policy.restrictedClaims.forbidden && config.policy.restrictedClaims.forbidden.length > 0) {\n lines.push(`Forbidden terms: ${config.policy.restrictedClaims.forbidden.join(', ')}`);\n }\n \n if (config.policy.restrictedClaims.whitelist && config.policy.restrictedClaims.whitelist.length > 0) {\n lines.push(`Exceptions: ${config.policy.restrictedClaims.whitelist.join(', ')}`);\n }\n \n lines.push('');\n }\n }\n\n // Social & Booking\n const hasSocial = config.contact?.social?.twitter || \n config.contact?.social?.linkedin || \n config.contact?.social?.github;\n const hasBooking = config.booking?.url;\n \n if (hasSocial || hasBooking) {\n lines.push('## Social & Booking');\n lines.push('');\n\n if (config.contact?.social?.twitter) {\n lines.push(`- Twitter: ${config.contact.social.twitter}`);\n }\n\n if (config.contact?.social?.linkedin) {\n lines.push(`- LinkedIn: ${config.contact.social.linkedin}`);\n }\n\n if (config.contact?.social?.github) {\n lines.push(`- GitHub: ${config.contact.social.github}`);\n }\n\n if (config.booking?.url) {\n const label = config.booking.label ?? 'Book consultation';\n lines.push(`- Booking: ${config.booking.url} (${label})`);\n }\n\n lines.push('');\n }\n\n // Machine Hints\n const hasMachineHints = config.machineHints?.robots || \n config.machineHints?.sitemap || \n config.machineHints?.llmsTxt || \n config.machineHints?.llmsFullTxt;\n \n if (hasMachineHints) {\n lines.push('## Machine Hints');\n lines.push('');\n\n if (config.machineHints?.robots) {\n lines.push(`- robots.txt: ${config.machineHints.robots}`);\n }\n\n if (config.machineHints?.sitemap) {\n lines.push(`- sitemap.xml: ${config.machineHints.sitemap}`);\n }\n\n if (config.machineHints?.llmsTxt) {\n lines.push(`- llms.txt: ${config.machineHints.llmsTxt}`);\n }\n\n if (config.machineHints?.llmsFullTxt) {\n lines.push(`- llms-full.txt: ${config.machineHints.llmsFullTxt}`);\n }\n\n lines.push('');\n }\n\n // Sitemap\n const hubs = config.sections?.hubs ?? [];\n if (hubs.length > 0 || manifestItems.length > 0) {\n lines.push('## Sitemap');\n lines.push('');\n\n // Add section hubs first\n if (hubs.length > 0) {\n const sortedHubs = sortStrings(hubs);\n for (const hub of sortedHubs) {\n lines.push(`- [${hub}](${hub}) - ${getHubLabel(hub)}`);\n }\n }\n\n // Add all manifest URLs\n if (manifestItems.length > 0) {\n const sortedItems = sortBy(manifestItems, (item) => item.slug);\n for (const item of sortedItems) {\n const url = item.canonicalOverride ?? `${config.site.baseUrl}${item.slug}`;\n const title = item.title ?? item.slug;\n const locales = item.locales?.join(', ') ?? config.brand.locales[0] ?? 'en';\n lines.push(`- [${title}](${url}) (${locales})`);\n }\n }\n\n lines.push('');\n }\n\n // Build final content\n let content = lines.join('\\n');\n \n // Normalize whitespace\n content = normalizeLineWhitespace(content);\n \n // Apply line endings\n content = normalizeLineEndings(content, lineEndings);\n\n // Calculate metadata\n const finalLines = content.split(lineEndings === 'crlf' ? '\\r\\n' : '\\n');\n\n return {\n content,\n byteSize: Buffer.byteLength(content, 'utf-8'),\n lineCount: finalLines.length,\n };\n}\n\n/**\n * Gets a human-readable label for a hub path.\n */\nfunction getHubLabel(hub: string): string {\n const labels: Record<string, string> = {\n '/services': 'Services overview',\n '/blog': 'Blog posts',\n '/projects': 'Our projects',\n '/cases': 'Case studies',\n '/contact': 'Contact us',\n '/about': 'About us',\n '/products': 'Products',\n '/docs': 'Documentation',\n '/faq': 'Frequently asked questions',\n '/pricing': 'Pricing information',\n '/team': 'Our team',\n '/careers': 'Career opportunities',\n '/news': 'News and updates',\n '/resources': 'Resources',\n '/support': 'Support center',\n };\n\n return labels[hub] ?? formatHubLabel(hub);\n}\n\n/**\n * Formats a hub path into a human-readable label.\n */\nfunction formatHubLabel(hub: string): string {\n // Remove leading slash and format\n const clean = hub.replace(/^\\//, '');\n // Replace hyphens and underscores with spaces, capitalize words\n return clean\n .replace(/[-_]/g, ' ')\n .replace(/\\b\\w/g, (char) => char.toUpperCase());\n}\n\n// Legacy exports for backwards compatibility\nexport interface LlmsFullTxtOptions {\n /** Maximum content length per page (0 = no limit) */\n maxContentLength?: number;\n}\n\n/**\n * Generates full page content for llms-full.txt.\n * @deprecated Use createLlmsFullTxt instead\n */\nexport function generatePageContent(\n page: { path: string; title?: string; description?: string; content?: string },\n manifest: { baseUrl: string },\n _options?: LlmsFullTxtOptions\n): string {\n const maxContentLength = _options?.maxContentLength ?? 0;\n const lines: string[] = [];\n const url = `${manifest.baseUrl}${page.path}`;\n lines.push(`## ${page.title ?? page.path}`);\n lines.push(`URL: ${url}`);\n lines.push('');\n \n if (page.description) {\n lines.push(page.description);\n lines.push('');\n }\n \n if (page.content) {\n let content = page.content;\n if (maxContentLength > 0 && content.length > maxContentLength) {\n content = `${content.slice(0, maxContentLength)}...`;\n }\n lines.push(content);\n lines.push('');\n }\n \n return lines.join('\\n');\n}\n\n/**\n /**\n * @deprecated Use createLlmsFullTxt instead\n */\n export function generateLlmsFullTxt(\n manifest: { baseUrl: string; title: string; description?: string | undefined; pages: Array<{ path: string; title?: string | undefined; description?: string | undefined; content?: string | undefined }> },\n _options?: LlmsFullTxtOptions\n ): string {\n const canonicalUrls = manifest.pages.map((page) => `${manifest.baseUrl}${page.path}`);\n const manifestItems: ManifestItem[] = manifest.pages.map((page) => ({\n slug: page.path,\n title: page.title,\n description: page.description,\n }));\n \n const config: LlmsSeoConfig = {\n site: { baseUrl: manifest.baseUrl },\n brand: {\n name: manifest.title,\n locales: ['en'],\n ...(manifest.description && { description: manifest.description }),\n },\n manifests: {},\n output: {\n paths: {\n llmsTxt: 'public/llms.txt',\n llmsFullTxt: 'public/llms-full.txt',\n },\n },\n };\n \n return createLlmsFullTxt({ config, canonicalUrls, manifestItems }).content;\n }","/**\n * 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,292 @@
|
|
|
1
|
+
import { M as ManifestItem, B as BuildManifest, S as SiteManifest } from '../../manifest.schema-B_z3rxRV.js';
|
|
2
|
+
import 'zod';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Manifest generation for Next.js static exports.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Next.js content manifest structure for fromNextContentManifest.
|
|
10
|
+
*/
|
|
11
|
+
interface NextContentManifest {
|
|
12
|
+
items: Array<{
|
|
13
|
+
slug: string;
|
|
14
|
+
locales?: string[];
|
|
15
|
+
publishedAt?: string;
|
|
16
|
+
updatedAt?: string;
|
|
17
|
+
title?: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
priority?: number;
|
|
20
|
+
canonicalOverride?: string;
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
}>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Options for fromNextContentManifest.
|
|
26
|
+
*/
|
|
27
|
+
interface FromNextContentManifestOptions {
|
|
28
|
+
/** Prefix to add to all slugs */
|
|
29
|
+
slugPrefix?: string;
|
|
30
|
+
/** Default locale if not specified */
|
|
31
|
+
defaultLocale?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Converts Next.js content manifest to llm-seo ManifestItem[].
|
|
35
|
+
*
|
|
36
|
+
* @param manifest - Next.js content manifest
|
|
37
|
+
* @param options - Conversion options
|
|
38
|
+
* @returns Normalized ManifestItem[] for use in config
|
|
39
|
+
*/
|
|
40
|
+
declare function fromNextContentManifest(manifest: NextContentManifest, options?: FromNextContentManifestOptions): ManifestItem[];
|
|
41
|
+
/**
|
|
42
|
+
* Options for createManifestFromPagesDir.
|
|
43
|
+
*/
|
|
44
|
+
interface CreateManifestFromPagesDirOptions {
|
|
45
|
+
/** Path to pages directory */
|
|
46
|
+
pagesDir: string;
|
|
47
|
+
/** Prefix to add to all routes */
|
|
48
|
+
routePrefix?: string;
|
|
49
|
+
/** Default locale for items */
|
|
50
|
+
defaultLocale?: string;
|
|
51
|
+
/** File extensions to include */
|
|
52
|
+
extensions?: string[];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Creates manifest from Next.js pages directory.
|
|
56
|
+
* Scans for .mdx, .md files and extracts frontmatter.
|
|
57
|
+
*
|
|
58
|
+
* @param options - Options for manifest creation
|
|
59
|
+
* @returns Promise resolving to ManifestItem[]
|
|
60
|
+
*/
|
|
61
|
+
declare function createManifestFromPagesDir(options: CreateManifestFromPagesDirOptions): Promise<ManifestItem[]>;
|
|
62
|
+
/**
|
|
63
|
+
* Options for createManifestFromData.
|
|
64
|
+
*/
|
|
65
|
+
interface CreateManifestFromDataOptions {
|
|
66
|
+
/** Prefix to add to all slugs */
|
|
67
|
+
slugPrefix?: string;
|
|
68
|
+
/** Default locale if not specified */
|
|
69
|
+
defaultLocale?: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Creates manifest from Next.js data (getStaticProps data).
|
|
73
|
+
*
|
|
74
|
+
* @param items - Array of items from getStaticProps
|
|
75
|
+
* @param options - Options for manifest creation
|
|
76
|
+
* @returns ManifestItem[]
|
|
77
|
+
*/
|
|
78
|
+
declare function createManifestFromData(items: Array<{
|
|
79
|
+
params: {
|
|
80
|
+
slug: string | string[];
|
|
81
|
+
};
|
|
82
|
+
locale?: string;
|
|
83
|
+
publishedAt?: string;
|
|
84
|
+
updatedAt?: string;
|
|
85
|
+
title?: string;
|
|
86
|
+
description?: string;
|
|
87
|
+
priority?: number;
|
|
88
|
+
[key: string]: unknown;
|
|
89
|
+
}>, options?: CreateManifestFromDataOptions): ManifestItem[];
|
|
90
|
+
/**
|
|
91
|
+
* Options for Next.js manifest generation.
|
|
92
|
+
*/
|
|
93
|
+
interface NextManifestOptions {
|
|
94
|
+
/** Base URL for the site */
|
|
95
|
+
baseUrl: string;
|
|
96
|
+
/** Site title */
|
|
97
|
+
title: string;
|
|
98
|
+
/** Site description */
|
|
99
|
+
description?: string;
|
|
100
|
+
/** Path to the Next.js build manifest */
|
|
101
|
+
buildManifestPath?: string;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Extracts page paths from Next.js build manifest.
|
|
105
|
+
* @param buildManifest - The Next.js build manifest
|
|
106
|
+
* @returns Array of page paths
|
|
107
|
+
*/
|
|
108
|
+
declare function extractPagePaths(buildManifest: BuildManifest): string[];
|
|
109
|
+
/**
|
|
110
|
+
* Generates a site manifest from Next.js build output.
|
|
111
|
+
* @param options - Manifest generation options
|
|
112
|
+
* @param buildManifest - Optional build manifest
|
|
113
|
+
* @returns Generated site manifest
|
|
114
|
+
*/
|
|
115
|
+
declare function generateNextManifest(options: NextManifestOptions, buildManifest?: BuildManifest): SiteManifest;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Build hooks for Next.js integration.
|
|
119
|
+
*/
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Options for generateBuildScripts.
|
|
123
|
+
*/
|
|
124
|
+
interface GenerateBuildScriptsOptions {
|
|
125
|
+
/** Path to config file */
|
|
126
|
+
configPath?: string;
|
|
127
|
+
/** Output directory for generated files */
|
|
128
|
+
outputPath?: string;
|
|
129
|
+
/** Whether to emit citations.json */
|
|
130
|
+
emitCitations?: boolean;
|
|
131
|
+
/** Package manager to use */
|
|
132
|
+
packageManager?: 'npm' | 'yarn' | 'pnpm';
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Result of generateBuildScripts.
|
|
136
|
+
*/
|
|
137
|
+
interface BuildScriptsResult {
|
|
138
|
+
/** Script for building SEO artifacts */
|
|
139
|
+
'build:seo': string;
|
|
140
|
+
/** Post-build hook script */
|
|
141
|
+
postbuild: string;
|
|
142
|
+
/** Script for checking SEO artifacts */
|
|
143
|
+
'check:seo': string;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Generates package.json scripts for llm-seo integration.
|
|
147
|
+
*
|
|
148
|
+
* @param options - Options for script generation
|
|
149
|
+
* @returns Object with script names as keys and commands as values
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```typescript
|
|
153
|
+
* const scripts = generateBuildScripts({
|
|
154
|
+
* configPath: 'llm-seo.config.ts',
|
|
155
|
+
* emitCitations: true,
|
|
156
|
+
* });
|
|
157
|
+
* // Returns:
|
|
158
|
+
* // {
|
|
159
|
+
* // "build:seo": "llm-seo generate --config llm-seo.config.ts",
|
|
160
|
+
* // "postbuild": "pnpm build:seo && llm-seo check --fail-on error",
|
|
161
|
+
* // "check:seo": "llm-seo check --fail-on warn"
|
|
162
|
+
* // }
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
165
|
+
declare function generateBuildScripts(options?: GenerateBuildScriptsOptions): BuildScriptsResult;
|
|
166
|
+
/**
|
|
167
|
+
* Options for createRobotsLlmsPolicySnippet.
|
|
168
|
+
*/
|
|
169
|
+
interface CreateRobotsLlmsPolicySnippetOptions {
|
|
170
|
+
/** Base URL of the site */
|
|
171
|
+
baseUrl: string;
|
|
172
|
+
/** Whether to allow llms.txt */
|
|
173
|
+
allowLlmsTxt?: boolean;
|
|
174
|
+
/** Whether to allow llms-full.txt */
|
|
175
|
+
allowLlmsFullTxt?: boolean;
|
|
176
|
+
/** Whether to allow sitemap.xml */
|
|
177
|
+
allowSitemap?: boolean;
|
|
178
|
+
/** Additional paths to allow */
|
|
179
|
+
additionalPaths?: string[];
|
|
180
|
+
/** User agent to target (default: *) */
|
|
181
|
+
userAgent?: string;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Creates robots.txt LLM policy snippet.
|
|
185
|
+
*
|
|
186
|
+
* @param options - Options for snippet generation
|
|
187
|
+
* @returns robots.txt snippet string
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* ```typescript
|
|
191
|
+
* const snippet = createRobotsLlmsPolicySnippet({
|
|
192
|
+
* baseUrl: 'https://example.com',
|
|
193
|
+
* allowLlmsTxt: true,
|
|
194
|
+
* allowLlmsFullTxt: true,
|
|
195
|
+
* });
|
|
196
|
+
* // Returns:
|
|
197
|
+
* // # LLM SEO
|
|
198
|
+
* // User-agent: *
|
|
199
|
+
* // Allow: /llms.txt
|
|
200
|
+
* // Allow: /llms-full.txt
|
|
201
|
+
* // Allow: /sitemap.xml
|
|
202
|
+
* ```
|
|
203
|
+
*/
|
|
204
|
+
declare function createRobotsLlmsPolicySnippet(options: CreateRobotsLlmsPolicySnippetOptions): string;
|
|
205
|
+
/**
|
|
206
|
+
* Options for createNextConfig.
|
|
207
|
+
*/
|
|
208
|
+
interface CreateNextConfigOptions {
|
|
209
|
+
/** Supported locales */
|
|
210
|
+
locales?: string[];
|
|
211
|
+
/** Default locale */
|
|
212
|
+
defaultLocale?: string;
|
|
213
|
+
/** Whether to use trailing slash */
|
|
214
|
+
trailingSlash?: boolean;
|
|
215
|
+
/** Whether to disable images optimization (for static export) */
|
|
216
|
+
unoptimizedImages?: boolean;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Next.js config object returned by createNextConfig.
|
|
220
|
+
*/
|
|
221
|
+
interface NextConfigResult {
|
|
222
|
+
/** Output mode */
|
|
223
|
+
output: 'export';
|
|
224
|
+
/** Trailing slash configuration */
|
|
225
|
+
trailingSlash: boolean;
|
|
226
|
+
/** Images configuration */
|
|
227
|
+
images: {
|
|
228
|
+
unoptimized: boolean;
|
|
229
|
+
};
|
|
230
|
+
/** i18n configuration (only if locales provided) */
|
|
231
|
+
i18n?: {
|
|
232
|
+
locales: string[];
|
|
233
|
+
defaultLocale: string;
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Creates Next.js config object for static export with locales.
|
|
238
|
+
*
|
|
239
|
+
* @param options - Options for config generation
|
|
240
|
+
* @returns Next.js config object
|
|
241
|
+
*
|
|
242
|
+
* @example
|
|
243
|
+
* ```typescript
|
|
244
|
+
* const nextConfig = createNextConfig({
|
|
245
|
+
* locales: ['en', 'uk'],
|
|
246
|
+
* defaultLocale: 'en',
|
|
247
|
+
* trailingSlash: false,
|
|
248
|
+
* });
|
|
249
|
+
*
|
|
250
|
+
* module.exports = nextConfig;
|
|
251
|
+
* ```
|
|
252
|
+
*/
|
|
253
|
+
declare function createNextConfig(options: CreateNextConfigOptions): NextConfigResult;
|
|
254
|
+
/**
|
|
255
|
+
* Options for build hooks.
|
|
256
|
+
*/
|
|
257
|
+
interface BuildHookOptions {
|
|
258
|
+
/** Output directory for generated files */
|
|
259
|
+
outputDir: string;
|
|
260
|
+
/** Site manifest */
|
|
261
|
+
manifest: SiteManifest;
|
|
262
|
+
/** Whether to generate llms-full.txt */
|
|
263
|
+
generateFull?: boolean;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Result of running build hooks.
|
|
267
|
+
*/
|
|
268
|
+
interface BuildHookResult {
|
|
269
|
+
/** Generated files */
|
|
270
|
+
files: string[];
|
|
271
|
+
/** Whether the hook succeeded */
|
|
272
|
+
success: boolean;
|
|
273
|
+
/** Error message if failed */
|
|
274
|
+
error?: string;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Post-build hook that generates llms.txt files.
|
|
278
|
+
* Call this after Next.js static export completes.
|
|
279
|
+
* @param options - Hook options
|
|
280
|
+
* @returns Hook result
|
|
281
|
+
*/
|
|
282
|
+
declare function postBuildHook(options: BuildHookOptions): Promise<BuildHookResult>;
|
|
283
|
+
/**
|
|
284
|
+
* Creates a plugin function for Next.js integration.
|
|
285
|
+
* @returns Plugin object with hooks
|
|
286
|
+
*/
|
|
287
|
+
declare function createNextPlugin(): {
|
|
288
|
+
name: string;
|
|
289
|
+
postBuild: (options: BuildHookOptions) => Promise<BuildHookResult>;
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
export { type BuildHookOptions, type BuildHookResult, type BuildScriptsResult, type CreateManifestFromDataOptions, type CreateManifestFromPagesDirOptions, type CreateNextConfigOptions, type CreateRobotsLlmsPolicySnippetOptions, type FromNextContentManifestOptions, type GenerateBuildScriptsOptions, type NextConfigResult, type NextContentManifest, type NextManifestOptions, createManifestFromData, createManifestFromPagesDir, createNextConfig, createNextPlugin, createRobotsLlmsPolicySnippet, extractPagePaths, fromNextContentManifest, generateBuildScripts, generateNextManifest, postBuildHook };
|