Jekyll and Layout inheritance and data sharing

In my theme, structRDFaL, I have a default page layout and a sitehome layout which repeats most of what is in the default. This is not DRY and I always felt foolish that sitehome could not inherit most of its processing from default. I had a similar issue when implementing schemas, for instance the Book schema, and I wanted the flexibility to have a book page vs a book blog post. This, as I remember doing but then later deleted for reasons I can't remember from 4 years ago, was accomplished by putting most of the processing into an include file. This felt inelegant and a failure of my ability to understand layouts.

One problem was that the schema differences between webpage-of-a-thing vs webpage-that-is-a-blogposting-of-a-thing extended into the header stuff, so default being a complete page layout that would be used as the (duh) default layout for other pages caused issues similar to the ones that I was having with sitehome.

I could solve some of my problems if I could process some data and then pass a new page title or similar down to default. An answer from Jekyll Talk or Stack Overflow that I can no longer find said variables defined in one layout could be accessed by another depending on order of inheritance. That was a lie. Variables (eg. {% assign myvariable = "something" %}) are not shared between layouts or even the page itself. Order does not matter. Custom variables (eg. {{ page.title}}) cannot be assigned to outside of the front matter. Further, front matter cannot handle liquid variables

---
title: My Name - {{ site.tag }}
---
This will not work.
A smattering of plugins have been created to fix this lack, but I don't know what works with the current version of Jekyll and it seems that the powers that be have no interest in ever adding liquid interpolation into front matter processing.

So, if you want to code in chunks in order to reuse bits and pieces and you want to use variables that change (and not just static variables you can insert into front matter) then the only answer is includes. Include files are just merged into the text of the layout don't need to "share" data. The main annoyance for me is that Liquid logic and flow control is so verbose. It feels like if you were allowed to have data cascade through your inherited layouts it would not feel so much like amateur hour kludging.

For a less emotional illustration of the issue, imagine that you have 4 types of pages that require processing of the <header> in general plus the title <h1> differently, say, sitehome, bloghome, blog page, and standard page. Footer, nav, and general page layout is the same which is put into a default layout. Obviously, you would need to code some switches into your default for the special cases but 4 is manageable. Then you start adding new types like, say, gallery home and gallery page, catalog home and catalog page, forum home and forum page. Databases or data files are involved so you can't just pass known text to the layout. The code explodes into a massive blob of if-then-else special cases. Wouldn't it be nice if, instead, you could designate pages with a gallery page layout, access the database, do some processing and pass the title plus custom breadcrumbs to default? Maybe gallery page and catalog page share some logic but access different databases so both gallery and catalog could share a framed layout which eventually slots into default. If only processed variables could be passed between layouts.

The problem here is most intractable if default is inviolable. If, say, you are using a theme that you don't want to re-clone or re-merge your customizations with each new release.

In any case, this is not to say that layout inheritance doesn't work or that it is useless. It was, however, a little counter-intuitive when I was trying to map it all out for my own mental model and using non-standard fragments. Let's say all your layouts are like this (except for default not having a further layout):

---
layout: default
---
1<br>
{{ content }}
1<br>
Then you get
(default)
1
"page content"
1
(default)
Which is not how my mind's eye expects [stuff] {{ content }} [stuff] to end up. Part of it is no doubt due to thinking of the layouts as envelopes, so then you don't expect the basic/core envelope to be the outermost.

Another confusing factor is that I was using fragments (as previously mentioned) to test out ideas of having header pieces in a layout that would then be completed in the basic/default layout but Jekyll was oh-so helpfully adding a basic html page's skeleton because my default layout didn't have anything of the sort. Frustrating and boggling when I wasn't expecting it. Further experimentation has shown, though, that if I at least put the <html><body></body></html> in myself, I can have layouts with wacky incomplete page fragments.

Now that I know exactly what my parameters are, I can decide for myself if I want to use the tools as intended or if shenanigans and tomfoolery will rule the day.

Post a New Comment






?

Note: for security reasons, a mailto link is being used. If configured on your end, this is the safest way for both parties. This activates your mailer to send the data entered. See here or here for why that might not work and what to do about it.