a11yanalyze
Version:
A command-line tool for developers and QA engineers to test web pages and websites for WCAG 2.2 AA accessibility compliance
409 lines (388 loc) • 9.91 kB
text/typescript
/**
* Site crawler type definitions
* Defines interfaces for multi-page accessibility scanning with crawling capabilities
*/
import { ScanResult, ScanOptions } from './index';
/**
* Crawler configuration options
*/
export interface CrawlerConfig {
/** Maximum crawl depth (0 = single page, unlimited = -1) */
maxDepth: number;
/** Maximum number of pages to crawl */
maxPages: number;
/** Allowed domains for crawling (empty = any domain) */
allowedDomains: string[];
/** Domain patterns to exclude */
excludedDomains: string[];
/** URL patterns to exclude (regex patterns) */
excludedPaths: string[];
/** URL patterns to include (regex patterns, empty = include all) */
includedPaths: string[];
/** Rate limiting: delay between requests in milliseconds */
requestDelay: number;
/** Maximum concurrent requests */
maxConcurrency: number;
/** Follow robots.txt directives */
respectRobotsTxt: boolean;
/** Include external links in discovery (but don't follow) */
discoverExternalLinks: boolean;
/** Enable sitemap discovery and parsing */
useSitemaps: boolean;
/** Custom User-Agent string */
userAgent: string;
/** Request timeout in milliseconds */
requestTimeout: number;
}
/**
* URL discovery sources
*/
export type URLDiscoverySource = 'initial' | 'page' | 'sitemap' | 'robots' | 'manual';
/**
* URL entry with metadata
*/
export interface URLEntry {
/** The URL to crawl */
url: string;
/** Crawl depth of this URL */
depth: number;
/** How this URL was discovered */
source: URLDiscoverySource;
/** Parent URL that led to this discovery */
parent?: string;
/** Priority for crawling (higher = more important) */
priority: number;
/** When this URL was discovered */
discoveredAt: Date;
/** When this URL was last attempted */
lastAttempt?: Date;
/** Number of attempts made */
attempts: number;
/** Current status of this URL */
status: URLStatus;
/** Error information if failed */
error?: string;
}
/**
* URL processing status
*/
export type URLStatus =
| 'pending' // Waiting to be processed
| 'processing' // Currently being processed
| 'completed' // Successfully processed
| 'failed' // Failed processing
| 'skipped' // Skipped due to filters/limits
| 'excluded'; // Excluded by configuration
/**
* Crawl session state
*/
export interface CrawlSession {
/** Unique session identifier */
id: string;
/** Base URLs where crawling started */
startUrls: string[];
/** Crawl configuration */
config: CrawlerConfig;
/** Scan options for individual pages */
scanOptions: Partial<ScanOptions>;
/** Session start time */
startTime: Date;
/** Session end time (if completed) */
endTime?: Date;
/** Current session status */
status: CrawlStatus;
/** All discovered URLs with their metadata */
urls: Map<string, URLEntry>;
/** Completed scan results */
results: Map<string, ScanResult>;
/** Session statistics */
stats: CrawlStats;
/** Error information if session failed */
error?: string;
}
/**
* Crawl session status
*/
export type CrawlStatus =
| 'initializing' // Setting up crawl session
| 'discovering' // Finding URLs to crawl
| 'crawling' // Actively crawling pages
| 'paused' // Temporarily paused
| 'completed' // Successfully completed
| 'failed' // Failed with errors
| 'cancelled'; // Manually cancelled
/**
* Crawl statistics
*/
export interface CrawlStats {
/** URLs by status */
urlCounts: {
total: number;
pending: number;
processing: number;
completed: number;
failed: number;
skipped: number;
excluded: number;
};
/** Pages successfully scanned */
pagesScanned: number;
/** Total accessibility issues found */
totalIssues: number;
/** Issues by severity */
issuesBySeverity: {
critical: number;
serious: number;
moderate: number;
minor: number;
warning: number;
};
/** Average accessibility score */
averageScore: number;
/** Crawl performance metrics */
performance: {
avgPageLoadTime: number;
avgScanTime: number;
totalCrawlTime: number;
pagesPerMinute: number;
};
/** WCAG compliance statistics */
wcagCompliance: {
compliantPages: number;
nonCompliantPages: number;
complianceRate: number;
levelBreakdown: {
A: number;
AA: number;
AAA: number;
ARIA: number;
};
};
}
/**
* URL discovery result
*/
export interface URLDiscoveryResult {
/** URLs discovered */
urls: URLEntry[];
/** Source of discovery */
source: URLDiscoverySource;
/** Parent URL (if applicable) */
parent?: string;
/** Any errors during discovery */
errors: string[];
}
/**
* Sitemap information
*/
export interface SitemapInfo {
/** Sitemap URL */
url: string;
/** Last modification time */
lastModified?: Date;
/** URLs found in sitemap */
urls: SitemapURL[];
/** Nested sitemaps */
sitemaps: string[];
}
/**
* Sitemap URL entry
*/
export interface SitemapURL {
/** The URL */
url: string;
/** Last modification time */
lastModified?: Date;
/** Change frequency */
changeFreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never';
/** Priority (0.0 to 1.0) */
priority?: number;
}
/**
* Robots.txt information
*/
export interface RobotsInfo {
/** User-agent rules */
userAgent: string;
/** Disallowed paths */
disallow: string[];
/** Allowed paths */
allow: string[];
/** Sitemap URLs */
sitemaps: string[];
/** Crawl delay in seconds */
crawlDelay?: number;
}
/**
* Crawl event types for progress tracking
*/
export type CrawlEventType =
| 'session_started'
| 'session_completed'
| 'session_failed'
| 'session_paused'
| 'session_resumed'
| 'url_discovered'
| 'url_started'
| 'url_completed'
| 'url_failed'
| 'url_skipped'
| 'depth_limit_reached'
| 'page_limit_reached'
| 'rate_limit_applied';
/**
* Crawl event data
*/
export interface CrawlEvent {
/** Event type */
type: CrawlEventType;
/** Event timestamp */
timestamp: Date;
/** Session ID */
sessionId: string;
/** URL associated with event (if applicable) */
url?: string;
/** Additional event data */
data?: any;
/** Error information (if applicable) */
error?: string;
}
/**
* Crawl result aggregation options
*/
export interface AggregationOptions {
/** Group results by domain */
groupByDomain: boolean;
/** Group results by page type/template */
groupByPageType: boolean;
/** Include individual page results */
includeIndividualResults: boolean;
/** Sort order for results */
sortBy: 'url' | 'score' | 'issues' | 'depth' | 'discoveredAt';
/** Sort direction */
sortDirection: 'asc' | 'desc';
/** Filter results by score threshold */
minScore?: number;
/** Filter results by issue count */
maxIssues?: number;
}
/**
* Aggregated crawl results
*/
export interface AggregatedCrawlResults {
/** Session information */
session: Pick<CrawlSession, 'id' | 'startUrls' | 'config' | 'startTime' | 'endTime' | 'status'>;
/** Overall statistics */
stats: CrawlStats;
/** Results grouped by domain */
domainResults?: Map<string, DomainResults>;
/** Results grouped by page type */
pageTypeResults?: Map<string, PageTypeResults>;
/** Individual page results */
pageResults?: ScanResult[];
/** Top issues across all pages */
topIssues: IssuesSummary[];
/** Compliance summary */
complianceSummary: ComplianceSummary;
}
/**
* Domain-specific results
*/
export interface DomainResults {
/** Domain name */
domain: string;
/** Number of pages scanned */
pageCount: number;
/** Average accessibility score */
averageScore: number;
/** Total issues found */
totalIssues: number;
/** Issues by severity */
issuesBySeverity: CrawlStats['issuesBySeverity'];
/** Most common issues */
commonIssues: IssuesSummary[];
/** WCAG compliance rate */
complianceRate: number;
}
/**
* Page type results
*/
export interface PageTypeResults {
/** Page type identifier */
pageType: string;
/** Number of pages of this type */
pageCount: number;
/** Average accessibility score */
averageScore: number;
/** Common issues for this page type */
commonIssues: IssuesSummary[];
/** Example URLs of this type */
exampleUrls: string[];
}
/**
* Issue summary for aggregation
*/
export interface IssuesSummary {
/** Issue identifier */
id: string;
/** WCAG reference */
wcagReference: string;
/** WCAG level */
level: string;
/** Issue description */
description: string;
/** Number of occurrences */
count: number;
/** Number of pages affected */
pagesAffected: number;
/** Severity level */
severity: string;
/** Remediation guidance */
remediation: string;
}
/**
* Compliance summary
*/
export interface ComplianceSummary {
/** Overall compliance rate */
overallCompliance: number;
/** Compliance by WCAG level */
levelCompliance: {
A: number;
AA: number;
AAA: number;
};
/** Pages meeting each level */
compliantPages: {
A: number;
AA: number;
AAA: number;
};
/** Total pages scanned */
totalPages: number;
/** Domains with compliance issues */
problematicDomains: string[];
}
/**
* Crawler progress information
*/
export interface CrawlProgress {
/** Current session status */
status: CrawlStatus;
/** Progress percentage (0-100) */
percentage: number;
/** URLs processed */
urlsProcessed: number;
/** Total URLs discovered */
totalUrls: number;
/** Current crawl depth */
currentDepth: number;
/** Pages scanned per minute */
scanRate: number;
/** Estimated time remaining (milliseconds) */
estimatedTimeRemaining?: number;
/** Current URL being processed */
currentUrl?: string;
/** Recent errors */
recentErrors: string[];
}