6 个版本
0.2.3 | 2024年1月24日 |
---|---|
0.2.2 | 2023年12月6日 |
0.2.1 | 2023年9月28日 |
0.1.1 | 2023年7月3日 |
#119 in 模板引擎
21KB
275 行
Stilts
Stilts 是一种受 Askama 启发的模板语言。这意味着它具有 Rust 编译器提供的一切类型安全。它仍然与 Jinja 有关联,但采用了更 Rust 风格的表达式语法。
这个项目还处于早期阶段,我只是因为我喜欢 Askama 而开始它,但我认为可以通过在模板表达式中允许更多 Rust 特定的语法来改进它。如果您有建议、功能、问题或任何其他事项,请随时提出。我特别需要帮助编写单元测试,并且愿意与他人合作完成这项工作。
指南
请参阅 书籍 以获取深入了解文档。
工作原理
Stilts 使用在结构体上定义的进程式 derive 宏来生成模板渲染代码,从而使模板代码由 Rust 编译器检查其正确性。
快速示例
以下是一些定义模板的 Rust 代码示例
use stilts::Template;
#[derive(Template)] // This derive macro will generate the template rendering code
#[stilts(path = "index.html")] // based on the contents of the given template path
struct IndexPage<'a> {
some_data: &'a str, // The fields on a struct are the variables
} // you want to use in your template
以下是 index.html 可能看起来像什么
<!DOCTYPE html>
<html>
<body>
<h1>My Index Page</h1>
{% some_data %} <!--This will print some_data to the template here using
the types implementaion of the Display trait-->
</body>
</html
关于 Stilts 表达式
In Stilts an expression is made up of two variants single
and block
expressions. A single expression is anything inside the delimiters {%%}
. Whereas a block expression has an opening single expression and a closing single expression with some kind of content in-between. For example
{% for i in 0..10 %}
This will be repeated 10 times
{% i %}
And I can put other expressions inside
{% end %}
Something you might notice if you have used Askama or Jinja before is that normally to render the value of something you have to use a different set of delimiters namely something like {{ some_data }}
. But here in Stilts there is only one set of delimiters {% some_data %}
.
那么我们如何判断用户是想渲染某些内容还是仅仅编写一些代码呢?答案是,通过判断括号内的Rust代码是一个表达式还是一个语句。在Rust中,表达式总是会产生一个值,而语句则不会。
因此,如果我们作为用户只想编写代码而不将其渲染到模板中,我们只需要添加一个分号即可。现在 {% some_data; %}
就是一个语句而不是表达式,这意味着Stilts将把它作为代码插入到模板渲染代码中,而不是渲染到最终的模板中。这对许多Rust开发者来说很熟悉,因为这就是我们可以在函数内部通过仅以表达式结束来省略 return
关键字的方式。
这也意味着你可以在括号内放置任何任意的Rust表达式或语句。例如 {% let myval = some_data.split(' ').filter(|s| s != "abcd"); %}
。但你不仅限于单行,你也可以将它们分成尽可能多的行。
{% fn my_useful_func() {
// do some stuff
} %}
功能
- 语法类似于Jinja,但也更紧密地与Rust相关
- 利用Rust的类型系统来验证你的代码
- 实现了与Askama相当的性能,而Askama已经非常好了
- 良好的错误信息和格式化,特别是带有可选的复杂特性
- 在稳定的Rust上运行
支持的模板构造
- 继承
- for循环
- if/else if/else
- match表达式
- 包含语句
- 变量(由于允许任意Rust表达式和语句,因此存在)
- 导入到作用域的有用的扩展特质
- 可配置的HTML转义选项
目标
- 创建一个既熟悉给Jinja用户又熟悉Rust开发者的模板语言
- 具有良好的错误报告和消息,并带有有用的错误位置。
其他东西
在工具目录中有一个正在进行的tree-sitter解析器实现。如果你知道如何更好地使其工作,那将是超级酷的。
依赖项
~2–17MB
~195K SLoC