Crates.io | html_compile |
lib.rs | html_compile |
version | 0.2.0 |
source | src |
created_at | 2024-03-07 19:39:49.897982 |
updated_at | 2024-03-22 13:43:03.097666 |
description | A template engine for generating HTML strings within Rust for use with static websites |
homepage | https://github.com/apburnie/html_compile |
repository | https://github.com/apburnie/html_compile |
max_upload_size | |
id | 1166219 |
size | 32,881 |
A template engine for generating HTML strings within Rust for use with static websites.
HTML strings can be generated by inputting a concise syntax into provided macros or, alternatively, from Rust structs.
This engine prioritizes speed and should only be used with trusted HTML data.
A complete example is provided on GitHub in the directory example. The below provides an explanation of different aspects of the syntax.
The syntax used is inspired by pug.js but has been adapted to better fit use within a Rust context.
html!(div (style = "border: 1px solid black;" class = "Hello") "Hello World");
Will create the following string of HTML that consists of a div
with a style
attribute that creates a black border, a class
attribute set to Hello
and text set to "Hello World"
"<div style=\"border: 1px solid black;\" class=\"Hello\">Hello World</div>"
The first token (here div
) specifies the name of the element.
The set of parentheses ()
contains the attributes for the element. The attribute name comes before the =
and the attribute value after and is in double quotation marks. Different attributes are separated by whitespace.
The text in double quotation marks at the end of the content specifies the text content "Hello World"
.
The text can also be derived from a variable. In this case surround the variable with curly brackets {}
let example_text = "Hello World";
html!(div (style = "border: 1px solid black;" class = "Hello") {example_text});
gives the same result as before:
"div style=\"border: 1px solid black;\" class=\"Hello\">Hello World</div>"
Both html!(div)
and html!(div ())
will create a string of HTML consisting of an empty div with no styling
"<div></div>"
Void elements should not have end tags and this is handled accordingly. For example html!(hr)
will return "<hr />"
html!(ul () [el!(li () "First Sibling")] [el!(li () "Second Sibling")])
Will create the following string of HTML that consists of an unordered list with two items
"<ul><li>First Sibling</li><li>Second Sibling</li></ul>"
In the browser this renders as
Each child component is surrounded by square brackets []
and is inputted into the macro el!
which creates the component. Multiple specified child components are treated as siblings.
The result from el!(li () "Second Sibling")
could have been stored in a variable and the variable used instead as follows:
let second_sibling = el!(li () "Second Sibling");
let result = html!(ul()[el!(li () "First Sibling")][second_sibling]);
This would return the same HTML String.
let example_list = [
el!(li () "First Sibling"),
el!(li () "Second Sibling")
];
html!(ul () vec[example_list])
Will create the following string of HTML that consists of an unordered list with two items
"<ul><li>First Sibling</li><li>Second Sibling</li></ul>"
In the browser this renders as
Inserting the text vec
before the square brackets []
tells the macro to expect a vector or array.
This library also provides tooling that enables generating HTML strings from Rust structs using the function build_component()
.
use std::fs;
fn main() {
use html_compile::compile::*;
use html_compile::types::*;
let item_list: Vec<String> = vec![1, 2, 3].iter().map(|x| format!("{}", x)).collect();
let item_components: Vec<Box<Component>> = item_list
.iter()
.map(|item| {
Box::new(Component {
tag: "li",
meta: None,
child: Child::Text(item),
})
})
.collect();
let input_component = Component {
tag: "section",
meta: Some(vec![
Attribute {
label: "class",
value: "Example",
},
]),
child: Child::ComponentVec(vec![
Box::new(Component {
tag: "h2",
meta: None,
child: Child::Text("A List of Items"),
}),
Box::new(Component {
tag: "p",
meta: None,
child: Child::Text("The list begins after the following line"),
}),
Box::new(Component {
tag: "hr",
meta: None,
child: Child::NoChild,
}),
Box::new(Component {
tag: "ul",
meta: None,
child: Child::ComponentVec(item_components),
}),
]),
};
let output = build_component(&input_component);
let write_output_path = "./output.html";
fs::write(write_output_path, output).expect("Unable to write to file");
}
The file output.html
looks like the following:
<section class="Example">
<h2>A List of Items</h2>
<p>The list begins after the following line</p><hr/><ul><li>1</li><li>2</li><li>3</li></ul>
</section>
This will render in the browser as follows:
The list begins after the following line
html_compile provides a macro insert_html!
and function insert_components
that searches for the placeholder string {COMPONENT}
and switches this for the HTML string generated.
insert_html!({test_contents}, div () "Hello World")
let test_component: Component = Component {
tag: "div",
meta: None,
child: Child::Text("Hello World"),
};
insert_components(test_contents, test_component)
Both search the String
in the variable test_contents
for the placeholder {COMPONENT}
and swap the placeholder for <div>Hello World</div>
.
Note that in the code on GitHub there is a directory example
that provides an example application using this library.