afdocs 0.6.2 → 0.7.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 +64 -6
- package/dist/helpers/config.d.ts +5 -0
- package/dist/helpers/config.d.ts.map +1 -1
- package/dist/helpers/config.js +26 -15
- package/dist/helpers/config.js.map +1 -1
- package/dist/helpers/vitest-runner.d.ts +6 -3
- package/dist/helpers/vitest-runner.d.ts.map +1 -1
- package/dist/helpers/vitest-runner.js +52 -21
- package/dist/helpers/vitest-runner.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -124,11 +124,51 @@ const result = await check.run(ctx);
|
|
|
124
124
|
|
|
125
125
|
## Test helpers
|
|
126
126
|
|
|
127
|
-
afdocs includes vitest helpers so you can add agent-friendliness checks to your docs site's
|
|
127
|
+
afdocs includes vitest helpers so you can add agent-friendliness checks to your docs site's CI pipeline. For a ready-to-copy setup with a GitHub Actions workflow, see the [`examples/`](examples/) directory.
|
|
128
128
|
|
|
129
|
-
###
|
|
129
|
+
### Setup
|
|
130
130
|
|
|
131
|
-
|
|
131
|
+
Install afdocs and vitest:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
npm install -D afdocs vitest
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Create `agent-docs.config.yml` in your project root (or a `tests/` subdirectory):
|
|
138
|
+
|
|
139
|
+
```yaml
|
|
140
|
+
url: https://docs.example.com
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Create a test file:
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
import { describeAgentDocsPerCheck } from 'afdocs/helpers';
|
|
147
|
+
|
|
148
|
+
describeAgentDocsPerCheck();
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Run it:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
npx vitest run agent-docs.test.ts
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Each check appears as its own test in the output, so you can see exactly what passed, warned, failed, or was skipped:
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
✓ Agent-Friendly Documentation > llms-txt-exists
|
|
161
|
+
✓ Agent-Friendly Documentation > llms-txt-valid
|
|
162
|
+
✓ Agent-Friendly Documentation > llms-txt-size
|
|
163
|
+
× Agent-Friendly Documentation > markdown-url-support
|
|
164
|
+
↓ Agent-Friendly Documentation > page-size-markdown
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Checks that fail cause the test to fail. Checks that warn still pass (they're informational). Checks skipped due to unmet dependencies or config filtering show as skipped.
|
|
168
|
+
|
|
169
|
+
### Running a subset of checks
|
|
170
|
+
|
|
171
|
+
If your platform doesn't support certain checks (for example, you can't serve markdown), you can limit which checks run via the config:
|
|
132
172
|
|
|
133
173
|
```yaml
|
|
134
174
|
url: https://docs.example.com
|
|
@@ -136,9 +176,27 @@ checks:
|
|
|
136
176
|
- llms-txt-exists
|
|
137
177
|
- llms-txt-valid
|
|
138
178
|
- llms-txt-size
|
|
179
|
+
- http-status-codes
|
|
180
|
+
- auth-gate-detection
|
|
139
181
|
```
|
|
140
182
|
|
|
141
|
-
|
|
183
|
+
Only the listed checks will run. The rest show as skipped in the test output.
|
|
184
|
+
|
|
185
|
+
### Config resolution
|
|
186
|
+
|
|
187
|
+
The helpers look for `agent-docs.config.yml` (or `.yaml`) starting from `process.cwd()` and walking up the directory tree, so the config works whether your test file is at the project root or in a subdirectory. You can also pass an explicit directory:
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
describeAgentDocsPerCheck(__dirname);
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Timeouts
|
|
194
|
+
|
|
195
|
+
The helpers set a 120-second timeout on the check run automatically. No vitest timeout configuration is needed.
|
|
196
|
+
|
|
197
|
+
### Summary helper
|
|
198
|
+
|
|
199
|
+
If you don't need per-check granularity, `describeAgentDocs` provides a simpler two-test suite (one to run checks, one to assert no failures):
|
|
142
200
|
|
|
143
201
|
```ts
|
|
144
202
|
import { describeAgentDocs } from 'afdocs/helpers';
|
|
@@ -146,10 +204,10 @@ import { describeAgentDocs } from 'afdocs/helpers';
|
|
|
146
204
|
describeAgentDocs();
|
|
147
205
|
```
|
|
148
206
|
|
|
149
|
-
This reads the config and generates one test assertion covering all specified checks.
|
|
150
|
-
|
|
151
207
|
### Direct imports
|
|
152
208
|
|
|
209
|
+
For full control, use the programmatic API directly:
|
|
210
|
+
|
|
153
211
|
```ts
|
|
154
212
|
import { createContext, getCheck } from 'afdocs';
|
|
155
213
|
import { describe, it, expect } from 'vitest';
|
package/dist/helpers/config.d.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
import type { AgentDocsConfig } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Search for an agent-docs config file starting from `dir` and walking up
|
|
4
|
+
* to the filesystem root (like eslint, prettier, etc.).
|
|
5
|
+
* If `dir` is omitted, starts from `process.cwd()`.
|
|
6
|
+
*/
|
|
2
7
|
export declare function loadConfig(dir?: string): Promise<AgentDocsConfig>;
|
|
3
8
|
//# sourceMappingURL=config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/helpers/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAInD,wBAAsB,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/helpers/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAInD;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CA2BvE"}
|
package/dist/helpers/config.js
CHANGED
|
@@ -1,24 +1,35 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
|
-
import { resolve } from 'node:path';
|
|
2
|
+
import { dirname, resolve } from 'node:path';
|
|
3
3
|
import { parse as parseYaml } from 'yaml';
|
|
4
4
|
const CONFIG_FILENAMES = ['agent-docs.config.yml', 'agent-docs.config.yaml'];
|
|
5
|
+
/**
|
|
6
|
+
* Search for an agent-docs config file starting from `dir` and walking up
|
|
7
|
+
* to the filesystem root (like eslint, prettier, etc.).
|
|
8
|
+
* If `dir` is omitted, starts from `process.cwd()`.
|
|
9
|
+
*/
|
|
5
10
|
export async function loadConfig(dir) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
let searchDir = resolve(dir ?? process.cwd());
|
|
12
|
+
while (true) {
|
|
13
|
+
for (const filename of CONFIG_FILENAMES) {
|
|
14
|
+
const filepath = resolve(searchDir, filename);
|
|
15
|
+
try {
|
|
16
|
+
const content = await readFile(filepath, 'utf-8');
|
|
17
|
+
const parsed = parseYaml(content);
|
|
18
|
+
if (!parsed.url) {
|
|
19
|
+
throw new Error(`Config file ${filepath} is missing required "url" field`);
|
|
20
|
+
}
|
|
21
|
+
return parsed;
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
if (err.code === 'ENOENT')
|
|
25
|
+
continue;
|
|
26
|
+
throw err;
|
|
14
27
|
}
|
|
15
|
-
return parsed;
|
|
16
|
-
}
|
|
17
|
-
catch (err) {
|
|
18
|
-
if (err.code === 'ENOENT')
|
|
19
|
-
continue;
|
|
20
|
-
throw err;
|
|
21
28
|
}
|
|
29
|
+
const parent = dirname(searchDir);
|
|
30
|
+
if (parent === searchDir)
|
|
31
|
+
break; // reached filesystem root
|
|
32
|
+
searchDir = parent;
|
|
22
33
|
}
|
|
23
34
|
throw new Error(`No agent-docs config file found. Create ${CONFIG_FILENAMES[0]} with at least a "url" field.`);
|
|
24
35
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/helpers/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/helpers/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAG1C,MAAM,gBAAgB,GAAG,CAAC,uBAAuB,EAAE,wBAAwB,CAAC,CAAC;AAE7E;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAY;IAC3C,IAAI,SAAS,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAE9C,OAAO,IAAI,EAAE,CAAC;QACZ,KAAK,MAAM,QAAQ,IAAI,gBAAgB,EAAE,CAAC;YACxC,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YAC9C,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAClD,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAoB,CAAC;gBACrD,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;oBAChB,MAAM,IAAI,KAAK,CAAC,eAAe,QAAQ,kCAAkC,CAAC,CAAC;gBAC7E,CAAC;gBACD,OAAO,MAAM,CAAC;YAChB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;oBAAE,SAAS;gBAC/D,MAAM,GAAG,CAAC;YACZ,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;QAClC,IAAI,MAAM,KAAK,SAAS;YAAE,MAAM,CAAC,0BAA0B;QAC3D,SAAS,GAAG,MAAM,CAAC;IACrB,CAAC;IAED,MAAM,IAAI,KAAK,CACb,2CAA2C,gBAAgB,CAAC,CAAC,CAAC,+BAA+B,CAC9F,CAAC;AACJ,CAAC"}
|
|
@@ -2,20 +2,23 @@ import type { AgentDocsConfig } from '../types.js';
|
|
|
2
2
|
import '../checks/index.js';
|
|
3
3
|
/**
|
|
4
4
|
* Auto-generates vitest tests from an agent-docs config file.
|
|
5
|
+
* Produces a single pass/fail test with a summary of all check results.
|
|
5
6
|
*
|
|
6
|
-
* Usage
|
|
7
|
+
* Usage:
|
|
7
8
|
* ```ts
|
|
8
|
-
* import { describeAgentDocs } from '
|
|
9
|
+
* import { describeAgentDocs } from 'afdocs/helpers';
|
|
9
10
|
* describeAgentDocs();
|
|
10
11
|
* ```
|
|
11
12
|
*/
|
|
12
13
|
export declare function describeAgentDocs(configOrDir?: AgentDocsConfig | string): void;
|
|
13
14
|
/**
|
|
14
15
|
* Auto-generates individual vitest tests per check from an agent-docs config.
|
|
16
|
+
* Each check appears as its own test line in CI output, giving clear visibility
|
|
17
|
+
* into which checks passed, warned, failed, or were skipped.
|
|
15
18
|
*
|
|
16
19
|
* Usage:
|
|
17
20
|
* ```ts
|
|
18
|
-
* import { describeAgentDocsPerCheck } from '
|
|
21
|
+
* import { describeAgentDocsPerCheck } from 'afdocs/helpers';
|
|
19
22
|
* describeAgentDocsPerCheck();
|
|
20
23
|
* ```
|
|
21
24
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitest-runner.d.ts","sourceRoot":"","sources":["../../src/helpers/vitest-runner.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"vitest-runner.d.ts","sourceRoot":"","sources":["../../src/helpers/vitest-runner.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAA6B,MAAM,aAAa,CAAC;AAG9E,OAAO,oBAAoB,CAAC;AAiB5B;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,CAAC,EAAE,eAAe,GAAG,MAAM,GAAG,IAAI,CAuB9E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,CAAC,EAAE,eAAe,GAAG,MAAM,GAAG,IAAI,CAyCtF"}
|
|
@@ -1,14 +1,28 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
1
|
+
import { describe, it, expect, beforeAll } from 'vitest';
|
|
2
2
|
import { runChecks } from '../runner.js';
|
|
3
3
|
import { loadConfig } from './config.js';
|
|
4
|
+
import { getChecksSorted } from '../checks/registry.js';
|
|
4
5
|
// Ensure all checks are registered
|
|
5
6
|
import '../checks/index.js';
|
|
7
|
+
const STATUS_ICON = {
|
|
8
|
+
pass: '\u2713',
|
|
9
|
+
warn: '\u26A0',
|
|
10
|
+
fail: '\u2717',
|
|
11
|
+
skip: '\u2192',
|
|
12
|
+
error: '!',
|
|
13
|
+
};
|
|
14
|
+
function resolveConfig(configOrDir) {
|
|
15
|
+
if (typeof configOrDir === 'object')
|
|
16
|
+
return Promise.resolve(configOrDir);
|
|
17
|
+
return loadConfig(typeof configOrDir === 'string' ? configOrDir : undefined);
|
|
18
|
+
}
|
|
6
19
|
/**
|
|
7
20
|
* Auto-generates vitest tests from an agent-docs config file.
|
|
21
|
+
* Produces a single pass/fail test with a summary of all check results.
|
|
8
22
|
*
|
|
9
|
-
* Usage
|
|
23
|
+
* Usage:
|
|
10
24
|
* ```ts
|
|
11
|
-
* import { describeAgentDocs } from '
|
|
25
|
+
* import { describeAgentDocs } from 'afdocs/helpers';
|
|
12
26
|
* describeAgentDocs();
|
|
13
27
|
* ```
|
|
14
28
|
*/
|
|
@@ -16,15 +30,13 @@ export function describeAgentDocs(configOrDir) {
|
|
|
16
30
|
describe('Agent-Friendly Documentation', () => {
|
|
17
31
|
let results;
|
|
18
32
|
it('should run checks', async () => {
|
|
19
|
-
const config =
|
|
20
|
-
? configOrDir
|
|
21
|
-
: await loadConfig(typeof configOrDir === 'string' ? configOrDir : undefined);
|
|
33
|
+
const config = await resolveConfig(configOrDir);
|
|
22
34
|
const report = await runChecks(config.url, {
|
|
23
35
|
checkIds: config.checks,
|
|
24
36
|
...config.options,
|
|
25
37
|
});
|
|
26
38
|
results = report.results;
|
|
27
|
-
});
|
|
39
|
+
}, 120_000);
|
|
28
40
|
it('should have no failing checks', () => {
|
|
29
41
|
expect(results).toBeDefined();
|
|
30
42
|
const failures = results.filter((r) => r.status === 'fail');
|
|
@@ -37,31 +49,50 @@ export function describeAgentDocs(configOrDir) {
|
|
|
37
49
|
}
|
|
38
50
|
/**
|
|
39
51
|
* Auto-generates individual vitest tests per check from an agent-docs config.
|
|
52
|
+
* Each check appears as its own test line in CI output, giving clear visibility
|
|
53
|
+
* into which checks passed, warned, failed, or were skipped.
|
|
40
54
|
*
|
|
41
55
|
* Usage:
|
|
42
56
|
* ```ts
|
|
43
|
-
* import { describeAgentDocsPerCheck } from '
|
|
57
|
+
* import { describeAgentDocsPerCheck } from 'afdocs/helpers';
|
|
44
58
|
* describeAgentDocsPerCheck();
|
|
45
59
|
* ```
|
|
46
60
|
*/
|
|
47
61
|
export function describeAgentDocsPerCheck(configOrDir) {
|
|
48
62
|
describe('Agent-Friendly Documentation', () => {
|
|
49
|
-
let
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const report = await runChecks(config.url, {
|
|
63
|
+
let report;
|
|
64
|
+
let resultsByCheck;
|
|
65
|
+
// Run all checks once upfront
|
|
66
|
+
beforeAll(async () => {
|
|
67
|
+
const config = await resolveConfig(configOrDir);
|
|
68
|
+
report = await runChecks(config.url, {
|
|
56
69
|
checkIds: config.checks,
|
|
57
70
|
...config.options,
|
|
58
71
|
});
|
|
59
|
-
|
|
60
|
-
});
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
|
|
72
|
+
resultsByCheck = new Map(report.results.map((r) => [r.id, r]));
|
|
73
|
+
}, 120_000);
|
|
74
|
+
// Register a test per known check. Checks not included in the run
|
|
75
|
+
// (filtered via config.checks) are reported as skipped rather than
|
|
76
|
+
// silently passing, so CI output accurately reflects what was tested.
|
|
77
|
+
const allChecks = getChecksSorted();
|
|
78
|
+
for (const check of allChecks) {
|
|
79
|
+
it(check.id, (ctx) => {
|
|
80
|
+
const result = resultsByCheck?.get(check.id);
|
|
81
|
+
if (!result) {
|
|
82
|
+
// Check was filtered out by config
|
|
83
|
+
ctx.skip();
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const icon = STATUS_ICON[result.status] ?? '?';
|
|
87
|
+
console.log(`${icon} [${result.status}] ${result.message}`);
|
|
88
|
+
if (result.status === 'fail') {
|
|
89
|
+
expect.fail(`${result.message}`);
|
|
90
|
+
}
|
|
91
|
+
if (result.status === 'error') {
|
|
92
|
+
expect.fail(`Check error: ${result.message}`);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
65
96
|
});
|
|
66
97
|
}
|
|
67
98
|
//# sourceMappingURL=vitest-runner.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitest-runner.js","sourceRoot":"","sources":["../../src/helpers/vitest-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"vitest-runner.js","sourceRoot":"","sources":["../../src/helpers/vitest-runner.ts"],"names":[],"mappings":"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"}
|