cbrowser 18.19.0 → 18.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analysis/accessibility-empathy.d.ts.map +1 -1
- package/dist/analysis/accessibility-empathy.js +2 -1
- package/dist/analysis/accessibility-empathy.js.map +1 -1
- package/dist/analysis/agent-ready-audit.d.ts.map +1 -1
- package/dist/analysis/agent-ready-audit.js +2 -1
- package/dist/analysis/agent-ready-audit.js.map +1 -1
- package/dist/analysis/competitive-benchmark.d.ts.map +1 -1
- package/dist/analysis/competitive-benchmark.js +2 -1
- package/dist/analysis/competitive-benchmark.js.map +1 -1
- package/dist/browser.d.ts +20 -1
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +98 -0
- package/dist/browser.js.map +1 -1
- package/dist/cli.js +259 -27
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/lightpanda.d.ts +184 -0
- package/dist/lightpanda.d.ts.map +1 -0
- package/dist/lightpanda.js +416 -0
- package/dist/lightpanda.js.map +1 -0
- package/dist/remediation/llms-txt.d.ts.map +1 -1
- package/dist/remediation/llms-txt.js +2 -1
- package/dist/remediation/llms-txt.js.map +1 -1
- package/dist/remediation/structured-data.d.ts.map +1 -1
- package/dist/remediation/structured-data.js +2 -1
- package/dist/remediation/structured-data.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { CBrowser } from "./browser.js";
|
|
13
13
|
// Analysis module imports
|
|
14
|
-
import { executeNaturalLanguage, executeNaturalLanguageScript, huntBugs, runChaosTest, comparePersonas, formatComparisonReport, findElementByIntent, runAgentReadyAudit, formatAgentReadyReport, generateAgentReadyHtmlReport, runCompetitiveBenchmark, formatCompetitiveBenchmarkReport, generateCompetitiveBenchmarkHtmlReport, runEmpathyAudit, formatEmpathyAuditReport, generateEmpathyAuditHtmlReport, runWebMCPReadyAudit, generateWebMCPReadyHtmlReport } from "./analysis/index.js";
|
|
14
|
+
import { executeNaturalLanguage, executeNaturalLanguageScript, huntBugs, runChaosTest, comparePersonas, formatComparisonReport, findElementByIntent, runAgentReadyAudit, formatAgentReadyReport, generateAgentReadyHtmlReport, runCompetitiveBenchmark, formatCompetitiveBenchmarkReport, generateCompetitiveBenchmarkHtmlReport, runEmpathyAudit, formatEmpathyAuditReport, generateEmpathyAuditHtmlReport, runWebMCPReadyAudit, generateWebMCPReadyHtmlReport, runAIReadinessBenchmark } from "./analysis/index.js";
|
|
15
15
|
// Testing module imports
|
|
16
16
|
import { parseNLInstruction, parseNLTestSuite, runNLTestSuite, formatNLTestReport, dryRunNLTestSuite, repairTestSuite, formatRepairReport, exportRepairedTest, detectFlakyTests, formatFlakyTestReport, generateCoverageMap, formatCoverageReport, generateCoverageHtmlReport } from "./testing/index.js";
|
|
17
17
|
// Performance module imports
|
|
@@ -26,6 +26,8 @@ import { startDaemon, stopDaemon, getDaemonStatus, isDaemonRunning, sendToDaemon
|
|
|
26
26
|
import { getStatusInfo, formatStatus, getDataDir } from "./config.js";
|
|
27
27
|
import { printEnterpriseStatus } from "./stealth/index.js";
|
|
28
28
|
import { runCognitiveJourney, getAnthropicApiKey, setAnthropicApiKey, removeAnthropicApiKey, isApiKeyConfigured, } from "./cognitive/index.js";
|
|
29
|
+
// Lightpanda integration (v18.20.0) - OPT-IN ONLY with security guardrails
|
|
30
|
+
import { getLightpandaStatus, LIGHTPANDA_SETUP_GUIDE, LIGHTPANDA_SECURITY_WARNING, } from "./lightpanda.js";
|
|
29
31
|
// Version from package.json - single source of truth
|
|
30
32
|
import { VERSION } from "./version.js";
|
|
31
33
|
// Node readline for interactive input
|
|
@@ -403,60 +405,77 @@ A/B VISUAL COMPARISON (v7.3.0)
|
|
|
403
405
|
"options": { "sensitivity": "medium" }
|
|
404
406
|
}
|
|
405
407
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
--url <url> Navigate to URL first
|
|
409
|
-
a11y audit [url] Audit a specific URL
|
|
408
|
+
AI FRIENDLINESS - Audit sites for AI agent compatibility
|
|
409
|
+
══════════════════════════════════════════════════════════════════════════════
|
|
410
410
|
|
|
411
|
-
|
|
412
|
-
|
|
411
|
+
agent-ready-audit <url> Audit site for AI-agent friendliness (A-F grade)
|
|
412
|
+
--headless Run in headless mode (default: true)
|
|
413
413
|
--output <file> Save JSON report to file
|
|
414
414
|
--html Generate HTML report
|
|
415
|
+
Grades sites on: Findability (35%), Stability (30%),
|
|
416
|
+
Accessibility (20%), Semantics (15%)
|
|
415
417
|
Examples:
|
|
416
418
|
cbrowser agent-ready-audit "https://example.com"
|
|
417
419
|
cbrowser agent-ready-audit "https://example.com" --html --output report.json
|
|
418
420
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
--sites <list> Comma-separated site URLs (required)
|
|
422
|
-
--goal <goal> Task goal (required)
|
|
423
|
-
--persona <name> Persona to use (default: first-timer)
|
|
424
|
-
--max-steps <n> Max steps per site (default: 30)
|
|
425
|
-
--max-time <sec> Max time per site in seconds (default: 180)
|
|
421
|
+
ai-benchmark Compare AI-friendliness across multiple sites
|
|
422
|
+
--urls <list> Comma-separated URLs to benchmark (required)
|
|
426
423
|
--output <file> Save JSON report to file
|
|
427
424
|
--html Generate HTML report
|
|
425
|
+
Runs agent-ready-audit on each URL and produces ranked comparison.
|
|
428
426
|
Examples:
|
|
429
|
-
cbrowser
|
|
430
|
-
|
|
431
|
-
--goal "sign up for free trial" \\
|
|
432
|
-
--html
|
|
427
|
+
cbrowser ai-benchmark --urls "https://site1.com,https://site2.com,https://site3.com"
|
|
428
|
+
cbrowser ai-benchmark --urls "https://amazon.com,https://ebay.com" --html
|
|
433
429
|
|
|
434
|
-
ACCESSIBILITY EMPATHY AUDIT (v8.0.0)
|
|
435
430
|
empathy-audit <url> Simulate disability experience on site
|
|
436
431
|
--goal <goal> Task goal (required)
|
|
437
|
-
--
|
|
432
|
+
--personas <list> Disability personas (comma-separated)
|
|
438
433
|
--wcag-level <level> WCAG level: A, AA, AAA (default: AA)
|
|
439
434
|
--output <file> Save JSON report to file
|
|
440
435
|
--html Generate HTML report
|
|
441
|
-
Available
|
|
436
|
+
Available personas:
|
|
442
437
|
motor-impairment-tremor, low-vision-magnified, cognitive-adhd,
|
|
443
438
|
dyslexic-user, deaf-user, elderly-low-vision, color-blind-deuteranopia
|
|
444
439
|
Examples:
|
|
445
440
|
cbrowser empathy-audit "https://example.com" \\
|
|
446
441
|
--goal "complete checkout" \\
|
|
447
|
-
--
|
|
448
|
-
--html
|
|
442
|
+
--personas "motor-impairment-tremor,cognitive-adhd" --html
|
|
449
443
|
|
|
450
|
-
|
|
451
|
-
webmcp-ready <url> Audit MCP server for Claude in Chrome compatibility
|
|
444
|
+
webmcp-ready <url> Audit MCP server for WebMCP compatibility
|
|
452
445
|
--api-key <key> API key for authenticated servers
|
|
453
446
|
--oauth-token <token> OAuth token for OAuth-protected servers
|
|
454
|
-
--timeout <ms> Request timeout
|
|
447
|
+
--timeout <ms> Request timeout (default: 30000)
|
|
455
448
|
--output <file> Save JSON report to file
|
|
456
449
|
--html Generate HTML report
|
|
450
|
+
6-tier evaluation: Server (25%), Tools (20%), Instrumentation (15%),
|
|
451
|
+
Consistency (15%), Agent Opts (15%), Docs (10%)
|
|
457
452
|
Examples:
|
|
458
453
|
cbrowser webmcp-ready "https://demo.cbrowser.ai/mcp"
|
|
459
|
-
cbrowser webmcp-ready "https://your-server.com/mcp" --api-key
|
|
454
|
+
cbrowser webmcp-ready "https://your-server.com/mcp" --api-key KEY --html
|
|
455
|
+
|
|
456
|
+
hunt-bugs <url> Automatically find UX bugs on a page
|
|
457
|
+
--max-pages <n> Max pages to crawl (default: 10)
|
|
458
|
+
--timeout <ms> Timeout in ms (default: 60000)
|
|
459
|
+
Examples:
|
|
460
|
+
cbrowser hunt-bugs "https://example.com"
|
|
461
|
+
|
|
462
|
+
competitive-benchmark Compare UX across competitor sites
|
|
463
|
+
--sites <list> Comma-separated site URLs (required)
|
|
464
|
+
--goal <goal> Task goal (required)
|
|
465
|
+
--persona <name> Persona to use (default: first-timer)
|
|
466
|
+
--max-steps <n> Max steps per site (default: 30)
|
|
467
|
+
--max-time <sec> Max time per site (default: 180)
|
|
468
|
+
--output <file> Save JSON report to file
|
|
469
|
+
--html Generate HTML report
|
|
470
|
+
Examples:
|
|
471
|
+
cbrowser competitive-benchmark \\
|
|
472
|
+
--sites "https://yoursite.com,https://competitor.com" \\
|
|
473
|
+
--goal "sign up for free trial" --html
|
|
474
|
+
|
|
475
|
+
ACCESSIBILITY (v2.5.0)
|
|
476
|
+
a11y audit Run WCAG accessibility audit
|
|
477
|
+
--url <url> Navigate to URL first
|
|
478
|
+
a11y audit [url] Audit a specific URL
|
|
460
479
|
|
|
461
480
|
TEST RECORDING (v2.5.0)
|
|
462
481
|
record start Start recording interactions
|
|
@@ -584,6 +603,22 @@ API CONFIGURATION (v8.0.0)
|
|
|
584
603
|
config remove-api-key Remove stored API key
|
|
585
604
|
config set-model <model> Set Claude model (default: claude-sonnet-4-20250514)
|
|
586
605
|
|
|
606
|
+
LIGHTPANDA (v18.20.0) - High-Performance Headless Browser (OPT-IN ONLY)
|
|
607
|
+
lightpanda-status Check Lightpanda availability and configuration
|
|
608
|
+
lightpanda-setup Show setup instructions with security warnings
|
|
609
|
+
⚠️ SECURITY NOTICE:
|
|
610
|
+
• Lightpanda is BETA software with no security audit
|
|
611
|
+
• Cloud mode exposes traffic to lightpanda.io servers
|
|
612
|
+
• NEVER use for auth, credentials, or payments
|
|
613
|
+
• Requires explicit --lightpanda flag (not automatic)
|
|
614
|
+
Environment Variables:
|
|
615
|
+
LIGHTPANDA_ENDPOINT WebSocket endpoint (e.g., ws://127.0.0.1:9222)
|
|
616
|
+
LIGHTPANDA_TOKEN Cloud API token (⚠️ data visible to lightpanda.io)
|
|
617
|
+
Examples:
|
|
618
|
+
cbrowser lightpanda-status
|
|
619
|
+
cbrowser screenshot https://example.com --lightpanda
|
|
620
|
+
cbrowser agent-ready-audit https://example.com --lightpanda
|
|
621
|
+
|
|
587
622
|
DIAGNOSTICS
|
|
588
623
|
version, -v, --version Show version number
|
|
589
624
|
status Show environment status and diagnostics
|
|
@@ -3760,6 +3795,59 @@ Documentation: https://github.com/alexandriashai/cbrowser/wiki
|
|
|
3760
3795
|
break;
|
|
3761
3796
|
}
|
|
3762
3797
|
// =========================================================================
|
|
3798
|
+
// Lightpanda Integration (v18.20.0) - OPT-IN ONLY
|
|
3799
|
+
// =========================================================================
|
|
3800
|
+
case "lightpanda-status": {
|
|
3801
|
+
console.log("\n🐼 Lightpanda Status\n");
|
|
3802
|
+
const status = await getLightpandaStatus();
|
|
3803
|
+
if (!status.configured) {
|
|
3804
|
+
console.log("❌ Not configured");
|
|
3805
|
+
console.log("");
|
|
3806
|
+
console.log("To enable Lightpanda, set one of these environment variables:");
|
|
3807
|
+
console.log(" LIGHTPANDA_ENDPOINT=ws://127.0.0.1:9222 (local, recommended)");
|
|
3808
|
+
console.log(" LIGHTPANDA_TOKEN=your-api-token (cloud, ⚠️ data exposure)");
|
|
3809
|
+
console.log("");
|
|
3810
|
+
console.log("Run 'cbrowser lightpanda-setup' for full setup instructions.");
|
|
3811
|
+
}
|
|
3812
|
+
else if (status.available) {
|
|
3813
|
+
console.log("✅ Available and connected");
|
|
3814
|
+
console.log(` Endpoint: ${status.endpoint}`);
|
|
3815
|
+
console.log(` Mode: ${status.isCloud ? "Cloud ⚠️ (traffic via lightpanda.io)" : "Local (recommended)"}`);
|
|
3816
|
+
console.log("");
|
|
3817
|
+
// Show security warning for cloud mode
|
|
3818
|
+
if (status.isCloud && status.securityWarning) {
|
|
3819
|
+
console.log(status.securityWarning);
|
|
3820
|
+
console.log("");
|
|
3821
|
+
}
|
|
3822
|
+
console.log("Usage (OPT-IN REQUIRED):");
|
|
3823
|
+
console.log(" cbrowser screenshot https://example.com --lightpanda");
|
|
3824
|
+
console.log(" cbrowser agent-ready-audit https://example.com --lightpanda");
|
|
3825
|
+
console.log("");
|
|
3826
|
+
console.log("Note: Lightpanda is NOT used automatically. The --lightpanda flag is required.");
|
|
3827
|
+
}
|
|
3828
|
+
else {
|
|
3829
|
+
console.log("⚠️ Configured but unavailable");
|
|
3830
|
+
console.log(` Endpoint: ${status.endpoint}`);
|
|
3831
|
+
console.log(` Error: ${status.error}`);
|
|
3832
|
+
console.log("");
|
|
3833
|
+
if (!status.isCloud) {
|
|
3834
|
+
console.log("Make sure Lightpanda is running:");
|
|
3835
|
+
console.log(" docker run -d -p 9222:9222 lightpanda/browser:nightly");
|
|
3836
|
+
}
|
|
3837
|
+
else {
|
|
3838
|
+
console.log("Check your API token and network connection.");
|
|
3839
|
+
}
|
|
3840
|
+
}
|
|
3841
|
+
// Always show security notice
|
|
3842
|
+
console.log("");
|
|
3843
|
+
console.log(LIGHTPANDA_SECURITY_WARNING);
|
|
3844
|
+
break;
|
|
3845
|
+
}
|
|
3846
|
+
case "lightpanda-setup": {
|
|
3847
|
+
console.log(LIGHTPANDA_SETUP_GUIDE);
|
|
3848
|
+
break;
|
|
3849
|
+
}
|
|
3850
|
+
// =========================================================================
|
|
3763
3851
|
// Natural Language Test Suites (Tier 6)
|
|
3764
3852
|
// =========================================================================
|
|
3765
3853
|
case "test-suite": {
|
|
@@ -4578,6 +4666,150 @@ Documentation: https://github.com/alexandriashai/cbrowser/wiki
|
|
|
4578
4666
|
}
|
|
4579
4667
|
break;
|
|
4580
4668
|
}
|
|
4669
|
+
case "ai-benchmark": {
|
|
4670
|
+
const urlsOption = options.urls;
|
|
4671
|
+
if (!urlsOption) {
|
|
4672
|
+
console.error("Error: --urls required");
|
|
4673
|
+
console.error("Usage: cbrowser ai-benchmark --urls <url1,url2,...> [--output <file>] [--html]");
|
|
4674
|
+
process.exit(1);
|
|
4675
|
+
}
|
|
4676
|
+
const urls = urlsOption.split(",").map(u => u.trim());
|
|
4677
|
+
if (urls.length < 2) {
|
|
4678
|
+
console.error("Error: At least 2 URLs required for benchmark comparison");
|
|
4679
|
+
process.exit(1);
|
|
4680
|
+
}
|
|
4681
|
+
console.log(`\n🏁 Running AI Readiness Benchmark on ${urls.length} sites...\n`);
|
|
4682
|
+
const result = await runAIReadinessBenchmark({
|
|
4683
|
+
urls,
|
|
4684
|
+
headless: options.headless !== false,
|
|
4685
|
+
maxConcurrency: options.concurrency ? parseInt(options.concurrency) : 3,
|
|
4686
|
+
});
|
|
4687
|
+
// Print ranking table
|
|
4688
|
+
console.log(`╔══════════════════════════════════════════════════════════════════════════════╗`);
|
|
4689
|
+
console.log(`║ AI Readiness Benchmark Results ║`);
|
|
4690
|
+
console.log(`╠══════════════════════════════════════════════════════════════════════════════╣`);
|
|
4691
|
+
console.log(`║ Rank Site Score Grade Find Stab A11y Sem ║`);
|
|
4692
|
+
console.log(`╠══════════════════════════════════════════════════════════════════════════════╣`);
|
|
4693
|
+
for (const site of result.sites) {
|
|
4694
|
+
const rank = result.ranking.find(r => r.site === site.siteName)?.rank || "-";
|
|
4695
|
+
const score = site.score !== null ? site.score.toString().padStart(3) : "ERR";
|
|
4696
|
+
const grade = site.grade || "-";
|
|
4697
|
+
const find = site.scoreBreakdown?.findability?.toString().padStart(3) || "-";
|
|
4698
|
+
const stab = site.scoreBreakdown?.stability?.toString().padStart(3) || "-";
|
|
4699
|
+
const a11y = site.scoreBreakdown?.accessibility?.toString().padStart(3) || "-";
|
|
4700
|
+
const sem = site.scoreBreakdown?.semantics?.toString().padStart(3) || "-";
|
|
4701
|
+
const siteName = site.siteName.substring(0, 32).padEnd(32);
|
|
4702
|
+
console.log(`║ ${String(rank).padStart(2)} ${siteName} ${score} ${grade.padEnd(2)} ${find} ${stab} ${a11y} ${sem} ║`);
|
|
4703
|
+
}
|
|
4704
|
+
console.log(`╚══════════════════════════════════════════════════════════════════════════════╝`);
|
|
4705
|
+
console.log(`\nDuration: ${result.duration}ms`);
|
|
4706
|
+
// Print best-in-class
|
|
4707
|
+
if (result.comparison.bestOverall) {
|
|
4708
|
+
console.log(`\n🏆 Best Overall: ${result.comparison.bestOverall}`);
|
|
4709
|
+
}
|
|
4710
|
+
if (result.comparison.bestFindability) {
|
|
4711
|
+
console.log(`🔍 Best Findability: ${result.comparison.bestFindability}`);
|
|
4712
|
+
}
|
|
4713
|
+
if (result.comparison.bestStability) {
|
|
4714
|
+
console.log(`🔒 Best Stability: ${result.comparison.bestStability}`);
|
|
4715
|
+
}
|
|
4716
|
+
if (result.comparison.bestAccessibility) {
|
|
4717
|
+
console.log(`♿ Best Accessibility: ${result.comparison.bestAccessibility}`);
|
|
4718
|
+
}
|
|
4719
|
+
if (result.comparison.bestSemantics) {
|
|
4720
|
+
console.log(`📋 Best Semantics: ${result.comparison.bestSemantics}`);
|
|
4721
|
+
}
|
|
4722
|
+
// Print recommendations
|
|
4723
|
+
if (result.recommendations.length > 0) {
|
|
4724
|
+
console.log(`\n📝 Recommendations:`);
|
|
4725
|
+
for (const rec of result.recommendations.slice(0, 5)) {
|
|
4726
|
+
console.log(` • ${rec}`);
|
|
4727
|
+
}
|
|
4728
|
+
}
|
|
4729
|
+
// Save JSON output if requested
|
|
4730
|
+
if (options.output) {
|
|
4731
|
+
const fs = await import("fs");
|
|
4732
|
+
fs.writeFileSync(options.output, JSON.stringify(result, null, 2));
|
|
4733
|
+
console.log(`\n📄 JSON report saved: ${options.output}`);
|
|
4734
|
+
}
|
|
4735
|
+
// Generate HTML report if requested
|
|
4736
|
+
if (options.html) {
|
|
4737
|
+
const fs = await import("fs");
|
|
4738
|
+
const htmlPath = options.output?.replace(".json", ".html") || "ai-benchmark-report.html";
|
|
4739
|
+
// Simple HTML table report
|
|
4740
|
+
const html = `<!DOCTYPE html>
|
|
4741
|
+
<html lang="en">
|
|
4742
|
+
<head>
|
|
4743
|
+
<meta charset="UTF-8">
|
|
4744
|
+
<title>AI Readiness Benchmark Report</title>
|
|
4745
|
+
<style>
|
|
4746
|
+
body { font-family: system-ui, sans-serif; max-width: 1200px; margin: 0 auto; padding: 2rem; }
|
|
4747
|
+
h1 { color: #333; }
|
|
4748
|
+
table { width: 100%; border-collapse: collapse; margin: 2rem 0; }
|
|
4749
|
+
th, td { padding: 0.75rem; text-align: left; border-bottom: 1px solid #ddd; }
|
|
4750
|
+
th { background: #f5f5f5; font-weight: 600; }
|
|
4751
|
+
.grade-A { color: #22c55e; font-weight: bold; }
|
|
4752
|
+
.grade-B { color: #84cc16; font-weight: bold; }
|
|
4753
|
+
.grade-C { color: #eab308; font-weight: bold; }
|
|
4754
|
+
.grade-D { color: #f97316; font-weight: bold; }
|
|
4755
|
+
.grade-F { color: #ef4444; font-weight: bold; }
|
|
4756
|
+
.best { background: #f0fdf4; }
|
|
4757
|
+
.timestamp { color: #666; font-size: 0.875rem; }
|
|
4758
|
+
</style>
|
|
4759
|
+
</head>
|
|
4760
|
+
<body>
|
|
4761
|
+
<h1>🏁 AI Readiness Benchmark Report</h1>
|
|
4762
|
+
<p class="timestamp">Generated: ${result.timestamp} | Duration: ${result.duration}ms</p>
|
|
4763
|
+
|
|
4764
|
+
<h2>Rankings</h2>
|
|
4765
|
+
<table>
|
|
4766
|
+
<thead>
|
|
4767
|
+
<tr><th>Rank</th><th>Site</th><th>Score</th><th>Grade</th><th>Findability</th><th>Stability</th><th>Accessibility</th><th>Semantics</th></tr>
|
|
4768
|
+
</thead>
|
|
4769
|
+
<tbody>
|
|
4770
|
+
${result.sites.map(site => {
|
|
4771
|
+
const rank = result.ranking.find(r => r.site === site.siteName)?.rank || "-";
|
|
4772
|
+
const isBest = result.comparison.bestOverall === site.siteName;
|
|
4773
|
+
return `<tr class="${isBest ? 'best' : ''}">
|
|
4774
|
+
<td>${rank}</td>
|
|
4775
|
+
<td>${site.siteName}</td>
|
|
4776
|
+
<td>${site.score ?? 'ERR'}</td>
|
|
4777
|
+
<td class="grade-${site.grade || 'F'}">${site.grade || '-'}</td>
|
|
4778
|
+
<td>${site.scoreBreakdown?.findability ?? '-'}</td>
|
|
4779
|
+
<td>${site.scoreBreakdown?.stability ?? '-'}</td>
|
|
4780
|
+
<td>${site.scoreBreakdown?.accessibility ?? '-'}</td>
|
|
4781
|
+
<td>${site.scoreBreakdown?.semantics ?? '-'}</td>
|
|
4782
|
+
</tr>`;
|
|
4783
|
+
}).join('')}
|
|
4784
|
+
</tbody>
|
|
4785
|
+
</table>
|
|
4786
|
+
|
|
4787
|
+
<h2>Best in Class</h2>
|
|
4788
|
+
<ul>
|
|
4789
|
+
${result.comparison.bestOverall ? `<li>🏆 Overall: <strong>${result.comparison.bestOverall}</strong></li>` : ''}
|
|
4790
|
+
${result.comparison.bestFindability ? `<li>🔍 Findability: <strong>${result.comparison.bestFindability}</strong></li>` : ''}
|
|
4791
|
+
${result.comparison.bestStability ? `<li>🔒 Stability: <strong>${result.comparison.bestStability}</strong></li>` : ''}
|
|
4792
|
+
${result.comparison.bestAccessibility ? `<li>♿ Accessibility: <strong>${result.comparison.bestAccessibility}</strong></li>` : ''}
|
|
4793
|
+
${result.comparison.bestSemantics ? `<li>📋 Semantics: <strong>${result.comparison.bestSemantics}</strong></li>` : ''}
|
|
4794
|
+
</ul>
|
|
4795
|
+
|
|
4796
|
+
${result.recommendations.length > 0 ? `
|
|
4797
|
+
<h2>Recommendations</h2>
|
|
4798
|
+
<ul>
|
|
4799
|
+
${result.recommendations.map(r => `<li>${r}</li>`).join('')}
|
|
4800
|
+
</ul>
|
|
4801
|
+
` : ''}
|
|
4802
|
+
|
|
4803
|
+
<footer style="margin-top: 3rem; padding-top: 1rem; border-top: 1px solid #ddd; color: #666; font-size: 0.875rem;">
|
|
4804
|
+
Generated by <a href="https://cbrowser.ai">CBrowser</a> v${(await import("./version.js")).VERSION}
|
|
4805
|
+
</footer>
|
|
4806
|
+
</body>
|
|
4807
|
+
</html>`;
|
|
4808
|
+
fs.writeFileSync(htmlPath, html);
|
|
4809
|
+
console.log(`🌐 HTML report saved: ${htmlPath}`);
|
|
4810
|
+
}
|
|
4811
|
+
break;
|
|
4812
|
+
}
|
|
4581
4813
|
case "webmcp-ready": {
|
|
4582
4814
|
const url = args[0];
|
|
4583
4815
|
if (!url) {
|