I've got some related posts in my Jekyll site, and I want to link them to each other. I'd like to just name the related posts in the yaml front matter, then when I render a post, include some nav bar that adds in links to the other posts.
For example:
title: This is Post One
layout: post
followup_post: 2013-02-02-two
---
Blah blah blah one.
Then in my post layout:
<h1>{{ page.title }}</h1>
{% if page.followup_post.size > 0 %}
follow up
{% endif %}
{{ content }}
However, this doesn't work, because post_url thinks I'm giving it a literal string when I want to give it a variable name.
Is there a way in Jekyll, without using a (GitHub-forbidden) plugin, to get a post URL for a post if the post's name in a variable?
Well, there is two things you could do:
1.) Loop over the site.posts array until you find the matching post object and use that
or
2.) Create the post url yourself, if you have a simple enough permalink (for example, i'm using simply :title)
Related
I'm using jekyll with GitHub pages for my blog. How can I display a short sentence right below my post title in the index/ home page? As an example, I am trying to write text between the red brackets:
example image
I've seen other posts on this site that ask a similar question, but they are very old and it seems that jekyll has changed since then. Any help would be appreciated.
If these are posts you should be able to use {{ post.excerpt }}. You can see more in the docs: https://jekyllrb.com/docs/posts/
If it's a page (and not a post) you'll need to use {{ page.content | truncatewords: 30 }}. See more in the docs: https://shopify.github.io/liquid/filters/truncatewords/
A note about page.content: if that page is HTML code you'll need to use the strip_html filter. If that page has liquid, there is no filter to strip that and you will need to add the excerpt to the front matter. Something like this:
---
title: This is a post title
description: This is a post description.
excerpt: This is the post excerpt.
---
{{ page.excerpt }}
If I understand correctly Jekyll takes the first paragraph as an excerpt unless you use one of the various methods mark or specify one manually.
In my case, I want to be able to distinguish in the templates whether there was no excerpt or not so I can effectively do this
{% if post.excerpt %}
{{ post.excerpt }}
{% else %}
{{ post.content }}
{% endif %}
Effectively if there was no excerpt use the entire post. As it is, since Jekyll auto generates excerpts the test will always fail.
I suppose one solution so to go to every post that has no excerpt and add <!-- more --> at the very bottom of the post but that's very error prone as in if I forget I'll get the wrong result. I'd prefer to make the default be if I didn't manually mark an excerpt then the entire post appears on the home page.
To put it another way I'm trying to port from Wordpress to Jekyll. Wordpress's behavior is that no excerpt = insert entire post.
Is that possible in Jekyll? Is there some flag or variable I can check in the templates on whether or not an excerpt was manually specified vs auto generated?
There is an alternative solution with Liquid. You need to check, if the excerpt separator is present in the post:
{% if post.content contains site.excerpt_separator %}
{{ post.excerpt }}
<p>Read more</p>
{% else %}
{{ post.content }}
{% endif %}
I don't know any method to tell if an excerpt is manual or generated. Maybe writing a plugin to analyze the raw file's front-matter can be an option (but that would not work on Github Pages for example).
But I may have a solution for this:
I'd prefer to make the default be if I didn't manually mark an excerpt then the entire post appears on the home page.
According to the documentation, you can set excerpt_separator for every page (you can also set it at once in defaults).
Try setting a value which you know will never appear in your posts. If Jekyll doesn't find the separator, it won't separate, so the generated excerpt will be the entire post.
Example:
---
title: Some title
excerpt_separator: "CANTFINDME!"
---
Post line 1
Post line 2
The generated excerpt will be the entire post:
<p>Post line 1</p>
<p>Post line 2</p>
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
I am using Jekyll to create a blog by following this excellent tutorial. I would like to add a post summary on the index page. I tried using:
post.content | truncatewords:50 | strip_html
it works but it displays the entire post until the 50 word count is reached. This includes the heading too. I would like to just summarize the actual content of the post. How can I structure my posts to do this?
Update 16 Nov, 2015
Now Jekyll support excerpt separator, In template you can do this:
{% if post.excerpt %}
{{ post.excerpt }}
{% endif %}
and In global config _config.yml you can set:
excerpt_separator: <!--more-->
and the same use with <!--more--> html comment tag.
Old answer
You can try this:
{% if post.content contains '<!--more-->' %}
{{ post.content | split:'<!--more-->' | first }}
{% else %}
{{ post.content }}
{% endif %}
and add <!--more--> tag in the article after summary, just like Wordpress.
Use YAML front matter and define a separate title per post, like this:
---
title: Efficient smuflet based kwoxel trees
---
Post content goes here.
Then you can use or not use post.title as you please.
Or, if you want to write a separate summary (not just the first n characters) for each post, just add a field for that summary in the front matter as well.
From the Jekyll documentation:
Each post automatically takes the first block of text, from the beginning of the content to the first occurrence of excerpt_separator, and sets it as the post.excerpt.
...
Because Jekyll grabs the first paragraph you will not need to wrap the excerpt in p tags, which is already done for you.
See http://jekyllrb.com/docs/posts/#post-excerpts for more info and an example.
Use {{ post.excerpt }} in your index.md file to get an excerpt of this post.
New to Jekyll and wondering if it's possible to include custom variables in Jekyll Front Matter. It would be useful for nested layouts, for example something like:
layouts/artist.html
----
layout: default
title: {{ page.artist }} (Artist)
----
I get an error trying that.
At the moment, Jekyll do not support Liquid variables in the front matter, and the only way to do that would be through a plugin, such as jekyll-conrefifier.
Alternatively, what you can do, though, is create variables that you re-use on the same file:
{% assign new_title = page.title | append: " (Artist)" %}
<h1>{{ new_title }}</h1>
and you can also pass variables to files that get included. For example, including a file from _includes\display-post.html passing the modified title as an argument:
{% assign new_title = page.title | append: " (Artist)" %}
{% include display-post.html post_title=new_title %}
And then getting the value of the value passed in (example content of _includes\display-post.html):
{% assign title_received = include.post_title %}
<h1>Title that as passed in: {{ title_received }}</h1>
I'm not sure if there is a way to do this properly (i.e. server side), but a stop-gap measure could be to have a small snippet of Javascript that sets the correct title in the users browser. e.g.
---
title: Default title blah blah
---
[... content ...]
<span id="pagetitle" style="display: none">{{ page.artist | escape }} (Artist)</span>
<script type="text/javascript">
var pagetitle = document.getElementById("pagetitle");
if (pagetitle) {
document.title = pagetitle.textContent;
}
</script>
Notes:
The substitution of page.artist is performed in HTML rather than in the Javascript because it is easier to quote any HTML special characters (via escape) rather than the Javascript special characters ' or " or \ (there isn't a built-in filter to do this).
One could also move the pagetitle span to the top of the page so that it is near the other YAML front matter.
Unfortunately, this is a very poor way of achieving this, but it looks like it might be the only way other than writing a plugin.