Include jekyll / liquid template data in a YAML variable?

12,922

Solution 1

I don't believe it's possible to nest liquid variables inside YAML. At least, I haven't figure out how to do it.

One approach that will work is to use a Liquid's replace filter. Specifically, define a string that you want to use for the variable replacement (e.g. !SITE_URL!). Then, use the replace filter to switch that to your desired Jekyll variable (e.g. site.url) during the output. Here's a cut down .md file that behaves as expected on my jekyll 0.11 install:

---
layout: post

excerpt: In the [earlier post in this series](!SITE_URL!/2013/01/12/)

---

{{ page.excerpt | replace: '!SITE_URL!', site.url }}

Testing that on my machine, the URL is inserted properly and then translated from markdown into an HTML link as expected. If you have more than one item to replace, you can string multiple replace calls together.

---
layout: post

my_name: Alan W. Smith
multi_replace_test: 'Name: !PAGE_MY_NAME! - Site: [!SITE_URL!](!SITE_URL!)'

---

{{ page.multi_replace_test | replace: '!SITE_URL!', site.url | replace: '!PAGE_MY_NAME!', page.my_name }}

An important note is that you must explicitly set the site.url value. You don't get that for free with Jekyll. You can either set it in your _config.yml file with:

url: http://alanwsmith.com

Or, define it when you call jekyll:

jekyll --url http://alanwsmith.com

Solution 2

Today I ran into a similar problem. As a solution I created the following simple Jekyll filter-plugin which allows to expand nested liquid-templates in (e.g. liquid-variables in the YAML front matter):

module Jekyll
  module LiquifyFilter
    def liquify(input)
      Liquid::Template.parse(input).render(@context)
    end
  end
end

Liquid::Template.register_filter(Jekyll::LiquifyFilter)

Filters can be added to a Jekyll site by placing them in the '_plugins' sub-directory of the site-root dir. The above code can be simply pasted into a yoursite/_plugins/liquify_filter.rb file.

After that a template like...

---
layout: default
first_name: Harry
last_name: Potter
greetings: Greetings {{ page.first_name }} {{ page.last_name }}!
---
{{ page.greetings | liquify }}

... should render some output like "Greetings Harry Potter!". The expansion works also for deeper nested structures - as long as the liquify filter is also specified on the inner liquid output-blocks. Something like {{ site.url }} works of course, too.

Update - looks like this is now available as a Ruby gem: https://github.com/gemfarmer/jekyll-liquify.

Share:
12,922
Gavin Simpson
Author by

Gavin Simpson

I'm an Assistant Professor of Applied Statistics in the Department of Animal Science, at the Aarhus University, Aarhus, Denmark. I undertake research on environmental problems, including climate change and atmospheric pollution, affecting lakes. I use lake sediments to look back in time at the history of lakes to look at what organisms are present and how the species in the lake have changed through time and how lakes evolve and respond to pollution and perturbations. I'm now applying these approaches to problems in Animal Science at the interaction between the environment and human and animal health.

Updated on June 11, 2022

Comments

  • Gavin Simpson
    Gavin Simpson about 2 years

    I am using the YAML heading of a markdown file to add an excerpt variable to blog posts that I can use elsewhere. In one of these excerpts I refer to an earlier blog post via markdown link markup, and I use the liquid template data variable {{ site.url }} in place of the base URL of the site.

    So I have something like (trimmed it somewhat)

    --- 
    title: "Decluttering ordination plots in vegan part 2: orditorp()"
    status: publish
    layout: post
    published: true
    tags: 
    - tag1
    - tag2
    excerpt: In the [earlier post in this series]({{ site.url }}/2013/01/12/
    decluttering-ordination-plots-in-vegan-part-1-ordilabel/ "Decluttering ordination
    plots in vegan part 1: ordilabel()") I looked at the `ordilabel()` function
    ----
    

    However, jekyll and the Maruku md parser don't like this, which makes me suspect that you can't use liquid markup in the YAML header.

    Is it possible to use liquid markup in the YAML header of pages handled by jekyll?

    1. If it is, what I am I doing wrong in the example shown?
    2. If it is not allowed, who else can I achieve what I intended? I am currently developing my site on my laptop and don't want to hard code the base URL as it'll have to change when I am ready to deploy.

    The errors I am getting from Maruku are:

    | Maruku tells you:
    +---------------------------------------------------------------------------
    | Must quote title
    | ---------------------------------------------------------------------------
    |  the [earlier post in this series]({{ site.url }}/2013/01/12/decluttering-o
    | --------------------------------------|-------------------------------------
    |                                       +--- Byte 40
    

    and

    | Maruku tells you:
    +---------------------------------------------------------------------------
    | Unclosed link
    | ---------------------------------------------------------------------------
    | the [earlier post in this series]({{ site.url }}/2013/01/12/decluttering-or
    | --------------------------------------|-------------------------------------
    |                                       +--- Byte 41
    

    and

    | Maruku tells you:
    +---------------------------------------------------------------------------
    | No closing ): I will not create the link for ["earlier post in this series"]
    | ---------------------------------------------------------------------------
    | the [earlier post in this series]({{ site.url }}/2013/01/12/decluttering-or
    | --------------------------------------|-------------------------------------
    |                                       +--- Byte 41
    
  • Gavin Simpson
    Gavin Simpson over 11 years
    +1 Thanks Alan for your thorough and well illustrated answer. (I have site.url set in my _config.yml and should have mentioned that.) I'll wait a tad longer to see if anyone has any other ideas/suggestions, but if not I'll accept this. Cheers.
  • KFunk
    KFunk almost 8 years
    While this is the best answer I've heard so far, it also means that I have to remember to use the liquify filter every time i want to use a variable, and if I forget, I silently get {{ }} in my page, making me want to put it on EVERY variable expansion just in case... :(
  • alxrb
    alxrb over 7 years
    This is perfect, exactly what I was looking for. This plugin should totally be a feature of core jekyll
  • Dan Ancona
    Dan Ancona over 7 years
    Very elegant solution. Thank you!
  • cregox
    cregox over 7 years
    is there any way to use this in github pages?
  • Brian Zelip
    Brian Zelip about 7 years
    @cregox GitHub Pages does not allow building with plugins. There's an info tip in the Jekyll docs on plugins, "GitHub Pages is powered by Jekyll. However, all Pages sites are generated using the --safe option to disable custom plugins for security reasons. Unfortunately, this means your plugins won’t work if you’re deploying to GitHub Pages. You can still use GitHub Pages to publish your site, but you’ll need to convert the site locally and push the generated static files to your GitHub repository instead of the Jekyll source files." source: jekyllrb.com/docs/plugins
  • cregox
    cregox about 7 years
    @BrianZ it does say "custom plugins" so how can we make something like this non-custom or official or whatever? :)
  • Brian Zelip
    Brian Zelip about 7 years
    @cregox "custom plugins" is the same thing as "plugins" -- a resource not available in jekyll core, ie, a resource created externally to jekyll. You'd have to either get the plugin included in jekyll core, or become a GitHub boss to change their policy :). Just use the plugin for local development, then push the static build to your GH repo like the last part of the above quote mentions. Cheers
  • Brian Zelip
    Brian Zelip about 7 years
    @cregox Or use Netlify in conjunction with GitHub, netlify.com.
  • cregox
    cregox about 7 years
    @BrianZ thanks for the netlify hint! I had seen it in the past and even created an account there but for some reason abandoned it in the middle... if anyone else might be interested, they offer a free pro plan for non commercial open source and integrate quite simply with jekyll netlify.com/blog/2015/10/28/… - I'll try to set it up today. :)
  • Ohad Schneider
    Ohad Schneider almost 7 years
    @cregox GitLab is also an option for custom plugins (for an example check out my blog repo: gitlab.com/ohadschn/ohadschn.gitlab.io).