jekyll: Excerpt handling in 3.8.5 generates Liquid errors despite valid Liquid syntax

My Environment

Software Version(s)
Operating System Ubuntu 18.04.1 LTS
jekyll 3.8.5
github-pages no

Expected Behaviour

Valid Liquid syntax should not throw errors when excerpted; excerpts should gracefully handle Liquid syntax that is correct in the full page (or at least explain what the issue is). This seems related to the changes in excerpt handling made in 3.8.5 as I do not get errors using jekyll 3.8.4.

Current Behavior

In some cases, valid Liquid syntax results in syntax errors related to the excerpt

Error: A Liquid tag in the excerpt of _test/test.xml couldn't be parsed.
Error: could not read file /tmp/test/_test/test.xml: undefined method `ancestors' for nil:NilClass

Calling jekyll _3.8.4_ build generates no errors. Putting excerpt: none in the front matter also eliminates the error.

Code Sample

This isn’t my use case (my use case is generating an RSS file), but here’s a minimal working example:

Directory tree:

.
├── _config.yml
└── _test
    └── test.xml

_config.yml:

collections:
    test:
        output:     true

_test/test.xml:

---
---

{% if true %}
xyzzy
{% else %}
plugh
{% endif %}

Output:

$ jekyll build
Configuration file: /tmp/test/_config.yml
            Source: /tmp/test
       Destination: /tmp/test/_site
 Incremental build: disabled. Enable with --incremental
      Generating... 
             Error: A Liquid tag in the excerpt of _test/test.xml couldn't be parsed.
             Error: could not read file /tmp/test/_test/test.xml: undefined method `ancestors' for nil:NilClass
                    done in 0.012 seconds.
 Auto-regeneration: disabled. Use --watch to enable.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 15 (11 by maintainers)

Commits related to this issue

Most upvoted comments

What about doing it this way?

def liquid_block?(tag_name)
  return false unless tag_name.is_a?(String)
  return false unless Liquid::Template.tags[tag_name]

  Liquid::Template.tags[tag_name].ancestors.include?(Liquid::Block)

Then excerpt.rb doesn’t have to know anything about blocks or Liquid. We can just ignore everything that isn’t in Liquid::Block. That covers user-created block tags, too, because their class should have class NewTag < Liquid::Block when defined. And neither intermediate nor ending logic gets registered in Liquid::Template.tags. Try:

$ irb
> require 'liquid'
=> true
> Liquid::Template.tags['if']
=> Liquid::If
> Liquid::Template.tags['else']
=> nil
> Liquid::Template.tags['elsif']
=> nil
> Liquid::Template.tags['endif']
=> nil

It also works for break and continue:

> Liquid::Template.tags['break'].ancestors.include?(Liquid::Block)
=> false
> Liquid::Template.tags['continue'].ancestors.include?(Liquid::Block)
=> false

If that sounds like the way to go, let me know — I’ve already created some tests and so I’m ready to make a pull request.

@kylebarbour Thanks for the fix 💪 🔧

@kylebarbour That suggestion looks awesome! 👍 Please go ahead with creating the pull request.

You’re too hard on yourself, I love the software you’ve helped write and this is a minor problem 😃

If you understand where the problem is and can easily fix it, amazing! If not I’ll have some time to look at it in a few days and I’ll take a stab but I might not get there.

I apologize, after looking at it for a while I’m not sure exactly why that happens,

@kylebarbour I should be the one apologizing. I’m the author of the implementation. This particular block of code has been changing over and over since v3.8.0 which means my original implementation was very poor. Since v3.8.5 contains just a single “patch” related to this very feature and that “patch” is troublesome for you, you can freely downgrade to v3.8.4

The reason, this bug arose was because I did not filter out {% else %} in the current implementation…