6个版本 (重大变更)
0.5.0 | 2023年3月30日 |
---|---|
0.4.1 | 2023年1月25日 |
0.3.0 | 2023年1月2日 |
0.2.0 | 2022年12月19日 |
0.1.0 | 2022年12月16日 |
#116 in 模板引擎
每月34次下载
在 2 个crate中使用
89KB
2K SLoC
axohtml
此crate提供了用于在Rust代码中构建完全类型检查的HTML文档的宏html!
,语法类似于JSX。
此crate是Bodil Stokke的typed-html crate的分支。选择分支而不是维护是因为目前不打算使用或维护Wasm兼容性(目前如此)。
快速预览
let mut doc: DOMTree<String> = html!(
<html>
<head>
<title>"Hello Axo"</title>
<meta name=Metadata::Author content="Axo Developer Co."/>
</head>
<body>
<h1>">o_o<"</h1>
<p class="official">
"The tool company for tool companies"
</p>
{ (0..3).map(|_| html!(
<p class="emphasis">
">o_o<"
</p>
)) }
<p class="citation-needed">
"Every company should be a developer experience company."
</p>
</body>
</html>
);
let doc_str = doc.to_string();
语法
此宏在很大程度上遵循JSX语法,但有少许差异
- 文本节点必须加引号,因为Rust的标记解析器只能处理字符串字面量中的内容。因此,不能写成
<p>Hello</p>
,而应该写成<p>"Hello"</p>
。(如果忘记这样做,解析器会抛出错误。) - 元素属性可以接受简单的Rust表达式,但解析器有其限制,因为它不是一个完整的Rust解析器。您可以使用字面量、变量、点属性、类型构造函数以及单个函数或方法调用。如果您使用解析器目前无法处理的某些内容,它将报错。如果解析器不理解表达式,您可以在表达式周围放置花括号或括号。您可以在花括号或括号块内使用任何Rust代码。
有效的HTML5
宏只接受有效的HTML5标签,没有标记为实验性或已废弃的标签或属性。如果它不接受您希望接受的内容,我们可以在拉取请求中讨论(特别是实验性标签和属性,大部分只是为了简洁而省略,欢迎您实现它们)。
由于必须依赖于类型系统,结构验证非常简单:一些元素将有一个或多个必需的子元素,而任何接受子元素的元素都将对子元素的类型有限制,通常是HTML规范中定义的广泛组。许多元素对子元素的子元素有限制,或要求可选元素有特定的顺序,这目前尚未进行验证。
属性值
在属性值位置的花括号块应返回属性期望的类型。如果您返回不支持的类型,类型检查器将报错。您还可以使用字面量或一些简单的Rust表达式作为属性值(请参阅上面的语法部分)。
《html!》宏将为值表达式添加一个into
调用,以便您可以使用任何为实际属性类型A
定义了Into
特质的类型。
作为一个特殊情况,如果您使用字符串字面量,宏将改用FromStr
特质来尝试将字符串字面量解析为期望的类型。这对于例如CSS类非常有用,允许您键入class="css-class-1 css-class-2"
而不是构建一个SpacedSet
。这个大前提是:目前,宏无法在编译时验证字符串,如果字符串无效,转换将在运行时引发恐慌。
示例
let classList: SpacedSet<Class> = ["foo", "bar", "baz"].try_into()?;
html!(
<div>
<div class="foo bar baz" /> // parses a string literal
<div class=["foo", "bar", "baz"] /> // uses From<[&str, &str, &str]>
<div class=classList /> // uses a variable in scope
<div class={ // evaluates a code block
SpacedSet::try_from(["foo", "bar", "baz"])?
} />
</div>
)
生成的节点
在子节点位置的花括号块应返回一个IntoIterator
,其中包含DOMTree
。您可以返回单个元素或文本节点,因为它们都实现了对自己的IntoIterator
。宏将在运行时消费这个迭代器,并将生成的节点作为期望位置的子节点插入。
示例
html!(
<ul>
{ (1..=5).map(|i| html!(
<li>{ text!("{}", i) }</li>
)) }
</ul>
)
渲染
您有两个选项可以从宏生成的DOM树中产生有用的内容。
渲染到字符串
DOM树数据结构实现了Display
,因此您可以在其上调用to_string()
来将其渲染为一个String
。如果您打算这样做,树的数据类型应该是DOMTree<String>
以确保您没有使用任何不能打印的事件处理器。
let doc: DOMTree<String> = html!(
<p>"Hello Axo"</p>
);
let doc_str = doc.to_string();
assert_eq!("<p>Hello Axo</p>", doc_str);
渲染到虚拟DOM
DOM树结构还实现了一个名为vnode()
的方法,它将树渲染为一个VNode
的树,这是生成树的镜像,每个属性值都渲染为String
。您可以遍历这个虚拟DOM树并将其传递给您最喜欢的虚拟DOM系统。
许可
本软件受Mozilla公共许可证第2.0版条款的约束。如果此文件未附带MPL副本,您可以在此处获得一份:http://mozilla.org/MPL/2.0/。
版权所有2018年Bodil Stokke,2022年Axo Developer Co。
依赖关系
~2-11MB
~115K SLoC