How do I best structure my Jekyll layouts for a blog? - jekyll

I have a very basic layout:
#_layouts/default.html
{% include header.html %}
{{ content }}
{% include footer.html %}
A front page that shows all posts (without their comments):
#index.html
---
title: Schmexy Title
---
<section id="fresh-off-the-press">
{% for post in site.posts %}
<article class="post">
<header>
<p class="post-date">{{ post.date | date: '%b %d, %Y' }}</p>
<h1 class="post-heading">{{ post.title }}</h1>
</header>
{{ post.content | split:'<!-- body -->' | last }}
</article>
{% endfor %}
</section>
And a simple article format:
#_posts/2015-02-25.superduper.md
---
title: SuperDuperHeadline
category: newsflash
---
[SuperDuperHeadline][1]
===================
<!-- body -->
After a hassle-free launch, [Jekyll] has kept me up all night.
[1]: {{ page.url }}
[Jekyll]: http://jekyllrb.com
The use of the comment to avoid jekyll displaying the article title twice seems very hacky.
I tried simply deleting the headline & body hack
[SuperDuperHeadline][1]
===================
<!-- body -->
which works great for the index.html but when I click on the heading link to take me to the article it is then displayed with no heading at all as Jekyll is outputting only the html conversion of the markup inside the default layout.
SO, I tried using a sub-template to display the single post, changing the front-matter in the article to use _layouts/post.html
#_posts/2015-02-25.superduper.md
---
title: SuperDuperHeadline
category: newsflash
layout: post
---
with the new layout much like the old layout (but with the potential to show comments)
#_layouts/post.html
---
layout: default
---
<article class="post">
<header>
<p class="post-date">{{ page.date | date: '%b %d, %Y' }}</p>
<h1 class="post-heading">{{ page.title }}</h1>
</header>
{{ page.content | markdownify | split:'<!-- body -->' | last }}
<!--
<section class="comments">
<header><h1 class="comments-heading">Comments</h1></header>
<article class="comment">
<footer><p>Posted by: Commenter 1</p></footer>
<p>Comment 1</p>
</article>
<article class="comment">
<footer><p>Posted by: Commenter 2</p></footer>
<p>Comment 2</p>
</article>
</section>
-->
This sub-template needed the further hack of piping everything through markdownify before using the body hack to separate the header from the contents.
It all seems very... well, hacky. I must be doing something wrong
How do I best structure my layouts and posts for a blog?
Why is markdown not used in the sub-template?

I have re-created your Jekyll site on my machine by copying the code from your question - except for the two include files which you didn't show in your question:
{% include header.html %}
{% include footer.html %}
I used the following content for them in my project:
<!DOCTYPE html>
<html>
<head>
<title>{{ page.title }}</title>
</head>
<body>
<h1>{{ page.title }}</h1>
and
</body>
</html>
...and I had no headline displayed twice.
Can you show me your header.html and footer.html?
(or better, is the whole project online somewhere, like on GitHub, where I can see the code?)
I'm suspecting that you have something in there that causes the headline to be displayed twice.
I have built multiple sites with Jekyll and it's definitely possible to do this without any hacks:
I am simply trying to list all posts on the front page (without comments) and click through to a single post (with comments). I'd like to write the posts is .md and have them marked up properly as per post.html.
I have simplified your example a bit - take a look at this:
The code
/index.html:
---
title: Schmexy Title
layout: default
---
<section id="fresh-off-the-press">
{% for post in site.posts %}
<article class="post">
<header>
<p class="post-date">{{ post.date | date: '%b %d, %Y' }}</p>
<h1 class="post-heading">{{ post.title }}</h1>
</header>
{{ post.content }}
</article>
{% endfor %}
</section>
/layouts/default.html:
<!DOCTYPE html>
<html>
<head>
<title>{{ page.title }}</title>
</head>
<body>
<h1>{{ page.title }}</h1>
{{ content }}
</body>
</html>
/_posts/2015-02-25-superduper.md:
---
title: SuperDuperHeadline
category: newsflash
layout: default
---
After a hassle-free launch, [Jekyll] has kept me up all night.
[Jekyll]: http://jekyllrb.com
The created HTML:
/index.html:
<!DOCTYPE html>
<html>
<head>
<title>Schmexy Title</title>
</head>
<body>
<h1>Schmexy Title</h1>
<section id="fresh-off-the-press">
<article class="post">
<header>
<p class="post-date">Feb 25, 2015</p>
<h1 class="post-heading">SuperDuperHeadline</h1>
</header>
<p>After a hassle-free launch, Jekyll has kept me up all night.</p>
</article>
</section>
</body>
</html>
/newsflash/2015/02/25/superduper.html:
<!DOCTYPE html>
<html>
<head>
<title>SuperDuperHeadline</title>
</head>
<body>
<h1>SuperDuperHeadline</h1>
<p>After a hassle-free launch, Jekyll has kept me up all night.</p>
</body>
</html>
There you are - one headline per page, and the headline is a permalink.
Is this what you wanted to achieve?
(I know I omitted the comments in this first step - we'll come to that later if you still need it)

Related

How can I pass a variable to a jekyll layout?

I don't understand how to pass a variable to a Jekyll layout. I have a markdown file with this header:
---
layout: post
next_tutorial: next_tutorial_name
---
And then, in the post layout, I have this:
---
layout: default
---
<article id="postBody">
<h1>{{ page.title }}</h1>
<p>{{ page.date | date_to_string }}</p>
{{ content }}
{% if site.next_tutorial %}
<h2>{{ site.next_tutorial }}</h2>
{% endif %}
</article>
But the h2 element never appears. I tried removing the if, but the result is the same. What I'm doing wrong?
What you are calling the "header of a markdown file" actually have a name in Jekyll, and this is called the Front Matter.
And the elements of the front matter can be accessed via the page variable, as pointed here and there.
So, your layout should read:
---
layout: default
---
<article id="postBody">
<h1>{{ page.title }}</h1>
<p>{{ page.date | date_to_string }}</p>
{{ content }}
{% if page.next_tutorial %}
<h2>{{ page.next_tutorial }}</h2>
{% endif %}
</article>

Please give me a suitable Jekyll index.md?

This is the source code of the index I am currently using, but it will display the date in the title bar. I don’t know how to modify it. It can only be displayed: title.html
<ul class="posts">
{% for post in site.posts %}
<li>
    {% for post in site.posts %}
      {{ post.date | date_to_string }} {{ post.title }}
    {% endfor %}
</ul>
I think this is nothing for the index.md file, but for the layout.
The HTML-Title is defined by the title-tag inside the head
<head>
<title>{{ site.title }} - {{ page.title }}</title>
</head>
So you have to look check the layout definition.

How use Jekyll toc in html templates? (out of *.md post files)

I am wondering why the TOC (surrounded by {{ }} or not in any kind of fashion is not rendered when used in the Jekyll post.html template:
---
layout: default
---
<article class="post" itemscope itemtype="http://schema.org/BlogPosting">
<header class="post-header">
<h1 class="post-title" itemprop="name headline">{{ page.title }}</h1>
<p class="post-meta"><time datetime="{{ page.date | date_to_xmlschema }}" itemprop="datePublished">{{ page.date | date: "%A, %B %-d, %Y" }}</time>{% if page.author %} • <span itemprop="author" itemscope itemtype="http://schema.org/Person"><span itemprop="name">{{ page.author }}</span></span>{% endif %}</p>
</header>
<div class="post-content" itemprop="articleBody">
>> * TOC <<
>> {:toc} <<
{{ content }}
</div>
</article>
The table of contents feature you are describing is a feature of the kramdown converter, which means that you have to add the toc generation code to your markdown file content. As I see you are adding it to `html.
I use it in the following way on my blog in my .md files:
* TOC
{:toc}
Please note that you can use the .no_toc classname to exclude headers from content generation.
# Contents header
{:.no_toc}
This means that you can to something like this in your post .md file, and that's another reason to add the toc to your content:
# Table of contents
{:.no_toc}
* TOC
{:toc}
# Heading 1
## Heading 2
Please also make sure that you set markdown: kramdown in your _config.yml. (kramdown is the default on GitHub pages).

Generate headings from a Jekyll Collection item's front-matter

As you see below, this is a fairly simple collection setup with an unordered lists of events that live in the _events folder at the root level (output is set to false). Instead of using {{ page.title }} in the layout, I want the heading(s) to read as months.
For example, if I add a new item into the _events collection and include month: January in the front-matter, I want that to generate a “January” heading, and place that unordered list underneath the heading. Likewise, if I add a new collection item and include month: February in the front-matter, I want to generate a “February” heading with a new unordered list below that heading.
I know I need a bit of re-arranging of where the heading lives, and I'm thinking I need some type of if statement, but I’m at a roadblock. I can’t figure this one out.
Is this possible with Jekyll Collections?
Layout
{% include root.html %}
<div class="flex-main">
{% include header.html %}
<main class="o-main" role="main">
<div class="o-grid-six">
<h1 class="f1 o-grid-six__child c-headline">{{ page.title }}</h1>
</div>
{{ content }}
</main>
</div>
<div class="flex-footer">
{% include footer.html %}
</div>
View (Events)
---
layout: events
title: Events
order: 2
---
<ul class="c-event-list">
{% for events in site.events %}
<li class="c-event-list__flag">
<div class="c-event-list__flag--left">
<div class="c-event-list__calendar">
<span class="c-event-list__day">{{ events.weekday }}</span>
<span class="f2 c-event-list__date">{{ events.date-number }}</span>
</div>
<img class="c-event-list__image" src="{{ p.url | prepend: site.baseurl }}{{ events.thumb }}" alt="">
</div>
<div class="c-event-list__flag--body">
<div class="c-event-list__content">
<h3 class="f2 c-event-list__title">{{ events.title }}</h3>
<p>{{ events.description }}</p>
<a class="c-button u-mt-2" href="{{ events.link }}">Sign Up</a>
</div>
</div>
</li>
{% endfor %}
</ul>
Collection item (an event)
---
layout: default
thumb: /images/event__screen-printing-basics.jpg
link: https://www.eventbrite.com/e/screen-printing-basics-tickets-41882948025
title: Screen Printing Basics
weekday: Wednesday
month: January
date-number: '10'
description: Join us for an after hours session to learn everything you need to know about screen printing in the Make Lab. We will be coating screens with emulsion, printing artwork onto transparencies, burning the image into the screen, washing out the stencil, mixing ink, prepping our work station, registering the paper, and finally pulling prints. The artwork always varies, so you’ll leave with a one-of-a-kind screen printed poster that you made yourself!
---
Interface
The best way to accomplish this is to use real dateTime and group_by_exp filter.
DateTime
---
layout: default
thumb: /images/event__screen-printing-basics.jpg
link: ...
title: Screen Printing Basics
description: ...
date: 2018-03-21 20:00
---
Note that for some reason date: 2018-03-21 doesn't work.
group_by_exp filter
Simplified print logic can be :
{% assign eventsByYear = site.events | group_by_exp:"event", "event.date | date: '%Y'" %}
{% for year in eventsByYear %}
<h1>{{ year.name }}</h1>
{% assign eventsByMonth = year.items | group_by_exp:"event", "event.date | date: '%B'" %}
{% for month in eventsByMonth %}
<h2>{{ month.name }}</h2>
<ul>
{% for event in month.items %}
<li>{{ event.title }}-{{ event.date | date: "%A, %B %d, %Y"}}</li>
{% endfor %}
</ul>
{% endfor %}
{% endfor %}

How to pass {% captured %} variable from a view to the layout in Jekyll/Liquid?

I am trying to rebuild a blog in Jekyll and I have stubled upon a simple task.
Provided I have the following set of templates:
default.html:
{{ head }}
{{ content }}
frontpage.html:
---
layout: default
---
{% capture head %}
Frontpage
{% end %}
{{ content }}
index.html:
---
layout: frontpage
---
Other stuff
I was expecting that {% capture head %} would pass a variable to layout. But it seems only variables from the Front Matter are actually being passed as page.variable_name.
Is there a way to pass capture-d var to the layout in Jekyll?
Guess I could make 2 different layouts for frontpage and normal_page that would replace the whole {{head}}{{content}} block in the layout. But that's like twice the html, so I'd rather solve it with capture if possible.
You can't do this with a capture, but you can using an include. Every level of the page hierarchy can override the head key to point to a different include file as required. This example wraps the include with a condition so if no head key is specified the page will still generate.
default.html
{% if page.head %}
{% include {{ page.head }} %}
{% endif %}
{{ content }}
frontpage.html
---
layout: default
head: header1.html
---
{{ content }}
_includes/header1.html
(Frontpage header content)
If your use-case is like mine and you want to include add'l content inside your template, you can include multiline content from your front matter into the template using YAML's block scalar feature. A | keeps line-breaks while a > removes ("folds") line-breaks. (Note that the block indicator must be followed by a blank line.)
index.html
---
layout: default
head: |
<link href="//cdn-images.mailchimp.com/embedcode/classic-081711.css" rel="stylesheet" type="text/css">
<style type="text/css">
#mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; }
</style>
script: |
<script type='text/javascript' src='//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js'></script>
<script type='text/javascript'>(function($) {window.fnames = new Array(); window.ftypes = new Array();fnames[0]='EMAIL';ftypes[0]='email';fnames[1]='FNAME';ftypes[1]='text';fnames[2]='LNAME';ftypes[2]='text';fnames[3]='PHONE';ftypes[3]='phone';fnames[4]='ORG';ftypes[4]='text';fnames[5]='MMERGE5';ftypes[5]='text';}(jQuery));var $mcj = jQuery.noConflict(true);</script>
---
<!-- Content, maybe a MailChimp signup form? -->
default.html
<!DOCTYPE html>
<html>
<head>
<title>
{{page.title}}
</title>
<link rel="stylesheet" type="text/css" href="/css/main.css">
<!-- here you can have add'l arbitrary head content -->
{{ page.head }}
</head>
<body>
{{content}}
<script>
// Google Analytics, perhaps?
</script>
<!-- here you can have add'l arbitrary content at the end of the page, good for scripts -->
{{page.script}}
</body>
</html>