0.1.0 |
|
---|
#5 in #consider
36KB
553 代码行
rubble-rs
Rust中的模板引擎。
它做什么?
它允许使用包含将被替换占位符的模板。考虑以下示例
Hello there, {{ name }}!
根据为 name
提供的值,输出可能会有所不同。例如,如果使用 name
并将其值设置为 Joe
,则将生成以下输出
Hello there, Joe!
该库评估此类模板并将它们编译成如上例所示的输出文本。
用法
要简单地编译模板,您可以使用 compile_template_from_file(file: PathBuf, variables: HashMap<String, String>, functions: HashMap<String, Box<dyn Function>>)
。
let file = PathBuf::from("template-file.txt");
let functions: HashMap<String, Box<dyn Function>> = HashMap::new();
let mut variables: HashMap<String, String> = HashMap::new();
variables.insert("name".to_string(), "Joe".to_string());
let result = compile_template_from_file(file, variables, functions);
assert_eq!(result.ok(), Some("Hello there, Joe!".to_string()));
还有一些其他实用函数
compile_template_from_string(template: String, variables: HashMap<String, String>, functions: HashMap<String, Box<dyn Function>>)
- 可以用于将模板文本作为原始文本编译。compile_template_fromcompile_template_from(template: Template, variables: HashMap<String, String>, functions: HashMap<String, Box<dyn Function>>)
- 可以用于从模板实例编译文本。
这些是编译模板的方便函数,但对于某些特殊案例,您可能需要直接使用 Evaluator
和 Compiler
来编译模板。
语法
默认情况下,rubble-rs 在解析模板时会寻找所有以 {{
开始并以 }}
结束的块,这些块被标记为评估点,其中的代码可以由 Evaluator
评估。
以下是一个示例
Hello there, {{ name }}!
这个模板包含三个部分
Hello there,
- 原始文本{{ name }}
- 代码!
- 原始文本
第二部分将通过 Compiler
传递给指定的 Evaluator
,以便获得字符串输出。代码片段将被替换为输出。
rubble-rs 库还可以评估更复杂的代码。您可以通过传递自己的函数来丰富模板。
在评估过程中,该库使用类似 Lisp 的语法。所有函数调用看起来都像以下这样
function_name arg0 arg1 arg2
要调用 plus
函数(可以假设实现)来计算 2 + 2 的结果,您需要编写
The result is: {{ plus 2 2 }}
参数也可以用括号分组。这在某些情况下可能会有所帮助。例如,对于 plus
和 multiply
函数,您需要使用以下代码来计算 (1 + 2) * 3
The result is: {{ multiply (plus 1 2) 3 }}
自定义
编译包含三个阶段
parsing
- 由模板迭代器执行,例如EvaluableMixedContentIterator'a, T>
,它可以提取模板部分,evaluation
- 由Evaluator
执行,它评估迭代器找到的所有代码,compiling
- 由Compiler
执行,它使用迭代器解析内容,向Evaluator
提供内容,然后将所有内容连接成输出文本。
您可以实现自己的迭代器、评估器或编译器。要修改编译过程,您只需使用自己的 trait 实现,而不是默认实现。
为了说明它是如何工作的,以下是 compile_template_from_string
实际上执行的操作
let raw_input = "Hello there, {{ name }}!".to_string();
let variables: HashMap<String, String> = HashMap::new();
let functions: HashMap<String, Box<dyn Function>> = HashMap::new();
// compilation below
let template = Template::from(raw_input);
let engine = SimpleEvaluationEngine::from(functions);
let compiler = TemplateCompiler::new(engine);
compiler.compile(&template, &variables)
自定义函数
评估器可以通过自定义 Function
特性实现来扩展函数。为了使这个过程更容易,存在默认实现为 F where F: Fn(&dyn Evaluator, &Vec<SyntaxNode>, &HashMap<String, String>) -> Result<String, EvaluationError>
,这意味着您可以使用lambda函数或Rust函数。
带有函数的示例
#[test]
fn should_compile_template() {
let text = Template::from("{{hello}}\n2 + 2 = {{ plus 2 2 }}".to_string());
let mut functions: HashMap<String, Box<dyn Function>> = HashMap::new();
functions.insert("plus".to_string(), Box::new(plus_function));
let mut variables: HashMap<String, String> = HashMap::new();
variables.insert("hello".to_string(), "Hello world!".to_string());
let result = compile_template_from_string(text, variables, functions);
assert_eq!(result.ok(), Some("Hello world!.\n2 + 2 = 4".to_string()));
}
fn plus_function(evaluator: &dyn Evaluator, parameters: &Vec<SyntaxNode>, variables: &HashMap<String, String>) -> Result<String, EvaluationError> {
Ok(
parameters.iter()
.map(|node|
evaluator.evaluate(node.clone(), variables).unwrap().parse::<i32>().unwrap()
)
.sum::<i32>()
.to_string()
)
}