diff --git a/History.md b/History.md index 940f2b5a6..7d619219f 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,9 @@ # Liquid Change Log -## 5.3.1 (unreleased) +## 5.4.0 (unreleased) + +### Features +* Allow `#` to be used as an inline comment tag (#1498) [CP Clermont] ### Fixes * `PartialCache` now shares snippet cache with subcontexts by default (#1553) [Chris AtLee] diff --git a/lib/liquid.rb b/lib/liquid.rb index f6aabb0d0..a0a058810 100644 --- a/lib/liquid.rb +++ b/lib/liquid.rb @@ -29,6 +29,7 @@ module Liquid WhitespaceControl = '-' TagStart = /\{\%/ TagEnd = /\%\}/ + TagName = /#|\w+/ VariableSignature = /\(?[\w\-\.\[\]]\)?/ VariableSegment = /[\w\-]/ VariableStart = /\{\{/ diff --git a/lib/liquid/block_body.rb b/lib/liquid/block_body.rb index d8c7e453f..a0d35a790 100644 --- a/lib/liquid/block_body.rb +++ b/lib/liquid/block_body.rb @@ -4,8 +4,8 @@ module Liquid class BlockBody - LiquidTagToken = /\A\s*(\w+)\s*(.*?)\z/o - FullToken = /\A#{TagStart}#{WhitespaceControl}?(\s*)(\w+)(\s*)(.*?)#{WhitespaceControl}?#{TagEnd}\z/om + LiquidTagToken = /\A\s*(#{TagName})\s*(.*?)\z/o + FullToken = /\A#{TagStart}#{WhitespaceControl}?(\s*)(#{TagName})(\s*)(.*?)#{WhitespaceControl}?#{TagEnd}\z/om ContentOfVariable = /\A#{VariableStart}#{WhitespaceControl}?(.*?)#{WhitespaceControl}?#{VariableEnd}\z/om WhitespaceOrNothing = /\A\s*\z/ TAGSTART = "{%" diff --git a/lib/liquid/locales/en.yml b/lib/liquid/locales/en.yml index eb35d8689..7e232de42 100644 --- a/lib/liquid/locales/en.yml +++ b/lib/liquid/locales/en.yml @@ -13,15 +13,16 @@ for_invalid_attribute: "Invalid attribute in for loop. Valid attributes are limit and offset" if: "Syntax Error in tag 'if' - Valid syntax: if [expression]" include: "Error in tag 'include' - Valid syntax: include '[template]' (with|for) [object|collection]" - unknown_tag: "Unknown tag '%{tag}'" + inline_comment_invalid: "Syntax error in tag '#' - Each line of comments must be prefixed by the '#' character" invalid_delimiter: "'%{tag}' is not a valid delimiter for %{block_name} tags. use %{block_delimiter}" + render: "Syntax error in tag 'render' - Template name must be a quoted string" + table_row: "Syntax Error in 'table_row loop' - Valid syntax: table_row [item] in [collection] cols=3" + tag_never_closed: "'%{block_name}' tag was never closed" + tag_termination: "Tag '%{token}' was not properly terminated with regexp: %{tag_end}" unexpected_else: "%{block_name} tag does not expect 'else' tag" unexpected_outer_tag: "Unexpected outer '%{tag}' tag" - tag_termination: "Tag '%{token}' was not properly terminated with regexp: %{tag_end}" + unknown_tag: "Unknown tag '%{tag}'" variable_termination: "Variable '%{token}' was not properly terminated with regexp: %{tag_end}" - tag_never_closed: "'%{block_name}' tag was never closed" - table_row: "Syntax Error in 'table_row loop' - Valid syntax: table_row [item] in [collection] cols=3" - render: "Syntax error in tag 'render' - Template name must be a quoted string" argument: include: "Argument error in tag 'include' - Illegal template name" disabled: diff --git a/lib/liquid/tags/inline_comment.rb b/lib/liquid/tags/inline_comment.rb new file mode 100644 index 000000000..493cfddc7 --- /dev/null +++ b/lib/liquid/tags/inline_comment.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +module Liquid + class InlineComment < Tag + def initialize(tag_name, markup, options) + super + + # Semantically, a comment should only ignore everything after it on the line. + # Currently, this implementation doesn't support mixing a comment with another tag + # but we need to reserve future support for this and prevent the introduction + # of inline comments from being backward incompatible change. + # + # As such, we're forcing users to put a # symbol on every line otherwise this + # tag will throw an error. + if markup.match?(/\n\s*[^#\s]/) + raise SyntaxError, options[:locale].t("errors.syntax.inline_comment_invalid") + end + end + + def render_to_output_buffer(_context, output) + output + end + + def blank? + true + end + end + + Template.register_tag('#', InlineComment) +end diff --git a/lib/liquid/version.rb b/lib/liquid/version.rb index 3fc87a5af..9b0de1431 100644 --- a/lib/liquid/version.rb +++ b/lib/liquid/version.rb @@ -2,5 +2,5 @@ # frozen_string_literal: true module Liquid - VERSION = "5.3.0" + VERSION = "5.4.0.alpha" end diff --git a/test/integration/tags/inline_comment_test.rb b/test/integration/tags/inline_comment_test.rb new file mode 100644 index 000000000..a4fb23ee1 --- /dev/null +++ b/test/integration/tags/inline_comment_test.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +require 'test_helper' + +class InlineCommentTest < Minitest::Test + include Liquid + + def test_inline_comment_returns_nothing + assert_template_result('', '{%- # this is an inline comment -%}') + assert_template_result('', '{%-# this is an inline comment -%}') + assert_template_result('', '{% # this is an inline comment %}') + assert_template_result('', '{%# this is an inline comment %}') + end + + def test_inline_comment_does_not_require_a_space_after_the_pound_sign + assert_template_result('', '{%#this is an inline comment%}') + end + + def test_liquid_inline_comment_returns_nothing + assert_template_result('Hey there, how are you doing today?', <<~LIQUID) + {%- liquid + # This is how you'd write a block comment in a liquid tag. + # It looks a lot like what you'd have in ruby. + + # You can use it as inline documentation in your + # liquid blocks to explain why you're doing something. + echo "Hey there, " + + # It won't affect the output. + echo "how are you doing today?" + -%} + LIQUID + end + + def test_inline_comment_can_be_written_on_multiple_lines + assert_template_result('', <<~LIQUID) + {%- + # That kind of block comment is also allowed. + # It would only be a stylistic difference. + + # Much like JavaScript's /* */ comments and their + # leading * on new lines. + -%} + LIQUID + end + + def test_inline_comment_multiple_pound_signs + assert_template_result('', <<~LIQUID) + {%- liquid + ###################################### + # We support comments like this too. # + ###################################### + -%} + LIQUID + end + + def test_inline_comments_require_the_pound_sign_on_every_new_line + assert_match_syntax_error("Each line of comments must be prefixed by the '#' character", <<~LIQUID) + {%- + # some comment + echo 'hello world' + -%} + LIQUID + end + + def test_inline_comment_does_not_support_nested_tags + assert_template_result(' -%}', "{%- # {% echo 'hello world' %} -%}") + end +end