diff options
Diffstat (limited to 'src/codegen.rs')
-rw-r--r-- | src/codegen.rs | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/src/codegen.rs b/src/codegen.rs index 5c4255f..5855d8b 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,10 +1,11 @@ +use crate::html::Location; use crate::{resource, Document, SubplotError, TemplateSpec}; use std::collections::HashMap; use std::fs::File; use std::io::Write; use std::path::{Path, PathBuf}; -use base64::encode; +use base64::prelude::{Engine as _, BASE64_STANDARD}; use serde::Serialize; use tera::{Context, Tera, Value}; @@ -32,7 +33,7 @@ fn context(doc: &mut Document, template: &str) -> Result<Context, SubplotError> let mut context = Context::new(); let scenarios = doc.matched_scenarios(template)?; context.insert("scenarios", &scenarios); - context.insert("files", doc.files()); + context.insert("files", doc.embedded_files()); let mut funcs = vec![]; if let Some(docimpl) = doc.meta().document_impl(template) { @@ -53,12 +54,11 @@ fn context(doc: &mut Document, template: &str) -> Result<Context, SubplotError> } fn tera(tmplspec: &TemplateSpec, templatename: &str) -> Result<Tera, SubplotError> { - // Tera insists on a glob, but we want to load a specific template - // only, so we use a glob that doesn't match anything. - let mut tera = Tera::new("/..IGNORE-THIS../..SUBPLOT-TERA-NOT-EXIST../*").expect("new"); + let mut tera = Tera::default(); tera.register_filter("base64", base64); tera.register_filter("nameslug", nameslug); tera.register_filter("commentsafe", commentsafe); + tera.register_filter("location", locationfilter); let dirname = tmplspec.template_filename().parent().unwrap(); for helper in tmplspec.helpers() { let helper_path = dirname.join(helper); @@ -88,13 +88,28 @@ fn write(filename: &Path, content: &str) -> Result<(), SubplotError> { fn base64(v: &Value, _: &HashMap<String, Value>) -> tera::Result<Value> { match v { - Value::String(s) => Ok(Value::String(encode(s))), + Value::String(s) => Ok(Value::String(BASE64_STANDARD.encode(s))), _ => Err(tera::Error::msg( "can only base64 encode strings".to_string(), )), } } +fn locationfilter(v: &Value, _: &HashMap<String, Value>) -> tera::Result<Value> { + let location: Location = serde_json::from_value(v.clone())?; + Ok(Value::String(format!( + "{:?}", + match location { + Location::Known { + filename, + line, + col, + } => format!("{}:{}:{}", filename.display(), line, col), + Location::Unknown => "unknown".to_string(), + } + ))) +} + fn nameslug(name: &Value, _: &HashMap<String, Value>) -> tera::Result<Value> { match name { Value::String(s) => { @@ -170,10 +185,10 @@ mod test { #[test] fn verify_name_slugification() { static GOOD_CASES: &[(&str, &str)] = &[ - ("foobar", "foobar"), // Simple words pass through - ("FooBar", "foobar"), // Capital letters are lowercased + ("foobar", "foobar"), // Simple words pass through + ("FooBar", "foobar"), // Capital letters are lowercased ("Motörhead", "mot_rhead"), // Non-ascii characters are changed for underscores - ("foo bar", "foo_bar"), // As is whitespace etc. + ("foo bar", "foo_bar"), // As is whitespace etc. ]; for (input, output) in GOOD_CASES.iter().copied() { let input = Value::from(input); |