Jekyll: Layouts as a Template
web jekyll layout frontmatter template data
Using a high level Layout as a template that makes use of FronmtMatter metadata of a post for layed out content in the template.
Context
Have been creating a set of lessons for the Grove Beginners Kit for Arduino. Starting point was the 10 lessons as provided for the board using the Arduino IDE, as one document. Idea was to break the lessons into 10 and to use CodeCraft coding instead of the Arduino IDE. That is, to code with the blocky style. Also, intention was to replace instructions as textual steps with an instructional video for each lesson. This way the material could target STEM at a lower age group.
My 8 year-old grandaughter had previosly taken to some STEM actvities with Lego Technics , needing minimal help making various nachines from written text. So I trialed her with the un-templated lessons (using vidoes). She quickly cottoned on to these lessons and soon breezing through them. Feedback was that the technical content was too deep so the intention is for the templated version of the lessons to simplify the discussion content. I also asked if she would like to create her own programs when she finished but she said she just likes playing with the lessons. But she was soon cutting and pasting lessons into lessons!
In creating the lessons, each as a separate blog post, it became clear that each lesson had the same content apart fromother posts’ metadata:
- A one sentence description of the lesson
- An image of the board with components used in the lesson circled.
- A list of the components used
- An image of the code in CodeCraft
- The instructional video
- The intial discussion
- The concluding discussion.
Comment
If a template can be used, the first 5 could be specified in the page’s FrontMatter data. For eample, the images can be specified as an image filename; the video as a Youtube link in the FrontMatter. The last two in the list would be provided as two sets of Markdown content; as one with a defined separator.
Solution
A new Layout was created which has a PostPage layout, the same layout which most blog posts on the site use. So in the first instance, these new posts have he same look and feel of the other posts in the site. This new layout then includes the 7 items as above in a generic manner with the specific details passed as page properties from the post. That is, the first 5 are defined as page FrontMatter data whereas the last two are provided as one to the layout as {
{
content }
}
but with a defined seprator within that can be used to separate the content into two parts. Actually a need arises to separate this content into 3 parts separating the blurb at the start first:
{
% assign contentParts = content | split: excerpt_separator %}
<p>{
{
contentParts[0] }
}
</p>
{
% assign specificContent = contentParts[1]| split: split_separator %}
The Liquid code above extracts the blurb from the first part of the content then splits the rest into first and second parts of the post’s content as the 2 part array contentParts
. This could be simply extended to have more than two parts to page’s specific content. The first part is layed out early in the layout followed by the specified images and a specified video followed by the second part of the content,
Data access
The FrontMatter data for the page is accessed in the layout page as per this example: page.property
where property is defined on the post page such as:
---
property: avalue
---
Global data in a file (eg grove.yml) in _data is accessed, for example, as site.data.someproperty
where someproperty is defined in grove.data as:
someproperty: someothervalue
Defaults
Some defaults (excerpt_separator,split_separator and ) are defined in the layout which are used there if not defined in the post’s FrontMatter, for example:
{
% assign split_separator=page.split_separator %}
{
% if split_separator and split_separator!=’’ %}
{
% else %}
{
% assign split_separator=”<!–more–>” %}
{
% endif %}
Sample FrontMatter for a ‘templated” post
---
componentsThisPage: [0,1,2]
boardImage: theboardlesson1.png
boardImageText: the board lesson 1
summary: For this lesson, the LED periodically flashes
implementImage: lesson1.png
implementText: lesson1
youtubeId: P-yRspOmtqk
expectedOutcome: The LED periodically flashes.
split_separator: <!--split-->
---
Global Data
Global data is defined in yml files in the _data directory. For this layout there are 2 such files:
- grove.yml
- grovecomponents.yml
The first defines global constants specific tothis layout, such as the default directory for its images, The second defines 10 components referenced in the pages, an example of each is:
- name: LED
type: output
interface: Digital
pinsoraddress: D4
When rendering the layout for a specific post, the compnents are loaded as an array and referenced for the page using the indexes from the FrontMatter property componentsThisPage
0,1 and 2 in the FrontMatter example which refere to the LED, Buzzer and OLEDDisplay components. The array can then be used to geneerate a list of components names for the specific post or a table of all components with their properties (with selected items highligyhted). For example the list is rendered in the laout as follows.
<ol>
{
% for comp in site.data.grovecomponents % }
{
% if page.componentsThisPage contains forloop.index %}
<li>Grove {
{
comp.name }
}
</li>
{
% endif %}
</ol>
The 10 components in the global data are those actually hardwired in an Arduino Beginners board. Other devices can be attached and used so some extensibility would be inorder such that additional components could be fully defined in the page FrontMatter. For example the page’s FrontMatter:
grovecomponents:
- name: LED2
type: output
interface: Digital
pinsoraddress: D4
- name: BuzzSaw
type: output
interface: Digital
pinsoraddress: D5
… and in the layout:
<ol>
{
% for comp in site.data.grovecomponents % }
{
% if page.componentsThisPage contains forloop.index %}
<li>Grove {
{
comp.name }
}
</li>
{
% endif %}
{
% endfor %}
{
% for comp in page.grovecomponents %}
<li>Grove {
{
comp.name }
}
</li>
{
% endfor %}
</ol>
The content on the Layout page is not Markdown but is HTML, as I found.
Footnote
In this page there is a need to post some Liquid code literally. Some code even when posted in between tilde triplets is still interpretted as Jekyll code; double braces, bracse followed by a percent. The solution here was to just post it as plain text not as code, but to escape all html characters, and to include braces singly encased in triple tildes . for example:
{
% is entered as ```{```%
and
{
{
is entered as ```{```<space>```{```
Topic | Subtopic | |
Next: > | Blazor Helpers Server App | Version 2 - Club Records |
< Prev: | Grove Beginners kit | Arduino Lesson 2 Press Button |
This Category Links | ||
Category: | Web Sites Index: | Web Sites |
Next: > | Jekyll | Blog Site Updates |
< Prev: | Jekyll | Embed Videos |