Skip to content

Commit 05dc7d7

Browse files
Add # inline comment tag.
This commit adds a new tag named `#` that behaves like a comment. Therefore it behaves as you'd expect any tag would work. The difference with the comment tag is that the comment is in the tag markup and that there is no block delimiter. What it looks like in practice: ```liquid {%- # this is an inline comment -%} {% # this too is an inline comment %} {% liquid # required args: assign product = product # optional args: assign should_show_border = should_show_border | default: true assign should_show_cursor = should_show_cursor | default: true %} {% liquid # This is a very long comment that spans multiple lines. # It looks very similar to what it would look like if you wrote # ruby code instead of liquid. But it doesn't have all the clunk # of having an open tag and a close tag with so many characters. %} ``` Co-authored-by: Dylan Thacker-Smith <Dylan.Smith@shopify.com>
1 parent db3999a commit 05dc7d7

6 files changed

Lines changed: 108 additions & 8 deletions

File tree

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ group :test do
2323
gem 'rubocop-performance', require: false
2424

2525
platform :mri, :truffleruby do
26-
gem 'liquid-c', github: 'Shopify/liquid-c', ref: 'master'
26+
gem 'liquid-c', github: 'Shopify/liquid-c', ref: 'inline-comment-fresh'
2727
end
2828
end

lib/liquid.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ module Liquid
2929
WhitespaceControl = '-'
3030
TagStart = /\{\%/
3131
TagEnd = /\%\}/
32+
TagName = /#|\w+/
3233
VariableSignature = /\(?[\w\-\.\[\]]\)?/
3334
VariableSegment = /[\w\-]/
3435
VariableStart = /\{\{/

lib/liquid/block_body.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
module Liquid
66
class BlockBody
7-
LiquidTagToken = /\A\s*(\w+)\s*(.*?)\z/o
8-
FullToken = /\A#{TagStart}#{WhitespaceControl}?(\s*)(\w+)(\s*)(.*?)#{WhitespaceControl}?#{TagEnd}\z/om
7+
LiquidTagToken = /\A\s*(#{TagName})\s*(.*?)\z/o
8+
FullToken = /\A#{TagStart}#{WhitespaceControl}?(\s*)(#{TagName})(\s*)(.*?)#{WhitespaceControl}?#{TagEnd}\z/om
99
ContentOfVariable = /\A#{VariableStart}#{WhitespaceControl}?(.*?)#{WhitespaceControl}?#{VariableEnd}\z/om
1010
WhitespaceOrNothing = /\A\s*\z/
1111
TAGSTART = "{%"

lib/liquid/locales/en.yml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,16 @@
1313
for_invalid_attribute: "Invalid attribute in for loop. Valid attributes are limit and offset"
1414
if: "Syntax Error in tag 'if' - Valid syntax: if [expression]"
1515
include: "Error in tag 'include' - Valid syntax: include '[template]' (with|for) [object|collection]"
16-
unknown_tag: "Unknown tag '%{tag}'"
16+
inline_comment_invalid: "Syntax error in tag '#' - Each line of comments must be prefixed by the '#' character"
1717
invalid_delimiter: "'%{tag}' is not a valid delimiter for %{block_name} tags. use %{block_delimiter}"
18+
render: "Syntax error in tag 'render' - Template name must be a quoted string"
19+
table_row: "Syntax Error in 'table_row loop' - Valid syntax: table_row [item] in [collection] cols=3"
20+
tag_never_closed: "'%{block_name}' tag was never closed"
21+
tag_termination: "Tag '%{token}' was not properly terminated with regexp: %{tag_end}"
1822
unexpected_else: "%{block_name} tag does not expect 'else' tag"
1923
unexpected_outer_tag: "Unexpected outer '%{tag}' tag"
20-
tag_termination: "Tag '%{token}' was not properly terminated with regexp: %{tag_end}"
24+
unknown_tag: "Unknown tag '%{tag}'"
2125
variable_termination: "Variable '%{token}' was not properly terminated with regexp: %{tag_end}"
22-
tag_never_closed: "'%{block_name}' tag was never closed"
23-
table_row: "Syntax Error in 'table_row loop' - Valid syntax: table_row [item] in [collection] cols=3"
24-
render: "Syntax error in tag 'render' - Template name must be a quoted string"
2526
argument:
2627
include: "Argument error in tag 'include' - Illegal template name"
2728
disabled:

lib/liquid/tags/inline_comment.rb

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# frozen_string_literal: true
2+
3+
module Liquid
4+
class InlineComment < Tag
5+
def initialize(tag_name, markup, options)
6+
super
7+
8+
# Semantically, a comment should only ignore everything after it on the line.
9+
# Currently, this implementation doesn't support mixing a comment with another tag
10+
# but we need to reserve future support for this and prevent the introduction
11+
# of inline comments from being backward incompatible change.
12+
#
13+
# As such, we're forcing users to put a # symbol on every line otherwise this
14+
# tag will throw an error.
15+
if markup.match?(/\n\s*[^#\s]/)
16+
raise SyntaxError, options[:locale].t("errors.syntax.inline_comment_invalid")
17+
end
18+
end
19+
20+
def render_to_output_buffer(_context, output)
21+
output
22+
end
23+
24+
def blank?
25+
true
26+
end
27+
end
28+
29+
Template.register_tag('#', InlineComment)
30+
end
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# frozen_string_literal: true
2+
3+
require 'test_helper'
4+
5+
class InlineCommentTest < Minitest::Test
6+
include Liquid
7+
8+
def test_inline_comment_returns_nothing
9+
assert_template_result('', '{%- # this is an inline comment -%}')
10+
assert_template_result('', '{%-# this is an inline comment -%}')
11+
assert_template_result('', '{% # this is an inline comment %}')
12+
assert_template_result('', '{%# this is an inline comment %}')
13+
end
14+
15+
def test_inline_comment_does_not_require_a_space_after_the_pound_sign
16+
assert_template_result('', '{%#this is an inline comment%}')
17+
end
18+
19+
def test_liquid_inline_comment_returns_nothing
20+
assert_template_result('Hey there, how are you doing today?', <<~LIQUID)
21+
{%- liquid
22+
# This is how you'd write a block comment in a liquid tag.
23+
# It looks a lot like what you'd have in ruby.
24+
25+
# You can use it as inline documentation in your
26+
# liquid blocks to explain why you're doing something.
27+
echo "Hey there, "
28+
29+
# It won't affect the output.
30+
echo "how are you doing today?"
31+
-%}
32+
LIQUID
33+
end
34+
35+
def test_inline_comment_can_be_written_on_multiple_lines
36+
assert_template_result('', <<~LIQUID)
37+
{%-
38+
# That kind of block comment is also allowed.
39+
# It would only be a stylistic difference.
40+
# Much like JavaScript's /* */ comments and their
41+
# leading * on new lines.
42+
-%}
43+
LIQUID
44+
end
45+
46+
def test_inline_comment_multiple_pound_signs
47+
assert_template_result('', <<~LIQUID)
48+
{%- liquid
49+
######################################
50+
# We support comments like this too. #
51+
######################################
52+
-%}
53+
LIQUID
54+
end
55+
56+
def test_inline_comments_require_the_pound_sign_on_every_new_line
57+
assert_match_syntax_error("Each line of comments must be prefixed by the '#' character", <<~LIQUID)
58+
{%-
59+
# some comment
60+
echo 'hello world'
61+
-%}
62+
LIQUID
63+
end
64+
65+
def test_inline_comment_does_not_support_nested_tags
66+
assert_template_result(' -%}', "{%- # {% echo 'hello world' %} -%}")
67+
end
68+
end

0 commit comments

Comments
 (0)