|
| 1 | +import type { ProcessedFile } from '../../src/llms-txt.ts' |
1 | 2 | import { mkdir, rm, writeFile } from 'node:fs/promises'
|
2 | 3 | import { tmpdir } from 'node:os'
|
3 | 4 | import { join } from 'node:path'
|
4 |
| -import { expect, it } from 'vitest' |
| 5 | +import { describe, expect, it } from 'vitest' |
5 | 6 | import { generateLlmsTxtArtifacts } from '../../src/llms-txt.ts'
|
6 | 7 |
|
7 | 8 | const testDir = join(tmpdir(), 'mdream-llms-txt-test')
|
@@ -108,9 +109,9 @@ it('should generate llms-full.txt when requested', async () => {
|
108 | 109 | expect(result.llmsFullTxt).toContain('# Test Site')
|
109 | 110 | expect(result.llmsFullTxt).toContain('> A test site for mdream')
|
110 | 111 | expect(result.llmsFullTxt).toContain('## Table of Contents')
|
111 |
| - expect(result.llmsFullTxt).toContain('## Test Site - Home') |
112 |
| - expect(result.llmsFullTxt).toContain('**URL:** https://example.com/') |
113 |
| - expect(result.llmsFullTxt).toContain('Welcome to Test Site') |
| 112 | + expect(result.llmsFullTxt).toContain('title: Test Site - Home') |
| 113 | + expect(result.llmsFullTxt).toContain('url: https://example.com/') |
| 114 | + expect(result.llmsFullTxt).toContain('# Welcome to Test Site') |
114 | 115 |
|
115 | 116 | await cleanup()
|
116 | 117 | })
|
@@ -222,3 +223,126 @@ it('should work with pre-processed files', async () => {
|
222 | 223 | expect(result.llmsFullTxt).toContain('# Welcome')
|
223 | 224 | expect(result.llmsFullTxt).toContain('# About')
|
224 | 225 | })
|
| 226 | + |
| 227 | +describe('llms-txt frontmatter handling', () => { |
| 228 | + it('should prepend metadata to existing frontmatter', async () => { |
| 229 | + const filesWithFrontmatter: ProcessedFile[] = [{ |
| 230 | + title: 'Test Page', |
| 231 | + content: `--- |
| 232 | +existingKey: existingValue |
| 233 | +tags: test, sample |
| 234 | +--- |
| 235 | +
|
| 236 | +# Content |
| 237 | +
|
| 238 | +This is the main content of the page.`, |
| 239 | + url: '/test-page', |
| 240 | + metadata: { |
| 241 | + description: 'A test page with frontmatter', |
| 242 | + author: 'Test Author', |
| 243 | + }, |
| 244 | + }] |
| 245 | + |
| 246 | + const result = await generateLlmsTxtArtifacts({ |
| 247 | + files: filesWithFrontmatter, |
| 248 | + siteName: 'Test Site', |
| 249 | + origin: 'https://example.com', |
| 250 | + generateFull: true, |
| 251 | + }) |
| 252 | + |
| 253 | + expect(result.llmsFullTxt).toBeDefined() |
| 254 | + expect(result.llmsFullTxt).toContain('---') |
| 255 | + expect(result.llmsFullTxt).toContain('title: Test Page') |
| 256 | + expect(result.llmsFullTxt).toContain('url: https://example.com/test-page') |
| 257 | + expect(result.llmsFullTxt).toContain('existingKey: existingValue') |
| 258 | + expect(result.llmsFullTxt).toContain('tags: test, sample') |
| 259 | + expect(result.llmsFullTxt).toContain('description: A test page with frontmatter') |
| 260 | + expect(result.llmsFullTxt).toContain('author: Test Author') |
| 261 | + expect(result.llmsFullTxt).toContain('# Content') |
| 262 | + }) |
| 263 | + |
| 264 | + it('should add frontmatter to content without existing frontmatter', async () => { |
| 265 | + const filesWithoutFrontmatter: ProcessedFile[] = [{ |
| 266 | + title: 'Simple Page', |
| 267 | + content: `# Simple Content |
| 268 | +
|
| 269 | +This page has no frontmatter.`, |
| 270 | + url: '/simple-page', |
| 271 | + }] |
| 272 | + |
| 273 | + const result = await generateLlmsTxtArtifacts({ |
| 274 | + files: filesWithoutFrontmatter, |
| 275 | + siteName: 'Test Site', |
| 276 | + origin: 'https://example.com', |
| 277 | + generateFull: true, |
| 278 | + }) |
| 279 | + |
| 280 | + expect(result.llmsFullTxt).toBeDefined() |
| 281 | + // Should now always have frontmatter with title and url |
| 282 | + expect(result.llmsFullTxt).toContain('---') |
| 283 | + expect(result.llmsFullTxt).toContain('title: Simple Page') |
| 284 | + expect(result.llmsFullTxt).toContain('url: https://example.com/simple-page') |
| 285 | + expect(result.llmsFullTxt).toContain('# Simple Content') |
| 286 | + // Should not have section header |
| 287 | + expect(result.llmsFullTxt).not.toContain('## Simple Page') |
| 288 | + }) |
| 289 | + |
| 290 | + it('should handle files with file paths and outputDir', async () => { |
| 291 | + const filesWithPaths: ProcessedFile[] = [{ |
| 292 | + title: 'File Page', |
| 293 | + filePath: '/home/user/output/md/page.md', |
| 294 | + content: `--- |
| 295 | +category: documentation |
| 296 | +--- |
| 297 | +
|
| 298 | +# Documentation Page`, |
| 299 | + url: '/docs/page', |
| 300 | + }] |
| 301 | + |
| 302 | + const result = await generateLlmsTxtArtifacts({ |
| 303 | + files: filesWithPaths, |
| 304 | + siteName: 'Test Site', |
| 305 | + origin: 'https://example.com', |
| 306 | + outputDir: '/home/user/output', |
| 307 | + generateFull: true, |
| 308 | + }) |
| 309 | + |
| 310 | + expect(result.llmsFullTxt).toBeDefined() |
| 311 | + expect(result.llmsFullTxt).toContain('file: md/page.md') |
| 312 | + expect(result.llmsFullTxt).toContain('category: documentation') |
| 313 | + }) |
| 314 | + |
| 315 | + it('should merge metadata correctly with existing frontmatter', async () => { |
| 316 | + const filesWithConflict: ProcessedFile[] = [{ |
| 317 | + title: 'Conflict Test', |
| 318 | + content: `--- |
| 319 | +title: Original Title |
| 320 | +url: /old-url |
| 321 | +custom: value |
| 322 | +--- |
| 323 | +
|
| 324 | +Content here`, |
| 325 | + url: '/new-url', |
| 326 | + metadata: { |
| 327 | + description: 'New description', |
| 328 | + }, |
| 329 | + }] |
| 330 | + |
| 331 | + const result = await generateLlmsTxtArtifacts({ |
| 332 | + files: filesWithConflict, |
| 333 | + siteName: 'Test Site', |
| 334 | + origin: 'https://example.com', |
| 335 | + generateFull: true, |
| 336 | + }) |
| 337 | + |
| 338 | + expect(result.llmsFullTxt).toBeDefined() |
| 339 | + // New metadata should be prepended, existing should be preserved |
| 340 | + expect(result.llmsFullTxt).toContain('title: Conflict Test') |
| 341 | + expect(result.llmsFullTxt).toContain('url: https://example.com/new-url') |
| 342 | + expect(result.llmsFullTxt).toContain('description: New description') |
| 343 | + expect(result.llmsFullTxt).toContain('custom: value') |
| 344 | + // Original values that conflict should be overwritten |
| 345 | + expect(result.llmsFullTxt).not.toContain('title: Original Title') |
| 346 | + expect(result.llmsFullTxt).not.toContain('url: /old-url') |
| 347 | + }) |
| 348 | +}) |
0 commit comments