diff --git a/lib/jekyll/excerpt.rb b/lib/jekyll/excerpt.rb index fc8f4a92f17..4a91515241b 100644 --- a/lib/jekyll/excerpt.rb +++ b/lib/jekyll/excerpt.rb @@ -131,36 +131,45 @@ def render_with_liquid? # # Returns excerpt String - LIQUID_TAG_REGEX = %r!{%-?\s*(\w+).+\s*-?%}!m.freeze + LIQUID_TAG_REGEX = %r!{%-?\s*(\w+)\s*.*?-?%}!m.freeze MKDWN_LINK_REF_REGEX = %r!^ {0,3}\[[^\]]+\]:.+$!.freeze def extract_excerpt(doc_content) head, _, tail = doc_content.to_s.partition(doc.excerpt_separator) - # append appropriate closing tag (to a Liquid block), to the "head" if the - # partitioning resulted in leaving the closing tag somewhere in the "tail" - # partition. + # append appropriate closing tag(s) (for each Liquid block), to the `head` if the + # partitioning resulted in leaving the closing tag somewhere in the `tail` partition. if head.include?("{%") - head =~ LIQUID_TAG_REGEX - tag_name = Regexp.last_match(1) - - if liquid_block?(tag_name) && head.match(%r!{%-?\s*end#{tag_name}\s*-?%}!).nil? - print_build_warning + modified = false + tag_names = head.scan(LIQUID_TAG_REGEX) + tag_names.flatten! + tag_names.reverse_each do |tag_name| + next unless liquid_block?(tag_name) + next if head =~ endtag_regex_stash(tag_name) + + modified = true head << "\n{% end#{tag_name} %}" end + print_build_warning if modified end - if tail.empty? - head - else - head.to_s.dup << "\n\n" << tail.scan(MKDWN_LINK_REF_REGEX).join("\n") - end + return head if tail.empty? + + head << "\n\n" << tail.scan(MKDWN_LINK_REF_REGEX).join("\n") end private + def endtag_regex_stash(tag_name) + @endtag_regex_stash ||= {} + @endtag_regex_stash[tag_name] ||= %r!{%-?\s*end#{tag_name}.*?\s*-?%}!m + end + def liquid_block?(tag_name) - Liquid::Template.tags[tag_name].superclass == Liquid::Block + return false unless tag_name.is_a?(String) + return false if tag_name.start_with?("end") + + Liquid::Template.tags[tag_name].ancestors.include?(Liquid::Block) rescue NoMethodError Jekyll.logger.error "Error:", "A Liquid tag in the excerpt of #{doc.relative_path} couldn't be parsed." @@ -169,12 +178,11 @@ def liquid_block?(tag_name) def print_build_warning Jekyll.logger.warn "Warning:", "Excerpt modified in #{doc.relative_path}!" - Jekyll.logger.warn "", - "Found a Liquid block containing separator '#{doc.excerpt_separator}'" \ - " and has been modified with the appropriate closing tag." - Jekyll.logger.warn "", - "Feel free to define a custom excerpt or excerpt_separator in the" \ - " document's Front Matter if the generated excerpt is unsatisfactory." + Jekyll.logger.warn "", "Found a Liquid block containing the excerpt separator" \ + " #{doc.excerpt_separator.inspect}. " + Jekyll.logger.warn "", "The block has been modified with the appropriate closing tag." + Jekyll.logger.warn "", "Feel free to define a custom excerpt or excerpt_separator in the" + Jekyll.logger.warn "", "document's Front Matter if the generated excerpt is unsatisfactory." end end end diff --git a/test/source/_posts/2018-01-28-closed-liquid-block-excerpt.markdown b/test/source/_posts/2018-01-28-closed-liquid-block-excerpt.markdown index 991ebf84e5b..a2c9fe56d5a 100644 --- a/test/source/_posts/2018-01-28-closed-liquid-block-excerpt.markdown +++ b/test/source/_posts/2018-01-28-closed-liquid-block-excerpt.markdown @@ -2,10 +2,23 @@ layout: post --- -{% if - page.layout == "post" %} -You’ll find this post in your `_posts` directory. -To add new posts, simply add a file in the `_posts` directory. -{% endif %} +{% + highlight + ruby +%} +{% assign foo = 'foobar' %} +{% raw +%} +def print_hi(name) + puts "Hi, #{name}" +end +print_hi('Tom') +#=> prints 'Hi, Tom' to STDOUT. +{% + endraw +%} +{% + endhighlight +%} So let's talk business. diff --git a/test/source/_posts/2018-01-28-open-liquid-block-excerpt.markdown b/test/source/_posts/2018-01-28-open-liquid-block-excerpt.markdown index bffe45f0b7b..24c2e0eb04d 100644 --- a/test/source/_posts/2018-01-28-open-liquid-block-excerpt.markdown +++ b/test/source/_posts/2018-01-28-open-liquid-block-excerpt.markdown @@ -2,10 +2,20 @@ layout: post --- -{% if page.layout == "post" %} - You’ll find this post in your `_posts` directory. +{% + highlight + ruby +%} +{% assign foo = 'foobar' %} +{% raw +%} +def print_hi(name) + puts "Hi, #{name}" +end -{% else %} +print_hi('Tom') +#=> prints 'Hi, Tom' to STDOUT. +{% endraw %} +{% endhighlight %} - To add new posts, simply add a file in the `_posts` directory. -{% endif %} +So let's talk business. diff --git a/test/test_excerpt.rb b/test/test_excerpt.rb index 986ef6b4617..d97dbe1b270 100644 --- a/test/test_excerpt.rb +++ b/test/test_excerpt.rb @@ -184,12 +184,17 @@ def do_render(document) @post = setup_post("2018-01-28-open-liquid-block-excerpt.markdown") @excerpt = @post.data["excerpt"] - assert_includes @post.content, "{% if" - refute_includes @post.content.split("\n\n")[0], "{% endif %}" + head = @post.content.split("\n\n")[0] + + assert_includes @post.content, "{%\n highlight\n" + assert_includes @post.content, "{% raw" + refute_includes head, "{% endraw %}" + refute_includes head, "{% endhighlight %}" end should "be appended to as necessary and generated" do - assert_includes @excerpt.content, "{% endif %}" + assert_includes @excerpt.content, "{% endraw %}" + assert_includes @excerpt.content, "{% endhighlight %}" assert_equal true, @excerpt.is_a?(Jekyll::Excerpt) end end @@ -201,13 +206,19 @@ def do_render(document) @post = setup_post("2018-01-28-closed-liquid-block-excerpt.markdown") @excerpt = @post.data["excerpt"] - assert_includes @post.content, "{% if" - assert_includes @post.content.split("\n\n")[0], "{% endif %}" + head = @post.content.split("\n\n")[0] + + assert_includes @post.content, "{%\n highlight\n" + assert_includes @post.content, "{% raw" + assert_includes head, "{%\n endraw\n%}" + assert_includes head, "{%\n endhighlight\n%}" end should "not be appended to but generated as is" do - assert_includes @excerpt.content, "{% endif %}" - refute_includes @excerpt.content, "{% endif %}\n\n{% endif %}" + assert_includes @excerpt.content, "{%\n endraw\n%}" + assert_includes @excerpt.content, "{%\n endhighlight\n%}" + refute_includes @excerpt.content, "{%\n endraw\n%}\n\n{% endraw %}" + refute_includes @excerpt.content, "{%\n endhighlight\n%}\n\n{% endhighlight %}" assert_equal true, @excerpt.is_a?(Jekyll::Excerpt) end end