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.