19个版本 (4个稳定版)
1.2.0 | 2024年6月5日 |
---|---|
1.1.0 | 2024年5月27日 |
0.3.1 | 2024年5月12日 |
0.2.3 | 2024年5月5日 |
0.1.10 | 2024年5月3日 |
#108 in 模板引擎
在 2 crate 中使用
21KB
285 行
Rust中的HTML模板引擎
cargo add cercis
使用示例
格式化
使用 format!()
宏将数据格式化为字符串
所有数据都通过引用传递到模板中
use cercis::prelude::*;
fn main() {
let name = "Boris";
let page = rsx!(h1 { "Hello {name}!" });
// output: <h1>Hello Boris!</h1>
println!("{}", page.render())
}
属性
属性以 tag: value
的形式写在标签内容之前
use cercis::prelude::*;
fn main() {
let text_id = "paragraph";
let text = "Lorem ipsum";
let page = rsx!(div {
class: "container",
h1 { "Hello World!" }
p {
id: "{text_id}",
"{text}"
}
});
// output: <div class='container'><h1>Hello World!</h1><p id='paragraph'>Lorem ipsum</p></div>
println!("{}", page.render())
}
如果需要分支
使用Rust的常规if语法,可以创建分支
use cercis::prelude::*;
fn main() {
let num = 8;
let page = rsx!(div {
if num == 9 {
span { "Num is 9" }
}
if num == 8 {
span { "Num is 8" }
}
});
// output: <div><span>Num is 8</span></div>
println!("{}", page.render())
}
循环
使用Rust的常规 for in
语法可以创建循环
use cercis::prelude::*;
fn main() {
let names = vec!["Boris", "Polina", "Igor"];
let page = rsx!(ol {
for name in names {
li { "{name}" }
}
});
// output: <ol><li>Boris</li><li>Polina</li><li>Igor</li></ol>
println!("{}", page.render())
}
带有参数的组件
参数声明为常规函数参数
use cercis::prelude::*;
fn main() {
let text = "Lorem ipsum";
let page = rsx!(div {
MyComponent {
text: text
}
});
// output: <div><p>Lorem ipsum</p></div>
println!("{}", page.render())
}
#[component]
fn MyComponent<'a>(text: &'a str) -> Element {
rsx!(p { "{text}" })
}
带有可选参数的组件
如果参数是可选的,则调用组件时可以省略它
use cercis::prelude::*;
fn main() {
let text = "Lorem ipsum";
let page = rsx!(div {
MyComponent {}
MyComponent {
text: text
}
});
// output: <div><p>empty</p><p>Lorem ipsum</p></div>
println!("{}", page.render())
}
#[component]
fn MyComponent<'a>(text: Option<&'a str>) -> Element {
let text = text.unwrap_or("empty");
rsx!(p { "{text}" })
}
带有子组件的组件
组件可以接受元素 example: Element<'a>
和子组件,如果变量名为 children: Element<'a>
所有
Element
类型都是可选的
use cercis::prelude::*;
fn main() {
let text = "Lorem ipsum";
let page = rsx!(div {
MyComponent { span { "children" } }
MyComponent {
text: rsx!(p { "{text}" }),
span { "children" }
}
MyComponent { text: rsx!(p { "my text" }) }
});
/* output(formatted):
<div>
<div class='container'>
<div></div>
<span>children</span>
</div>
<div class='container'>
<div><p>Lorem ipsum</p></div>
<span>children</span>
</div>
<div class='container'>
<div><p>my text</p></div>
</div>
</div>
*/
println!("{}", page.render())
}
#[component]
fn MyComponent<'a>(text: Element<'a>, children: Element<'a>) -> Element {
rsx!(div {
class: "container",
div { text }
children
})
}
完整页面
use cercis::prelude::*;
fn main() {
// declarate people names
let names = vec!["Boris", "Polina", "Igor", "Nikita"];
// create peoples ordered list
let peoples = rsx!(ol {
for name in names {
li { "{name}" }
}
});
// create full page using our Page component
let page = rsx!(Page {
title: "Cercis",
h1 { "Peoples:" }
// insert element from peoples variable
peoples
});
// render our page to string
println!("{}", page.render())
}
#[component]
pub fn Page<'a>(title: Option<&'a str>, head: Element<'a>, children: Element<'a>) -> Element {
const META_CONTENT: &str = "witdh=device-width, initial-scale=1.0";
rsx!(
// turn into: <!DOCTYPE html>
doctype {}
html {
head {
meta { charset: "UTF-8" }
meta {
name: "viewport",
// interpolate META_CONTENT const into value like format!() macro
content: "{META_CONTENT}",
}
head
// declarate title if exists
if let Some(title) = title {
title { "{title}" }
}
}
body { children }
}
)
}
如果您有任何问题 创建问题
依赖关系
~0.5–1MB
~22K SLoC