diff --git a/lib/ruby-handlebars/parser.rb b/lib/ruby-handlebars/parser.rb index 656b2bf..1031415 100644 --- a/lib/ruby-handlebars/parser.rb +++ b/lib/ruby-handlebars/parser.rb @@ -15,6 +15,7 @@ class Parser < Parslet::Parser rule(:at) { str('@') } rule(:tilde) { str('~') } rule(:caret) { str('^') } + rule(:dash) { str('-') } rule(:else_kw) { str('else') | caret } rule(:as_kw) { str('as') } @@ -24,6 +25,7 @@ class Parser < Parslet::Parser rule(:tccurly) { space? >> tilde.maybe.as(:collapse_after) >> ccurly >> ccurly >> ccurly } rule(:qocurly) { ocurly >> ocurly >> ocurly >> ocurly } rule(:qccurly) { ccurly >> ccurly >> ccurly >> ccurly } + rule(:ddash) { dash >> dash } rule(:else_absent?) { (else_kw >> space? >> dccurly).absent? } rule(:as_absent?) { (as_kw >> space? >> pipe).absent? } @@ -40,8 +42,9 @@ class Parser < Parslet::Parser rule(:path) { identifier >> (dot >> (identifier | else_kw)).repeat } rule(:nocurly) { match('[^{}]') } - rule(:noocurly) { match('[^{]') } - rule(:noccurly) { match('[^}]') } + rule(:noocurly) { match('[^{]') } + rule(:noccurly) { match('[^}]') } + rule(:nodash) { match('[^-]') } rule(:eof) { any.absent? } rule(:sq_string) { str("'") >> match("[^']").repeat.maybe.as(:str_content) >> str("'") } @@ -109,9 +112,29 @@ class Parser < Parslet::Parser rule(:comment) do docurly >> - bang >> - space? >> - nocurly.repeat.maybe.as(:comment) >> + bang >> ( + ( + nodash >> ( + nocurly.repeat(1) | + ocurly >> nocurly | + ocurly >> ocurly >> nocurly | + ccurly >> nocurly + ).repeat(1) + ).as(:comment) | + ( + ddash >> ( + match('[^{}-]').repeat(1) | + dash >> nodash | + dash >> dash >> noccurly | + ocurly >> noocurly | + ocurly >> ocurly >> noocurly | + ocurly >> ocurly >> ocurly >> noocurly | + ccurly | + ocurly >> eof + ).repeat(1).as(:comment) >> + ddash + ) + ) >> dccurly end diff --git a/spec/handlebars_spec.rb b/spec/handlebars_spec.rb index df31cbd..c4487c1 100644 --- a/spec/handlebars_spec.rb +++ b/spec/handlebars_spec.rb @@ -59,6 +59,16 @@ def evaluate(template, args = {}) it 'can remove comments with whitespace' do expect(evaluate('Hello {{~! comment content~}} world')).to eq('Hello world') end + + it "removes multiline comments" do + expect(evaluate(<<~TEMPLATE.strip)).to eq("Hello\n\nworld") + Hello + {{!-- + this is a multiline comment, with {{handlebars}} and -- included + --}} + world + TEMPLATE + end end context 'partials' do diff --git a/spec/parser_spec.rb b/spec/parser_spec.rb index a3d09ab..9e44da8 100644 --- a/spec/parser_spec.rb +++ b/spec/parser_spec.rb @@ -95,12 +95,29 @@ ) end - it 'comments' do - expect(parser.parse('{{! this is a comment }}')).to eq( - block_items: [ - collapse_options.merge(comment: 'this is a comment ') - ] - ) + context "with comments" do + it 'parses single-line comments' do + expect(parser.parse('foo{{! this is a {{comment} }}bar')).to eq( + block_items: [ + {template_content: 'foo'}, + collapse_options.merge(comment: ' this is a {{comment} '), + {template_content: 'bar'}, + ] + ) + end + + it 'parses multi-line comments' do + template = <<~TEMPLATE.strip + foo{{!--\nthis is a multiline {{{comment}}},\nand it contains -- and {}.\n--}}bar + TEMPLATE + expect(parser.parse(template)).to eq( + block_items: [ + {template_content: 'foo'}, + collapse_options.merge(comment: "\nthis is a multiline {{{comment}}},\nand it contains -- and {}.\n"), + {template_content: 'bar'}, + ] + ) + end end context 'helpers' do