blocks 0.1.0

A high-performance Rust library for block-based content editing with JSON, Markdown, and HTML support
Documentation
//! File Operations Example
//!
//! Demonstrates reading and writing documents in different formats.
//! This is the typical workflow for a block editor backend.

use blocks::{Block, BlockType, Document};
use std::fs;
use std::path::Path;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let testdata = Path::new("testdata");
    let output = Path::new("testdata/output");

    // Create output directory
    fs::create_dir_all(output)?;

    println!("📁 Blocks Library - File Operations\n");

    // ═══════════════════════════════════════════════════════════════════
    // 1. READ JSON → CONVERT TO ALL FORMATS
    // ═══════════════════════════════════════════════════════════════════
    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    println!("1. JSON → Markdown, HTML, Plain Text");
    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");

    let json_content = fs::read_to_string(testdata.join("sample.json"))?;
    let doc = Document::from_json(&json_content)?;

    println!("✓ Read: testdata/sample.json");
    println!("  Title: '{}'", doc.title);
    println!("  Blocks: {}", doc.blocks.len());

    // Export to Markdown
    let markdown = doc.to_markdown()?;
    fs::write(output.join("from_json.md"), &markdown)?;
    println!(
        "✓ Wrote: testdata/output/from_json.md ({} bytes)",
        markdown.len()
    );

    // Export to HTML
    let html = doc.to_html()?;
    fs::write(output.join("from_json.html"), &html)?;
    println!(
        "✓ Wrote: testdata/output/from_json.html ({} bytes)",
        html.len()
    );

    // Export to Plain Text
    let plain = doc.to_plain_text()?;
    fs::write(output.join("from_json.txt"), &plain)?;
    println!(
        "✓ Wrote: testdata/output/from_json.txt ({} bytes)",
        plain.len()
    );

    // ═══════════════════════════════════════════════════════════════════
    // 2. READ MARKDOWN → CONVERT TO JSON
    // ═══════════════════════════════════════════════════════════════════
    println!("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    println!("2. Markdown → JSON");
    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");

    let md_content = fs::read_to_string(testdata.join("sample.md"))?;
    let doc_from_md = Document::from_markdown(&md_content)?;

    println!("✓ Read: testdata/sample.md");
    println!("  Title: '{}'", doc_from_md.title);
    println!("  Blocks: {}", doc_from_md.blocks.len());

    let json_output = doc_from_md.to_json_pretty()?;
    fs::write(output.join("from_markdown.json"), &json_output)?;
    println!(
        "✓ Wrote: testdata/output/from_markdown.json ({} bytes)",
        json_output.len()
    );

    // ═══════════════════════════════════════════════════════════════════
    // 3. READ HTML → CONVERT TO JSON
    // ═══════════════════════════════════════════════════════════════════
    println!("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    println!("3. HTML → JSON");
    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");

    let html_content = fs::read_to_string(testdata.join("sample.html"))?;
    let doc_from_html = Document::from_html(&html_content)?;

    println!("✓ Read: testdata/sample.html");
    println!("  Title: '{}'", doc_from_html.title);
    println!("  Blocks: {}", doc_from_html.blocks.len());

    let json_output = doc_from_html.to_json_pretty()?;
    fs::write(output.join("from_html.json"), &json_output)?;
    println!(
        "✓ Wrote: testdata/output/from_html.json ({} bytes)",
        json_output.len()
    );

    // ═══════════════════════════════════════════════════════════════════
    // 4. CREATE NEW DOCUMENT → SAVE AS JSON
    // ═══════════════════════════════════════════════════════════════════
    println!("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    println!("4. Create New → Save JSON");
    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");

    let mut new_doc = Document::with_title("API Generated Document".to_string());
    new_doc.add_block(Block::new(
        BlockType::Header { level: 1 },
        "Created via API".to_string(),
    ));
    new_doc.add_block(Block::new(
        BlockType::Text,
        "This document was created programmatically.".to_string(),
    ));
    new_doc.add_block(Block::new(
        BlockType::Code {
            language: Some("json".to_string()),
        },
        r#"{"status": "success", "created": true}"#.to_string(),
    ));

    let json_output = new_doc.to_json_pretty()?;
    fs::write(output.join("new_document.json"), &json_output)?;
    println!("✓ Created and saved: testdata/output/new_document.json");

    // Also save as all formats
    fs::write(output.join("new_document.md"), new_doc.to_markdown()?)?;
    fs::write(output.join("new_document.html"), new_doc.to_html()?)?;
    println!("✓ Also saved as .md and .html");

    // ═══════════════════════════════════════════════════════════════════
    // 5. ROUNDTRIP VERIFICATION
    // ═══════════════════════════════════════════════════════════════════
    println!("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    println!("5. Roundtrip Verification");
    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");

    // JSON → Document → JSON (should be identical structure)
    let original_json = fs::read_to_string(testdata.join("sample.json"))?;
    let doc1 = Document::from_json(&original_json)?;
    let roundtrip_json = doc1.to_json()?;
    let doc2 = Document::from_json(&roundtrip_json)?;

    println!("JSON Roundtrip:");
    println!("  Original blocks: {}", doc1.blocks.len());
    println!("  After roundtrip: {}", doc2.blocks.len());
    println!("  Titles match: {}", doc1.title == doc2.title);
    println!(
        "  Block count match: {}",
        doc1.blocks.len() == doc2.blocks.len()
    );

    // ═══════════════════════════════════════════════════════════════════
    // SUMMARY
    // ═══════════════════════════════════════════════════════════════════
    println!("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    println!("📊 Summary");
    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");

    println!("Input files:");
    println!("  • testdata/sample.json");
    println!("  • testdata/sample.md");
    println!("  • testdata/sample.html");

    println!("\nOutput files:");
    for entry in fs::read_dir(output)? {
        let entry = entry?;
        let metadata = entry.metadata()?;
        println!(
            "{} ({} bytes)",
            entry.file_name().to_string_lossy(),
            metadata.len()
        );
    }

    println!("\n✅ All file operations completed!");

    Ok(())
}