2 个版本
0.1.1 | 2024年7月28日 |
---|---|
0.1.0 | 2024年7月28日 |
#218 in 过程宏
240 每月下载量
210KB
4.5K SLoC
rstml
的控制流实现
rstml
中用于控制流的 CustomNode
集合。
动机
此crate旨在提供一个如何使用自定义节点扩展 rstml
的示例。使用自定义节点而不是使用内部宏调用可以降低编写模板的复杂性,并允许 rstml
一次性解析整个模板。
自定义节点
rstml
中的自定义节点允许外部代码扩展 Node
枚举。这对于支持不常见于HTML/XML文档的定制语法很有用。它只能在 Node
的上下文中使用,不能在元素属性或节点名称中使用。
控制流实现
自定义节点的常见用例是实现 if/else 操作符和循环。此crate提供了两种不同的方式来实现 if/else 控制流。
使用标签的控制流
第一种方法是使用自定义标签。这是在HTML模板中实现控制流的最高效方式,因为控制流看起来像常规的HTML元素。这种方法的缺点是,无法在HTML元素属性中正确解析 Rust
表达式。例如,对于 <if foo > bar> </if>
,很难确定属性标签的结束和内容的开始。
在这个包中,我们强制用户在标签的末尾使用一个特殊的分隔符。因此,而不是使用<if foo > bar> </if>
,我们必须编写<if foo > bar !> </if>
,其中!>
是一个分隔符。这种特殊语法在<else if>
和<for>
标签内部也使用。
示例
use rstml::{parse2_with_config, node::*};
use rstml_controll_flow::tags::*;
use quote::quote;
let template = quote!{
<if foo !>
<p> foo is true </p>
<else if bar !>
<p> bar is true </p>
<else if/>
<else>
<p> foo and bar are false </p>
<else/>
</if>
}
let nodes = parse2_with_config(template, Default::default().with_custom_nodes::<Conditions>())
.unwrap();
注意:标签else if
和else
是可选的,并且它们的内容被移动到IfNode
的字段中。标签if
内的其他节点全部收集到IfNode::body
字段中,即使它们在上面的示例中位于<else if/>
和<else>
标签之间。
使用转义符号在未引用文本中的控制流。
第二种方式是在未引用文本中使用转义符号。这种方法对于Rust
来说更自然,因为它的声明方式与Rust
代码相同。唯一的区别是{}
内的块不是Rust
代码,而是rstml
模板。
示例
use rstml::{parse2_with_config, node::*};
use rstml_controll_flow::escape::*;
use quote::quote;
let template = quote!{
<p>
@if foo {
<p> foo is true </p>
} else if bar {
<p> bar is true </p>
} else {
<p> foo and bar are false </p>
}
</p>
};
let nodes = parse2_with_config(template, Default::default().with_custom_nodes::<EscapedCode>())
EscapedCode
转义字符是可配置的,默认使用“@”符号。
同时使用多个CustomNode
。
也可以同时使用多个CustomNode
。例如,如果您想同时使用Conditions
和EscapedCode
自定义节点。rstml-control-flow
包提供了一个ExtendableCustomNode
结构体,可以将多个CustomNode
组合成一个。请查看lib.rs
中的extendable.rs
文档和测试,以获取更多详细信息。
依赖关系
~0.3–0.8MB
~19K SLoC