From 65b1dedac547ca5a89e5613554e8ddacf8ae1018 Mon Sep 17 00:00:00 2001 From: James Meng Date: Thu, 1 May 2025 09:11:15 -0700 Subject: [PATCH 1/5] Expose tag body in the Doc tag --- lib/liquid/tags/doc.rb | 5 +++++ test/unit/tags/doc_tag_unit_test.rb | 15 +++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/lib/liquid/tags/doc.rb b/lib/liquid/tags/doc.rb index 2138b641..4c650b8c 100644 --- a/lib/liquid/tags/doc.rb +++ b/lib/liquid/tags/doc.rb @@ -30,8 +30,11 @@ module Liquid class Doc < Block NO_UNEXPECTED_ARGS = /\A\s*\z/ + attr_reader :body + def initialize(tag_name, markup, parse_context) super + @body = +"" ensure_valid_markup(tag_name, markup, parse_context) end @@ -43,8 +46,10 @@ module Liquid if tag_name == block_delimiter parse_context.trim_whitespace = (token[-3] == WhitespaceControl) + @body << Regexp.last_match(1) if Regexp.last_match(1) != "" return end + @body << token unless token.empty? end raise_tag_never_closed(block_name) diff --git a/test/unit/tags/doc_tag_unit_test.rb b/test/unit/tags/doc_tag_unit_test.rb index a0a36629..1d5db06d 100644 --- a/test/unit/tags/doc_tag_unit_test.rb +++ b/test/unit/tags/doc_tag_unit_test.rb @@ -20,6 +20,21 @@ class DocTagUnitTest < Minitest::Test assert_template_result('', template) end + def test_doc_tag_body_content + doc_content = " Documentation content\n @param {string} foo - test\n" + template_source = "{% doc %}#{doc_content}{% enddoc %}" + + doc_tag = nil + ParseTreeVisitor + .for(Template.parse(template_source).root) + .add_callback_for(Liquid::Doc) do |tag| + doc_tag = tag + end + .visit + + assert_equal(doc_content, doc_tag.body) + end + def test_doc_tag_does_not_support_extra_arguments error = assert_raises(Liquid::SyntaxError) do template = <<~LIQUID.chomp From 79a771d72427a514bcbff674dfd42af87d0e3f0f Mon Sep 17 00:00:00 2001 From: James Meng Date: Wed, 4 Jun 2025 19:30:47 -0700 Subject: [PATCH 2/5] Add test for doc tag capturing token before enddoc --- test/unit/tags/doc_tag_unit_test.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/unit/tags/doc_tag_unit_test.rb b/test/unit/tags/doc_tag_unit_test.rb index 1d5db06d..cf17b1d0 100644 --- a/test/unit/tags/doc_tag_unit_test.rb +++ b/test/unit/tags/doc_tag_unit_test.rb @@ -131,6 +131,20 @@ class DocTagUnitTest < Minitest::Test assert_template_result('', template) end + def test_doc_tag_captures_token_before_enddoc + template_source = "{% doc %}{{ incomplete{% enddoc %}" + + doc_tag = nil + ParseTreeVisitor + .for(Template.parse(template_source).root) + .add_callback_for(Liquid::Doc) do |tag| + doc_tag = tag + end + .visit + + assert_equal("{{ incomplete", doc_tag.body) + end + def test_doc_tag_preserves_error_line_numbers template = Liquid::Template.parse(<<~LIQUID.chomp, line_numbers: true) {% doc %} From 8548b96a97a65720552d7bef74e4404b11facedd Mon Sep 17 00:00:00 2001 From: James Meng Date: Fri, 6 Jun 2025 12:06:35 -0700 Subject: [PATCH 3/5] Remove `body` attr_reader and initiliaze `@body` instance variable in `parse` method --- lib/liquid/tags/doc.rb | 7 +++---- test/unit/tags/doc_tag_unit_test.rb | 6 +++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/liquid/tags/doc.rb b/lib/liquid/tags/doc.rb index 4c650b8c..b61d7e95 100644 --- a/lib/liquid/tags/doc.rb +++ b/lib/liquid/tags/doc.rb @@ -30,15 +30,14 @@ module Liquid class Doc < Block NO_UNEXPECTED_ARGS = /\A\s*\z/ - attr_reader :body - def initialize(tag_name, markup, parse_context) super - @body = +"" ensure_valid_markup(tag_name, markup, parse_context) end def parse(tokens) + @body = +"" + while (token = tokens.shift) tag_name = token =~ BlockBody::FullTokenPossiblyInvalid && Regexp.last_match(2) @@ -64,7 +63,7 @@ module Liquid end def nodelist - [] + [@body] end private diff --git a/test/unit/tags/doc_tag_unit_test.rb b/test/unit/tags/doc_tag_unit_test.rb index cf17b1d0..7c6ef6f3 100644 --- a/test/unit/tags/doc_tag_unit_test.rb +++ b/test/unit/tags/doc_tag_unit_test.rb @@ -32,7 +32,7 @@ class DocTagUnitTest < Minitest::Test end .visit - assert_equal(doc_content, doc_tag.body) + assert_equal(doc_content, doc_tag.nodelist.first.to_s) end def test_doc_tag_does_not_support_extra_arguments @@ -132,7 +132,7 @@ class DocTagUnitTest < Minitest::Test end def test_doc_tag_captures_token_before_enddoc - template_source = "{% doc %}{{ incomplete{% enddoc %}" + template_source = "{% doc %}{{ incomplete{% enddoc %}" doc_tag = nil ParseTreeVisitor @@ -142,7 +142,7 @@ class DocTagUnitTest < Minitest::Test end .visit - assert_equal("{{ incomplete", doc_tag.body) + assert_equal("{{ incomplete", doc_tag.nodelist.first.to_s) end def test_doc_tag_preserves_error_line_numbers From 7b2b25fda1ff025b7ec790cdd28fb9535de96f3d Mon Sep 17 00:00:00 2001 From: James Meng Date: Mon, 9 Jun 2025 11:36:18 -0700 Subject: [PATCH 4/5] Fix Doc tag blank? method to check body content Previously the blank? method always returned true. Now it properly checks if the body is empty, making the tag behavior consistent with other tags. Also updated test to use whitespace control for cleaner assertions. --- lib/liquid/tags/doc.rb | 2 +- test/unit/tags/doc_tag_unit_test.rb | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/liquid/tags/doc.rb b/lib/liquid/tags/doc.rb index b61d7e95..499102d7 100644 --- a/lib/liquid/tags/doc.rb +++ b/lib/liquid/tags/doc.rb @@ -59,7 +59,7 @@ module Liquid end def blank? - true + @body.empty? end def nodelist diff --git a/test/unit/tags/doc_tag_unit_test.rb b/test/unit/tags/doc_tag_unit_test.rb index 7c6ef6f3..64b950b7 100644 --- a/test/unit/tags/doc_tag_unit_test.rb +++ b/test/unit/tags/doc_tag_unit_test.rb @@ -174,11 +174,11 @@ class DocTagUnitTest < Minitest::Test def test_doc_tag_delimiter_handling assert_template_result('', <<~LIQUID.chomp) - {% if true %} - {% doc %} - {% docEXTRA %}wut{% enddocEXTRA %}xyz - {% enddoc %} - {% endif %} + {%- if true -%} + {%- doc -%} + {%- docEXTRA -%}wut{% enddocEXTRA -%}xyz + {%- enddoc -%} + {%- endif -%} LIQUID assert_template_result('', "{% doc %}123{% enddoc xyz %}") From 7f2f8a226b013d7fe8abb140f2dea83405ca6623 Mon Sep 17 00:00:00 2001 From: James Meng Date: Mon, 9 Jun 2025 12:24:59 -0700 Subject: [PATCH 5/5] Add tests for new public methods --- test/unit/tags/doc_tag_unit_test.rb | 74 +++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/test/unit/tags/doc_tag_unit_test.rb b/test/unit/tags/doc_tag_unit_test.rb index 64b950b7..223f3ca0 100644 --- a/test/unit/tags/doc_tag_unit_test.rb +++ b/test/unit/tags/doc_tag_unit_test.rb @@ -196,6 +196,80 @@ class DocTagUnitTest < Minitest::Test ) end + def test_doc_tag_blank_with_empty_content + template_source = "{% doc %}{% enddoc %}" + + doc_tag = nil + ParseTreeVisitor + .for(Template.parse(template_source).root) + .add_callback_for(Liquid::Doc) do |tag| + doc_tag = tag + end + .visit + + assert_equal(true, doc_tag.blank?) + end + + def test_doc_tag_blank_with_content + template_source = "{% doc %}Some documentation{% enddoc %}" + + doc_tag = nil + ParseTreeVisitor + .for(Template.parse(template_source).root) + .add_callback_for(Liquid::Doc) do |tag| + doc_tag = tag + end + .visit + + assert_equal(false, doc_tag.blank?) + end + + def test_doc_tag_blank_with_whitespace_only + template_source = "{% doc %} {% enddoc %}" + + doc_tag = nil + ParseTreeVisitor + .for(Template.parse(template_source).root) + .add_callback_for(Liquid::Doc) do |tag| + doc_tag = tag + end + .visit + + assert_equal(false, doc_tag.blank?) + end + + def test_doc_tag_nodelist_returns_array_with_body + doc_content = "Documentation content\n@param {string} foo" + template_source = "{% doc %}#{doc_content}{% enddoc %}" + + doc_tag = nil + ParseTreeVisitor + .for(Template.parse(template_source).root) + .add_callback_for(Liquid::Doc) do |tag| + doc_tag = tag + end + .visit + + assert_equal([doc_content], doc_tag.nodelist) + assert_equal(1, doc_tag.nodelist.length) + assert_equal(doc_content, doc_tag.nodelist.first) + end + + def test_doc_tag_nodelist_with_empty_content + template_source = "{% doc %}{% enddoc %}" + + doc_tag = nil + ParseTreeVisitor + .for(Template.parse(template_source).root) + .add_callback_for(Liquid::Doc) do |tag| + doc_tag = tag + end + .visit + + assert_equal([""], doc_tag.nodelist) + assert_equal(1, doc_tag.nodelist.length) + end + private def traversal(template)