I have a basic layout page template:
---
layout: default
---
<header class="sidebar">
{{ page.title }}
</header>
<section class="content">
{{ content }}
</section>
My pages that use this as the page template are just Markdown that gets put into the <section> block.
I'm looking for a way to keep all my page content in one file but have it so I can define separate content that gets put into the <header> tag from the page template.
Is there any way to do this and keep all the page's content in one file?
You can do so by defining the content you wish to be separate and reused in the _includes/ directory.
You would then include it by calling for example: {% include file.ext %} to include the of the file name _includes/file.ext (almost as if you just copy and pasted it in).
See section pertaining to the _includes in the Jekyll documentation here.
The YAML Front Matter can be used to directly store additional content for the page. This is done by creating custom key/value variables. The layout/template uses liquid tags to check to see if the secondary content is available. If so, it gets output. Otherwise, the section is skipped.
Here's an example of a layout template that checks to see if a custom variable called myvar1 is set:
---
layout: default
---
<header class="sidebar">
<h2>{{ page.title }}</h2>
{% if page.myvar1 %}
<p>Secondary content here: {{ page.myvar1 }}</p>
{% endif %}
</header>
<section class="content">
{{ content }}
</section>
Note: To match your original example, this layout file calls a parent "default" layout. For this example, the above is in a layout file called "_layouts/nested_layout.html".
To use the new slot, a myvar1 variable is added to the front matter, like this:
---
layout: nested_layout
title: This is the post test layout
myvar1: More here <strong>including bold text</strong>.
---
And here is the page content: The quick brown fox jumps over the lazy dog.
When that page is processed, the secondary content will show up. If you create another page that doesn't have myvar1, nothing will be rendered at that part of the template.
You can add as many custom variables to your pages as necessary. The values can include HTML as shown in this example. (It works for me in Jekyll 0.11.2.) If you have a lot of code that you want to add (instead of something that easily fits on one line), or if you want to have the same content available to turn on/off for multiple pages, you can use the custom variable as a flag. Then, in the {% if %} tag, you would call an include if the value is set.
Related
I'm really excited to see that we can apply a block assignment for set through Nunjucks. What would be the correct way to allow HTML to be passed through this approach?
I want to do the following from my initial nunjucks file:
{% set demoSetBlock %}
<div class="mClass">
<p>a header value in a nunjucks set block</p>
</div>
{% endset %}
I then want to call it into my nunjucks template like so...
{{demoSetBlock}}
but...it's printing out the content along with the HTML markup on the web page, just like this...
<div class="mClass"> <p>a header value in a nunjucks set block</p> </div>
How can we render this so that it shows it as...
a header value in a nunjucks set block
Not sure if this is the official way of resolving the situation, but what appears to be working for me now is using |safe as an attribute when the set block is called, like so:
{{demoSetBlock|safe}}
as a result, my HTML is perfectly rendered on the browser.
This is helpful in cases
when I don't want to depend on macros.
when I want to depend on set as an instrumental component for defining and passing data through various parts of my templates.
where I have other include files (i.e. _include-header.njk, _include-footer.njk) that are directly attached to my main template file. I could then use set block for one of these files.
I'm having some difficulty getting Jekyll to use a particular theme and I think there's something fundamental I'm missing about how {{ content }} works with posts.
So, in a generic Jekyll site, index.html has a layout specified in its front matter. When the site is generated, the layout includes index.html as {{ content }}. It's kind of inverted, where the page specifies the layout and then the layout calls the page, but simple enough.
Posts, on the other hand, are all generated via a file, post.html, which resides in the _layouts folder even though it isn't really a layout. Like index.html it's essentially just a for loop. This is where I'm running into trouble.
Is post.html a required file? Could I rename it story.html?
Why does post.html require a layout in the front matter? The actual post, that is, the markdown that contains the text for said post, also requires a layout in its front mater. Is there a circumstance where post.html would have a different layout than the layout specified in the markdown file?
Edit: one other question. Why is {{ content }} called in multiple places? index.html and the layout file both have {{ content }}. Why doesn't the layout simply {% include %} index.html and let index.html call {{ content }}
I think you largely figured it out by yourself, but I'll still explain it in my own words.
You're right that {{ content }} is the placeholder in the layout file where the content of the actual page will go.
What probably confused you is the fact that you can build a set of nested layout files where one "inherits" from the other, and each layout has its own {{ content }}.
And yes, I didn't find anything about this in the docs, I figured it out by myself or better, by looking at examples.
So here's an example for you.
First, a default layout and a page:
/_layouts/default.html:
<!DOCTYPE html>
<html>
<head>
<title>{{ page.title }}</title>
</head>
<body>
<h1>{{ page.title }}</h1>
{{ content }}
</body>
</html>
/index.md:
---
title: example page
layout: default
---
This is the page content.
The generated HTML will look like this:
<!DOCTYPE html>
<html>
<head>
<title>example page</title>
</head>
<body>
<h1>example page</h1>
<p>This is the page content.</p>
</body>
</html>
Now let's create another layout file that "inherits" from the first one.
You'll probably want to use something like this if you're building a blog with Jekyll.
The layout file shown above is the default for all pages, blog posts and regular ones.
When you want all blog posts to contain additional information like post date and user, tags and so on.
For this, you can create a second layout file which uses the first one:
/_layouts/post.html:
---
layout: default
---
<div class="blogpost">
<i>post date: {{ page.date }}</i>
{{ content }}
</div>
And a blog post which uses this layout:
/_posts\2015-04-08-example-post.md:
---
title: example post
layout: post
---
This is the post content.
And the generated HTML:
<!DOCTYPE html>
<html>
<head>
<title>example post</title>
</head>
<body>
<h1>example post</h1>
<div class="blogpost">
<i>post date: 2015-04-08 00:00:00 +0200</i>
<p>This is the post content.</p>
</div>
</body>
</html>
In other words, something like this happened:
Jekyll used the post layout and put the content of the post into {{ content }}
Jekyll used the default layout and put the complete generated HTML from step 1 into {{ content }}
(no idea if Jekyll really does things in this order under the hood, but you get the idea)
You can see another example if you create a new Jekyll project as shown in the "Quick-start Instructions" on the home page of the Jekyll site.
The example site that Jekyll (version 2.1.1 on my machine) creates has three layout files, two of which (page and post) inherit from the default one.
I have an answer for myself, sort of. Each markdown file is assigned a layout in the front matter. But this "layout" isn't really a layout at all or it's a partial layout?
The terminology escapes me, so I'll just list the steps.
1) The markdown file has layout: post
2) Whatever is in the markdown file gets processed and then sent over to the logic residing in post.html. Here's the part that I wasn't getting right off: post.html has it's own layout. That's what's up in the front matter. Essentially we have the layout's layout.
3) The outer "layout" (default.html in a vanilla jekyll install), wraps itself around the inner "layout" (post.html), which wraps itself around the actual {{ content }}.
post.html could be named whatever, so long as the various layout lines are properly set.
I still don't know why {{ content }} winds up at the top of the layout stack only to be passed all the way back down. I'm not even sure "passed" is the right word when dealing with liquid. I like Jekyll, but it's kind of a nest of snakes.
I have a website that consists out of a few 'slides'. Each has a fixed structure, used by some scripts, but variable content. I'm hosting it on github and am now trying to use Jekyll to make it easier to add new slides.
I already have each slide in a different html file, which I include in the main page: {% include_relative _slides/about.html %}. Now I'm trying to make it a markdown file, and I wanted to use front matter to make a layout that each slide's file could use. I can include a markdown file, and get it to render by doing:
{% capture myInclude %}{% include_relative _slides/test.md %}{% endcapture %}
{{ myInclude | markdownify }}
However, when I add a front-matter block to it with a layout defined in it, the layout doesn't get applied. It just gets rendered as a horizontal line (for the first ---) and then "layout: slide title: Test Slide —" in plain text.
Is there any way to fix this? Or perhaps a better way to break up my index.html and the slides in it?
Thanks a lot!
Note: Sorry if this was asked before, I Googled everything I could imagine it would be called.
I found something that works for me. I divided my template in two parts, the part above the content, and the part under it. Then in the file I include, there are two includes as well, one at the top and one at the bottom.
So my 'slide' files look like this:
{% include slide_start.html title="About" image="images/about.jpg" %}
... the content of the slide ...
{% include slide_end.html %}
As you can see, in the first include I give some parameters, these will be filled in and can be accessed with the liquid tags {{ include.something }}.
My slide_start.html looks like:
<div class="slide">
<div class="header">
<span>{{ include.title }}</span><!-- no whitespace
--><img src="{{ include.image }}" alt="{{ include.title }}"/>
</div>
<div class="content" markdown="1">
the slide_end.html is just two closing div tags.
You're trying to mix the page/post and the include strategies.
Page/post have a front matter and are decorated with a template, which can itself be decorated. `mypage.html -> layout: page -> layout: default.
Includes are included in page/post but they are only code parts. They cannot be decorated with a template.
You will have to choose.
Take a lool at https://github.com/shower/jekyller this can be helpfull.
I'm working with Sphinx (sphinx-1.2b1-py2.7). I want a TOC to appear in a sidebar. It seems binary: I can only get both a TOC in the sidebar and a bulleted list in the body of the text, or I get nothing (no TOC in the sidebar and no bulleted list).
When I use the toctree directive like this:
.. toctree::
:hidden:
Topic1
Topic2
Result: no TOC in the sidebar, no bulleted list of topics in body.
When I use the toctree directive like this:
.. toctree::
Topic1
Topic2
Result: TOC in the sidebar AND a bulleted list of topics in the body.
I just want the TOC in the sidebar. Other commands (maxdepth, includehidden) don't work. I've seen it done, but cannot get it to work. The conf.py looks fine, but no luck after several days of searching for an answer.
Thanks.
I had trouble with this too; I found the answer here.
The TOC is shown via a call to toctree() inside, e.g., a file called layout.html. In particular, it is shown in the sidebar via a snippet of code similar to the following, which resides in <div class="sidebar">:
{% block sidebartoc %}
<h3>{{ _('Table Of Contents') }}</h3>
{{ toctree() }}
{% endblock %}
Since I am using a theme, layout.html is within the theme directory inside the directory _themes; otherwise layout.html might be inside the directory _templates.
In newer versions of Sphinx, what is needed to display the TOC when :hidden: is used as in
.. toctree::
:hidden:
is to add the argument includehidden=True to the call to toctree(), as in
{% block sidebartoc %}
<h3>{{ _('Table Of Contents') }}</h3>
{{ toctree(includehidden=True) }}
{% endblock %}
I'm getting into Jekyll in a big way and would like to use it as a general front-end development platform, but am running up against the limitations of the Liquid templating language, specifically its difference to Django templating.
I discovered the liquid-inheritance gem, which adds the all-important Extends and Block syntax from Django. This blog post extends the gem further to suit Jekyll's file system:
http://www.sameratiani.com/2011/10/22/get-jekyll-working-with-liquid-inheritance.html
The problem is that it doesn't appear to implement blocks in exactly the same way Django does, which essentially renders the gem useless.
I have two jekyll "layouts" called - for the sake of understanding - parent.html and child.html. Neither of these contain YAML sections.
Parent
<html>
{% block foo %} {% endblock %}
</html>
Child
{% extends _layouts/parent.html %}
{% block foo %}
<div>
Bar comes next:
{% block bar %} {% endblock %}
</div>
{% endblock %}
And then I have a jekyll page which includes a YAML section thus:
---
title: test
---
{% extends _layouts/child.html %}
{% block bar %}My title is {{ page.title }} {% endblock %}
What I'd expect:
<html>
<div>
Bar comes next:
My title is test
</div>
</html>
What I get:
<html>
<div>
Bar comes next:
</div>
</html>My title is test
It seems something is failing to treat the blocks in mypage.html as being eligible for insertion into the suitable places of parent/child, although it's clearly still doing something.
I'm not a ruby developer and am reasonably new to Jekyll, so I need help identifying what part of this stack is failing. The liquid-inheritance issues on github suggest others are experiencing this block nesting problem: https://github.com/danwrong/liquid-inheritance/issues/3
I've tried several of the forks of liquid-inheritance, many of which apparently fix that problem regex, but none seem to solve this.
Is what i'm tring to do fundamentally impossible? It seems like I'm at least 85% of the way there and the final bit needs fixing.
I'm not sure this is ever going to work within Jekyll. I might be wrong, but here's my reasoning:
Each page is rendered out using do_layout in https://github.com/mojombo/jekyll/blob/master/lib/jekyll/convertible.rb
This works recursively - it processes the content of the page, then processes the page's layout, then that layout's layout and so on and so forth, passing the YAML variables up the chain (so they're always available in parent templates as {{ page.whatever}}).
This means that the only things which get passed up are the YAML values, and whatever the value of 'content' is after it has been processed by Liquid. I don't know how it is done elsewhere, but that seems incompatible with the idea of blocks, as they'd require you to pass up the two blocks separately.
Fundamentally, it seems to me that the issue is that Jekyll already has a simple form of inheritance - via the "layout" attribute that you can give to a layout. Fundamentally, I think that this is compatible with liquid-templating.
All that said, I'm not sure that you've exhausted the limits of using YAML, _includes, and template logic. If you're at the point of putting Django style blocks into your content, why not just do something like this:
Content:
---
title: some title
secondary_content: |
Here is some *secondary* content that will be [markdownified](http://example.com).
It can run to multiple lines and include
* Lists
* Good things
* Etc
---
And here is the main content, as per usual
Template:
<html>
<article>
<h1>{{ page.title }}</h1>
{{ content }}
</article>
<aside>
{{ page.secondary_content | markdownify}}
</aside>
If you wanted to keep your templates clean, and have different content for different types of pages, you could use various includes:
Template:
<aside>
{% include sidebar_negotiation.html %}
</aside>
_includes/sidebar_negotiation.html:
{% if page.type = 'foo' %}
{% include sidebar_foo.html %}
{% else if page.type = 'bar' %}
{% include sidebar_bar.html %}
{% endif %}
And then put your page type specific stuff in those files. Obviously you could include it directly, but it is probably nice to abstract it out. Those includes will get all of the variables in the YAML.
If none of this is a win, you could always try Hyde: http://hyde.github.com/ which is written in Python, uses Jinja2 (basically Django templates++), and does the same sort of thing.