Passing Jekyll variables "up" scope - jekyll

I am trying to set a Jekyll (Liquid) variable in my content page, and exposing that variable and its content in the including Jekyll template. In this use case, I want to author the main page content, and side-bar content in a single MD file, but control the injection of said content.
Here is my setup..
_layouts/default.html
<div>{{ content }}</div>
<div class="side-bar">{% include sidebar.html sidebarContent=sidebar %}
_includes/sidebar.html
{{ include.sidebarContent }}
pages/my-content-page.md
----
layout:default
----
This is the main content portion's content.
{% capture sidebar %}
This is the sidebar content
* one
* two
{% endcapture %}
It seems like there is no way to pass the "sidebar" variable UP the scope; I can only seem to pass it down. All i want to to do is separate the content authoring for a single page (which consists of 2 discrete areas; Content and Sidebar) and avoid introducing layout marking into my "content" files (aka the MD files).
If there is a way i can break them out into different MD files i'db be open to that as well... ex.
my-page.md
my_page_sidebar.md
or
my_page/index.md
my_page/sidebar.md
I have some leeway in this as im building out using pages not posts.

From a page, you can get datas from front matter and content itself when you are in a layout. So only page.something variables are available.
But, there is no way to capture or assign in page content and get the resulting variable from a layout.
You can try to store your sidebar in your front matter, but it can be tricky.
One solution can be to separate content from sidebar with something like an excerpt separator used by posts.
In _config.yml, set
content_separator: "<!--separator-->"
In your page :
This is the main content portion's content.
{{ site.content_separator }}
This is the sidebar content
* one
* two
In your template :
{% assign contentSplitted = content | split: site.content_separator %}
{% assign myContent = contentSplitted | first %}
{% assign navbar = contentSplitted | last %}
<div>{{ myContent }}</div>
<div class="side-bar">{{ navbar }}</div>
Note I use myContent as content variable is already in use.

Related

Jekyll: Liquid custom output statement for dynamic CSS classes

My Jekyll website has two kinds of content: personal, and professional.
I would like to emphasize which kind of content a visitor is currently reading with dynamic CSS classes:
If the visitor is on a page tagged as "personal", my <main> element's class should be "personal-content".
If the visitor is on a page tagged as "professional", my <main> element's class should be "professional-content".
Otherwise, the class should be "site-content".
In the front-matter of each page, I'm creating an output statement that I set either at "personal" or "professional", for example:
---
content: "personal"
----
Then I'm using this output statement in my tag like this: (indented for reading purposes)
<main
{% if page.content %}
class="{{ page.content }}-content"
{% else %}
class="site-content"
{% endif %}
>
However I'm only seeing styling from my site-content class. What did I do wrong?
Thanks to the comments above, I fixed it!
The problem was that I was not using a custom output statement as I thought I was: {{ content }} is already used by Jekyll to include markdown articles into HTML layouts.
So I switched {{ page.content }} to {{ page.contenttype }} and it works fine!
Caveat:
I also had to change the values I was giving my output statement. professional was working fine, but for some reason personal was returning nil. So I simply switched them for pro and perso and voilà.

Markdown rendering differs when invoked on members of foreach or via a where filter

I wonder if anyone can illuminate this puzzle. I am using a new installation of vanilla jekyll on a Mac. Everything seems to work fine, but I discovered that some text being shown in my page footer was rendering differently on posts and all other pages. On most pages the text would render as HTML, but in posts it was rendering as Markdown. I found a workaround, but it left me with even more questions.
Context
I have defined footer_sections as a collection to hold portions of the footer. In my _config.yml this looks like:
collections:
footer_sections:
output: false
A footer section is then defined in a Markdown file such as _footer_sections/address.md as:
---
title: Address
order: 1
---
**My Name**
123 My Street
My Town, ST 12345
123-555-5555
In my default.html I had a footer section in my HTML something like this:
<div id="footer">
{{ site.footer_sections | where: "title", "Address" }}
</div>
And my posts are set up like this example:
---
title: Silly new post
date: 2017-02-27T12:33:53+00:00
author: Eric Celeste
layout: post
---
Silly post.
And finally, the post layout is connected to the default layout like this:
---
layout: default
---
<h1>{{ page.title }}</h1>
<p class="meta">{{ page.date | date_to_string }}</p>
<div class="post">
{{ content }}
</div>
The Problem
Notice that the address.md file is defined in Markdown and then its content is shown in the footer by the inclusion of the section in default.html. On all regular pages this would render as HTML (a bold name, a plain address), but on posts like the silly post above, it would render as Markdown (a name surrounded by stars and an address without like breaks).
I thought maybe it had to do with different procedural steps between posts and pages, maybe the Markdown rendering is happening "later" on pages but has already happened "earlier" in posts. I am only two days old on Jekyll, so I really don't know how it works.
In order to test that theory, I tried forcing the Markdown rendering with the markdownify filter. I changed the liquid tags in default.html so that they read:
{% assign section = site.footer_sections | where: "title", "Address" %}
{{ section.content | markdownify }}
Oddly, this produced a worse result everywhere. Now no text of any sort appeared in the footer of regular or post pages.
On the theory that maybe the where filter is actually different from looping through members of an array with foreach I tried another approach:
{% for section in site.footer_sections %}
{% if section.title == "Address" %}
{{ section.content | markdownify }}
{% endif %}
{% endfor %}
That worked! Now the content of the footer sections rendered as HTML on both regular pages and posts.
My Questions
Why didn't the initial approach work? What is the difference between rendering of posts and other pages in Jekyll?
While I found workaround, I don't understand why it works. In what ways does pulling out an item from an array with a where filter differ from using a member from a foreach loop? How does this affect the results of the markdownify filter?
Is there a cleaner, simpler way to grab the HTML-rendered content from my sections than looping through them each time I want to use one of them?
Thanks for any insights you may have!
site.footer_sections is an array and the output of the 'where' filter is still an array (but only containing the values that match your condition).
In your case, you are getting a single-element array but it's still an array object.
To see this for yourself use the inspect filter:
{% assign section = site.footer_sections | where: "title", "Address" %}
{{ section.content | inspect }}
On the other hand, when you loop through the elements with a for loop, at each iteration you get the individual elements of the array. Try using inspect inside your loop to see how the two types of your section variable differ.
For the 'where' method to work you need to get the actual element from the array either with first or [0]:
{% assign section = site.footer_sections | where: "title", "Address" %}
{{ section.first.content | markdownify }}
OR
{% assign section = site.footer_sections | where: "title", "Address" %}
{{ section[0].content | markdownify }}
links:
array documentation
first documentation
where documentation

In Jekyll can I pass a reference to a site data set in front matter

I have a layout used for the home page for different sections on my Jekyll site. On each of these pages I would like to have links to each item in the section, the details of which are stored in a YAML file in the site _data directory. My aim is to have the name of the site data variable in the section page front matter and pass this into the layout for rendering. For example:
Page Front Matter
---
sectionItems: site.data.sectionItems.awesomeSectionItems
---
...which is passed to the section home layout...
Section Home Layout
{% for item in page.sectionItems %}
// Work with section item...
{% endfor %}
Unfortunately, when I run the site nothing appears. How would I go about doing this? I have also tried an include but this also does not work. I would like to avoid adding the for loop to each page, plus I would like the links to appear beneath the main content section.
You cannot use variables in front matter. You will have to use a content variable like {% assign sectionItems = site.data.sectionItems.awesomeSectionItems %} and then loop with {% for item in sectionItems %}.

Send variable along within include block

I'm working on a personal Django project where my plan is to make some sort of function in my site in form of a CSS Marquee (scrolling text).
I was able to make a marquee.html file with the code from here, and use it on several pages on my site using {% include "marquee.html" %} blocks, but the displayed string in the marquee is within the HTML file itself (marquee.html) between <p>-tags
Is there any way to send a variable/string along with a {%include "" %} block that replaces/adds to the <p> tags at the end of the marquee code?
(e.g. {% include "marquee.html" {{ stringToDisplay }} %} )
The current context is available for the included template. You can use the "with" option to send any additional context.
{% include "marquee.html" with message="Hello" %}
and in your marquee.html template
<div>{{ message }}</div>
The include documentation is here

Render static html page inside my base django template

I'm developing a web portal using
- Django 1.2
- Apache
- Mod WSGI
I've several HTML files which are being served by apache.
I want to render those static HTML pages under my base template in order to keep my header / footer and dynamic menus intact.
One way I could thought its using iframes. Another way is to do read HTML files and return string while rendering but in that case I'm loosing advantage of apache, so I want to know if there would be any better way of doing it, is there any existing solution provided by django stuff ?
I'm not sure if this is exactly what you're asking for, but you can insert an html file (or even another template) in a template with the ssi and include tags, depending on your needs:
{% ssi '/path/to/file.html' %}
{% include 'relative/path/to/template.html' %}
yes, it's the include tag
Loads a template and renders it with the current context. This is a way of "including" other templates within a template.
it's as simple as
{% include "templates/static_template_1.html" %}
or, if you create a variable in the view side:
{% include template_name_variable %}
it shares the context with the base template (the one including them)
Edit:
Perhaps you ment to load html-files outside the template-system. Then my way will not suffice.
An option is to extend your base template.
Your base template should not be aware of the sub templates as that would be logically wrong.
Example:
base_template.html:
<html>
<div id='header'></div>
{% block content %}
This text can be left out else it it will shown when nothing is loaded here
{% endblock %}
sub_template.html:
{% extends "base_template.html" %}
{% block content %}
<h1>This is my subpage</h1>
{% endblock %}
You can read more here:
https://docs.djangoproject.com/en/1.2/topics/templates/