user12341234
user12341234

Reputation: 7193

Jekyll Include one YAML file in another YAML file

I have a Jekyll project where two separate pages (A.html and B.html) are displaying different content based on data in YAML files A.yml and B.yml respectively. Each yml file has a bunch of variables that are defined identically. I'd prefer to keep this common list of variables in a third file C.yml and include it into both A.yml and B.yml. How can I do this?

Things I've tried:

Edit - example usage

Using a common data file in multiple views isn't quite sufficient for me because there would also need to be name-resolution logic in liquid to accompany it. Here's an example of what my data might look like:

A.yml

ingredients:
  - avacado: &avacado
      name: Avacado
      color: Green
      foods:
        - *octopus_ceviche

B.yml

chefs:
  - anthony_bourdain: &anthony_bourdain
      name: Anthony Bourdain
      hobby: Brazilian Jiu-Jitsu
      foods:
        - *octopus_ceviche

C.yml

foods:
  - octopus_ceviche: &octopus_ceviche
      name: Octopus Ceviche
      taste: Delicious

If there's no way to include C.yml in A and B, then all the foods need to be shared in both places. If food is used in the md/html page entries need to be accessed by direct hash access (e.g. {{ site.data.foods[octopus_ceviche] }}), which a) doesn't seem to work and b) feels like too much logic for a view.

Upvotes: 1

Views: 2696

Answers (4)

user12341234
user12341234

Reputation: 7193

As the question above is worded, @flyx’s is the most appropriate answer, however given external constraints (see my other question) I ended writing my own plugin to let data files textually include one another through liquid.

The goals of this plugin are to let the data be:

  1. DRY - (don’t repeat yourself) each model should be defined only once.
  2. Grouped - all similar data should be defined in the same format next to each other.
  3. Separated - different data should be defined in different places.

@flyx’s solutions here fail goals #2 and #3, requiring all different types of data to be defined in the same place, and in the case of the second suggestion intermixing the definitions of foods and ingredients.

My proposed solution allows textual inclusion of one data file into another. This allows different models to be defined in different files, yet referenced from other files as if they were defined in the same place, in an arbitrary order. Applied to this problem, my solution would like this:

A.yml

{% include_relative_once C.yml %}

 ingredients:
  - avacado: &avacado
      name: Avacado
      color: Green
      foods:
        - *octopus_ceviche

B.yml

{% include_relative_once C.yml %}

chefs:
  - anthony_bourdain: &anthony_bourdain
      name: Anthony Bourdain
      hobby: Brazilian Jiu-Jitsu
      foods:
        - *octopus_ceviche

C.yml

foods:
  - octopus_ceviche: &octopus_ceviche
      name: Octopus Ceviche
      taste: Delicious

For the plugin itself, see this gist

Upvotes: 1

flyx
flyx

Reputation: 39638

New answer based on the edited question:

*octupus_ceviche is a YAML alias and has nothing to do with Liquid. As I said, YAML files are not processed with Liquid. YAML, however, defines that aliases must point to achors in the same document. One YAML document must reside in one stream which for most YAML processors means that it cannot be split into multiple files.

That being said, a valid option would be to place all data into a single YAML file:

C:
  foods:
    - octopus_ceviche: &octopus_ceviche
        name: Octopus Ceviche
        taste: Delicious
A:
  ingredients:
    - avacado: &avacado
        name: Avacado
        color: Green
        foods:
          - *octopus_ceviche
B:
  chefs:
    - anthony_bourdain: &anthony_bourdain
        name: Anthony Bourdain
        hobby: Brazilian Jiu-Jitsu
        foods:
          - *octopus_ceviche

You may leave out A, B and C if their child keys are disjoint as they are in this example. Note however that the anchor must always be located in front of the alias (textually), even though YAML defines that mapping keys have no order. That's why I moved C in front.

Nota Bene: Anchors and aliases in YAML have been designed to serialize cyclic structures. Using them as named, reusable values is generally fine. But actually, you do not need a list with all defined “variables”, you can also just define them on first occurrence. Example:

A:
  ingredients:
    - avocado: &avocado
        name: Avocado
        color: Green
        foods:
          - &octopus_ceviche
            name: Octopus Ceviche
            taste: Delicious
B:
  chefs:
    - anthony_bourdain: &anthony_bourdain
        name: Anthony Bourdain
        hobby: Brazilian Jiu-Jitsu
        foods:
          - *octopus_ceviche

But this can be less readable of course. ymmv.

Upvotes: 2

marcanuy
marcanuy

Reputation: 23942

To have a common list of key-value variables define a third data file _data/common.yml.

Then in A.html and B.html you can access all the common.yml variables with:

 {{ site.data.common.myvar }}

Upvotes: 3

flyx
flyx

Reputation: 39638

Since Jekyll does not process data files with Liquid when it loads them, it is not possible to include one YAML file in another with {% include %}. YAML itself does not have the ability to include other files (because it is stream-based, not file-based).

However, it should not be necessary. If you move all common variables to C.yml, you can just access them via {{ site.data.C.myvar }} in both your HTML files and do not need to include anything in A.yml or B.yml.

Upvotes: 1

Related Questions