@pseolint/core 0.4.1 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +264 -169
- package/dist/ai/manifest/diff.d.ts +78 -0
- package/dist/ai/manifest/diff.d.ts.map +1 -0
- package/dist/ai/manifest/diff.js +139 -0
- package/dist/ai/manifest/diff.js.map +1 -0
- package/dist/ai/manifest/index.d.ts +18 -0
- package/dist/ai/manifest/index.d.ts.map +1 -0
- package/dist/ai/manifest/index.js +15 -0
- package/dist/ai/manifest/index.js.map +1 -0
- package/dist/ai/manifest/validate-manifest.d.ts +37 -0
- package/dist/ai/manifest/validate-manifest.d.ts.map +1 -0
- package/dist/ai/manifest/validate-manifest.js +67 -0
- package/dist/ai/manifest/validate-manifest.js.map +1 -0
- package/dist/ai/manifest/validators/domain-patches.d.ts +15 -0
- package/dist/ai/manifest/validators/domain-patches.d.ts.map +1 -0
- package/dist/ai/manifest/validators/domain-patches.js +110 -0
- package/dist/ai/manifest/validators/domain-patches.js.map +1 -0
- package/dist/ai/manifest/validators/index.d.ts +5 -0
- package/dist/ai/manifest/validators/index.d.ts.map +1 -0
- package/dist/ai/manifest/validators/index.js +4 -0
- package/dist/ai/manifest/validators/index.js.map +1 -0
- package/dist/ai/manifest/validators/page-changes.d.ts +36 -0
- package/dist/ai/manifest/validators/page-changes.d.ts.map +1 -0
- package/dist/ai/manifest/validators/page-changes.js +221 -0
- package/dist/ai/manifest/validators/page-changes.js.map +1 -0
- package/dist/ai/manifest/validators/types.d.ts +17 -0
- package/dist/ai/manifest/validators/types.d.ts.map +1 -0
- package/dist/ai/manifest/validators/types.js +5 -0
- package/dist/ai/manifest/validators/types.js.map +1 -0
- package/dist/ai/orchestrate.d.ts +74 -0
- package/dist/ai/orchestrate.d.ts.map +1 -0
- package/dist/ai/orchestrate.js +54 -0
- package/dist/ai/orchestrate.js.map +1 -0
- package/dist/ai/orchestrator/budget.d.ts +57 -0
- package/dist/ai/orchestrator/budget.d.ts.map +1 -0
- package/dist/ai/orchestrator/budget.js +114 -0
- package/dist/ai/orchestrator/budget.js.map +1 -0
- package/dist/ai/orchestrator/finish-tool.d.ts +568 -0
- package/dist/ai/orchestrator/finish-tool.d.ts.map +1 -0
- package/dist/ai/orchestrator/finish-tool.js +114 -0
- package/dist/ai/orchestrator/finish-tool.js.map +1 -0
- package/dist/ai/orchestrator/index.d.ts +25 -0
- package/dist/ai/orchestrator/index.d.ts.map +1 -0
- package/dist/ai/orchestrator/index.js +21 -0
- package/dist/ai/orchestrator/index.js.map +1 -0
- package/dist/ai/orchestrator/log.d.ts +24 -0
- package/dist/ai/orchestrator/log.d.ts.map +1 -0
- package/dist/ai/orchestrator/log.js +48 -0
- package/dist/ai/orchestrator/log.js.map +1 -0
- package/dist/ai/orchestrator/page-cache.d.ts +64 -0
- package/dist/ai/orchestrator/page-cache.d.ts.map +1 -0
- package/dist/ai/orchestrator/page-cache.js +127 -0
- package/dist/ai/orchestrator/page-cache.js.map +1 -0
- package/dist/ai/orchestrator/prompt.d.ts +16 -0
- package/dist/ai/orchestrator/prompt.d.ts.map +1 -0
- package/dist/ai/orchestrator/prompt.js +52 -0
- package/dist/ai/orchestrator/prompt.js.map +1 -0
- package/dist/ai/orchestrator/runner.d.ts +65 -0
- package/dist/ai/orchestrator/runner.d.ts.map +1 -0
- package/dist/ai/orchestrator/runner.js +223 -0
- package/dist/ai/orchestrator/runner.js.map +1 -0
- package/dist/ai/orchestrator/session.d.ts +44 -0
- package/dist/ai/orchestrator/session.d.ts.map +1 -0
- package/dist/ai/orchestrator/session.js +64 -0
- package/dist/ai/orchestrator/session.js.map +1 -0
- package/dist/ai/orchestrator/types.d.ts +99 -0
- package/dist/ai/orchestrator/types.d.ts.map +1 -0
- package/dist/ai/orchestrator/types.js +8 -0
- package/dist/ai/orchestrator/types.js.map +1 -0
- package/dist/ai/probes/cache.d.ts +12 -0
- package/dist/ai/probes/cache.d.ts.map +1 -0
- package/dist/ai/probes/cache.js +46 -0
- package/dist/ai/probes/cache.js.map +1 -0
- package/dist/ai/tools/ask-ai-engine.d.ts +77 -0
- package/dist/ai/tools/ask-ai-engine.d.ts.map +1 -0
- package/dist/ai/tools/ask-ai-engine.js +253 -0
- package/dist/ai/tools/ask-ai-engine.js.map +1 -0
- package/dist/ai/tools/check-domain-crawler-access.d.ts +71 -0
- package/dist/ai/tools/check-domain-crawler-access.d.ts.map +1 -0
- package/dist/ai/tools/check-domain-crawler-access.js +76 -0
- package/dist/ai/tools/check-domain-crawler-access.js.map +1 -0
- package/dist/ai/tools/check-domain-llms-txt.d.ts +70 -0
- package/dist/ai/tools/check-domain-llms-txt.d.ts.map +1 -0
- package/dist/ai/tools/check-domain-llms-txt.js +75 -0
- package/dist/ai/tools/check-domain-llms-txt.js.map +1 -0
- package/dist/ai/tools/check-indexability.d.ts +58 -0
- package/dist/ai/tools/check-indexability.d.ts.map +1 -0
- package/dist/ai/tools/check-indexability.js +64 -0
- package/dist/ai/tools/check-indexability.js.map +1 -0
- package/dist/ai/tools/check-robots.d.ts +68 -0
- package/dist/ai/tools/check-robots.d.ts.map +1 -0
- package/dist/ai/tools/check-robots.js +90 -0
- package/dist/ai/tools/check-robots.js.map +1 -0
- package/dist/ai/tools/check-rule-answer-first.d.ts +54 -0
- package/dist/ai/tools/check-rule-answer-first.d.ts.map +1 -0
- package/dist/ai/tools/check-rule-answer-first.js +50 -0
- package/dist/ai/tools/check-rule-answer-first.js.map +1 -0
- package/dist/ai/tools/check-rule-canonical-consistency.d.ts +66 -0
- package/dist/ai/tools/check-rule-canonical-consistency.d.ts.map +1 -0
- package/dist/ai/tools/check-rule-canonical-consistency.js +51 -0
- package/dist/ai/tools/check-rule-canonical-consistency.js.map +1 -0
- package/dist/ai/tools/check-rule-citable-facts.d.ts +58 -0
- package/dist/ai/tools/check-rule-citable-facts.d.ts.map +1 -0
- package/dist/ai/tools/check-rule-citable-facts.js +41 -0
- package/dist/ai/tools/check-rule-citable-facts.js.map +1 -0
- package/dist/ai/tools/check-rule-content-modularity.d.ts +58 -0
- package/dist/ai/tools/check-rule-content-modularity.d.ts.map +1 -0
- package/dist/ai/tools/check-rule-content-modularity.js +45 -0
- package/dist/ai/tools/check-rule-content-modularity.js.map +1 -0
- package/dist/ai/tools/check-rule-faq-coverage.d.ts +54 -0
- package/dist/ai/tools/check-rule-faq-coverage.d.ts.map +1 -0
- package/dist/ai/tools/check-rule-faq-coverage.js +39 -0
- package/dist/ai/tools/check-rule-faq-coverage.js.map +1 -0
- package/dist/ai/tools/check-rule-freshness-signals.d.ts +54 -0
- package/dist/ai/tools/check-rule-freshness-signals.d.ts.map +1 -0
- package/dist/ai/tools/check-rule-freshness-signals.js +45 -0
- package/dist/ai/tools/check-rule-freshness-signals.js.map +1 -0
- package/dist/ai/tools/check-rule-json-ld-valid.d.ts +54 -0
- package/dist/ai/tools/check-rule-json-ld-valid.d.ts.map +1 -0
- package/dist/ai/tools/check-rule-json-ld-valid.js +44 -0
- package/dist/ai/tools/check-rule-json-ld-valid.js.map +1 -0
- package/dist/ai/tools/check-rule-missing-author.d.ts +54 -0
- package/dist/ai/tools/check-rule-missing-author.d.ts.map +1 -0
- package/dist/ai/tools/check-rule-missing-author.js +45 -0
- package/dist/ai/tools/check-rule-missing-author.js.map +1 -0
- package/dist/ai/tools/check-rule-near-duplicate.d.ts +82 -0
- package/dist/ai/tools/check-rule-near-duplicate.d.ts.map +1 -0
- package/dist/ai/tools/check-rule-near-duplicate.js +63 -0
- package/dist/ai/tools/check-rule-near-duplicate.js.map +1 -0
- package/dist/ai/tools/check-rule-required-fields.d.ts +50 -0
- package/dist/ai/tools/check-rule-required-fields.d.ts.map +1 -0
- package/dist/ai/tools/check-rule-required-fields.js +38 -0
- package/dist/ai/tools/check-rule-required-fields.js.map +1 -0
- package/dist/ai/tools/check-rule-schema-consistency.d.ts +54 -0
- package/dist/ai/tools/check-rule-schema-consistency.d.ts.map +1 -0
- package/dist/ai/tools/check-rule-schema-consistency.js +44 -0
- package/dist/ai/tools/check-rule-schema-consistency.js.map +1 -0
- package/dist/ai/tools/check-rule-summary-bait.d.ts +54 -0
- package/dist/ai/tools/check-rule-summary-bait.d.ts.map +1 -0
- package/dist/ai/tools/check-rule-summary-bait.js +39 -0
- package/dist/ai/tools/check-rule-summary-bait.js.map +1 -0
- package/dist/ai/tools/check-rule-thin-content.d.ts +66 -0
- package/dist/ai/tools/check-rule-thin-content.d.ts.map +1 -0
- package/dist/ai/tools/check-rule-thin-content.js +58 -0
- package/dist/ai/tools/check-rule-thin-content.js.map +1 -0
- package/dist/ai/tools/detect-templates.d.ts +60 -0
- package/dist/ai/tools/detect-templates.d.ts.map +1 -0
- package/dist/ai/tools/detect-templates.js +43 -0
- package/dist/ai/tools/detect-templates.js.map +1 -0
- package/dist/ai/tools/fetch-page.d.ts +70 -0
- package/dist/ai/tools/fetch-page.d.ts.map +1 -0
- package/dist/ai/tools/fetch-page.js +93 -0
- package/dist/ai/tools/fetch-page.js.map +1 -0
- package/dist/ai/tools/fetch-sitemap.d.ts +60 -0
- package/dist/ai/tools/fetch-sitemap.d.ts.map +1 -0
- package/dist/ai/tools/fetch-sitemap.js +116 -0
- package/dist/ai/tools/fetch-sitemap.js.map +1 -0
- package/dist/ai/tools/index.d.ts +1555 -0
- package/dist/ai/tools/index.d.ts.map +1 -0
- package/dist/ai/tools/index.js +119 -0
- package/dist/ai/tools/index.js.map +1 -0
- package/dist/ai/tools/parse-page.d.ts +94 -0
- package/dist/ai/tools/parse-page.d.ts.map +1 -0
- package/dist/ai/tools/parse-page.js +108 -0
- package/dist/ai/tools/parse-page.js.map +1 -0
- package/dist/ai/tools/query-serp.d.ts +113 -0
- package/dist/ai/tools/query-serp.d.ts.map +1 -0
- package/dist/ai/tools/query-serp.js +131 -0
- package/dist/ai/tools/query-serp.js.map +1 -0
- package/dist/ai/tools/sample-template.d.ts +67 -0
- package/dist/ai/tools/sample-template.d.ts.map +1 -0
- package/dist/ai/tools/sample-template.js +75 -0
- package/dist/ai/tools/sample-template.js.map +1 -0
- package/dist/ai/tools/types.d.ts +73 -0
- package/dist/ai/tools/types.d.ts.map +1 -0
- package/dist/ai/tools/types.js +64 -0
- package/dist/ai/tools/types.js.map +1 -0
- package/dist/ai/tools/validate-jsonld.d.ts +62 -0
- package/dist/ai/tools/validate-jsonld.d.ts.map +1 -0
- package/dist/ai/tools/validate-jsonld.js +84 -0
- package/dist/ai/tools/validate-jsonld.js.map +1 -0
- package/dist/auditor.d.ts +16 -1
- package/dist/auditor.d.ts.map +1 -1
- package/dist/auditor.js +862 -88
- package/dist/auditor.js.map +1 -1
- package/dist/backpressure.d.ts.map +1 -1
- package/dist/backpressure.js +10 -3
- package/dist/backpressure.js.map +1 -1
- package/dist/enrich-findings.d.ts.map +1 -1
- package/dist/enrich-findings.js +15 -1
- package/dist/enrich-findings.js.map +1 -1
- package/dist/formatters/bucket-findings.d.ts +43 -0
- package/dist/formatters/bucket-findings.d.ts.map +1 -0
- package/dist/formatters/bucket-findings.js +110 -0
- package/dist/formatters/bucket-findings.js.map +1 -0
- package/dist/formatters/console.d.ts.map +1 -1
- package/dist/formatters/console.js +116 -34
- package/dist/formatters/console.js.map +1 -1
- package/dist/formatters/fixplan.d.ts +13 -0
- package/dist/formatters/fixplan.d.ts.map +1 -0
- package/dist/formatters/fixplan.js +328 -0
- package/dist/formatters/fixplan.js.map +1 -0
- package/dist/formatters/html.d.ts.map +1 -1
- package/dist/formatters/html.js +27 -0
- package/dist/formatters/html.js.map +1 -1
- package/dist/formatters/index.d.ts +2 -0
- package/dist/formatters/index.d.ts.map +1 -1
- package/dist/formatters/index.js +1 -0
- package/dist/formatters/index.js.map +1 -1
- package/dist/formatters/markdown.d.ts.map +1 -1
- package/dist/formatters/markdown.js +97 -9
- package/dist/formatters/markdown.js.map +1 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/page-filter.d.ts +64 -6
- package/dist/page-filter.d.ts.map +1 -1
- package/dist/page-filter.js +124 -3
- package/dist/page-filter.js.map +1 -1
- package/dist/rule-references.d.ts.map +1 -1
- package/dist/rule-references.js +5 -0
- package/dist/rule-references.js.map +1 -1
- package/dist/rules/aeo/answer-first.d.ts.map +1 -1
- package/dist/rules/aeo/answer-first.js +17 -3
- package/dist/rules/aeo/answer-first.js.map +1 -1
- package/dist/rules/aeo/citable-facts.d.ts.map +1 -1
- package/dist/rules/aeo/citable-facts.js +12 -1
- package/dist/rules/aeo/citable-facts.js.map +1 -1
- package/dist/rules/aeo/content-modularity.d.ts.map +1 -1
- package/dist/rules/aeo/content-modularity.js +3 -0
- package/dist/rules/aeo/content-modularity.js.map +1 -1
- package/dist/rules/aeo/crawler-access.d.ts.map +1 -1
- package/dist/rules/aeo/crawler-access.js +6 -0
- package/dist/rules/aeo/crawler-access.js.map +1 -1
- package/dist/rules/aeo/faq-coverage.d.ts.map +1 -1
- package/dist/rules/aeo/faq-coverage.js +4 -0
- package/dist/rules/aeo/faq-coverage.js.map +1 -1
- package/dist/rules/aeo/freshness-signals.d.ts.map +1 -1
- package/dist/rules/aeo/freshness-signals.js +9 -2
- package/dist/rules/aeo/freshness-signals.js.map +1 -1
- package/dist/rules/aeo/llms-txt.d.ts.map +1 -1
- package/dist/rules/aeo/llms-txt.js +6 -1
- package/dist/rules/aeo/llms-txt.js.map +1 -1
- package/dist/rules/aeo/summary-bait.d.ts.map +1 -1
- package/dist/rules/aeo/summary-bait.js +5 -2
- package/dist/rules/aeo/summary-bait.js.map +1 -1
- package/dist/rules/content/heading-structure.d.ts +21 -0
- package/dist/rules/content/heading-structure.d.ts.map +1 -0
- package/dist/rules/content/heading-structure.js +56 -0
- package/dist/rules/content/heading-structure.js.map +1 -0
- package/dist/rules/content/image-alt-text.d.ts +18 -0
- package/dist/rules/content/image-alt-text.d.ts.map +1 -0
- package/dist/rules/content/image-alt-text.js +77 -0
- package/dist/rules/content/image-alt-text.js.map +1 -0
- package/dist/rules/content/missing-author.d.ts.map +1 -1
- package/dist/rules/content/missing-author.js +10 -2
- package/dist/rules/content/missing-author.js.map +1 -1
- package/dist/rules/content/title-uniqueness.d.ts +18 -0
- package/dist/rules/content/title-uniqueness.d.ts.map +1 -0
- package/dist/rules/content/title-uniqueness.js +70 -0
- package/dist/rules/content/title-uniqueness.js.map +1 -0
- package/dist/rules/links/host-section-divergence.d.ts +3 -0
- package/dist/rules/links/host-section-divergence.d.ts.map +1 -0
- package/dist/rules/links/host-section-divergence.js +158 -0
- package/dist/rules/links/host-section-divergence.js.map +1 -0
- package/dist/rules/links/link-depth.d.ts +12 -1
- package/dist/rules/links/link-depth.d.ts.map +1 -1
- package/dist/rules/links/link-depth.js +25 -12
- package/dist/rules/links/link-depth.js.map +1 -1
- package/dist/rules/scope.d.ts.map +1 -1
- package/dist/rules/scope.js +5 -0
- package/dist/rules/scope.js.map +1 -1
- package/dist/rules/spam/doorway-pattern.d.ts.map +1 -1
- package/dist/rules/spam/doorway-pattern.js +27 -4
- package/dist/rules/spam/doorway-pattern.js.map +1 -1
- package/dist/rules/spam/publication-velocity.d.ts +1 -1
- package/dist/rules/spam/publication-velocity.d.ts.map +1 -1
- package/dist/rules/spam/publication-velocity.js +9 -4
- package/dist/rules/spam/publication-velocity.js.map +1 -1
- package/dist/rules/spam/template-coverage.js +1 -1
- package/dist/rules/spam/template-coverage.js.map +1 -1
- package/dist/rules/spam/template-diversity.js +1 -1
- package/dist/rules/spam/template-diversity.js.map +1 -1
- package/dist/rules/spam/thin-content.d.ts.map +1 -1
- package/dist/rules/spam/thin-content.js +9 -1
- package/dist/rules/spam/thin-content.js.map +1 -1
- package/dist/rules/tech/hreflang-consistency.d.ts.map +1 -1
- package/dist/rules/tech/hreflang-consistency.js +33 -4
- package/dist/rules/tech/hreflang-consistency.js.map +1 -1
- package/dist/rules/tech/og-completeness.d.ts +11 -0
- package/dist/rules/tech/og-completeness.d.ts.map +1 -1
- package/dist/rules/tech/og-completeness.js +22 -23
- package/dist/rules/tech/og-completeness.js.map +1 -1
- package/dist/ruleset-version.d.ts +8 -0
- package/dist/ruleset-version.d.ts.map +1 -0
- package/dist/ruleset-version.js +8 -0
- package/dist/ruleset-version.js.map +1 -0
- package/dist/scrape-strategy.d.ts +42 -0
- package/dist/scrape-strategy.d.ts.map +1 -0
- package/dist/scrape-strategy.js +101 -0
- package/dist/scrape-strategy.js.map +1 -0
- package/dist/site-classifier.d.ts +1 -1
- package/dist/site-classifier.d.ts.map +1 -1
- package/dist/site-classifier.js +217 -0
- package/dist/site-classifier.js.map +1 -1
- package/dist/state.d.ts +36 -1
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +3 -1
- package/dist/state.js.map +1 -1
- package/dist/stratified-sample.d.ts +9 -1
- package/dist/stratified-sample.d.ts.map +1 -1
- package/dist/stratified-sample.js +23 -6
- package/dist/stratified-sample.js.map +1 -1
- package/dist/types.d.ts +179 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/url-normalize.d.ts.map +1 -1
- package/dist/url-normalize.js +13 -1
- package/dist/url-normalize.js.map +1 -1
- package/package.json +90 -90
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crawler-access.d.ts","sourceRoot":"","sources":["../../../src/rules/aeo/crawler-access.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD;;GAEG;AACH,eAAO,MAAM,mBAAmB,kIAStB,CAAC;AAEX;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAsC/E;AAED,6DAA6D;AAC7D,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,SAAS,GAAG,OAAO,CAGzE;AAED,MAAM,WAAW,oBAAoB;IACnC,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,gBAAgB,EAAE,MAAM,EACxB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"crawler-access.d.ts","sourceRoot":"","sources":["../../../src/rules/aeo/crawler-access.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD;;GAEG;AACH,eAAO,MAAM,mBAAmB,kIAStB,CAAC;AAEX;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAsC/E;AAED,6DAA6D;AAC7D,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,SAAS,GAAG,OAAO,CAGzE;AAED,MAAM,WAAW,oBAAoB;IACnC,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,gBAAgB,EAAE,MAAM,EACxB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,UAAU,EAAE,CAwDd"}
|
|
@@ -94,6 +94,9 @@ export function crawlerAccessRule(robotsTxtContent, options) {
|
|
|
94
94
|
findings.push({
|
|
95
95
|
ruleId: "aeo/crawler-access",
|
|
96
96
|
severity: "error",
|
|
97
|
+
// High: blocking ALL crawlers is either deliberate (clear intent) or a clear
|
|
98
|
+
// mistake — either way the finding is unambiguous.
|
|
99
|
+
confidence: "high",
|
|
97
100
|
message: `robots.txt blocks all ${crawlers.length} configured AI crawlers: ${blocked.join(", ")}.`,
|
|
98
101
|
fix: `Blocking every AI crawler makes your pages invisible to answer engines. ` +
|
|
99
102
|
`Sites uncited in AI Overviews lose ~68% of traffic vs ~12% for cited sites. ` +
|
|
@@ -105,6 +108,9 @@ export function crawlerAccessRule(robotsTxtContent, options) {
|
|
|
105
108
|
findings.push({
|
|
106
109
|
ruleId: "aeo/crawler-access",
|
|
107
110
|
severity: "warning",
|
|
111
|
+
// Medium: partial blocks are often deliberate (e.g. blocking Bytespider for
|
|
112
|
+
// policy reasons while leaving GPTBot allowed).
|
|
113
|
+
confidence: "medium",
|
|
108
114
|
message: `robots.txt blocks ${crawler}.`,
|
|
109
115
|
fix: `Remove the "Disallow: /" directive for User-agent: ${crawler} in your robots.txt. ` +
|
|
110
116
|
`Blocking ${crawler} removes your pages from its answer engine's citation pool. ` +
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crawler-access.js","sourceRoot":"","sources":["../../../src/rules/aeo/crawler-access.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"crawler-access.js","sourceRoot":"","sources":["../../../src/rules/aeo/crawler-access.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,QAAQ;IACR,cAAc;IACd,WAAW;IACX,eAAe;IACf,YAAY;IACZ,iBAAiB;IACjB,OAAO;IACP,mBAAmB;CACX,CAAC;AAEX;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAiB;IACtD,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC3C,IAAI,aAAa,GAAa,EAAE,CAAC;IACjC,IAAI,cAAc,GAAG,KAAK,CAAC;IAE3B,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QACxB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAE5C,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YACxE,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpB,8EAA8E;gBAC9E,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACzB,CAAC;iBAAM,CAAC;gBACN,aAAa,GAAG,CAAC,EAAE,CAAC,CAAC;gBACrB,cAAc,GAAG,KAAK,CAAC;YACzB,CAAC;YACD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;gBAAE,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACxC,SAAS;QACX,CAAC;QAED,IAAI,4CAA4C,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5D,cAAc,GAAG,IAAI,CAAC;QACxB,CAAC;QAED,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YAC3D,IAAI,CAAC,KAAK;gBAAE,SAAS;YACrB,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;gBAClC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBACjC,IAAI,MAAM;oBAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,iBAAiB,CAAC,QAA8B;IAC9D,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5B,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;AACvD,CAAC;AAOD;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,gBAAwB,EACxB,OAA8B;IAE9B,IAAI,CAAC,gBAAgB;QAAE,OAAO,EAAE,CAAC;IAEjC,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,mBAAmB,CAAC;IAC1D,MAAM,OAAO,GAAG,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;IACzD,MAAM,eAAe,GAAG,iBAAiB,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAE5D,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,0EAA0E;YAC1E,IAAI,eAAe;gBAAE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC3C,SAAS;QACX,CAAC;QACD,IAAI,iBAAiB,CAAC,QAAQ,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzD,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEpC,MAAM,QAAQ,GAAiB,EAAE,CAAC;IAClC,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,CAAC;IAEtD,IAAI,UAAU,EAAE,CAAC;QACf,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,oBAAoB;YAC5B,QAAQ,EAAE,OAAO;YACjB,6EAA6E;YAC7E,mDAAmD;YACnD,UAAU,EAAE,MAAM;YAClB,OAAO,EAAE,yBAAyB,QAAQ,CAAC,MAAM,4BAA4B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;YAClG,GAAG,EACD,0EAA0E;gBAC1E,8EAA8E;gBAC9E,oHAAoH;SACvH,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,OAAO,EAAE,CAAC;QAC9B,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,oBAAoB;YAC5B,QAAQ,EAAE,SAAS;YACnB,4EAA4E;YAC5E,gDAAgD;YAChD,UAAU,EAAE,QAAQ;YACpB,OAAO,EAAE,qBAAqB,OAAO,GAAG;YACxC,GAAG,EACD,sDAAsD,OAAO,uBAAuB;gBACpF,YAAY,OAAO,8DAA8D;gBACjF,gIAAgI;SACnI,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"faq-coverage.d.ts","sourceRoot":"","sources":["../../../src/rules/aeo/faq-coverage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE7D,MAAM,WAAW,kBAAkB;IACjC,gEAAgE;IAChE,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,mFAAmF;IACnF,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AA6CD,wBAAgB,eAAe,CAC7B,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"faq-coverage.d.ts","sourceRoot":"","sources":["../../../src/rules/aeo/faq-coverage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE7D,MAAM,WAAW,kBAAkB;IACjC,gEAAgE;IAChE,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,mFAAmF;IACnF,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AA6CD,wBAAgB,eAAe,CAC7B,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,UAAU,EAAE,CAkCd"}
|
|
@@ -59,6 +59,10 @@ export function faqCoverageRule(pages, options) {
|
|
|
59
59
|
findings.push({
|
|
60
60
|
ruleId: "aeo/faq-coverage",
|
|
61
61
|
severity: "info",
|
|
62
|
+
// Always medium: detecting FAQ-shape from H2 phrasing + URL is heuristic — some
|
|
63
|
+
// pages with question-style headings aren't actually FAQ content (e.g. blog
|
|
64
|
+
// posts titled "How we built X").
|
|
65
|
+
confidence: "medium",
|
|
62
66
|
message: `${page.url} contains FAQ-style content (${detail}) but no FAQPage/HowTo JSON-LD.`,
|
|
63
67
|
pageUrl: page.url,
|
|
64
68
|
fix: `Add FAQPage JSON-LD that mirrors the existing Q&A content. For pSEO templates, generate the ` +
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"faq-coverage.js","sourceRoot":"","sources":["../../../src/rules/aeo/faq-coverage.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"faq-coverage.js","sourceRoot":"","sources":["../../../src/rules/aeo/faq-coverage.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"freshness-signals.d.ts","sourceRoot":"","sources":["../../../src/rules/aeo/freshness-signals.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE7D,MAAM,WAAW,gBAAgB;IAC/B,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAkED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,CAAC,EAAE,gBAAgB,GACzB,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"freshness-signals.d.ts","sourceRoot":"","sources":["../../../src/rules/aeo/freshness-signals.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE7D,MAAM,WAAW,gBAAgB;IAC/B,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAkED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,CAAC,EAAE,gBAAgB,GACzB,UAAU,EAAE,CA+Dd"}
|
|
@@ -76,7 +76,11 @@ export function freshnessSignalsRule(pages, options) {
|
|
|
76
76
|
findings.push({
|
|
77
77
|
ruleId: "aeo/freshness-signals",
|
|
78
78
|
severity: "warning",
|
|
79
|
-
|
|
79
|
+
// Medium: a missing dateModified is often deliberate on evergreen pages (about,
|
|
80
|
+
// pricing, policy) where re-stamping would mislead readers.
|
|
81
|
+
confidence: "medium",
|
|
82
|
+
message: `${page.url} has no dateModified signal (no JSON-LD dateModified, no modification meta tag, no visible "Last updated"). ` +
|
|
83
|
+
`Evergreen pages may legitimately omit this — verify whether freshness signals matter for this page type.`,
|
|
80
84
|
pageUrl: page.url,
|
|
81
85
|
fix: `Add a freshness signal so AI engines know the page is current. Three recommended places: ` +
|
|
82
86
|
`(1) dateModified in your JSON-LD schema, ` +
|
|
@@ -96,7 +100,10 @@ export function freshnessSignalsRule(pages, options) {
|
|
|
96
100
|
findings.push({
|
|
97
101
|
ruleId: "aeo/freshness-signals",
|
|
98
102
|
severity: "info",
|
|
99
|
-
|
|
103
|
+
// Low: stale-by-clock isn't always stale-by-meaning. Some pages are evergreen by design.
|
|
104
|
+
confidence: "low",
|
|
105
|
+
message: `${page.url} was last updated ${ageDays} days ago (threshold: ${maxStaleDays}). ` +
|
|
106
|
+
`Some pages are evergreen by design — only act if this page's information changes over time.`,
|
|
100
107
|
pageUrl: page.url,
|
|
101
108
|
fix: `AI engines prioritize fresh content for citation. If the page is still accurate, ` +
|
|
102
109
|
`refresh the visible date and bump dateModified. If information has changed, update the body accordingly.`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"freshness-signals.js","sourceRoot":"","sources":["../../../src/rules/aeo/freshness-signals.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"freshness-signals.js","sourceRoot":"","sources":["../../../src/rules/aeo/freshness-signals.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llms-txt.d.ts","sourceRoot":"","sources":["../../../src/rules/aeo/llms-txt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,WAAW,cAAc;IAC7B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACvC;AAkBD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAgCpF;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,gBAAgB,GAAE,cAAc,GAAG,kBAAuB,GACzD,OAAO,CAAC,UAAU,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"llms-txt.d.ts","sourceRoot":"","sources":["../../../src/rules/aeo/llms-txt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,WAAW,cAAc;IAC7B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACvC;AAkBD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAgCpF;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,gBAAgB,GAAE,cAAc,GAAG,kBAAuB,GACzD,OAAO,CAAC,UAAU,EAAE,CAAC,CA2CvB"}
|
|
@@ -72,7 +72,11 @@ export async function llmsTxtRule(source, fetcherOrOptions = {}) {
|
|
|
72
72
|
return [{
|
|
73
73
|
ruleId: "aeo/llms-txt",
|
|
74
74
|
severity: "warning",
|
|
75
|
-
|
|
75
|
+
// Always low: llms.txt is a draft proposal with low industry adoption. Absence
|
|
76
|
+
// is not a defect, only a missed opportunity.
|
|
77
|
+
confidence: "low",
|
|
78
|
+
message: `No llms.txt found at ${llmsUrl}. ` +
|
|
79
|
+
`llms.txt is a draft standard with low adoption — absence isn't a defect, only a missed opportunity.`,
|
|
76
80
|
fix: `Create ${llmsUrl} to guide AI engines toward your most authoritative, citable content. ` +
|
|
77
81
|
`Start with an # H1 title, a blockquote summary, then ## sections listing your key pages as markdown links. ` +
|
|
78
82
|
`See https://llmstxt.org for the emerging convention.`,
|
|
@@ -83,6 +87,7 @@ export async function llmsTxtRule(source, fetcherOrOptions = {}) {
|
|
|
83
87
|
return [{
|
|
84
88
|
ruleId: "aeo/llms-txt",
|
|
85
89
|
severity: "warning",
|
|
90
|
+
confidence: "low",
|
|
86
91
|
message: `${llmsUrl} exists but is malformed: ${check.reason}.`,
|
|
87
92
|
fix: `Ensure ${llmsUrl} opens with an "# Site Name" H1, has at least one "## Section" heading, ` +
|
|
88
93
|
`and lists pages as "- [Title](https://...): short description". See https://llmstxt.org.`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llms-txt.js","sourceRoot":"","sources":["../../../src/rules/aeo/llms-txt.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"llms-txt.js","sourceRoot":"","sources":["../../../src/rules/aeo/llms-txt.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summary-bait.d.ts","sourceRoot":"","sources":["../../../src/rules/aeo/summary-bait.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGhF,MAAM,WAAW,kBAAkB;IACjC,kFAAkF;IAClF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oGAAoG;IACpG,gCAAgC,CAAC,EAAE,MAAM,CAAC;IAC1C,yFAAyF;IACzF,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AA8FD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,UAAU,EAAE,EACnB,cAAc,EAAE,iBAAiB,EAAE,EACnC,OAAO,CAAC,EAAE,kBAAkB,GAC3B,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"summary-bait.d.ts","sourceRoot":"","sources":["../../../src/rules/aeo/summary-bait.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGhF,MAAM,WAAW,kBAAkB;IACjC,kFAAkF;IAClF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oGAAoG;IACpG,gCAAgC,CAAC,EAAE,MAAM,CAAC;IAC1C,yFAAyF;IACzF,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AA8FD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,UAAU,EAAE,EACnB,cAAc,EAAE,iBAAiB,EAAE,EACnC,OAAO,CAAC,EAAE,kBAAkB,GAC3B,UAAU,EAAE,CA8Cd"}
|
|
@@ -126,11 +126,14 @@ export function summaryBaitRule(pages, entityPatterns, options) {
|
|
|
126
126
|
findings.push({
|
|
127
127
|
ruleId: "aeo/summary-bait",
|
|
128
128
|
severity: "error",
|
|
129
|
+
// Always medium: this is a forecast — we measure what AI MIGHT do (cite without
|
|
130
|
+
// sending the click), not what it WILL do for any given page.
|
|
131
|
+
confidence: "medium",
|
|
129
132
|
message: `${page.url} is optimized for summarization, not retention. ` +
|
|
130
133
|
`${Math.round(concentration * 100)}% of citable facts (${openerFacts.length}/${fullFacts.length}) ` +
|
|
131
134
|
`sit in the first ${openerWords} words, the page has no interactive / downloadable / gated value ` +
|
|
132
|
-
`below the fold, and the opener passes answer-first. AI Overviews
|
|
133
|
-
`without sending the click.`,
|
|
135
|
+
`below the fold, and the opener passes answer-first. AI Overviews are likely to cite this page ` +
|
|
136
|
+
`without sending the click — this is a forecast based on page shape, not a guarantee.`,
|
|
134
137
|
pageUrl: page.url,
|
|
135
138
|
fix: `Redistribute value across the page so the full answer requires scrolling: ` +
|
|
136
139
|
`(1) move the interactive element — calculator, checklist, comparison tool, generator, ` +
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summary-bait.js","sourceRoot":"","sources":["../../../src/rules/aeo/summary-bait.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"summary-bait.js","sourceRoot":"","sources":["../../../src/rules/aeo/summary-bait.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ParsedPage, RuleResult } from "../../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* content/heading-structure — three checks:
|
|
4
|
+
* 1. Pages missing an <h1> entirely (severity: error — almost always a
|
|
5
|
+
* template bug or a misconfigured CMS).
|
|
6
|
+
* 2. Pages with multiple <h1> elements (severity: warning — accessibility
|
|
7
|
+
* anti-pattern + ambiguous primary topic signal).
|
|
8
|
+
* 3. Long pages (>600 words) with no <h2> sub-structure (severity: info
|
|
9
|
+
* — readability / Featured Snippet eligibility issue).
|
|
10
|
+
*
|
|
11
|
+
* Kept separate from `content/title-uniqueness` because heading hierarchy
|
|
12
|
+
* is a different signal (Google reads H1+H2 to understand topic
|
|
13
|
+
* structure) and has a different fix path.
|
|
14
|
+
*
|
|
15
|
+
* The 2026-05-03 blind-spot audit named the previously-phantom
|
|
16
|
+
* `content/heading-uniqueness` as a gap; this is the corrected rule
|
|
17
|
+
* (heading STRUCTURE, not uniqueness — duplicate H1s across catalog
|
|
18
|
+
* pages aren't actually a problem the way duplicate titles are).
|
|
19
|
+
*/
|
|
20
|
+
export declare function headingStructureRule(pages: ParsedPage[]): RuleResult[];
|
|
21
|
+
//# sourceMappingURL=heading-structure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heading-structure.d.ts","sourceRoot":"","sources":["../../../src/rules/content/heading-structure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAI7D;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAsCtE"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const MIN_BODY_WORDS_FOR_H2_REQUIREMENT = 600;
|
|
2
|
+
/**
|
|
3
|
+
* content/heading-structure — three checks:
|
|
4
|
+
* 1. Pages missing an <h1> entirely (severity: error — almost always a
|
|
5
|
+
* template bug or a misconfigured CMS).
|
|
6
|
+
* 2. Pages with multiple <h1> elements (severity: warning — accessibility
|
|
7
|
+
* anti-pattern + ambiguous primary topic signal).
|
|
8
|
+
* 3. Long pages (>600 words) with no <h2> sub-structure (severity: info
|
|
9
|
+
* — readability / Featured Snippet eligibility issue).
|
|
10
|
+
*
|
|
11
|
+
* Kept separate from `content/title-uniqueness` because heading hierarchy
|
|
12
|
+
* is a different signal (Google reads H1+H2 to understand topic
|
|
13
|
+
* structure) and has a different fix path.
|
|
14
|
+
*
|
|
15
|
+
* The 2026-05-03 blind-spot audit named the previously-phantom
|
|
16
|
+
* `content/heading-uniqueness` as a gap; this is the corrected rule
|
|
17
|
+
* (heading STRUCTURE, not uniqueness — duplicate H1s across catalog
|
|
18
|
+
* pages aren't actually a problem the way duplicate titles are).
|
|
19
|
+
*/
|
|
20
|
+
export function headingStructureRule(pages) {
|
|
21
|
+
const findings = [];
|
|
22
|
+
for (const page of pages) {
|
|
23
|
+
const h1Count = page.headings.h1.length;
|
|
24
|
+
const h2Count = page.headings.h2.length;
|
|
25
|
+
const wordCount = (page.contentText ?? "").trim().split(/\s+/).filter(Boolean).length;
|
|
26
|
+
if (h1Count === 0) {
|
|
27
|
+
findings.push({
|
|
28
|
+
ruleId: "content/heading-structure",
|
|
29
|
+
severity: "error",
|
|
30
|
+
message: `${page.url} has no <h1> element.`,
|
|
31
|
+
pageUrl: page.url,
|
|
32
|
+
fix: "Add a single <h1> that names the page's primary topic. Google uses H1 to disambiguate when the title tag is unclear.",
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
else if (h1Count > 1) {
|
|
36
|
+
findings.push({
|
|
37
|
+
ruleId: "content/heading-structure",
|
|
38
|
+
severity: "warning",
|
|
39
|
+
message: `${page.url} has ${h1Count} <h1> elements.`,
|
|
40
|
+
pageUrl: page.url,
|
|
41
|
+
fix: "Use a single <h1> per page. Demote the others to <h2>. HTML5 'document outline' tolerates multiple H1s in theory, but every accessibility checker and several SEO heuristics still expect one.",
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
if (wordCount >= MIN_BODY_WORDS_FOR_H2_REQUIREMENT && h2Count === 0) {
|
|
45
|
+
findings.push({
|
|
46
|
+
ruleId: "content/heading-structure",
|
|
47
|
+
severity: "info",
|
|
48
|
+
message: `${page.url} has ${wordCount} words but no <h2> sub-structure.`,
|
|
49
|
+
pageUrl: page.url,
|
|
50
|
+
fix: "Break long pages into sections with <h2> sub-headings. Sub-headings drive Featured Snippet eligibility and improve scannability.",
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return findings;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=heading-structure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heading-structure.js","sourceRoot":"","sources":["../../../src/rules/content/heading-structure.ts"],"names":[],"mappings":"AAEA,MAAM,iCAAiC,GAAG,GAAG,CAAC;AAE9C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAmB;IACtD,MAAM,QAAQ,GAAiB,EAAE,CAAC;IAElC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC;QACxC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC;QACxC,MAAM,SAAS,GAAG,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;QAEtF,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;YAClB,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,2BAA2B;gBACnC,QAAQ,EAAE,OAAO;gBACjB,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,uBAAuB;gBAC3C,OAAO,EAAE,IAAI,CAAC,GAAG;gBACjB,GAAG,EAAE,sHAAsH;aAC5H,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;YACvB,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,2BAA2B;gBACnC,QAAQ,EAAE,SAAS;gBACnB,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,QAAQ,OAAO,iBAAiB;gBACpD,OAAO,EAAE,IAAI,CAAC,GAAG;gBACjB,GAAG,EAAE,gMAAgM;aACtM,CAAC,CAAC;QACL,CAAC;QAED,IAAI,SAAS,IAAI,iCAAiC,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;YACpE,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,2BAA2B;gBACnC,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,QAAQ,SAAS,mCAAmC;gBACxE,OAAO,EAAE,IAAI,CAAC,GAAG;gBACjB,GAAG,EAAE,kIAAkI;aACxI,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ParsedPage, RuleResult } from "../../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* content/image-alt-text — checks every <img> tag in the parsed HTML for
|
|
4
|
+
* alt-text presence. Decorative images (`role="presentation"`,
|
|
5
|
+
* `aria-hidden="true"`, or empty `alt=""` explicitly) are skipped — the
|
|
6
|
+
* rule fires only on content-bearing images that lack ANY alt attribute.
|
|
7
|
+
*
|
|
8
|
+
* Reports per-page count (one finding per page summarising N missing).
|
|
9
|
+
* The templated-image case (every catalog page has the same 200
|
|
10
|
+
* placeholder thumbnails) doesn't need 200 line-items in the report;
|
|
11
|
+
* one summary line per page is enough — sample sources truncated to 3.
|
|
12
|
+
*
|
|
13
|
+
* The 2026-05-03 blind-spot audit named this as a tier-1 gap that hits
|
|
14
|
+
* every templated pSEO site (template iterates over a data source, the
|
|
15
|
+
* image-alt slot is left at the literal default).
|
|
16
|
+
*/
|
|
17
|
+
export declare function imageAltTextRule(pages: ParsedPage[]): RuleResult[];
|
|
18
|
+
//# sourceMappingURL=image-alt-text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-alt-text.d.ts","sourceRoot":"","sources":["../../../src/rules/content/image-alt-text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AA8B7D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAsClE"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
const IMG_RE = /<img\b[^>]*>/gi;
|
|
2
|
+
const ALT_RE = /\balt\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]*))/i;
|
|
3
|
+
const ROLE_RE = /\brole\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]*))/i;
|
|
4
|
+
const SRC_RE = /\bsrc\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]*))/i;
|
|
5
|
+
const ARIA_HIDDEN_RE = /\baria-hidden\s*=\s*(?:"true"|'true'|true)/i;
|
|
6
|
+
function parseImg(tag) {
|
|
7
|
+
const altMatch = tag.match(ALT_RE);
|
|
8
|
+
const roleMatch = tag.match(ROLE_RE);
|
|
9
|
+
const srcMatch = tag.match(SRC_RE);
|
|
10
|
+
const altText = altMatch ? (altMatch[1] ?? altMatch[2] ?? altMatch[3] ?? "") : "";
|
|
11
|
+
return {
|
|
12
|
+
hasAltAttr: altMatch !== null,
|
|
13
|
+
altText: altText.trim(),
|
|
14
|
+
role: roleMatch ? ((roleMatch[1] ?? roleMatch[2] ?? roleMatch[3] ?? "")).toLowerCase() : "",
|
|
15
|
+
src: srcMatch ? (srcMatch[1] ?? srcMatch[2] ?? srcMatch[3] ?? "") : "",
|
|
16
|
+
ariaHidden: ARIA_HIDDEN_RE.test(tag),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* content/image-alt-text — checks every <img> tag in the parsed HTML for
|
|
21
|
+
* alt-text presence. Decorative images (`role="presentation"`,
|
|
22
|
+
* `aria-hidden="true"`, or empty `alt=""` explicitly) are skipped — the
|
|
23
|
+
* rule fires only on content-bearing images that lack ANY alt attribute.
|
|
24
|
+
*
|
|
25
|
+
* Reports per-page count (one finding per page summarising N missing).
|
|
26
|
+
* The templated-image case (every catalog page has the same 200
|
|
27
|
+
* placeholder thumbnails) doesn't need 200 line-items in the report;
|
|
28
|
+
* one summary line per page is enough — sample sources truncated to 3.
|
|
29
|
+
*
|
|
30
|
+
* The 2026-05-03 blind-spot audit named this as a tier-1 gap that hits
|
|
31
|
+
* every templated pSEO site (template iterates over a data source, the
|
|
32
|
+
* image-alt slot is left at the literal default).
|
|
33
|
+
*/
|
|
34
|
+
export function imageAltTextRule(pages) {
|
|
35
|
+
const findings = [];
|
|
36
|
+
for (const page of pages) {
|
|
37
|
+
const html = page.html ?? "";
|
|
38
|
+
if (!html)
|
|
39
|
+
continue;
|
|
40
|
+
const tags = html.match(IMG_RE) ?? [];
|
|
41
|
+
if (tags.length === 0)
|
|
42
|
+
continue;
|
|
43
|
+
let missing = 0;
|
|
44
|
+
let total = 0;
|
|
45
|
+
const samples = [];
|
|
46
|
+
for (const tag of tags) {
|
|
47
|
+
const a = parseImg(tag);
|
|
48
|
+
// Skip decorative images that are explicitly marked as such.
|
|
49
|
+
if (a.role === "presentation" || a.role === "none")
|
|
50
|
+
continue;
|
|
51
|
+
if (a.ariaHidden)
|
|
52
|
+
continue;
|
|
53
|
+
// Empty `alt=""` is a deliberate signal that the image is decorative —
|
|
54
|
+
// we accept it. The rule fires only when the alt attribute is MISSING.
|
|
55
|
+
total += 1;
|
|
56
|
+
if (!a.hasAltAttr) {
|
|
57
|
+
missing += 1;
|
|
58
|
+
if (samples.length < 3 && a.src)
|
|
59
|
+
samples.push(a.src);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (missing === 0)
|
|
63
|
+
continue;
|
|
64
|
+
const ratio = missing / Math.max(1, total);
|
|
65
|
+
const severity = ratio >= 0.5 ? "warning" : "info";
|
|
66
|
+
const sampleSuffix = samples.length > 0 ? ` (e.g. ${samples.join(", ")})` : "";
|
|
67
|
+
findings.push({
|
|
68
|
+
ruleId: "content/image-alt-text",
|
|
69
|
+
severity,
|
|
70
|
+
message: `${page.url}: ${missing} of ${total} content-bearing <img> tags have no alt attribute${sampleSuffix}.`,
|
|
71
|
+
pageUrl: page.url,
|
|
72
|
+
fix: "Add an `alt` attribute to every content-bearing <img>. For purely-decorative images, use `alt=\"\"` explicitly (or set `aria-hidden=\"true\"`) so the rule recognises them as intentional. Templated catalog images should pull alt text from the same data source as the rest of the page (the integration name, the city, the currency pair) — never leave the alt slot at a static default.",
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
return findings;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=image-alt-text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-alt-text.js","sourceRoot":"","sources":["../../../src/rules/content/image-alt-text.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"missing-author.d.ts","sourceRoot":"","sources":["../../../src/rules/content/missing-author.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"missing-author.d.ts","sourceRoot":"","sources":["../../../src/rules/content/missing-author.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAczE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CA0BnE"}
|
|
@@ -2,6 +2,11 @@ function hasAuthorSignal(page) {
|
|
|
2
2
|
const { metaAuthor, schemaAuthor, bylineElement, relAuthorLink } = page.authorSignals;
|
|
3
3
|
return metaAuthor !== "" || schemaAuthor || bylineElement || relAuthorLink;
|
|
4
4
|
}
|
|
5
|
+
// Always medium: technical docs, product pages, marketing pages, and pricing pages
|
|
6
|
+
// legitimately ship without bylines. Author attribution matters most on blog/news
|
|
7
|
+
// content where E-E-A-T is the primary trust signal.
|
|
8
|
+
const AUTHOR_CONFIDENCE = "medium";
|
|
9
|
+
const AUTHOR_CONTEXT_NOTE = " Author bylines matter most on blog/news content; technical docs and product pages legitimately omit them.";
|
|
5
10
|
export function missingAuthorRule(pages) {
|
|
6
11
|
const missing = pages.filter((page) => !hasAuthorSignal(page));
|
|
7
12
|
if (missing.length === 0)
|
|
@@ -10,7 +15,9 @@ export function missingAuthorRule(pages) {
|
|
|
10
15
|
return [{
|
|
11
16
|
ruleId: "content/missing-author",
|
|
12
17
|
severity: "warning",
|
|
13
|
-
|
|
18
|
+
confidence: AUTHOR_CONFIDENCE,
|
|
19
|
+
message: `All ${missing.length} pages have no author signals (meta author, schema author, byline, or rel="author" link). ` +
|
|
20
|
+
`This is a site-wide E-E-A-T risk.${AUTHOR_CONTEXT_NOTE}`,
|
|
14
21
|
fix: `Add author attribution site-wide: <meta name="author" content="Name">, a visible byline, or author data in your JSON-LD schema.`,
|
|
15
22
|
relatedUrls: missing.map((p) => p.url).sort()
|
|
16
23
|
}];
|
|
@@ -18,7 +25,8 @@ export function missingAuthorRule(pages) {
|
|
|
18
25
|
return missing.map((page) => ({
|
|
19
26
|
ruleId: "content/missing-author",
|
|
20
27
|
severity: "warning",
|
|
21
|
-
|
|
28
|
+
confidence: AUTHOR_CONFIDENCE,
|
|
29
|
+
message: `${page.url} has no author signals. This is an E-E-A-T risk.${AUTHOR_CONTEXT_NOTE}`,
|
|
22
30
|
pageUrl: page.url,
|
|
23
31
|
fix: `Add author attribution: <meta name="author" content="Name">, a visible byline, or author data in your JSON-LD schema.`
|
|
24
32
|
}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"missing-author.js","sourceRoot":"","sources":["../../../src/rules/content/missing-author.ts"],"names":[],"mappings":"AAEA,SAAS,eAAe,CAAC,IAAgB;IACvC,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC;IACtF,OAAO,UAAU,KAAK,EAAE,IAAI,YAAY,IAAI,aAAa,IAAI,aAAa,CAAC;AAC7E,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAmB;IACnD,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;IAE/D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEpC,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxD,OAAO,CAAC;gBACN,MAAM,EAAE,wBAAwB;gBAChC,QAAQ,EAAE,SAAS;gBACnB,
|
|
1
|
+
{"version":3,"file":"missing-author.js","sourceRoot":"","sources":["../../../src/rules/content/missing-author.ts"],"names":[],"mappings":"AAEA,SAAS,eAAe,CAAC,IAAgB;IACvC,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC;IACtF,OAAO,UAAU,KAAK,EAAE,IAAI,YAAY,IAAI,aAAa,IAAI,aAAa,CAAC;AAC7E,CAAC;AAED,mFAAmF;AACnF,kFAAkF;AAClF,qDAAqD;AACrD,MAAM,iBAAiB,GAAe,QAAQ,CAAC;AAC/C,MAAM,mBAAmB,GACvB,4GAA4G,CAAC;AAE/G,MAAM,UAAU,iBAAiB,CAAC,KAAmB;IACnD,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;IAE/D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEpC,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxD,OAAO,CAAC;gBACN,MAAM,EAAE,wBAAwB;gBAChC,QAAQ,EAAE,SAAS;gBACnB,UAAU,EAAE,iBAAiB;gBAC7B,OAAO,EACL,OAAO,OAAO,CAAC,MAAM,4FAA4F;oBACjH,oCAAoC,mBAAmB,EAAE;gBAC3D,GAAG,EAAE,iIAAiI;gBACtI,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE;aAC9C,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC5B,MAAM,EAAE,wBAAwB;QAChC,QAAQ,EAAE,SAAkB;QAC5B,UAAU,EAAE,iBAAiB;QAC7B,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,mDAAmD,mBAAmB,EAAE;QAC5F,OAAO,EAAE,IAAI,CAAC,GAAG;QACjB,GAAG,EAAE,uHAAuH;KAC7H,CAAC,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ParsedPage, RuleResult } from "../../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* content/title-uniqueness — three checks rolled into one rule:
|
|
4
|
+
* 1. Pages missing a title element (or with empty/whitespace-only titles).
|
|
5
|
+
* 2. Pages whose title is so short that Google fills it from H1 / link
|
|
6
|
+
* text instead.
|
|
7
|
+
* 3. Two or more pages sharing the EXACT raw title (templated catalog
|
|
8
|
+
* titles like "Slack to Google Sheets" vs "Slack to Airtable" are
|
|
9
|
+
* DIFFERENT raw titles, so this rule does NOT entity-mask — that
|
|
10
|
+
* would false-positive on every catalog directory in existence).
|
|
11
|
+
*
|
|
12
|
+
* Title is the highest-impact on-page signal Google ranks against. The
|
|
13
|
+
* 2026-05-03 blind-spot audit surfaced it as a tier-1 gap that the
|
|
14
|
+
* existing `content/meta-uniqueness` rule didn't cover (titles ≠ meta
|
|
15
|
+
* descriptions).
|
|
16
|
+
*/
|
|
17
|
+
export declare function titleUniquenessRule(pages: ParsedPage[]): RuleResult[];
|
|
18
|
+
//# sourceMappingURL=title-uniqueness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"title-uniqueness.d.ts","sourceRoot":"","sources":["../../../src/rules/content/title-uniqueness.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAM7D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAoDrE"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
const MIN_TITLE_LENGTH = 10;
|
|
2
|
+
const MAX_TITLE_LENGTH = 70;
|
|
3
|
+
const TRUNCATION_RISK_LENGTH = 60;
|
|
4
|
+
/**
|
|
5
|
+
* content/title-uniqueness — three checks rolled into one rule:
|
|
6
|
+
* 1. Pages missing a title element (or with empty/whitespace-only titles).
|
|
7
|
+
* 2. Pages whose title is so short that Google fills it from H1 / link
|
|
8
|
+
* text instead.
|
|
9
|
+
* 3. Two or more pages sharing the EXACT raw title (templated catalog
|
|
10
|
+
* titles like "Slack to Google Sheets" vs "Slack to Airtable" are
|
|
11
|
+
* DIFFERENT raw titles, so this rule does NOT entity-mask — that
|
|
12
|
+
* would false-positive on every catalog directory in existence).
|
|
13
|
+
*
|
|
14
|
+
* Title is the highest-impact on-page signal Google ranks against. The
|
|
15
|
+
* 2026-05-03 blind-spot audit surfaced it as a tier-1 gap that the
|
|
16
|
+
* existing `content/meta-uniqueness` rule didn't cover (titles ≠ meta
|
|
17
|
+
* descriptions).
|
|
18
|
+
*/
|
|
19
|
+
export function titleUniquenessRule(pages) {
|
|
20
|
+
const findings = [];
|
|
21
|
+
const titleToPages = new Map();
|
|
22
|
+
for (const page of pages) {
|
|
23
|
+
const title = (page.title ?? "").trim();
|
|
24
|
+
if (title.length === 0) {
|
|
25
|
+
findings.push({
|
|
26
|
+
ruleId: "content/title-uniqueness",
|
|
27
|
+
severity: "error",
|
|
28
|
+
message: `${page.url} has no <title> element (or its title is empty).`,
|
|
29
|
+
pageUrl: page.url,
|
|
30
|
+
fix: "Add a non-empty <title> element to the page <head>. Title is Google's strongest on-page ranking signal.",
|
|
31
|
+
});
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (title.length < MIN_TITLE_LENGTH) {
|
|
35
|
+
findings.push({
|
|
36
|
+
ruleId: "content/title-uniqueness",
|
|
37
|
+
severity: "warning",
|
|
38
|
+
message: `${page.url} has a very short title (${title.length} chars: "${title}").`,
|
|
39
|
+
pageUrl: page.url,
|
|
40
|
+
fix: `Expand the title to ${MIN_TITLE_LENGTH}-${TRUNCATION_RISK_LENGTH} characters. Short titles get rewritten by Google from H1 / anchor text.`,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
else if (title.length > MAX_TITLE_LENGTH) {
|
|
44
|
+
findings.push({
|
|
45
|
+
ruleId: "content/title-uniqueness",
|
|
46
|
+
severity: "info",
|
|
47
|
+
message: `${page.url} has a long title (${title.length} chars). Google truncates around ${TRUNCATION_RISK_LENGTH} chars in SERPs.`,
|
|
48
|
+
pageUrl: page.url,
|
|
49
|
+
fix: `Tighten the title to under ${TRUNCATION_RISK_LENGTH} characters so the full text shows in the SERP snippet.`,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
const arr = titleToPages.get(title) ?? [];
|
|
53
|
+
arr.push(page);
|
|
54
|
+
titleToPages.set(title, arr);
|
|
55
|
+
}
|
|
56
|
+
for (const [title, group] of titleToPages.entries()) {
|
|
57
|
+
if (group.length < 2)
|
|
58
|
+
continue;
|
|
59
|
+
findings.push({
|
|
60
|
+
ruleId: "content/title-uniqueness",
|
|
61
|
+
severity: "error",
|
|
62
|
+
message: `${group.length} pages share the exact title "${title}".`,
|
|
63
|
+
pageUrl: group[0].url,
|
|
64
|
+
relatedUrls: group.slice(1, 6).map((p) => p.url),
|
|
65
|
+
fix: "Each page needs a unique title that reflects its specific content. Templated titles must include the per-record entity (e.g. include the integration name, currency pair, or city in the title).",
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return findings;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=title-uniqueness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"title-uniqueness.js","sourceRoot":"","sources":["../../../src/rules/content/title-uniqueness.ts"],"names":[],"mappings":"AAEA,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAC5B,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAC5B,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAElC;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAmB;IACrD,MAAM,QAAQ,GAAiB,EAAE,CAAC;IAClC,MAAM,YAAY,GAAG,IAAI,GAAG,EAAwB,CAAC;IAErD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACxC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,0BAA0B;gBAClC,QAAQ,EAAE,OAAO;gBACjB,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,kDAAkD;gBACtE,OAAO,EAAE,IAAI,CAAC,GAAG;gBACjB,GAAG,EAAE,yGAAyG;aAC/G,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,GAAG,gBAAgB,EAAE,CAAC;YACpC,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,0BAA0B;gBAClC,QAAQ,EAAE,SAAS;gBACnB,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,4BAA4B,KAAK,CAAC,MAAM,YAAY,KAAK,KAAK;gBAClF,OAAO,EAAE,IAAI,CAAC,GAAG;gBACjB,GAAG,EAAE,uBAAuB,gBAAgB,IAAI,sBAAsB,0EAA0E;aACjJ,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,GAAG,gBAAgB,EAAE,CAAC;YAC3C,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,0BAA0B;gBAClC,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,sBAAsB,KAAK,CAAC,MAAM,oCAAoC,sBAAsB,kBAAkB;gBAClI,OAAO,EAAE,IAAI,CAAC,GAAG;gBACjB,GAAG,EAAE,8BAA8B,sBAAsB,yDAAyD;aACnH,CAAC,CAAC;QACL,CAAC;QAED,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAC1C,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACf,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,YAAY,CAAC,OAAO,EAAE,EAAE,CAAC;QACpD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,SAAS;QAC/B,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,0BAA0B;YAClC,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,GAAG,KAAK,CAAC,MAAM,iCAAiC,KAAK,IAAI;YAClE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG;YACrB,WAAW,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;YAChD,GAAG,EAAE,kMAAkM;SACxM,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-section-divergence.d.ts","sourceRoot":"","sources":["../../../src/rules/links/host-section-divergence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AA2D7D,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,UAAU,EAAE,EACnB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,GAClC,UAAU,EAAE,CA8Gd"}
|