forme 0.1.1

Compile-time HTML template engine — plain HTML templates with tpl-* directives generate type-safe Rust rendering functions
Documentation
// Showcase Example: Demonstrates the template system
// This example generates HTML output using the template system

use std::fs;

// Import types from types module
mod types;

// Import generated template code as a standalone module
// The generated code references types using super::types::Item paths
mod generated;

// Re-export the render functions for convenience
use generated::{render_card, render_page, render_showcase, render_simple};
// Re-export types for convenience
use types::{Item, User};

fn main() {
    println!("Template System Showcase Example");
    println!("=================================\n");

    // Render templates to HTML
    render_all_examples();
}

fn render_all_examples() {
    // Render simple template (no arguments needed)
    let mut simple_html = String::new();
    if let Err(e) = render_simple(&mut simple_html) {
        eprintln!("Error rendering simple template: {}", e);
    } else {
        let output_path = "examples/simple_output.html";
        fs::write(output_path, &simple_html).expect("Failed to write simple output");
        println!("✓ Generated simple.html");
        println!("  Output: {}", output_path);
        println!("  Size: {} bytes", simple_html.len());
        println!();
    }

    // Render card template with sample data
    {
        let title = "Sample Card";
        let content = "This is a card component rendered from the card.html template!";

        let mut card_html = String::new();
        if let Err(e) = render_card(&mut card_html, title, content, "") {
            eprintln!("Error rendering card template: {}", e);
        } else {
            let output_path = "examples/card_output.html";
            fs::write(output_path, &card_html).expect("Failed to write card output");
            println!("✓ Generated card.html");
            println!("  Output: {}", output_path);
            println!("  Size: {} bytes", card_html.len());
            println!();
        }
    }

    // Render showcase template with full sample data
    {
        let title = "Advanced Template Features";
        let show_header = true;
        let status = "active";
        let id = 123u32;
        let is_enabled = true;
        let is_readonly = false;
        let input_value = "Sample Input";
        let is_active = true;

        let items = vec![
            Item {
                id: 1,
                name: "Laptop".to_string(),
                price: 999.99,
                in_stock: true,
                is_featured: true,
            },
            Item {
                id: 2,
                name: "Keyboard".to_string(),
                price: 79.99,
                in_stock: true,
                is_featured: false,
            },
            Item {
                id: 3,
                name: "Mouse".to_string(),
                price: 49.99,
                in_stock: false,
                is_featured: false,
            },
            Item {
                id: 4,
                name: "Monitor".to_string(),
                price: 299.99,
                in_stock: true,
                is_featured: true,
            },
            Item {
                id: 5,
                name: "Headphones".to_string(),
                price: 149.99,
                in_stock: false,
                is_featured: false,
            },
        ];

        let user = Some(User {
            id: 42,
            name: "Alice".to_string(),
            email: "alice@example.com".to_string(),
            is_admin: true,
        });

        let mut showcase_html = String::new();
        if let Err(e) = render_showcase(
            &mut showcase_html,
            title,
            show_header,
            &items,
            user.as_ref(),
            status,
            id,
            is_enabled,
            is_readonly,
            input_value,
            is_active,
        ) {
            eprintln!("Error rendering showcase template: {}", e);
        } else {
            let output_path = "examples/showcase_output.html";
            fs::write(output_path, &showcase_html).expect("Failed to write showcase output");
            println!("✓ Generated showcase.html");
            println!("  Output: {}", output_path);
            println!("  Size: {} bytes", showcase_html.len());
            println!();
        }
        let mut page_html = String::new();
        if let Err(e) = render_page(&mut page_html) {
            eprintln!("Error rendering showcase template: {}", e);
        } else {
            let output_path = "examples/page_output.html";
            fs::write(output_path, &page_html).expect("Failed to write showcase output");
            println!("✓ Generated page.html");
            println!("  Output: {}", output_path);
            println!("  Size: {} bytes", page_html.len());
            println!();
        }
    }

    println!("\nSuccess! All templates rendered.");
    println!("\nTo view the results:");
    println!("  Open examples/simple_output.html in your browser");
    println!("  Open examples/card_output.html in your browser");
    println!("  Open examples/showcase_output.html in your browser");
    println!();

    print_template_features();
}

fn print_template_features() {
    println!("Template Features Demonstrated:");
    println!("================================");
    println!();
    println!("1. ✓ tpl-arg - Declare template arguments");
    println!("   <tpl-arg value=\"title: &str\"/>");
    println!();
    println!("2. ✓ tpl-if - Conditional rendering");
    println!("   <div tpl-if=\"show_header\">...</div>");
    println!();
    println!("3. ✓ tpl-text - Text content with expressions");
    println!("   <p tpl-text=\"title\">Fallback</p>");
    println!();
    println!("4. ✓ tpl-attr:* - Dynamic attributes");
    println!("   <div tpl-attr:class='format!(\"card-{{}}\", id)'>...</div>");
    println!();
    println!("5. ✓ tpl-optional-attr:* - Conditional attributes");
    println!("   <button tpl-optional-attr:disabled=\"!is_enabled\">Click</button>");
    println!();
    println!("6. ✓ tpl-repeat - Repeating elements");
    println!("   <li tpl-repeat=\"item in &items\">...</li>");
    println!();
    println!("7. ✓ tpl-template - Nested templates");
    println!("   <div tpl-template='card.html: title, content'></div>");
    println!();
    println!("8. ✓ Complex expressions");
    println!("   Use any Rust expression: if/else, .map(), .filter(), etc.");
    println!();
    println!("9. ✓ Void elements");
    println!("   Properly handles <img>, <input>, <br>, etc.");
    println!();
    println!("10. ✓ Multiple directives on same element");
    println!("    Combine tpl-if, tpl-repeat, tpl-text, tpl-attr:*, etc.");
    println!();
    println!("\nKey Syntax Notes:");
    println!("  • Use single quotes for attributes with double quotes inside");
    println!("  • tpl-repeat syntax: tpl-repeat=\"item in &items\"");
    println!("  • tpl-template syntax: tpl-template='name.html: arg1, arg2'");
    println!("  • Variables in templates must be in scope when rendering");
}