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