@rankcli/agent-runtime 0.0.31 → 0.0.33
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/dist/index.d.mts +36 -17
- package/dist/index.d.ts +36 -17
- package/dist/index.js +115 -17
- package/dist/index.mjs +114 -17
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -3031,20 +3031,6 @@ declare function buildDeterministicFixes(input: DeterministicFixInput): Determin
|
|
|
3031
3031
|
*/
|
|
3032
3032
|
declare function findAppRoot(files: string[]): string;
|
|
3033
3033
|
|
|
3034
|
-
interface ReplacementConcern {
|
|
3035
|
-
/** Machine-readable, for logs and the PR body. */
|
|
3036
|
-
code: 'shrunk' | 'lost_closing_tag' | 'lost_script' | 'lost_stylesheet' | 'lost_verification' | 'lost_import' | 'invalid_json' | 'invalid_xml' | 'invalid_json_ld' | 'fewer_sitemap_urls' | 'lastmod_moved_backwards';
|
|
3037
|
-
detail: string;
|
|
3038
|
-
}
|
|
3039
|
-
/**
|
|
3040
|
-
* Everything wrong with replacing `original` with `replacement` at `path`. Empty means safe
|
|
3041
|
-
* to commit. `original` is null for a file being created, where there is nothing to lose and
|
|
3042
|
-
* only the content's own validity matters.
|
|
3043
|
-
*/
|
|
3044
|
-
declare function assessReplacement(path: string, original: string | null, replacement: string): ReplacementConcern[];
|
|
3045
|
-
/** One line naming why a file was dropped, for a log line or a PR body. */
|
|
3046
|
-
declare function describeConcerns(concerns: ReplacementConcern[]): string;
|
|
3047
|
-
|
|
3048
3034
|
/**
|
|
3049
3035
|
* Framework Detection
|
|
3050
3036
|
*
|
|
@@ -3056,7 +3042,7 @@ declare function describeConcerns(concerns: ReplacementConcern[]): string;
|
|
|
3056
3042
|
*
|
|
3057
3043
|
* Supports 25+ frameworks across JavaScript, Ruby, Python, PHP, Java, C#, Go, and Elixir.
|
|
3058
3044
|
*/
|
|
3059
|
-
type Framework = 'react' | 'nextjs' | 'vue' | 'nuxt' | 'angular' | 'svelte' | 'sveltekit' | 'astro' | 'remix' | 'gatsby' | 'solidjs' | 'qwik' | 'fresh' | 'rails' | 'django' | 'flask' | 'fastapi' | 'laravel' | 'symfony' | 'wordpress' | 'spring' | 'aspnet' | 'go' | 'phoenix' | 'htmx' | 'hotwire' | 'hugo' | 'jekyll' | 'eleventy' | 'pelican' | 'sphinx' | 'unknown';
|
|
3045
|
+
type Framework = 'react' | 'nextjs' | 'vue' | 'nuxt' | 'angular' | 'svelte' | 'sveltekit' | 'astro' | 'remix' | 'gatsby' | 'solidjs' | 'qwik' | 'fresh' | 'rails' | 'django' | 'flask' | 'fastapi' | 'laravel' | 'symfony' | 'wordpress' | 'spring' | 'aspnet' | 'go' | 'phoenix' | 'htmx' | 'hotwire' | 'hugo' | 'jekyll' | 'eleventy' | 'pelican' | 'sphinx' | 'docusaurus' | 'unknown';
|
|
3060
3046
|
type Language = 'javascript' | 'typescript' | 'ruby' | 'python' | 'php' | 'java' | 'csharp' | 'go' | 'elixir' | 'rust' | 'unknown';
|
|
3061
3047
|
interface FrameworkInfo {
|
|
3062
3048
|
framework: Framework;
|
|
@@ -3108,6 +3094,30 @@ declare function detectFramework$1(options: {
|
|
|
3108
3094
|
*/
|
|
3109
3095
|
declare function getFrameworkDisplayName(framework: Framework): string;
|
|
3110
3096
|
|
|
3097
|
+
/**
|
|
3098
|
+
* Where to write a file that must be served at the site root.
|
|
3099
|
+
*
|
|
3100
|
+
* @param framework what detection identified, or 'unknown'
|
|
3101
|
+
* @param files every path in the repository
|
|
3102
|
+
* @param appRoot the app's directory, with a trailing slash, or ''
|
|
3103
|
+
* @returns a path prefix relative to appRoot: 'public/', 'static/', or '' for the app root
|
|
3104
|
+
*/
|
|
3105
|
+
declare function servedDir(framework: Framework | undefined, files: string[], appRoot?: string): string;
|
|
3106
|
+
|
|
3107
|
+
interface ReplacementConcern {
|
|
3108
|
+
/** Machine-readable, for logs and the PR body. */
|
|
3109
|
+
code: 'shrunk' | 'lost_closing_tag' | 'lost_script' | 'lost_stylesheet' | 'lost_verification' | 'lost_import' | 'invalid_json' | 'invalid_xml' | 'invalid_json_ld' | 'fewer_sitemap_urls' | 'lastmod_moved_backwards';
|
|
3110
|
+
detail: string;
|
|
3111
|
+
}
|
|
3112
|
+
/**
|
|
3113
|
+
* Everything wrong with replacing `original` with `replacement` at `path`. Empty means safe
|
|
3114
|
+
* to commit. `original` is null for a file being created, where there is nothing to lose and
|
|
3115
|
+
* only the content's own validity matters.
|
|
3116
|
+
*/
|
|
3117
|
+
declare function assessReplacement(path: string, original: string | null, replacement: string): ReplacementConcern[];
|
|
3118
|
+
/** One line naming why a file was dropped, for a log line or a PR body. */
|
|
3119
|
+
declare function describeConcerns(concerns: ReplacementConcern[]): string;
|
|
3120
|
+
|
|
3111
3121
|
/**
|
|
3112
3122
|
* Framework-Specific SEO Suggestion Engine
|
|
3113
3123
|
*
|
|
@@ -3131,6 +3141,13 @@ interface FrameworkCheck {
|
|
|
3131
3141
|
};
|
|
3132
3142
|
app_router_only?: boolean;
|
|
3133
3143
|
pages_router_only?: boolean;
|
|
3144
|
+
/**
|
|
3145
|
+
* Only meaningful on a page search engines are allowed to index. A check that
|
|
3146
|
+
* says "crawlers will not see your content" is not a finding on a page that
|
|
3147
|
+
* asks not to be crawled - every SaaS has a noindex /login, and reporting a
|
|
3148
|
+
* critical SEO error on it is noise that drags the score down.
|
|
3149
|
+
*/
|
|
3150
|
+
indexable_only?: boolean;
|
|
3134
3151
|
}
|
|
3135
3152
|
interface FrameworkRecipe {
|
|
3136
3153
|
framework: Framework;
|
|
@@ -3158,7 +3175,9 @@ declare function loadRecipe(framework: Framework): Promise<FrameworkRecipe | nul
|
|
|
3158
3175
|
/**
|
|
3159
3176
|
* Get framework-specific issues based on HTML analysis
|
|
3160
3177
|
*/
|
|
3161
|
-
declare function getFrameworkIssues(frameworkInfo: FrameworkInfo, html: string, url: string
|
|
3178
|
+
declare function getFrameworkIssues(frameworkInfo: FrameworkInfo, html: string, url: string, options?: {
|
|
3179
|
+
indexable?: boolean;
|
|
3180
|
+
}): Promise<AuditIssue[]>;
|
|
3162
3181
|
/**
|
|
3163
3182
|
* Get framework-specific suggestions for fixing issues
|
|
3164
3183
|
*/
|
|
@@ -5689,4 +5708,4 @@ declare namespace index {
|
|
|
5689
5708
|
export { type index_DetectionResult as DetectionResult, type index_Evidence as Evidence, type index_Framework as Framework, type index_FrameworkCheck as FrameworkCheck, type index_FrameworkInfo as FrameworkInfo, type index_FrameworkRecipe as FrameworkRecipe, index_SCORE_FLOOR as SCORE_FLOOR, index_SIGNALS as SIGNALS, index_SUPPORTED_FRAMEWORKS as SUPPORTED_FRAMEWORKS, type index_Signal as Signal, index_WEIGHT as WEIGHT, detectFramework$1 as detectFramework, index_detectFromEvidence as detectFromEvidence, index_detectFromHeaders as detectFromHeaders, index_detectFromHtml as detectFromHtml, index_detectFromPackageJson as detectFromPackageJson, index_embedRecipe as embedRecipe, index_getFrameworkChecks as getFrameworkChecks, index_getFrameworkDisplayName as getFrameworkDisplayName, index_getFrameworkIssues as getFrameworkIssues, index_getFrameworkSuggestions as getFrameworkSuggestions, index_getFrameworkSummary as getFrameworkSummary, index_getMigrationPaths as getMigrationPaths, index_getPerformanceTips as getPerformanceTips, index_getSeoChallenges as getSeoChallenges, index_getTotalFrameworkChecks as getTotalFrameworkChecks, index_loadRecipe as loadRecipe };
|
|
5690
5709
|
}
|
|
5691
5710
|
|
|
5692
|
-
export { type AIContentConfig, type AIKeywordResearchOptions, type AgentDefinition, type AgentTool, type AlertChannel, type AlertConfig, type AlertMessage, type AlertResult, type AlertSeverity, type AlertType, type AuditAlertPayload, type AuditIssue, type AuditIssueData, type AuditOptions, type AuditPRResult, type AuditReport, type AuditReportData, type AuditRunnerOptions, type AuditRunnerResult, type AuditSchedule, type BlogPostConfig, type BrandConfig, type CIAction, type CIKeywordOptions, type CIKeywordResult, COMMIT_TYPES, type ChangelogConfig, type ChangelogResult, type CitationCheckOptions, type CommitConfig, type ComparisonConfig, type ComparisonRow, type CompetitiveInsight, type CompetitiveSearchOptions, type CompetitiveSearchResult, type CompetitorComparison, type CompetitorKeywordResult, type CompetitorOverlap, type CompetitorTool, type CompetitorUrl, type ContentElements, type ContentGeneratorOptions, type ContentRecommendation, type ConventionalCommit, type CrawlResult, type CrawlStats, type CrawledPage, type CreateAuditPROptions, type CreatePROptions, type DataForSEOCredentials, type DeterministicFixInput, type DeterministicFixes, type DiscoveredPage, type EnhancedToolIdea, type ExecOptions, type ExecuteOptions, type ExecutionResult, type FAQItem, type FAQSchemaOptions, type FeaturedSnippetAnalysis, type Fix, type FixFile, type FixGeneratorOptions, type FixResult, type FrameworkInfo$1 as FrameworkInfo, type FreeKeywordResult, type FreeToolIdea, type GA4Config, type GEOAlert, type GEOAlertType, type GEOHistory, type GEOHistoryOptions, type GEOQuery, type GEOReport, type GEOResult, type GEOTrend, type GSCConfig, type GSCCredentials, type GSCPerformanceData, type GSCQueryData, type GSCQueryResult, type GeneratedCode, type GeneratedContent, type GeneratedFix, type HeadingStructure, type HeadlineAnalysis, type HealthScore, ISSUE_DEFINITIONS, type ImageInfo$2 as ImageInfo, type InjectionResult, type IntentAnalysis, type IssueCategory, type IssueDefinition, type IssueSeverity, type KeyFact, type KeyFactsOptions, type KeywordAction, type KeywordCluster, type KeywordData, type KeywordDensityAnalysis, type KeywordLLM, type KeywordOpportunity, type KeywordRecommendation, type KeywordResearchOptions, type KeywordResearchResult, type KeywordStats, type KeywordTopic, type KeywordTrend, type LLMCitationResult, type LLMJudgeOptions, type LLMProvider, LOCATION_CODES, type LSIKeyword, type LinkInfo$1 as LinkInfo, type Mention, type MentionType, type MetaData, type MetaFixOptions, type NGram, type NLPAnalysisResult, OG_IMAGE_SPECS, type OptimizeOptions, type PRConfig, type PRDescription, PRIORITY_WEIGHTS, type PRResult, type PageAudit, type PageData, type PageMeta, type PaidKeywordResult, type ParsedResponse, type PlanTier, type ProviderStats, type QuickWin, type RankCheckOptions, type RankCheckResult, type RankHistory, RankTracker, type RankingResult, type RankingTierLimits, type ReadabilityResult, type ReadmeConfig, type ReadmeResult, type ReportBranding, type ReportConfig, type ReportData, type ReportPageData, type RouteInfo, type SEOAnalysisResult, type SEOFixCommit, type SEOFixSummary, type SEOIssue, type SEORecommendation, type SEOScore, SEO_SCOPES, SITE_PROFILE_QUESTIONS, type ScheduledAuditConfig, type ScheduledAuditResult, type SchemaData, Schemas, type SearchIntent, type Sentiment, type SerpApiConfig, SerpClient, type SerpClientConfig, type SerpFeature, type SiteCrawlResult, type SiteProfile, type SiteSummary, type SnippetRecommendation, type SnippetType, type SocialMetaConfig, type SocialMetaFix, type SummarizerOptions, type TFIDFResult, TIER_LIMITS, type ToolFeasibilityScore, type ToolFunction, type ToolResult, type TopicClusterResult, type TopicModel, type TrackedKeyword, type TrackerConfig, type TrackingOptions, type TrendDirection, type UncertaintyAssessment, type WizardQuestion, type WizardResponse, type WizardResult, type WizardSession, type WorkflowConfig, addTrackingResult, analyzeAnchorText, analyzeCanonicalAdvanced, analyzeClientRendering, analyzeContentFreshness, analyzeDOMStructure, analyzeFeaturedSnippetPotential, analyzeHeadings, analyzeHeadline, analyzeHreflang, analyzeImages$1 as analyzeImages, analyzeKeywordDensity, analyzeKeywords, analyzeLinks, analyzeLocalSEO, analyzeMobile, analyzeModernImages, analyzeOnPage, analyzePagination, analyzePerformance, analyzeReadability, analyzeRedirectChain, analyzeRedirects, analyzeResponsiveImages, analyzeSERPPreview, analyzeSecurity, analyzeSecurityHeaders$1 as analyzeSecurityHeaders, analyzeSocialMeta, analyzeStructuredData$1 as analyzeStructuredData, analyzeTrackerBloat, analyzeUrl, analyzeUrlSafety, index$1 as analyzers, applyFixes, assessReplacement, buildDeterministicFixes, buildFrameworkGuidance, buildGSCApiRequest, buildGSCRequest, calculateAIVisibilityScore, calculateBM25, calculateTFIDF$1 as calculateKeywordTFIDF, calculateNextRun, calculateTFIDF, checkAIBotBlocking, checkAMP, checkAdsTxt, checkAppleTouchIcon, checkBalance, checkCertificate, checkDMARC, checkGitHubCLI, checkInternalRedirects, checkJSRenderingRatio, checkLLMCitations, checkLlmsTxt, checkMobileResources, checkPlaintextEmails, checkRedirects, checkRobots, checkRobotsTxt, checkSPF, checkSitemap, classifyIntent, classifyIntents, clusterKeywordsByEmbedding, compareCompetitorVisibility, comparePeriods, completeWizard, crawlSite, crawlUrl, createAuditPR, createFallbackSummary, createGEOHistory, createPullRequest, createSEOCommit, createSEOCommits, describeConcerns, detectDuplicates, detectFramework, detectGitHubPages, detectMentions, detectSoft404, detectTechnologies, detectVisibilityChanges, discoverCompetitorKeywords, discoverPagesFromLinks, discoverRoutesFromRepo, enhanceSummaryWithCompetitors, enhanceToolIdea, enrichKeywordsWithEstimates, ensureGitRepo, evaluateAndEnhanceToolIdeas, evaluateToolFeasibility, executeAgent, extractContentHash, extractEntityPhrases, extractImages, extractKeyPhrases, extractLinks, extractMeta, extractNgrams, extractSchema, extractSeedKeywords, extractTopics, fetchCoreWebVitals, findAlmostPage1Keywords, findAppRoot, findCTROpportunities, findHtmlEntry, findLSIKeywords, findPageFiles, findTopPerformers, formatAlertMessage, formatCIResult, formatCompetitorReport, formatConventionalCommit, formatFeaturedSnippetReport, formatHeadlineReport, formatIntentReport, formatKeywordDensityReport, formatKeywordReport, formatPRBody, formatPRTitle, formatReadabilityReport, formatReport, formatSEOCommitMessage, formatTopicReport, formatWizardProgress, index as frameworks, generateAICitableContent, generateAllFixes, generateAngularSEOService, generateAspNetCoreSEO, generateAstroBaseHead, generateAstroMeta, generateBlogPost, generateBranchName, generateChangelog, generateCommitSummary, generateComparisonTable, generateCompleteSocialMetaSetup, generateDjangoSEOHelper, generateDuplicateIssues, generateEleventySEO, generateFAQSchema, generateFixes, generateGA4EnvTemplate, generateGA4ReactComponent, generateGA4Script, generateGA4ViteScript, generateGEOReport, generateGSCVerificationTag, generateGitHubActionSetup, generateGoSEO, generateHTMLReport, generateHTMLSocialMeta, generateHTMXSEO, generateHeadlineVariations, generateHugoSEO, generateJekyllSEO, generateJsonReport, generateKeyFacts, generateLaravelSEOHelper, generateMarkdownReport, generateNextAppMetadata, generateNextJsAppRouterMetadata, generateNextJsPagesRouterHead, generateNextPagesHead, generateNuxtSEOHead, generatePDFReport, generatePRDescription, generatePhoenixSEO, generateRailsSEOHelper, generateReactHelmetSocialMeta, generateReactSEOHead, generateRecommendationQueries, generateRemixMeta, generateRemixSEO, generateSecretsDoc, generateSocialMetaFix, generateSpringBootSEO, generateSvelteKitMeta, generateSvelteKitSEOHead, generateUncertaintyQuestions, generateVueSEOHead, generateWizardQuestions, generateWorkflow, getAIVisibilitySummary, getAutocompleteSuggestions, getDateRange, getExpandedSuggestions, getFrameworkSpecificFix, getFrameworkSpecificFixExtended, getGSCSetupInstructions, getGitUser, getKeywordData, getKeywordSuggestions, getMaxKdThreshold, getNextQuestion, getRelatedKeywords, getVisibilityTrend, groupKeywordsByTopic, identifyQuickWins, injectGA4, injectGSCVerification, interpolatePrompt, isGitRepo, keywordLLM, listFiles, loadAgent, loadAgentByName, mergePages, openAIKeywordLLM, optimizeForAI, optimizeReadme, parseGEOResponse, parseGSCResponse, parseJsonReply, parseSitemap, prioritizeKeywords, processWizardResponse, readFile, routesToUrls, runAIKeywordResearch, runAIReadinessChecks, runAdditionalChecks, runAuditWithFixes, runCIKeywordResearch, runCrawlabilityChecks, runDirectAnalysis, runFullAudit, runKeywordResearch, runNLPAnalysis, runScheduledAudit, scoreContentSEO, scoreMention, searchCompetitors, searchFormatConverters, searchHackerNews, sendAlert, sendAlerts, sendDiscordAlert, sendSlackAlert, shouldRunAudit, shouldSendAlert, startWizardSession, suggestSchemaTypes, summarizeSite, tokenize, tools, trackLLMVisibility, transformGSCData, urlSafetyDatabase, wizardResponsesToContext, writeFile, writeGitHubActionFiles };
|
|
5711
|
+
export { type AIContentConfig, type AIKeywordResearchOptions, type AgentDefinition, type AgentTool, type AlertChannel, type AlertConfig, type AlertMessage, type AlertResult, type AlertSeverity, type AlertType, type AuditAlertPayload, type AuditIssue, type AuditIssueData, type AuditOptions, type AuditPRResult, type AuditReport, type AuditReportData, type AuditRunnerOptions, type AuditRunnerResult, type AuditSchedule, type BlogPostConfig, type BrandConfig, type CIAction, type CIKeywordOptions, type CIKeywordResult, COMMIT_TYPES, type ChangelogConfig, type ChangelogResult, type CitationCheckOptions, type CommitConfig, type ComparisonConfig, type ComparisonRow, type CompetitiveInsight, type CompetitiveSearchOptions, type CompetitiveSearchResult, type CompetitorComparison, type CompetitorKeywordResult, type CompetitorOverlap, type CompetitorTool, type CompetitorUrl, type ContentElements, type ContentGeneratorOptions, type ContentRecommendation, type ConventionalCommit, type CrawlResult, type CrawlStats, type CrawledPage, type CreateAuditPROptions, type CreatePROptions, type DataForSEOCredentials, type DeterministicFixInput, type DeterministicFixes, type DiscoveredPage, type EnhancedToolIdea, type ExecOptions, type ExecuteOptions, type ExecutionResult, type FAQItem, type FAQSchemaOptions, type FeaturedSnippetAnalysis, type Fix, type FixFile, type FixGeneratorOptions, type FixResult, type FrameworkInfo$1 as FrameworkInfo, type FreeKeywordResult, type FreeToolIdea, type GA4Config, type GEOAlert, type GEOAlertType, type GEOHistory, type GEOHistoryOptions, type GEOQuery, type GEOReport, type GEOResult, type GEOTrend, type GSCConfig, type GSCCredentials, type GSCPerformanceData, type GSCQueryData, type GSCQueryResult, type GeneratedCode, type GeneratedContent, type GeneratedFix, type HeadingStructure, type HeadlineAnalysis, type HealthScore, ISSUE_DEFINITIONS, type ImageInfo$2 as ImageInfo, type InjectionResult, type IntentAnalysis, type IssueCategory, type IssueDefinition, type IssueSeverity, type KeyFact, type KeyFactsOptions, type KeywordAction, type KeywordCluster, type KeywordData, type KeywordDensityAnalysis, type KeywordLLM, type KeywordOpportunity, type KeywordRecommendation, type KeywordResearchOptions, type KeywordResearchResult, type KeywordStats, type KeywordTopic, type KeywordTrend, type LLMCitationResult, type LLMJudgeOptions, type LLMProvider, LOCATION_CODES, type LSIKeyword, type LinkInfo$1 as LinkInfo, type Mention, type MentionType, type MetaData, type MetaFixOptions, type NGram, type NLPAnalysisResult, OG_IMAGE_SPECS, type OptimizeOptions, type PRConfig, type PRDescription, PRIORITY_WEIGHTS, type PRResult, type PageAudit, type PageData, type PageMeta, type PaidKeywordResult, type ParsedResponse, type PlanTier, type ProviderStats, type QuickWin, type RankCheckOptions, type RankCheckResult, type RankHistory, RankTracker, type RankingResult, type RankingTierLimits, type ReadabilityResult, type ReadmeConfig, type ReadmeResult, type ReportBranding, type ReportConfig, type ReportData, type ReportPageData, type RouteInfo, type SEOAnalysisResult, type SEOFixCommit, type SEOFixSummary, type SEOIssue, type SEORecommendation, type SEOScore, SEO_SCOPES, SITE_PROFILE_QUESTIONS, type ScheduledAuditConfig, type ScheduledAuditResult, type SchemaData, Schemas, type SearchIntent, type Sentiment, type SerpApiConfig, SerpClient, type SerpClientConfig, type SerpFeature, type SiteCrawlResult, type SiteProfile, type SiteSummary, type SnippetRecommendation, type SnippetType, type SocialMetaConfig, type SocialMetaFix, type SummarizerOptions, type TFIDFResult, TIER_LIMITS, type ToolFeasibilityScore, type ToolFunction, type ToolResult, type TopicClusterResult, type TopicModel, type TrackedKeyword, type TrackerConfig, type TrackingOptions, type TrendDirection, type UncertaintyAssessment, type WizardQuestion, type WizardResponse, type WizardResult, type WizardSession, type WorkflowConfig, addTrackingResult, analyzeAnchorText, analyzeCanonicalAdvanced, analyzeClientRendering, analyzeContentFreshness, analyzeDOMStructure, analyzeFeaturedSnippetPotential, analyzeHeadings, analyzeHeadline, analyzeHreflang, analyzeImages$1 as analyzeImages, analyzeKeywordDensity, analyzeKeywords, analyzeLinks, analyzeLocalSEO, analyzeMobile, analyzeModernImages, analyzeOnPage, analyzePagination, analyzePerformance, analyzeReadability, analyzeRedirectChain, analyzeRedirects, analyzeResponsiveImages, analyzeSERPPreview, analyzeSecurity, analyzeSecurityHeaders$1 as analyzeSecurityHeaders, analyzeSocialMeta, analyzeStructuredData$1 as analyzeStructuredData, analyzeTrackerBloat, analyzeUrl, analyzeUrlSafety, index$1 as analyzers, applyFixes, assessReplacement, buildDeterministicFixes, buildFrameworkGuidance, buildGSCApiRequest, buildGSCRequest, calculateAIVisibilityScore, calculateBM25, calculateTFIDF$1 as calculateKeywordTFIDF, calculateNextRun, calculateTFIDF, checkAIBotBlocking, checkAMP, checkAdsTxt, checkAppleTouchIcon, checkBalance, checkCertificate, checkDMARC, checkGitHubCLI, checkInternalRedirects, checkJSRenderingRatio, checkLLMCitations, checkLlmsTxt, checkMobileResources, checkPlaintextEmails, checkRedirects, checkRobots, checkRobotsTxt, checkSPF, checkSitemap, classifyIntent, classifyIntents, clusterKeywordsByEmbedding, compareCompetitorVisibility, comparePeriods, completeWizard, crawlSite, crawlUrl, createAuditPR, createFallbackSummary, createGEOHistory, createPullRequest, createSEOCommit, createSEOCommits, describeConcerns, detectDuplicates, detectFramework, detectGitHubPages, detectMentions, detectSoft404, detectTechnologies, detectVisibilityChanges, discoverCompetitorKeywords, discoverPagesFromLinks, discoverRoutesFromRepo, enhanceSummaryWithCompetitors, enhanceToolIdea, enrichKeywordsWithEstimates, ensureGitRepo, evaluateAndEnhanceToolIdeas, evaluateToolFeasibility, executeAgent, extractContentHash, extractEntityPhrases, extractImages, extractKeyPhrases, extractLinks, extractMeta, extractNgrams, extractSchema, extractSeedKeywords, extractTopics, fetchCoreWebVitals, findAlmostPage1Keywords, findAppRoot, findCTROpportunities, findHtmlEntry, findLSIKeywords, findPageFiles, findTopPerformers, formatAlertMessage, formatCIResult, formatCompetitorReport, formatConventionalCommit, formatFeaturedSnippetReport, formatHeadlineReport, formatIntentReport, formatKeywordDensityReport, formatKeywordReport, formatPRBody, formatPRTitle, formatReadabilityReport, formatReport, formatSEOCommitMessage, formatTopicReport, formatWizardProgress, index as frameworks, generateAICitableContent, generateAllFixes, generateAngularSEOService, generateAspNetCoreSEO, generateAstroBaseHead, generateAstroMeta, generateBlogPost, generateBranchName, generateChangelog, generateCommitSummary, generateComparisonTable, generateCompleteSocialMetaSetup, generateDjangoSEOHelper, generateDuplicateIssues, generateEleventySEO, generateFAQSchema, generateFixes, generateGA4EnvTemplate, generateGA4ReactComponent, generateGA4Script, generateGA4ViteScript, generateGEOReport, generateGSCVerificationTag, generateGitHubActionSetup, generateGoSEO, generateHTMLReport, generateHTMLSocialMeta, generateHTMXSEO, generateHeadlineVariations, generateHugoSEO, generateJekyllSEO, generateJsonReport, generateKeyFacts, generateLaravelSEOHelper, generateMarkdownReport, generateNextAppMetadata, generateNextJsAppRouterMetadata, generateNextJsPagesRouterHead, generateNextPagesHead, generateNuxtSEOHead, generatePDFReport, generatePRDescription, generatePhoenixSEO, generateRailsSEOHelper, generateReactHelmetSocialMeta, generateReactSEOHead, generateRecommendationQueries, generateRemixMeta, generateRemixSEO, generateSecretsDoc, generateSocialMetaFix, generateSpringBootSEO, generateSvelteKitMeta, generateSvelteKitSEOHead, generateUncertaintyQuestions, generateVueSEOHead, generateWizardQuestions, generateWorkflow, getAIVisibilitySummary, getAutocompleteSuggestions, getDateRange, getExpandedSuggestions, getFrameworkSpecificFix, getFrameworkSpecificFixExtended, getGSCSetupInstructions, getGitUser, getKeywordData, getKeywordSuggestions, getMaxKdThreshold, getNextQuestion, getRelatedKeywords, getVisibilityTrend, groupKeywordsByTopic, identifyQuickWins, injectGA4, injectGSCVerification, interpolatePrompt, isGitRepo, keywordLLM, listFiles, loadAgent, loadAgentByName, mergePages, openAIKeywordLLM, optimizeForAI, optimizeReadme, parseGEOResponse, parseGSCResponse, parseJsonReply, parseSitemap, prioritizeKeywords, processWizardResponse, readFile, routesToUrls, runAIKeywordResearch, runAIReadinessChecks, runAdditionalChecks, runAuditWithFixes, runCIKeywordResearch, runCrawlabilityChecks, runDirectAnalysis, runFullAudit, runKeywordResearch, runNLPAnalysis, runScheduledAudit, scoreContentSEO, scoreMention, searchCompetitors, searchFormatConverters, searchHackerNews, sendAlert, sendAlerts, sendDiscordAlert, sendSlackAlert, servedDir, shouldRunAudit, shouldSendAlert, startWizardSession, suggestSchemaTypes, summarizeSite, tokenize, tools, trackLLMVisibility, transformGSCData, urlSafetyDatabase, wizardResponsesToContext, writeFile, writeGitHubActionFiles };
|
package/dist/index.d.ts
CHANGED
|
@@ -3031,20 +3031,6 @@ declare function buildDeterministicFixes(input: DeterministicFixInput): Determin
|
|
|
3031
3031
|
*/
|
|
3032
3032
|
declare function findAppRoot(files: string[]): string;
|
|
3033
3033
|
|
|
3034
|
-
interface ReplacementConcern {
|
|
3035
|
-
/** Machine-readable, for logs and the PR body. */
|
|
3036
|
-
code: 'shrunk' | 'lost_closing_tag' | 'lost_script' | 'lost_stylesheet' | 'lost_verification' | 'lost_import' | 'invalid_json' | 'invalid_xml' | 'invalid_json_ld' | 'fewer_sitemap_urls' | 'lastmod_moved_backwards';
|
|
3037
|
-
detail: string;
|
|
3038
|
-
}
|
|
3039
|
-
/**
|
|
3040
|
-
* Everything wrong with replacing `original` with `replacement` at `path`. Empty means safe
|
|
3041
|
-
* to commit. `original` is null for a file being created, where there is nothing to lose and
|
|
3042
|
-
* only the content's own validity matters.
|
|
3043
|
-
*/
|
|
3044
|
-
declare function assessReplacement(path: string, original: string | null, replacement: string): ReplacementConcern[];
|
|
3045
|
-
/** One line naming why a file was dropped, for a log line or a PR body. */
|
|
3046
|
-
declare function describeConcerns(concerns: ReplacementConcern[]): string;
|
|
3047
|
-
|
|
3048
3034
|
/**
|
|
3049
3035
|
* Framework Detection
|
|
3050
3036
|
*
|
|
@@ -3056,7 +3042,7 @@ declare function describeConcerns(concerns: ReplacementConcern[]): string;
|
|
|
3056
3042
|
*
|
|
3057
3043
|
* Supports 25+ frameworks across JavaScript, Ruby, Python, PHP, Java, C#, Go, and Elixir.
|
|
3058
3044
|
*/
|
|
3059
|
-
type Framework = 'react' | 'nextjs' | 'vue' | 'nuxt' | 'angular' | 'svelte' | 'sveltekit' | 'astro' | 'remix' | 'gatsby' | 'solidjs' | 'qwik' | 'fresh' | 'rails' | 'django' | 'flask' | 'fastapi' | 'laravel' | 'symfony' | 'wordpress' | 'spring' | 'aspnet' | 'go' | 'phoenix' | 'htmx' | 'hotwire' | 'hugo' | 'jekyll' | 'eleventy' | 'pelican' | 'sphinx' | 'unknown';
|
|
3045
|
+
type Framework = 'react' | 'nextjs' | 'vue' | 'nuxt' | 'angular' | 'svelte' | 'sveltekit' | 'astro' | 'remix' | 'gatsby' | 'solidjs' | 'qwik' | 'fresh' | 'rails' | 'django' | 'flask' | 'fastapi' | 'laravel' | 'symfony' | 'wordpress' | 'spring' | 'aspnet' | 'go' | 'phoenix' | 'htmx' | 'hotwire' | 'hugo' | 'jekyll' | 'eleventy' | 'pelican' | 'sphinx' | 'docusaurus' | 'unknown';
|
|
3060
3046
|
type Language = 'javascript' | 'typescript' | 'ruby' | 'python' | 'php' | 'java' | 'csharp' | 'go' | 'elixir' | 'rust' | 'unknown';
|
|
3061
3047
|
interface FrameworkInfo {
|
|
3062
3048
|
framework: Framework;
|
|
@@ -3108,6 +3094,30 @@ declare function detectFramework$1(options: {
|
|
|
3108
3094
|
*/
|
|
3109
3095
|
declare function getFrameworkDisplayName(framework: Framework): string;
|
|
3110
3096
|
|
|
3097
|
+
/**
|
|
3098
|
+
* Where to write a file that must be served at the site root.
|
|
3099
|
+
*
|
|
3100
|
+
* @param framework what detection identified, or 'unknown'
|
|
3101
|
+
* @param files every path in the repository
|
|
3102
|
+
* @param appRoot the app's directory, with a trailing slash, or ''
|
|
3103
|
+
* @returns a path prefix relative to appRoot: 'public/', 'static/', or '' for the app root
|
|
3104
|
+
*/
|
|
3105
|
+
declare function servedDir(framework: Framework | undefined, files: string[], appRoot?: string): string;
|
|
3106
|
+
|
|
3107
|
+
interface ReplacementConcern {
|
|
3108
|
+
/** Machine-readable, for logs and the PR body. */
|
|
3109
|
+
code: 'shrunk' | 'lost_closing_tag' | 'lost_script' | 'lost_stylesheet' | 'lost_verification' | 'lost_import' | 'invalid_json' | 'invalid_xml' | 'invalid_json_ld' | 'fewer_sitemap_urls' | 'lastmod_moved_backwards';
|
|
3110
|
+
detail: string;
|
|
3111
|
+
}
|
|
3112
|
+
/**
|
|
3113
|
+
* Everything wrong with replacing `original` with `replacement` at `path`. Empty means safe
|
|
3114
|
+
* to commit. `original` is null for a file being created, where there is nothing to lose and
|
|
3115
|
+
* only the content's own validity matters.
|
|
3116
|
+
*/
|
|
3117
|
+
declare function assessReplacement(path: string, original: string | null, replacement: string): ReplacementConcern[];
|
|
3118
|
+
/** One line naming why a file was dropped, for a log line or a PR body. */
|
|
3119
|
+
declare function describeConcerns(concerns: ReplacementConcern[]): string;
|
|
3120
|
+
|
|
3111
3121
|
/**
|
|
3112
3122
|
* Framework-Specific SEO Suggestion Engine
|
|
3113
3123
|
*
|
|
@@ -3131,6 +3141,13 @@ interface FrameworkCheck {
|
|
|
3131
3141
|
};
|
|
3132
3142
|
app_router_only?: boolean;
|
|
3133
3143
|
pages_router_only?: boolean;
|
|
3144
|
+
/**
|
|
3145
|
+
* Only meaningful on a page search engines are allowed to index. A check that
|
|
3146
|
+
* says "crawlers will not see your content" is not a finding on a page that
|
|
3147
|
+
* asks not to be crawled - every SaaS has a noindex /login, and reporting a
|
|
3148
|
+
* critical SEO error on it is noise that drags the score down.
|
|
3149
|
+
*/
|
|
3150
|
+
indexable_only?: boolean;
|
|
3134
3151
|
}
|
|
3135
3152
|
interface FrameworkRecipe {
|
|
3136
3153
|
framework: Framework;
|
|
@@ -3158,7 +3175,9 @@ declare function loadRecipe(framework: Framework): Promise<FrameworkRecipe | nul
|
|
|
3158
3175
|
/**
|
|
3159
3176
|
* Get framework-specific issues based on HTML analysis
|
|
3160
3177
|
*/
|
|
3161
|
-
declare function getFrameworkIssues(frameworkInfo: FrameworkInfo, html: string, url: string
|
|
3178
|
+
declare function getFrameworkIssues(frameworkInfo: FrameworkInfo, html: string, url: string, options?: {
|
|
3179
|
+
indexable?: boolean;
|
|
3180
|
+
}): Promise<AuditIssue[]>;
|
|
3162
3181
|
/**
|
|
3163
3182
|
* Get framework-specific suggestions for fixing issues
|
|
3164
3183
|
*/
|
|
@@ -5689,4 +5708,4 @@ declare namespace index {
|
|
|
5689
5708
|
export { type index_DetectionResult as DetectionResult, type index_Evidence as Evidence, type index_Framework as Framework, type index_FrameworkCheck as FrameworkCheck, type index_FrameworkInfo as FrameworkInfo, type index_FrameworkRecipe as FrameworkRecipe, index_SCORE_FLOOR as SCORE_FLOOR, index_SIGNALS as SIGNALS, index_SUPPORTED_FRAMEWORKS as SUPPORTED_FRAMEWORKS, type index_Signal as Signal, index_WEIGHT as WEIGHT, detectFramework$1 as detectFramework, index_detectFromEvidence as detectFromEvidence, index_detectFromHeaders as detectFromHeaders, index_detectFromHtml as detectFromHtml, index_detectFromPackageJson as detectFromPackageJson, index_embedRecipe as embedRecipe, index_getFrameworkChecks as getFrameworkChecks, index_getFrameworkDisplayName as getFrameworkDisplayName, index_getFrameworkIssues as getFrameworkIssues, index_getFrameworkSuggestions as getFrameworkSuggestions, index_getFrameworkSummary as getFrameworkSummary, index_getMigrationPaths as getMigrationPaths, index_getPerformanceTips as getPerformanceTips, index_getSeoChallenges as getSeoChallenges, index_getTotalFrameworkChecks as getTotalFrameworkChecks, index_loadRecipe as loadRecipe };
|
|
5690
5709
|
}
|
|
5691
5710
|
|
|
5692
|
-
export { type AIContentConfig, type AIKeywordResearchOptions, type AgentDefinition, type AgentTool, type AlertChannel, type AlertConfig, type AlertMessage, type AlertResult, type AlertSeverity, type AlertType, type AuditAlertPayload, type AuditIssue, type AuditIssueData, type AuditOptions, type AuditPRResult, type AuditReport, type AuditReportData, type AuditRunnerOptions, type AuditRunnerResult, type AuditSchedule, type BlogPostConfig, type BrandConfig, type CIAction, type CIKeywordOptions, type CIKeywordResult, COMMIT_TYPES, type ChangelogConfig, type ChangelogResult, type CitationCheckOptions, type CommitConfig, type ComparisonConfig, type ComparisonRow, type CompetitiveInsight, type CompetitiveSearchOptions, type CompetitiveSearchResult, type CompetitorComparison, type CompetitorKeywordResult, type CompetitorOverlap, type CompetitorTool, type CompetitorUrl, type ContentElements, type ContentGeneratorOptions, type ContentRecommendation, type ConventionalCommit, type CrawlResult, type CrawlStats, type CrawledPage, type CreateAuditPROptions, type CreatePROptions, type DataForSEOCredentials, type DeterministicFixInput, type DeterministicFixes, type DiscoveredPage, type EnhancedToolIdea, type ExecOptions, type ExecuteOptions, type ExecutionResult, type FAQItem, type FAQSchemaOptions, type FeaturedSnippetAnalysis, type Fix, type FixFile, type FixGeneratorOptions, type FixResult, type FrameworkInfo$1 as FrameworkInfo, type FreeKeywordResult, type FreeToolIdea, type GA4Config, type GEOAlert, type GEOAlertType, type GEOHistory, type GEOHistoryOptions, type GEOQuery, type GEOReport, type GEOResult, type GEOTrend, type GSCConfig, type GSCCredentials, type GSCPerformanceData, type GSCQueryData, type GSCQueryResult, type GeneratedCode, type GeneratedContent, type GeneratedFix, type HeadingStructure, type HeadlineAnalysis, type HealthScore, ISSUE_DEFINITIONS, type ImageInfo$2 as ImageInfo, type InjectionResult, type IntentAnalysis, type IssueCategory, type IssueDefinition, type IssueSeverity, type KeyFact, type KeyFactsOptions, type KeywordAction, type KeywordCluster, type KeywordData, type KeywordDensityAnalysis, type KeywordLLM, type KeywordOpportunity, type KeywordRecommendation, type KeywordResearchOptions, type KeywordResearchResult, type KeywordStats, type KeywordTopic, type KeywordTrend, type LLMCitationResult, type LLMJudgeOptions, type LLMProvider, LOCATION_CODES, type LSIKeyword, type LinkInfo$1 as LinkInfo, type Mention, type MentionType, type MetaData, type MetaFixOptions, type NGram, type NLPAnalysisResult, OG_IMAGE_SPECS, type OptimizeOptions, type PRConfig, type PRDescription, PRIORITY_WEIGHTS, type PRResult, type PageAudit, type PageData, type PageMeta, type PaidKeywordResult, type ParsedResponse, type PlanTier, type ProviderStats, type QuickWin, type RankCheckOptions, type RankCheckResult, type RankHistory, RankTracker, type RankingResult, type RankingTierLimits, type ReadabilityResult, type ReadmeConfig, type ReadmeResult, type ReportBranding, type ReportConfig, type ReportData, type ReportPageData, type RouteInfo, type SEOAnalysisResult, type SEOFixCommit, type SEOFixSummary, type SEOIssue, type SEORecommendation, type SEOScore, SEO_SCOPES, SITE_PROFILE_QUESTIONS, type ScheduledAuditConfig, type ScheduledAuditResult, type SchemaData, Schemas, type SearchIntent, type Sentiment, type SerpApiConfig, SerpClient, type SerpClientConfig, type SerpFeature, type SiteCrawlResult, type SiteProfile, type SiteSummary, type SnippetRecommendation, type SnippetType, type SocialMetaConfig, type SocialMetaFix, type SummarizerOptions, type TFIDFResult, TIER_LIMITS, type ToolFeasibilityScore, type ToolFunction, type ToolResult, type TopicClusterResult, type TopicModel, type TrackedKeyword, type TrackerConfig, type TrackingOptions, type TrendDirection, type UncertaintyAssessment, type WizardQuestion, type WizardResponse, type WizardResult, type WizardSession, type WorkflowConfig, addTrackingResult, analyzeAnchorText, analyzeCanonicalAdvanced, analyzeClientRendering, analyzeContentFreshness, analyzeDOMStructure, analyzeFeaturedSnippetPotential, analyzeHeadings, analyzeHeadline, analyzeHreflang, analyzeImages$1 as analyzeImages, analyzeKeywordDensity, analyzeKeywords, analyzeLinks, analyzeLocalSEO, analyzeMobile, analyzeModernImages, analyzeOnPage, analyzePagination, analyzePerformance, analyzeReadability, analyzeRedirectChain, analyzeRedirects, analyzeResponsiveImages, analyzeSERPPreview, analyzeSecurity, analyzeSecurityHeaders$1 as analyzeSecurityHeaders, analyzeSocialMeta, analyzeStructuredData$1 as analyzeStructuredData, analyzeTrackerBloat, analyzeUrl, analyzeUrlSafety, index$1 as analyzers, applyFixes, assessReplacement, buildDeterministicFixes, buildFrameworkGuidance, buildGSCApiRequest, buildGSCRequest, calculateAIVisibilityScore, calculateBM25, calculateTFIDF$1 as calculateKeywordTFIDF, calculateNextRun, calculateTFIDF, checkAIBotBlocking, checkAMP, checkAdsTxt, checkAppleTouchIcon, checkBalance, checkCertificate, checkDMARC, checkGitHubCLI, checkInternalRedirects, checkJSRenderingRatio, checkLLMCitations, checkLlmsTxt, checkMobileResources, checkPlaintextEmails, checkRedirects, checkRobots, checkRobotsTxt, checkSPF, checkSitemap, classifyIntent, classifyIntents, clusterKeywordsByEmbedding, compareCompetitorVisibility, comparePeriods, completeWizard, crawlSite, crawlUrl, createAuditPR, createFallbackSummary, createGEOHistory, createPullRequest, createSEOCommit, createSEOCommits, describeConcerns, detectDuplicates, detectFramework, detectGitHubPages, detectMentions, detectSoft404, detectTechnologies, detectVisibilityChanges, discoverCompetitorKeywords, discoverPagesFromLinks, discoverRoutesFromRepo, enhanceSummaryWithCompetitors, enhanceToolIdea, enrichKeywordsWithEstimates, ensureGitRepo, evaluateAndEnhanceToolIdeas, evaluateToolFeasibility, executeAgent, extractContentHash, extractEntityPhrases, extractImages, extractKeyPhrases, extractLinks, extractMeta, extractNgrams, extractSchema, extractSeedKeywords, extractTopics, fetchCoreWebVitals, findAlmostPage1Keywords, findAppRoot, findCTROpportunities, findHtmlEntry, findLSIKeywords, findPageFiles, findTopPerformers, formatAlertMessage, formatCIResult, formatCompetitorReport, formatConventionalCommit, formatFeaturedSnippetReport, formatHeadlineReport, formatIntentReport, formatKeywordDensityReport, formatKeywordReport, formatPRBody, formatPRTitle, formatReadabilityReport, formatReport, formatSEOCommitMessage, formatTopicReport, formatWizardProgress, index as frameworks, generateAICitableContent, generateAllFixes, generateAngularSEOService, generateAspNetCoreSEO, generateAstroBaseHead, generateAstroMeta, generateBlogPost, generateBranchName, generateChangelog, generateCommitSummary, generateComparisonTable, generateCompleteSocialMetaSetup, generateDjangoSEOHelper, generateDuplicateIssues, generateEleventySEO, generateFAQSchema, generateFixes, generateGA4EnvTemplate, generateGA4ReactComponent, generateGA4Script, generateGA4ViteScript, generateGEOReport, generateGSCVerificationTag, generateGitHubActionSetup, generateGoSEO, generateHTMLReport, generateHTMLSocialMeta, generateHTMXSEO, generateHeadlineVariations, generateHugoSEO, generateJekyllSEO, generateJsonReport, generateKeyFacts, generateLaravelSEOHelper, generateMarkdownReport, generateNextAppMetadata, generateNextJsAppRouterMetadata, generateNextJsPagesRouterHead, generateNextPagesHead, generateNuxtSEOHead, generatePDFReport, generatePRDescription, generatePhoenixSEO, generateRailsSEOHelper, generateReactHelmetSocialMeta, generateReactSEOHead, generateRecommendationQueries, generateRemixMeta, generateRemixSEO, generateSecretsDoc, generateSocialMetaFix, generateSpringBootSEO, generateSvelteKitMeta, generateSvelteKitSEOHead, generateUncertaintyQuestions, generateVueSEOHead, generateWizardQuestions, generateWorkflow, getAIVisibilitySummary, getAutocompleteSuggestions, getDateRange, getExpandedSuggestions, getFrameworkSpecificFix, getFrameworkSpecificFixExtended, getGSCSetupInstructions, getGitUser, getKeywordData, getKeywordSuggestions, getMaxKdThreshold, getNextQuestion, getRelatedKeywords, getVisibilityTrend, groupKeywordsByTopic, identifyQuickWins, injectGA4, injectGSCVerification, interpolatePrompt, isGitRepo, keywordLLM, listFiles, loadAgent, loadAgentByName, mergePages, openAIKeywordLLM, optimizeForAI, optimizeReadme, parseGEOResponse, parseGSCResponse, parseJsonReply, parseSitemap, prioritizeKeywords, processWizardResponse, readFile, routesToUrls, runAIKeywordResearch, runAIReadinessChecks, runAdditionalChecks, runAuditWithFixes, runCIKeywordResearch, runCrawlabilityChecks, runDirectAnalysis, runFullAudit, runKeywordResearch, runNLPAnalysis, runScheduledAudit, scoreContentSEO, scoreMention, searchCompetitors, searchFormatConverters, searchHackerNews, sendAlert, sendAlerts, sendDiscordAlert, sendSlackAlert, shouldRunAudit, shouldSendAlert, startWizardSession, suggestSchemaTypes, summarizeSite, tokenize, tools, trackLLMVisibility, transformGSCData, urlSafetyDatabase, wizardResponsesToContext, writeFile, writeGitHubActionFiles };
|
|
5711
|
+
export { type AIContentConfig, type AIKeywordResearchOptions, type AgentDefinition, type AgentTool, type AlertChannel, type AlertConfig, type AlertMessage, type AlertResult, type AlertSeverity, type AlertType, type AuditAlertPayload, type AuditIssue, type AuditIssueData, type AuditOptions, type AuditPRResult, type AuditReport, type AuditReportData, type AuditRunnerOptions, type AuditRunnerResult, type AuditSchedule, type BlogPostConfig, type BrandConfig, type CIAction, type CIKeywordOptions, type CIKeywordResult, COMMIT_TYPES, type ChangelogConfig, type ChangelogResult, type CitationCheckOptions, type CommitConfig, type ComparisonConfig, type ComparisonRow, type CompetitiveInsight, type CompetitiveSearchOptions, type CompetitiveSearchResult, type CompetitorComparison, type CompetitorKeywordResult, type CompetitorOverlap, type CompetitorTool, type CompetitorUrl, type ContentElements, type ContentGeneratorOptions, type ContentRecommendation, type ConventionalCommit, type CrawlResult, type CrawlStats, type CrawledPage, type CreateAuditPROptions, type CreatePROptions, type DataForSEOCredentials, type DeterministicFixInput, type DeterministicFixes, type DiscoveredPage, type EnhancedToolIdea, type ExecOptions, type ExecuteOptions, type ExecutionResult, type FAQItem, type FAQSchemaOptions, type FeaturedSnippetAnalysis, type Fix, type FixFile, type FixGeneratorOptions, type FixResult, type FrameworkInfo$1 as FrameworkInfo, type FreeKeywordResult, type FreeToolIdea, type GA4Config, type GEOAlert, type GEOAlertType, type GEOHistory, type GEOHistoryOptions, type GEOQuery, type GEOReport, type GEOResult, type GEOTrend, type GSCConfig, type GSCCredentials, type GSCPerformanceData, type GSCQueryData, type GSCQueryResult, type GeneratedCode, type GeneratedContent, type GeneratedFix, type HeadingStructure, type HeadlineAnalysis, type HealthScore, ISSUE_DEFINITIONS, type ImageInfo$2 as ImageInfo, type InjectionResult, type IntentAnalysis, type IssueCategory, type IssueDefinition, type IssueSeverity, type KeyFact, type KeyFactsOptions, type KeywordAction, type KeywordCluster, type KeywordData, type KeywordDensityAnalysis, type KeywordLLM, type KeywordOpportunity, type KeywordRecommendation, type KeywordResearchOptions, type KeywordResearchResult, type KeywordStats, type KeywordTopic, type KeywordTrend, type LLMCitationResult, type LLMJudgeOptions, type LLMProvider, LOCATION_CODES, type LSIKeyword, type LinkInfo$1 as LinkInfo, type Mention, type MentionType, type MetaData, type MetaFixOptions, type NGram, type NLPAnalysisResult, OG_IMAGE_SPECS, type OptimizeOptions, type PRConfig, type PRDescription, PRIORITY_WEIGHTS, type PRResult, type PageAudit, type PageData, type PageMeta, type PaidKeywordResult, type ParsedResponse, type PlanTier, type ProviderStats, type QuickWin, type RankCheckOptions, type RankCheckResult, type RankHistory, RankTracker, type RankingResult, type RankingTierLimits, type ReadabilityResult, type ReadmeConfig, type ReadmeResult, type ReportBranding, type ReportConfig, type ReportData, type ReportPageData, type RouteInfo, type SEOAnalysisResult, type SEOFixCommit, type SEOFixSummary, type SEOIssue, type SEORecommendation, type SEOScore, SEO_SCOPES, SITE_PROFILE_QUESTIONS, type ScheduledAuditConfig, type ScheduledAuditResult, type SchemaData, Schemas, type SearchIntent, type Sentiment, type SerpApiConfig, SerpClient, type SerpClientConfig, type SerpFeature, type SiteCrawlResult, type SiteProfile, type SiteSummary, type SnippetRecommendation, type SnippetType, type SocialMetaConfig, type SocialMetaFix, type SummarizerOptions, type TFIDFResult, TIER_LIMITS, type ToolFeasibilityScore, type ToolFunction, type ToolResult, type TopicClusterResult, type TopicModel, type TrackedKeyword, type TrackerConfig, type TrackingOptions, type TrendDirection, type UncertaintyAssessment, type WizardQuestion, type WizardResponse, type WizardResult, type WizardSession, type WorkflowConfig, addTrackingResult, analyzeAnchorText, analyzeCanonicalAdvanced, analyzeClientRendering, analyzeContentFreshness, analyzeDOMStructure, analyzeFeaturedSnippetPotential, analyzeHeadings, analyzeHeadline, analyzeHreflang, analyzeImages$1 as analyzeImages, analyzeKeywordDensity, analyzeKeywords, analyzeLinks, analyzeLocalSEO, analyzeMobile, analyzeModernImages, analyzeOnPage, analyzePagination, analyzePerformance, analyzeReadability, analyzeRedirectChain, analyzeRedirects, analyzeResponsiveImages, analyzeSERPPreview, analyzeSecurity, analyzeSecurityHeaders$1 as analyzeSecurityHeaders, analyzeSocialMeta, analyzeStructuredData$1 as analyzeStructuredData, analyzeTrackerBloat, analyzeUrl, analyzeUrlSafety, index$1 as analyzers, applyFixes, assessReplacement, buildDeterministicFixes, buildFrameworkGuidance, buildGSCApiRequest, buildGSCRequest, calculateAIVisibilityScore, calculateBM25, calculateTFIDF$1 as calculateKeywordTFIDF, calculateNextRun, calculateTFIDF, checkAIBotBlocking, checkAMP, checkAdsTxt, checkAppleTouchIcon, checkBalance, checkCertificate, checkDMARC, checkGitHubCLI, checkInternalRedirects, checkJSRenderingRatio, checkLLMCitations, checkLlmsTxt, checkMobileResources, checkPlaintextEmails, checkRedirects, checkRobots, checkRobotsTxt, checkSPF, checkSitemap, classifyIntent, classifyIntents, clusterKeywordsByEmbedding, compareCompetitorVisibility, comparePeriods, completeWizard, crawlSite, crawlUrl, createAuditPR, createFallbackSummary, createGEOHistory, createPullRequest, createSEOCommit, createSEOCommits, describeConcerns, detectDuplicates, detectFramework, detectGitHubPages, detectMentions, detectSoft404, detectTechnologies, detectVisibilityChanges, discoverCompetitorKeywords, discoverPagesFromLinks, discoverRoutesFromRepo, enhanceSummaryWithCompetitors, enhanceToolIdea, enrichKeywordsWithEstimates, ensureGitRepo, evaluateAndEnhanceToolIdeas, evaluateToolFeasibility, executeAgent, extractContentHash, extractEntityPhrases, extractImages, extractKeyPhrases, extractLinks, extractMeta, extractNgrams, extractSchema, extractSeedKeywords, extractTopics, fetchCoreWebVitals, findAlmostPage1Keywords, findAppRoot, findCTROpportunities, findHtmlEntry, findLSIKeywords, findPageFiles, findTopPerformers, formatAlertMessage, formatCIResult, formatCompetitorReport, formatConventionalCommit, formatFeaturedSnippetReport, formatHeadlineReport, formatIntentReport, formatKeywordDensityReport, formatKeywordReport, formatPRBody, formatPRTitle, formatReadabilityReport, formatReport, formatSEOCommitMessage, formatTopicReport, formatWizardProgress, index as frameworks, generateAICitableContent, generateAllFixes, generateAngularSEOService, generateAspNetCoreSEO, generateAstroBaseHead, generateAstroMeta, generateBlogPost, generateBranchName, generateChangelog, generateCommitSummary, generateComparisonTable, generateCompleteSocialMetaSetup, generateDjangoSEOHelper, generateDuplicateIssues, generateEleventySEO, generateFAQSchema, generateFixes, generateGA4EnvTemplate, generateGA4ReactComponent, generateGA4Script, generateGA4ViteScript, generateGEOReport, generateGSCVerificationTag, generateGitHubActionSetup, generateGoSEO, generateHTMLReport, generateHTMLSocialMeta, generateHTMXSEO, generateHeadlineVariations, generateHugoSEO, generateJekyllSEO, generateJsonReport, generateKeyFacts, generateLaravelSEOHelper, generateMarkdownReport, generateNextAppMetadata, generateNextJsAppRouterMetadata, generateNextJsPagesRouterHead, generateNextPagesHead, generateNuxtSEOHead, generatePDFReport, generatePRDescription, generatePhoenixSEO, generateRailsSEOHelper, generateReactHelmetSocialMeta, generateReactSEOHead, generateRecommendationQueries, generateRemixMeta, generateRemixSEO, generateSecretsDoc, generateSocialMetaFix, generateSpringBootSEO, generateSvelteKitMeta, generateSvelteKitSEOHead, generateUncertaintyQuestions, generateVueSEOHead, generateWizardQuestions, generateWorkflow, getAIVisibilitySummary, getAutocompleteSuggestions, getDateRange, getExpandedSuggestions, getFrameworkSpecificFix, getFrameworkSpecificFixExtended, getGSCSetupInstructions, getGitUser, getKeywordData, getKeywordSuggestions, getMaxKdThreshold, getNextQuestion, getRelatedKeywords, getVisibilityTrend, groupKeywordsByTopic, identifyQuickWins, injectGA4, injectGSCVerification, interpolatePrompt, isGitRepo, keywordLLM, listFiles, loadAgent, loadAgentByName, mergePages, openAIKeywordLLM, optimizeForAI, optimizeReadme, parseGEOResponse, parseGSCResponse, parseJsonReply, parseSitemap, prioritizeKeywords, processWizardResponse, readFile, routesToUrls, runAIKeywordResearch, runAIReadinessChecks, runAdditionalChecks, runAuditWithFixes, runCIKeywordResearch, runCrawlabilityChecks, runDirectAnalysis, runFullAudit, runKeywordResearch, runNLPAnalysis, runScheduledAudit, scoreContentSEO, scoreMention, searchCompetitors, searchFormatConverters, searchHackerNews, sendAlert, sendAlerts, sendDiscordAlert, sendSlackAlert, servedDir, shouldRunAudit, shouldSendAlert, startWizardSession, suggestSchemaTypes, summarizeSite, tokenize, tools, trackLLMVisibility, transformGSCData, urlSafetyDatabase, wizardResponsesToContext, writeFile, writeGitHubActionFiles };
|
package/dist/index.js
CHANGED
|
@@ -3562,6 +3562,7 @@ __export(index_exports, {
|
|
|
3562
3562
|
sendAlerts: () => sendAlerts,
|
|
3563
3563
|
sendDiscordAlert: () => sendDiscordAlert,
|
|
3564
3564
|
sendSlackAlert: () => sendSlackAlert,
|
|
3565
|
+
servedDir: () => servedDir,
|
|
3565
3566
|
shouldRunAudit: () => shouldRunAudit,
|
|
3566
3567
|
shouldSendAlert: () => shouldSendAlert,
|
|
3567
3568
|
startWizardSession: () => startWizardSession,
|
|
@@ -3623,6 +3624,7 @@ var RECIPES = {
|
|
|
3623
3624
|
eleventy: null,
|
|
3624
3625
|
pelican: null,
|
|
3625
3626
|
sphinx: null,
|
|
3627
|
+
docusaurus: null,
|
|
3626
3628
|
// Unknown
|
|
3627
3629
|
unknown: null
|
|
3628
3630
|
};
|
|
@@ -3658,12 +3660,13 @@ async function loadRecipe(framework) {
|
|
|
3658
3660
|
}
|
|
3659
3661
|
return null;
|
|
3660
3662
|
}
|
|
3661
|
-
async function getFrameworkIssues(frameworkInfo, html, url) {
|
|
3663
|
+
async function getFrameworkIssues(frameworkInfo, html, url, options = {}) {
|
|
3662
3664
|
const recipe = await loadRecipe(frameworkInfo.framework);
|
|
3663
3665
|
if (!recipe) return [];
|
|
3664
3666
|
const issues = [];
|
|
3667
|
+
const indexable = options.indexable ?? true;
|
|
3665
3668
|
for (const check of recipe.checks) {
|
|
3666
|
-
const matched = evaluateCheck(check, html, frameworkInfo);
|
|
3669
|
+
const matched = evaluateCheck(check, html, frameworkInfo, indexable);
|
|
3667
3670
|
if (matched) {
|
|
3668
3671
|
issues.push({
|
|
3669
3672
|
code: check.code,
|
|
@@ -3684,7 +3687,10 @@ async function getFrameworkIssues(frameworkInfo, html, url) {
|
|
|
3684
3687
|
}
|
|
3685
3688
|
return issues;
|
|
3686
3689
|
}
|
|
3687
|
-
function evaluateCheck(check, html, frameworkInfo) {
|
|
3690
|
+
function evaluateCheck(check, html, frameworkInfo, indexable = true) {
|
|
3691
|
+
if (check.indexable_only && !indexable) {
|
|
3692
|
+
return false;
|
|
3693
|
+
}
|
|
3688
3694
|
if (check.app_router_only && html.includes("__next")) {
|
|
3689
3695
|
return false;
|
|
3690
3696
|
}
|
|
@@ -3798,6 +3804,7 @@ seo_challenges:
|
|
|
3798
3804
|
|
|
3799
3805
|
checks:
|
|
3800
3806
|
- code: ANGULAR_NO_UNIVERSAL
|
|
3807
|
+
indexable_only: true
|
|
3801
3808
|
severity: error
|
|
3802
3809
|
title: "Angular app without Universal (SSR)"
|
|
3803
3810
|
description: "Client-side Angular apps send empty HTML to crawlers."
|
|
@@ -3816,6 +3823,7 @@ checks:
|
|
|
3816
3823
|
missing_content: true
|
|
3817
3824
|
|
|
3818
3825
|
- code: ANGULAR_NO_TITLE_SERVICE
|
|
3826
|
+
indexable_only: true
|
|
3819
3827
|
severity: error
|
|
3820
3828
|
title: "Not using Title/Meta services"
|
|
3821
3829
|
description: "Angular has built-in services for managing title and meta tags."
|
|
@@ -3864,6 +3872,7 @@ checks:
|
|
|
3864
3872
|
\`\`\`
|
|
3865
3873
|
|
|
3866
3874
|
- code: ANGULAR_PRERENDER_MISSING
|
|
3875
|
+
indexable_only: true
|
|
3867
3876
|
severity: warning
|
|
3868
3877
|
title: "Static routes not prerendered"
|
|
3869
3878
|
description: "Static pages should be prerendered at build time."
|
|
@@ -4222,6 +4231,7 @@ checks:
|
|
|
4222
4231
|
\`\`\`
|
|
4223
4232
|
|
|
4224
4233
|
- code: DJANGO_NO_META_FRAMEWORK
|
|
4234
|
+
indexable_only: true
|
|
4225
4235
|
severity: warning
|
|
4226
4236
|
title: "No SEO meta framework detected"
|
|
4227
4237
|
description: "Use django-meta for consistent meta tag management."
|
|
@@ -4369,6 +4379,7 @@ seo_strengths:
|
|
|
4369
4379
|
|
|
4370
4380
|
checks:
|
|
4371
4381
|
- code: LARAVEL_NO_META_PACKAGE
|
|
4382
|
+
indexable_only: true
|
|
4372
4383
|
severity: warning
|
|
4373
4384
|
title: "No SEO package detected"
|
|
4374
4385
|
description: "Laravel benefits from an SEO package like artesaos/seotools."
|
|
@@ -4420,6 +4431,7 @@ checks:
|
|
|
4420
4431
|
\`\`\`
|
|
4421
4432
|
|
|
4422
4433
|
- code: LARAVEL_INERTIA_NO_SSR
|
|
4434
|
+
indexable_only: true
|
|
4423
4435
|
severity: error
|
|
4424
4436
|
title: "Inertia.js without SSR"
|
|
4425
4437
|
description: "Inertia apps are client-rendered by default, losing SEO benefits."
|
|
@@ -4514,6 +4526,7 @@ seo_strengths:
|
|
|
4514
4526
|
checks:
|
|
4515
4527
|
# App Router specific
|
|
4516
4528
|
- code: NEXTJS_NO_METADATA_API
|
|
4529
|
+
indexable_only: true
|
|
4517
4530
|
severity: warning
|
|
4518
4531
|
title: "Not using Next.js Metadata API"
|
|
4519
4532
|
description: "Next.js 13+ has a built-in Metadata API that's better than react-helmet."
|
|
@@ -4786,6 +4799,7 @@ seo_strengths:
|
|
|
4786
4799
|
|
|
4787
4800
|
checks:
|
|
4788
4801
|
- code: NUXT_NO_USESEOMETA
|
|
4802
|
+
indexable_only: true
|
|
4789
4803
|
severity: warning
|
|
4790
4804
|
title: "Not using useSeoMeta composable"
|
|
4791
4805
|
description: "Nuxt 3 has built-in SEO meta composables that are cleaner than useHead."
|
|
@@ -4895,6 +4909,7 @@ checks:
|
|
|
4895
4909
|
\`\`\`
|
|
4896
4910
|
|
|
4897
4911
|
- code: NUXT_SPA_MODE
|
|
4912
|
+
indexable_only: true
|
|
4898
4913
|
severity: error
|
|
4899
4914
|
title: "Nuxt running in SPA mode"
|
|
4900
4915
|
description: "SPA mode disables SSR, losing SEO benefits."
|
|
@@ -4920,6 +4935,7 @@ checks:
|
|
|
4920
4935
|
missing_content: true
|
|
4921
4936
|
|
|
4922
4937
|
- code: NUXT_NO_PRERENDER
|
|
4938
|
+
indexable_only: true
|
|
4923
4939
|
severity: notice
|
|
4924
4940
|
title: "Static pages not pre-rendered"
|
|
4925
4941
|
description: "Static pages could be pre-rendered for better performance."
|
|
@@ -4963,6 +4979,7 @@ seo_strengths:
|
|
|
4963
4979
|
|
|
4964
4980
|
checks:
|
|
4965
4981
|
- code: RAILS_NO_META_TAGS_GEM
|
|
4982
|
+
indexable_only: true
|
|
4966
4983
|
severity: warning
|
|
4967
4984
|
title: "Not using meta-tags gem"
|
|
4968
4985
|
description: "The meta-tags gem provides a clean API for SEO tags."
|
|
@@ -5035,6 +5052,7 @@ checks:
|
|
|
5035
5052
|
\`\`\`
|
|
5036
5053
|
|
|
5037
5054
|
- code: RAILS_TURBO_BREAKS_CRAWLERS
|
|
5055
|
+
indexable_only: true
|
|
5038
5056
|
severity: notice
|
|
5039
5057
|
title: "Turbo may affect JavaScript-dependent crawlers"
|
|
5040
5058
|
description: "Turbo Drive updates pages via JavaScript, which some crawlers may miss."
|
|
@@ -5157,6 +5175,7 @@ seo_challenges:
|
|
|
5157
5175
|
checks:
|
|
5158
5176
|
# Critical - these will severely hurt SEO
|
|
5159
5177
|
- code: REACT_CSR_DETECTED
|
|
5178
|
+
indexable_only: true
|
|
5160
5179
|
severity: error
|
|
5161
5180
|
title: "Client-side rendered React app detected"
|
|
5162
5181
|
description: "React apps without SSR send empty HTML to crawlers. Search engines may not index your content."
|
|
@@ -5172,6 +5191,7 @@ checks:
|
|
|
5172
5191
|
missing_content: true # Body has minimal text content
|
|
5173
5192
|
|
|
5174
5193
|
- code: REACT_NO_SSR_META
|
|
5194
|
+
indexable_only: true
|
|
5175
5195
|
severity: error
|
|
5176
5196
|
title: "Meta tags not server-rendered"
|
|
5177
5197
|
description: "Title and meta description are set client-side and won't be seen by crawlers."
|
|
@@ -5238,6 +5258,7 @@ checks:
|
|
|
5238
5258
|
\`\`\`
|
|
5239
5259
|
|
|
5240
5260
|
- code: REACT_ROUTER_NO_SSR
|
|
5261
|
+
indexable_only: true
|
|
5241
5262
|
severity: warning
|
|
5242
5263
|
title: "React Router without server-side support"
|
|
5243
5264
|
description: "Client-side routing breaks when crawlers access URLs directly."
|
|
@@ -5256,6 +5277,7 @@ checks:
|
|
|
5256
5277
|
\`\`\`
|
|
5257
5278
|
|
|
5258
5279
|
- code: REACT_NO_PRERENDER
|
|
5280
|
+
indexable_only: true
|
|
5259
5281
|
severity: warning
|
|
5260
5282
|
title: "No prerendering configured"
|
|
5261
5283
|
description: "Static pages could be prerendered for better SEO and performance."
|
|
@@ -5412,6 +5434,7 @@ checks:
|
|
|
5412
5434
|
- 'name="description"'
|
|
5413
5435
|
|
|
5414
5436
|
- code: SVELTEKIT_NO_PRERENDER
|
|
5437
|
+
indexable_only: true
|
|
5415
5438
|
severity: notice
|
|
5416
5439
|
title: "Static pages not prerendered"
|
|
5417
5440
|
description: "Static pages should be prerendered for best performance."
|
|
@@ -5517,6 +5540,7 @@ seo_challenges:
|
|
|
5517
5540
|
|
|
5518
5541
|
checks:
|
|
5519
5542
|
- code: VUE_CSR_DETECTED
|
|
5543
|
+
indexable_only: true
|
|
5520
5544
|
severity: error
|
|
5521
5545
|
title: "Client-side rendered Vue app detected"
|
|
5522
5546
|
description: "Vue apps without SSR send empty HTML to crawlers."
|
|
@@ -5533,6 +5557,7 @@ checks:
|
|
|
5533
5557
|
missing_content: true
|
|
5534
5558
|
|
|
5535
5559
|
- code: VUE_NO_META_MANAGEMENT
|
|
5560
|
+
indexable_only: true
|
|
5536
5561
|
severity: error
|
|
5537
5562
|
title: "No meta tag management library"
|
|
5538
5563
|
description: "Title and meta description are not dynamically managed."
|
|
@@ -7836,6 +7861,11 @@ var SIGNALS = [
|
|
|
7836
7861
|
// Sphinx: what nearly every Python project's documentation is built with, and the shape
|
|
7837
7862
|
// flask.palletsprojects.com turned out to be. Structural markers only - not the word
|
|
7838
7863
|
// "sphinx", which appears in plenty of prose.
|
|
7864
|
+
// Validated against docusaurus.io, jestjs.io and redux.js.org - all three carry the mount
|
|
7865
|
+
// point and the skip-to-content id. Deliberately not the word "docusaurus", which appears on
|
|
7866
|
+
// deno.com purely as a link in a logo list; that near-miss is why this needed a real marker.
|
|
7867
|
+
{ framework: "docusaurus", language: "typescript", weight: WEIGHT.DECISIVE, name: "docusaurus-root", html: /id=["']__docusaurus/ },
|
|
7868
|
+
{ framework: "docusaurus", language: "typescript", weight: WEIGHT.STRONG, name: "docusaurus-skip-link", html: /__docusaurus_skipToContent/ },
|
|
7839
7869
|
{ framework: "sphinx", language: "python", weight: WEIGHT.DECISIVE, name: "sphinx-doc-options", html: /_static\/documentation_options\.js/ },
|
|
7840
7870
|
{ framework: "sphinx", language: "python", weight: WEIGHT.STRONG, name: "sphinx-theme-markup", html: /class=["'][^"']*sphinxsidebar|sphinx-highlight|_static\/searchtools\.js/ },
|
|
7841
7871
|
{ framework: "sphinx", language: "python", weight: WEIGHT.STRONG, name: "docutils-generator", html: /name=["']?generator["']?[^>]*content=["']?Docutils/i }
|
|
@@ -8249,6 +8279,7 @@ function getFrameworkDisplayName(framework) {
|
|
|
8249
8279
|
eleventy: "Eleventy (11ty)",
|
|
8250
8280
|
pelican: "Pelican",
|
|
8251
8281
|
sphinx: "Sphinx",
|
|
8282
|
+
docusaurus: "Docusaurus",
|
|
8252
8283
|
unknown: "Unknown"
|
|
8253
8284
|
};
|
|
8254
8285
|
return names[framework];
|
|
@@ -8494,6 +8525,23 @@ function metaHasNoindex(content) {
|
|
|
8494
8525
|
if (!content) return false;
|
|
8495
8526
|
return content.toLowerCase().split(",").some((d) => ["noindex", "none"].includes(d.trim()));
|
|
8496
8527
|
}
|
|
8528
|
+
function readRobotsDirectives(html, headers) {
|
|
8529
|
+
const $ = cheerio.load(html);
|
|
8530
|
+
const metaValues = [];
|
|
8531
|
+
$("meta[name]").each((_, el) => {
|
|
8532
|
+
const name = ($(el).attr("name") || "").toLowerCase();
|
|
8533
|
+
if (name === "robots" || name === "googlebot") {
|
|
8534
|
+
metaValues.push($(el).attr("content") || "");
|
|
8535
|
+
}
|
|
8536
|
+
});
|
|
8537
|
+
const metaNoindex = metaValues.some(metaHasNoindex);
|
|
8538
|
+
const xRobotsTag = headers ? Object.entries(headers).find(([k]) => k.toLowerCase() === "x-robots-tag")?.[1] : void 0;
|
|
8539
|
+
const headerNoindex = xRobotsTagHasNoindex(xRobotsTag);
|
|
8540
|
+
return { metaValues, metaNoindex, xRobotsTag, headerNoindex, hasNoindex: metaNoindex || headerNoindex };
|
|
8541
|
+
}
|
|
8542
|
+
function pageHasNoindex(html, headers) {
|
|
8543
|
+
return readRobotsDirectives(html, headers).hasNoindex;
|
|
8544
|
+
}
|
|
8497
8545
|
function isSiteRoot(url) {
|
|
8498
8546
|
try {
|
|
8499
8547
|
const u = new URL(url);
|
|
@@ -8509,17 +8557,7 @@ function analyzeOnPage(html, url, headers, options = {}) {
|
|
|
8509
8557
|
const description = $('meta[name="description"]').attr("content")?.trim();
|
|
8510
8558
|
const canonical = $('link[rel="canonical"]').attr("href");
|
|
8511
8559
|
const metaRobots = $('meta[name="robots"]').attr("content");
|
|
8512
|
-
const robotsMetaValues =
|
|
8513
|
-
$("meta[name]").each((_, el) => {
|
|
8514
|
-
const name = ($(el).attr("name") || "").toLowerCase();
|
|
8515
|
-
if (name === "robots" || name === "googlebot") {
|
|
8516
|
-
robotsMetaValues.push($(el).attr("content") || "");
|
|
8517
|
-
}
|
|
8518
|
-
});
|
|
8519
|
-
const metaNoindex = robotsMetaValues.some(metaHasNoindex);
|
|
8520
|
-
const headerLookup = headers ? Object.entries(headers).find(([k]) => k.toLowerCase() === "x-robots-tag")?.[1] : void 0;
|
|
8521
|
-
const headerNoindex = xRobotsTagHasNoindex(headerLookup);
|
|
8522
|
-
const hasNoindex = metaNoindex || headerNoindex;
|
|
8560
|
+
const { metaValues: robotsMetaValues, metaNoindex, xRobotsTag: headerLookup, headerNoindex, hasNoindex } = readRobotsDirectives(html, headers);
|
|
8523
8561
|
const h1s = [];
|
|
8524
8562
|
$("h1").each((_, el) => {
|
|
8525
8563
|
h1s.push($(el).text().trim());
|
|
@@ -15940,6 +15978,17 @@ var NAMED_COLORS = {
|
|
|
15940
15978
|
transparent: [255, 255, 255]
|
|
15941
15979
|
// Treat as white for calculation
|
|
15942
15980
|
};
|
|
15981
|
+
function inheritedBackground($el) {
|
|
15982
|
+
for (const ancestor of $el.parents().toArray()) {
|
|
15983
|
+
const style = ancestor.attribs?.style;
|
|
15984
|
+
if (!style) continue;
|
|
15985
|
+
const match = style.match(/(?:^|;)\s*background(?:-color)?\s*:\s*([^;]+)/i);
|
|
15986
|
+
if (!match) continue;
|
|
15987
|
+
const value = match[1].trim();
|
|
15988
|
+
if (!/^(transparent|none)$/i.test(value)) return value;
|
|
15989
|
+
}
|
|
15990
|
+
return null;
|
|
15991
|
+
}
|
|
15943
15992
|
function analyzeColorContrast(html, url) {
|
|
15944
15993
|
const issues = [];
|
|
15945
15994
|
const $ = cheerio32.load(html);
|
|
@@ -15960,12 +16009,16 @@ function analyzeColorContrast(html, url) {
|
|
|
15960
16009
|
const colorMatch = style.match(/(?:^|;)\s*color\s*:\s*([^;]+)/i);
|
|
15961
16010
|
const bgMatch = style.match(/(?:^|;)\s*background(?:-color)?\s*:\s*([^;]+)/i);
|
|
15962
16011
|
const foreground = colorMatch ? colorMatch[1].trim() : null;
|
|
15963
|
-
const background = bgMatch ? bgMatch[1].trim() :
|
|
16012
|
+
const background = bgMatch ? bgMatch[1].trim() : inheritedBackground($el);
|
|
15964
16013
|
if (!foreground) {
|
|
15965
16014
|
cannotDetermine++;
|
|
15966
16015
|
return;
|
|
15967
16016
|
}
|
|
15968
|
-
|
|
16017
|
+
if (!background) {
|
|
16018
|
+
cannotDetermine++;
|
|
16019
|
+
return;
|
|
16020
|
+
}
|
|
16021
|
+
const bgColor = background;
|
|
15969
16022
|
const fgRgb = parseColor(foreground);
|
|
15970
16023
|
const bgRgb = parseColor(bgColor);
|
|
15971
16024
|
if (!fgRgb || !bgRgb) {
|
|
@@ -17661,7 +17714,9 @@ async function runFullAudit(options) {
|
|
|
17661
17714
|
asyncChecks.push(safeAsyncIssues("Framework Detection", async () => {
|
|
17662
17715
|
const frameworkInfo = detectFramework({ html, headers });
|
|
17663
17716
|
if (frameworkInfo.framework === "unknown") return [];
|
|
17664
|
-
return getFrameworkIssues(frameworkInfo, html, url
|
|
17717
|
+
return getFrameworkIssues(frameworkInfo, html, url, {
|
|
17718
|
+
indexable: !pageHasNoindex(html, headers)
|
|
17719
|
+
});
|
|
17665
17720
|
}));
|
|
17666
17721
|
if (runExtendedChecks) {
|
|
17667
17722
|
asyncChecks.push(safeAsync("Hreflang", () => analyzeHreflang(html, url, { validateUrls: checkHreflangUrls })));
|
|
@@ -32936,6 +32991,48 @@ function findAppRoot(files) {
|
|
|
32936
32991
|
return `${nonRoot[0]}/`;
|
|
32937
32992
|
}
|
|
32938
32993
|
|
|
32994
|
+
// src/fixer/served-dir.ts
|
|
32995
|
+
var SERVED_DIR = {
|
|
32996
|
+
// Bundlers and meta-frameworks that copy a public/ directory verbatim.
|
|
32997
|
+
react: "public/",
|
|
32998
|
+
vue: "public/",
|
|
32999
|
+
svelte: "public/",
|
|
33000
|
+
angular: "public/",
|
|
33001
|
+
solidjs: "public/",
|
|
33002
|
+
qwik: "public/",
|
|
33003
|
+
nextjs: "public/",
|
|
33004
|
+
nuxt: "public/",
|
|
33005
|
+
astro: "public/",
|
|
33006
|
+
sveltekit: "static/",
|
|
33007
|
+
// SvelteKit's is static/, not public/
|
|
33008
|
+
remix: "public/",
|
|
33009
|
+
fresh: "static/",
|
|
33010
|
+
// Gatsby, Hugo, Eleventy and Docusaurus all name theirs static/.
|
|
33011
|
+
gatsby: "static/",
|
|
33012
|
+
hugo: "static/",
|
|
33013
|
+
eleventy: "public/",
|
|
33014
|
+
docusaurus: "static/",
|
|
33015
|
+
// Server frameworks with a public document root.
|
|
33016
|
+
rails: "public/",
|
|
33017
|
+
laravel: "public/",
|
|
33018
|
+
symfony: "public/",
|
|
33019
|
+
phoenix: "priv/static/",
|
|
33020
|
+
spring: "src/main/resources/static/",
|
|
33021
|
+
aspnet: "wwwroot/",
|
|
33022
|
+
// Jekyll and Pelican copy their source tree, so the app root is the served root.
|
|
33023
|
+
jekyll: "",
|
|
33024
|
+
pelican: ""
|
|
33025
|
+
// Python web frameworks have no single convention; the tree decides below.
|
|
33026
|
+
};
|
|
33027
|
+
function servedDir(framework, files, appRoot = "") {
|
|
33028
|
+
const known = framework ? SERVED_DIR[framework] : void 0;
|
|
33029
|
+
if (known !== void 0) return known;
|
|
33030
|
+
for (const candidate of ["public/", "static/", "assets/"]) {
|
|
33031
|
+
if (files.some((f) => f.startsWith(`${appRoot}${candidate}`))) return candidate;
|
|
33032
|
+
}
|
|
33033
|
+
return "";
|
|
33034
|
+
}
|
|
33035
|
+
|
|
32939
33036
|
// src/fixer/safety.ts
|
|
32940
33037
|
var HTML_EXT = /\.html?$/i;
|
|
32941
33038
|
var SOURCE_EXT = /\.(ts|tsx|js|jsx|mjs|cjs|vue|svelte|astro)$/i;
|
|
@@ -35915,6 +36012,7 @@ var SUPPORTED_FRAMEWORKS = [
|
|
|
35915
36012
|
sendAlerts,
|
|
35916
36013
|
sendDiscordAlert,
|
|
35917
36014
|
sendSlackAlert,
|
|
36015
|
+
servedDir,
|
|
35918
36016
|
shouldRunAudit,
|
|
35919
36017
|
shouldSendAlert,
|
|
35920
36018
|
startWizardSession,
|
package/dist/index.mjs
CHANGED
|
@@ -95,6 +95,7 @@ var RECIPES = {
|
|
|
95
95
|
eleventy: null,
|
|
96
96
|
pelican: null,
|
|
97
97
|
sphinx: null,
|
|
98
|
+
docusaurus: null,
|
|
98
99
|
// Unknown
|
|
99
100
|
unknown: null
|
|
100
101
|
};
|
|
@@ -130,12 +131,13 @@ async function loadRecipe(framework) {
|
|
|
130
131
|
}
|
|
131
132
|
return null;
|
|
132
133
|
}
|
|
133
|
-
async function getFrameworkIssues(frameworkInfo, html, url) {
|
|
134
|
+
async function getFrameworkIssues(frameworkInfo, html, url, options = {}) {
|
|
134
135
|
const recipe = await loadRecipe(frameworkInfo.framework);
|
|
135
136
|
if (!recipe) return [];
|
|
136
137
|
const issues = [];
|
|
138
|
+
const indexable = options.indexable ?? true;
|
|
137
139
|
for (const check of recipe.checks) {
|
|
138
|
-
const matched = evaluateCheck(check, html, frameworkInfo);
|
|
140
|
+
const matched = evaluateCheck(check, html, frameworkInfo, indexable);
|
|
139
141
|
if (matched) {
|
|
140
142
|
issues.push({
|
|
141
143
|
code: check.code,
|
|
@@ -156,7 +158,10 @@ async function getFrameworkIssues(frameworkInfo, html, url) {
|
|
|
156
158
|
}
|
|
157
159
|
return issues;
|
|
158
160
|
}
|
|
159
|
-
function evaluateCheck(check, html, frameworkInfo) {
|
|
161
|
+
function evaluateCheck(check, html, frameworkInfo, indexable = true) {
|
|
162
|
+
if (check.indexable_only && !indexable) {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
160
165
|
if (check.app_router_only && html.includes("__next")) {
|
|
161
166
|
return false;
|
|
162
167
|
}
|
|
@@ -270,6 +275,7 @@ seo_challenges:
|
|
|
270
275
|
|
|
271
276
|
checks:
|
|
272
277
|
- code: ANGULAR_NO_UNIVERSAL
|
|
278
|
+
indexable_only: true
|
|
273
279
|
severity: error
|
|
274
280
|
title: "Angular app without Universal (SSR)"
|
|
275
281
|
description: "Client-side Angular apps send empty HTML to crawlers."
|
|
@@ -288,6 +294,7 @@ checks:
|
|
|
288
294
|
missing_content: true
|
|
289
295
|
|
|
290
296
|
- code: ANGULAR_NO_TITLE_SERVICE
|
|
297
|
+
indexable_only: true
|
|
291
298
|
severity: error
|
|
292
299
|
title: "Not using Title/Meta services"
|
|
293
300
|
description: "Angular has built-in services for managing title and meta tags."
|
|
@@ -336,6 +343,7 @@ checks:
|
|
|
336
343
|
\`\`\`
|
|
337
344
|
|
|
338
345
|
- code: ANGULAR_PRERENDER_MISSING
|
|
346
|
+
indexable_only: true
|
|
339
347
|
severity: warning
|
|
340
348
|
title: "Static routes not prerendered"
|
|
341
349
|
description: "Static pages should be prerendered at build time."
|
|
@@ -694,6 +702,7 @@ checks:
|
|
|
694
702
|
\`\`\`
|
|
695
703
|
|
|
696
704
|
- code: DJANGO_NO_META_FRAMEWORK
|
|
705
|
+
indexable_only: true
|
|
697
706
|
severity: warning
|
|
698
707
|
title: "No SEO meta framework detected"
|
|
699
708
|
description: "Use django-meta for consistent meta tag management."
|
|
@@ -841,6 +850,7 @@ seo_strengths:
|
|
|
841
850
|
|
|
842
851
|
checks:
|
|
843
852
|
- code: LARAVEL_NO_META_PACKAGE
|
|
853
|
+
indexable_only: true
|
|
844
854
|
severity: warning
|
|
845
855
|
title: "No SEO package detected"
|
|
846
856
|
description: "Laravel benefits from an SEO package like artesaos/seotools."
|
|
@@ -892,6 +902,7 @@ checks:
|
|
|
892
902
|
\`\`\`
|
|
893
903
|
|
|
894
904
|
- code: LARAVEL_INERTIA_NO_SSR
|
|
905
|
+
indexable_only: true
|
|
895
906
|
severity: error
|
|
896
907
|
title: "Inertia.js without SSR"
|
|
897
908
|
description: "Inertia apps are client-rendered by default, losing SEO benefits."
|
|
@@ -986,6 +997,7 @@ seo_strengths:
|
|
|
986
997
|
checks:
|
|
987
998
|
# App Router specific
|
|
988
999
|
- code: NEXTJS_NO_METADATA_API
|
|
1000
|
+
indexable_only: true
|
|
989
1001
|
severity: warning
|
|
990
1002
|
title: "Not using Next.js Metadata API"
|
|
991
1003
|
description: "Next.js 13+ has a built-in Metadata API that's better than react-helmet."
|
|
@@ -1258,6 +1270,7 @@ seo_strengths:
|
|
|
1258
1270
|
|
|
1259
1271
|
checks:
|
|
1260
1272
|
- code: NUXT_NO_USESEOMETA
|
|
1273
|
+
indexable_only: true
|
|
1261
1274
|
severity: warning
|
|
1262
1275
|
title: "Not using useSeoMeta composable"
|
|
1263
1276
|
description: "Nuxt 3 has built-in SEO meta composables that are cleaner than useHead."
|
|
@@ -1367,6 +1380,7 @@ checks:
|
|
|
1367
1380
|
\`\`\`
|
|
1368
1381
|
|
|
1369
1382
|
- code: NUXT_SPA_MODE
|
|
1383
|
+
indexable_only: true
|
|
1370
1384
|
severity: error
|
|
1371
1385
|
title: "Nuxt running in SPA mode"
|
|
1372
1386
|
description: "SPA mode disables SSR, losing SEO benefits."
|
|
@@ -1392,6 +1406,7 @@ checks:
|
|
|
1392
1406
|
missing_content: true
|
|
1393
1407
|
|
|
1394
1408
|
- code: NUXT_NO_PRERENDER
|
|
1409
|
+
indexable_only: true
|
|
1395
1410
|
severity: notice
|
|
1396
1411
|
title: "Static pages not pre-rendered"
|
|
1397
1412
|
description: "Static pages could be pre-rendered for better performance."
|
|
@@ -1435,6 +1450,7 @@ seo_strengths:
|
|
|
1435
1450
|
|
|
1436
1451
|
checks:
|
|
1437
1452
|
- code: RAILS_NO_META_TAGS_GEM
|
|
1453
|
+
indexable_only: true
|
|
1438
1454
|
severity: warning
|
|
1439
1455
|
title: "Not using meta-tags gem"
|
|
1440
1456
|
description: "The meta-tags gem provides a clean API for SEO tags."
|
|
@@ -1507,6 +1523,7 @@ checks:
|
|
|
1507
1523
|
\`\`\`
|
|
1508
1524
|
|
|
1509
1525
|
- code: RAILS_TURBO_BREAKS_CRAWLERS
|
|
1526
|
+
indexable_only: true
|
|
1510
1527
|
severity: notice
|
|
1511
1528
|
title: "Turbo may affect JavaScript-dependent crawlers"
|
|
1512
1529
|
description: "Turbo Drive updates pages via JavaScript, which some crawlers may miss."
|
|
@@ -1629,6 +1646,7 @@ seo_challenges:
|
|
|
1629
1646
|
checks:
|
|
1630
1647
|
# Critical - these will severely hurt SEO
|
|
1631
1648
|
- code: REACT_CSR_DETECTED
|
|
1649
|
+
indexable_only: true
|
|
1632
1650
|
severity: error
|
|
1633
1651
|
title: "Client-side rendered React app detected"
|
|
1634
1652
|
description: "React apps without SSR send empty HTML to crawlers. Search engines may not index your content."
|
|
@@ -1644,6 +1662,7 @@ checks:
|
|
|
1644
1662
|
missing_content: true # Body has minimal text content
|
|
1645
1663
|
|
|
1646
1664
|
- code: REACT_NO_SSR_META
|
|
1665
|
+
indexable_only: true
|
|
1647
1666
|
severity: error
|
|
1648
1667
|
title: "Meta tags not server-rendered"
|
|
1649
1668
|
description: "Title and meta description are set client-side and won't be seen by crawlers."
|
|
@@ -1710,6 +1729,7 @@ checks:
|
|
|
1710
1729
|
\`\`\`
|
|
1711
1730
|
|
|
1712
1731
|
- code: REACT_ROUTER_NO_SSR
|
|
1732
|
+
indexable_only: true
|
|
1713
1733
|
severity: warning
|
|
1714
1734
|
title: "React Router without server-side support"
|
|
1715
1735
|
description: "Client-side routing breaks when crawlers access URLs directly."
|
|
@@ -1728,6 +1748,7 @@ checks:
|
|
|
1728
1748
|
\`\`\`
|
|
1729
1749
|
|
|
1730
1750
|
- code: REACT_NO_PRERENDER
|
|
1751
|
+
indexable_only: true
|
|
1731
1752
|
severity: warning
|
|
1732
1753
|
title: "No prerendering configured"
|
|
1733
1754
|
description: "Static pages could be prerendered for better SEO and performance."
|
|
@@ -1884,6 +1905,7 @@ checks:
|
|
|
1884
1905
|
- 'name="description"'
|
|
1885
1906
|
|
|
1886
1907
|
- code: SVELTEKIT_NO_PRERENDER
|
|
1908
|
+
indexable_only: true
|
|
1887
1909
|
severity: notice
|
|
1888
1910
|
title: "Static pages not prerendered"
|
|
1889
1911
|
description: "Static pages should be prerendered for best performance."
|
|
@@ -1989,6 +2011,7 @@ seo_challenges:
|
|
|
1989
2011
|
|
|
1990
2012
|
checks:
|
|
1991
2013
|
- code: VUE_CSR_DETECTED
|
|
2014
|
+
indexable_only: true
|
|
1992
2015
|
severity: error
|
|
1993
2016
|
title: "Client-side rendered Vue app detected"
|
|
1994
2017
|
description: "Vue apps without SSR send empty HTML to crawlers."
|
|
@@ -2005,6 +2028,7 @@ checks:
|
|
|
2005
2028
|
missing_content: true
|
|
2006
2029
|
|
|
2007
2030
|
- code: VUE_NO_META_MANAGEMENT
|
|
2031
|
+
indexable_only: true
|
|
2008
2032
|
severity: error
|
|
2009
2033
|
title: "No meta tag management library"
|
|
2010
2034
|
description: "Title and meta description are not dynamically managed."
|
|
@@ -4305,6 +4329,11 @@ var SIGNALS = [
|
|
|
4305
4329
|
// Sphinx: what nearly every Python project's documentation is built with, and the shape
|
|
4306
4330
|
// flask.palletsprojects.com turned out to be. Structural markers only - not the word
|
|
4307
4331
|
// "sphinx", which appears in plenty of prose.
|
|
4332
|
+
// Validated against docusaurus.io, jestjs.io and redux.js.org - all three carry the mount
|
|
4333
|
+
// point and the skip-to-content id. Deliberately not the word "docusaurus", which appears on
|
|
4334
|
+
// deno.com purely as a link in a logo list; that near-miss is why this needed a real marker.
|
|
4335
|
+
{ framework: "docusaurus", language: "typescript", weight: WEIGHT.DECISIVE, name: "docusaurus-root", html: /id=["']__docusaurus/ },
|
|
4336
|
+
{ framework: "docusaurus", language: "typescript", weight: WEIGHT.STRONG, name: "docusaurus-skip-link", html: /__docusaurus_skipToContent/ },
|
|
4308
4337
|
{ framework: "sphinx", language: "python", weight: WEIGHT.DECISIVE, name: "sphinx-doc-options", html: /_static\/documentation_options\.js/ },
|
|
4309
4338
|
{ framework: "sphinx", language: "python", weight: WEIGHT.STRONG, name: "sphinx-theme-markup", html: /class=["'][^"']*sphinxsidebar|sphinx-highlight|_static\/searchtools\.js/ },
|
|
4310
4339
|
{ framework: "sphinx", language: "python", weight: WEIGHT.STRONG, name: "docutils-generator", html: /name=["']?generator["']?[^>]*content=["']?Docutils/i }
|
|
@@ -4718,6 +4747,7 @@ function getFrameworkDisplayName(framework) {
|
|
|
4718
4747
|
eleventy: "Eleventy (11ty)",
|
|
4719
4748
|
pelican: "Pelican",
|
|
4720
4749
|
sphinx: "Sphinx",
|
|
4750
|
+
docusaurus: "Docusaurus",
|
|
4721
4751
|
unknown: "Unknown"
|
|
4722
4752
|
};
|
|
4723
4753
|
return names[framework];
|
|
@@ -4962,6 +4992,23 @@ function metaHasNoindex(content) {
|
|
|
4962
4992
|
if (!content) return false;
|
|
4963
4993
|
return content.toLowerCase().split(",").some((d) => ["noindex", "none"].includes(d.trim()));
|
|
4964
4994
|
}
|
|
4995
|
+
function readRobotsDirectives(html, headers) {
|
|
4996
|
+
const $ = cheerio.load(html);
|
|
4997
|
+
const metaValues = [];
|
|
4998
|
+
$("meta[name]").each((_, el) => {
|
|
4999
|
+
const name = ($(el).attr("name") || "").toLowerCase();
|
|
5000
|
+
if (name === "robots" || name === "googlebot") {
|
|
5001
|
+
metaValues.push($(el).attr("content") || "");
|
|
5002
|
+
}
|
|
5003
|
+
});
|
|
5004
|
+
const metaNoindex = metaValues.some(metaHasNoindex);
|
|
5005
|
+
const xRobotsTag = headers ? Object.entries(headers).find(([k]) => k.toLowerCase() === "x-robots-tag")?.[1] : void 0;
|
|
5006
|
+
const headerNoindex = xRobotsTagHasNoindex(xRobotsTag);
|
|
5007
|
+
return { metaValues, metaNoindex, xRobotsTag, headerNoindex, hasNoindex: metaNoindex || headerNoindex };
|
|
5008
|
+
}
|
|
5009
|
+
function pageHasNoindex(html, headers) {
|
|
5010
|
+
return readRobotsDirectives(html, headers).hasNoindex;
|
|
5011
|
+
}
|
|
4965
5012
|
function isSiteRoot(url) {
|
|
4966
5013
|
try {
|
|
4967
5014
|
const u = new URL(url);
|
|
@@ -4977,17 +5024,7 @@ function analyzeOnPage(html, url, headers, options = {}) {
|
|
|
4977
5024
|
const description = $('meta[name="description"]').attr("content")?.trim();
|
|
4978
5025
|
const canonical = $('link[rel="canonical"]').attr("href");
|
|
4979
5026
|
const metaRobots = $('meta[name="robots"]').attr("content");
|
|
4980
|
-
const robotsMetaValues =
|
|
4981
|
-
$("meta[name]").each((_, el) => {
|
|
4982
|
-
const name = ($(el).attr("name") || "").toLowerCase();
|
|
4983
|
-
if (name === "robots" || name === "googlebot") {
|
|
4984
|
-
robotsMetaValues.push($(el).attr("content") || "");
|
|
4985
|
-
}
|
|
4986
|
-
});
|
|
4987
|
-
const metaNoindex = robotsMetaValues.some(metaHasNoindex);
|
|
4988
|
-
const headerLookup = headers ? Object.entries(headers).find(([k]) => k.toLowerCase() === "x-robots-tag")?.[1] : void 0;
|
|
4989
|
-
const headerNoindex = xRobotsTagHasNoindex(headerLookup);
|
|
4990
|
-
const hasNoindex = metaNoindex || headerNoindex;
|
|
5027
|
+
const { metaValues: robotsMetaValues, metaNoindex, xRobotsTag: headerLookup, headerNoindex, hasNoindex } = readRobotsDirectives(html, headers);
|
|
4991
5028
|
const h1s = [];
|
|
4992
5029
|
$("h1").each((_, el) => {
|
|
4993
5030
|
h1s.push($(el).text().trim());
|
|
@@ -12387,6 +12424,17 @@ var NAMED_COLORS = {
|
|
|
12387
12424
|
transparent: [255, 255, 255]
|
|
12388
12425
|
// Treat as white for calculation
|
|
12389
12426
|
};
|
|
12427
|
+
function inheritedBackground($el) {
|
|
12428
|
+
for (const ancestor of $el.parents().toArray()) {
|
|
12429
|
+
const style = ancestor.attribs?.style;
|
|
12430
|
+
if (!style) continue;
|
|
12431
|
+
const match = style.match(/(?:^|;)\s*background(?:-color)?\s*:\s*([^;]+)/i);
|
|
12432
|
+
if (!match) continue;
|
|
12433
|
+
const value = match[1].trim();
|
|
12434
|
+
if (!/^(transparent|none)$/i.test(value)) return value;
|
|
12435
|
+
}
|
|
12436
|
+
return null;
|
|
12437
|
+
}
|
|
12390
12438
|
function analyzeColorContrast(html, url) {
|
|
12391
12439
|
const issues = [];
|
|
12392
12440
|
const $ = cheerio32.load(html);
|
|
@@ -12407,12 +12455,16 @@ function analyzeColorContrast(html, url) {
|
|
|
12407
12455
|
const colorMatch = style.match(/(?:^|;)\s*color\s*:\s*([^;]+)/i);
|
|
12408
12456
|
const bgMatch = style.match(/(?:^|;)\s*background(?:-color)?\s*:\s*([^;]+)/i);
|
|
12409
12457
|
const foreground = colorMatch ? colorMatch[1].trim() : null;
|
|
12410
|
-
const background = bgMatch ? bgMatch[1].trim() :
|
|
12458
|
+
const background = bgMatch ? bgMatch[1].trim() : inheritedBackground($el);
|
|
12411
12459
|
if (!foreground) {
|
|
12412
12460
|
cannotDetermine++;
|
|
12413
12461
|
return;
|
|
12414
12462
|
}
|
|
12415
|
-
|
|
12463
|
+
if (!background) {
|
|
12464
|
+
cannotDetermine++;
|
|
12465
|
+
return;
|
|
12466
|
+
}
|
|
12467
|
+
const bgColor = background;
|
|
12416
12468
|
const fgRgb = parseColor(foreground);
|
|
12417
12469
|
const bgRgb = parseColor(bgColor);
|
|
12418
12470
|
if (!fgRgb || !bgRgb) {
|
|
@@ -14105,7 +14157,9 @@ async function runFullAudit(options) {
|
|
|
14105
14157
|
asyncChecks.push(safeAsyncIssues("Framework Detection", async () => {
|
|
14106
14158
|
const frameworkInfo = detectFramework({ html, headers });
|
|
14107
14159
|
if (frameworkInfo.framework === "unknown") return [];
|
|
14108
|
-
return getFrameworkIssues(frameworkInfo, html, url
|
|
14160
|
+
return getFrameworkIssues(frameworkInfo, html, url, {
|
|
14161
|
+
indexable: !pageHasNoindex(html, headers)
|
|
14162
|
+
});
|
|
14109
14163
|
}));
|
|
14110
14164
|
if (runExtendedChecks) {
|
|
14111
14165
|
asyncChecks.push(safeAsync("Hreflang", () => analyzeHreflang(html, url, { validateUrls: checkHreflangUrls })));
|
|
@@ -29365,6 +29419,48 @@ function findAppRoot(files) {
|
|
|
29365
29419
|
return `${nonRoot[0]}/`;
|
|
29366
29420
|
}
|
|
29367
29421
|
|
|
29422
|
+
// src/fixer/served-dir.ts
|
|
29423
|
+
var SERVED_DIR = {
|
|
29424
|
+
// Bundlers and meta-frameworks that copy a public/ directory verbatim.
|
|
29425
|
+
react: "public/",
|
|
29426
|
+
vue: "public/",
|
|
29427
|
+
svelte: "public/",
|
|
29428
|
+
angular: "public/",
|
|
29429
|
+
solidjs: "public/",
|
|
29430
|
+
qwik: "public/",
|
|
29431
|
+
nextjs: "public/",
|
|
29432
|
+
nuxt: "public/",
|
|
29433
|
+
astro: "public/",
|
|
29434
|
+
sveltekit: "static/",
|
|
29435
|
+
// SvelteKit's is static/, not public/
|
|
29436
|
+
remix: "public/",
|
|
29437
|
+
fresh: "static/",
|
|
29438
|
+
// Gatsby, Hugo, Eleventy and Docusaurus all name theirs static/.
|
|
29439
|
+
gatsby: "static/",
|
|
29440
|
+
hugo: "static/",
|
|
29441
|
+
eleventy: "public/",
|
|
29442
|
+
docusaurus: "static/",
|
|
29443
|
+
// Server frameworks with a public document root.
|
|
29444
|
+
rails: "public/",
|
|
29445
|
+
laravel: "public/",
|
|
29446
|
+
symfony: "public/",
|
|
29447
|
+
phoenix: "priv/static/",
|
|
29448
|
+
spring: "src/main/resources/static/",
|
|
29449
|
+
aspnet: "wwwroot/",
|
|
29450
|
+
// Jekyll and Pelican copy their source tree, so the app root is the served root.
|
|
29451
|
+
jekyll: "",
|
|
29452
|
+
pelican: ""
|
|
29453
|
+
// Python web frameworks have no single convention; the tree decides below.
|
|
29454
|
+
};
|
|
29455
|
+
function servedDir(framework, files, appRoot = "") {
|
|
29456
|
+
const known = framework ? SERVED_DIR[framework] : void 0;
|
|
29457
|
+
if (known !== void 0) return known;
|
|
29458
|
+
for (const candidate of ["public/", "static/", "assets/"]) {
|
|
29459
|
+
if (files.some((f) => f.startsWith(`${appRoot}${candidate}`))) return candidate;
|
|
29460
|
+
}
|
|
29461
|
+
return "";
|
|
29462
|
+
}
|
|
29463
|
+
|
|
29368
29464
|
// src/fixer/safety.ts
|
|
29369
29465
|
var HTML_EXT = /\.html?$/i;
|
|
29370
29466
|
var SOURCE_EXT = /\.(ts|tsx|js|jsx|mjs|cjs|vue|svelte|astro)$/i;
|
|
@@ -32336,6 +32432,7 @@ export {
|
|
|
32336
32432
|
sendAlerts,
|
|
32337
32433
|
sendDiscordAlert,
|
|
32338
32434
|
sendSlackAlert,
|
|
32435
|
+
servedDir,
|
|
32339
32436
|
shouldRunAudit,
|
|
32340
32437
|
shouldSendAlert,
|
|
32341
32438
|
startWizardSession,
|