Get a hash into a Jekyll Liquid template from a Plugin for use in the FOR loop?

jekyll, liquid, ruby, yaml

Solution

Here's the solution that I came up:

A Jekyll Plugin that create's a Liquid Tag: `yaml_to_liquid`. This plugin parses the yaml file into a hash and then adds it to the Jekyll `page` variable.

module Jekyll

  class YamlToLiquid < Liquid::Tag
    def initialize(tag_name, arg, tokens)
      super

      if arg.length == 0
        raise 'Please enter a yaml file path'
      else
        @yml_path = arg
      end
    end

    def render(context)

      yml = YAML::load(File.read(@yml_path))
      context.registers[:page]['yml'] = yml
    end
  end
end

Liquid::Template.register_tag('yaml_to_liquid', Jekyll::YamlToLiquid)

To use it. Place the tag at the top of your `.html` or `.md` page just below the Yaml Front Matter and then access the `yml` variable as usual. This loop will only output the `code` hash (allows you to access the whole hash or just sub-hashes):

---
layout: page
---
{% yaml_to_liquid work/_projects.yml %}

<ul>
  {% for n in page.yml.projects.code %}
    <li>
    <a href="{{ n.url }}">{{ n.title }}</a>
    </li>
  {% endfor %}
</ul>

Example of `work/_projects.yml`:

projects:

  code:
    - title:
      url:

    - title:
      url:

  websites:
    - title:
      url:

    - title:
      url:

Problem

This one's got me stumped... I'd like to share a YAML hash from a single file among a few other Jekyll pages. I know you can put it in the Front Matter (which would require duplicating it), and I know you can generate (write) pages via a plugin (but I'm using it in a few different types of pages, which would be complex). Neither is what I'm looking for. I'd like to loop over the hash with Liquid in my pages, but I can't seem to get the hash from the plugin to Liquid. `{% capture %}` only works with strings and `{% assign %}` won't let you call a tag within itself, like `{% assign projects = gethash %}` where `gethash` is a custom Liquid tag. Basically, I'd like to use the separate YAML file like a text-based database. YAML File has this in it: ``` projects: category1: - title: Project 1 desc: Description etc... - title: Project 2 etc... category2: - title: Project 3 desc: Description etc... - title: Project 4 etc... ``` Plugin is calling (which gives a Ruby Hash of the YAML): ``` def... YAML::load(File.read('projects.yml')) end... ``` And in template, I want to: ``` {% for p in projects %} ... ``` This should be really simple, but it's one of those Liquid things that is a pain. How can you get a hash into Liquid from a plugin for use in the `{% for %}` loop?

Original source