waddling-errors 0.7.3

Structured, secure-by-default diagnostic codes for distributed systems with no_std and role-based documentation
Documentation
//! Example demonstrating HTML customization features
//!
//! This example shows how to customize the generated HTML documentation
//! with custom CSS, logos, accent colors, and more.

use waddling_errors::doc_generator::{DocRegistry, HtmlCustomization, HtmlRenderer};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create a registry with some example errors
    let mut registry = DocRegistry::new("CustomProject", "1.0.0");

    registry
        .register(
            "E.CUSTOM.ERROR.001",
            "This demonstrates the customization features of the HTML documentation generator.",
            &[
                "Check the documentation for styling options",
                "Use HtmlCustomization to brand your docs",
            ],
            &["example", "styling"],
        )
        .expect("Valid error code");

    registry
        .register(
            "W.CUSTOM.WARNING.001",
            "Notice the custom accent colors and styling applied to this documentation.",
            &[
                "Custom branding helps users identify your project",
                "Add your logo for recognition",
            ],
            &["example", "styling", "branding"],
        )
        .expect("Valid error code");

    registry
        .register(
            "I.CUSTOM.INFO.001",
            "Information messages can also be customized with your project's theme.",
            &["Consistent styling across severity levels"],
            &["example"],
        )
        .expect("Valid error code");

    println!("=== Basic HTML (No Customization) ===");
    let basic_renderer = HtmlRenderer::new();
    registry.render(vec![Box::new(basic_renderer)], "target/docs/basic")?;
    println!("✓ Generated basic HTML at target/docs/basic/index.html");

    println!("\n=== Custom Branding ===");
    // Example 1: Simple branding with logo and colors
    let branding = HtmlCustomization::new()
        .with_logo(
            "https://raw.githubusercontent.com/rust-lang/rust-artwork/master/logo/rust-logo-128x128.png",
            "CustomProject Logo"
        )
        .with_accent_color("#FF5722", "#FF8A65");

    let branded_renderer = HtmlRenderer::with_customization(branding);
    registry.render(vec![Box::new(branded_renderer)], "target/docs/branded")?;
    println!("✓ Generated branded HTML at target/docs/branded/index.html");

    println!("\n=== Custom CSS & Styling ===");
    // Example 2: Custom CSS overrides
    let custom_css = r#"
        /* Custom styling example */
        .error-card {
            border-radius: 16px;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
        }

        .error-card:hover {
            transform: translateY(-2px);
            transition: transform 0.2s ease;
        }

        h1 {
            font-family: 'Georgia', serif;
        }
    "#;

    let styled = HtmlCustomization::new()
        .with_custom_css(custom_css.to_string())
        .with_accent_color("#9C27B0", "#BA68C8");

    let styled_renderer = HtmlRenderer::with_customization(styled);
    registry.render(vec![Box::new(styled_renderer)], "target/docs/styled")?;
    println!("✓ Generated styled HTML at target/docs/styled/index.html");

    println!("\n=== Custom Footer ===");
    // Example 3: Custom footer
    let with_footer = HtmlCustomization::new()
        .with_footer("<p style='text-align: center; margin-top: 2rem; color: #666;'>© 2025 CustomProject | Documentation powered by waddling-errors</p>");

    let footer_renderer = HtmlRenderer::with_customization(with_footer);
    registry.render(vec![Box::new(footer_renderer)], "target/docs/footer")?;
    println!("✓ Generated HTML with footer at target/docs/footer/index.html");

    println!("\n=== Complete Replacement ===");
    // Example 4: Complete CSS replacement (advanced)
    let minimal_css = r#"
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body {
            font-family: monospace;
            background: #000;
            color: #0f0;
            padding: 20px;
        }
        .error-card {
            border: 2px solid #0f0;
            margin: 10px 0;
            padding: 10px;
        }
        h1 { color: #0f0; }
        a { color: #0ff; }
    "#;

    let replaced = HtmlCustomization::new().replace_css(minimal_css.to_string());

    let replaced_renderer = HtmlRenderer::with_customization(replaced);
    registry.render(vec![Box::new(replaced_renderer)], "target/docs/replaced")?;
    println!("✓ Generated HTML with replaced CSS at target/docs/replaced/index.html");

    println!("\n=== Data URI Logo ===");
    // Example 5: Using a data URI for logo (embedded image)
    let data_uri_logo = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E%3Ccircle cx='16' cy='16' r='14' fill='%23FF5722'/%3E%3C/svg%3E";

    let with_data_uri = HtmlCustomization::new()
        .with_logo(data_uri_logo, "Orange Circle Logo")
        .with_accent_color("#FF5722", "#FF8A65");

    let data_uri_renderer = HtmlRenderer::with_customization(with_data_uri);
    registry.render(vec![Box::new(data_uri_renderer)], "target/docs/data-uri")?;
    println!("✓ Generated HTML with data URI logo at target/docs/data-uri/index.html");

    println!("\n✅ All customization examples generated successfully!");
    println!("Open the HTML files in your browser to see the different styles.");

    Ok(())
}