[solved] Include file outputting local (.md) front matter values

As detailed in another thread about project, collaboration, and tree architecture, I have a primary content type — a glossary term definition.

One of my objectives for front matter in that project is to serialize out certain data values from HTML so collaborators (e.g. copywriters) who are not comfortable in lots of markup can more easily work with the content. Content that needs marked up in ways Markdown fails to do.

But, I’m not skilled with Jekyll and Liquid enough to figure out what I’m trying to do.

One example is dealing with authors & affiliations.

# Relevant, default front matter in term.md
---
collaborators:
  - 
    who: "First Last"
    affiliation: "Entity Name"
    affiliation_url: "URL"
...

Contributing authors add their own front matter values. The first contributor (usually the person starting the initial file from an available template) simply changes the default values for their own details. The next contributor would copy the four lines and creating a second array:

# Author data for 2 contributors on term.md
collaborators:
  - 
    who: "Jackie Jones"
    affiliation: "JJ Enterprises"
    affiliation_url: "URL"
  - 
    who: "Pat Stewart"
    affiliation: "Pat Stewart Media"
    affiliation_url: "URL"
...

Btw, I’m not sure if that front matter is correct, or if it should look like this:

# Author data for 2 contributors on term.md
collaborators:
  - who: "First Last"
    affiliation: "Entity Name"
    affiliation_url: "URL"
  - who: "First Last"
    affiliation: "Entity Name"
    affiliation_url: "URL"
...

But when I ran it through YAML Lint validator, it corrected it to the former.


Anyway, the associated markup is kept in an include file instead of the term.md file, primarily to help keep the .md files a little more streamlined; I just want writers focusing on paragraphs, and not even seeing the tedious markup blocks):

<!-- Associated markup in /_includes/authors.html -->

<section>
  <ul>
    <li><<???>><sup><<???>></sup></li>
  </ul>
  <ol>
    <li><sup><<???>></sup><a href="<<???>>"><<???>></a></li>
  </ol>
</section>

The regions marked as <<???>> are part of the Liquid I need to figure out…

  • For each new contributor’s added to the front matter in a term.md file, a new author/affiliation pair of list items should be returned in the include output:
    • The author list (ul) needs to get the who key value in each li.
    • the affiliation list (ol) needs to get the affiliation and affiliation_url key values in each li.
  • The two instances of <sup><<???>></sup> need to be filled with a numeral beginning with 1, and increasing sequentially with each additional li added to list.

And, of course, this markup is inserted in term.md via a Liquid include tag, for which the structure needed I’m not entirely certain, indicated by parameter=var_name:

<!-- Liquid include tag in term.md -->
{% include authors.html parameter=var_name %}

The problem is I don’t know how to add the necessary Liquid in authors.html, and pass that data to the include tag in the term.md file.

Because there are arrays in the front matter, I’m expecting some kind of loop needs used in the include markup:

<section>
{% for <<something>> in <<something_else>> %}
...
{% endfor %}
</section>

And I think each instance of sup can be handled like this, where for each iteration through the array, the second assign tag takes the previous value of {{counter}} and adds 1 to it.

<ul>
    {% assign counter = 1 %}
    <li>... <sup>{{counter}}</sup></li>
    {% assign counter = counter | plus:1 %}

<ol>
    {% assign counter = 1 %}
    <li><sup>{{counter}}</sup> ... </li>
    {% assign counter = counter | plus:1 %}

And the li in each list type needs some kind of iterative processing too, perhaps like this:

...
<ul>
{% for <<this>> in <<that>> %}
<li><<???>>...</sup></li>
{% endfor %}
...
<ol>
{% for <<this>> in <<that>> %}
<li><sup> ... <a href="<<???>>"><<???>></a></li>
{% endfor %}
...

Then altogether looking like this, roughly:

<!-- Hypothetical Liquid in /_includes/authors.html -->

<section>
{% for <<something>> in <<something_else>> %}

  <ul>
   {% for <<this>> in <<that>> %}
      {% assign counter = 1 %}
      <li><<???>><sup>{{counter}}</sup></li>
      {% assign counter = counter | plus:1 %}
   {% endfor %}
  </ul>
  <ol class="affiliations nomark">
   {% for <<this>> in <<that>> %}
      {% assign counter = 1 %}
      <li><sup>{{counter}}</sup> <a href="<<???>>"><<???>></a></li>
      {% assign counter = counter | plus:1 %}
   {% endfor %}
  </ol>

{% endfor %}
</section>

But that’s as much as I’ve been able to guess. I tried plugging different things into the holes, but it was like shooting bats in the dark with a blindfold on.

Can anyone help me with the needed Liquid structure?

You can pass parameters to includes. However, your question here is so long it’s difficult to understand what you’re asking. I recommend using collections instead of a giant yaml file like this.

I’ll try to keep things shorter next time.

This isn’t a long YAML file, actually. I’m just elaborating on the markup that would go in the include file, because I don’t really know how to do it, and I’m showing what my thought process was in trying to figure it out.

I’m not 100% sure what you’re hoping to achieve with the include parameters, but here are some simplified examples that hopefully point you in the right direction as far as the loops are considered.

RE: your collaborator YAML. You can do it either way.

# Author data for 2 contributors on term.md
collaborators:
  - 
    who: "Jackie Jones"
    affiliation: "JJ Enterprises"
    affiliation_url: "URL"
  - 
    who: "Pat Stewart"
    affiliation: "Pat Stewart Media"
    affiliation_url: "URL"

Or

# Author data for 2 contributors on term.md
collaborators:
  - who: "Jackie Jones"
    affiliation: "JJ Enterprises"
    affiliation_url: "URL"
  - who: "Pat Stewart"
    affiliation: "Pat Stewart Media"
    affiliation_url: "URL"

To get the collaborator data on the page you’ll need to loop over it. Since the YAML data is in the page object that is how you’ll access it with something like this:

<section>
  {% if page.collaborators %}
    <ul>
      {% for collaborator in page.collaborators %}
         <li>{{ collaborator.who }}<sup>{{ forloop.index }}</sup></li>
      {% endfor %}
    </ul>
    <ol>
      {% for collaborator in page.collaborators %}
         <li><sup>{{ forloop.index }}</sup><a href="{{ collaborator.affiliation_url }}">{{ collaborator.affiliation }}</a></li>
      {% endfor %}
    </ol>
  {% endif %}

You’ll notice I’m using {{ index }} for the <sup> bits. That variable will output the current index in the loop which will give you the increasing sequence of numbers you want. No need to create your own counter and increment it.


I would suggest sticking all of your collaborator info in a data file instead. It would DRY things up considerable.

# _data/collaborators.yml
jackie_jones:
    who: "Jackie Jones"
    affiliation: "JJ Enterprises"
    affiliation_url: "URL"

pat_stewart:
    who: "Pat Stewart"
    affiliation: "Pat Stewart Media"
    affiliation_url: "URL"

Then in your page YAML you’d access them with collaborators: [jackie_jones, pat_stewart]

The liquid for loop above would need to be slightly modified since you’d want to access site.data.collaborators instead of page.collaborators.

@mmistakes Thank you! That looks like a big step in the right direction. I’ll play around with it.

Some context about collaborators. This is an open, rolling project. Collaborators can come and go at will. I have no idea who might show up and play. If they do contribute, they need to add their own data values to wherever the yaml object exists.

Also, a given collaborator can contribute to any combination of definition files they want, one or several, and it will certainly vary across collaborators. This was why I was putting a collaborators front matter object in each definition file, so it’s easier to see who contributed to what file. I don’t see how you could parse author data otherwise under the many combinations of possibilities if it was in a single file. How would you parse author data to the respective definition files they worked on?

(Btw, apologies if I’m calling things wrong. I don’t really know the yaml nomenclature yet.)

The benefit of using a data file is it centralizes all your collaborators into a single file. Less error prone and avoids duplication in the case where you may be using a collaborator across multiple pages.

You still reference the specific collabs you want to include in front matter, but instead of putting the data there you list the collab keys (see my example above) you want on that page. Which pull the data from _data/collaborators.yml.

Take a look at the data file link above on the Jekyll documentation site. It provides examples.

Thanks, I’ll think about the _data approach.

Meanwhile, your include markup worked (almost) like this:

<section class="contributors">
    <ul class="authors nomark">
      {% for collaborator in page.collaborators %}
         <li>{{ collaborator.who }}<sup>{{ index }}</sup></li>
      {% endfor %}
    </ul>
    <ol class="affiliations nomark">
      {% for collaborator in page.collaborators %}
         <li><sup>{{ index }}</sup><a href="{{ collaborator.affiliation_url }}">{{ collaborator.affiliation }}</a></li>
      {% endfor %}
    </ol>
</section>

Note I left out the wrapping if tags because it didn’t seem needed.

And I called that from the .md file using:

{% include authors.html %}

The only problem is there are no superscripts showing up.

My bad, instead of {{ index }} use {{ forloop.index }}

Adding the counter liquid back in does make it work, however, so I’m fine with that.

Here’s the working markup for those following along (classes removed for clarity):

<section>
    <ul>
      {% for collaborator in page.collaborators %}
	{% assign counter = 1 %}
        <li>{{ collaborator.who }}<sup>{{ counter }}</sup></li>
	{% assign counter = counter | plus:1 %}
      {% endfor %}
    </ul>
    <ol>
      {% for collaborator in page.collaborators %}
	{% assign counter = 1 %}
        <li><sup>{{ counter }}</sup><a href="{{ collaborator.affiliation_url }}">{{ collaborator.affiliation }}</a></li>
	{% assign counter = counter | plus:1 %}
      {% endfor %}
    </ol>
</section>

@mmistakes Thanks for your help.

Ha, you beat to the punch. I’ll try it, it’s cleaner.

Confirmed. Works good.

This helped me figure out the other problem I had with Figures, more or less the same situation, but no looping this time.

In both cases it turned out to be simpler than I was hacking on it. You don’t know how many hours I struggled… Was near ready to go back to straight HTML.

Thanks again!

Okay, I see what you mean now. Yeah, that’s neat. It means collaborators would have to add their data to 2 files (which they’ll probably forget to do so I will be stuck doing it), but it does make a lot of sense in terms of centralization, and and keeping the local front matter tidier.

You can also use https://yamlonline.com/ for the yaml validator as well as yaml converter to json,csv,xml,base64 also for beautify and minify YAML.