Function hairy::hairy_compile
source · [−]pub fn hairy_compile<'a, 'b, 'c>(
reader: &'b str,
filename: &'b str,
inlines: Option<&'a DecodedValue<'b>>,
defaults: ValueRef<'b>,
scope: &mut MemoryScope<'c>,
option_custom: Option<&mut dyn CustomFuncs>,
escaping: Option<&[(usize, &'b [u8])]>
) -> Result<BytecodeVec, HairCompileError<'b>> where
'c: 'b,
'b: 'a,
Expand description
Converts a Hair template (in reader
) to bytecode that can be evaluation later. To help debugging during later evaluation, a
filename
can be added to the bytecode. A MemoryScope is used to reduce the number of
allocated strings. The result stays valid as long as the MemoryScope is in the scope (forced by
the lifetime system of Rust). The globals and custom functions are used when evaluation the
defaults (for template calls and such).
For an easy to version of this function, see the hairy_compile_html
function (which provide
auto escaping automatically).
Escaping
Normally, all strings that are dynamically outputted (between an evaluating {{..}}
statement) are automatically ‘escaped’ using the escaper as given to an argument to the
hairy_eval
function. However, often you will want different escape modes depending on the
input context. For example in HTML, output may not normally contain <
or >
, but output
inside attributes in HTML tags are normally escaped using url-escaping. Although users can specify for
every output the escape mode by appending a :html
or :url
escaping mode to an expression,
this is error prone. Auto escaping is therefore a safer alternative, by automatically dedcing
the escape mode from the input. That is where the escaping
argument comes in to play. That
argument is used to lookup the escaping mode for a certain position in the input.
Example
use hairy::*;
use expry::memorypool::MemoryPool;
use std::io::Write;
let mut allocator = MemoryPool::new();
let mut scope = allocator.rewind();
let template = r#"foo {{bar}}"#;
let result = hairy_compile(template, "test.tpl", None, ValueRef::new(), &mut scope, None, None);
match result {
Ok(parsed) => {
let value = ValueRef(b"");
let output = hairy_eval(parsed.to_ref(), value, &mut scope, None, &[], None);
if let Ok(output) = output {
std::io::stdout().write_all(&output.concat());
// OR, more efficient (avoiding allocations):
for v in output {
std::io::stdout().write_all(v);
}
}
},
Err(err) => {
eprintln!("{}", hairy_compile_error_format(template, &err, 0));
}
}