afdocs 0.1.3 → 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 +48 -24
- package/dist/checks/authentication/auth-alternative-access.d.ts +2 -0
- package/dist/checks/authentication/auth-alternative-access.d.ts.map +1 -0
- package/dist/checks/authentication/auth-alternative-access.js +17 -0
- package/dist/checks/authentication/auth-alternative-access.js.map +1 -0
- package/dist/checks/authentication/auth-gate-detection.d.ts +2 -0
- package/dist/checks/authentication/auth-gate-detection.d.ts.map +1 -0
- package/dist/checks/authentication/auth-gate-detection.js +175 -0
- package/dist/checks/authentication/auth-gate-detection.js.map +1 -0
- package/dist/checks/content-structure/markdown-code-fence-validity.js +119 -5
- package/dist/checks/content-structure/markdown-code-fence-validity.js.map +1 -1
- package/dist/checks/index.d.ts +2 -0
- package/dist/checks/index.d.ts.map +1 -1
- package/dist/checks/index.js +3 -0
- package/dist/checks/index.js.map +1 -1
- package/dist/checks/llms-txt/llms-txt-exists.js +83 -6
- package/dist/checks/llms-txt/llms-txt-exists.js.map +1 -1
- package/dist/checks/llms-txt/llms-txt-links-markdown.js +46 -21
- package/dist/checks/llms-txt/llms-txt-links-markdown.js.map +1 -1
- package/dist/checks/llms-txt/llms-txt-links-resolve.js +10 -3
- package/dist/checks/llms-txt/llms-txt-links-resolve.js.map +1 -1
- package/dist/checks/markdown-availability/content-negotiation.js +101 -5
- package/dist/checks/markdown-availability/content-negotiation.js.map +1 -1
- package/dist/checks/markdown-availability/markdown-url-support.js +82 -5
- package/dist/checks/markdown-availability/markdown-url-support.js.map +1 -1
- package/dist/checks/observability/cache-header-hygiene.js +200 -5
- package/dist/checks/observability/cache-header-hygiene.js.map +1 -1
- package/dist/checks/page-size/content-start-position.js +161 -5
- package/dist/checks/page-size/content-start-position.js.map +1 -1
- package/dist/checks/page-size/page-size-html.js +127 -5
- package/dist/checks/page-size/page-size-html.js.map +1 -1
- package/dist/checks/page-size/page-size-markdown.js +100 -5
- package/dist/checks/page-size/page-size-markdown.js.map +1 -1
- package/dist/checks/url-stability/http-status-codes.js +106 -5
- package/dist/checks/url-stability/http-status-codes.js.map +1 -1
- package/dist/cli/commands/check.d.ts.map +1 -1
- package/dist/cli/commands/check.js +9 -1
- package/dist/cli/commands/check.js.map +1 -1
- package/dist/cli/formatters/text.d.ts +4 -1
- package/dist/cli/formatters/text.d.ts.map +1 -1
- package/dist/cli/formatters/text.js +94 -1
- package/dist/cli/formatters/text.js.map +1 -1
- package/dist/constants.d.ts +6 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +3 -0
- package/dist/constants.js.map +1 -1
- package/dist/helpers/detect-markdown.d.ts +10 -0
- package/dist/helpers/detect-markdown.d.ts.map +1 -0
- package/dist/helpers/detect-markdown.js +29 -0
- package/dist/helpers/detect-markdown.js.map +1 -0
- package/dist/helpers/get-markdown-content.d.ts +23 -0
- package/dist/helpers/get-markdown-content.d.ts.map +1 -0
- package/dist/helpers/get-markdown-content.js +93 -0
- package/dist/helpers/get-markdown-content.js.map +1 -0
- package/dist/helpers/get-page-urls.d.ts +42 -0
- package/dist/helpers/get-page-urls.d.ts.map +1 -0
- package/dist/helpers/get-page-urls.js +236 -0
- package/dist/helpers/get-page-urls.js.map +1 -0
- package/dist/helpers/html-to-markdown.d.ts +7 -0
- package/dist/helpers/html-to-markdown.d.ts.map +1 -0
- package/dist/helpers/html-to-markdown.js +11 -0
- package/dist/helpers/html-to-markdown.js.map +1 -0
- package/dist/helpers/index.d.ts +5 -0
- package/dist/helpers/index.d.ts.map +1 -1
- package/dist/helpers/index.js +4 -0
- package/dist/helpers/index.js.map +1 -1
- package/dist/helpers/to-md-urls.d.ts +7 -0
- package/dist/helpers/to-md-urls.d.ts.map +1 -0
- package/dist/helpers/to-md-urls.js +24 -0
- package/dist/helpers/to-md-urls.js.map +1 -0
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +21 -14
- package/dist/runner.js.map +1 -1
- package/dist/types.d.ts +13 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -2
|
@@ -39,7 +39,8 @@ async function checkLlmsTxtExists(ctx) {
|
|
|
39
39
|
if (response.ok && isText) {
|
|
40
40
|
const content = await response.text();
|
|
41
41
|
// Check it's not an HTML error page
|
|
42
|
-
const
|
|
42
|
+
const trimmed = content.trimStart().toLowerCase();
|
|
43
|
+
const looksLikeHtml = trimmed.startsWith('<!') || trimmed.startsWith('<html');
|
|
43
44
|
if (!looksLikeHtml && content.trim().length > 0) {
|
|
44
45
|
const crossHost = response.redirected && isCrossHostRedirect(url, response.url);
|
|
45
46
|
discovered.push({
|
|
@@ -53,21 +54,97 @@ async function checkLlmsTxtExists(ctx) {
|
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
56
|
}
|
|
56
|
-
catch {
|
|
57
|
-
checkedUrls.push({
|
|
57
|
+
catch (err) {
|
|
58
|
+
checkedUrls.push({
|
|
59
|
+
url,
|
|
60
|
+
status: 0,
|
|
61
|
+
redirected: false,
|
|
62
|
+
error: err instanceof Error ? err.message : String(err),
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// When no llms.txt found, check if any candidates redirected cross-host.
|
|
67
|
+
// If so, try {redirected_origin}/llms.txt as a fallback.
|
|
68
|
+
const redirectedOrigins = [];
|
|
69
|
+
if (discovered.length === 0) {
|
|
70
|
+
const checkedSet = new Set(checkedUrls.map((u) => u.url));
|
|
71
|
+
const seenOrigins = new Set();
|
|
72
|
+
for (const checked of checkedUrls) {
|
|
73
|
+
if (checked.finalUrl && isCrossHostRedirect(checked.url, checked.finalUrl)) {
|
|
74
|
+
try {
|
|
75
|
+
const redirectedOrigin = new URL(checked.finalUrl).origin;
|
|
76
|
+
const fallbackUrl = `${redirectedOrigin}/llms.txt`;
|
|
77
|
+
if (!checkedSet.has(fallbackUrl) && !seenOrigins.has(redirectedOrigin)) {
|
|
78
|
+
seenOrigins.add(redirectedOrigin);
|
|
79
|
+
checkedSet.add(fallbackUrl);
|
|
80
|
+
redirectedOrigins.push(redirectedOrigin);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
/* malformed URL */
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
for (const redirectedOrigin of redirectedOrigins) {
|
|
89
|
+
const fallbackUrl = `${redirectedOrigin}/llms.txt`;
|
|
90
|
+
try {
|
|
91
|
+
const response = await ctx.http.fetch(fallbackUrl);
|
|
92
|
+
const contentType = response.headers.get('content-type') ?? '';
|
|
93
|
+
const isText = contentType.includes('text/');
|
|
94
|
+
checkedUrls.push({
|
|
95
|
+
url: fallbackUrl,
|
|
96
|
+
status: response.status,
|
|
97
|
+
redirected: response.redirected,
|
|
98
|
+
finalUrl: response.redirected ? response.url : undefined,
|
|
99
|
+
});
|
|
100
|
+
if (response.ok && isText) {
|
|
101
|
+
const content = await response.text();
|
|
102
|
+
const trimmed = content.trimStart().toLowerCase();
|
|
103
|
+
const looksLikeHtml = trimmed.startsWith('<!') || trimmed.startsWith('<html');
|
|
104
|
+
if (!looksLikeHtml && content.trim().length > 0) {
|
|
105
|
+
discovered.push({
|
|
106
|
+
url: fallbackUrl,
|
|
107
|
+
content,
|
|
108
|
+
status: response.status,
|
|
109
|
+
redirected: false,
|
|
110
|
+
crossHostRedirect: true,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
checkedUrls.push({
|
|
117
|
+
url: fallbackUrl,
|
|
118
|
+
status: 0,
|
|
119
|
+
redirected: false,
|
|
120
|
+
error: err instanceof Error ? err.message : String(err),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
58
123
|
}
|
|
59
124
|
}
|
|
125
|
+
const fetchErrors = checkedUrls.filter((u) => u.error).length;
|
|
126
|
+
const rateLimited = checkedUrls.filter((u) => u.status === 429).length;
|
|
127
|
+
const suffix = (fetchErrors > 0 ? `; ${fetchErrors} failed to fetch` : '') +
|
|
128
|
+
(rateLimited > 0 ? `; ${rateLimited} rate-limited (HTTP 429)` : '');
|
|
60
129
|
// Store discovered files for downstream checks
|
|
61
130
|
const details = {
|
|
62
131
|
candidateUrls: checkedUrls,
|
|
63
132
|
discoveredFiles: discovered,
|
|
133
|
+
fetchErrors,
|
|
134
|
+
rateLimited,
|
|
64
135
|
};
|
|
136
|
+
if (redirectedOrigins.length > 0) {
|
|
137
|
+
details.redirectedOrigins = redirectedOrigins;
|
|
138
|
+
}
|
|
65
139
|
if (discovered.length === 0) {
|
|
140
|
+
const redirectNote = redirectedOrigins.length > 0
|
|
141
|
+
? `; candidates redirected cross-host to ${redirectedOrigins.join(', ')} (agents can't follow cross-host redirects)`
|
|
142
|
+
: '';
|
|
66
143
|
return {
|
|
67
144
|
id: 'llms-txt-exists',
|
|
68
145
|
category: 'llms-txt',
|
|
69
146
|
status: 'fail',
|
|
70
|
-
message: `No llms.txt found at any candidate location (${candidates.join(', ')})`,
|
|
147
|
+
message: `No llms.txt found at any candidate location (${candidates.join(', ')})${redirectNote}${suffix}`,
|
|
71
148
|
details,
|
|
72
149
|
};
|
|
73
150
|
}
|
|
@@ -78,7 +155,7 @@ async function checkLlmsTxtExists(ctx) {
|
|
|
78
155
|
id: 'llms-txt-exists',
|
|
79
156
|
category: 'llms-txt',
|
|
80
157
|
status: 'warn',
|
|
81
|
-
message:
|
|
158
|
+
message: `llms.txt found but only reachable via cross-host redirect (agents may not follow it)${suffix}`,
|
|
82
159
|
details,
|
|
83
160
|
};
|
|
84
161
|
}
|
|
@@ -93,7 +170,7 @@ async function checkLlmsTxtExists(ctx) {
|
|
|
93
170
|
id: 'llms-txt-exists',
|
|
94
171
|
category: 'llms-txt',
|
|
95
172
|
status: 'pass',
|
|
96
|
-
message: `llms.txt found at ${discovered.length} location(s)`,
|
|
173
|
+
message: `llms.txt found at ${discovered.length} location(s)${suffix}`,
|
|
97
174
|
details,
|
|
98
175
|
};
|
|
99
176
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llms-txt-exists.js","sourceRoot":"","sources":["../../../src/checks/llms-txt/llms-txt-exists.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAG/C;;;;GAIG;AACH,SAAS,gBAAgB,CAAC,OAAe,EAAE,MAAc;IACvD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;IACrC,UAAU,CAAC,GAAG,CAAC,GAAG,OAAO,WAAW,CAAC,CAAC;IACtC,UAAU,CAAC,GAAG,CAAC,GAAG,MAAM,WAAW,CAAC,CAAC;IACrC,UAAU,CAAC,GAAG,CAAC,GAAG,MAAM,gBAAgB,CAAC,CAAC;IAC1C,OAAO,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,mBAAmB,CAAC,WAAmB,EAAE,QAAgB;IAChE,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;QACjC,OAAO,QAAQ,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAC,GAAiB;IACjD,MAAM,UAAU,GAAG,gBAAgB,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7D,MAAM,UAAU,GAAqB,EAAE,CAAC;IACxC,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"llms-txt-exists.js","sourceRoot":"","sources":["../../../src/checks/llms-txt/llms-txt-exists.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { registerCheck } from '../registry.js';
|
|
2
2
|
import { extractMarkdownLinks } from './llms-txt-valid.js';
|
|
3
|
+
import { toMdUrls } from '../../helpers/to-md-urls.js';
|
|
3
4
|
function hasMarkdownExtension(url) {
|
|
4
5
|
try {
|
|
5
6
|
const pathname = new URL(url).pathname;
|
|
@@ -42,7 +43,8 @@ async function checkLlmsTxtLinksMarkdown(ctx) {
|
|
|
42
43
|
// Sample if too many
|
|
43
44
|
let linksToTest = Array.from(allLinks);
|
|
44
45
|
const totalLinks = linksToTest.length;
|
|
45
|
-
|
|
46
|
+
const wasSampled = totalLinks > ctx.options.maxLinksToTest;
|
|
47
|
+
if (wasSampled) {
|
|
46
48
|
for (let i = linksToTest.length - 1; i > 0; i--) {
|
|
47
49
|
const j = Math.floor(Math.random() * (i + 1));
|
|
48
50
|
[linksToTest[i], linksToTest[j]] = [linksToTest[j], linksToTest[i]];
|
|
@@ -66,33 +68,48 @@ async function checkLlmsTxtLinksMarkdown(ctx) {
|
|
|
66
68
|
});
|
|
67
69
|
const contentType = response.headers.get('content-type') ?? '';
|
|
68
70
|
if (contentType.includes('text/markdown')) {
|
|
69
|
-
return {
|
|
71
|
+
return {
|
|
72
|
+
url,
|
|
73
|
+
hasMarkdownExtension: false,
|
|
74
|
+
servesMarkdown: true,
|
|
75
|
+
status: response.status,
|
|
76
|
+
};
|
|
70
77
|
}
|
|
71
|
-
// Try .md variant
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
// Try .md variant candidates
|
|
79
|
+
const candidates = toMdUrls(url);
|
|
80
|
+
for (const mdUrl of candidates) {
|
|
81
|
+
try {
|
|
82
|
+
const mdResponse = await ctx.http.fetch(mdUrl, { method: 'HEAD' });
|
|
83
|
+
if (mdResponse.ok) {
|
|
84
|
+
return {
|
|
85
|
+
url,
|
|
86
|
+
hasMarkdownExtension: false,
|
|
87
|
+
servesMarkdown: false,
|
|
88
|
+
status: response.status,
|
|
89
|
+
mdVariantAvailable: true,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// Try next candidate
|
|
82
95
|
}
|
|
83
|
-
}
|
|
84
|
-
catch {
|
|
85
|
-
// .md variant not available
|
|
86
96
|
}
|
|
87
97
|
return {
|
|
88
98
|
url,
|
|
89
99
|
hasMarkdownExtension: false,
|
|
90
100
|
servesMarkdown: false,
|
|
101
|
+
status: response.status,
|
|
91
102
|
mdVariantAvailable: false,
|
|
92
103
|
};
|
|
93
104
|
}
|
|
94
|
-
catch {
|
|
95
|
-
return {
|
|
105
|
+
catch (err) {
|
|
106
|
+
return {
|
|
107
|
+
url,
|
|
108
|
+
hasMarkdownExtension: false,
|
|
109
|
+
servesMarkdown: false,
|
|
110
|
+
status: 0,
|
|
111
|
+
error: err instanceof Error ? err.message : String(err),
|
|
112
|
+
};
|
|
96
113
|
}
|
|
97
114
|
}));
|
|
98
115
|
results.push(...batchResults);
|
|
@@ -100,20 +117,28 @@ async function checkLlmsTxtLinksMarkdown(ctx) {
|
|
|
100
117
|
const markdownLinks = results.filter((r) => r.hasMarkdownExtension || r.servesMarkdown).length;
|
|
101
118
|
const mdVariantsAvailable = results.filter((r) => r.mdVariantAvailable).length;
|
|
102
119
|
const markdownRate = results.length > 0 ? markdownLinks / results.length : 0;
|
|
120
|
+
const fetchErrors = results.filter((r) => r.error).length;
|
|
121
|
+
const rateLimited = results.filter((r) => r.status === 429).length;
|
|
122
|
+
const linkLabel = wasSampled ? 'sampled links' : 'links';
|
|
123
|
+
const suffix = (fetchErrors > 0 ? `; ${fetchErrors} failed to fetch` : '') +
|
|
124
|
+
(rateLimited > 0 ? `; ${rateLimited} rate-limited (HTTP 429)` : '');
|
|
103
125
|
const details = {
|
|
104
126
|
totalLinks,
|
|
105
127
|
testedLinks: results.length,
|
|
128
|
+
sampled: wasSampled,
|
|
106
129
|
markdownLinks,
|
|
107
130
|
htmlLinks: results.length - markdownLinks,
|
|
108
131
|
mdVariantsAvailable,
|
|
109
132
|
markdownRate: Math.round(markdownRate * 100),
|
|
133
|
+
fetchErrors,
|
|
134
|
+
rateLimited,
|
|
110
135
|
};
|
|
111
136
|
if (markdownRate >= 0.9) {
|
|
112
137
|
return {
|
|
113
138
|
id: 'llms-txt-links-markdown',
|
|
114
139
|
category: 'llms-txt',
|
|
115
140
|
status: 'pass',
|
|
116
|
-
message: `${markdownLinks}/${results.length}
|
|
141
|
+
message: `${markdownLinks}/${results.length} ${linkLabel} point to markdown content (${Math.round(markdownRate * 100)}%)${suffix}`,
|
|
117
142
|
details,
|
|
118
143
|
};
|
|
119
144
|
}
|
|
@@ -122,7 +147,7 @@ async function checkLlmsTxtLinksMarkdown(ctx) {
|
|
|
122
147
|
id: 'llms-txt-links-markdown',
|
|
123
148
|
category: 'llms-txt',
|
|
124
149
|
status: 'warn',
|
|
125
|
-
message: `Links point to HTML, but ${mdVariantsAvailable} have .md variants available`,
|
|
150
|
+
message: `Links point to HTML, but ${mdVariantsAvailable} have .md variants available${suffix}`,
|
|
126
151
|
details,
|
|
127
152
|
};
|
|
128
153
|
}
|
|
@@ -130,7 +155,7 @@ async function checkLlmsTxtLinksMarkdown(ctx) {
|
|
|
130
155
|
id: 'llms-txt-links-markdown',
|
|
131
156
|
category: 'llms-txt',
|
|
132
157
|
status: 'fail',
|
|
133
|
-
message:
|
|
158
|
+
message: `Links point to HTML and no markdown alternatives detected${suffix}`,
|
|
134
159
|
details,
|
|
135
160
|
};
|
|
136
161
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llms-txt-links-markdown.js","sourceRoot":"","sources":["../../../src/checks/llms-txt/llms-txt-links-markdown.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"llms-txt-links-markdown.js","sourceRoot":"","sources":["../../../src/checks/llms-txt/llms-txt-links-markdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -72,6 +72,11 @@ async function checkLlmsTxtLinksResolve(ctx) {
|
|
|
72
72
|
const resolved = results.filter((r) => r.ok).length;
|
|
73
73
|
const broken = results.filter((r) => !r.ok);
|
|
74
74
|
const resolveRate = resolved / results.length;
|
|
75
|
+
const fetchErrors = results.filter((r) => r.error).length;
|
|
76
|
+
const rateLimited = results.filter((r) => r.status === 429).length;
|
|
77
|
+
const linkLabel = wasSampled ? 'sampled links' : 'links';
|
|
78
|
+
const suffix = (fetchErrors > 0 ? `; ${fetchErrors} failed to fetch` : '') +
|
|
79
|
+
(rateLimited > 0 ? `; ${rateLimited} rate-limited (HTTP 429)` : '');
|
|
75
80
|
const details = {
|
|
76
81
|
totalLinks,
|
|
77
82
|
testedLinks: results.length,
|
|
@@ -79,13 +84,15 @@ async function checkLlmsTxtLinksResolve(ctx) {
|
|
|
79
84
|
resolved,
|
|
80
85
|
broken: broken.map((b) => ({ url: b.url, status: b.status, error: b.error })),
|
|
81
86
|
resolveRate: Math.round(resolveRate * 100),
|
|
87
|
+
fetchErrors,
|
|
88
|
+
rateLimited,
|
|
82
89
|
};
|
|
83
90
|
if (resolveRate === 1) {
|
|
84
91
|
return {
|
|
85
92
|
id: 'llms-txt-links-resolve',
|
|
86
93
|
category: 'llms-txt',
|
|
87
94
|
status: 'pass',
|
|
88
|
-
message: `All ${results.length} tested
|
|
95
|
+
message: `All ${results.length} tested ${linkLabel} resolve (${totalLinks} total links)${suffix}`,
|
|
89
96
|
details,
|
|
90
97
|
};
|
|
91
98
|
}
|
|
@@ -94,7 +101,7 @@ async function checkLlmsTxtLinksResolve(ctx) {
|
|
|
94
101
|
id: 'llms-txt-links-resolve',
|
|
95
102
|
category: 'llms-txt',
|
|
96
103
|
status: 'warn',
|
|
97
|
-
message: `${resolved}/${results.length}
|
|
104
|
+
message: `${resolved}/${results.length} ${linkLabel} resolve (${Math.round(resolveRate * 100)}%); ${broken.length} broken${suffix}`,
|
|
98
105
|
details,
|
|
99
106
|
};
|
|
100
107
|
}
|
|
@@ -102,7 +109,7 @@ async function checkLlmsTxtLinksResolve(ctx) {
|
|
|
102
109
|
id: 'llms-txt-links-resolve',
|
|
103
110
|
category: 'llms-txt',
|
|
104
111
|
status: 'fail',
|
|
105
|
-
message: `Only ${resolved}/${results.length}
|
|
112
|
+
message: `Only ${resolved}/${results.length} ${linkLabel} resolve (${Math.round(resolveRate * 100)}%); ${broken.length} broken${suffix}`,
|
|
106
113
|
details,
|
|
107
114
|
};
|
|
108
115
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llms-txt-links-resolve.js","sourceRoot":"","sources":["../../../src/checks/llms-txt/llms-txt-links-resolve.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"llms-txt-links-resolve.js","sourceRoot":"","sources":["../../../src/checks/llms-txt/llms-txt-links-resolve.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,106 @@
|
|
|
1
1
|
import { registerCheck } from '../registry.js';
|
|
2
|
-
|
|
2
|
+
import { looksLikeMarkdown } from '../../helpers/detect-markdown.js';
|
|
3
|
+
import { discoverAndSamplePages } from '../../helpers/get-page-urls.js';
|
|
4
|
+
async function check(ctx) {
|
|
5
|
+
const id = 'content-negotiation';
|
|
6
|
+
const category = 'markdown-availability';
|
|
7
|
+
const { urls: pageUrls, totalPages, sampled: wasSampled, warnings, } = await discoverAndSamplePages(ctx);
|
|
8
|
+
const results = [];
|
|
9
|
+
const concurrency = ctx.options.maxConcurrency;
|
|
10
|
+
for (let i = 0; i < pageUrls.length; i += concurrency) {
|
|
11
|
+
const batch = pageUrls.slice(i, i + concurrency);
|
|
12
|
+
const batchResults = await Promise.all(batch.map(async (url) => {
|
|
13
|
+
try {
|
|
14
|
+
const response = await ctx.http.fetch(url, {
|
|
15
|
+
headers: { Accept: 'text/markdown' },
|
|
16
|
+
});
|
|
17
|
+
const body = await response.text();
|
|
18
|
+
const contentType = response.headers.get('content-type') ?? '';
|
|
19
|
+
const isMarkdownType = contentType.includes('text/markdown');
|
|
20
|
+
const isMarkdownBody = looksLikeMarkdown(body);
|
|
21
|
+
let classification;
|
|
22
|
+
if (isMarkdownType && isMarkdownBody) {
|
|
23
|
+
classification = 'markdown-with-correct-type';
|
|
24
|
+
// Cache the markdown content (only if not already cached by md-url check)
|
|
25
|
+
if (!ctx.pageCache.has(url)) {
|
|
26
|
+
ctx.pageCache.set(url, {
|
|
27
|
+
url,
|
|
28
|
+
markdown: { content: body, source: 'content-negotiation' },
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else if (isMarkdownBody) {
|
|
33
|
+
classification = 'markdown-with-wrong-type';
|
|
34
|
+
if (!ctx.pageCache.has(url)) {
|
|
35
|
+
ctx.pageCache.set(url, {
|
|
36
|
+
url,
|
|
37
|
+
markdown: { content: body, source: 'content-negotiation' },
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
classification = 'html';
|
|
43
|
+
}
|
|
44
|
+
return { url, classification, contentType, status: response.status };
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
return {
|
|
48
|
+
url,
|
|
49
|
+
classification: 'html',
|
|
50
|
+
contentType: '',
|
|
51
|
+
status: 0,
|
|
52
|
+
error: err instanceof Error ? err.message : String(err),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}));
|
|
56
|
+
results.push(...batchResults);
|
|
57
|
+
}
|
|
58
|
+
const markdownWithCorrectType = results.filter((r) => r.classification === 'markdown-with-correct-type').length;
|
|
59
|
+
const markdownWithWrongType = results.filter((r) => r.classification === 'markdown-with-wrong-type').length;
|
|
60
|
+
const htmlOnly = results.filter((r) => r.classification === 'html').length;
|
|
61
|
+
const negotiationRate = Math.round((markdownWithCorrectType / results.length) * 100);
|
|
62
|
+
const fetchErrors = results.filter((r) => r.error).length;
|
|
63
|
+
const rateLimited = results.filter((r) => r.status === 429).length;
|
|
64
|
+
const pageLabel = wasSampled ? 'sampled pages' : 'pages';
|
|
65
|
+
const suffix = (fetchErrors > 0 ? `; ${fetchErrors} failed to fetch` : '') +
|
|
66
|
+
(rateLimited > 0 ? `; ${rateLimited} rate-limited (HTTP 429)` : '');
|
|
67
|
+
const details = {
|
|
68
|
+
totalPages,
|
|
69
|
+
testedPages: results.length,
|
|
70
|
+
sampled: wasSampled,
|
|
71
|
+
markdownWithCorrectType,
|
|
72
|
+
markdownWithWrongType,
|
|
73
|
+
htmlOnly,
|
|
74
|
+
negotiationRate,
|
|
75
|
+
fetchErrors,
|
|
76
|
+
rateLimited,
|
|
77
|
+
pageResults: results,
|
|
78
|
+
discoveryWarnings: warnings,
|
|
79
|
+
};
|
|
80
|
+
if (negotiationRate >= 90) {
|
|
81
|
+
return {
|
|
82
|
+
id,
|
|
83
|
+
category,
|
|
84
|
+
status: 'pass',
|
|
85
|
+
message: `${markdownWithCorrectType}/${results.length} ${pageLabel} support content negotiation (${negotiationRate}%)${suffix}`,
|
|
86
|
+
details,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (markdownWithCorrectType > 0 || markdownWithWrongType > 0) {
|
|
90
|
+
return {
|
|
91
|
+
id,
|
|
92
|
+
category,
|
|
93
|
+
status: 'warn',
|
|
94
|
+
message: `Content negotiation partially supported: ${markdownWithCorrectType} correct type, ${markdownWithWrongType} wrong type, ${htmlOnly} HTML only${suffix}`,
|
|
95
|
+
details,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
3
98
|
return {
|
|
4
|
-
id
|
|
5
|
-
category
|
|
6
|
-
status: '
|
|
7
|
-
message:
|
|
99
|
+
id,
|
|
100
|
+
category,
|
|
101
|
+
status: 'fail',
|
|
102
|
+
message: `Server ignores Accept: text/markdown header (0/${results.length} ${pageLabel} return markdown)${suffix}`,
|
|
103
|
+
details,
|
|
8
104
|
};
|
|
9
105
|
}
|
|
10
106
|
registerCheck({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-negotiation.js","sourceRoot":"","sources":["../../../src/checks/markdown-availability/content-negotiation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"content-negotiation.js","sourceRoot":"","sources":["../../../src/checks/markdown-availability/content-negotiation.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,87 @@
|
|
|
1
1
|
import { registerCheck } from '../registry.js';
|
|
2
|
-
|
|
2
|
+
import { looksLikeMarkdown } from '../../helpers/detect-markdown.js';
|
|
3
|
+
import { discoverAndSamplePages } from '../../helpers/get-page-urls.js';
|
|
4
|
+
import { toMdUrls } from '../../helpers/to-md-urls.js';
|
|
5
|
+
async function check(ctx) {
|
|
6
|
+
const id = 'markdown-url-support';
|
|
7
|
+
const category = 'markdown-availability';
|
|
8
|
+
const { urls: pageUrls, totalPages, sampled: wasSampled, warnings, } = await discoverAndSamplePages(ctx);
|
|
9
|
+
const results = [];
|
|
10
|
+
const concurrency = ctx.options.maxConcurrency;
|
|
11
|
+
for (let i = 0; i < pageUrls.length; i += concurrency) {
|
|
12
|
+
const batch = pageUrls.slice(i, i + concurrency);
|
|
13
|
+
const batchResults = await Promise.all(batch.map(async (url) => {
|
|
14
|
+
const candidates = toMdUrls(url);
|
|
15
|
+
let lastError;
|
|
16
|
+
for (const mdUrl of candidates) {
|
|
17
|
+
try {
|
|
18
|
+
const response = await ctx.http.fetch(mdUrl);
|
|
19
|
+
const body = await response.text();
|
|
20
|
+
const contentType = response.headers.get('content-type') ?? '';
|
|
21
|
+
const isMarkdownType = contentType.includes('text/markdown');
|
|
22
|
+
const isMarkdownBody = looksLikeMarkdown(body);
|
|
23
|
+
const supported = response.ok && (isMarkdownType || isMarkdownBody);
|
|
24
|
+
if (supported) {
|
|
25
|
+
ctx.pageCache.set(url, {
|
|
26
|
+
url,
|
|
27
|
+
markdown: { content: body, source: 'md-url' },
|
|
28
|
+
});
|
|
29
|
+
return { url, mdUrl, supported: true, status: response.status };
|
|
30
|
+
}
|
|
31
|
+
lastError = undefined; // Got a response, not a fetch error
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
lastError = err instanceof Error ? err.message : String(err);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return { url, mdUrl: candidates[0], supported: false, status: 0, error: lastError };
|
|
38
|
+
}));
|
|
39
|
+
results.push(...batchResults);
|
|
40
|
+
}
|
|
41
|
+
const mdSupported = results.filter((r) => r.supported).length;
|
|
42
|
+
const mdUnsupported = results.length - mdSupported;
|
|
43
|
+
const supportRate = Math.round((mdSupported / results.length) * 100);
|
|
44
|
+
const fetchErrors = results.filter((r) => r.error).length;
|
|
45
|
+
const rateLimited = results.filter((r) => r.status === 429).length;
|
|
46
|
+
const pageLabel = wasSampled ? 'sampled pages' : 'pages';
|
|
47
|
+
const suffix = (fetchErrors > 0 ? `; ${fetchErrors} failed to fetch` : '') +
|
|
48
|
+
(rateLimited > 0 ? `; ${rateLimited} rate-limited (HTTP 429)` : '');
|
|
49
|
+
const details = {
|
|
50
|
+
totalPages,
|
|
51
|
+
testedPages: results.length,
|
|
52
|
+
sampled: wasSampled,
|
|
53
|
+
mdSupported,
|
|
54
|
+
mdUnsupported,
|
|
55
|
+
supportRate,
|
|
56
|
+
fetchErrors,
|
|
57
|
+
rateLimited,
|
|
58
|
+
pageResults: results,
|
|
59
|
+
discoveryWarnings: warnings,
|
|
60
|
+
};
|
|
61
|
+
if (supportRate >= 90) {
|
|
62
|
+
return {
|
|
63
|
+
id,
|
|
64
|
+
category,
|
|
65
|
+
status: 'pass',
|
|
66
|
+
message: `${mdSupported}/${results.length} ${pageLabel} support .md URLs (${supportRate}%)${suffix}`,
|
|
67
|
+
details,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
if (mdSupported > 0) {
|
|
71
|
+
return {
|
|
72
|
+
id,
|
|
73
|
+
category,
|
|
74
|
+
status: 'warn',
|
|
75
|
+
message: `${mdSupported}/${results.length} ${pageLabel} support .md URLs (${supportRate}%); inconsistent support${suffix}`,
|
|
76
|
+
details,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
3
79
|
return {
|
|
4
|
-
id
|
|
5
|
-
category
|
|
6
|
-
status: '
|
|
7
|
-
message:
|
|
80
|
+
id,
|
|
81
|
+
category,
|
|
82
|
+
status: 'fail',
|
|
83
|
+
message: `No ${pageLabel} support .md URLs (0/${results.length} tested)${suffix}`,
|
|
84
|
+
details,
|
|
8
85
|
};
|
|
9
86
|
}
|
|
10
87
|
registerCheck({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown-url-support.js","sourceRoot":"","sources":["../../../src/checks/markdown-availability/markdown-url-support.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"markdown-url-support.js","sourceRoot":"","sources":["../../../src/checks/markdown-availability/markdown-url-support.ts"],"names":[],"mappings":"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"}
|