cri.dev about posts rss

Exclude specific tags in Eleventy using a custom filter

Published on
Tagged with eleventy3

Let’s say you have an eleventy blog, and want to show the tags related to a given blog post.

E.g. this post is tagged with eleventy as you can see above.

But, it has also other tags attached, e.g. post and featured for example, that are mainly used for creating the posts and featured collections.

The HTML/nunjucks code for showing the taglist on this very site is the following:


<div class="taglist">
  Tagged with 
  {% for tag in tags | exclude("post") | exclude("featured") | limit(3) %}
    <a aria-hidden href="/tags/{{ tag }}/" data-track="click-post-tag">{{ tag }}<sup>{{collections.tagList | findTagCount(tag)}}</sup></a>
  {% endfor %}
</div>

There are a few things going on here:

  • the post exposes its tags property, that’s straightforward
  • the filter exclude comes up twice, it’s chainable
  • the filter limit does exactly what you think
  • the link to the specific tag is /tags/, so there is a dedicated page for each tag
  • the collection tagList comes into play, together with the filter findTagCount

Let’s break it down and go into each step and needed code

The exclude filter

You can simply add the next few filters and collections to your eleventy config file.

The exclude filter takes an array (namely the tags array as a list of tags/string) and excludes the first parameter passed to the filter

eleventyConfig.addFilter("exclude", (arr, exclude) => arr.filter(el => el !== exclude))

The limit filter

Nothing fancy, limits a given array to a specified number of items:

eleventyConfig.addFilter("limit", (arr, limit) => arr.slice(0, limit))

The tagList collection and findTagCount filter

The tagList collection goes over all blog posts, reduces them to an array of objects in the form {tag, count}:

eleventyConfig.addCollection("tagList", collections => {
  const tags = collections
    .getAll()
    .reduce((tags, item) => tags.concat(item.data.tags), [])
    .filter(tag => !!tag && !["post", "featured", "popular", "opinion", "all"].includes(tag))
    .sort()
  return Array.from(new Set(tags)).map(tag => ({
    tag,
    count: collections.getFilteredByTag(tag).length,
  }))
})

The findTagCount filter takes the above tagList and finds the number of occurrencies across all blog posts:

eleventyConfig.addFilter("findTagCount", (tagList, findTag) => tagList.find(({tag}) => tag === findTag)?.count)

Here, have a slice of pizza 🍕