Skip to content

Commit

Permalink
Pass handlebars render context down when rendering via get helper.
Browse files Browse the repository at this point in the history
This isn't used yet, but will allow the helper to modify the context
(useful for #10).
  • Loading branch information
mkantor committed Jan 2, 2022
1 parent ce29435 commit 136cfc3
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 12 deletions.
1 change: 1 addition & 0 deletions src/content/content_engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ where
) -> RenderContext<ServerInfo, Self> {
RenderContext {
content_engine: self,
handlebars_render_context: None,
data: RenderData {
server_info: self.server_info.clone(),
index: self.index.clone(),
Expand Down
62 changes: 56 additions & 6 deletions src/content/content_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ pub enum RenderingFailedError {
#[from]
source: io::Error,
},

#[error("{} This should never happen: {}", bug_message!(), .0)]
Bug(String),
}

/// A static file from the content directory (such as an image or a text file).
Expand Down Expand Up @@ -88,6 +91,7 @@ impl RegisteredTemplate {
&self,
handlebars_registry: &Handlebars,
render_data: RenderData<ServerInfo>,
handlebars_render_context: Option<handlebars::RenderContext>,
) -> Result<Media<InMemoryBody>, RenderingFailedError>
where
ServerInfo: Clone + Serialize,
Expand All @@ -96,7 +100,23 @@ impl RegisteredTemplate {
target_media_type: Some(self.rendered_media_type.clone()),
..render_data
};
let rendered_content = handlebars_registry.render(&self.name_in_registry, &render_data)?;
let rendered_content = match handlebars_render_context {
None => handlebars_registry.render(&self.name_in_registry, &render_data)?,
Some(mut context) => handlebars_registry
.get_template(&self.name_in_registry)
.ok_or_else(|| {
RenderingFailedError::Bug(format!(
"Template '{}' was not found in the registry",
&self.name_in_registry
))
})?
.renders(
handlebars_registry,
&handlebars::Context::wraps(render_data)?,
&mut context,
)?,
};

Ok(Media::new(
self.rendered_media_type.clone(),
InMemoryBody(rendered_content.bytes().collect()),
Expand Down Expand Up @@ -247,7 +267,7 @@ mod tests {
use crate::test_lib::*;
use crate::ServerInfo;
use ::mime;
use std::collections::HashMap;
use maplit::hashmap;
use std::fs;
use std::io::Write;
use std::str;
Expand All @@ -262,8 +282,8 @@ mod tests {
error_code: None,
request: RequestData {
route: None,
query_parameters: HashMap::new(),
request_headers: HashMap::new(),
query_parameters: hashmap![],
request_headers: hashmap![],
},
}
}
Expand Down Expand Up @@ -317,7 +337,7 @@ mod tests {
let rendered = template.render_to_native_media_type(
content_engine.handlebars_registry(),
content_engine
.render_context(None, HashMap::new(), HashMap::new())
.render_context(None, hashmap![], hashmap![])
.data,
);

Expand All @@ -339,14 +359,44 @@ mod tests {
let rendered = template.render_to_native_media_type(
content_engine.handlebars_registry(),
content_engine
.render_context(Some(route("/test")), HashMap::new(), HashMap::new())
.render_context(Some(route("/test")), hashmap![], hashmap![])
.data,
None,
);

let template_output = media_to_string(rendered.expect("Rendering failed"));
assert_eq!(template_output, "it works!");
}

#[test]
fn registered_template_can_be_rendered_with_custom_handlebars_context() {
let mut content_engine = MockContentEngine::new();
content_engine
.register_template("test", "{{ ping }}")
.expect("Could not register test template");

let template = RegisteredTemplate::new(
"test",
MediaType::from_media_range(mime::TEXT_PLAIN).unwrap(),
);

let replaced_render_data = handlebars::Context::wraps(hashmap!["ping" => "pong"])
.expect("Could not create fake render data");
let mut handlebars_render_context = handlebars::RenderContext::new(None);
handlebars_render_context.set_context(replaced_render_data);

let rendered = template.render_to_native_media_type(
content_engine.handlebars_registry(),
content_engine
.render_context(Some(route("/test")), hashmap![], hashmap![])
.data,
Some(handlebars_render_context),
);

let template_output = media_to_string(rendered.expect("Rendering failed"));
assert_eq!(template_output, "pong");
}

#[test]
fn executables_execute_when_rendered() {
let path = format!("{}/src", PROJECT_DIRECTORY);
Expand Down
1 change: 1 addition & 0 deletions src/content/content_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ impl Render for ContentRepresentations {
.render_to_native_media_type(
context.content_engine.handlebars_registry(),
context.data.clone(),
context.handlebars_render_context.clone()
)
.map(box_media),
RegisteredContent::Executable(renderable) => renderable
Expand Down
10 changes: 4 additions & 6 deletions src/content/handlebars_helpers/get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ where
helper: &handlebars::Helper<'registry, 'context>,
_: &'registry Handlebars<'registry>,
handlebars_context: &'context handlebars::Context,
_: &mut handlebars::RenderContext<'registry, 'context>,
handlebars_render_context: &mut handlebars::RenderContext<'registry, 'context>,
output: &mut dyn handlebars::Output,
) -> handlebars::HelperResult {
let content_engine = self
Expand Down Expand Up @@ -91,11 +91,9 @@ where
let query_parameters = get_query_parameters(current_render_data, handlebars_context)?;
let request_headers = get_request_headers(current_render_data, handlebars_context)?;

let context = content_engine.render_context(
optional_request_route,
query_parameters,
request_headers,
);
let context = content_engine
.render_context(optional_request_route, query_parameters, request_headers)
.with_handlebars_render_context(handlebars_render_context.clone());

let rendered = content_item
.render(context, &[target_media_type.into_media_range()]).map_err(|render_error| {
Expand Down
11 changes: 11 additions & 0 deletions src/content/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ where
{
content_engine: &'engine Engine,
data: RenderData<ServerInfo>,
handlebars_render_context: Option<handlebars::RenderContext<'engine, 'engine>>,
}

impl<'engine, ServerInfo, Engine> RenderContext<'engine, ServerInfo, Engine>
Expand All @@ -184,4 +185,14 @@ where
..self
}
}

pub fn with_handlebars_render_context(
self,
handlebars_render_context: handlebars::RenderContext<'engine, 'engine>,
) -> Self {
RenderContext {
handlebars_render_context: Some(handlebars_render_context),
..self
}
}
}
1 change: 1 addition & 0 deletions src/content/test_lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ impl<'a> ContentEngine<()> for MockContentEngine<'a> {
) -> RenderContext<(), Self> {
RenderContext {
content_engine: self,
handlebars_render_context: None,
data: RenderData {
server_info: (),
index: ContentIndex::Directory(ContentIndexEntries::new()),
Expand Down

0 comments on commit 136cfc3

Please sign in to comment.