Creating Blog Statistic/Summary Pages with Jekyll - II
Building on the list of brews by style page I built for the brewlog, I also wanted a page to summarize all of the ingredients I’ve used, with total weights.
Not just fun trivia, but this is actually useful. It could help me understand which speciality grains would be worth buying in bulk, since I’d use them enough to justify it.
Unfortunately, this isn’t quite as easy as the styles page. In addition to creating a list of ingredients, I also need to tally up the total amount for each. And, unlike the styles, each recipe has lists of ingredients so some nested loops are needed.
This is a bit more than what can be done in markdown and Liquid.
Jekyll Plugins
A custom plugin can be included in a Jekyll site by placing it in the _plugins directory. My plugin is a simple Ruby script: ingredients.rb. No other changes are needed to load the file, when Jekyll generates the site, it will automatically find the file and load it as a plugin.
A Ruby Plugin
The structure of a Jekyll plugin written in Ruby is simple. I want to add a couple of filters that can be used in markdown with Liquid:
I decided the easiest approach was to break the task apart into a few steps:
- Get a list of ingredients across all recipes
- Get a total weight for a given ingredient
- Parse weight strings from the formatted value in the recipe
- Format a raw weight back to a nice formatted string
Ingredients List
First, generating a list of all ingredients. I actually split everything between ‘grains’ (mash) and ‘boil.’ Not only is that a logical split (between grain and hops), but the recipe definied in the front matter of each posts defines them the same way; two lists.
So, this is the filter that returns a table of grain names and corresponding total amounts. It takes a list of posts as an argument:
In my new page, ingredients.markdown, I use this like a normal filter:
Creating a list in markdown is now super simple:
The table can be accessed like an array, the ingredient name ends up in index ‘0’ and the amount in ‘1.’
Parsing and Formatting Weight Strings
The grain_weights
filter uses another function, parse_weight
to convert the string defined in the recipe to an actual number. This is done with a few simple regular expressions:
Then a simple filter to format the totals back when displaying them: