Find the right Liquid filter for your Jekyll data
Tags: jekyll, liquid, webdev, codenewbie
Published: 2020-11-18 10:16:01

Liquid filters are great for manipulating data. Finding the one you need in the documentation is another matter.

A few weeks ago I decided to use Jekyll to quickly build a prototype. On one of the pages I needed to combine data from two JSON files to create a hierarchical list. That's where it got tricky. I needed array manipulation filters but I spent more time looking for them in the documentations than actually implementing the feature.

Most filters are specific to a particular type of data: array, string, number, date. However this is not how the [Liquid documentation](https://shopify.github.io/liquid/) or the [Jekyll Filter page](https://jekyllrb.com/docs/liquid/filters/) are structured. Instead filters are listed alphabetically (Liquid) or in some arbitrary order (Jekyll). In order to see what type of data they work on, you have to go through every single item in each list, and, in the case of Liquid, click on each one.

If only they could be listed by type of input...

## Contents
- [Introduction](#introduction)
- [Array Filters](#array-filters)
- [String Filters](#string-filters)
- [Number Filters](#number-filters)
- [Date Filters](#date-filters)
- [Weakly Typed Filters](#weakly-typed-filters)
- [Side Note: Jekyll Tags](#jekyll-tags)
- [Conclusion](#conclusion)

## Introduction
### Liquid filters: an overview
In Jekyll, posts and layouts are written in the Liquid template language. Liquid is characterised by three types of elements:
- data, called `objects`
- control flow structures, called `tags`
- data transformation functions, called `filters`

This post focuses on filters.

When using Liquid in the context of Jekyll, you have access to Jekyll's custom filters in addition to the standard filters that come with Liquid.

If your needs are too specific, you can add new filters through library plugins or you can write your own in Ruby. This, however, is out of the scope of this article.

### About this post
This post is based on the documentations for Jekyll `4.1.1` and Liquid `4.0.3`.

All filters link to the relevant documentation, where you can find a full description of the filter with examples.

## Array Filters

![](https://dev-to-uploads.s3.amazonaws.com/i/gyulbykpo14i4gkxod36.png)

### Liquid Array Filters
* [`compact`]: remove nil values from array
* [`concat`]: concatenates another array
* [`first`]: returns the first item
* [`join`]: converts array into a string with given separator
* [`last`]: returns the last item
* [`map`]: extracts the values for a given item property into a new array
* [`reverse`]: reverse the order of the items
* [`size`]: number of items
* [`sort`][sort-liq]: case sensitive, can sort on item property
* [`sort_natural`]: case insensitive version of [`sort`][sort-liq]
* [`uniq`]: remove duplicate elements
* [`where`][where-liq]: filter an array of objects

### Jekyll Array Filters
#### Array Queries
* [`where`]: same as standard [`where`][where-liq]
* [`where_exp`]: combine conditionals to filter an array
* [`find`]: get the first item matching the condition
* [`find_exp`]: [`find`] with combined conditionals
* [`group_by`]: group an array's items by a given property
* [`group_by_exp`]: [`group_by`] with combined conditionals

Note that [`find`] and [`find_exp`] seem to have a bug. I don't know why but in my case they returned the whole array. Combining [`where`] with [`first`] instead of using [`find`] works well.

#### Array Manipulation
Those filters work on a copy of the input array.

- [`push`](https://jekyllrb.com/docs/liquid/filters/#array-filters): adds an item at the end of the array
- [`pop`](https://jekyllrb.com/docs/liquid/filters/#array-filters): returns the first element of the array
- [`shift`](https://jekyllrb.com/docs/liquid/filters/#array-filters): returns the last element of the array
- [`unshift`](https://jekyllrb.com/docs/liquid/filters/#array-filters): adds an item at the beginning of the array

#### Other Array Filters
- [`array_to_sentence_string`]: converts array into a string, alternative output format to [`join`]
- [`sample`]: pick one or more random values from an array
- [`sort`]: like standard [`sort`][sort-liq], with additional argument for whether to place nils first or last
- See also [`jsonify`] and [`inspect`] in [Jekyll Weakly Typed Filters](#jekyll-weakly-typed-filters) below.

## String Filters

![](https://dev-to-uploads.s3.amazonaws.com/i/nvyoek0966nr8yq03mkz.png)

### Liquid String Filters
* [`append`](https://shopify.github.io/liquid/filters/append/)
* [`capitalize`](https://shopify.github.io/liquid/filters/capitalize/)
* [`downcase`](https://shopify.github.io/liquid/filters/downcase/)
* [`escape`](https://shopify.github.io/liquid/filters/escape/)
* [`escape_once`](https://shopify.github.io/liquid/filters/escape_once/)
* [`lstrip`](https://shopify.github.io/liquid/filters/lstrip/)
* [`newline_to_br`](https://shopify.github.io/liquid/filters/newline_to_br/)
* [`prepend`](https://shopify.github.io/liquid/filters/prepend/)
* [`remove`](https://shopify.github.io/liquid/filters/remove/)
* [`remove_first`](https://shopify.github.io/liquid/filters/remove_first/)
* [`replace`](https://shopify.github.io/liquid/filters/replace/)
* [`replace_first`](https://shopify.github.io/liquid/filters/replace_first/)
* [`rstrip`](https://shopify.github.io/liquid/filters/rstrip/)
* [`size`]
* [`slice`](https://shopify.github.io/liquid/filters/slice/)
* [`split`](https://shopify.github.io/liquid/filters/split/): convert to an array
* [`strip`](https://shopify.github.io/liquid/filters/strip/)
* [`strip_html`](https://shopify.github.io/liquid/filters/strip_html/)
* [`strip_newlines`](https://shopify.github.io/liquid/filters/strip_newlines/)
* [`truncate`](https://shopify.github.io/liquid/filters/truncate/)
* [`truncatewords`](https://shopify.github.io/liquid/filters/truncatewords/)
* [`upcase`](https://shopify.github.io/liquid/filters/upcase/)
* [`url_decode`](https://shopify.github.io/liquid/filters/url_decode/)
* [`url_encode`](https://shopify.github.io/liquid/filters/url_encode/)

### Jekyll String Filters
#### Path
- [`absolute_url`](https://jekyllrb.com/docs/liquid/filters/#absolute-url)
- [`relative_url`](https://jekyllrb.com/docs/liquid/filters/#relative-url)

#### Escaping
- [`cgi_escape`](https://jekyllrb.com/docs/liquid/filters/#cgi-escape)
- [`uri_escape`](https://jekyllrb.com/docs/liquid/filters/#uri-escape)
- [`xml_escape`](https://jekyllrb.com/docs/liquid/filters/#xml-escape)

#### Other String Filters
- [`markdownify`](https://jekyllrb.com/docs/liquid/filters/#markdownify): convert markdown to HTML
- [`normalize_whitespace`](https://jekyllrb.com/docs/liquid/filters/#normalize-whitespace)
- [`number_of_words`](https://jekyllrb.com/docs/liquid/filters/#number-of-words)
- [`sassify`](https://jekyllrb.com/docs/liquid/filters/#converting-sass-scss)
- [`slugify`](https://jekyllrb.com/docs/liquid/filters/#slugify)
- [`smartify`](https://jekyllrb.com/docs/liquid/filters/#smartify): convert `""` to smart quotes `“”`
- See also [`to_integer`] and [`inspect`] in [Jekyll Weakly Typed Filters](#jekyll-weakly-typed-filters) below.

## Number Filters

![](https://dev-to-uploads.s3.amazonaws.com/i/t9kp1nmifwu85i4eeq6o.png)

### Liquid Number Filters
* [`abs`](https://shopify.github.io/liquid/filters/abs/)
* [`at_least`](https://shopify.github.io/liquid/filters/at_least/)
* [`at_most`](https://shopify.github.io/liquid/filters/at_most/)
* [`ceil`](https://shopify.github.io/liquid/filters/ceil/): tries to convert input to number first
* [`divided_by`](https://shopify.github.io/liquid/filters/divided_by/)
* [`floor`](https://shopify.github.io/liquid/filters/floor/)
* [`minus`](https://shopify.github.io/liquid/filters/minus/)
* [`modulo`](https://shopify.github.io/liquid/filters/modulo/)
* [`plus`](https://shopify.github.io/liquid/filters/plus/)
* [`round`](https://shopify.github.io/liquid/filters/round/)
* [`times`](https://shopify.github.io/liquid/filters/times/)

### Jekyll Number Filters
There are no number-specific Jekyll filters.

## Date Filters

![](https://dev-to-uploads.s3.amazonaws.com/i/190lnutaui9qlhpap8ng.png)

Those filters format a date for output and return a string. Strictly speaking there is no date type in Liquid. The input to those filters is normally a timestamp.

### Liquid Date Filters
* [`date`]: convert date (timestamp or string) to string

### Jekyll Date Filters
- [`date_to_xmlschema`](https://jekyllrb.com/docs/liquid/filters/#date-to-xml-schema)
- [`date_to_rfc822`](https://jekyllrb.com/docs/liquid/filters/#date-to-rfc-822-format)
- [`date_to_string`](https://jekyllrb.com/docs/liquid/filters/#date-to-string)
- [`date_to_long_string`](https://jekyllrb.com/docs/liquid/filters/#date-to-long-string)

## Weakly Typed Filters

![](https://dev-to-uploads.s3.amazonaws.com/i/5gdps0huead2jocf4siq.png)

Those filters accept more than one type of data as input.

### Liquid Weakly Typed Filters
* [`default`]: output a default value if the input is nil, false or empty

### Jekyll Weakly Typed Filters
- [`jsonify`]: convert a hash or array to a JSON string
- [`to_integer`]: convert a string or boolean to an integer
- [`inspect`]: convert any object to a string

[`compact`]: https://shopify.github.io/liquid/filters/compact/
[`concat`]: https://shopify.github.io/liquid/filters/concat/
[`first`]: https://shopify.github.io/liquid/filters/first/
[`join`]: https://shopify.github.io/liquid/filters/join/
[`last`]: https://shopify.github.io/liquid/filters/last/
[`map`]: https://shopify.github.io/liquid/filters/map/
[`reverse`]: https://shopify.github.io/liquid/filters/reverse/
[`size`]: https://shopify.github.io/liquid/filters/size/
[`sort_natural`]: https://shopify.github.io/liquid/filters/sort_natural/
[`uniq`]: https://shopify.github.io/liquid/filters/uniq/

[sort-liq]: https://shopify.github.io/liquid/filters/sort/
[where-liq]: https://shopify.github.io/liquid/filters/where/

[`date`]: https://shopify.github.io/liquid/filters/date/
[`default`]: https://shopify.github.io/liquid/filters/default/

[`where`]: https://jekyllrb.com/docs/liquid/filters/#where
[`where_exp`]: https://jekyllrb.com/docs/liquid/filters/#where-expression
[`find`]: https://jekyllrb.com/docs/liquid/filters/#find
[`find_exp`]: https://jekyllrb.com/docs/liquid/filters/#find-expression
[`group_by`]: https://jekyllrb.com/docs/liquid/filters/#group-by
[`group_by_exp`]: https://jekyllrb.com/docs/liquid/filters/#group-by-expression

[`sort`]: https://jekyllrb.com/docs/liquid/filters/#sort
[`sample`]: https://jekyllrb.com/docs/liquid/filters/#sample
[`array_to_sentence_string`]: https://jekyllrb.com/docs/liquid/filters/#array-to-sentence

[`jsonify`]: https://jekyllrb.com/docs/liquid/filters/#data-to-json
[`to_integer`]: https://jekyllrb.com/docs/liquid/filters/#to-integer
[`inspect`]: https://jekyllrb.com/docs/liquid/filters/#inspect


## Side Note: Jekyll Tags <a name="jekyll-tags"></a>

![](https://dev-to-uploads.s3.amazonaws.com/i/6swl9pmdqma9azpm8txp.png)

In addition to filters, Jekyll also provides [a few tags](https://jekyllrb.com/docs/liquid/tags/) which might come in handy. They are also listed here for easy reference:
* [`highlight`](https://jekyllrb.com/docs/liquid/tags/#code-snippet-highlighting): syntax highlighting with Rouge
* [`include`](https://jekyllrb.com/docs/includes/): include partial from the `_includes` folder
* [`include_relative`](https://jekyllrb.com/docs/includes/#including-files-relative-to-another-file): include partial located with the current file (in the same directory or one of its subdirectories)
* [`link`]: creates and validates site permalink url (build fails if url is wrong)
* [`post_url`](https://jekyllrb.com/docs/liquid/tags/#linking-to-posts): same as [`link`] but specific to posts so you don’t need to give the full path from the root

[`link`]: https://jekyllrb.com/docs/liquid/tags/#link

## Conclusion
It wasn't too hard to implement my feature after finding the relevant filters. It's the search that was time-consuming!

I hope this post helps you find what you need fast. Happy coding!

---

***This is my first blog post!*** I'd love some feedback. Please let me know what you think in the comments.

<small><span>Photo by <a href="https://unsplash.com/@yogidan2012?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Daniele Levis Pelusi</a> on <a href="https://unsplash.com/s/photos/directions?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></span></small>