11ty / eleventy

A simpler site generator. Transforms a directory of templates (of varying types) into HTML.
https://www.11ty.dev/
MIT License
17.27k stars 495 forks source link

Trouble with using custom filter for pagination of tags #684

Closed anyuzx closed 4 years ago

anyuzx commented 5 years ago

Describe the bug I am having a problem using a custom markdown filter with pagination. I have a custom filter defined in .eleventy.js which is a markdown-it renderer. In .eleventy.js, I have something like the following,

// .eleventy.js
const markdownIt = require("markdown-it");

const mdRender = new markdownIt({});

module.exports = function(config) {
        ...
    config.addFilter("renderUsingMarkdown", function(rawString) {
        return mdRender.render(rawString);
    })
    ...
}

I want to use this filter within the pagination of collections. Following the tutorial and sample code, I have the following codes,

// tags.njk this is the template page
---
pagination:
  data: collections
  size: 1
  alias: tag
  filter:
    - all
    - posts
  addAllPagesToCollections: true
permalink: /tags/{{ tag | slug }}/
title: Tags
layout: layouts/tags.njk
description: "Posts tags"
---

and

// tags.njk this is the layout lives inside _includes/layouts/

{% set tagPosts = collections[ tag ] %}

...
<div>
    {% for post in tagPosts | reverse %}
        {{ post.data.excerpt | renderUsingMarkdown | safe }}
    {% endfor %}
</div>
...

This generate error Error: Input data should be a String, which is from markdown-it. It seems that post.data.excerpt is evaluated as Object and markdown-it couldn't render it. However, if I don't pass the filter renderUsingMarkdown, post.data.excerpt can be correctly rendered. It seems all built-in nunjucks filter works except the custom defined filter.

I found that the problem seems to be that tagPosts is defined using the bracket syntax instead of dot syntax, tagPosts = collection[ tag ]. This produces the same error

{% set myTestObj = {key: "value"} %}
{% set myTestValue = myTestObj[ key ] %} // use bracket syntax
...
<div>
    {{ myTestValue | renderUsingMarkdown | safe }}
</div>
...

But the following works,

{% set myTestObj = {key: "value"} %}
{% set myTestValue = myTestObj.key %} // use dot syntax instead

...
<div>
    {{ myTestValue | renderUsingMarkdown | safe }}
</div>
...

Maybe this issue https://github.com/11ty/eleventy/issues/567 and this one https://github.com/11ty/eleventy/issues/680 are related here? But I couldn't figure out how to solve it.

philiprenich commented 5 years ago

I'm going to be doing the same thing - parsing my excerpt as markdown. I had a similar issue. The problem was that not all of my tagged posts had an excerpt field. This meant that when I called {{ post.data.page.excerpt }} it would return undefined for the posts with no excerpt. Either the template or the filter needs an if statement catch.

Try this

    {% for post in tagPosts | reverse %}
        {% if post.data.excerpt %}
            {{ post.data.excerpt | renderUsingMarkdown | safe }}
        {% else %}
            {{ post.data.templateContent }}
        {% endif %}
    {% endfor %}

You could do a check for undefined in the filter, but that won't give you a fallback string to render. Probably still a good idea so things don't blow up. (though maybe that's a good warning that the post doesn't have an excerpt!)

anyuzx commented 4 years ago

#

I'm going to be doing the same thing - parsing my excerpt as markdown. I had a similar issue. The problem was that not all of my tagged posts had an excerpt field. This meant that when I called {{ post.data.page.excerpt }} it would return undefined for the posts with no excerpt. Either the template or the filter needs an if statement catch.

Try this

  {% for post in tagPosts | reverse %}
      {% if post.data.excerpt %}
          {{ post.data.excerpt | renderUsingMarkdown | safe }}
      {% else %}
          {{ post.data.templateContent }}
      {% endif %}
  {% endfor %}

You could do a check for undefined in the filter, but that won't give you a fallback string to render. Probably still a good idea so things don't blow up. (though maybe that's a good warning that the post doesn't have an excerpt!)

In my case, I actually have all excerpt defined in the front-matter so it is not this issue. The weird thing is that I have no problem using custom markdown-it render to render excerpt in layout or normal template. Only have this issue when using pagination.

The issue still preserves in version 0.11.0

anyuzx commented 4 years ago

Using the built-in log filter, I found out that the reason is just that I didn't filter all the tags needed to be filtered.