recker 1.0.43 → 1.0.44
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 +47 -0
- package/dist/bin/recker-linux-x64 +0 -0
- package/dist/bin/recker-macos-x64 +0 -0
- package/dist/bin/recker-win-x64.exe +0 -0
- package/dist/bin/rek.cjs +85152 -100207
- package/dist/browser/ai/adaptive-timeout.d.ts +50 -0
- package/dist/browser/ai/adaptive-timeout.js +208 -0
- package/dist/browser/ai/client.d.ts +22 -0
- package/dist/browser/ai/client.js +294 -0
- package/dist/browser/ai/index.d.ts +14 -0
- package/dist/browser/ai/index.js +11 -0
- package/dist/browser/ai/providers/anthropic.d.ts +63 -0
- package/dist/browser/ai/providers/anthropic.js +370 -0
- package/dist/browser/ai/providers/base.d.ts +48 -0
- package/dist/browser/ai/providers/base.js +150 -0
- package/dist/browser/ai/providers/google.d.ts +59 -0
- package/dist/browser/ai/providers/google.js +305 -0
- package/dist/browser/ai/providers/ollama.d.ts +44 -0
- package/dist/browser/ai/providers/ollama.js +240 -0
- package/dist/browser/ai/providers/openai.d.ts +64 -0
- package/dist/browser/ai/providers/openai.js +298 -0
- package/dist/browser/ai/rate-limiter.d.ts +43 -0
- package/dist/browser/ai/rate-limiter.js +215 -0
- package/dist/browser/ai/vector/index.d.ts +2 -0
- package/dist/browser/ai/vector/index.js +2 -0
- package/dist/browser/ai/vector/similarity.d.ts +2 -0
- package/dist/browser/ai/vector/similarity.js +27 -0
- package/dist/browser/ai/vector/store.d.ts +27 -0
- package/dist/browser/ai/vector/store.js +82 -0
- package/dist/browser/browser/cache.d.ts +2 -40
- package/dist/browser/browser/cache.js +2 -199
- package/dist/browser/browser/index.d.ts +8 -0
- package/dist/browser/browser/index.js +8 -0
- package/dist/browser/browser/recker.d.ts +8 -1
- package/dist/browser/browser/recker.js +8 -2
- package/dist/browser/cache/indexed-db.d.ts +10 -0
- package/dist/browser/cache/indexed-db.js +88 -0
- package/dist/browser/cache/service-worker-cache.d.ts +18 -0
- package/dist/browser/cache/service-worker-cache.js +103 -0
- package/dist/browser/cache.d.ts +2 -40
- package/dist/browser/cache.js +2 -199
- package/dist/browser/constants/user-agents.d.ts +7 -0
- package/dist/browser/constants/user-agents.js +7 -0
- package/dist/browser/core/client.d.ts +2 -0
- package/dist/browser/core/client.js +19 -1
- package/dist/browser/index.d.ts +8 -0
- package/dist/browser/index.js +8 -0
- package/dist/browser/plugins/har-recorder.d.ts +40 -0
- package/dist/browser/plugins/har-recorder.js +120 -0
- package/dist/browser/plugins/network-simulation.d.ts +7 -0
- package/dist/browser/plugins/network-simulation.js +13 -0
- package/dist/browser/presets/android.d.ts +2 -0
- package/dist/browser/presets/android.js +16 -0
- package/dist/browser/presets/anthropic.d.ts +8 -0
- package/dist/browser/presets/anthropic.js +27 -0
- package/dist/browser/presets/aws.d.ts +19 -0
- package/dist/browser/presets/aws.js +68 -0
- package/dist/browser/presets/azure-openai.d.ts +10 -0
- package/dist/browser/presets/azure-openai.js +35 -0
- package/dist/browser/presets/azure.d.ts +41 -0
- package/dist/browser/presets/azure.js +104 -0
- package/dist/browser/presets/chaturbate.d.ts +2 -0
- package/dist/browser/presets/chaturbate.js +17 -0
- package/dist/browser/presets/cloudflare.d.ts +12 -0
- package/dist/browser/presets/cloudflare.js +39 -0
- package/dist/browser/presets/cohere.d.ts +7 -0
- package/dist/browser/presets/cohere.js +22 -0
- package/dist/browser/presets/deepseek.d.ts +7 -0
- package/dist/browser/presets/deepseek.js +22 -0
- package/dist/browser/presets/digitalocean.d.ts +5 -0
- package/dist/browser/presets/digitalocean.js +16 -0
- package/dist/browser/presets/discord.d.ts +6 -0
- package/dist/browser/presets/discord.js +17 -0
- package/dist/browser/presets/elevenlabs.d.ts +6 -0
- package/dist/browser/presets/elevenlabs.js +20 -0
- package/dist/browser/presets/enhancers.d.ts +20 -0
- package/dist/browser/presets/enhancers.js +85 -0
- package/dist/browser/presets/fireworks.d.ts +7 -0
- package/dist/browser/presets/fireworks.js +22 -0
- package/dist/browser/presets/gcp.d.ts +34 -0
- package/dist/browser/presets/gcp.js +91 -0
- package/dist/browser/presets/gemini.d.ts +7 -0
- package/dist/browser/presets/gemini.js +23 -0
- package/dist/browser/presets/github.d.ts +6 -0
- package/dist/browser/presets/github.js +17 -0
- package/dist/browser/presets/gitlab.d.ts +6 -0
- package/dist/browser/presets/gitlab.js +16 -0
- package/dist/browser/presets/groq.d.ts +7 -0
- package/dist/browser/presets/groq.js +22 -0
- package/dist/browser/presets/hubspot.d.ts +9 -0
- package/dist/browser/presets/hubspot.js +28 -0
- package/dist/browser/presets/huggingface.d.ts +7 -0
- package/dist/browser/presets/huggingface.js +23 -0
- package/dist/browser/presets/index.d.ts +47 -0
- package/dist/browser/presets/index.js +47 -0
- package/dist/browser/presets/ios.d.ts +2 -0
- package/dist/browser/presets/ios.js +13 -0
- package/dist/browser/presets/linear.d.ts +5 -0
- package/dist/browser/presets/linear.js +16 -0
- package/dist/browser/presets/mailgun.d.ts +7 -0
- package/dist/browser/presets/mailgun.js +20 -0
- package/dist/browser/presets/meta.d.ts +10 -0
- package/dist/browser/presets/meta.js +33 -0
- package/dist/browser/presets/mistral.d.ts +7 -0
- package/dist/browser/presets/mistral.js +22 -0
- package/dist/browser/presets/notion.d.ts +6 -0
- package/dist/browser/presets/notion.js +17 -0
- package/dist/browser/presets/openai.d.ts +9 -0
- package/dist/browser/presets/openai.js +30 -0
- package/dist/browser/presets/oracle.d.ts +19 -0
- package/dist/browser/presets/oracle.js +117 -0
- package/dist/browser/presets/perplexity.d.ts +7 -0
- package/dist/browser/presets/perplexity.js +22 -0
- package/dist/browser/presets/pinecone.d.ts +8 -0
- package/dist/browser/presets/pinecone.js +42 -0
- package/dist/browser/presets/registry.d.ts +23 -0
- package/dist/browser/presets/registry.js +519 -0
- package/dist/browser/presets/replicate.d.ts +7 -0
- package/dist/browser/presets/replicate.js +23 -0
- package/dist/browser/presets/sendgrid.d.ts +6 -0
- package/dist/browser/presets/sendgrid.js +20 -0
- package/dist/browser/presets/sentry.d.ts +11 -0
- package/dist/browser/presets/sentry.js +48 -0
- package/dist/browser/presets/sinch.d.ts +9 -0
- package/dist/browser/presets/sinch.js +39 -0
- package/dist/browser/presets/slack.d.ts +5 -0
- package/dist/browser/presets/slack.js +16 -0
- package/dist/browser/presets/square.d.ts +10 -0
- package/dist/browser/presets/square.js +33 -0
- package/dist/browser/presets/stripe.d.ts +7 -0
- package/dist/browser/presets/stripe.js +23 -0
- package/dist/browser/presets/supabase.d.ts +6 -0
- package/dist/browser/presets/supabase.js +18 -0
- package/dist/browser/presets/tiktok.d.ts +10 -0
- package/dist/browser/presets/tiktok.js +38 -0
- package/dist/browser/presets/together.d.ts +7 -0
- package/dist/browser/presets/together.js +22 -0
- package/dist/browser/presets/twilio.d.ts +6 -0
- package/dist/browser/presets/twilio.js +17 -0
- package/dist/browser/presets/vercel.d.ts +6 -0
- package/dist/browser/presets/vercel.js +23 -0
- package/dist/browser/presets/vultr.d.ts +5 -0
- package/dist/browser/presets/vultr.js +16 -0
- package/dist/browser/presets/xai.d.ts +8 -0
- package/dist/browser/presets/xai.js +23 -0
- package/dist/browser/presets/youtube.d.ts +5 -0
- package/dist/browser/presets/youtube.js +20 -0
- package/dist/browser/recker.d.ts +8 -1
- package/dist/browser/recker.js +8 -2
- package/dist/browser/scrape/document.d.ts +5 -4
- package/dist/browser/scrape/document.js +89 -76
- package/dist/browser/scrape/element.d.ts +10 -8
- package/dist/browser/scrape/element.js +295 -81
- package/dist/browser/scrape/extractors.d.ts +11 -11
- package/dist/browser/scrape/extractors.js +145 -113
- package/dist/browser/scrape/parser/back.d.ts +1 -0
- package/dist/browser/scrape/parser/back.js +3 -0
- package/dist/browser/scrape/parser/index.d.ts +20 -0
- package/dist/browser/scrape/parser/index.js +19 -0
- package/dist/browser/scrape/parser/matcher.d.ts +30 -0
- package/dist/browser/scrape/parser/matcher.js +99 -0
- package/dist/browser/scrape/parser/nodes/comment.d.ts +12 -0
- package/dist/browser/scrape/parser/nodes/comment.js +21 -0
- package/dist/browser/scrape/parser/nodes/html.d.ts +110 -0
- package/dist/browser/scrape/parser/nodes/html.js +978 -0
- package/dist/browser/scrape/parser/nodes/node.d.ts +18 -0
- package/dist/browser/scrape/parser/nodes/node.js +31 -0
- package/dist/browser/scrape/parser/nodes/text.d.ts +14 -0
- package/dist/browser/scrape/parser/nodes/text.js +30 -0
- package/dist/browser/scrape/parser/nodes/type.d.ts +6 -0
- package/dist/browser/scrape/parser/nodes/type.js +7 -0
- package/dist/browser/scrape/parser/parse.d.ts +1 -0
- package/dist/browser/scrape/parser/parse.js +1 -0
- package/dist/browser/scrape/parser/valid.d.ts +2 -0
- package/dist/browser/scrape/parser/valid.js +5 -0
- package/dist/browser/scrape/parser/void-tag.d.ts +7 -0
- package/dist/browser/scrape/parser/void-tag.js +43 -0
- package/dist/browser/scrape/types.d.ts +7 -0
- package/dist/browser/seo/analyzer.d.ts +59 -0
- package/dist/browser/seo/analyzer.js +1399 -0
- package/dist/browser/seo/keywords.d.ts +16 -0
- package/dist/browser/seo/keywords.js +55 -0
- package/dist/browser/seo/rules/accessibility.d.ts +2 -0
- package/dist/browser/seo/rules/accessibility.js +733 -0
- package/dist/browser/seo/rules/ai-search.d.ts +2 -0
- package/dist/browser/seo/rules/ai-search.js +436 -0
- package/dist/browser/seo/rules/analytics.d.ts +2 -0
- package/dist/browser/seo/rules/analytics.js +306 -0
- package/dist/browser/seo/rules/best-practices.d.ts +2 -0
- package/dist/browser/seo/rules/best-practices.js +195 -0
- package/dist/browser/seo/rules/canonical.d.ts +12 -0
- package/dist/browser/seo/rules/canonical.js +270 -0
- package/dist/browser/seo/rules/content.d.ts +2 -0
- package/dist/browser/seo/rules/content.js +522 -0
- package/dist/browser/seo/rules/crawl.d.ts +2 -0
- package/dist/browser/seo/rules/crawl.js +435 -0
- package/dist/browser/seo/rules/cwv.d.ts +2 -0
- package/dist/browser/seo/rules/cwv.js +248 -0
- package/dist/browser/seo/rules/ecommerce.d.ts +2 -0
- package/dist/browser/seo/rules/ecommerce.js +312 -0
- package/dist/browser/seo/rules/i18n.d.ts +2 -0
- package/dist/browser/seo/rules/i18n.js +288 -0
- package/dist/browser/seo/rules/images.d.ts +2 -0
- package/dist/browser/seo/rules/images.js +255 -0
- package/dist/browser/seo/rules/index.d.ts +52 -0
- package/dist/browser/seo/rules/index.js +159 -0
- package/dist/browser/seo/rules/internal-linking.d.ts +2 -0
- package/dist/browser/seo/rules/internal-linking.js +394 -0
- package/dist/browser/seo/rules/links.d.ts +2 -0
- package/dist/browser/seo/rules/links.js +498 -0
- package/dist/browser/seo/rules/local.d.ts +2 -0
- package/dist/browser/seo/rules/local.js +289 -0
- package/dist/browser/seo/rules/meta.d.ts +2 -0
- package/dist/browser/seo/rules/meta.js +805 -0
- package/dist/browser/seo/rules/mobile.d.ts +2 -0
- package/dist/browser/seo/rules/mobile.js +161 -0
- package/dist/browser/seo/rules/performance.d.ts +2 -0
- package/dist/browser/seo/rules/performance.js +738 -0
- package/dist/browser/seo/rules/pwa.d.ts +2 -0
- package/dist/browser/seo/rules/pwa.js +299 -0
- package/dist/browser/seo/rules/readability.d.ts +2 -0
- package/dist/browser/seo/rules/readability.js +264 -0
- package/dist/browser/seo/rules/redirects.d.ts +16 -0
- package/dist/browser/seo/rules/redirects.js +199 -0
- package/dist/browser/seo/rules/resources.d.ts +2 -0
- package/dist/browser/seo/rules/resources.js +390 -0
- package/dist/browser/seo/rules/schema.d.ts +2 -0
- package/dist/browser/seo/rules/schema.js +379 -0
- package/dist/browser/seo/rules/security.d.ts +2 -0
- package/dist/browser/seo/rules/security.js +877 -0
- package/dist/browser/seo/rules/social.d.ts +2 -0
- package/dist/browser/seo/rules/social.js +603 -0
- package/dist/browser/seo/rules/structural.d.ts +2 -0
- package/dist/browser/seo/rules/structural.js +223 -0
- package/dist/browser/seo/rules/technical-advanced.d.ts +10 -0
- package/dist/browser/seo/rules/technical-advanced.js +289 -0
- package/dist/browser/seo/rules/technical.d.ts +2 -0
- package/dist/browser/seo/rules/technical.js +480 -0
- package/dist/browser/seo/rules/thresholds.d.ts +196 -0
- package/dist/browser/seo/rules/thresholds.js +118 -0
- package/dist/browser/seo/rules/types.d.ts +498 -0
- package/dist/browser/seo/rules/types.js +11 -0
- package/dist/browser/seo/types.d.ts +211 -0
- package/dist/browser/seo/types.js +1 -0
- package/dist/browser/transport/curl.d.ts +4 -0
- package/dist/browser/transport/curl.js +101 -0
- package/dist/browser/transport/undici.js +1 -2
- package/dist/browser/transport/worker.d.ts +18 -0
- package/dist/browser/transport/worker.js +278 -0
- package/dist/browser/types/index.d.ts +4 -1
- package/dist/browser/utils/binary-manager.d.ts +4 -0
- package/dist/browser/utils/binary-manager.js +72 -0
- package/dist/browser/utils/user-agent.js +2 -13
- package/dist/cache/indexed-db.d.ts +10 -0
- package/dist/cache/indexed-db.js +88 -0
- package/dist/cache/service-worker-cache.d.ts +18 -0
- package/dist/cache/service-worker-cache.js +103 -0
- package/dist/cli/commands/ai.d.ts +2 -0
- package/dist/cli/commands/ai.js +162 -0
- package/dist/cli/commands/bench.d.ts +2 -0
- package/dist/cli/commands/bench.js +51 -0
- package/dist/cli/commands/dns.d.ts +2 -0
- package/dist/cli/commands/dns.js +295 -0
- package/dist/cli/commands/har.d.ts +2 -0
- package/dist/cli/commands/har.js +171 -0
- package/dist/cli/commands/hls.d.ts +2 -0
- package/dist/cli/commands/hls.js +192 -0
- package/dist/cli/commands/network.d.ts +2 -0
- package/dist/cli/commands/network.js +288 -0
- package/dist/cli/commands/protocols.d.ts +2 -0
- package/dist/cli/commands/protocols.js +344 -0
- package/dist/cli/commands/scrape.d.ts +2 -0
- package/dist/cli/commands/scrape.js +176 -0
- package/dist/cli/commands/security.d.ts +2 -0
- package/dist/cli/commands/security.js +57 -0
- package/dist/cli/commands/seo.d.ts +2 -0
- package/dist/cli/commands/seo.js +125 -0
- package/dist/cli/commands/serve.d.ts +2 -0
- package/dist/cli/commands/serve.js +531 -0
- package/dist/cli/commands/spider.d.ts +3 -0
- package/dist/cli/commands/spider.js +456 -0
- package/dist/cli/commands/utils.d.ts +2 -0
- package/dist/cli/commands/utils.js +176 -0
- package/dist/cli/commands/vector.d.ts +2 -0
- package/dist/cli/commands/vector.js +158 -0
- package/dist/cli/handler.d.ts +2 -2
- package/dist/cli/handler.js +6 -6
- package/dist/cli/helpers.d.ts +7 -0
- package/dist/cli/helpers.js +128 -0
- package/dist/cli/index.js +96 -5228
- package/dist/cli/parser/help.d.ts +2 -0
- package/dist/cli/parser/help.js +52 -0
- package/dist/cli/parser/index.d.ts +3 -0
- package/dist/cli/parser/index.js +3 -0
- package/dist/cli/parser/parser.d.ts +4 -0
- package/dist/cli/parser/parser.js +146 -0
- package/dist/cli/parser/types.d.ts +41 -0
- package/dist/cli/parser/types.js +1 -0
- package/dist/cli/presets.d.ts +1 -1
- package/dist/cli/presets.js +1 -1
- package/dist/cli/router.d.ts +36 -0
- package/dist/cli/router.js +195 -0
- package/dist/cli/tui/ai-chat.js +1 -1
- package/dist/cli/tui/commands/context.d.ts +9 -0
- package/dist/cli/tui/commands/context.js +1 -0
- package/dist/cli/tui/commands/dns.d.ts +10 -0
- package/dist/cli/tui/commands/dns.js +461 -0
- package/dist/cli/tui/commands/hls.d.ts +2 -0
- package/dist/cli/tui/commands/hls.js +162 -0
- package/dist/cli/tui/commands/ip.d.ts +2 -0
- package/dist/cli/tui/commands/ip.js +45 -0
- package/dist/cli/tui/commands/network.d.ts +3 -0
- package/dist/cli/tui/commands/network.js +81 -0
- package/dist/cli/tui/commands/protocols.d.ts +6 -0
- package/dist/cli/tui/commands/protocols.js +531 -0
- package/dist/cli/tui/commands/security.d.ts +2 -0
- package/dist/cli/tui/commands/security.js +48 -0
- package/dist/cli/tui/commands/seo.d.ts +2 -0
- package/dist/cli/tui/commands/seo.js +74 -0
- package/dist/cli/tui/context.d.ts +12 -0
- package/dist/cli/tui/context.js +1 -0
- package/dist/cli/tui/shell.d.ts +11 -20
- package/dist/cli/tui/shell.js +216 -1873
- package/dist/constants/user-agents.d.ts +7 -0
- package/dist/constants/user-agents.js +7 -0
- package/dist/core/client.d.ts +2 -0
- package/dist/core/client.js +19 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/mcp/cli.js +2 -3
- package/dist/mcp/data/embeddings.json +1 -1
- package/dist/mcp/tools/network.js +298 -158
- package/dist/plugins/har-player.d.ts +23 -0
- package/dist/plugins/har-player.js +49 -0
- package/dist/plugins/har-recorder.d.ts +37 -3
- package/dist/plugins/har-recorder.js +116 -63
- package/dist/plugins/network-simulation.d.ts +7 -0
- package/dist/plugins/network-simulation.js +13 -0
- package/dist/presets/android.d.ts +2 -0
- package/dist/presets/android.js +16 -0
- package/dist/presets/chaturbate.d.ts +2 -0
- package/dist/presets/chaturbate.js +17 -0
- package/dist/presets/elevenlabs.d.ts +6 -0
- package/dist/presets/elevenlabs.js +20 -0
- package/dist/presets/enhancers.d.ts +20 -0
- package/dist/presets/enhancers.js +85 -0
- package/dist/presets/hubspot.d.ts +9 -0
- package/dist/presets/hubspot.js +28 -0
- package/dist/presets/index.d.ts +10 -0
- package/dist/presets/index.js +10 -0
- package/dist/presets/ios.d.ts +2 -0
- package/dist/presets/ios.js +13 -0
- package/dist/presets/pinecone.d.ts +8 -0
- package/dist/presets/pinecone.js +42 -0
- package/dist/presets/registry.js +60 -0
- package/dist/presets/sendgrid.d.ts +6 -0
- package/dist/presets/sendgrid.js +20 -0
- package/dist/presets/sentry.d.ts +11 -0
- package/dist/presets/sentry.js +48 -0
- package/dist/presets/square.d.ts +10 -0
- package/dist/presets/square.js +33 -0
- package/dist/recker.d.ts +3 -0
- package/dist/recker.js +4 -0
- package/dist/scrape/document.d.ts +5 -4
- package/dist/scrape/document.js +89 -76
- package/dist/scrape/element.d.ts +10 -8
- package/dist/scrape/element.js +295 -81
- package/dist/scrape/extractors.d.ts +11 -11
- package/dist/scrape/extractors.js +145 -113
- package/dist/scrape/index.d.ts +2 -0
- package/dist/scrape/index.js +1 -0
- package/dist/scrape/parser/back.d.ts +1 -0
- package/dist/scrape/parser/back.js +3 -0
- package/dist/scrape/parser/index.d.ts +20 -0
- package/dist/scrape/parser/index.js +19 -0
- package/dist/scrape/parser/matcher.d.ts +30 -0
- package/dist/scrape/parser/matcher.js +99 -0
- package/dist/scrape/parser/nodes/comment.d.ts +12 -0
- package/dist/scrape/parser/nodes/comment.js +21 -0
- package/dist/scrape/parser/nodes/html.d.ts +110 -0
- package/dist/scrape/parser/nodes/html.js +978 -0
- package/dist/scrape/parser/nodes/node.d.ts +18 -0
- package/dist/scrape/parser/nodes/node.js +31 -0
- package/dist/scrape/parser/nodes/text.d.ts +14 -0
- package/dist/scrape/parser/nodes/text.js +30 -0
- package/dist/scrape/parser/nodes/type.d.ts +6 -0
- package/dist/scrape/parser/nodes/type.js +7 -0
- package/dist/scrape/parser/parse.d.ts +1 -0
- package/dist/scrape/parser/parse.js +1 -0
- package/dist/scrape/parser/valid.d.ts +2 -0
- package/dist/scrape/parser/valid.js +5 -0
- package/dist/scrape/parser/void-tag.d.ts +7 -0
- package/dist/scrape/parser/void-tag.js +43 -0
- package/dist/scrape/spider.d.ts +19 -0
- package/dist/scrape/spider.js +28 -3
- package/dist/scrape/types.d.ts +7 -0
- package/dist/seo/analyzer.d.ts +15 -5
- package/dist/seo/analyzer.js +636 -175
- package/dist/seo/formatter.d.ts +16 -0
- package/dist/seo/formatter.js +228 -0
- package/dist/seo/index.d.ts +2 -0
- package/dist/seo/index.js +1 -0
- package/dist/seo/keywords.d.ts +16 -0
- package/dist/seo/keywords.js +55 -0
- package/dist/seo/rules/accessibility.js +96 -57
- package/dist/seo/rules/ai-search.js +44 -31
- package/dist/seo/rules/analytics.d.ts +2 -0
- package/dist/seo/rules/analytics.js +306 -0
- package/dist/seo/rules/best-practices.js +21 -14
- package/dist/seo/rules/canonical.js +53 -32
- package/dist/seo/rules/content.js +317 -31
- package/dist/seo/rules/crawl.js +55 -40
- package/dist/seo/rules/cwv.js +21 -15
- package/dist/seo/rules/ecommerce.js +82 -22
- package/dist/seo/rules/i18n.js +75 -36
- package/dist/seo/rules/images.js +109 -30
- package/dist/seo/rules/index.js +2 -0
- package/dist/seo/rules/internal-linking.js +58 -39
- package/dist/seo/rules/links.js +79 -52
- package/dist/seo/rules/local.js +49 -25
- package/dist/seo/rules/meta.js +339 -81
- package/dist/seo/rules/mobile.js +112 -2
- package/dist/seo/rules/performance.js +434 -66
- package/dist/seo/rules/pwa.js +36 -39
- package/dist/seo/rules/readability.js +31 -22
- package/dist/seo/rules/redirects.js +21 -15
- package/dist/seo/rules/resources.js +59 -42
- package/dist/seo/rules/schema.js +333 -8
- package/dist/seo/rules/security.js +142 -80
- package/dist/seo/rules/social.js +277 -47
- package/dist/seo/rules/structural.js +87 -19
- package/dist/seo/rules/technical-advanced.js +30 -24
- package/dist/seo/rules/technical.js +243 -42
- package/dist/seo/rules/types.d.ts +53 -1
- package/dist/seo/seo-spider.d.ts +22 -0
- package/dist/seo/seo-spider.js +77 -13
- package/dist/seo/types.d.ts +8 -1
- package/dist/seo/validators/llms-txt.js +19 -0
- package/dist/seo/validators/rss.d.ts +11 -0
- package/dist/seo/validators/rss.js +93 -0
- package/dist/seo/validators/sitemap.js +36 -26
- package/dist/transport/curl.d.ts +4 -0
- package/dist/transport/curl.js +101 -0
- package/dist/transport/udp.js +0 -1
- package/dist/transport/undici.js +1 -2
- package/dist/transport/worker.d.ts +18 -0
- package/dist/transport/worker.js +278 -0
- package/dist/types/index.d.ts +4 -1
- package/dist/utils/binary-manager.d.ts +4 -0
- package/dist/utils/binary-manager.js +72 -0
- package/dist/utils/optional-require.d.ts +7 -8
- package/dist/utils/optional-require.js +2 -21
- package/dist/utils/upload.d.ts +6 -0
- package/dist/utils/upload.js +11 -0
- package/dist/utils/user-agent.js +2 -13
- package/dist/version.js +1 -1
- package/package.json +12 -6
- package/dist/browser/utils/optional-require.d.ts +0 -19
- package/dist/browser/utils/optional-require.js +0 -105
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
import { createResult } from './types.js';
|
|
2
|
+
export const schemaRules = [
|
|
3
|
+
{
|
|
4
|
+
id: 'json-ld-exists',
|
|
5
|
+
name: 'Structured Data',
|
|
6
|
+
category: 'structured-data',
|
|
7
|
+
severity: 'info',
|
|
8
|
+
description: 'Page should have JSON-LD structured data',
|
|
9
|
+
check: (ctx) => {
|
|
10
|
+
if (ctx.jsonLdCount === undefined) {
|
|
11
|
+
return createResult({ id: 'json-ld-exists', name: 'Structured Data', category: 'structured-data', severity: 'info' }, 'info', 'Not applicable (JSON-LD count data unavailable)', { recommendation: 'This rule checks for JSON-LD structured data to enable rich snippets in search results' });
|
|
12
|
+
}
|
|
13
|
+
if (ctx.jsonLdCount === 0) {
|
|
14
|
+
return createResult({ id: 'json-ld-exists', name: 'Structured Data', category: 'structured-data', severity: 'info' }, 'info', 'No JSON-LD structured data found', {
|
|
15
|
+
recommendation: 'Add Schema.org structured data to enable rich snippets in search results.',
|
|
16
|
+
evidence: {
|
|
17
|
+
found: 'No structured data',
|
|
18
|
+
expected: 'At least one JSON-LD block with Schema.org markup',
|
|
19
|
+
impact: 'Pages with structured data can get rich results like star ratings, prices, FAQs, and more.',
|
|
20
|
+
example: '<script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","name":"Page Title"}</script>',
|
|
21
|
+
learnMore: 'https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data'
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
const types = ctx.jsonLdTypes?.join(', ') || 'unknown';
|
|
26
|
+
return createResult({ id: 'json-ld-exists', name: 'Structured Data', category: 'structured-data', severity: 'info' }, 'pass', `${ctx.jsonLdCount} JSON-LD block(s) found: ${types}`, { value: types });
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: 'schema-standard-types',
|
|
31
|
+
name: 'Schema Types',
|
|
32
|
+
category: 'structured-data',
|
|
33
|
+
severity: 'info',
|
|
34
|
+
description: 'Use standard Schema.org types',
|
|
35
|
+
check: (ctx) => {
|
|
36
|
+
if (!ctx.jsonLdTypes || ctx.jsonLdTypes.length === 0) {
|
|
37
|
+
return createResult({ id: 'schema-standard-types', name: 'Schema Types', category: 'structured-data', severity: 'info' }, 'info', 'Not applicable (no JSON-LD types detected)', { recommendation: 'This rule checks for standard Schema.org types when structured data is present' });
|
|
38
|
+
}
|
|
39
|
+
const recommended = [
|
|
40
|
+
'WebSite', 'WebPage', 'Article', 'Product', 'BreadcrumbList',
|
|
41
|
+
'Organization', 'Person', 'LocalBusiness', 'Recipe', 'Event',
|
|
42
|
+
'JobPosting', 'FAQPage', 'HowTo', 'VideoObject',
|
|
43
|
+
'SoftwareApplication', 'Review'
|
|
44
|
+
];
|
|
45
|
+
const hasStandard = ctx.jsonLdTypes.some(t => recommended.includes(t));
|
|
46
|
+
if (!hasStandard) {
|
|
47
|
+
return createResult({ id: 'schema-standard-types', name: 'Schema Types', category: 'structured-data', severity: 'info' }, 'info', 'Using uncommon Schema.org types', { value: ctx.jsonLdTypes.join(', '), recommendation: `Consider using standard types like ${recommended.slice(0, 3).join(', ')}` });
|
|
48
|
+
}
|
|
49
|
+
return createResult({ id: 'schema-standard-types', name: 'Schema Types', category: 'structured-data', severity: 'info' }, 'pass', 'Using standard Schema.org types', { value: ctx.jsonLdTypes.join(', ') });
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
id: 'breadcrumbs-presence',
|
|
54
|
+
name: 'Breadcrumbs Presence',
|
|
55
|
+
category: 'structured-data',
|
|
56
|
+
severity: 'info',
|
|
57
|
+
description: 'Breadcrumbs improve navigation and SEO structure',
|
|
58
|
+
check: (ctx) => {
|
|
59
|
+
if (!ctx.hasBreadcrumbsHtml && !ctx.hasBreadcrumbsSchema) {
|
|
60
|
+
return createResult({ id: 'breadcrumbs-presence', name: 'Breadcrumbs Presence', category: 'structured-data', severity: 'info' }, 'info', 'No breadcrumbs found (HTML or Schema.org)', {
|
|
61
|
+
recommendation: 'Add breadcrumbs to help users understand their location in your site hierarchy.',
|
|
62
|
+
evidence: {
|
|
63
|
+
found: 'No breadcrumbs',
|
|
64
|
+
expected: 'HTML breadcrumb navigation with BreadcrumbList schema',
|
|
65
|
+
impact: 'Breadcrumbs appear in Google search results and improve user navigation.',
|
|
66
|
+
example: '<script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://example.com/"},{"@type":"ListItem","position":2,"name":"Category","item":"https://example.com/category/"}]}</script>',
|
|
67
|
+
learnMore: 'https://developers.google.com/search/docs/appearance/structured-data/breadcrumb'
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (ctx.hasBreadcrumbsHtml && ctx.hasBreadcrumbsSchema) {
|
|
72
|
+
return createResult({ id: 'breadcrumbs-presence', name: 'Breadcrumbs Presence', category: 'structured-data', severity: 'info' }, 'pass', 'Breadcrumbs found (HTML + Schema.org)', { value: 'HTML + BreadcrumbList schema' });
|
|
73
|
+
}
|
|
74
|
+
if (ctx.hasBreadcrumbsSchema) {
|
|
75
|
+
return createResult({ id: 'breadcrumbs-presence', name: 'Breadcrumbs Presence', category: 'structured-data', severity: 'info' }, 'pass', 'Breadcrumbs schema found', { value: 'BreadcrumbList schema' });
|
|
76
|
+
}
|
|
77
|
+
return createResult({ id: 'breadcrumbs-presence', name: 'Breadcrumbs Presence', category: 'structured-data', severity: 'info' }, 'info', 'HTML breadcrumbs found, consider adding Schema.org markup', {
|
|
78
|
+
recommendation: 'Add BreadcrumbList schema for better search visibility.',
|
|
79
|
+
evidence: {
|
|
80
|
+
found: 'HTML breadcrumbs only',
|
|
81
|
+
expected: 'BreadcrumbList schema markup',
|
|
82
|
+
impact: 'Schema.org breadcrumbs enable rich results in search.',
|
|
83
|
+
learnMore: 'https://developers.google.com/search/docs/appearance/structured-data/breadcrumb'
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
id: 'schema-organization',
|
|
90
|
+
name: 'Organization Schema',
|
|
91
|
+
category: 'structured-data',
|
|
92
|
+
severity: 'info',
|
|
93
|
+
description: 'Organization schema helps search engines understand your business identity',
|
|
94
|
+
check: (ctx) => {
|
|
95
|
+
if (!ctx.jsonLdTypes) {
|
|
96
|
+
return createResult({ id: 'schema-organization', name: 'Organization Schema', category: 'structured-data', severity: 'info' }, 'info', 'Not applicable (JSON-LD types data unavailable)', { recommendation: 'This rule checks for Organization schema when structured data is present' });
|
|
97
|
+
}
|
|
98
|
+
const hasOrg = ctx.jsonLdTypes.some(t => ['Organization', 'LocalBusiness', 'Corporation', 'NGO', 'EducationalOrganization',
|
|
99
|
+
'GovernmentOrganization', 'MedicalOrganization', 'SportsOrganization'].includes(t));
|
|
100
|
+
if (!hasOrg) {
|
|
101
|
+
if (ctx.isStartPage || ctx.url?.endsWith('/') || ctx.hasAboutPageLink) {
|
|
102
|
+
return createResult({ id: 'schema-organization', name: 'Organization Schema', category: 'structured-data', severity: 'info' }, 'info', 'No Organization schema found', {
|
|
103
|
+
recommendation: 'Add Organization schema to establish your brand identity with search engines.',
|
|
104
|
+
evidence: {
|
|
105
|
+
found: 'No Organization-type schema',
|
|
106
|
+
expected: 'Organization, LocalBusiness, or similar schema',
|
|
107
|
+
impact: 'Organization schema can trigger Knowledge Panel and improves E-E-A-T signals.',
|
|
108
|
+
example: '{"@context":"https://schema.org","@type":"Organization","name":"Company Name","url":"https://example.com","logo":"https://example.com/logo.png","sameAs":["https://twitter.com/company","https://linkedin.com/company/name"]}',
|
|
109
|
+
learnMore: 'https://developers.google.com/search/docs/appearance/structured-data/organization'
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
return createResult({ id: 'schema-organization', name: 'Organization Schema', category: 'structured-data', severity: 'info' }, 'info', 'Not applicable (not a homepage or about page)', { recommendation: 'Organization schema is typically used on homepage or about pages' });
|
|
114
|
+
}
|
|
115
|
+
return createResult({ id: 'schema-organization', name: 'Organization Schema', category: 'structured-data', severity: 'info' }, 'pass', 'Organization schema found', { value: ctx.jsonLdTypes.find(t => t.includes('Organization') || t === 'LocalBusiness' || t === 'Corporation') });
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
id: 'schema-faq',
|
|
120
|
+
name: 'FAQ Schema',
|
|
121
|
+
category: 'structured-data',
|
|
122
|
+
severity: 'info',
|
|
123
|
+
description: 'FAQ pages should have FAQPage schema for rich results',
|
|
124
|
+
check: (ctx) => {
|
|
125
|
+
if (!ctx.jsonLdTypes) {
|
|
126
|
+
return createResult({ id: 'schema-faq', name: 'FAQ Schema', category: 'structured-data', severity: 'info' }, 'info', 'Not applicable (JSON-LD types data unavailable)', { recommendation: 'This rule checks for FAQPage schema when FAQ content is detected' });
|
|
127
|
+
}
|
|
128
|
+
const hasFaq = ctx.jsonLdTypes.includes('FAQPage');
|
|
129
|
+
const hasQuestionHeadings = ctx.hasQuestionHeadings;
|
|
130
|
+
const faqCount = ctx.faqCount || 0;
|
|
131
|
+
if (!hasFaq && (hasQuestionHeadings || faqCount >= 3)) {
|
|
132
|
+
return createResult({ id: 'schema-faq', name: 'FAQ Schema', category: 'structured-data', severity: 'info' }, 'info', 'FAQ content detected but no FAQPage schema found', {
|
|
133
|
+
recommendation: 'Add FAQPage schema to get FAQ rich results in search.',
|
|
134
|
+
evidence: {
|
|
135
|
+
found: `${faqCount} FAQ-like items detected`,
|
|
136
|
+
expected: 'FAQPage schema with Question/Answer items',
|
|
137
|
+
impact: 'FAQ rich results take more SERP space and increase CTR by up to 30%.',
|
|
138
|
+
example: '{"@context":"https://schema.org","@type":"FAQPage","mainEntity":[{"@type":"Question","name":"Question text?","acceptedAnswer":{"@type":"Answer","text":"Answer text"}}]}',
|
|
139
|
+
learnMore: 'https://developers.google.com/search/docs/appearance/structured-data/faqpage'
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
if (hasFaq) {
|
|
144
|
+
return createResult({ id: 'schema-faq', name: 'FAQ Schema', category: 'structured-data', severity: 'info' }, 'pass', 'FAQPage schema found');
|
|
145
|
+
}
|
|
146
|
+
return createResult({ id: 'schema-faq', name: 'FAQ Schema', category: 'structured-data', severity: 'info' }, 'info', 'Not applicable (no FAQ content detected)', { recommendation: 'This rule suggests FAQPage schema when FAQ-like content is present' });
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
id: 'schema-article',
|
|
151
|
+
name: 'Article Schema',
|
|
152
|
+
category: 'structured-data',
|
|
153
|
+
severity: 'info',
|
|
154
|
+
description: 'Blog posts and articles should have Article schema',
|
|
155
|
+
check: (ctx) => {
|
|
156
|
+
if (!ctx.jsonLdTypes) {
|
|
157
|
+
return createResult({ id: 'schema-article', name: 'Article Schema', category: 'structured-data', severity: 'info' }, 'info', 'Not applicable (JSON-LD types data unavailable)', { recommendation: 'This rule checks for Article schema on blog posts and news articles' });
|
|
158
|
+
}
|
|
159
|
+
const hasArticle = ctx.jsonLdTypes.some(t => ['Article', 'NewsArticle', 'BlogPosting', 'TechArticle', 'ScholarlyArticle'].includes(t));
|
|
160
|
+
const looksLikeArticle = ctx.hasArticle ||
|
|
161
|
+
ctx.ogType === 'article' ||
|
|
162
|
+
ctx.ogArticlePublishedTime ||
|
|
163
|
+
ctx.ogArticleAuthor;
|
|
164
|
+
if (!hasArticle && looksLikeArticle) {
|
|
165
|
+
return createResult({ id: 'schema-article', name: 'Article Schema', category: 'structured-data', severity: 'info' }, 'info', 'Article content detected but no Article schema found', {
|
|
166
|
+
recommendation: 'Add Article schema for blog posts and news articles.',
|
|
167
|
+
evidence: {
|
|
168
|
+
found: 'Article-like content without Article schema',
|
|
169
|
+
expected: 'Article, BlogPosting, or NewsArticle schema',
|
|
170
|
+
impact: 'Article schema enables article-specific rich results and improves content indexing.',
|
|
171
|
+
example: '{"@context":"https://schema.org","@type":"Article","headline":"Article Title","author":{"@type":"Person","name":"Author Name"},"datePublished":"2024-01-15","dateModified":"2024-01-20"}',
|
|
172
|
+
learnMore: 'https://developers.google.com/search/docs/appearance/structured-data/article'
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
if (hasArticle) {
|
|
177
|
+
return createResult({ id: 'schema-article', name: 'Article Schema', category: 'structured-data', severity: 'info' }, 'pass', `Article schema found: ${ctx.jsonLdTypes.find(t => t.includes('Article') || t === 'BlogPosting')}`);
|
|
178
|
+
}
|
|
179
|
+
return createResult({ id: 'schema-article', name: 'Article Schema', category: 'structured-data', severity: 'info' }, 'info', 'Not applicable (no article-like content detected)', { recommendation: 'This rule suggests Article schema when article-like content is detected' });
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
id: 'schema-website',
|
|
184
|
+
name: 'WebSite Schema',
|
|
185
|
+
category: 'structured-data',
|
|
186
|
+
severity: 'info',
|
|
187
|
+
description: 'Homepage should have WebSite schema for sitelinks searchbox',
|
|
188
|
+
check: (ctx) => {
|
|
189
|
+
if (!ctx.jsonLdTypes) {
|
|
190
|
+
return createResult({ id: 'schema-website', name: 'WebSite Schema', category: 'structured-data', severity: 'info' }, 'info', 'Not applicable (JSON-LD types data unavailable)', { recommendation: 'This rule checks for WebSite schema on homepage to enable sitelinks searchbox' });
|
|
191
|
+
}
|
|
192
|
+
const hasWebSite = ctx.jsonLdTypes.includes('WebSite');
|
|
193
|
+
if (!ctx.isStartPage && !ctx.url?.match(/^https?:\/\/[^\/]+\/?$/)) {
|
|
194
|
+
return createResult({ id: 'schema-website', name: 'WebSite Schema', category: 'structured-data', severity: 'info' }, 'info', 'Not applicable (not a homepage)', { recommendation: 'WebSite schema is typically used on the homepage for sitelinks searchbox' });
|
|
195
|
+
}
|
|
196
|
+
if (!hasWebSite) {
|
|
197
|
+
return createResult({ id: 'schema-website', name: 'WebSite Schema', category: 'structured-data', severity: 'info' }, 'info', 'No WebSite schema found on homepage', {
|
|
198
|
+
recommendation: 'Add WebSite schema to enable sitelinks searchbox in Google results.',
|
|
199
|
+
evidence: {
|
|
200
|
+
found: 'No WebSite schema',
|
|
201
|
+
expected: 'WebSite schema with SearchAction for sitelinks searchbox',
|
|
202
|
+
impact: 'WebSite schema can show a search box directly in Google search results.',
|
|
203
|
+
example: '{"@context":"https://schema.org","@type":"WebSite","url":"https://example.com","name":"Site Name","potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://example.com/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}',
|
|
204
|
+
learnMore: 'https://developers.google.com/search/docs/appearance/structured-data/sitelinks-searchbox'
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
return createResult({ id: 'schema-website', name: 'WebSite Schema', category: 'structured-data', severity: 'info' }, 'pass', 'WebSite schema found');
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
id: 'schema-person',
|
|
213
|
+
name: 'Person Schema',
|
|
214
|
+
category: 'structured-data',
|
|
215
|
+
severity: 'info',
|
|
216
|
+
description: 'Person schema strengthens E-E-A-T signals and helps AI understand authorship',
|
|
217
|
+
check: (ctx) => {
|
|
218
|
+
if (!ctx.jsonLdTypes) {
|
|
219
|
+
return createResult({ id: 'schema-person', name: 'Person Schema', category: 'structured-data', severity: 'info' }, 'info', 'Not applicable (JSON-LD types data unavailable)', { recommendation: 'This rule checks for Person schema to strengthen E-E-A-T signals' });
|
|
220
|
+
}
|
|
221
|
+
const hasPerson = ctx.jsonLdTypes.includes('Person');
|
|
222
|
+
const hasArticle = ctx.jsonLdTypes.some(t => ['Article', 'NewsArticle', 'BlogPosting', 'TechArticle'].includes(t));
|
|
223
|
+
const isAboutPage = ctx.url?.toLowerCase().includes('/about') ||
|
|
224
|
+
ctx.url?.toLowerCase().includes('/team') ||
|
|
225
|
+
ctx.url?.toLowerCase().includes('/author');
|
|
226
|
+
if (!hasPerson && (hasArticle || isAboutPage)) {
|
|
227
|
+
return createResult({ id: 'schema-person', name: 'Person Schema', category: 'structured-data', severity: 'info' }, 'info', 'No Person schema found', {
|
|
228
|
+
recommendation: 'Add Person schema to establish authorship and strengthen E-E-A-T signals.',
|
|
229
|
+
evidence: {
|
|
230
|
+
found: 'No Person schema',
|
|
231
|
+
expected: 'Person schema with name, jobTitle, and sameAs properties',
|
|
232
|
+
impact: 'Person schema helps Google and AI systems understand content authorship and expertise. 72% of top-ranking pages use some type of schema.',
|
|
233
|
+
example: '{"@context":"https://schema.org","@type":"Person","name":"John Doe","jobTitle":"SEO Specialist","url":"https://example.com/team/john","sameAs":["https://twitter.com/johndoe","https://linkedin.com/in/johndoe"]}',
|
|
234
|
+
learnMore: 'https://developers.google.com/search/docs/appearance/structured-data/profile-page'
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
if (hasPerson) {
|
|
239
|
+
return createResult({ id: 'schema-person', name: 'Person Schema', category: 'structured-data', severity: 'info' }, 'pass', 'Person schema found (strengthens E-E-A-T)');
|
|
240
|
+
}
|
|
241
|
+
return createResult({ id: 'schema-person', name: 'Person Schema', category: 'structured-data', severity: 'info' }, 'info', 'Not applicable (not an article or about/team page)', { recommendation: 'Person schema is recommended for article pages and about/team pages' });
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
id: 'schema-review',
|
|
246
|
+
name: 'Review Schema',
|
|
247
|
+
category: 'structured-data',
|
|
248
|
+
severity: 'info',
|
|
249
|
+
description: 'Review and AggregateRating schema enables star ratings in search results',
|
|
250
|
+
check: (ctx) => {
|
|
251
|
+
if (!ctx.jsonLdTypes) {
|
|
252
|
+
return createResult({ id: 'schema-review', name: 'Review Schema', category: 'structured-data', severity: 'info' }, 'info', 'Not applicable (JSON-LD types data unavailable)', { recommendation: 'This rule checks for Review schema to enable star ratings in search results' });
|
|
253
|
+
}
|
|
254
|
+
const hasReview = ctx.jsonLdTypes.some(t => ['Review', 'AggregateRating'].includes(t));
|
|
255
|
+
const hasProduct = ctx.jsonLdTypes.includes('Product');
|
|
256
|
+
const hasLocalBusiness = ctx.jsonLdTypes.some(t => ['LocalBusiness', 'Restaurant', 'Hotel', 'Store'].includes(t));
|
|
257
|
+
if (!hasReview && (hasProduct || hasLocalBusiness || ctx.isProductPage)) {
|
|
258
|
+
return createResult({ id: 'schema-review', name: 'Review Schema', category: 'structured-data', severity: 'info' }, 'info', 'No Review/Rating schema found', {
|
|
259
|
+
recommendation: 'Add Review or AggregateRating schema to show star ratings in search results.',
|
|
260
|
+
evidence: {
|
|
261
|
+
found: 'No Review schema',
|
|
262
|
+
expected: 'Review or AggregateRating schema',
|
|
263
|
+
impact: 'Pages with schema receive 40% higher CTR than pages without. Star ratings significantly increase click-through rates.',
|
|
264
|
+
example: '{"@context":"https://schema.org","@type":"AggregateRating","ratingValue":"4.5","reviewCount":"89","bestRating":"5"}',
|
|
265
|
+
learnMore: 'https://developers.google.com/search/docs/appearance/structured-data/review-snippet'
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
if (hasReview) {
|
|
270
|
+
return createResult({ id: 'schema-review', name: 'Review Schema', category: 'structured-data', severity: 'info' }, 'pass', 'Review/Rating schema found');
|
|
271
|
+
}
|
|
272
|
+
return createResult({ id: 'schema-review', name: 'Review Schema', category: 'structured-data', severity: 'info' }, 'info', 'Not applicable (not a product or local business page)', { recommendation: 'Review schema is recommended for product and local business pages' });
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
id: 'schema-service',
|
|
277
|
+
name: 'Service Schema',
|
|
278
|
+
category: 'structured-data',
|
|
279
|
+
severity: 'info',
|
|
280
|
+
description: 'Service businesses should use Service schema to describe offerings',
|
|
281
|
+
check: (ctx) => {
|
|
282
|
+
if (!ctx.jsonLdTypes) {
|
|
283
|
+
return createResult({ id: 'schema-service', name: 'Service Schema', category: 'structured-data', severity: 'info' }, 'info', 'Not applicable (JSON-LD types data unavailable)', { recommendation: 'This rule checks for Service schema to describe business service offerings' });
|
|
284
|
+
}
|
|
285
|
+
const hasService = ctx.jsonLdTypes.some(t => ['Service', 'ProfessionalService', 'FinancialService', 'LegalService'].includes(t));
|
|
286
|
+
const hasLocalBusiness = ctx.jsonLdTypes.some(t => ['LocalBusiness', 'ProfessionalService', 'LegalService', 'FinancialService',
|
|
287
|
+
'AccountingService', 'AutoRepair', 'Dentist', 'MedicalClinic'].includes(t));
|
|
288
|
+
const isServicePage = ctx.url?.toLowerCase().includes('/service') ||
|
|
289
|
+
ctx.url?.toLowerCase().includes('/pricing');
|
|
290
|
+
if (!hasService && (hasLocalBusiness || isServicePage)) {
|
|
291
|
+
return createResult({ id: 'schema-service', name: 'Service Schema', category: 'structured-data', severity: 'info' }, 'info', 'No Service schema found', {
|
|
292
|
+
recommendation: 'Add Service schema to help AI understand your specific service offerings.',
|
|
293
|
+
evidence: {
|
|
294
|
+
found: 'LocalBusiness without Service schema',
|
|
295
|
+
expected: 'Service schema with provider, areaServed, and offers',
|
|
296
|
+
impact: 'Service schema helps AI systems accurately represent your business services in generated responses.',
|
|
297
|
+
example: '{"@context":"https://schema.org","@type":"Service","name":"Tax Preparation","provider":{"@type":"LocalBusiness","name":"ABC Accounting"},"areaServed":"Austin, TX","offers":{"@type":"Offer","price":"150","priceCurrency":"USD"}}',
|
|
298
|
+
learnMore: 'https://schema.org/Service'
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
if (hasService) {
|
|
303
|
+
return createResult({ id: 'schema-service', name: 'Service Schema', category: 'structured-data', severity: 'info' }, 'pass', 'Service schema found');
|
|
304
|
+
}
|
|
305
|
+
return createResult({ id: 'schema-service', name: 'Service Schema', category: 'structured-data', severity: 'info' }, 'info', 'Not applicable (not a local business or service page)', { recommendation: 'Service schema is recommended for service business pages' });
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
id: 'schema-sameas',
|
|
310
|
+
name: 'Schema sameAs (Social Links)',
|
|
311
|
+
category: 'structured-data',
|
|
312
|
+
severity: 'info',
|
|
313
|
+
description: 'sameAs property links your entity to social profiles, improving AI visibility',
|
|
314
|
+
check: (ctx) => {
|
|
315
|
+
if (!ctx.jsonLdTypes) {
|
|
316
|
+
return createResult({ id: 'schema-sameas', name: 'Schema sameAs (Social Links)', category: 'structured-data', severity: 'info' }, 'info', 'Not applicable (JSON-LD types data unavailable)', { recommendation: 'This rule checks for sameAs property to link entities to social profiles' });
|
|
317
|
+
}
|
|
318
|
+
const hasOrgOrPerson = ctx.jsonLdTypes.some(t => ['Organization', 'LocalBusiness', 'Person', 'Corporation'].includes(t));
|
|
319
|
+
if (!hasOrgOrPerson) {
|
|
320
|
+
return createResult({ id: 'schema-sameas', name: 'Schema sameAs (Social Links)', category: 'structured-data', severity: 'info' }, 'info', 'Not applicable (no Organization or Person schema detected)', { recommendation: 'This rule applies when Organization or Person schema is present' });
|
|
321
|
+
}
|
|
322
|
+
const hasSocialLinks = ctx.socialLinksFound && ctx.socialLinksFound.length > 0;
|
|
323
|
+
if (hasSocialLinks) {
|
|
324
|
+
const socialCount = ctx.socialLinksFound?.length ?? 0;
|
|
325
|
+
return createResult({ id: 'schema-sameas', name: 'Schema sameAs', category: 'structured-data', severity: 'info' }, 'info', 'Social links found - ensure they are included in schema sameAs property', {
|
|
326
|
+
recommendation: 'Add sameAs property to your Organization/Person schema with all social profile URLs.',
|
|
327
|
+
evidence: {
|
|
328
|
+
found: `${socialCount} social profile(s) on page`,
|
|
329
|
+
expected: 'sameAs array in Organization or Person schema',
|
|
330
|
+
impact: 'sameAs helps AI systems connect your brand across platforms and improves Knowledge Panel eligibility.',
|
|
331
|
+
example: '"sameAs": ["https://twitter.com/company", "https://linkedin.com/company/name", "https://facebook.com/company"]',
|
|
332
|
+
learnMore: 'https://developers.google.com/search/docs/appearance/structured-data/organization'
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
return createResult({ id: 'schema-sameas', name: 'Schema sameAs', category: 'structured-data', severity: 'info' }, 'pass', 'Organization/Person schema present (verify sameAs includes social profiles)');
|
|
337
|
+
},
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
id: 'schema-ai-completeness',
|
|
341
|
+
name: 'Schema Completeness for AI',
|
|
342
|
+
category: 'structured-data',
|
|
343
|
+
severity: 'info',
|
|
344
|
+
description: 'Comprehensive structured data improves AI citations and visibility',
|
|
345
|
+
check: (ctx) => {
|
|
346
|
+
if (!ctx.jsonLdTypes || ctx.jsonLdTypes.length === 0) {
|
|
347
|
+
return createResult({ id: 'schema-ai-completeness', name: 'Schema Completeness for AI', category: 'structured-data', severity: 'info' }, 'info', 'Not applicable (no JSON-LD types detected)', { recommendation: 'This rule checks for comprehensive structured data to improve AI citations' });
|
|
348
|
+
}
|
|
349
|
+
const importantTypes = [
|
|
350
|
+
'Organization', 'LocalBusiness', 'Person', 'Product', 'Service',
|
|
351
|
+
'FAQPage', 'Article', 'BlogPosting', 'WebSite', 'BreadcrumbList'
|
|
352
|
+
];
|
|
353
|
+
const foundImportant = ctx.jsonLdTypes.filter(t => importantTypes.includes(t));
|
|
354
|
+
if (foundImportant.length >= 3) {
|
|
355
|
+
return createResult({ id: 'schema-ai-completeness', name: 'Schema AI Completeness', category: 'structured-data', severity: 'info' }, 'pass', `Comprehensive schema found (${foundImportant.length} key types)`, {
|
|
356
|
+
value: foundImportant.join(', '),
|
|
357
|
+
evidence: {
|
|
358
|
+
found: foundImportant,
|
|
359
|
+
impact: 'Comprehensive structured data significantly increases chances of AI citations.'
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
if (foundImportant.length >= 1) {
|
|
364
|
+
const missing = importantTypes.filter(t => !foundImportant.includes(t)).slice(0, 3);
|
|
365
|
+
return createResult({ id: 'schema-ai-completeness', name: 'Schema AI Completeness', category: 'structured-data', severity: 'info' }, 'info', `Basic schema found (${foundImportant.length} key type(s))`, {
|
|
366
|
+
value: foundImportant.join(', '),
|
|
367
|
+
recommendation: 'Add more schema types for better AI visibility.',
|
|
368
|
+
evidence: {
|
|
369
|
+
found: foundImportant,
|
|
370
|
+
expected: 'Multiple schema types for comprehensive coverage',
|
|
371
|
+
impact: 'AI systems prioritize sites with comprehensive structured data for citations.',
|
|
372
|
+
issue: `Consider adding: ${missing.join(', ')}`
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
return createResult({ id: 'schema-ai-completeness', name: 'Schema AI Completeness', category: 'structured-data', severity: 'info' }, 'info', 'Not applicable (no key schema types detected)', { recommendation: 'This rule analyzes schema completeness when important schema types are present' });
|
|
377
|
+
},
|
|
378
|
+
},
|
|
379
|
+
];
|