diff options
Diffstat (limited to 'src/context.rs')
-rw-r--r-- | src/context.rs | 59 |
1 files changed, 56 insertions, 3 deletions
diff --git a/src/context.rs b/src/context.rs index 55f3f97..925db0b 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,9 +1,13 @@ -use structopt::StructOpt; -use serde::Deserialize; use std::collections::HashMap; use std::fs; use std::io; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; + +use structopt::StructOpt; +use serde::Deserialize; +use tera::{Tera, Filter, Value}; + +const TMPL_FILES: &'static [&'static str] = &["index.html"]; #[derive(Debug, StructOpt)] #[structopt(name = "gallery")] @@ -30,6 +34,7 @@ pub enum ConfigError { Reading(io::Error), Parsing(serde_yaml::Error), CompilePattern(glob::PatternError), + CompileTemplate(tera::Error), } #[derive(Deserialize, Debug)] @@ -41,11 +46,17 @@ pub struct Config { pub imageglob_compiled: glob::Pattern, } +struct ReltoFilter { + dir: PathBuf, +} + #[derive(Debug)] pub struct Context { pub options: Options, pub config: Config, pub imgdir: PathBuf, + + pub tmpl: Tera, } impl Context { @@ -61,10 +72,22 @@ impl Context { } } + // Compile templates + let mut tera = Tera::default(); + let tmpl_dir = opts.load.join("templates"); + TMPL_FILES.iter().map(|fname| -> Result<(), ConfigError> { + let path = tmpl_dir.join(fname); + tera.add_template_file(path, Some(fname))?; + Ok(()) + }).collect::<Result<(), ConfigError>>()?; + + tera.register_filter("relto_build", ReltoFilter::new(&opts.builddir)); + Ok(Context { options: opts, config: config, imgdir: imgdir, + tmpl: tera, }) } @@ -83,6 +106,30 @@ impl Context { } } +impl ReltoFilter { + pub fn new(dir: &Path) -> Self { + ReltoFilter { + dir: dir.to_path_buf(), + } + } +} + +impl Filter for ReltoFilter { + fn filter(&self, value: &Value, _: &HashMap<String, tera::Value>) -> tera::Result<Value> { + if let Value::String(path) = value { + let path = PathBuf::from(path); + match path.strip_prefix(&self.dir) { + Ok(relto) => Ok(Value::String(relto.to_string_lossy().to_string())), + Err(err) => Err(tera::Error::call_filter("relto", err)), + } + } else { + Err(tera::Error::msg("Input to relto filter must be string")) + } + } + + fn is_safe(&self) -> bool { true } +} + impl Config { fn load_from_file(path: &PathBuf) -> Result<Config, ConfigError> { let content = fs::read_to_string(path)?; @@ -122,3 +169,9 @@ impl From<glob::PatternError> for ConfigError { ConfigError::CompilePattern(error) } } + +impl From<tera::Error> for ConfigError { + fn from(error: tera::Error) -> Self { + ConfigError::CompileTemplate(error) + } +} |