diff --git a/examples/decorator/template.hbs b/examples/decorator/template.hbs index c21a40395..5b965182b 100644 --- a/examples/decorator/template.hbs +++ b/examples/decorator/template.hbs @@ -7,12 +7,12 @@

CSL {{year}}

{{*set version="v3.0"}} diff --git a/examples/error/template.hbs b/examples/error/template.hbs index eefc5388a..9ed5b7bde 100644 --- a/examples/error/template.hbs +++ b/examples/error/template.hbs @@ -5,13 +5,13 @@

CSL {{year}}

Rendered by Handlebars from {{engine}} data.

diff --git a/examples/partials/base0.hbs b/examples/partials/base0.hbs index 63360e2af..34b38e763 100644 --- a/examples/partials/base0.hbs +++ b/examples/partials/base0.hbs @@ -2,6 +2,6 @@ {{title}}

Derived from base0.hbs

- {{~> page}} + {{> page}} diff --git a/examples/partials/base1.hbs b/examples/partials/base1.hbs index 3eddcd763..8f771dfad 100644 --- a/examples/partials/base1.hbs +++ b/examples/partials/base1.hbs @@ -2,6 +2,6 @@ {{title}}

Derived from base1.hbs

- {{~> page}} + {{> page}} diff --git a/examples/partials/template2.hbs b/examples/partials/template2.hbs index 091f242c8..0ba758942 100644 --- a/examples/partials/template2.hbs +++ b/examples/partials/template2.hbs @@ -1,5 +1,4 @@ {{#*inline "page"}}

Rendered in partial, parent is {{parent}}

{{/inline}} -{{! remove whitespaces with ~ }} -{{~> (parent)~}} +{{> (parent)}} diff --git a/examples/render/template.hbs b/examples/render/template.hbs index b6817adb1..2a62d014f 100644 --- a/examples/render/template.hbs +++ b/examples/render/template.hbs @@ -5,12 +5,12 @@

CSL {{year}}

Rendered by Handlebars from {{engine}} data.

diff --git a/examples/script/template.hbs b/examples/script/template.hbs index cfcb0d2cc..c04253c72 100644 --- a/examples/script/template.hbs +++ b/examples/script/template.hbs @@ -1,10 +1,10 @@ Bundesliga Match Day -{{#each this as |match| ~}} +{{#each this as |match|}} {{#each match as |team|}} {{team.name}} - {{score team.goals}} {{#each team.goals as |scorer|}} > {{scorer}} {{/each}} - {{~ /each}} + {{/each}} --- {{/each}} diff --git a/src/grammar.pest b/src/grammar.pest index 34044324d..9f87fae94 100644 --- a/src/grammar.pest +++ b/src/grammar.pest @@ -55,37 +55,45 @@ decorator_expression = { "{{" ~ pre_whitespace_omitter? ~ "*" ~ exp_line ~ pro_whitespace_omitter? ~ "}}" } partial_expression = { "{{" ~ pre_whitespace_omitter? ~ ">" ~ partial_exp_line ~ pro_whitespace_omitter? ~ "}}" } + +brackets_open = @{ (NEWLINE ~ (" "|"\t")*)? ~ "{{" } +brackets_close = @{ "}}" ~ ((" "|"\t")* ~ NEWLINE)? } + invert_tag_item = { "else"|"^" } -invert_tag = { !escape ~ "{{" ~ pre_whitespace_omitter? ~ invert_tag_item - ~ pro_whitespace_omitter? ~ "}}"} -helper_block_start = { "{{" ~ pre_whitespace_omitter? ~ "#" ~ exp_line ~ - pro_whitespace_omitter? ~ "}}" } -helper_block_end = { "{{" ~ pre_whitespace_omitter? ~ "/" ~ identifier ~ - pro_whitespace_omitter? ~ "}}" } +invert_tag = { !escape ~ brackets_open ~ pre_whitespace_omitter? ~ invert_tag_item + ~ pro_whitespace_omitter? ~ brackets_close } +helper_block_start = { brackets_open ~ pre_whitespace_omitter? ~ "#" ~ exp_line ~ + pro_whitespace_omitter? ~ brackets_close } +helper_block_end = { brackets_open ~ pre_whitespace_omitter? ~ "/" ~ identifier ~ + pro_whitespace_omitter? ~ brackets_close } helper_block = _{ helper_block_start ~ template ~ (invert_tag ~ template)? ~ helper_block_end } -decorator_block_start = { "{{" ~ pre_whitespace_omitter? ~ "#" ~ "*" - ~ exp_line ~ pro_whitespace_omitter? ~ "}}" } -decorator_block_end = { "{{" ~ pre_whitespace_omitter? ~ "/" ~ identifier ~ - pro_whitespace_omitter? ~ "}}" } +decorator_block_start = { brackets_open ~ pre_whitespace_omitter? ~ "#" ~ "*" + ~ exp_line ~ pro_whitespace_omitter? ~ brackets_close } +decorator_block_end = { brackets_open ~ pre_whitespace_omitter? ~ "/" ~ identifier ~ + pro_whitespace_omitter? ~ brackets_close } decorator_block = _{ decorator_block_start ~ template ~ decorator_block_end } -partial_block_start = { "{{" ~ pre_whitespace_omitter? ~ "#" ~ ">" - ~ partial_exp_line ~ pro_whitespace_omitter? ~ "}}" } -partial_block_end = { "{{" ~ pre_whitespace_omitter? ~ "/" ~ partial_identifier ~ - pro_whitespace_omitter? ~ "}}" } +partial_block_start = { brackets_open ~ pre_whitespace_omitter? ~ "#" ~ ">" + ~ partial_exp_line ~ pro_whitespace_omitter? ~ brackets_close } +partial_block_end = { brackets_open ~ pre_whitespace_omitter? ~ "/" ~ partial_identifier ~ + pro_whitespace_omitter? ~ brackets_close } partial_block = _{ partial_block_start ~ template ~ partial_block_end } -raw_block_start = { "{{{{" ~ pre_whitespace_omitter? ~ exp_line ~ - pro_whitespace_omitter? ~ "}}}}" } -raw_block_end = { "{{{{" ~ pre_whitespace_omitter? ~ "/" ~ identifier ~ - pro_whitespace_omitter? ~ "}}}}" } +double_brackets_open = @{ (NEWLINE ~ (" "|"\t")*)? ~ "{{{{" } +double_brackets_close = @{ "}}}}" ~ ((" "|"\t")* ~ NEWLINE)? } + +raw_block_start = { double_brackets_open ~ pre_whitespace_omitter? ~ exp_line ~ + pro_whitespace_omitter? ~ double_brackets_close } +raw_block_end = { double_brackets_open ~ pre_whitespace_omitter? ~ "/" ~ identifier ~ + pro_whitespace_omitter? ~ double_brackets_close } raw_block = _{ raw_block_start ~ raw_block_text ~ raw_block_end } -hbs_comment = { "{{!--" ~ (!"--}}" ~ ANY)* ~ "--}}" } -hbs_comment_compact = { "{{!" ~ (!"}}" ~ ANY)* ~ "}}" } +comment_brackets_open = @{ ("\r"? ~ "\n" ~ (" "|"\t")*)? ~ "{{!" } +hbs_comment = { comment_brackets_open ~ "--" ~ (!"--}}" ~ ANY)* ~ "--" ~ brackets_close } +hbs_comment_compact = { comment_brackets_open ~ (!"}}" ~ ANY)* ~ brackets_close } template = { ( raw_text | diff --git a/src/grammar.rs b/src/grammar.rs index 40d526bbc..6f7b23803 100644 --- a/src/grammar.rs +++ b/src/grammar.rs @@ -145,7 +145,9 @@ mod test { let s = vec!["{{!-- {{this.title}} - --}}"]; + --}}", + "\r\n {{!-- yes --}} \r\n", + "{{! -- good --}}"]; for i in s.iter() { assert_rule!(Rule::hbs_comment, i); } @@ -225,6 +227,10 @@ mod test { "{{#each people as |person|}}", "{{#each-obj obj as |val key|}}", "{{#each assets}}", + "\n{{#each assets}}\n", + "\r\n{{#each assets}}\r\n", + "\r\n {{#each assets}}\r\n", + "\r\n\t\t{{#each assets}}\r\n", ]; for i in s.iter() { assert_rule!(Rule::helper_block_start, i); @@ -252,6 +258,7 @@ mod test { "{{#if}}hello{{else~}}world{{/if}}", "{{#if}}hello{{~^~}}world{{/if}}", "{{#if}}{{/if}}", + "\r\n{{#if}}\r\n\r\n{{/if}}\r\n", ]; for i in s.iter() { assert_rule!(Rule::helper_block, i); @@ -263,6 +270,7 @@ mod test { let s = vec![ "{{{{if hello}}}}good {{hello}}{{{{/if}}}}", "{{{{if hello}}}}{{#if nice}}{{/if}}{{{{/if}}}}", + "\n{{{{if hello}}}}\n{{#if nice}}{{/if}}{{{{/if}}}}", ]; for i in s.iter() { assert_rule!(Rule::raw_block, i); diff --git a/src/helpers/helper_if.rs b/src/helpers/helper_if.rs index 3f8f040bd..10c424f5f 100644 --- a/src/helpers/helper_if.rs +++ b/src/helpers/helper_if.rs @@ -126,4 +126,14 @@ mod test { .unwrap() ); } + + #[test] + fn test_invisible_line_stripping() { + let hbs = Registry::new(); + assert_eq!( + "yes\n", + hbs.render_template("{{#if a}}\nyes\n{{/if}}\n", &json!({"a": true})) + .unwrap() + ); + } } diff --git a/src/template.rs b/src/template.rs index b9240eedb..5d05b059e 100644 --- a/src/template.rs +++ b/src/template.rs @@ -441,7 +441,18 @@ impl Template { // remove escape from our pair queue let mut it = parser_queue .flatten() - .filter(|p| p.as_rule() != Rule::escape) + .filter(|p| { + // remove rules that should be silent but not for now due to pest limitation + !matches!( + p.as_rule(), + Rule::escape + | Rule::brackets_open + | Rule::brackets_close + | Rule::double_brackets_open + | Rule::double_brackets_close + | Rule::comment_brackets_open + ) + }) .peekable(); let mut end_pos: Option> = None; loop { @@ -1025,7 +1036,9 @@ fn test_whitespace_elements() { " {{elem}}\n\t{{#if true}} \ {{/if}}\n{{{{raw}}}} {{{{/raw}}}}\n{{{{raw}}}}{{{{/raw}}}}\n", ); - assert_eq!(c.ok().unwrap().elements.len(), 9); + let r = c.unwrap(); + // the \n after last raw block is dropped by pest + assert_eq!(r.elements.len(), 6); } #[test]