An open API service indexing awesome lists of open source software.

https://github.com/swlkr/shtml

Yet another ssr only jsx implementation in rust
https://github.com/swlkr/shtml

Last synced: 9 months ago
JSON representation

Yet another ssr only jsx implementation in rust

Awesome Lists containing this project

README

          

# shtml

shtml is a rust library for rendering html.

## Installation

```
cargo add --git https://github.com/swlkr/shtml shtml
```

## Examples

Just write or copy/paste plain old html

```rust
use shtml::{html, Elements, Component, Render};

let result = html! {



shtml the s is silent

}
.to_string();
```

Get this back in the result var

```html


shtml the s is silent

```

Attrs work like you would expect

```rust
let class = "flex items-center h-full";
let result = html! {

}.to_string();

//


```

Pass in rust exprs in curlies just make sure they impl `Render`

```rust
let x = 1;
let result = html! {

{x}
}.to_string();

//

1

```

Strings get escaped

```rust
let x = "alert(\"pwned\")";
let result = html! {

{x}
}.to_string();

//

<script>alert(&quotpwned&quot)</script>

```

Components work like jsx

```rust
#![allow(non_snake_case)]

fn HStack(elements: Elements) -> Component {
html! {

{elements}
}
}

let component = html! {

1

2

3


}.to_string();

//


1

2

3


```

Attrs with components work as well

```rust
#![allow(non_snake_case)]

fn Hypermedia(target: &str) -> Component {
html! {

}
}

let x = "body";
let result = html! { }.to_string();

//


```

Nested components

```rust
#![allow(non_snake_case)]

fn HStack(elements: Elements) -> Component {
html! {

{elements}
}
}

fn VStack(elements: Elements) -> Component {
html! {

{elements}
}
}

let component = html! {


1

2



}.to_string();

//


1

2


```

Attrs + nested components

```rust
fn Heading(class: &str, els: Elements) -> Component {
html! {

{els}

}
}

let result = html! {

How now brown cow



}.to_string();

//

How now brown cow


```

Fragments just pass through their children

```rust
#![allow(non_snake_case)]

fn HStack(elements: Elements) -> Component {
html! {

{elements}
}
}

fn VStack(elements: Elements) -> Component {
html! {

{elements}
}
}

let component = html! {

<>

1

2


>

}.to_string();

//


1

2


```

The `Render` trait is only implemented for `Vec`

```rust
#![allow(non_snake_case)]

fn List(elements: Elements) -> Component {
html! {

    {elements}
}
}

fn Item(elements: Elements) -> Component {
html! {

  • {elements}
  • }
    }

    let items = vec![1, 2, 3];

    let result = html! {

    {
    items
    .iter()
    .map(|i| html! {
    {i}
    })
    .collect::>()
    }

    }.to_string();

    //


    • 1

    • 2

    • 3


    ```

    # Feature flags

    - chaos

    The `chaos` feature flag requires that you annotate all component functions with a `#[component]` macro attribute and allows you to specify any attr order:

    ```rust
    #[component]
    fn Chaos(a: &str, b: u8, c: String) -> Component {
    html! {

    }
    }
    let result = html! { }.to_string();

    //

    // without the chaos feature flag you need to specify the attrs
    // in the same order as the fn args
    html! {

    }
    ```

    # Tips and tricks

    - [leptosfmt](https://github.com/bram209/leptosfmt) with this override `rustfmt = { overrideCommand = ["leptosfmt", "--stdin", "--rustfmt", "--override-macro-names", "html"] }`
    - [tree-sitter-rstml](https://github.com/rayliwell/tree-sitter-rstml) for html autocomplete inside of html! macros

    For helix users: the html! macro should just work and have correct syntax highlighting and autocomplete with the default html lsp + tailwind if that's your jam

    ```toml
    [language-server.tailwind-ls]
    command = "tailwindcss-language-server"
    args = ["--stdio"]

    [language-server.tailwind-ls.config]
    tailwindCSS = { experimental = { classRegex = ["class=\"(.*)\""] } }

    [[language]]
    name = "rust"
    language-servers = ["rust-analyzer", "vscode-html-language-server", "tailwind-ls"]
    ```