@rivi-software/agentic-seo-check 0.1.0 → 0.2.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 (144) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +124 -18
  3. package/dist/brand.d.ts +11 -0
  4. package/dist/brand.js +22 -0
  5. package/dist/brand.js.map +1 -0
  6. package/dist/cli.js +174 -86
  7. package/dist/cli.js.map +1 -1
  8. package/dist/core/aeo/audit.d.ts +44 -0
  9. package/dist/core/aeo/audit.js +310 -0
  10. package/dist/core/aeo/audit.js.map +1 -0
  11. package/dist/core/aeo/bots.d.ts +30 -0
  12. package/dist/core/aeo/bots.js +299 -0
  13. package/dist/core/aeo/bots.js.map +1 -0
  14. package/dist/core/aeo/llms-txt.d.ts +8 -0
  15. package/dist/core/aeo/llms-txt.js +88 -0
  16. package/dist/core/aeo/llms-txt.js.map +1 -0
  17. package/dist/core/aeo/page.d.ts +53 -0
  18. package/dist/core/aeo/page.js +312 -0
  19. package/dist/core/aeo/page.js.map +1 -0
  20. package/dist/core/aeo/probe.d.ts +10 -0
  21. package/dist/core/aeo/probe.js +53 -0
  22. package/dist/core/aeo/probe.js.map +1 -0
  23. package/dist/core/aeo/site-rules.d.ts +13 -0
  24. package/dist/core/aeo/site-rules.js +178 -0
  25. package/dist/core/aeo/site-rules.js.map +1 -0
  26. package/dist/core/audit.d.ts +37 -16
  27. package/dist/core/audit.js +389 -249
  28. package/dist/core/audit.js.map +1 -1
  29. package/dist/core/concurrency.d.ts +4 -4
  30. package/dist/core/concurrency.js +33 -23
  31. package/dist/core/concurrency.js.map +1 -1
  32. package/dist/core/crawl.d.ts +9 -5
  33. package/dist/core/crawl.js +271 -123
  34. package/dist/core/crawl.js.map +1 -1
  35. package/dist/core/fetch.d.ts +5 -5
  36. package/dist/core/fetch.js +151 -100
  37. package/dist/core/fetch.js.map +1 -1
  38. package/dist/core/html/answer.d.ts +4 -0
  39. package/dist/core/html/answer.js +198 -0
  40. package/dist/core/html/answer.js.map +1 -0
  41. package/dist/core/html/dom.d.ts +17 -0
  42. package/dist/core/html/dom.js +83 -0
  43. package/dist/core/html/dom.js.map +1 -0
  44. package/dist/core/html/extract.d.ts +2 -2
  45. package/dist/core/html/extract.js +102 -111
  46. package/dist/core/html/extract.js.map +1 -1
  47. package/dist/core/html/structured-data.d.ts +16 -6
  48. package/dist/core/html/structured-data.js +180 -145
  49. package/dist/core/html/structured-data.js.map +1 -1
  50. package/dist/core/html/text.d.ts +14 -14
  51. package/dist/core/html/text.js +110 -107
  52. package/dist/core/html/text.js.map +1 -1
  53. package/dist/core/lighthouse.d.ts +26 -25
  54. package/dist/core/lighthouse.js +181 -105
  55. package/dist/core/lighthouse.js.map +1 -1
  56. package/dist/core/performance-rules.d.ts +2 -2
  57. package/dist/core/performance-rules.js +105 -33
  58. package/dist/core/performance-rules.js.map +1 -1
  59. package/dist/core/render-rules.d.ts +5 -4
  60. package/dist/core/render-rules.js +129 -62
  61. package/dist/core/render-rules.js.map +1 -1
  62. package/dist/core/render.d.ts +2 -2
  63. package/dist/core/render.js +29 -23
  64. package/dist/core/render.js.map +1 -1
  65. package/dist/core/report/markdown.d.ts +4 -2
  66. package/dist/core/report/markdown.js +210 -129
  67. package/dist/core/report/markdown.js.map +1 -1
  68. package/dist/core/robots.d.ts +12 -5
  69. package/dist/core/robots.js +43 -17
  70. package/dist/core/robots.js.map +1 -1
  71. package/dist/core/rules/aeo.d.ts +11 -0
  72. package/dist/core/rules/aeo.js +423 -0
  73. package/dist/core/rules/aeo.js.map +1 -0
  74. package/dist/core/rules/canonical.d.ts +1 -1
  75. package/dist/core/rules/canonical.js +93 -57
  76. package/dist/core/rules/canonical.js.map +1 -1
  77. package/dist/core/rules/content.js +40 -26
  78. package/dist/core/rules/content.js.map +1 -1
  79. package/dist/core/rules/document.js +64 -41
  80. package/dist/core/rules/document.js.map +1 -1
  81. package/dist/core/rules/headings.js +58 -38
  82. package/dist/core/rules/headings.js.map +1 -1
  83. package/dist/core/rules/hreflang.js +70 -38
  84. package/dist/core/rules/hreflang.js.map +1 -1
  85. package/dist/core/rules/images.js +44 -26
  86. package/dist/core/rules/images.js.map +1 -1
  87. package/dist/core/rules/index.d.ts +10 -6
  88. package/dist/core/rules/index.js +43 -36
  89. package/dist/core/rules/index.js.map +1 -1
  90. package/dist/core/rules/indexing.d.ts +2 -2
  91. package/dist/core/rules/indexing.js +48 -26
  92. package/dist/core/rules/indexing.js.map +1 -1
  93. package/dist/core/rules/keyword.js +84 -47
  94. package/dist/core/rules/keyword.js.map +1 -1
  95. package/dist/core/rules/links.js +72 -37
  96. package/dist/core/rules/links.js.map +1 -1
  97. package/dist/core/rules/meta.js +55 -34
  98. package/dist/core/rules/meta.js.map +1 -1
  99. package/dist/core/rules/response.js +75 -41
  100. package/dist/core/rules/response.js.map +1 -1
  101. package/dist/core/rules/rule.d.ts +6 -6
  102. package/dist/core/rules/rule.js +36 -36
  103. package/dist/core/rules/rule.js.map +1 -1
  104. package/dist/core/rules/social.js +86 -45
  105. package/dist/core/rules/social.js.map +1 -1
  106. package/dist/core/rules/structured-data.d.ts +6 -4
  107. package/dist/core/rules/structured-data.js +314 -102
  108. package/dist/core/rules/structured-data.js.map +1 -1
  109. package/dist/core/rules/title.js +48 -33
  110. package/dist/core/rules/title.js.map +1 -1
  111. package/dist/core/score.d.ts +5 -3
  112. package/dist/core/score.js +11 -9
  113. package/dist/core/score.js.map +1 -1
  114. package/dist/core/site-rules.d.ts +3 -3
  115. package/dist/core/site-rules.js +409 -198
  116. package/dist/core/site-rules.js.map +1 -1
  117. package/dist/core/sitemap.d.ts +5 -5
  118. package/dist/core/sitemap.js +109 -64
  119. package/dist/core/sitemap.js.map +1 -1
  120. package/dist/core/static.d.ts +2 -2
  121. package/dist/core/static.js +210 -112
  122. package/dist/core/static.js.map +1 -1
  123. package/dist/core/summary.d.ts +2 -2
  124. package/dist/core/summary.js +11 -6
  125. package/dist/core/summary.js.map +1 -1
  126. package/dist/core/types.d.ts +189 -14
  127. package/dist/core/types.js +15 -8
  128. package/dist/core/types.js.map +1 -1
  129. package/dist/core/url.d.ts +11 -11
  130. package/dist/core/url.js +122 -70
  131. package/dist/core/url.js.map +1 -1
  132. package/dist/index.d.ts +15 -11
  133. package/dist/index.js +11 -9
  134. package/dist/index.js.map +1 -1
  135. package/dist/mcp-bin.js +7 -4
  136. package/dist/mcp-bin.js.map +1 -1
  137. package/dist/mcp.d.ts +3 -3
  138. package/dist/mcp.js +437 -121
  139. package/dist/mcp.js.map +1 -1
  140. package/dist/version.d.ts +0 -1
  141. package/dist/version.js +4 -2
  142. package/dist/version.js.map +1 -1
  143. package/package.json +32 -10
  144. package/skills/seo-audit/SKILL.md +8 -2
@@ -1,68 +1,100 @@
1
- import { normalizeUrl } from '../url.js';
2
- import { cap, defineRule, GOOGLE_DOCS } from './rule.js';
3
- const HREFLANG_CODE = /^(x-default|[a-zA-Z]{2,3}(-[a-zA-Z]{4})?(-([a-zA-Z]{2}|\d{3}))?)$/;
1
+ import { normalizeUrl } from "../url.js";
2
+ import { cap, defineRule, GOOGLE_DOCS } from "./rule.js";
3
+ const HREFLANG_CODE = /^(?:x-default|[a-zA-Z]{2,3}(?:-[a-zA-Z]{4})?(?:-(?:[a-zA-Z]{2}|\d{3}))?)$/u;
4
4
  export const hreflangRules = [
5
5
  defineRule({
6
- id: 'hreflang.invalid-code',
7
- category: 'international',
8
- severity: 'warning',
9
- description: 'hreflang values that are not valid ISO 639-1 language codes with an optional ISO 3166-1 region (or x-default).',
6
+ id: "hreflang.invalid-code",
7
+ category: "international",
8
+ severity: "warning",
9
+ description: "hreflang values that are not valid ISO 639-1 language codes with an optional ISO 3166-1 region (or x-default).",
10
10
  recommendation: 'Use codes like "en", "en-gb", "nl-nl", "zh-hant" or "x-default". Country codes alone ("uk", "eu") are invalid.',
11
11
  docs: GOOGLE_DOCS.hreflang,
12
12
  }, ({ page }, make) => {
13
13
  const bad = page.hreflang.filter((h) => !HREFLANG_CODE.test(h.lang));
14
- return bad.length ? make(`${bad.length} hreflang value(s) are invalid.`, { selector: 'link[rel="alternate"][hreflang]', evidence: { invalid: cap(bad.map((h) => h.lang)) } }) : null;
14
+ return bad.length
15
+ ? make(`${bad.length} hreflang value(s) are invalid.`, {
16
+ selector: 'link[rel="alternate"][hreflang]',
17
+ evidence: { invalid: cap(bad.map((h) => h.lang)) },
18
+ })
19
+ : null;
15
20
  }),
16
21
  defineRule({
17
- id: 'hreflang.relative-url',
18
- category: 'international',
19
- severity: 'warning',
20
- description: 'hreflang links must use absolute URLs.',
21
- recommendation: 'Use fully qualified URLs (https://example.com/nl/) in every hreflang link.',
22
+ id: "hreflang.relative-url",
23
+ category: "international",
24
+ severity: "warning",
25
+ description: "hreflang links must use absolute URLs.",
26
+ recommendation: "Use fully qualified URLs (https://example.com/nl/) in every hreflang link.",
22
27
  docs: GOOGLE_DOCS.hreflang,
23
28
  }, ({ page }, make) => {
24
- const rel = page.hreflang.filter((h) => !/^https?:\/\//i.test(h.href));
25
- return rel.length ? make(`${rel.length} hreflang link(s) use relative URLs.`, { selector: 'link[rel="alternate"][hreflang]', evidence: { examples: cap(rel.map((h) => h.href)) } }) : null;
29
+ const rel = page.hreflang.filter((h) => !/^https?:\/\//iu.test(h.href));
30
+ return rel.length
31
+ ? make(`${rel.length} hreflang link(s) use relative URLs.`, {
32
+ selector: 'link[rel="alternate"][hreflang]',
33
+ evidence: { examples: cap(rel.map((h) => h.href)) },
34
+ })
35
+ : null;
26
36
  }),
27
37
  defineRule({
28
- id: 'hreflang.duplicate-lang',
29
- category: 'international',
30
- severity: 'warning',
31
- description: 'The same hreflang value appears more than once with different URLs.',
32
- recommendation: 'Each language/region code may map to exactly one URL per page.',
38
+ id: "hreflang.duplicate-lang",
39
+ category: "international",
40
+ severity: "warning",
41
+ description: "The same hreflang value appears more than once with different URLs.",
42
+ recommendation: "Each language/region code may map to exactly one URL per page.",
33
43
  docs: GOOGLE_DOCS.hreflang,
34
44
  }, ({ page }, make) => {
35
45
  const seen = new Map();
36
46
  for (const h of page.hreflang) {
37
47
  const key = h.lang.toLowerCase();
38
- if (!seen.has(key))
39
- seen.set(key, new Set());
40
- seen.get(key).add(h.url ?? h.href);
48
+ const urls = seen.get(key) ?? new Set();
49
+ urls.add(h.url ?? h.href);
50
+ seen.set(key, urls);
41
51
  }
42
- const dupes = [...seen.entries()].filter(([, urls]) => urls.size > 1).map(([lang]) => lang);
43
- return dupes.length ? make(`hreflang codes with conflicting URLs: ${dupes.join(', ')}.`, { selector: 'link[rel="alternate"][hreflang]', evidence: { codes: dupes } }) : null;
52
+ const dupes = [...seen.entries()].flatMap(([lang, urls]) => urls.size > 1 ? [lang] : []);
53
+ return dupes.length
54
+ ? make(`hreflang codes with conflicting URLs: ${dupes.join(", ")}.`, {
55
+ selector: 'link[rel="alternate"][hreflang]',
56
+ evidence: { codes: dupes },
57
+ })
58
+ : null;
44
59
  }),
45
60
  defineRule({
46
- id: 'hreflang.missing-self',
47
- category: 'international',
48
- severity: 'warning',
49
- description: 'The hreflang set does not include this page itself (self-referencing entry).',
50
- recommendation: 'Every page in an hreflang cluster must list itself as well as its alternates, otherwise the annotations may be ignored.',
61
+ id: "hreflang.missing-self",
62
+ category: "international",
63
+ severity: "warning",
64
+ description: "The hreflang set does not include this page itself (self-referencing entry).",
65
+ recommendation: "Every page in an hreflang cluster must list itself as well as its alternates, otherwise the annotations may be ignored.",
51
66
  docs: GOOGLE_DOCS.hreflang,
52
67
  }, ({ page }, make) => {
53
- if (page.hreflang.length === 0)
68
+ if (page.hreflang.length === 0) {
54
69
  return null;
55
- const self = new Set([normalizeUrl(page.url), page.canonical ? normalizeUrl(page.canonical) : null].filter(Boolean));
70
+ }
71
+ const self = new Set([
72
+ normalizeUrl(page.url),
73
+ page.canonical ? normalizeUrl(page.canonical) : null,
74
+ ].filter(Boolean));
56
75
  const hasSelf = page.hreflang.some((h) => h.url && self.has(normalizeUrl(h.url)));
57
- return hasSelf ? null : make('hreflang set has no entry pointing at this page.', { selector: 'link[rel="alternate"][hreflang]', evidence: { page: page.url, alternates: cap(page.hreflang.map((h) => `${h.lang} → ${h.href}`)) } });
76
+ return hasSelf
77
+ ? null
78
+ : make("hreflang set has no entry pointing at this page.", {
79
+ selector: 'link[rel="alternate"][hreflang]',
80
+ evidence: {
81
+ page: page.url,
82
+ alternates: cap(page.hreflang.map((h) => `${h.lang} → ${h.href}`)),
83
+ },
84
+ });
58
85
  }),
59
86
  defineRule({
60
- id: 'hreflang.missing-x-default',
61
- category: 'international',
62
- severity: 'info',
63
- description: 'The hreflang set has no x-default entry.',
87
+ id: "hreflang.missing-x-default",
88
+ category: "international",
89
+ severity: "info",
90
+ description: "The hreflang set has no x-default entry.",
64
91
  recommendation: 'Add <link rel="alternate" hreflang="x-default" href="..."> pointing at the language-selector or default version.',
65
92
  docs: GOOGLE_DOCS.hreflang,
66
- }, ({ page }, make) => (page.hreflang.length > 0 && !page.hreflang.some((h) => h.lang.toLowerCase() === 'x-default') ? make('hreflang set has no x-default entry.', { selector: 'link[rel="alternate"][hreflang]' }) : null)),
93
+ }, ({ page }, make) => page.hreflang.length > 0 &&
94
+ !page.hreflang.some((h) => h.lang.toLowerCase() === "x-default")
95
+ ? make("hreflang set has no x-default entry.", {
96
+ selector: 'link[rel="alternate"][hreflang]',
97
+ })
98
+ : null),
67
99
  ];
68
100
  //# sourceMappingURL=hreflang.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"hreflang.js","sourceRoot":"","sources":["../../../src/core/rules/hreflang.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hreflang.js","sourceRoot":"","sources":["../../../src/core/rules/hreflang.ts"],"names":[],"mappings":"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"}
@@ -1,59 +1,77 @@
1
- import { cap, defineRule, GOOGLE_DOCS } from './rule.js';
2
- const FILENAME_ALT = /^(img|image|dsc|dscn|dcim|photo|screenshot|screen shot|untitled)[-_ ]?\d*|\.(jpe?g|png|gif|webp|avif|svg)$/i;
1
+ import { cap, defineRule, GOOGLE_DOCS } from "./rule.js";
2
+ const FILENAME_ALT = /^(?:img|image|dsc|dscn|dcim|photo|screenshot|screen shot|untitled)[-_ ]?\d*|\.(?:jpe?g|png|gif|webp|avif|svg)$/iu;
3
3
  export const imageRules = [
4
4
  defineRule({
5
- id: 'img.alt-missing',
6
- category: 'images',
7
- severity: 'warning',
8
- description: 'Images without an alt attribute.',
5
+ id: "img.alt-missing",
6
+ category: "images",
7
+ severity: "warning",
8
+ description: "Images without an alt attribute.",
9
9
  recommendation: 'Give every <img> an alt attribute: a short description for meaningful images, alt="" for purely decorative ones. Alt text is used for image search and accessibility.',
10
10
  docs: GOOGLE_DOCS.images,
11
11
  }, ({ page }, make) => {
12
12
  const missing = page.images.filter((i) => i.alt === null);
13
13
  return missing.length
14
14
  ? make(`${missing.length} of ${page.images.length} images have no alt attribute.`, {
15
- selector: 'img:not([alt])',
16
- evidence: { count: missing.length, total: page.images.length, examples: cap(missing.map((i) => i.src ?? '(no src)')) },
15
+ selector: "img:not([alt])",
16
+ evidence: {
17
+ count: missing.length,
18
+ total: page.images.length,
19
+ examples: cap(missing.map((i) => i.src ?? "(no src)")),
20
+ },
17
21
  })
18
22
  : null;
19
23
  }),
20
24
  defineRule({
21
- id: 'img.alt-filename',
22
- category: 'images',
23
- severity: 'info',
24
- description: 'Image alt text looks like a filename (IMG_1234.jpg, screenshot.png).',
25
- recommendation: 'Replace filename-style alt text with a description of what the image shows.',
25
+ id: "img.alt-filename",
26
+ category: "images",
27
+ severity: "info",
28
+ description: "Image alt text looks like a filename (IMG_1234.jpg, screenshot.png).",
29
+ recommendation: "Replace filename-style alt text with a description of what the image shows.",
26
30
  docs: GOOGLE_DOCS.images,
27
31
  }, ({ page }, make) => {
28
32
  const bad = page.images.filter((i) => i.alt && FILENAME_ALT.test(i.alt.trim()));
29
- return bad.length ? make(`${bad.length} image(s) have filename-like alt text.`, { evidence: { examples: cap(bad.map((i) => ({ src: i.src, alt: i.alt }))) } }) : null;
33
+ return bad.length
34
+ ? make(`${bad.length} image(s) have filename-like alt text.`, {
35
+ evidence: {
36
+ examples: cap(bad.map((i) => ({ src: i.src, alt: i.alt }))),
37
+ },
38
+ })
39
+ : null;
30
40
  }),
31
41
  defineRule({
32
- id: 'img.dimensions-missing',
33
- category: 'images',
34
- severity: 'info',
35
- description: 'Images without explicit width and height attributes, which causes layout shift (CLS) while they load.',
36
- recommendation: 'Add width and height attributes (or CSS aspect-ratio) to <img> elements so the browser can reserve space before the image loads.',
42
+ id: "img.dimensions-missing",
43
+ category: "images",
44
+ severity: "info",
45
+ description: "Images without explicit width and height attributes, which causes layout shift (CLS) while they load.",
46
+ recommendation: "Add width and height attributes (or CSS aspect-ratio) to <img> elements so the browser can reserve space before the image loads.",
37
47
  docs: GOOGLE_DOCS.cwv,
38
48
  }, ({ page }, make) => {
39
49
  const missing = page.images.filter((i) => i.src && (!i.width || !i.height));
40
50
  return missing.length
41
51
  ? make(`${missing.length} of ${page.images.length} images lack width/height attributes.`, {
42
- selector: 'img:not([width]), img:not([height])',
43
- evidence: { count: missing.length, examples: cap(missing.map((i) => i.src)) },
52
+ selector: "img:not([width]), img:not([height])",
53
+ evidence: {
54
+ count: missing.length,
55
+ examples: cap(missing.map((i) => i.src)),
56
+ },
44
57
  })
45
58
  : null;
46
59
  }),
47
60
  defineRule({
48
- id: 'img.src-missing',
49
- category: 'images',
50
- severity: 'info',
51
- description: 'Images without a src attribute (usually lazy-loading via data-src without a fallback).',
61
+ id: "img.src-missing",
62
+ category: "images",
63
+ severity: "info",
64
+ description: "Images without a src attribute (usually lazy-loading via data-src without a fallback).",
52
65
  recommendation: 'Use native loading="lazy" with a real src, or ensure the lazy-loader also works without JavaScript, so crawlers can discover the images.',
53
66
  docs: GOOGLE_DOCS.images,
54
67
  }, ({ page }, make) => {
55
68
  const missing = page.images.filter((i) => !i.src);
56
- return missing.length ? make(`${missing.length} image(s) have no src attribute.`, { selector: 'img:not([src])', evidence: { count: missing.length } }) : null;
69
+ return missing.length
70
+ ? make(`${missing.length} image(s) have no src attribute.`, {
71
+ selector: "img:not([src])",
72
+ evidence: { count: missing.length },
73
+ })
74
+ : null;
57
75
  }),
58
76
  ];
59
77
  //# sourceMappingURL=images.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"images.js","sourceRoot":"","sources":["../../../src/core/rules/images.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"images.js","sourceRoot":"","sources":["../../../src/core/rules/images.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAEzD,MAAM,YAAY,GAChB,kHAAkH,CAAC;AAErH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,UAAU,CACR;QACE,EAAE,EAAE,iBAAiB;QACrB,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,SAAS;QACnB,WAAW,EAAE,kCAAkC;QAC/C,cAAc,EACZ,uKAAuK;QACzK,IAAI,EAAE,WAAW,CAAC,MAAM;KACzB,EACD,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE;QACjB,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC;QAE1D,OAAO,OAAO,CAAC,MAAM;YACnB,CAAC,CAAC,IAAI,CACF,GAAG,OAAO,CAAC,MAAM,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,gCAAgC,EAC1E;gBACE,QAAQ,EAAE,gBAAgB;gBAC1B,QAAQ,EAAE;oBACR,KAAK,EAAE,OAAO,CAAC,MAAM;oBACrB,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM;oBACzB,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,UAAU,CAAC,CAAC;iBACvD;aACF,CACF;YACH,CAAC,CAAC,IAAI,CAAC;IACX,CAAC,CACF;IACD,UAAU,CACR;QACE,EAAE,EAAE,kBAAkB;QACtB,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,MAAM;QAChB,WAAW,EACT,sEAAsE;QACxE,cAAc,EACZ,6EAA6E;QAC/E,IAAI,EAAE,WAAW,CAAC,MAAM;KACzB,EACD,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE;QACjB,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAC5B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAChD,CAAC;QAEF,OAAO,GAAG,CAAC,MAAM;YACf,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,wCAAwC,EAAE;gBAC1D,QAAQ,EAAE;oBACR,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;iBAC5D;aACF,CAAC;YACJ,CAAC,CAAC,IAAI,CAAC;IACX,CAAC,CACF;IACD,UAAU,CACR;QACE,EAAE,EAAE,wBAAwB;QAC5B,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,MAAM;QAChB,WAAW,EACT,uGAAuG;QACzG,cAAc,EACZ,kIAAkI;QACpI,IAAI,EAAE,WAAW,CAAC,GAAG;KACtB,EACD,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE;QACjB,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAChC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CACxC,CAAC;QAEF,OAAO,OAAO,CAAC,MAAM;YACnB,CAAC,CAAC,IAAI,CACF,GAAG,OAAO,CAAC,MAAM,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,uCAAuC,EACjF;gBACE,QAAQ,EAAE,qCAAqC;gBAC/C,QAAQ,EAAE;oBACR,KAAK,EAAE,OAAO,CAAC,MAAM;oBACrB,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;iBACzC;aACF,CACF;YACH,CAAC,CAAC,IAAI,CAAC;IACX,CAAC,CACF;IACD,UAAU,CACR;QACE,EAAE,EAAE,iBAAiB;QACrB,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,MAAM;QAChB,WAAW,EACT,wFAAwF;QAC1F,cAAc,EACZ,0IAA0I;QAC5I,IAAI,EAAE,WAAW,CAAC,MAAM;KACzB,EACD,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE;QACjB,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAElD,OAAO,OAAO,CAAC,MAAM;YACnB,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,kCAAkC,EAAE;gBACxD,QAAQ,EAAE,gBAAgB;gBAC1B,QAAQ,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE;aACpC,CAAC;YACJ,CAAC,CAAC,IAAI,CAAC;IACX,CAAC,CACF;CACF,CAAC"}
@@ -1,14 +1,18 @@
1
- import type { Finding, RuleMeta } from '../types.js';
2
- import type { PageContext, Rule } from './rule.js';
3
- export type { PageContext, Rule } from './rule.js';
1
+ import type { Finding, RuleMeta } from "../types.js";
2
+ import type { PageContext, Rule } from "./rule.js";
3
+ export type { PageContext, Rule } from "./rule.js";
4
4
  /** Rules evaluated against a single HTML document. */
5
5
  export declare const PAGE_RULES: Rule[];
6
+ /** Rules the AEO audit evaluates against each page; the SEO audit never runs them. */
7
+ export declare const AEO_PAGE_RULES: Rule[];
6
8
  /** Metadata for every rule the tool can emit, including rules implemented outside the page-rule loop. */
7
9
  export declare const ALL_RULES: RuleMeta[];
8
10
  export interface RunRulesOptions {
9
11
  /** Rule ids to skip. */
10
12
  disable?: Set<string>;
13
+ /** The rules to run (default: the SEO page rules). */
14
+ rules?: Rule[];
11
15
  }
12
- export declare function runPageRules(ctx: PageContext, options?: RunRulesOptions): Finding[];
13
- export declare function sortFindings(findings: Finding[]): Finding[];
14
- export declare function findRule(id: string): RuleMeta | undefined;
16
+ export declare const sortFindings: (findings: Finding[]) => Finding[];
17
+ export declare const runPageRules: (ctx: PageContext, options?: RunRulesOptions) => Finding[];
18
+ export declare const findRule: (id: string) => RuleMeta | undefined;
@@ -1,20 +1,22 @@
1
- import { canonicalRules } from './canonical.js';
2
- import { contentRules } from './content.js';
3
- import { documentRules } from './document.js';
4
- import { headingRules } from './headings.js';
5
- import { hreflangRules } from './hreflang.js';
6
- import { imageRules } from './images.js';
7
- import { indexingRules } from './indexing.js';
8
- import { keywordRules } from './keyword.js';
9
- import { linkRules } from './links.js';
10
- import { metaRules } from './meta.js';
11
- import { responseRules } from './response.js';
12
- import { socialRules } from './social.js';
13
- import { structuredDataRules } from './structured-data.js';
14
- import { titleRules } from './title.js';
15
- import { RENDER_RULES } from '../render-rules.js';
16
- import { PERFORMANCE_RULES } from '../performance-rules.js';
17
- import { SITE_RULES } from '../site-rules.js';
1
+ import { AEO_SITE_RULES } from "../aeo/site-rules.js";
2
+ import { PERFORMANCE_RULES } from "../performance-rules.js";
3
+ import { RENDER_RULES } from "../render-rules.js";
4
+ import { SITE_RULES } from "../site-rules.js";
5
+ import { aeoRules } from "./aeo.js";
6
+ import { canonicalRules } from "./canonical.js";
7
+ import { contentRules } from "./content.js";
8
+ import { documentRules } from "./document.js";
9
+ import { headingRules } from "./headings.js";
10
+ import { hreflangRules } from "./hreflang.js";
11
+ import { imageRules } from "./images.js";
12
+ import { indexingRules } from "./indexing.js";
13
+ import { keywordRules } from "./keyword.js";
14
+ import { linkRules } from "./links.js";
15
+ import { metaRules } from "./meta.js";
16
+ import { responseRules } from "./response.js";
17
+ import { socialRules } from "./social.js";
18
+ import { structuredDataRules } from "./structured-data.js";
19
+ import { titleRules } from "./title.js";
18
20
  /** Rules evaluated against a single HTML document. */
19
21
  export const PAGE_RULES = [
20
22
  ...titleRules,
@@ -32,45 +34,50 @@ export const PAGE_RULES = [
32
34
  ...keywordRules,
33
35
  ...responseRules,
34
36
  ];
37
+ /** Rules the AEO audit evaluates against each page; the SEO audit never runs them. */
38
+ export const AEO_PAGE_RULES = aeoRules;
35
39
  /** Metadata for every rule the tool can emit, including rules implemented outside the page-rule loop. */
36
40
  export const ALL_RULES = [
37
41
  ...PAGE_RULES.map((r) => r.meta),
38
42
  ...RENDER_RULES,
39
43
  ...PERFORMANCE_RULES,
40
44
  ...SITE_RULES,
45
+ ...AEO_PAGE_RULES.map((r) => r.meta),
46
+ ...AEO_SITE_RULES,
41
47
  ];
42
- export function runPageRules(ctx, options = {}) {
48
+ export const sortFindings = (findings) => {
49
+ const rank = { error: 0, warning: 1, info: 2 };
50
+ return findings.toSorted((a, b) => rank[a.severity] - rank[b.severity] || a.rule.localeCompare(b.rule));
51
+ };
52
+ export const runPageRules = (ctx, options = {}) => {
43
53
  const findings = [];
44
- for (const rule of PAGE_RULES) {
45
- if (options.disable?.has(rule.meta.id))
54
+ for (const rule of options.rules ?? PAGE_RULES) {
55
+ if (options.disable?.has(rule.meta.id)) {
46
56
  continue;
47
- if (rule.meta.requires === 'keyword' && !ctx.keyword)
57
+ }
58
+ if (rule.meta.requires === "keyword" && !ctx.keyword) {
48
59
  continue;
60
+ }
49
61
  try {
50
62
  for (const f of rule.check(ctx)) {
51
- if (!f.url)
63
+ if (!f.url) {
52
64
  f.url = ctx.response?.finalUrl ?? ctx.page.url;
65
+ }
53
66
  findings.push(f);
54
67
  }
55
68
  }
56
- catch (err) {
69
+ catch (error) {
57
70
  findings.push({
58
- rule: 'tool.rule-error',
59
- severity: 'info',
60
- category: 'tool',
61
- message: `Rule ${rule.meta.id} failed: ${err.message}`,
62
- recommendation: 'Report this as a bug at https://github.com/rivi-software/agentic-seo-check/issues; the rest of the audit is unaffected.',
71
+ rule: "tool.rule-error",
72
+ severity: "info",
73
+ category: "tool",
74
+ message: `Rule ${rule.meta.id} failed: ${error instanceof Error ? error.message : String(error)}`,
75
+ recommendation: "Report this as a bug at https://github.com/rivi-software/agentic-seo-check/issues; the rest of the audit is unaffected.",
63
76
  url: ctx.page.url,
64
77
  });
65
78
  }
66
79
  }
67
80
  return sortFindings(findings);
68
- }
69
- export function sortFindings(findings) {
70
- const rank = { error: 0, warning: 1, info: 2 };
71
- return [...findings].sort((a, b) => rank[a.severity] - rank[b.severity] || a.rule.localeCompare(b.rule));
72
- }
73
- export function findRule(id) {
74
- return ALL_RULES.find((r) => r.id === id);
75
- }
81
+ };
82
+ export const findRule = (id) => ALL_RULES.find((r) => r.id === id);
76
83
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/rules/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/rules/index.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { ExtractedPage, ResponseInfo } from '../types.js';
1
+ import type { ExtractedPage, ResponseInfo } from "../types.js";
2
2
  export interface RobotsDirectives {
3
3
  noindex: boolean;
4
4
  nofollow: boolean;
@@ -6,5 +6,5 @@ export interface RobotsDirectives {
6
6
  directives: string[];
7
7
  }
8
8
  /** Combine <meta name="robots"> / googlebot and the X-Robots-Tag header. */
9
- export declare function robotsDirectives(page: ExtractedPage, response?: ResponseInfo): RobotsDirectives;
9
+ export declare const robotsDirectives: (page: ExtractedPage, response?: ResponseInfo) => RobotsDirectives;
10
10
  export declare const indexingRules: import("./rule.js").Rule[];
@@ -1,53 +1,75 @@
1
- import { defineRule, GOOGLE_DOCS } from './rule.js';
1
+ import { defineRule, GOOGLE_DOCS } from "./rule.js";
2
2
  /** Combine <meta name="robots"> / googlebot and the X-Robots-Tag header. */
3
- export function robotsDirectives(page, response) {
3
+ export const robotsDirectives = (page, response) => {
4
4
  const directives = [];
5
5
  const sources = [];
6
6
  for (const content of page.metaRobots) {
7
- for (const d of content.split(',').map((s) => s.trim()).filter(Boolean)) {
7
+ for (const d of content
8
+ .split(",")
9
+ .map((s) => s.trim())
10
+ .filter(Boolean)) {
8
11
  directives.push(d);
9
- sources.push('meta');
12
+ sources.push("meta");
10
13
  }
11
14
  }
12
- const header = response?.headers['x-robots-tag'];
15
+ const header = response?.headers["x-robots-tag"];
13
16
  if (header) {
14
- for (const d of header.toLowerCase().split(',').map((s) => s.trim()).filter(Boolean)) {
17
+ for (const d of header
18
+ .toLowerCase()
19
+ .split(",")
20
+ .map((s) => s.trim())
21
+ .filter(Boolean)) {
15
22
  // "googlebot: noindex" form
16
- directives.push(d.includes(':') ? (d.split(':').pop() ?? d).trim() : d);
17
- sources.push('header');
23
+ directives.push(d.includes(":") ? (d.split(":").pop() ?? d).trim() : d);
24
+ sources.push("header");
18
25
  }
19
26
  }
20
- const noindex = directives.some((d) => d === 'noindex' || d === 'none');
21
- const nofollow = directives.some((d) => d === 'nofollow' || d === 'none');
22
- return { noindex, nofollow, sources: [...new Set(sources)], directives: [...new Set(directives)] };
23
- }
27
+ const noindex = directives.some((d) => d === "noindex" || d === "none");
28
+ const nofollow = directives.some((d) => d === "nofollow" || d === "none");
29
+ return {
30
+ noindex,
31
+ nofollow,
32
+ sources: [...new Set(sources)],
33
+ directives: [...new Set(directives)],
34
+ };
35
+ };
24
36
  export const indexingRules = [
25
37
  defineRule({
26
- id: 'robots.noindex',
27
- category: 'indexing',
28
- severity: 'warning',
29
- description: 'The page tells search engines not to index it (meta robots or X-Robots-Tag).',
30
- recommendation: 'If this page should appear in search results, remove the noindex directive. Preview/staging hosts often add X-Robots-Tag: noindex at the platform level; verify on production. If the page is intentionally private (login, thank-you, internal search), this is correct.',
38
+ id: "robots.noindex",
39
+ category: "indexing",
40
+ severity: "warning",
41
+ description: "The page tells search engines not to index it (meta robots or X-Robots-Tag).",
42
+ recommendation: "If this page should appear in search results, remove the noindex directive. Preview/staging hosts often add X-Robots-Tag: noindex at the platform level; verify on production. If the page is intentionally private (login, thank-you, internal search), this is correct.",
31
43
  docs: GOOGLE_DOCS.robotsMeta,
32
44
  }, ({ page, response }, make) => {
33
45
  const r = robotsDirectives(page, response);
34
46
  return r.noindex
35
- ? make(`Page is set to noindex via ${r.sources.join(' and ')}.`, {
36
- selector: r.sources.includes('meta') ? 'head > meta[name="robots"]' : undefined,
37
- evidence: { directives: r.directives, sources: r.sources, xRobotsTag: response?.headers['x-robots-tag'] ?? null },
47
+ ? make(`Page is set to noindex via ${r.sources.join(" and ")}.`, {
48
+ selector: r.sources.includes("meta")
49
+ ? 'head > meta[name="robots"]'
50
+ : undefined,
51
+ evidence: {
52
+ directives: r.directives,
53
+ sources: r.sources,
54
+ xRobotsTag: response?.headers["x-robots-tag"] ?? null,
55
+ },
38
56
  })
39
57
  : null;
40
58
  }),
41
59
  defineRule({
42
- id: 'robots.nofollow',
43
- category: 'indexing',
44
- severity: 'info',
45
- description: 'The page tells search engines not to follow its links.',
46
- recommendation: 'Remove nofollow unless you deliberately want link equity to stop at this page; it also hides linked pages from discovery.',
60
+ id: "robots.nofollow",
61
+ category: "indexing",
62
+ severity: "info",
63
+ description: "The page tells search engines not to follow its links.",
64
+ recommendation: "Remove nofollow unless you deliberately want link equity to stop at this page; it also hides linked pages from discovery.",
47
65
  docs: GOOGLE_DOCS.robotsMeta,
48
66
  }, ({ page, response }, make) => {
49
67
  const r = robotsDirectives(page, response);
50
- return r.nofollow ? make(`Page-level nofollow is set via ${r.sources.join(' and ')}.`, { evidence: { directives: r.directives } }) : null;
68
+ return r.nofollow
69
+ ? make(`Page-level nofollow is set via ${r.sources.join(" and ")}.`, {
70
+ evidence: { directives: r.directives },
71
+ })
72
+ : null;
51
73
  }),
52
74
  ];
53
75
  //# sourceMappingURL=indexing.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"indexing.js","sourceRoot":"","sources":["../../../src/core/rules/indexing.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"indexing.js","sourceRoot":"","sources":["../../../src/core/rules/indexing.ts"],"names":[],"mappings":"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"}