5 个版本
0.2.2 | 2020年2月7日 |
---|---|
0.2.1 | 2019年6月28日 |
0.2.0 | 2019年3月16日 |
0.1.1 | 2018年11月29日 |
0.1.0 | 2018年11月17日 |
#337 在 WebAssembly 中
52 每月下载量
在 graph-store 中使用
84KB
2K SLoC
typed-html
这个 crate 提供了 html!
宏,用于在 Rust 代码中使用类似 JSX 的语法构建 HTML 文档。
快速预览
let mut doc: DOMTree<String> = html!(
<html>
<head>
<title>"Hello Kitty"</title>
<meta name=Metadata::Author content="Not Sanrio Co., Ltd"/>
</head>
<body>
<h1>"Hello Kitty"</h1>
<p class="official">
"She is not a cat. She is a human girl."
</p>
{ (0..3).map(|_| html!(
<p class="emphasis">
"Her name is Kitty White."
</p>
)) }
<p class="citation-needed">
"We still don't know how she eats."
</p>
</body>
</html>
);
let doc_str = doc.to_string();
语法
此宏在很大程度上遵循 JSX 语法,但有一些不同之处
- 文本节点必须加引号,因为 Rust 的词法分析器只能处理有限的字符串字面量之外的文本。因此,您需要将
<p>Hello</p>
写成<p>"Hello"</p>
。(如果忘记这样做,解析器将抛出一个错误。) - 元素属性将接受简单的 Rust 表达式,但解析器有其限制,因为它不是完整的 Rust 解析器。您可以使用字面量、变量、点属性、类型构造函数以及单个函数或方法调用。如果您使用解析器当前无法处理的内容,它将抱怨。如果解析器不理解表达式,您可以在表达式中放置括号或大括号。您可以在括号或大括号块中使用任何 Rust 代码。
有效的 HTML5
该宏只接受有效的 HTML5 标签,不接受标记为实验性或过时的标签或属性。如果它不接受您想要接受的内容,我们可以在 pull request 中讨论(特别是,实验性标签和属性主要被省略以简化,欢迎您实现它们)。
由于结构验证需要依赖于类型系统,因此它是简化的:一些元素将有一个或多个必需的子元素,任何接受子元素的元素将对子元素的类型有所限制,通常是一个由HTML规范定义的广泛组。许多元素对子元素的子元素有所限制,或要求可选元素具有特定的顺序,但目前尚未进行验证。
属性值
在属性值位置的花括号块应返回属性期望的类型。如果你返回了不受支持的类型,类型检查器会发出警告。你还可以使用字面量或一些简单的Rust表达式作为属性值(参见上面的语法部分)。
宏 html!
将向值表达式添加一个 .into()
调用,这样你就可以使用任何具有为实际属性类型 A
定义的 Into<A>
特性的类型。
作为一个特殊情况,如果你使用字符串字面量,宏将使用 FromStr<A>
特性尝试将字符串字面量解析为期望的类型。这对于例如CSS类非常有用,允许你输入 class="css-class-1 css-class-2"
而不是麻烦地构建一个 SpacedSet<Class>
。这个大问题:目前,宏无法在编译时验证字符串,如果字符串无效,转换将在运行时引发恐慌。
示例
let classList: SpacedSet<Class> = ["foo", "bar", "baz"].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::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 Kitty"</p>
);
let doc_str = doc.to_string();
assert_eq!("<p>Hello Kitty</p>", doc_str);
渲染为虚拟DOM
DOM树结构还实现了一个名为vnode()
的方法,该方法将树渲染成Node
树的集合,这是生成树的镜像,其中每个属性值都渲染为String
。您可以遍历这个虚拟DOM树,并使用它来用stdweb
构建实际的DOM树,或者将其传递给您的虚拟DOM系统。
许可证
版权所有 2018 Bodil Stokke
本软件受Mozilla公共许可证第2.0版的约束。如果此文件未附带MPL副本,您可以在http://mozilla.org/MPL/2.0/获取一份。
行为准则
请注意,该项目以贡献者行为准则的形式发布。通过参与此项目,您同意遵守其条款。
依赖项
~1.8–6MB
~113K SLoC