plait 0.1.0

A modern HTML templating library for Rust that embraces composition.
Documentation
# plait

A fast, type-safe HTML templating library for Rust.

Plait provides compile-time HTML generation with a familiar, JSX-like syntax. Templates are checked at compile
time and generate efficient code with minimal runtime overhead.

## Quick Start

```rust
use plait::html;

let name = "World";
let output = html!(
    div class="greeting" {
        h1 { "Hello, " (name) "!" }
    }
);

assert_eq!(&*output, r#"<div class="greeting"><h1>Hello, World!</h1></div>"#);
```

## Macros

Plait provides four main macros:

- `html!` - Creates an `Html` value from a template
- `component!` - Creates a reusable component that renders lazily
- `render!` - Renders content to an existing `HtmlFormatter`
- `attrs!` - Creates an `Attributes` collection

## Template Syntax

### Elements

Elements are written as `name { children }` for normal elements or `name;` for void elements:

```rust
use plait::html;

let output = html!(
    div {
        p { "A paragraph" }
        br;
        input type="text" name="field";
    }
);

assert_eq!(&*output, r#"<div><p>A paragraph</p><br><input type="text" name="field"></div>"#);
```

### Attributes

Attributes support several value types:

```rust
use plait::html;

let class_name = "container";
let maybe_id: Option<&str> = Some("main");
let is_disabled = true;

let output = html!(
    div
        class="literal"              // Literal string
        data-value=(class_name)      // Dynamic expression
        id=[maybe_id]                // Optional (renders if Some)
        disabled?[is_disabled]       // Boolean (renders if true)
    {
        "content"
    }
);

assert_eq!(&*output, r#"<div class="literal" data-value="container" id="main" disabled>content</div>"#);
```

### Dynamic Content

Expressions in parentheses are escaped by default:

```rust
use plait::html;

let user_input = "<script>alert('xss')</script>";

let output = html!(
    div { (user_input) }
);

// Content is safely escaped
assert!(!output.contains("<script>"));
```

Use `: raw` to include pre-escaped content:

```rust
use plait::html;

let trusted_html = "<strong>Bold</strong>";

let output = html!(
    div { (trusted_html : raw) }
);

assert!(output.contains("<strong>"));
```

### Control Flow

#### Conditionals

```rust
use plait::html;

let show = true;
let value: Option<&str> = Some("hello");

let output = html!(
    div {
        @if show {
            span { "Visible" }
        }

        @if let Some(v) = value {
            span { (v) }
        } @else {
            span { "No value" }
        }
    }
);

assert_eq!(&*output, r#"<div><span>Visible</span><span>hello</span></div>"#);
```

#### Loops

```rust
use plait::html;

let items = vec!["one", "two", "three"];

let output = html!(
    ul {
        @for item in &items {
            li { (item) }
        }
    }
);

assert_eq!(&*output, r#"<ul><li>one</li><li>two</li><li>three</li></ul>"#);
```

#### Match Expressions

```rust
use plait::html;

enum Status { Active, Inactive }
let status = Status::Active;

let output = html!(
    span {
        @match status {
            Status::Active => "Online",
            Status::Inactive => "Offline",
        }
    }
);

assert_eq!(&*output, r#"<span>Online</span>"#);
```

## Custom Components

Use the `component!` macro to create reusable components as functions:

```rust
use plait::{Render, component};

fn button(label: &str, primary: bool) -> impl Render + '_ {
    let class = if primary { "btn btn-primary" } else { "btn" };
    component! {
        button class=(class) { (label) }
    }
}

// Use in templates
let output = plait::html!(
    div { (button("Click me", true)) }
);

assert_eq!(&*output, r#"<div><button class="btn btn-primary">Click me</button></div>"#);
```

For components with owned data, use `(&value)` to borrow:

```rust
use plait::{Render, component};

fn greeting(message: String) -> impl Render {
    component! {
        span { (&message) }
    }
}
```

For more control, implement the `Render` trait directly. See the `Render` documentation for details.

## Safety

Plait automatically escapes dynamic content to prevent XSS vulnerabilities. The `Html` and `PreEscaped` types
represent content that is already safe and will not be escaped again.

## License

Licensed under either of

- Apache License, Version 2.0 ([LICENSE-APACHE]LICENSE-APACHE)
- MIT license ([LICENSE-MIT]LICENSE-MIT)

at your option.

## Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as
defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.