use webpage_quality_analyzer::async_runtime::TokioRuntime;
use webpage_quality_analyzer::{
analyze, analyze_with_profile, from_config_file, Analyzer, AnalyzerBuilder, QualityBand,
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("📚 Comprehensive API Reference");
println!("==============================\n");
println!("🔥 Section 1: Core Analysis Functions");
println!("-------------------------------------");
demonstrate_analyze_function().await?;
demonstrate_analyze_with_profile().await?;
println!();
println!("🏗️ Section 2: Builder Pattern API");
println!("----------------------------------");
demonstrate_builder_api().await?;
println!();
println!("⚙️ Section 3: Configuration API");
println!("--------------------------------");
demonstrate_configuration_api().await?;
println!();
println!("📊 Section 4: Report Structure");
println!("------------------------------");
demonstrate_report_structure().await?;
println!();
println!("⚠️ Section 5: Error Handling");
println!("-----------------------------");
demonstrate_error_handling().await?;
println!();
println!("🚀 Section 6: Advanced Features");
println!("-------------------------------");
demonstrate_advanced_features().await?;
println!();
println!("✅ API Reference examples completed!");
println!();
println!("📖 Complete API Coverage:");
println!(" • All public functions demonstrated");
println!(" • Builder pattern with all options");
println!(" • Configuration file examples");
println!(" • Complete report structure breakdown");
println!(" • Comprehensive error handling");
println!(" • Advanced feature configuration");
Ok(())
}
async fn demonstrate_analyze_function() -> Result<(), Box<dyn std::error::Error>> {
println!("📖 analyze() function:");
println!(" Purpose: Simple, one-line webpage analysis");
println!(" Signature: async fn analyze(url: &str, html: Option<&str>) -> Result<PageQualityReport>");
println!();
println!(" Example 1: Automatic URL fetching");
match analyze("https://httpbin.org/html", None).await {
Ok(report) => {
println!(
" ✅ Score: {:.1}/100, Verdict: {}",
report.score, report.verdict
);
}
Err(e) => {
println!(" ❌ Error: {}", e);
}
}
println!(" Example 2: Provided HTML content");
let html = r#"<html><head><title>Test Page</title></head><body><h1>Hello</h1><p>Content here.</p></body></html>"#;
match analyze("https://example.com", Some(html)).await {
Ok(report) => {
println!(
" ✅ Score: {:.1}/100, Word count: {}",
report.score, report.metrics.html_analysis.content.word_count
);
}
Err(e) => {
println!(" ❌ Error: {}", e);
}
}
Ok(())
}
async fn demonstrate_analyze_with_profile() -> Result<(), Box<dyn std::error::Error>> {
println!();
println!("🎯 analyze_with_profile() function:");
println!(" Purpose: Profile-specific analysis for different content types");
println!(" Signature: async fn analyze_with_profile(url: &str, html: Option<&str>, profile: &str) -> Result<PageQualityReport>");
println!();
let test_html = r#"
<html>
<head><title>Test Content</title></head>
<body><h1>Main Title</h1><p>Sample content for testing different profiles.</p></body>
</html>
"#;
let profiles = ["content_article", "news", "blog", "product"];
for profile in &profiles {
match analyze_with_profile("https://example.com", Some(test_html), profile).await {
Ok(report) => {
println!(
" Profile '{}': {:.1}/100 ({})",
profile, report.score, report.verdict
);
}
Err(e) => {
println!(" Profile '{}': ❌ {}", profile, e);
}
}
}
Ok(())
}
async fn demonstrate_builder_api() -> Result<(), Box<dyn std::error::Error>> {
println!("🏗️ Analyzer::builder() API:");
println!(" Purpose: Configurable analyzer creation with fine-grained control");
println!();
println!(" 📝 Basic Builder:");
let basic_analyzer: Analyzer = Analyzer::builder().build()?;
println!(" Created with default settings");
println!(
" Active profile: {}",
basic_analyzer.get_active_profile_name()?
);
println!();
println!(" 🎯 Profile Configuration:");
let profile_analyzer: Analyzer = Analyzer::builder().with_profile_name("news")?.build()?;
println!(
" Profile set to: {}",
profile_analyzer.get_active_profile_name()?
);
println!();
println!(" ⚙️ Feature Configuration:");
let feature_analyzer: Analyzer = Analyzer::builder()
.with_profile_name("content_article")?
.enable_linkcheck(true)
.linkcheck_sample(25)
.enable_nlp(true)
.add_report(true)
.build()?;
println!(" ✅ Link checking enabled (sample: 25)");
println!(" ✅ NLP features enabled");
println!(" ✅ Detailed reporting enabled");
let test_html = r#"
<html>
<head><title>Builder Test</title></head>
<body>
<h1>Testing Builder Configuration</h1>
<p>This content tests the configured analyzer settings.</p>
<a href="https://example.com">External link</a>
</body>
</html>
"#;
match feature_analyzer
.run("https://test.example.com", Some(test_html))
.await
{
Ok(report) => {
println!(" Analysis result: {:.1}/100", report.score);
}
Err(e) => {
println!(" Analysis failed: {}", e);
}
}
println!();
println!(" 📋 Available Builder Methods:");
println!(" • with_profile_name(name: &str) -> Result<Self, AnalyzeError>");
println!(" • enable_linkcheck(enable: bool) -> Self");
println!(" • linkcheck_sample(sample_size: usize) -> Self");
println!(" • enable_nlp(enable: bool) -> Self");
println!(" • add_report(enable: bool) -> Self");
println!(" • build() -> Result<Analyzer, AnalyzeError>");
Ok(())
}
async fn demonstrate_configuration_api() -> Result<(), Box<dyn std::error::Error>> {
println!("📋 Configuration File API:");
println!(" Purpose: Load analyzer configuration from external files");
println!();
let sample_config = r#"
active_profile: "demo"
presets:
demo:
description: "Demo configuration for API reference"
weights:
content: 0.6
structure: 0.2
seo: 0.15
technical: 0.05
authority: 0.0
content:
breakdown:
text: 0.8
image: 0.2
video: 0.0
output:
verbosity: "normal"
"#;
std::fs::write("demo_config.yaml", sample_config)?;
println!(" 📄 from_config_file() function:");
println!(" Signature: fn from_config_file<P: AsRef<Path>>(path: P) -> Result<Analyzer>");
match from_config_file("demo_config.yaml") {
Ok(config_analyzer) => {
println!(" ✅ Configuration loaded successfully");
println!(
" Active profile: {}",
config_analyzer.get_active_profile_name()?
);
let html = r#"<html><head><title>Config Test</title></head><body><h1>Test</h1><p>Testing configuration.</p></body></html>"#;
if let Ok(report) = config_analyzer
.run("https://config-test.example.com", Some(html))
.await
{
println!(" Analysis score: {:.1}/100", report.score);
}
}
Err(e) => {
println!(" ❌ Configuration failed: {}", e);
}
}
let _ = std::fs::remove_file("demo_config.yaml");
println!();
println!(" 📋 Supported Configuration Formats:");
println!(" • YAML (.yaml, .yml)");
println!(" • JSON (.json)");
println!(" • TOML (.toml)");
println!();
println!(" ⚙️ Configuration Structure:");
println!(" • active_profile: string");
println!(" • presets: map of profile configurations");
println!(" • output: output formatting options");
println!(" • bands: quality score bands");
println!(" • plugins: plugin configuration");
Ok(())
}
async fn demonstrate_report_structure() -> Result<(), Box<dyn std::error::Error>> {
println!("📊 PageQualityReport Structure:");
println!(" Complete breakdown of the analysis report");
println!();
let analyzer: Analyzer = Analyzer::builder()
.with_profile_name("content_article")?
.add_report(true) .build()?;
let comprehensive_html = r#"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Comprehensive Report Test</title>
<meta name="description" content="Testing comprehensive report structure">
<meta name="author" content="API Demo">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<h1>Report Structure Demo</h1>
<h2>Content Section</h2>
<p>This content demonstrates the complete report structure returned by the analyzer.</p>
<h3>Subsection</h3>
<p>Additional content to provide more comprehensive metrics.</p>
<img src="demo.jpg" alt="Demo image">
<a href="https://example.com">External link</a>
</body>
</html>
"#;
match analyzer
.run("https://demo.example.com", Some(comprehensive_html))
.await
{
Ok(report) => {
println!(" 📈 Top-level Report Fields:");
println!(" • url: {}", report.url);
println!(" • fetched_at: {:?}", report.fetched_at);
println!(" • score: {:.1}", report.score);
println!(" • verdict: {} (enum QualityBand)", report.verdict);
println!(" • version: {}", report.version);
println!(" • notes: {} items", report.notes.len());
println!();
println!(" 📋 ExtractedMetadata Fields:");
println!(" • title: \"{}\"", report.metadata.title);
println!(
" • meta_description: {:?}",
report.metadata.meta_description
);
println!(" • author: {:?}", report.metadata.author);
println!(" • language: {:?}", report.metadata.language);
println!(" • charset: {:?}", report.metadata.charset);
println!(" • viewport: {:?}", report.metadata.viewport);
println!(" • og_tags: {} items", report.metadata.og_tags.len());
println!(
" • twitter_tags: {} items",
report.metadata.twitter_tags.len()
);
println!();
println!(" 📊 PageMetrics Structure:");
println!(" • html_analysis: PageMetricsFromHTML (86 metrics)");
println!(" • network_analysis: Option<PageMetricsFullFetch> (23 metrics)");
println!(" • analysis_mode: {:?}", report.metrics.analysis_mode);
println!(
" • javascript_rendered: {}",
report.metrics.javascript_rendered
);
println!();
println!(" 📝 HTML Analysis Breakdown:");
let html_metrics = &report.metrics.html_analysis;
println!(" Content Metrics:");
println!(" • word_count: {}", html_metrics.content.word_count);
println!(
" • reading_time_minutes: {:.1}",
html_metrics.content.reading_time_minutes
);
println!(
" • main_text_ratio: {:.2}",
html_metrics.content.main_text_ratio
);
println!(
" • unique_word_ratio: {:.2}",
html_metrics.content.unique_word_ratio
);
println!(" Structure Metrics:");
println!(
" • headings_count: {}",
html_metrics.structure.headings_count
);
println!(
" • heading_depth: {}",
html_metrics.structure.heading_depth
);
println!(
" • heading_order_score: {:.1}",
html_metrics.structure.heading_order_score
);
println!(
" • paragraph_count: {}",
html_metrics.structure.paragraph_count
);
println!(" SEO Metrics:");
println!(" • title_len: {}", html_metrics.seo.title_len);
println!(
" • meta_desc_len: {:?}",
html_metrics.seo.meta_desc_len
);
println!(" • og_tags: {}", html_metrics.seo.og_tags);
println!(
" • viewport_tag_present: {}",
html_metrics.seo.viewport_tag_present
);
println!(" Media Metrics:");
println!(" • images_count: {}", html_metrics.media.images_count);
println!(
" • image_alt_coverage: {:.2}",
html_metrics.media.image_alt_coverage
);
println!(
" • missing_alt_text_count: {}",
html_metrics.media.missing_alt_text_count
);
println!(" Link Metrics:");
println!(" • total_links: {}", html_metrics.links.total_links);
println!(
" • internal_links: {}",
html_metrics.links.internal_links
);
println!(
" • external_links: {}",
html_metrics.links.external_links
);
println!(" Technical Metrics:");
println!(" • html_bytes: {}", html_metrics.technical.html_bytes);
println!(
" • technical_score: {:.1}",
html_metrics.technical.technical_score
);
println!();
println!(" 📄 ProcessedDocument Fields:");
println!(
" • cleaned_text: {} chars",
report.processed_document.cleaned_text.len()
);
println!(
" • headings: {} items",
report.processed_document.headings.len()
);
println!(
" • links: {} items",
report.processed_document.links.len()
);
println!(
" • images: {} items",
report.processed_document.images.len()
);
println!(
" • forms: {} items",
report.processed_document.forms.len()
);
}
Err(e) => {
println!(" ❌ Report generation failed: {}", e);
}
}
println!();
println!(" 🎯 QualityBand Enum Values:");
let bands = [
QualityBand::Excellent,
QualityBand::Good,
QualityBand::Fair,
QualityBand::Poor,
QualityBand::VeryPoor,
];
for band in &bands {
println!(" • QualityBand::{:?} - \"{}\"", band, band);
}
Ok(())
}
async fn demonstrate_error_handling() -> Result<(), Box<dyn std::error::Error>> {
println!("⚠️ Error Handling:");
println!(" AnalyzeError enum variants and handling patterns");
println!();
println!(" 🔍 Error Types:");
println!(" 1. InvalidUrl:");
match analyze("", None).await {
Ok(_) => println!(" Unexpected success"),
Err(e) => println!(" ✅ Caught: {}", e),
}
println!(" 2. InvalidProfile:");
match Analyzer::builder().with_profile_name("nonexistent_profile") {
Ok::<AnalyzerBuilder<TokioRuntime>, _>(_) => println!(" Unexpected success"),
Err(e) => println!(" ✅ Caught: {}", e),
}
println!(" 3. ParseError:");
match analyze("https://example.com", Some("")).await {
Ok(report) => println!(" ⚠️ Handled gracefully: {:.1}/100", report.score),
Err(e) => println!(" ✅ Caught: {}", e),
}
println!(" 4. NetworkError:");
match analyze("https://definitely-does-not-exist-12345.invalid", None).await {
Ok(_) => println!(" Unexpected success"),
Err(e) => println!(" ✅ Caught: {}", e),
}
println!();
println!(" 📋 Error Handling Best Practices:");
println!(" • Always use Result<T, AnalyzeError> return type");
println!(" • Handle each error variant appropriately");
println!(" • Provide meaningful error messages to users");
println!(" • Log errors for debugging purposes");
println!(" • Implement retry logic for network errors");
println!(" • Validate inputs before processing");
println!();
println!(" 💡 Example Error Handling Pattern:");
println!(
r#" match analyzer.run(url, html).await {{
Ok(report) => {{
// Process successful analysis
println!("Score: {{}}", report.score);
}}
Err(AnalyzeError::NetworkError(e)) => {{
// Handle network issues - maybe retry
eprintln!("Network error: {{}}", e);
}}
Err(AnalyzeError::InvalidUrl(e)) => {{
// Handle URL validation errors
eprintln!("Invalid URL: {{}}", e);
}}
Err(e) => {{
// Handle other errors
eprintln!("Analysis failed: {{}}", e);
}}
}}"#
);
Ok(())
}
async fn demonstrate_advanced_features() -> Result<(), Box<dyn std::error::Error>> {
println!("🚀 Advanced Features:");
println!(" Specialized functionality and configuration options");
println!();
println!(" 📋 Profile Management:");
let analyzer: Analyzer = Analyzer::builder().build()?;
let available_profiles = analyzer.get_available_profiles();
println!(" Available profiles: {:?}", available_profiles);
println!(
" Current profile: {}",
analyzer.get_active_profile_name()?
);
println!();
println!(" 🎛️ Feature Configuration:");
let _advanced_analyzer: Analyzer = Analyzer::builder()
.with_profile_name("content_article")?
.enable_linkcheck(true)
.linkcheck_sample(50)
.enable_nlp(true)
.add_report(true)
.build()?;
println!(" ✅ Link checking: enabled (sample size: 50)");
println!(" ✅ NLP processing: enabled");
println!(" ✅ Detailed reporting: enabled");
println!();
println!(" ⚡ Performance Optimization:");
println!(" • Disable unused features for faster analysis");
println!(" • Use smaller link samples for speed");
println!(" • Set add_report(false) for minimal output");
println!(" • Reuse analyzer instances for batch processing");
let fast_analyzer: Analyzer = Analyzer::builder()
.enable_linkcheck(false)
.enable_nlp(false)
.add_report(false)
.build()?;
let start = std::time::Instant::now();
let _ = fast_analyzer
.run(
"https://example.com",
Some("<html><head><title>Fast</title></head><body><p>Speed test</p></body></html>"),
)
.await;
let duration = start.elapsed();
println!(" Fast analysis completed in: {:?}", duration);
println!();
println!(" 📦 Batch Processing:");
let batch_urls = vec![
"https://example1.com",
"https://example2.com",
"https://example3.com",
];
let batch_analyzer: Analyzer = Analyzer::builder()
.with_profile_name("blog")?
.add_report(false)
.build()?;
println!(" Processing {} URLs...", batch_urls.len());
let mut successful = 0;
for url in batch_urls {
let html = format!("<html><head><title>Test {}</title></head><body><h1>Content</h1><p>Test content for {}.</p></body></html>", url, url);
if let Ok(_) = batch_analyzer.run(url, Some(&html)).await {
successful += 1;
}
}
println!(" ✅ Successfully processed {}/3 URLs", successful);
println!();
println!(" 💾 Memory Management:");
println!(" • Analyzer instances are lightweight and reusable");
println!(" • Reports contain all analysis data - clone selectively");
println!(" • Use add_report(false) to reduce memory usage");
println!(" • Large HTML documents may require more memory");
Ok(())
}