afdocs 0.4.0 → 0.5.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.
Files changed (73) hide show
  1. package/README.md +46 -23
  2. package/dist/checks/authentication/auth-alternative-access.js +109 -6
  3. package/dist/checks/authentication/auth-alternative-access.js.map +1 -1
  4. package/dist/checks/authentication/auth-gate-detection.js +8 -3
  5. package/dist/checks/authentication/auth-gate-detection.js.map +1 -1
  6. package/dist/checks/content-structure/markdown-code-fence-validity.js +1 -1
  7. package/dist/checks/content-structure/markdown-code-fence-validity.js.map +1 -1
  8. package/dist/checks/content-structure/section-header-quality.js +240 -6
  9. package/dist/checks/content-structure/section-header-quality.js.map +1 -1
  10. package/dist/checks/content-structure/tabbed-content-serialization.js +200 -5
  11. package/dist/checks/content-structure/tabbed-content-serialization.js.map +1 -1
  12. package/dist/checks/index.d.ts +1 -0
  13. package/dist/checks/index.d.ts.map +1 -1
  14. package/dist/checks/index.js +1 -0
  15. package/dist/checks/index.js.map +1 -1
  16. package/dist/checks/llms-txt/llms-txt-exists.js +17 -10
  17. package/dist/checks/llms-txt/llms-txt-exists.js.map +1 -1
  18. package/dist/checks/observability/llms-txt-freshness.d.ts +24 -1
  19. package/dist/checks/observability/llms-txt-freshness.d.ts.map +1 -1
  20. package/dist/checks/observability/llms-txt-freshness.js +391 -5
  21. package/dist/checks/observability/llms-txt-freshness.js.map +1 -1
  22. package/dist/checks/observability/markdown-content-parity.js +599 -5
  23. package/dist/checks/observability/markdown-content-parity.js.map +1 -1
  24. package/dist/checks/page-size/content-start-position.js +3 -7
  25. package/dist/checks/page-size/content-start-position.js.map +1 -1
  26. package/dist/checks/page-size/page-size-html.js +4 -8
  27. package/dist/checks/page-size/page-size-html.js.map +1 -1
  28. package/dist/checks/page-size/rendering-strategy.d.ts +2 -0
  29. package/dist/checks/page-size/rendering-strategy.d.ts.map +1 -0
  30. package/dist/checks/page-size/rendering-strategy.js +154 -0
  31. package/dist/checks/page-size/rendering-strategy.js.map +1 -0
  32. package/dist/cli/commands/check.d.ts.map +1 -1
  33. package/dist/cli/commands/check.js +9 -0
  34. package/dist/cli/commands/check.js.map +1 -1
  35. package/dist/cli/formatters/text.d.ts.map +1 -1
  36. package/dist/cli/formatters/text.js +13 -3
  37. package/dist/cli/formatters/text.js.map +1 -1
  38. package/dist/cli/index.d.ts.map +1 -1
  39. package/dist/cli/index.js +4 -1
  40. package/dist/cli/index.js.map +1 -1
  41. package/dist/constants.d.ts.map +1 -1
  42. package/dist/constants.js +1 -0
  43. package/dist/constants.js.map +1 -1
  44. package/dist/helpers/detect-rendering.d.ts +31 -0
  45. package/dist/helpers/detect-rendering.d.ts.map +1 -0
  46. package/dist/helpers/detect-rendering.js +85 -0
  47. package/dist/helpers/detect-rendering.js.map +1 -0
  48. package/dist/helpers/detect-tabs.d.ts +12 -0
  49. package/dist/helpers/detect-tabs.d.ts.map +1 -0
  50. package/dist/helpers/detect-tabs.js +309 -0
  51. package/dist/helpers/detect-tabs.js.map +1 -0
  52. package/dist/helpers/fetch-page.d.ts +8 -0
  53. package/dist/helpers/fetch-page.d.ts.map +1 -0
  54. package/dist/helpers/fetch-page.js +20 -0
  55. package/dist/helpers/fetch-page.js.map +1 -0
  56. package/dist/helpers/get-page-urls.d.ts +9 -0
  57. package/dist/helpers/get-page-urls.d.ts.map +1 -1
  58. package/dist/helpers/get-page-urls.js +153 -21
  59. package/dist/helpers/get-page-urls.js.map +1 -1
  60. package/dist/helpers/index.d.ts +5 -0
  61. package/dist/helpers/index.d.ts.map +1 -1
  62. package/dist/helpers/index.js +3 -0
  63. package/dist/helpers/index.js.map +1 -1
  64. package/dist/helpers/to-md-urls.d.ts +4 -0
  65. package/dist/helpers/to-md-urls.d.ts.map +1 -1
  66. package/dist/helpers/to-md-urls.js +13 -0
  67. package/dist/helpers/to-md-urls.js.map +1 -1
  68. package/dist/runner.d.ts.map +1 -1
  69. package/dist/runner.js +1 -0
  70. package/dist/runner.js.map +1 -1
  71. package/dist/types.d.ts +19 -0
  72. package/dist/types.d.ts.map +1 -1
  73. package/package.json +2 -1
package/README.md CHANGED
@@ -7,12 +7,12 @@ Test your documentation site against the [Agent-Friendly Documentation Spec](htt
7
7
 
8
8
  Agents don't use docs like humans. They hit truncation limits, get walls of CSS instead of content, can't follow cross-host redirects, and don't know about quality-of-life improvements like `llms.txt` or `.md` docs pages that would make life swell. Maybe this is because the industry has lacked guidance - until now.
9
9
 
10
- afdocs runs 21 checks across 8 categories to evaluate how well your docs serve agent consumers. 16 are fully implemented; the rest return `skip` until completed.
10
+ afdocs runs 22 checks across 8 categories to evaluate how well your docs serve agent consumers.
11
11
 
12
12
  > **Status: Early development (0.x)**
13
13
  > This project is under active development. Check IDs, CLI flags, and output formats may change between minor versions. Feel free to try it out, but don't build automation against specific output until 1.0.
14
14
  >
15
- > Implements [spec v0.1.0](https://agentdocsspec.com/spec) (2026-02-22).
15
+ > Implements [spec v0.2.1](https://agentdocsspec.com/spec) (2026-03-15).
16
16
 
17
17
  ## Quick start
18
18
 
@@ -43,7 +43,7 @@ Authentication
43
43
  ✓ auth-gate-detection: All 50 sampled pages are publicly accessible
44
44
 
45
45
  Summary
46
- 9 passed, 3 failed, 9 skipped (21 total)
46
+ 9 passed, 3 failed, 10 skipped (22 total)
47
47
  ```
48
48
 
49
49
  ## Install
@@ -75,12 +75,34 @@ afdocs check https://docs.example.com --pass-threshold 30000 --fail-threshold 80
75
75
  | `--format <format>` | `text` | Output format: `text` or `json` |
76
76
  | `-v, --verbose` | | Show per-page details for checks with issues |
77
77
  | `--checks <ids>` | all | Comma-separated list of check IDs |
78
+ | `--sampling <strategy>` | `random` | URL sampling strategy (see below) |
78
79
  | `--max-concurrency <n>` | `3` | Maximum concurrent HTTP requests |
79
80
  | `--request-delay <ms>` | `200` | Delay between requests |
80
81
  | `--max-links <n>` | `50` | Maximum links to test in link checks |
81
82
  | `--pass-threshold <n>` | `50000` | Size pass threshold (characters) |
82
83
  | `--fail-threshold <n>` | `100000` | Size fail threshold (characters) |
83
84
 
85
+ ### Sampling strategies
86
+
87
+ By default, afdocs discovers pages from your site (via `llms.txt`, sitemap, or both) and randomly samples up to `--max-links` pages to check. The `--sampling` flag gives you control over how that sample is selected.
88
+
89
+ | Strategy | Behavior |
90
+ | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
91
+ | `random` | Shuffle discovered URLs and take the first N. Fast and broad, but results vary between runs. |
92
+ | `deterministic` | Sort discovered URLs alphabetically, then pick every Nth URL for an even spread. Produces the same sample on repeated runs as long as the URL set is stable. |
93
+ | `none` | Skip discovery entirely. Only check the URL you pass on the command line. |
94
+
95
+ ```bash
96
+ # Reproducible runs for CI or iteration (same pages every time)
97
+ afdocs check https://docs.example.com --sampling deterministic
98
+
99
+ # Check a single page without any discovery
100
+ afdocs check https://docs.example.com/api/auth --sampling none
101
+
102
+ # Check a single page with specific checks
103
+ afdocs check https://docs.example.com/api/auth --sampling none --checks page-size-html,redirect-behavior
104
+ ```
105
+
84
106
  ### Exit codes
85
107
 
86
108
  - `0` if all checks pass or warn
@@ -144,7 +166,7 @@ describe('agent-friendliness', () => {
144
166
 
145
167
  ## Checks
146
168
 
147
- 21 checks across 8 categories. Checks marked with \* are not yet implemented and return `skip`.
169
+ 22 checks across 8 categories.
148
170
 
149
171
  ### Category 1: llms.txt
150
172
 
@@ -165,19 +187,20 @@ describe('agent-friendliness', () => {
165
187
 
166
188
  ### Category 3: Page Size and Truncation Risk
167
189
 
168
- | Check | Description |
169
- | ------------------------ | ------------------------------------------------ |
170
- | `page-size-markdown` | Character count when served as markdown |
171
- | `page-size-html` | Character count of HTML and post-conversion size |
172
- | `content-start-position` | How far into the response actual content begins |
190
+ | Check | Description |
191
+ | ------------------------ | --------------------------------------------------------------- |
192
+ | `rendering-strategy` | Whether pages contain server-rendered content or are SPA shells |
193
+ | `page-size-markdown` | Character count when served as markdown |
194
+ | `page-size-html` | Character count of HTML and post-conversion size |
195
+ | `content-start-position` | How far into the response actual content begins |
173
196
 
174
197
  ### Category 4: Content Structure
175
198
 
176
- | Check | Description |
177
- | --------------------------------- | -------------------------------------------------- |
178
- | `tabbed-content-serialization` \* | Whether tabbed content creates oversized output |
179
- | `section-header-quality` \* | Whether headers in tabbed sections include context |
180
- | `markdown-code-fence-validity` | Whether markdown has unclosed code fences |
199
+ | Check | Description |
200
+ | ------------------------------ | -------------------------------------------------- |
201
+ | `tabbed-content-serialization` | Whether tabbed content creates oversized output |
202
+ | `section-header-quality` | Whether headers in tabbed sections include context |
203
+ | `markdown-code-fence-validity` | Whether markdown has unclosed code fences |
181
204
 
182
205
  ### Category 5: URL Stability and Redirects
183
206
 
@@ -194,18 +217,18 @@ describe('agent-friendliness', () => {
194
217
 
195
218
  ### Category 7: Observability and Content Health
196
219
 
197
- | Check | Description |
198
- | ---------------------------- | ---------------------------------------------- |
199
- | `llms-txt-freshness` \* | Whether `llms.txt` reflects current site state |
200
- | `markdown-content-parity` \* | Whether markdown and HTML versions match |
201
- | `cache-header-hygiene` | Whether cache headers allow timely updates |
220
+ | Check | Description |
221
+ | ------------------------- | ---------------------------------------------- |
222
+ | `llms-txt-freshness` | Whether `llms.txt` reflects current site state |
223
+ | `markdown-content-parity` | Whether markdown and HTML versions match |
224
+ | `cache-header-hygiene` | Whether cache headers allow timely updates |
202
225
 
203
226
  ### Category 8: Authentication and Access
204
227
 
205
- | Check | Description |
206
- | ---------------------------- | -------------------------------------------------------------------- |
207
- | `auth-gate-detection` | Whether documentation pages require authentication to access content |
208
- | `auth-alternative-access` \* | Whether auth-gated sites provide alternative access paths for agents |
228
+ | Check | Description |
229
+ | ------------------------- | -------------------------------------------------------------------- |
230
+ | `auth-gate-detection` | Whether documentation pages require authentication to access content |
231
+ | `auth-alternative-access` | Whether auth-gated sites provide alternative access paths for agents |
209
232
 
210
233
  ## Check dependencies
211
234
 
@@ -1,17 +1,120 @@
1
1
  import { registerCheck } from '../registry.js';
2
- async function check(_ctx) {
2
+ async function check(ctx) {
3
+ const id = 'auth-alternative-access';
4
+ const category = 'authentication';
5
+ // Read auth-gate-detection result; skip if it didn't run or docs are all public
6
+ const authResult = ctx.previousResults.get('auth-gate-detection');
7
+ if (!authResult) {
8
+ return {
9
+ id,
10
+ category,
11
+ status: 'skip',
12
+ message: 'auth-gate-detection did not run',
13
+ };
14
+ }
15
+ if (authResult.status === 'pass') {
16
+ return {
17
+ id,
18
+ category,
19
+ status: 'skip',
20
+ message: 'All docs pages are publicly accessible; no alternative access paths needed',
21
+ };
22
+ }
23
+ if (authResult.status === 'skip' || authResult.status === 'error') {
24
+ return {
25
+ id,
26
+ category,
27
+ status: 'skip',
28
+ message: `auth-gate-detection ${authResult.status === 'error' ? 'errored' : 'was skipped'}; cannot assess alternative access`,
29
+ };
30
+ }
31
+ // Auth-gate-detection returned warn or fail — look for alternative access paths
32
+ const authDetails = (authResult.details ?? {});
33
+ const gatedCount = (authDetails.authRequired ?? 0) +
34
+ (authDetails.softAuthGate ?? 0) +
35
+ (authDetails.authRedirect ?? 0);
36
+ const accessibleCount = authDetails.accessible ?? 0;
37
+ const testedCount = authDetails.testedPages ?? 0;
38
+ const detectedPaths = [];
39
+ // 1. Check for public llms.txt
40
+ const llmsResult = ctx.previousResults.get('llms-txt-exists');
41
+ if (llmsResult?.status === 'pass' || llmsResult?.status === 'warn') {
42
+ detectedPaths.push({
43
+ type: 'public-llms-txt',
44
+ description: 'Site serves a public llms.txt file, giving agents a navigational index even though docs pages are gated',
45
+ });
46
+ }
47
+ // 2. Check for publicly accessible markdown
48
+ const mdUrlResult = ctx.previousResults.get('markdown-url-support');
49
+ const cnResult = ctx.previousResults.get('content-negotiation');
50
+ if (mdUrlResult?.status === 'pass' || mdUrlResult?.status === 'warn') {
51
+ detectedPaths.push({
52
+ type: 'public-markdown',
53
+ description: 'Some pages serve markdown via .md URLs, providing agent-readable content without authentication',
54
+ });
55
+ }
56
+ else if (cnResult?.status === 'pass' || cnResult?.status === 'warn') {
57
+ detectedPaths.push({
58
+ type: 'public-markdown',
59
+ description: 'Some pages serve markdown via content negotiation, providing agent-readable content without authentication',
60
+ });
61
+ }
62
+ // 3. Check for partially accessible pages (from auth-gate-detection itself)
63
+ if (accessibleCount > 0 && gatedCount > 0) {
64
+ const pct = Math.round((accessibleCount / testedCount) * 100);
65
+ detectedPaths.push({
66
+ type: 'partial-public-access',
67
+ description: `${accessibleCount} of ${testedCount} tested pages (${pct}%) are publicly accessible without authentication`,
68
+ });
69
+ }
70
+ // Determine status
71
+ const manualOnlyNote = 'Some access paths cannot be detected automatically: bundled SDK docs, CLI doc commands, and MCP servers';
72
+ let status;
73
+ let message;
74
+ if (detectedPaths.length === 0) {
75
+ status = 'fail';
76
+ message = `No alternative access paths detected for ${gatedCount} auth-gated pages. ${manualOnlyNote}`;
77
+ }
78
+ else {
79
+ // Pass if we found a full-content path (llms.txt + markdown, or most pages accessible).
80
+ // Warn if we only found partial paths (llms.txt alone is just an index, not content).
81
+ const hasContentPath = detectedPaths.some((p) => p.type === 'public-markdown');
82
+ const hasHighAccessibility = accessibleCount > 0 && testedCount > 0 && accessibleCount / testedCount >= 0.5;
83
+ if (hasContentPath || hasHighAccessibility) {
84
+ status = 'pass';
85
+ }
86
+ else {
87
+ status = 'warn';
88
+ }
89
+ const pathSummary = detectedPaths.map((p) => p.type).join(', ');
90
+ message =
91
+ status === 'pass'
92
+ ? `Alternative access detected (${pathSummary}) for site with ${gatedCount} auth-gated pages`
93
+ : `Partial alternative access detected (${pathSummary}) for site with ${gatedCount} auth-gated pages. ${manualOnlyNote}`;
94
+ }
3
95
  return {
4
- id: 'auth-alternative-access',
5
- category: 'authentication',
6
- status: 'skip',
7
- message: 'Not yet implemented',
96
+ id,
97
+ category,
98
+ status,
99
+ message,
100
+ details: {
101
+ gatedPages: gatedCount,
102
+ accessiblePages: accessibleCount,
103
+ testedPages: testedCount,
104
+ detectedPaths,
105
+ manualVerificationNeeded: [
106
+ 'Bundled documentation (docs shipped in package/SDK)',
107
+ 'CLI-based doc access (e.g. `yourproduct docs search "topic"`)',
108
+ 'MCP server providing doc access through tool calls',
109
+ ],
110
+ },
8
111
  };
9
112
  }
10
113
  registerCheck({
11
114
  id: 'auth-alternative-access',
12
115
  category: 'authentication',
13
116
  description: 'Whether an auth-gated documentation site provides alternative access paths for agents',
14
- dependsOn: [['auth-gate-detection']],
117
+ dependsOn: [],
15
118
  run: check,
16
119
  });
17
120
  //# sourceMappingURL=auth-alternative-access.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth-alternative-access.js","sourceRoot":"","sources":["../../../src/checks/authentication/auth-alternative-access.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAG/C,KAAK,UAAU,KAAK,CAAC,IAAkB;IACrC,OAAO;QACL,EAAE,EAAE,yBAAyB;QAC7B,QAAQ,EAAE,gBAAgB;QAC1B,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,qBAAqB;KAC/B,CAAC;AACJ,CAAC;AAED,aAAa,CAAC;IACZ,EAAE,EAAE,yBAAyB;IAC7B,QAAQ,EAAE,gBAAgB;IAC1B,WAAW,EACT,uFAAuF;IACzF,SAAS,EAAE,CAAC,CAAC,qBAAqB,CAAC,CAAC;IACpC,GAAG,EAAE,KAAK;CACX,CAAC,CAAC"}
1
+ {"version":3,"file":"auth-alternative-access.js","sourceRoot":"","sources":["../../../src/checks/authentication/auth-alternative-access.ts"],"names":[],"mappings":"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"}
@@ -25,11 +25,16 @@ function detectLoginForm(body) {
25
25
  if (sample.includes('<input') && sample.includes('type="password"')) {
26
26
  return 'Contains password input field';
27
27
  }
28
- // Check page title for login indicators
28
+ // Check page title for login indicators.
29
+ // Only match titles that suggest the page IS a login form, not pages that
30
+ // mention login as a topic (e.g. "unable to login" in a knowledge base article).
31
+ // We require the login keyword to appear at the start or after a separator.
29
32
  const titleMatch = /<title[^>]*>(.*?)<\/title>/i.exec(sample);
30
33
  if (titleMatch) {
31
- const title = titleMatch[1].toLowerCase();
32
- if (/sign\s*in|log\s*in|authenticate/i.test(title)) {
34
+ const title = titleMatch[1].toLowerCase().trim();
35
+ if (/^(sign\s*in|log\s*in)\b/.test(title) ||
36
+ /[|\-–—:]\s*(sign\s*in|log\s*in)\s*$/i.test(title) ||
37
+ /^authenticate\b/.test(title)) {
33
38
  return `Page title suggests login: "${titleMatch[1].trim()}"`;
34
39
  }
35
40
  }
@@ -1 +1 @@
1
- {"version":3,"file":"auth-gate-detection.js","sourceRoot":"","sources":["../../../src/checks/authentication/auth-gate-detection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth-gate-detection.js","sourceRoot":"","sources":["../../../src/checks/authentication/auth-gate-detection.ts"],"names":[],"mappings":"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"}
@@ -104,7 +104,7 @@ registerCheck({
104
104
  id: 'markdown-code-fence-validity',
105
105
  category: 'content-structure',
106
106
  description: 'Whether markdown contains unclosed code fences',
107
- dependsOn: [['markdown-url-support', 'content-negotiation']],
107
+ dependsOn: [],
108
108
  run: check,
109
109
  });
110
110
  //# sourceMappingURL=markdown-code-fence-validity.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"markdown-code-fence-validity.js","sourceRoot":"","sources":["../../../src/checks/content-structure/markdown-code-fence-validity.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"markdown-code-fence-validity.js","sourceRoot":"","sources":["../../../src/checks/content-structure/markdown-code-fence-validity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAiB3E;;;;GAIG;AACH,SAAS,qBAAqB,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC;AAC9C,CAAC;AAED,mFAAmF;AACnF,MAAM,QAAQ,GAAG,kCAAkC,CAAC;AAEpD,SAAS,aAAa,CAAC,OAAe;IACpC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,SAAS,GAA0D,IAAI,CAAC;IAE5E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,QAAQ,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtC,IAAI,CAAC,KAAK;YAAE,SAAS;QAErB,wEAAwE;QACxE,sFAAsF;QACtF,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,SAAS;QAErC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QAClC,MAAM,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QAE7C,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,gBAAgB;YAChB,SAAS,GAAG,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;YAC1C,UAAU,EAAE,CAAC;QACf,CAAC;aAAM,CAAC;YACN,uEAAuE;YACvE,0EAA0E;YAC1E,0EAA0E;YAC1E,uDAAuD;YACvD,IAAI,IAAI,KAAK,SAAS,CAAC,IAAI,IAAI,MAAM,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;gBAC1D,SAAS,GAAG,IAAI,CAAC;YACnB,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,SAAS,CAAC,IAAI;YACpB,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;SAChD,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;AAChC,CAAC;AAED,SAAS,WAAW,CAAC,QAAuB;IAC1C,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IAC7C,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IAC7C,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,KAAK,UAAU,KAAK,CAAC,GAAiB;IACpC,MAAM,EAAE,GAAG,8BAA8B,CAAC;IAC1C,MAAM,QAAQ,GAAG,mBAAmB,CAAC;IAErC,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,GAAG,CAAC,CAAC;IAE/C,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,IAAI,QAAQ,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;YACtD,OAAO;gBACL,EAAE;gBACF,QAAQ;gBACR,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,0DAA0D;aACpE,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,GACR,QAAQ,CAAC,IAAI,KAAK,YAAY;YAC5B,CAAC,CAAC,uEAAuE;YACzE,CAAC,CAAC,EAAE,CAAC;QACT,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,4BAA4B,IAAI,EAAE,EAAE,CAAC;IACvF,CAAC;IAED,MAAM,OAAO,GAAsB,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE;QACjF,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QACtD,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;QAE9D,MAAM,MAAM,GAAgB,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;QAE1D,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IAChE,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IACtE,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAE3E,MAAM,OAAO,GACX,aAAa,KAAK,MAAM;QACtB,CAAC,CAAC,OAAO,WAAW,uCAAuC,OAAO,CAAC,MAAM,QAAQ;QACjF,CAAC,CAAC,GAAG,aAAa,sCAAsC,OAAO,CAAC,MAAM,QAAQ,CAAC;IAEnF,OAAO;QACL,EAAE;QACF,QAAQ;QACR,MAAM,EAAE,aAAa;QACrB,OAAO;QACP,OAAO,EAAE;YACP,aAAa,EAAE,OAAO,CAAC,MAAM;YAC7B,WAAW;YACX,aAAa;YACb,WAAW,EAAE,OAAO;SACrB;KACF,CAAC;AACJ,CAAC;AAED,aAAa,CAAC;IACZ,EAAE,EAAE,8BAA8B;IAClC,QAAQ,EAAE,mBAAmB;IAC7B,WAAW,EAAE,gDAAgD;IAC7D,SAAS,EAAE,EAAE;IACb,GAAG,EAAE,KAAK;CACX,CAAC,CAAC"}
@@ -1,17 +1,251 @@
1
+ import { parse } from 'node-html-parser';
1
2
  import { registerCheck } from '../registry.js';
2
- async function check(_ctx) {
3
+ const MD_HEADING_RE = /^#{1,6}\s+(.+)$/gm;
4
+ /**
5
+ * Extract header text from content that may be HTML, markdown, or a mix (MDX).
6
+ * Tries HTML parsing first, then falls back to markdown heading regex.
7
+ */
8
+ function extractHeaders(content) {
9
+ const headers = [];
10
+ // HTML headers
11
+ const root = parse(content);
12
+ const htmlHeaders = root.querySelectorAll('h1, h2, h3, h4, h5, h6');
13
+ for (const h of htmlHeaders) {
14
+ const text = h.textContent.trim();
15
+ if (text.length > 0)
16
+ headers.push(text);
17
+ }
18
+ // Markdown headers (## Heading)
19
+ let match;
20
+ while ((match = MD_HEADING_RE.exec(content)) !== null) {
21
+ const text = match[1].trim();
22
+ if (text.length > 0)
23
+ headers.push(text);
24
+ }
25
+ return headers;
26
+ }
27
+ async function check(ctx) {
28
+ const id = 'section-header-quality';
29
+ const category = 'content-structure';
30
+ const tabResult = ctx.previousResults.get('tabbed-content-serialization');
31
+ if (!tabResult || tabResult.status === 'skip') {
32
+ return {
33
+ id,
34
+ category,
35
+ status: 'skip',
36
+ message: 'Skipped: tabbed-content-serialization did not run',
37
+ };
38
+ }
39
+ const tabbedPages = tabResult.details?.tabbedPages ?? [];
40
+ const pagesWithGroups = tabbedPages.filter((p) => p.tabGroups && p.tabGroups.length > 0);
41
+ if (pagesWithGroups.length === 0) {
42
+ return {
43
+ id,
44
+ category,
45
+ status: 'pass',
46
+ message: 'No tabbed content found; header quality check not applicable',
47
+ };
48
+ }
49
+ const analyses = [];
50
+ // Track unique headers per analysis for cross-group pass
51
+ const analysisHeaderSets = [];
52
+ for (const page of pagesWithGroups) {
53
+ for (const group of page.tabGroups) {
54
+ if (group.panels.length < 2)
55
+ continue;
56
+ // Extract headers from each panel
57
+ const panelHeaders = group.panels.map((panel) => ({
58
+ label: panel.label,
59
+ headers: extractHeaders(panel.html),
60
+ }));
61
+ // Count how many times each header text appears across panels
62
+ const headerCounts = new Map();
63
+ const uniqueHeaders = new Set();
64
+ for (const ph of panelHeaders) {
65
+ for (const h of ph.headers) {
66
+ const lower = h.toLowerCase();
67
+ headerCounts.set(lower, (headerCounts.get(lower) ?? 0) + 1);
68
+ uniqueHeaders.add(lower);
69
+ }
70
+ }
71
+ const allHeaders = panelHeaders.flatMap((ph) => ph.headers);
72
+ let genericCount = 0;
73
+ let contextualCount = 0;
74
+ for (const ph of panelHeaders) {
75
+ for (const h of ph.headers) {
76
+ const lower = h.toLowerCase();
77
+ const appearsInMultiple = (headerCounts.get(lower) ?? 0) >= 2;
78
+ // A header is contextual if it includes the panel label or is unique
79
+ const includesLabel = ph.label != null && lower.includes(ph.label.toLowerCase());
80
+ if (includesLabel || !appearsInMultiple) {
81
+ contextualCount++;
82
+ }
83
+ else {
84
+ genericCount++;
85
+ }
86
+ }
87
+ }
88
+ const totalHeaders = allHeaders.length;
89
+ const hasGenericMajority = totalHeaders > 0 && genericCount > totalHeaders / 2;
90
+ analysisHeaderSets.push(uniqueHeaders);
91
+ analyses.push({
92
+ url: page.url,
93
+ framework: group.framework,
94
+ totalHeaders,
95
+ genericHeaders: genericCount,
96
+ contextualHeaders: contextualCount,
97
+ hasGenericMajority,
98
+ hasCrossGroupGeneric: false,
99
+ });
100
+ }
101
+ }
102
+ // Cross-group analysis: detect identical headers repeated across separate tab groups
103
+ // on the same page without variant context (e.g. "Build a MongoDB Search Query"
104
+ // appearing in 7 driver-specific tab groups).
105
+ let crossGroupGenericGroupCount = 0;
106
+ let crossGroupTotalGroupCount = 0;
107
+ const crossGroupRepeatedHeaders = [];
108
+ for (const page of pagesWithGroups) {
109
+ if (page.tabGroups.length < 2)
110
+ continue;
111
+ // Collect all panel labels and unique headers per group
112
+ const allLabels = new Set();
113
+ const perGroup = [];
114
+ for (const group of page.tabGroups) {
115
+ const headers = new Set();
116
+ for (const panel of group.panels) {
117
+ if (panel.label)
118
+ allLabels.add(panel.label.toLowerCase());
119
+ for (const h of extractHeaders(panel.html))
120
+ headers.add(h.toLowerCase());
121
+ }
122
+ perGroup.push(headers);
123
+ }
124
+ // Count how many groups each header appears in
125
+ const headerGroupCount = new Map();
126
+ for (const hs of perGroup) {
127
+ for (const h of hs)
128
+ headerGroupCount.set(h, (headerGroupCount.get(h) ?? 0) + 1);
129
+ }
130
+ // A header is cross-group generic if it appears in 2+ groups and doesn't
131
+ // include any panel label (i.e. lacks variant context)
132
+ const crossGenericSet = new Set();
133
+ for (const [header, count] of headerGroupCount) {
134
+ if (count >= 2 && ![...allLabels].some((l) => header.includes(l))) {
135
+ crossGenericSet.add(header);
136
+ crossGroupRepeatedHeaders.push({ url: page.url, header, groupCount: count });
137
+ }
138
+ }
139
+ // Count groups affected by cross-group generic headers
140
+ for (const hs of perGroup) {
141
+ if (hs.size === 0)
142
+ continue;
143
+ crossGroupTotalGroupCount++;
144
+ if ([...hs].some((h) => crossGenericSet.has(h)))
145
+ crossGroupGenericGroupCount++;
146
+ }
147
+ // Update individual analyses with cross-group flag
148
+ if (crossGenericSet.size > 0) {
149
+ for (let i = 0; i < analyses.length; i++) {
150
+ if (analyses[i].url !== page.url)
151
+ continue;
152
+ if ([...analysisHeaderSets[i]].some((h) => crossGenericSet.has(h))) {
153
+ analyses[i].hasCrossGroupGeneric = true;
154
+ }
155
+ }
156
+ }
157
+ }
158
+ if (analyses.length === 0 && crossGroupTotalGroupCount === 0) {
159
+ return {
160
+ id,
161
+ category,
162
+ status: 'pass',
163
+ message: 'Tab groups have fewer than 2 panels; header quality check not applicable',
164
+ };
165
+ }
166
+ const groupsWithGenericMajority = analyses.filter((a) => a.hasGenericMajority).length;
167
+ const groupsWithHeaders = analyses.filter((a) => a.totalHeaders > 0).length;
168
+ // If no tab panels contain any section headers, we can't evaluate quality
169
+ if (groupsWithHeaders === 0 && crossGroupTotalGroupCount === 0) {
170
+ return {
171
+ id,
172
+ category,
173
+ status: 'skip',
174
+ message: `${pagesWithGroups.length} page(s) with tabs found, but no section headers inside tab panels to evaluate`,
175
+ };
176
+ }
177
+ // Identify affected pages: pages where any group has within-group or cross-group issues
178
+ const pagesWithWithinGroupIssues = new Set(analyses.filter((a) => a.hasGenericMajority).map((a) => a.url));
179
+ const pagesWithCrossGroupIssues = new Set(crossGroupRepeatedHeaders.map((h) => h.url));
180
+ const affectedPages = new Set([...pagesWithWithinGroupIssues, ...pagesWithCrossGroupIssues]);
181
+ // Count pages where we actually found headers to evaluate
182
+ const pagesWithHeaders = new Set(analyses.filter((a) => a.totalHeaders > 0).map((a) => a.url));
183
+ // Scoring: use group-level ratios for fine-grained thresholds
184
+ // Within-group: ratio of groups-with-headers that have majority-generic
185
+ let withinStatus = 'pass';
186
+ if (groupsWithHeaders > 0) {
187
+ const wRatio = groupsWithGenericMajority / groupsWithHeaders;
188
+ if (wRatio > 0.5)
189
+ withinStatus = 'fail';
190
+ else if (wRatio > 0.25)
191
+ withinStatus = 'warn';
192
+ }
193
+ // Cross-group: ratio of groups on multi-group pages that have cross-group generics
194
+ let crossGroupStatus = 'pass';
195
+ if (crossGroupTotalGroupCount > 0) {
196
+ const cRatio = crossGroupGenericGroupCount / crossGroupTotalGroupCount;
197
+ if (cRatio > 0.5)
198
+ crossGroupStatus = 'fail';
199
+ else if (cRatio > 0.25)
200
+ crossGroupStatus = 'warn';
201
+ }
202
+ // Combined status: worst of both
203
+ const statusRank = { pass: 0, skip: 0, warn: 1, fail: 2, error: 2 };
204
+ const status = statusRank[crossGroupStatus] > statusRank[withinStatus] ? crossGroupStatus : withinStatus;
205
+ // Build a page-oriented message for docs teams
206
+ let message;
207
+ if (affectedPages.size === 0) {
208
+ message = `${pagesWithHeaders.size} page(s) with tab headers checked; headers include variant context`;
209
+ }
210
+ else {
211
+ // Find the most-repeated cross-group header for a concrete example
212
+ const worstHeader = crossGroupRepeatedHeaders.length > 0
213
+ ? [...crossGroupRepeatedHeaders].sort((a, b) => b.groupCount - a.groupCount)[0]
214
+ : null;
215
+ const pageSummary = `${affectedPages.size} of ${pagesWithHeaders.size} page(s) with tab headers ` +
216
+ `don't distinguish between variants`;
217
+ if (worstHeader) {
218
+ message = `${pageSummary} (e.g. "${worstHeader.header}" repeats across ${worstHeader.groupCount} tab groups)`;
219
+ }
220
+ else {
221
+ message = pageSummary;
222
+ }
223
+ }
3
224
  return {
4
- id: 'section-header-quality',
5
- category: 'content-structure',
6
- status: 'skip',
7
- message: 'Not yet implemented',
225
+ id,
226
+ category,
227
+ status,
228
+ message,
229
+ details: {
230
+ pagesWithTabs: pagesWithGroups.length,
231
+ pagesAffected: affectedPages.size,
232
+ totalGroupsAnalyzed: analyses.length,
233
+ groupsWithHeaders,
234
+ groupsWithGenericMajority,
235
+ crossGroupGenericGroupCount,
236
+ crossGroupTotalGroupCount,
237
+ crossGroupRepeatedHeaders,
238
+ analyses,
239
+ },
8
240
  };
9
241
  }
10
242
  registerCheck({
11
243
  id: 'section-header-quality',
12
244
  category: 'content-structure',
13
245
  description: 'Whether headers in tabbed sections include variant context',
14
- dependsOn: ['tabbed-content-serialization'],
246
+ // No hard dependency: we read from previousResults if available,
247
+ // but the check handles missing data gracefully (returns skip).
248
+ dependsOn: [],
15
249
  run: check,
16
250
  });
17
251
  //# sourceMappingURL=section-header-quality.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"section-header-quality.js","sourceRoot":"","sources":["../../../src/checks/content-structure/section-header-quality.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAG/C,KAAK,UAAU,KAAK,CAAC,IAAkB;IACrC,OAAO;QACL,EAAE,EAAE,wBAAwB;QAC5B,QAAQ,EAAE,mBAAmB;QAC7B,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,qBAAqB;KAC/B,CAAC;AACJ,CAAC;AAED,aAAa,CAAC;IACZ,EAAE,EAAE,wBAAwB;IAC5B,QAAQ,EAAE,mBAAmB;IAC7B,WAAW,EAAE,4DAA4D;IACzE,SAAS,EAAE,CAAC,8BAA8B,CAAC;IAC3C,GAAG,EAAE,KAAK;CACX,CAAC,CAAC"}
1
+ {"version":3,"file":"section-header-quality.js","sourceRoot":"","sources":["../../../src/checks/content-structure/section-header-quality.ts"],"names":[],"mappings":"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"}