From 55482f880cfa67e68e52e5937f36251e886c137c Mon Sep 17 00:00:00 2001 From: Philipp Korber Date: Thu, 22 Nov 2018 20:22:23 +0100 Subject: fix(examples) made template example usable again --- template/src/handlebars.rs | 27 +++++++++++++++++ template/src/lib.rs | 3 ++ template/src/serde_impl.rs | 72 +++++++++++++++++++++++++++++++++++----------- 3 files changed, 86 insertions(+), 16 deletions(-) (limited to 'template') diff --git a/template/src/handlebars.rs b/template/src/handlebars.rs index 2d06a31..370e649 100644 --- a/template/src/handlebars.rs +++ b/template/src/handlebars.rs @@ -11,6 +11,14 @@ use super::{ serde_impl }; +//TODO[FEAT] add custom engine config section to loading +// e.g. something like: +// ``` +// [engine] +// load_partial = "../partials/baseh.html" +// ``` +// +// Just specific to each engine. pub struct Handlebars { @@ -20,6 +28,25 @@ pub struct Handlebars { impl Handlebars { + pub fn new() -> Self { + Handlebars { + inner: hbs::Handlebars::new(), + name_counter: 0 + } + } + + pub fn inner(&self) -> &hbs::Handlebars { + &self.inner + } + + /// Provides mutable access to the underling handlebars instance. + /// + /// This can be used to e.g. add partials (in the future the template + /// file will have a custom config section but currently it doesn't). + pub fn inner_mut(&mut self) -> &mut hbs::Handlebars { + &mut self.inner + } + fn next_body_template_name(&mut self) -> String { let name = format!("body_{}", self.name_counter); self.name_counter += 1; diff --git a/template/src/lib.rs b/template/src/lib.rs index 09aea12..26e70cb 100644 --- a/template/src/lib.rs +++ b/template/src/lib.rs @@ -87,6 +87,9 @@ pub trait TemplateEngineCanHandleData: TemplateEngine { } /// Load a template as described in a toml file. +/// +/// This will set the default of the base_dir to the +/// dir the template file loaded is in. pub fn load_toml_template_from_path( engine: TE, path: PathBuf, diff --git a/template/src/serde_impl.rs b/template/src/serde_impl.rs index 2ab709d..f8e7021 100644 --- a/template/src/serde_impl.rs +++ b/template/src/serde_impl.rs @@ -1,13 +1,12 @@ use std::{ collections::HashMap, - path::{Path, PathBuf} + path::{Path, PathBuf}, + mem }; use serde::{ Serialize, Deserialize, - de::{ - Deserializer, - }, + Serializer, Deserializer }; use failure::Error; use futures::{Future, future::{self, Either}}; @@ -52,10 +51,10 @@ pub struct TemplateBase { base_dir: Option, subject: LazySubject, bodies: Vec1, - //TODO impl. deserialize where - // resource:String -> IRI::new("path", resource) -> Resource::Source + #[serde(default)] #[serde(deserialize_with="deserialize_embeddings")] embeddings: HashMap, + #[serde(default)] #[serde(deserialize_with="deserialize_attachments")] attachments: Vec, } @@ -65,7 +64,7 @@ impl TemplateBase { //TODO!! make this load all embeddings/attachments and make it a future - /// Couples the template base with a specific engine instance. + /// Couples the template base with a specific engine instance.`` pub fn load(self, mut engine: TE, default_base_dir: CwdBaseDir, ctx: &impl Context) -> impl Future, Error=Error> { let TemplateBase { template_name, @@ -98,18 +97,31 @@ impl TemplateBase Ok((subject, bodies)) })(); - let (subject, bodies) = + let (subject, mut bodies) = match catch_res { Ok(vals) => vals, Err(err) => { return Either::B(future::err(err)); } }; - let loading_fut = Resource::load_container(embeddings, ctx) - .join(Resource::load_container(attachments, ctx)); + let loading_embeddings = Resource::load_container(embeddings, ctx); + let loading_attachments = Resource::load_container(attachments, ctx); + let loading_body_embeddings = bodies.iter_mut() + .map(|body| { + //Note: empty HashMap does not alloc! + let body_embeddings = mem::replace(&mut body.inline_embeddings, HashMap::new()); + Resource::load_container(body_embeddings, ctx) + }) + .collect::>(); + let loading_body_embeddings = future::join_all(loading_body_embeddings); + - let fut = loading_fut + let fut = loading_embeddings + .join3(loading_attachments, loading_body_embeddings) .map_err(Error::from) - .map(|(embeddings, attachments)| { + .map(|(embeddings, attachments, body_embeddings)| { + for (body, loaded_embeddings) in bodies.iter_mut().zip(body_embeddings) { + mem::replace(&mut body.inline_embeddings, loaded_embeddings); + } Template { template_name, base_dir, @@ -125,12 +137,30 @@ impl TemplateBase } } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug)] struct LazySubject { - #[serde(flatten)] template_string: String } +impl Serialize for LazySubject { + + fn serialize(&self, serializer: S) -> Result + where S: Serializer + { + serializer.serialize_str(&self.template_string) + } +} + +impl<'de> Deserialize<'de> for LazySubject { + + fn deserialize(deserializer: D) -> Result + where D: Deserializer<'de> + { + let template_string = String::deserialize(deserializer)?; + Ok(LazySubject { template_string }) + } +} + #[derive(Deserialize)] #[serde(untagged)] enum ResourceDeserializationHelper { @@ -214,13 +244,23 @@ impl PathRebaseable for StandardLazyBodyTemplate { fn rebase_to_include_base_dir(&mut self, base_dir: impl AsRef) -> Result<(), UnsupportedPathError> { - self.path.rebase_to_include_base_dir(base_dir) + let base_dir = base_dir.as_ref(); + self.path.rebase_to_include_base_dir(base_dir)?; + for embedding in self.embeddings.values_mut() { + embedding.rebase_to_include_base_dir(base_dir)?; + } + Ok(()) } fn rebase_to_exclude_base_dir(&mut self, base_dir: impl AsRef) -> Result<(), UnsupportedPathError> { - self.path.rebase_to_exclude_base_dir(base_dir) + let base_dir = base_dir.as_ref(); + self.path.rebase_to_exclude_base_dir(base_dir)?; + for embedding in self.embeddings.values_mut() { + embedding.rebase_to_exclude_base_dir(base_dir)?; + } + Ok(()) } } -- cgit v1.2.3