forge-rsx

Crates.ioforge-rsx
lib.rsforge-rsx
version0.1.0
created_at2026-01-23 20:04:41.542678+00
updated_at2026-01-23 20:04:41.542678+00
descriptionA Rust macro library for declarative, JSX-like HTML generation. It allows you to write HTML structures with embedded logic, attributes, nested tags, loops, and more, directly in Rust code with a concise syntax.
homepagehttps://github.com/dr-montasir/forge-rsx
repositoryhttps://github.com/dr-montasir/forge-rsx
max_upload_size
id2065382
size23,889
Dr. Montasir (dr-montasir)

documentation

README

forge-rsx

forge-rsx is a Rust macro library for declarative, JSX-like HTML generation. It allows you to write HTML structures with embedded logic, attributes, nested tags, loops, and more, directly in Rust code with a concise syntax.


Features

  • Declarative HTML macro: rsx! macro
  • Supports nested tags, attributes, loops, and embedded expressions
  • Indentation-aware formatting
  • String literal and identifier attributes
  • Flexible syntax for defining complex HTML structures

Usage

Run the following Cargo command in your project directory:

cargo add forge-rsx

Or add forge-rsx as a dependency in your Cargo.toml:

[dependencies]
forge-rsx = "MAJOR.MINOR.PATCH" # Replace with the latest version

In your Rust code, import the macro:

use forge_rsx::rsx;

Macro Variants

  • lined: produces HTML without indentation or line breaks (single-line output)
  • btfy0: uses 0 spaces (no indentation, minified output)
  • btfy2: Indentation with 2 spaces per level.
  • btfy4: Indentation with 4 spaces per level.

Examples:

rsx!(btfy0, div { "No indentation" });
rsx!(btfy2, div { "Indented with 2 spaces" });
rsx!(btfy4, div { "Indented with 4 spaces" });

Examples

Basic Tag with Content

let greeting = rsx!(lined, span { "Hello, World!" });
println!("{}", greeting);

Nested Tags

let nested_html = rsx!(lined, div {
    header {
        span { "Navigation" }
    }
    section {
        p { "Welcome to the forge-rsx template!" }
    }
});
println!("{}", nested_html);

Attributes

let button_html = rsx!(lined, button {
    class: "btn-primary",
    "data-toggle": "modal",
    "Click me!"
});
println!("{}", button_html);

Loop Example

let users = vec!["Ahmed", "Mohamed", "Montasir"];

let list_html = rsx!(lined, ul {
    for user in &users => {
        li { { format!("User: {}", user) } }
    }
});
println!("{}", list_html);

Full Complex Example

use forge_rsx::{rsx, get_char};
fn main() {
    let apple = "🍎 Apple";
    let apple_component = rsx!(lined, span { {&apple} });
    let fruits = vec!["🍇", "mango", "orange"];
    let div = rsx!(btfy4, div { "..." 
        {"<!--  How to use attributes with hyphens, like x-show in Alpine.js -->"}
        span {
            id: "my-id",
            class: "my-class",
            "x-show": "",
            ":class": "p-4",
            "..."
        }
        "..."
    });
    let span = rsx!(btfy0, span { "..." });
    let empty_p = rsx!(btfy2, p { });
    let p = rsx!(btfy2, p {"..."});
    let section = rsx!(btfy4, section { div { ol { 
        for fruit in &fruits => {
            li {
                span {
                    {
                        if fruit == &"🍇" {
                            &format!("{} {}", fruit.to_string(), "Grapes")

                        } else if fruit == &"mango" {
                            &format!("{} {}", "🥭", fruit.to_lowercase())
                        } else {
                            &fruit.to_uppercase()
                        }
                    }
                }
            }
        }
        li { 
            {"<!-- How to join RSX component -->"}
            {&apple_component.to_string()} 
            {
                if get_char(&apple, 1).to_string() == "🍎" {
                    "🍎".to_string()
                } else {
                    apple_component.to_string()
                }
            }
        }
    } } });
    println!(
        "{}\n\n{}\n\n{}\n\n{}\n\n{}", 
        div, span, empty_p, p, section
    );
    // <div>
    //     ...
    //     <!--  How to use attributes with hyphens, like x-show in Alpine.js -->
    //     <span id="my-id" class="my-class" x-show='' :class='p-4'>
    //         ...
    //     </span>
    //     ...
    // </div>
    //
    // <span>
    // ...
    // </span>
    //
    // <p></p>
    //
    // <p>
    //   ...
    // </p>
    //
    // <section>
    //     <div>
    //         <ol>
    //             <li>
    //                 <span>
    //                     🍇 Grapes
    //                 </span>
    //             </li>
    //             <li>
    //                 <span>
    //                     🥭 mango
    //                 </span>
    //             </li>
    //             <li>
    //                 <span>
    //                     ORANGE
    //                 </span>
    //             </li>
    //             <li>
    //                 <!-- How to join RSX component -->
    //                 <span>🍎 Apple</span>
    //                 🍎
    //             </li>
    //         </ol>
    //     </div>
    // </section>
}

License

MIT License


Notes

  • The macro supports attributes with string literals and identifiers.
  • Nested tags are handled with recursive macro calls.
  • Looping constructs generate repeated content.
  • Content inside braces {} can contain any Rust expression that implements Display.

Commit count: 1

cargo fmt