From a33b847205178d44564937f2e769c85721d64987 Mon Sep 17 00:00:00 2001 From: dacharyc Date: Mon, 23 Mar 2026 22:30:15 -0400 Subject: [PATCH] fix: llms-txt-links-markdown: false positive --- .../llms-txt/llms-txt-links-markdown.ts | 22 ++++++++ .../checks/llms-txt-links-markdown.test.ts | 53 +++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/src/checks/llms-txt/llms-txt-links-markdown.ts b/src/checks/llms-txt/llms-txt-links-markdown.ts index 200993a..1510b90 100644 --- a/src/checks/llms-txt/llms-txt-links-markdown.ts +++ b/src/checks/llms-txt/llms-txt-links-markdown.ts @@ -1,6 +1,7 @@ import { registerCheck } from '../registry.js'; import { extractMarkdownLinks } from './llms-txt-valid.js'; import { toMdUrls } from '../../helpers/to-md-urls.js'; +import { looksLikeMarkdown } from '../../helpers/detect-markdown.js'; import type { CheckContext, CheckResult, DiscoveredFile } from '../../types.js'; interface LinkMarkdownResult { @@ -107,6 +108,27 @@ async function checkLlmsTxtLinksMarkdown(ctx: CheckContext): Promise { + server.use( + http.head( + 'http://test.local/llms-full.txt', + () => + new HttpResponse(null, { + status: 200, + headers: { 'content-type': 'text/plain' }, + }), + ), + http.get( + 'http://test.local/llms-full.txt', + () => + new HttpResponse( + '# Full docs\n\n## API Reference\n\n- [Endpoint](http://test.local/api.md): API', + { + status: 200, + headers: { 'content-type': 'text/plain' }, + }, + ), + ), + ); + + const content = `# Test\n> Summary\n## Links\n- [Full docs](http://test.local/llms-full.txt): Complete documentation\n`; + const result = await check.run(makeCtx(content)); + expect(result.status).toBe('pass'); + }); + + it('fails for .txt files that do not contain markdown', async () => { + server.use( + http.head( + 'http://test.local/robots.txt', + () => + new HttpResponse(null, { + status: 200, + headers: { 'content-type': 'text/plain' }, + }), + ), + http.get( + 'http://test.local/robots.txt', + () => + new HttpResponse('User-agent: *\nDisallow: /private/', { + status: 200, + headers: { 'content-type': 'text/plain' }, + }), + ), + ); + + const content = `# Test\n> Summary\n## Links\n- [Robots](http://test.local/robots.txt): Robots file\n`; + const result = await check.run(makeCtx(content)); + expect(result.status).toBe('fail'); + }); + it('uses toMdUrls to find .md variants (handles trailing slash and .html)', async () => { server.use( http.head(