Jekyll: How to generate new Tags on the fly
My site has many snippets of different languages, and I wanted to tag them for CSS purposes among other possible useful things marking them might make possible. One problem with that is I am still searching out the “correct” labelling, so using mutable tags would be easier to remember as well as change later. Time for a new data file, jekyll-root/_data/langs.json
, with records that look like so:
"pyn": {
"language": "Romanized Chinese-Pin Yin",
"latag": "zh-Latn"
},
which I wanted to call like so:
{% la_pyn pinyin text %}
which would generate:
<span lang="zh-Latn">pinyin text</span>
but how to create a bunch of tags from a data file?
As before, my filter and first tag are actually implemented in the same plugin file.
require 'json' # to access the json data file outside of the scope of the Jekyll module
module Jekyll
######################################################################
# this is where my *filter* code is, removed for clarity
# this is where my cantag *tag* is, removed for clarity
######################################################################
######################################################################
# Language tags
# {% la_chs text to tag %}
######################################################################
class RenderLangTag < Liquid::Tag
def initialize(tag_name, params, tokens)
super
@langkey = tag_name.split("_")[1] # the "@" makes params global in scope (I think)
@textstr = params.strip # strip trailing whitespace
end
def render(context) # render is where the output happens
langdata = context.registers[:site].data["langs"] # the incantation required to access the site data
langrec = langdata[@langkey] # getting to my specific langs.json data record
langtag = langrec['latag']
return "<span lang=\"#{langtag}\">#{@textstr}</span>"
end # render
end # class RenderLangTag
end # Jekyll module
######################################################################
# generate a tag for each language in the code list
######################################################################
langfile = File.read("_data/langs.json") # accessing the json data file outside of the Jekyll module
langdata = JSON.parse(langfile) # parse the contents of the langs.json file
langdata.each_key do |key| # loop through all the records
Liquid::Template.register_tag("la_#{key}", Jekyll::RenderLangTag) # register a *tag* for each one
end
I realize in retrospect that I could have created basically the same functionality with a single “la” tag and parsed the first 3 characters as a language key, but done is done and it’s more fun this way in any case. 8-)