Skip to content

Commit

Permalink
Merge pull request #658 from cmrschwarz/recursive_empty_partials_fix
Browse files Browse the repository at this point in the history
Fix edge case around nested empty partials
  • Loading branch information
sunng87 authored Jul 14, 2024
2 parents 38f94d9 + c60ef28 commit 98d51a1
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 6 deletions.
54 changes: 48 additions & 6 deletions src/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,16 @@ pub struct RenderContextInner<'reg: 'rc, 'rc> {
/// root template name
root_template: Option<&'reg String>,
disable_escape: bool,
// whether the previous text that we rendered ended on a newline
// necessary to make indenting decisions after the end of partials

// Indicates whether the previous text that we rendered ended on a newline.
// This is necessary to make indenting decisions after the end of partials.
trailing_newline: bool,
// whether the previous text that we render should indent itself

// This should be set to true whenever any output is written.
// We need this to detect empty partials/helpers for indenting decisions.
content_produced: bool,

// The next text that we render should indent itself.
indent_before_write: bool,
indent_string: Option<Cow<'reg, str>>,
}
Expand All @@ -72,6 +78,7 @@ impl<'reg: 'rc, 'rc> RenderContext<'reg, 'rc> {
root_template,
disable_escape: false,
trailing_newline: false,
content_produced: false,
indent_before_write: false,
indent_string: None,
});
Expand Down Expand Up @@ -304,6 +311,16 @@ impl<'reg: 'rc, 'rc> RenderContext<'reg, 'rc> {
self.inner().trailing_newline
}

#[inline]
pub fn set_content_produced(&mut self, content_produced: bool) {
self.inner_mut().content_produced = content_produced;
}

#[inline]
pub fn get_content_produced(&self) -> bool {
self.inner().content_produced
}

#[inline]
pub fn set_indent_before_write(&mut self, indent_before_write: bool) {
self.inner_mut().indent_before_write = indent_before_write;
Expand Down Expand Up @@ -786,9 +803,21 @@ fn render_helper<'reg: 'rc, 'rc>(
h.hash()
);
let mut call_indent_aware = |helper_def: &dyn HelperDef, rc: &mut RenderContext<'reg, 'rc>| {
rc.set_indent_before_write(ht.indent_before_write && rc.get_trailine_newline());
let indent_directive_before = rc.get_indent_before_write();
let content_produced_before = rc.get_content_produced();
rc.set_content_produced(false);
rc.set_indent_before_write(
indent_directive_before || (ht.indent_before_write && rc.get_trailine_newline()),
);

helper_def.call(&h, registry, ctx, rc, out)?;
rc.set_indent_before_write(rc.get_trailine_newline());

if rc.get_content_produced() {
rc.set_indent_before_write(rc.get_trailine_newline());
} else {
rc.set_content_produced(content_produced_before);
rc.set_indent_before_write(indent_directive_before);
}
Ok(())
};
if let Some(ref d) = rc.get_local_helper(h.name()) {
Expand Down Expand Up @@ -827,6 +856,7 @@ pub fn indent_aware_write(
if v.is_empty() {
return Ok(());
}
rc.set_content_produced(true);

if !v.starts_with(newline_matcher) && rc.get_indent_before_write() {
if let Some(indent) = rc.get_indent_string() {
Expand Down Expand Up @@ -904,11 +934,23 @@ impl Renderable for TemplateElement {
DecoratorExpression(_) | DecoratorBlock(_) => self.eval(registry, ctx, rc),
PartialExpression(ref dt) | PartialBlock(ref dt) => {
let di = Decorator::try_from_template(dt, registry, ctx, rc)?;

let indent_directive_before = rc.get_indent_before_write();
let content_produced_before = rc.get_content_produced();

rc.set_indent_before_write(
dt.indent_before_write && (rc.get_trailine_newline() || dt.indent.is_some()),
);
rc.set_content_produced(false);

partial::expand_partial(&di, registry, ctx, rc, out)?;
rc.set_indent_before_write(rc.get_trailine_newline());

if rc.get_content_produced() {
rc.set_indent_before_write(rc.get_trailine_newline());
} else {
rc.set_content_produced(content_produced_before);
rc.set_indent_before_write(indent_directive_before);
}
Ok(())
}
_ => Ok(()),
Expand Down
30 changes: 30 additions & 0 deletions tests/whitespace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,36 @@ foo
);
}

#[test]
fn test_empty_inline_partials_and_helpers_retain_indent_directive() {
let input = r#"
{{~#*inline "empty_partial"}}{{/inline}}
{{~#*inline "indented_partial"}}
{{>empty_partial}}{{#if true}}{{>empty_partial}}{{/if}}foo
{{/inline}}
{{>indented_partial}}
"#;
let output = " foo\n";
let hbs = Handlebars::new();

assert_eq!(hbs.render_template(input, &()).unwrap(), output);
}

#[test]
fn test_indent_directive_propagated_but_not_restored_if_content_was_written() {
let input = r#"
{{~#*inline "indented_partial"}}
{{#if true}}{{/if}}{{#if true}}foo{{/if}}foo
{{/inline}}
{{>indented_partial}}
"#;
let output = " foofoo\n";
let hbs = Handlebars::new();

assert_eq!(hbs.render_template(input, &()).unwrap(), output);
}

//regression test for #611
#[test]
fn tag_before_eof_becomes_standalone_in_full_template() {
Expand Down

0 comments on commit 98d51a1

Please sign in to comment.