ax-audit 4.2.1 → 6.0.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 (188) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +39 -4
  3. package/dist/baseline.js +1 -1
  4. package/dist/baseline.js.map +1 -1
  5. package/dist/check-ids.js +1 -1
  6. package/dist/check-ids.js.map +1 -1
  7. package/dist/cli.js +1 -1
  8. package/dist/cli.js.map +1 -1
  9. package/dist/constants.d.ts +1 -85
  10. package/dist/constants.d.ts.map +1 -1
  11. package/dist/constants.js +0 -135
  12. package/dist/constants.js.map +1 -1
  13. package/dist/index.d.ts +3 -1
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +2 -1
  16. package/dist/index.js.map +1 -1
  17. package/dist/license.d.ts +8 -0
  18. package/dist/license.d.ts.map +1 -0
  19. package/dist/license.js +18 -0
  20. package/dist/license.js.map +1 -0
  21. package/dist/metadata.d.ts +6 -0
  22. package/dist/metadata.d.ts.map +1 -0
  23. package/dist/metadata.js +205 -0
  24. package/dist/metadata.js.map +1 -0
  25. package/dist/orchestrator.d.ts +1 -0
  26. package/dist/orchestrator.d.ts.map +1 -1
  27. package/dist/orchestrator.js +134 -56
  28. package/dist/orchestrator.js.map +1 -1
  29. package/dist/scorer.js +2 -2
  30. package/dist/scorer.js.map +1 -1
  31. package/dist/types.d.ts +4 -0
  32. package/dist/types.d.ts.map +1 -1
  33. package/docs/api.md +14 -3
  34. package/docs/architecture.md +9 -98
  35. package/docs/ci.md +19 -0
  36. package/docs/cli.md +11 -0
  37. package/docs/faq.md +18 -0
  38. package/docs/getting-started.md +33 -1
  39. package/package.json +5 -5
  40. package/dist/checks/agent-access.d.ts +0 -33
  41. package/dist/checks/agent-access.d.ts.map +0 -1
  42. package/dist/checks/agent-access.js +0 -256
  43. package/dist/checks/agent-access.js.map +0 -1
  44. package/dist/checks/agent-card.d.ts +0 -37
  45. package/dist/checks/agent-card.d.ts.map +0 -1
  46. package/dist/checks/agent-card.js +0 -352
  47. package/dist/checks/agent-card.js.map +0 -1
  48. package/dist/checks/agent-operability.d.ts +0 -66
  49. package/dist/checks/agent-operability.d.ts.map +0 -1
  50. package/dist/checks/agent-operability.js +0 -383
  51. package/dist/checks/agent-operability.js.map +0 -1
  52. package/dist/checks/agent-skills.d.ts +0 -24
  53. package/dist/checks/agent-skills.d.ts.map +0 -1
  54. package/dist/checks/agent-skills.js +0 -316
  55. package/dist/checks/agent-skills.js.map +0 -1
  56. package/dist/checks/ai-catalog.d.ts +0 -28
  57. package/dist/checks/ai-catalog.d.ts.map +0 -1
  58. package/dist/checks/ai-catalog.js +0 -254
  59. package/dist/checks/ai-catalog.js.map +0 -1
  60. package/dist/checks/ai-directives.d.ts +0 -57
  61. package/dist/checks/ai-directives.d.ts.map +0 -1
  62. package/dist/checks/ai-directives.js +0 -263
  63. package/dist/checks/ai-directives.js.map +0 -1
  64. package/dist/checks/api-discovery.d.ts +0 -26
  65. package/dist/checks/api-discovery.d.ts.map +0 -1
  66. package/dist/checks/api-discovery.js +0 -432
  67. package/dist/checks/api-discovery.js.map +0 -1
  68. package/dist/checks/auth-discovery.d.ts +0 -28
  69. package/dist/checks/auth-discovery.d.ts.map +0 -1
  70. package/dist/checks/auth-discovery.js +0 -302
  71. package/dist/checks/auth-discovery.js.map +0 -1
  72. package/dist/checks/commerce-discovery.d.ts +0 -40
  73. package/dist/checks/commerce-discovery.d.ts.map +0 -1
  74. package/dist/checks/commerce-discovery.js +0 -295
  75. package/dist/checks/commerce-discovery.js.map +0 -1
  76. package/dist/checks/content-negotiation.d.ts +0 -4
  77. package/dist/checks/content-negotiation.d.ts.map +0 -1
  78. package/dist/checks/content-negotiation.js +0 -253
  79. package/dist/checks/content-negotiation.js.map +0 -1
  80. package/dist/checks/crawl-efficiency.d.ts +0 -16
  81. package/dist/checks/crawl-efficiency.d.ts.map +0 -1
  82. package/dist/checks/crawl-efficiency.js +0 -186
  83. package/dist/checks/crawl-efficiency.js.map +0 -1
  84. package/dist/checks/frontmatter.d.ts +0 -34
  85. package/dist/checks/frontmatter.d.ts.map +0 -1
  86. package/dist/checks/frontmatter.js +0 -100
  87. package/dist/checks/frontmatter.js.map +0 -1
  88. package/dist/checks/html-rendering.d.ts +0 -21
  89. package/dist/checks/html-rendering.d.ts.map +0 -1
  90. package/dist/checks/html-rendering.js +0 -221
  91. package/dist/checks/html-rendering.js.map +0 -1
  92. package/dist/checks/html-utils.d.ts +0 -66
  93. package/dist/checks/html-utils.d.ts.map +0 -1
  94. package/dist/checks/html-utils.js +0 -139
  95. package/dist/checks/html-utils.js.map +0 -1
  96. package/dist/checks/http-headers.d.ts +0 -11
  97. package/dist/checks/http-headers.d.ts.map +0 -1
  98. package/dist/checks/http-headers.js +0 -249
  99. package/dist/checks/http-headers.js.map +0 -1
  100. package/dist/checks/http-hygiene.d.ts +0 -26
  101. package/dist/checks/http-hygiene.d.ts.map +0 -1
  102. package/dist/checks/http-hygiene.js +0 -257
  103. package/dist/checks/http-hygiene.js.map +0 -1
  104. package/dist/checks/index.d.ts +0 -3
  105. package/dist/checks/index.d.ts.map +0 -1
  106. package/dist/checks/index.js +0 -55
  107. package/dist/checks/index.js.map +0 -1
  108. package/dist/checks/llms-txt.d.ts +0 -19
  109. package/dist/checks/llms-txt.d.ts.map +0 -1
  110. package/dist/checks/llms-txt.js +0 -281
  111. package/dist/checks/llms-txt.js.map +0 -1
  112. package/dist/checks/mcp-discovery.d.ts +0 -30
  113. package/dist/checks/mcp-discovery.d.ts.map +0 -1
  114. package/dist/checks/mcp-discovery.js +0 -523
  115. package/dist/checks/mcp-discovery.js.map +0 -1
  116. package/dist/checks/meta-tags.d.ts +0 -17
  117. package/dist/checks/meta-tags.d.ts.map +0 -1
  118. package/dist/checks/meta-tags.js +0 -188
  119. package/dist/checks/meta-tags.js.map +0 -1
  120. package/dist/checks/robots-parser.d.ts +0 -110
  121. package/dist/checks/robots-parser.d.ts.map +0 -1
  122. package/dist/checks/robots-parser.js +0 -277
  123. package/dist/checks/robots-parser.js.map +0 -1
  124. package/dist/checks/robots-txt.d.ts +0 -6
  125. package/dist/checks/robots-txt.d.ts.map +0 -1
  126. package/dist/checks/robots-txt.js +0 -367
  127. package/dist/checks/robots-txt.js.map +0 -1
  128. package/dist/checks/rsl.d.ts +0 -4
  129. package/dist/checks/rsl.d.ts.map +0 -1
  130. package/dist/checks/rsl.js +0 -242
  131. package/dist/checks/rsl.js.map +0 -1
  132. package/dist/checks/security-txt.d.ts +0 -4
  133. package/dist/checks/security-txt.d.ts.map +0 -1
  134. package/dist/checks/security-txt.js +0 -81
  135. package/dist/checks/security-txt.js.map +0 -1
  136. package/dist/checks/seo-basics.d.ts +0 -13
  137. package/dist/checks/seo-basics.d.ts.map +0 -1
  138. package/dist/checks/seo-basics.js +0 -221
  139. package/dist/checks/seo-basics.js.map +0 -1
  140. package/dist/checks/sitemap.d.ts +0 -12
  141. package/dist/checks/sitemap.d.ts.map +0 -1
  142. package/dist/checks/sitemap.js +0 -240
  143. package/dist/checks/sitemap.js.map +0 -1
  144. package/dist/checks/structured-data.d.ts +0 -4
  145. package/dist/checks/structured-data.d.ts.map +0 -1
  146. package/dist/checks/structured-data.js +0 -408
  147. package/dist/checks/structured-data.js.map +0 -1
  148. package/dist/checks/structured-fields.d.ts +0 -46
  149. package/dist/checks/structured-fields.d.ts.map +0 -1
  150. package/dist/checks/structured-fields.js +0 -112
  151. package/dist/checks/structured-fields.js.map +0 -1
  152. package/dist/checks/surface.d.ts +0 -59
  153. package/dist/checks/surface.d.ts.map +0 -1
  154. package/dist/checks/surface.js +0 -106
  155. package/dist/checks/surface.js.map +0 -1
  156. package/dist/checks/tls-https.d.ts +0 -13
  157. package/dist/checks/tls-https.d.ts.map +0 -1
  158. package/dist/checks/tls-https.js +0 -163
  159. package/dist/checks/tls-https.js.map +0 -1
  160. package/dist/checks/usage-policy.d.ts +0 -53
  161. package/dist/checks/usage-policy.d.ts.map +0 -1
  162. package/dist/checks/usage-policy.js +0 -339
  163. package/dist/checks/usage-policy.js.map +0 -1
  164. package/dist/checks/utils.d.ts +0 -40
  165. package/dist/checks/utils.d.ts.map +0 -1
  166. package/dist/checks/utils.js +0 -74
  167. package/dist/checks/utils.js.map +0 -1
  168. package/dist/checks/waf.d.ts +0 -75
  169. package/dist/checks/waf.d.ts.map +0 -1
  170. package/dist/checks/waf.js +0 -203
  171. package/dist/checks/waf.js.map +0 -1
  172. package/dist/checks/webmcp.d.ts +0 -55
  173. package/dist/checks/webmcp.d.ts.map +0 -1
  174. package/dist/checks/webmcp.js +0 -209
  175. package/dist/checks/webmcp.js.map +0 -1
  176. package/dist/checks/well-known.d.ts +0 -38
  177. package/dist/checks/well-known.d.ts.map +0 -1
  178. package/dist/checks/well-known.js +0 -202
  179. package/dist/checks/well-known.js.map +0 -1
  180. package/dist/fetcher.d.ts +0 -15
  181. package/dist/fetcher.d.ts.map +0 -1
  182. package/dist/fetcher.js +0 -127
  183. package/dist/fetcher.js.map +0 -1
  184. package/dist/guide-urls.d.ts +0 -2
  185. package/dist/guide-urls.d.ts.map +0 -1
  186. package/dist/guide-urls.js +0 -5
  187. package/dist/guide-urls.js.map +0 -1
  188. package/docs/roadmap.md +0 -367
@@ -1,100 +0,0 @@
1
- /**
2
- * Minimal YAML frontmatter reader.
3
- *
4
- * ax-audit has two runtime dependencies and will not grow a YAML parser for
5
- * this. The documents it reads frontmatter from — SKILL.md, the Markdown
6
- * mirrors Vercel and Mintlify serve — use a flat `key: value` block by
7
- * convention, so a focused reader handles them exactly and reports anything
8
- * more elaborate as unparsed rather than guessing at it.
9
- *
10
- * Supported: `key: value`, single- and double-quoted values, `#` comments on
11
- * their own line or after a value, and inline flow sequences (`tags: [a, b]`).
12
- * Nested mappings and block sequences are recognised and skipped, with their
13
- * keys recorded in `skipped` so a caller can say what it could not read.
14
- */
15
- /** Strip matching surrounding quotes and unescape the pairs YAML defines inside them. */
16
- function unquote(value) {
17
- const trimmed = value.trim();
18
- if (trimmed.length >= 2 && trimmed.startsWith('"') && trimmed.endsWith('"')) {
19
- return trimmed.slice(1, -1).replace(/\\(["\\n])/g, (_, c) => (c === 'n' ? '\n' : c));
20
- }
21
- if (trimmed.length >= 2 && trimmed.startsWith("'") && trimmed.endsWith("'")) {
22
- return trimmed.slice(1, -1).replace(/''/g, "'");
23
- }
24
- return trimmed;
25
- }
26
- /** Remove a trailing `#` comment from an unquoted value. */
27
- function stripComment(value) {
28
- const trimmed = value.trim();
29
- if (trimmed.startsWith('"') || trimmed.startsWith("'"))
30
- return trimmed;
31
- const hash = trimmed.search(/\s#/);
32
- return hash === -1 ? trimmed : trimmed.slice(0, hash).trim();
33
- }
34
- /**
35
- * Parse a leading `---` delimited frontmatter block.
36
- *
37
- * A document with no block returns `present: false` and its whole text as the
38
- * body, so callers can distinguish "no frontmatter" from "empty frontmatter".
39
- */
40
- export function parseFrontmatter(document) {
41
- const empty = { frontmatter: {}, lists: {}, skipped: [], body: document, present: false };
42
- // Tolerate a BOM and leading blank lines before the opening delimiter.
43
- const text = document.replace(/^\uFEFF/, '');
44
- const opening = text.match(/^\s*---[ \t]*\r?\n/);
45
- if (!opening)
46
- return empty;
47
- const rest = text.slice(opening[0].length);
48
- const closing = rest.match(/^---[ \t]*(?:\r?\n|$)/m);
49
- if (!closing || closing.index === undefined)
50
- return empty;
51
- const block = rest.slice(0, closing.index);
52
- const body = rest.slice(closing.index + closing[0].length);
53
- const frontmatter = {};
54
- const lists = {};
55
- const skipped = [];
56
- const lines = block.split(/\r?\n/);
57
- for (let i = 0; i < lines.length; i++) {
58
- const line = lines[i];
59
- if (line.trim() === '' || line.trim().startsWith('#'))
60
- continue;
61
- // Indented lines belong to a structure the previous key opened.
62
- if (/^\s/.test(line))
63
- continue;
64
- const match = line.match(/^([A-Za-z0-9_.-]+)\s*:\s*(.*)$/);
65
- if (!match)
66
- continue;
67
- const key = match[1].toLowerCase();
68
- const raw = match[2];
69
- if (raw.trim() === '') {
70
- // A key with no inline value opens a nested mapping or block sequence.
71
- const next = lines[i + 1] ?? '';
72
- if (/^\s*-\s+/.test(next)) {
73
- const items = [];
74
- for (let j = i + 1; j < lines.length && /^\s*-\s+/.test(lines[j]); j++) {
75
- items.push(unquote(stripComment(lines[j].replace(/^\s*-\s+/, ''))));
76
- }
77
- lists[key] = items;
78
- }
79
- else if (/^\s+\S/.test(next)) {
80
- skipped.push(key);
81
- }
82
- else {
83
- frontmatter[key] = '';
84
- }
85
- continue;
86
- }
87
- const value = stripComment(raw);
88
- const flow = value.match(/^\[(.*)\]$/);
89
- if (flow) {
90
- lists[key] = flow[1]
91
- .split(',')
92
- .map((v) => unquote(v))
93
- .filter((v) => v !== '');
94
- continue;
95
- }
96
- frontmatter[key] = unquote(value);
97
- }
98
- return { frontmatter, lists, skipped, body, present: true };
99
- }
100
- //# sourceMappingURL=frontmatter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../../src/checks/frontmatter.ts"],"names":[],"mappings":"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"}
@@ -1,21 +0,0 @@
1
- import type { CheckContext, CheckResult, CheckMeta } from '../types.js';
2
- /**
3
- * "html-rendering" — does the HTML delivered to a non-JS agent actually contain content?
4
- *
5
- * Most AI crawlers (GPTBot, ClaudeBot, CCBot, etc.) do **not** execute JavaScript. A site
6
- * built as a client-rendered SPA returns an empty `<div id="root"></div>` shell to those
7
- * agents, and is effectively invisible regardless of how good its `llms.txt` and structured
8
- * data are. This check estimates server-side rendering by inspecting the static HTML body.
9
- *
10
- * Signals (each contributes to the score):
11
- * - Visible text length and word count (low → likely JS-rendered shell)
12
- * - Text-to-markup ratio against structural markup (high JS, no text → SPA)
13
- * - Presence of semantic landmarks (`<main>`, `<article>`, `<header>`, `<footer>`, `<nav>`)
14
- * - Single, meaningful `<h1>`
15
- * - `<noscript>` fallback for JS-only frameworks
16
- * - Non-empty SPA root containers (`#root`, `#app`, `#__next`)
17
- * - Image `alt` attribute coverage
18
- */
19
- export declare const meta: CheckMeta;
20
- export default function check(ctx: CheckContext): Promise<CheckResult>;
21
- //# sourceMappingURL=html-rendering.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"html-rendering.d.ts","sourceRoot":"","sources":["../../src/checks/html-rendering.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAW,MAAM,aAAa,CAAC;AAUjF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,IAAI,EAAE,SAIlB,CAAC;AAOF,wBAA8B,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CA6L3E"}
@@ -1,221 +0,0 @@
1
- import { guideUrl } from '../guide-urls.js';
2
- import { countExecutableScripts, extractVisibleText, findOpeningTag, getMetaContent, structuralMarkupLength, } from './html-utils.js';
3
- import { buildResult } from './utils.js';
4
- /**
5
- * "html-rendering" — does the HTML delivered to a non-JS agent actually contain content?
6
- *
7
- * Most AI crawlers (GPTBot, ClaudeBot, CCBot, etc.) do **not** execute JavaScript. A site
8
- * built as a client-rendered SPA returns an empty `<div id="root"></div>` shell to those
9
- * agents, and is effectively invisible regardless of how good its `llms.txt` and structured
10
- * data are. This check estimates server-side rendering by inspecting the static HTML body.
11
- *
12
- * Signals (each contributes to the score):
13
- * - Visible text length and word count (low → likely JS-rendered shell)
14
- * - Text-to-markup ratio against structural markup (high JS, no text → SPA)
15
- * - Presence of semantic landmarks (`<main>`, `<article>`, `<header>`, `<footer>`, `<nav>`)
16
- * - Single, meaningful `<h1>`
17
- * - `<noscript>` fallback for JS-only frameworks
18
- * - Non-empty SPA root containers (`#root`, `#app`, `#__next`)
19
- * - Image `alt` attribute coverage
20
- */
21
- export const meta = {
22
- id: 'html-rendering',
23
- name: 'HTML Rendering',
24
- description: 'Checks server-rendered content, semantic landmarks, and SPA-shell heuristics',
25
- };
26
- const MIN_TEXT_LENGTH = 500;
27
- const MIN_WORD_COUNT = 80;
28
- const MIN_TEXT_TO_HTML_RATIO = 0.05;
29
- const SPA_ROOT_IDS = ['root', 'app', '__next', '__nuxt', 'svelte', 'gatsby', 'gatsby-focus-wrapper'];
30
- export default async function check(ctx) {
31
- const start = performance.now();
32
- const findings = [];
33
- let score = 100;
34
- const html = ctx.html;
35
- if (!html) {
36
- findings.push({
37
- status: 'fail',
38
- message: 'Could not fetch homepage HTML',
39
- hint: 'The homepage did not return any HTML body. Verify your server returns 200 OK with a non-empty response on the root URL.',
40
- learnMoreUrl: guideUrl(meta.id, 'no-html'),
41
- });
42
- return buildResult(meta, 0, findings, start);
43
- }
44
- const visibleText = extractVisibleText(html);
45
- const wordCount = visibleText ? visibleText.split(/\s+/).filter(Boolean).length : 0;
46
- const textOk = visibleText.length >= MIN_TEXT_LENGTH && wordCount >= MIN_WORD_COUNT;
47
- // Against the markup that could have carried text — script and style
48
- // bodies, svg interiors and the head excluded (see structuralMarkupLength).
49
- const markup = structuralMarkupLength(html);
50
- const ratio = markup > 0 ? visibleText.length / markup : 0;
51
- if (textOk) {
52
- findings.push({
53
- status: 'pass',
54
- message: `Server-rendered content detected (${wordCount} words, ${visibleText.length} chars of visible text)`,
55
- });
56
- }
57
- else if (visibleText.length > 0) {
58
- findings.push({
59
- status: 'warn',
60
- message: `Sparse server-rendered content (${wordCount} words, ${visibleText.length} chars)`,
61
- detail: `Below thresholds: ${MIN_WORD_COUNT} words, ${MIN_TEXT_LENGTH} chars`,
62
- hint: 'Render at least the main page content server-side. Many AI crawlers (GPTBot, ClaudeBot, CCBot) do not execute JavaScript and will see only the static HTML.',
63
- learnMoreUrl: guideUrl(meta.id, 'sparse-content'),
64
- });
65
- score -= 25;
66
- }
67
- else {
68
- findings.push({
69
- status: 'fail',
70
- message: 'No visible text content in static HTML',
71
- hint: 'Your homepage appears to be a JavaScript-only shell. Add server-side rendering (Next.js SSR/SSG, Astro, Remix, or a static prerender) so AI agents that do not execute JS can read your content.',
72
- learnMoreUrl: guideUrl(meta.id, 'js-shell'),
73
- });
74
- score -= 50;
75
- }
76
- if (ratio >= MIN_TEXT_TO_HTML_RATIO) {
77
- findings.push({
78
- status: 'pass',
79
- message: `Text-to-markup ratio is healthy (${(ratio * 100).toFixed(1)}% of structural markup)`,
80
- });
81
- }
82
- else if (textOk) {
83
- // The ratio exists as a shell symptom, and the text thresholds just
84
- // proved this page is not a shell: the words are demonstrably there.
85
- // What a low ratio still says is that the structure around them is
86
- // expensive for an agent consuming raw HTML — worth saying, not
87
- // worth charging for twice.
88
- findings.push({
89
- status: 'warn',
90
- message: `Markup-heavy page (text is ${(ratio * 100).toFixed(1)}% of structural markup)`,
91
- detail: `Recommended minimum: ${(MIN_TEXT_TO_HTML_RATIO * 100).toFixed(0)}%. The content thresholds are met, so this does not move the score.`,
92
- hint: 'The visible text clears the content thresholds, so agents can read this page. Trimming wrapper markup would still make it cheaper to consume.',
93
- learnMoreUrl: guideUrl(meta.id, 'low-ratio'),
94
- });
95
- }
96
- else {
97
- findings.push({
98
- status: 'warn',
99
- message: `Low text-to-markup ratio (${(ratio * 100).toFixed(1)}%)`,
100
- detail: `Recommended minimum: ${(MIN_TEXT_TO_HTML_RATIO * 100).toFixed(0)}% of structural markup (script/style bodies and svg interiors excluded)`,
101
- hint: 'A very low text-to-markup ratio is a typical SPA-shell symptom. Inline more content directly into the HTML response.',
102
- learnMoreUrl: guideUrl(meta.id, 'low-ratio'),
103
- });
104
- score -= 10;
105
- }
106
- const emptyShell = SPA_ROOT_IDS.find((id) => {
107
- const re = new RegExp(`<[^>]+\\bid\\s*=\\s*["']${id}["'][^>]*>\\s*</[^>]+>`, 'i');
108
- return re.test(html);
109
- });
110
- if (emptyShell) {
111
- findings.push({
112
- status: 'fail',
113
- message: `Empty SPA mount point detected: #${emptyShell}`,
114
- hint: 'The static HTML contains an empty SPA mount node, which means content is rendered only client-side. Enable SSR/SSG so the initial HTML response includes meaningful content.',
115
- learnMoreUrl: guideUrl(meta.id, 'empty-spa'),
116
- });
117
- score -= 20;
118
- }
119
- const semanticLandmarks = ['main', 'article', 'section', 'header', 'footer', 'nav'];
120
- const presentLandmarks = semanticLandmarks.filter((tag) => findOpeningTag(html, tag) !== null);
121
- if (presentLandmarks.length >= 3) {
122
- findings.push({
123
- status: 'pass',
124
- message: `Semantic landmarks present (${presentLandmarks.join(', ')})`,
125
- });
126
- }
127
- else if (presentLandmarks.length > 0) {
128
- findings.push({
129
- status: 'warn',
130
- message: `Only ${presentLandmarks.length} semantic landmark(s) found`,
131
- detail: `Found: ${presentLandmarks.join(', ')}. Missing: ${semanticLandmarks.filter((t) => !presentLandmarks.includes(t)).join(', ')}`,
132
- hint: 'Use semantic HTML tags so AI agents can understand page structure: <header>, <nav>, <main>, <article>, <section>, <footer>.',
133
- learnMoreUrl: guideUrl(meta.id, 'few-landmarks'),
134
- });
135
- score -= 10;
136
- }
137
- else {
138
- findings.push({
139
- status: 'warn',
140
- message: 'No semantic HTML landmarks found',
141
- hint: 'Replace generic <div> structures with semantic tags: <main>, <article>, <header>, <nav>, <footer>. Agents use these to identify the primary content region.',
142
- learnMoreUrl: guideUrl(meta.id, 'no-landmarks'),
143
- });
144
- score -= 15;
145
- }
146
- const h1Matches = [...html.matchAll(/<h1\b[^>]*>([\s\S]*?)<\/h1>/gi)];
147
- if (h1Matches.length === 1) {
148
- const h1Text = extractVisibleText(h1Matches[0][1]);
149
- if (h1Text.length > 0) {
150
- findings.push({ status: 'pass', message: `Single <h1> heading: "${truncate(h1Text, 60)}"` });
151
- }
152
- else {
153
- findings.push({
154
- status: 'warn',
155
- message: '<h1> is empty',
156
- hint: 'Add meaningful text inside your <h1> element so agents can identify the page topic.',
157
- learnMoreUrl: guideUrl(meta.id, 'empty-h1'),
158
- });
159
- score -= 5;
160
- }
161
- }
162
- else if (h1Matches.length > 1) {
163
- findings.push({
164
- status: 'warn',
165
- message: `${h1Matches.length} <h1> headings found (recommend exactly 1)`,
166
- hint: 'Use a single <h1> per page to clearly mark the primary topic. Demote secondary headings to <h2>+.',
167
- learnMoreUrl: guideUrl(meta.id, 'multiple-h1'),
168
- });
169
- score -= 5;
170
- }
171
- else {
172
- findings.push({
173
- status: 'warn',
174
- message: 'No <h1> heading found',
175
- hint: 'Add a single <h1> describing the page. Agents and search engines treat the H1 as the primary topic indicator.',
176
- learnMoreUrl: guideUrl(meta.id, 'no-h1'),
177
- });
178
- score -= 10;
179
- }
180
- const heavyJs = countExecutableScripts(html) > 15;
181
- const hasNoscript = /<noscript\b[^>]*>[\s\S]*?<\/noscript>/i.test(html);
182
- if (heavyJs && !hasNoscript) {
183
- findings.push({
184
- status: 'warn',
185
- message: 'Heavy JavaScript with no <noscript> fallback',
186
- detail: `${countExecutableScripts(html)} executable <script> tags`,
187
- hint: 'Provide a <noscript> fallback that explains the site or links to a non-JS variant. This helps agents that disable JS.',
188
- learnMoreUrl: guideUrl(meta.id, 'no-noscript'),
189
- });
190
- score -= 5;
191
- }
192
- const imgs = [...html.matchAll(/<img\b([^>]*)>/gi)];
193
- if (imgs.length > 0) {
194
- const withAlt = imgs.filter((m) => /\balt\s*=/i.test(m[1])).length;
195
- const coverage = withAlt / imgs.length;
196
- if (coverage >= 0.9) {
197
- findings.push({
198
- status: 'pass',
199
- message: `${withAlt}/${imgs.length} <img> tags have alt attributes`,
200
- });
201
- }
202
- else {
203
- findings.push({
204
- status: 'warn',
205
- message: `Only ${withAlt}/${imgs.length} <img> tags have alt attributes`,
206
- hint: 'Add descriptive alt="" to every <img>. Agents use alt text to understand images they cannot process visually.',
207
- learnMoreUrl: guideUrl(meta.id, 'missing-alt'),
208
- });
209
- score -= 5;
210
- }
211
- }
212
- const generator = getMetaContent(html, 'generator');
213
- if (generator) {
214
- findings.push({ status: 'pass', message: `Generator: ${generator}` });
215
- }
216
- return buildResult(meta, score, findings, start);
217
- }
218
- function truncate(value, max) {
219
- return value.length > max ? `${value.slice(0, max - 1)}…` : value;
220
- }
221
- //# sourceMappingURL=html-rendering.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"html-rendering.js","sourceRoot":"","sources":["../../src/checks/html-rendering.ts"],"names":[],"mappings":"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"}
@@ -1,66 +0,0 @@
1
- /**
2
- * Shared HTML parsing primitives used by checks that need to inspect homepage markup.
3
- *
4
- * These are deliberately regex-based (no DOM dependency) so the audit stays free of
5
- * heavyweight HTML parsers. They are designed for resilience over completeness — every
6
- * helper returns `null` / empty values on malformed input rather than throwing.
7
- */
8
- /** Escape a string for safe inclusion inside a `RegExp` source. */
9
- export declare function escapeRegex(value: string): string;
10
- /** Decode the small set of HTML entities that show up most often inside attribute values. */
11
- export declare function unescapeHtml(value: string): string;
12
- /**
13
- * Match the first opening tag (`<tag ...>`) and return its raw attribute string.
14
- * Returns `null` if the tag is absent.
15
- */
16
- export declare function findOpeningTag(html: string, tagName: string): string | null;
17
- /** Pull a single attribute out of a raw attribute fragment (the `...` in `<tag ...>`). */
18
- export declare function getAttribute(attrFragment: string, attrName: string): string | null;
19
- /** Convenience: read an attribute from the first matching opening tag. */
20
- export declare function getTagAttribute(html: string, tagName: string, attrName: string): string | null;
21
- /**
22
- * Extract the `content` value of the first `<meta name="..."|property="..."|http-equiv="...">`
23
- * matching `key`. Searches `name`, `property`, and `http-equiv` (case-insensitive).
24
- */
25
- export declare function getMetaContent(html: string, key: string): string | null;
26
- /** Match every `<meta>` tag whose name/property begins with `prefix` (e.g. `og:`, `twitter:`). */
27
- export declare function findMetaTagsByPrefix(html: string, prefix: string): string[];
28
- /** Match every `<link rel="...">` tag with the requested `rel` value. */
29
- export declare function findLinkTags(html: string, rel: string): string[];
30
- /**
31
- * Strip `<script>` / `<style>` blocks and HTML tags to produce a rough text-content estimate.
32
- * Returns the trimmed plain text — used for content-density / SSR heuristics.
33
- */
34
- export declare function extractVisibleText(html: string): string;
35
- /**
36
- * Extract the contents of every `<script type="application/ld+json">` block.
37
- *
38
- * Attribute order matters here, and it is easy to get wrong: a pattern anchored
39
- * on `<script type=...` misses `<script id="org-json-ld" type="application/ld+json">`,
40
- * which is how several frameworks emit it. That mistake reads as "no structured
41
- * data found" on a site whose markup is perfectly good, so the matcher tolerates
42
- * any attributes before `type`.
43
- */
44
- export declare function findJsonLdBlocks(html: string): string[];
45
- /** Count `<script>` tags (excluding `type="application/ld+json"` data blocks). */
46
- export declare function countExecutableScripts(html: string): number;
47
- /**
48
- * How much of the document is markup that could have carried visible text.
49
- *
50
- * The denominator for the text-to-markup ratio. Three element classes are
51
- * emptied rather than counted, because their contents are not markup an
52
- * agent parses for content: script bodies are code or serialized data (a
53
- * framework's hydration payload alone can be ten times the page), style
54
- * bodies are presentation, and svg interiors are drawing instructions —
55
- * the inline twin of image bytes, which nobody would count against an
56
- * `<img>`. Comments likewise. The head is metadata by definition — much
57
- * of it demanded by other checks in this engine — so the measurement
58
- * starts at `<body>` when one exists.
59
- *
60
- * Measured against the raw document instead, vercel.com, stripe.com and
61
- * nextjs.org all sat under the 5% threshold while serving hundreds of
62
- * words of visible text: the raw ratio graded framework choice, not
63
- * agent experience.
64
- */
65
- export declare function structuralMarkupLength(html: string): number;
66
- //# sourceMappingURL=html-utils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"html-utils.d.ts","sourceRoot":"","sources":["../../src/checks/html-utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,mEAAmE;AACnE,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,6FAA6F;AAC7F,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CASlD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI3E;AAED,0FAA0F;AAC1F,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKlF;AAED,0EAA0E;AAC1E,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG9F;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMvE;AAED,kGAAkG;AAClG,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAG3E;AAED,yEAAyE;AACzE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAGhE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CASvD;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAQvD;AAED,kFAAkF;AAClF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAS3D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQ3D"}
@@ -1,139 +0,0 @@
1
- /**
2
- * Shared HTML parsing primitives used by checks that need to inspect homepage markup.
3
- *
4
- * These are deliberately regex-based (no DOM dependency) so the audit stays free of
5
- * heavyweight HTML parsers. They are designed for resilience over completeness — every
6
- * helper returns `null` / empty values on malformed input rather than throwing.
7
- */
8
- /** Escape a string for safe inclusion inside a `RegExp` source. */
9
- export function escapeRegex(value) {
10
- return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
11
- }
12
- /** Decode the small set of HTML entities that show up most often inside attribute values. */
13
- export function unescapeHtml(value) {
14
- return value
15
- .replace(/&amp;/g, '&')
16
- .replace(/&lt;/g, '<')
17
- .replace(/&gt;/g, '>')
18
- .replace(/&quot;/g, '"')
19
- .replace(/&#39;/g, "'")
20
- .replace(/&#x27;/g, "'")
21
- .replace(/&#x2F;/g, '/');
22
- }
23
- /**
24
- * Match the first opening tag (`<tag ...>`) and return its raw attribute string.
25
- * Returns `null` if the tag is absent.
26
- */
27
- export function findOpeningTag(html, tagName) {
28
- const re = new RegExp(`<${escapeRegex(tagName)}\\b([^>]*)>`, 'i');
29
- const m = html.match(re);
30
- return m ? m[1] : null;
31
- }
32
- /** Pull a single attribute out of a raw attribute fragment (the `...` in `<tag ...>`). */
33
- export function getAttribute(attrFragment, attrName) {
34
- const re = new RegExp(`\\b${escapeRegex(attrName)}\\s*=\\s*(?:"([^"]*)"|'([^']*)'|([^\\s>]+))`, 'i');
35
- const m = attrFragment.match(re);
36
- if (!m)
37
- return null;
38
- return unescapeHtml(m[1] ?? m[2] ?? m[3] ?? '');
39
- }
40
- /** Convenience: read an attribute from the first matching opening tag. */
41
- export function getTagAttribute(html, tagName, attrName) {
42
- const frag = findOpeningTag(html, tagName);
43
- return frag === null ? null : getAttribute(frag, attrName);
44
- }
45
- /**
46
- * Extract the `content` value of the first `<meta name="..."|property="..."|http-equiv="...">`
47
- * matching `key`. Searches `name`, `property`, and `http-equiv` (case-insensitive).
48
- */
49
- export function getMetaContent(html, key) {
50
- const escaped = escapeRegex(key);
51
- const re = new RegExp(`<meta\\s+[^>]*\\b(?:name|property|http-equiv)\\s*=\\s*["']${escaped}["'][^>]*>`, 'i');
52
- const m = html.match(re);
53
- if (!m)
54
- return null;
55
- return getAttribute(m[0], 'content');
56
- }
57
- /** Match every `<meta>` tag whose name/property begins with `prefix` (e.g. `og:`, `twitter:`). */
58
- export function findMetaTagsByPrefix(html, prefix) {
59
- const re = new RegExp(`<meta\\s+[^>]*\\b(?:name|property)\\s*=\\s*["']${escapeRegex(prefix)}[^"']*["'][^>]*>`, 'gi');
60
- return [...html.matchAll(re)].map((m) => m[0]);
61
- }
62
- /** Match every `<link rel="...">` tag with the requested `rel` value. */
63
- export function findLinkTags(html, rel) {
64
- const re = new RegExp(`<link\\s+[^>]*\\brel\\s*=\\s*["'][^"']*\\b${escapeRegex(rel)}\\b[^"']*["'][^>]*>`, 'gi');
65
- return [...html.matchAll(re)].map((m) => m[0]);
66
- }
67
- /**
68
- * Strip `<script>` / `<style>` blocks and HTML tags to produce a rough text-content estimate.
69
- * Returns the trimmed plain text — used for content-density / SSR heuristics.
70
- */
71
- export function extractVisibleText(html) {
72
- return html
73
- .replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, ' ')
74
- .replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, ' ')
75
- .replace(/<noscript\b[^>]*>[\s\S]*?<\/noscript>/gi, ' ')
76
- .replace(/<!--[\s\S]*?-->/g, ' ')
77
- .replace(/<[^>]+>/g, ' ')
78
- .replace(/\s+/g, ' ')
79
- .trim();
80
- }
81
- /**
82
- * Extract the contents of every `<script type="application/ld+json">` block.
83
- *
84
- * Attribute order matters here, and it is easy to get wrong: a pattern anchored
85
- * on `<script type=...` misses `<script id="org-json-ld" type="application/ld+json">`,
86
- * which is how several frameworks emit it. That mistake reads as "no structured
87
- * data found" on a site whose markup is perfectly good, so the matcher tolerates
88
- * any attributes before `type`.
89
- */
90
- export function findJsonLdBlocks(html) {
91
- const re = /<script\b([^>]*)>([\s\S]*?)<\/script>/gi;
92
- const blocks = [];
93
- for (const m of html.matchAll(re)) {
94
- const type = (getAttribute(m[1], 'type') ?? '').toLowerCase();
95
- if (type.includes('application/ld+json'))
96
- blocks.push(m[2]);
97
- }
98
- return blocks;
99
- }
100
- /** Count `<script>` tags (excluding `type="application/ld+json"` data blocks). */
101
- export function countExecutableScripts(html) {
102
- const re = /<script\b([^>]*)>/gi;
103
- let count = 0;
104
- for (const m of html.matchAll(re)) {
105
- const type = getAttribute(m[1], 'type') ?? '';
106
- if (/json|template/i.test(type))
107
- continue;
108
- count++;
109
- }
110
- return count;
111
- }
112
- /**
113
- * How much of the document is markup that could have carried visible text.
114
- *
115
- * The denominator for the text-to-markup ratio. Three element classes are
116
- * emptied rather than counted, because their contents are not markup an
117
- * agent parses for content: script bodies are code or serialized data (a
118
- * framework's hydration payload alone can be ten times the page), style
119
- * bodies are presentation, and svg interiors are drawing instructions —
120
- * the inline twin of image bytes, which nobody would count against an
121
- * `<img>`. Comments likewise. The head is metadata by definition — much
122
- * of it demanded by other checks in this engine — so the measurement
123
- * starts at `<body>` when one exists.
124
- *
125
- * Measured against the raw document instead, vercel.com, stripe.com and
126
- * nextjs.org all sat under the 5% threshold while serving hundreds of
127
- * words of visible text: the raw ratio graded framework choice, not
128
- * agent experience.
129
- */
130
- export function structuralMarkupLength(html) {
131
- const stripped = html
132
- .replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, '<script></script>')
133
- .replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, '<style></style>')
134
- .replace(/<svg\b[\s\S]*?<\/svg>/gi, '<svg></svg>')
135
- .replace(/<!--[\s\S]*?-->/g, '');
136
- const body = stripped.match(/<body[\s\S]*<\/body>/i);
137
- return (body ? body[0] : stripped).length;
138
- }
139
- //# sourceMappingURL=html-utils.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"html-utils.js","sourceRoot":"","sources":["../../src/checks/html-utils.ts"],"names":[],"mappings":"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"}
@@ -1,11 +0,0 @@
1
- import type { CheckContext, CheckResult, CheckMeta } from '../types.js';
2
- interface LinkEntry {
3
- url: string;
4
- params: Record<string, string>;
5
- }
6
- /** Parse an RFC 5988 Link header into structured entries. */
7
- export declare function parseLinkHeader(header: string): LinkEntry[];
8
- export declare const meta: CheckMeta;
9
- export default function check(ctx: CheckContext): Promise<CheckResult>;
10
- export {};
11
- //# sourceMappingURL=http-headers.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"http-headers.d.ts","sourceRoot":"","sources":["../../src/checks/http-headers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAW,MAAM,aAAa,CAAC;AAGjF,UAAU,SAAS;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,6DAA6D;AAC7D,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,CA2B3D;AAsFD,eAAO,MAAM,IAAI,EAAE,SAKlB,CAAC;AAwBF,wBAA8B,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAoH3E"}