Reputation: 7193
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:
*site.data.C.vars
- this didn't parse.{% include C.yml %}
- this compiled, but the emitted html page had no content whatsoever.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
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:
@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
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
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
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