Jekyll - Change _config.yml variables in the post layout - jekyll

In my config.yml I have:
...
showheader: "yes"
And in my default.html template I have a conditional to show the header include:
<!DOCTYPE html>
<html>
{% include head.html %}
<body>
{% if site.showheader == "yes" %}{% include header.html %}{% endif %}
<main class="page-main">
{{ content }}
</main>
{% include footer.html %}
</body>
</html>
In my post.html template I don't want to show the header.html so I try this:
---
layout: default
---
{{ site.showheader = "no" }}
<article class="post">
<header class="post-header">
<h1 class="post-h1" href="{{ post.url | prepend: site.baseurl }}">{{ page.title }}</h1>
<p class="post-meta">{{ page.date | date: "%b %-d, %Y" }}{% if page.author %} • {{ page.author }}{% endif %}{% if page.meta %} • {{ page.meta }}{% endif %}</p>
</header>
<p class="post-p">{{ content }}</p>
<footer class="post-footer">
<p class="rss-subscribe">subscribe via RSS</p>
</footer>
</article>
But it's simple don't work,and neither returned a error.
It is possible in Jekyll to change the value of a variable set in _config.yml from the post.html template layout?

It seems that you cannot reassign a site.variable value. {% assign site.showheader = false %} doesn't work if showheader: true is set in _config.yml.
If you want to show header depending on the page you're on, just set the variable in page front matter.
In index.html :
---
showheader: true
layout: default
---
In post :
---
showheader: false
layout: default
---
In _layouts/default.html
{% if page.showheader == true %}
header
{% endif %}

Related

11ty/nunjucks - templating a for loop to be extended to multiple layouts but use different data

I am creating an eleventy scaffolding project to learn more about SSG, this is my first time using an SSG so I am new to the templating stuff with nunjucks, etc.
What I am trying to build:
I want to create a template for a landing page/showcase that can be re-used but display different data within a for loop.
What I have:
site.json
{
"showcase": [
{
"title": "explore docs",
"url": "#"
},
{
"title": "visit github repository",
"url": "https://github.com/ExampleUser/ExampleRepo"
}
],
"404showcase": [
{
"title": "return home",
"url": "/"
}
]
}
pageShowcase.njk
Currently, I am just using an if statement to control what data set to
use but if I ever extend this to other layouts and use a third
or fourth set of data this will become really repetitive adding in a
new elseif for every new set of data
{%- set pageTitle %}{% if title %} {{title}} {% else %} {{ site.title }} {% endif %}{% endset -%}
{%- set pageDescription %}{% if description %} {{ description }} {% else %} {{ site.description }} {% endif %}{% endset -%}
<!-- Showcase -->
<div class="container">
<div>
<div>
<h1>{{ pageTitle }}</h1>
<p>{{ pageDescription }}</p>
<div class="navbar" id="navmenu">
<ul class="navbar">
{% if defualt %}
{% for item in site.showcase %}
<li>
{{ item.title}}
</li>
{% endfor %}
{% else %}
{% for item in site.404showcase %}
<li>
{{ item.title}}
</li>
{% endfor %}
{% endif %}
</ul>
</div>
</div>
<!-- <img src="assets/img/#.svg" alt="temp"> -->
</div>
</div>
</section>
index.njk
---
layout: base
defualt: true
---
<!-- include pageShowcase -->
{% include "partials/pageShowcase.njk" %}
<!-- home page content -->
<section>
<div class="container">
<main>
{{content | safe}}
</main>
</div>
</section>
404.njk
---
title: "404: Page Not Found"
description: "It looks like the page doesn not exist"
defualt: false
---
<!DOCTYPE html>
<html lang="{{ lang }}">
<!-- include head -->
{% include "partials/head.njk" %}
<body>
<!-- use pageShowcase for 404 page -->
{% include "partials/pageShowcase.njk" %}
</body>
</html>
This is the best I could come up with on my own, but I feel like there has to be a better way without re-writing the same code over and over.
Appreciate any help I can get on this one.

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>

How to add Navigation Bar in github jekyll theme

I am having hard time adding navbar to the github page.
I downloaded Monophase jekyll theme via this link :
http://jekyllthemes.org/themes/monophase/
I saw a navbar in the demo, but when i applied to the github.io page, I am missing navbar.
Index.markdown:
---
layout: default
---
If I set layout to default, nothing shows up and if I set to home all the posts are displaying but it does not navbar.
And there is no such thing as _data/navigation.yml in the monophase package zip I downloaded.
_site is set to .gitignore from what I received so I did not include the _site folder to the git as it was originally set, but do I need to add _site to git and create _data and navigation.yml inside this folder? to make the navigation bar?
I tried doing this but it did not work out so I'm not sure if I'm doing things right but would be nice if someone can explain what I'm doing wrong ;~;
default.html:
<!DOCTYPE html>
<html lang="{{ page.lang | default: site.lang | default: 'en' }}">
{% include head.html %}
<body>
<div class="container">
{% include header.html %}
<div>hello</div>
<main>{{ content }}</main>
{% include footer.html %}
</div>
{% if page.math %} {% include mathjax.html %} {% endif %} {% if
jekyll.environment == 'production' and site.google_analytics %} {% include
google-analytics.html %} {% endif %}
</body>
</html>
Header.html :
<header class="masthead">
<div class="masthead-title">
{{ site.title }}
<small class="tagline">{{ site.tagline }}</small>
</div>
{% if site.data.navigation %}
<nav class="nav">
<ul class="nav-list">
{% for item in site.data.navigation %}
<li class="nav-item">
<a href="{{ item.url | relative_url }}" class="{% if page.url == item.url %}current{% endif %}">
{{ item.title }}
</a>
</li>
{% endfor %}
</ul>
</nav>
{% endif %}
</header>
Home.html:
---
layout: default
title:home
---
<div class="posts">
{% assign posts = site.posts %} {% if paginator %} {% assign posts =
paginator.posts %} {% endif %} {% for post in posts %}
<div class="post">
<h2 class="post-title">
{{ post.title }}
</h2>
<time datetime="{{ post.date | date_to_xmlschema }}" class="post-meta"
>{{ post.date | date_to_string }}</time
>
<p class="post-excerpt">
{% if post.description %} {{ post.description | strip_html }} {% else %}
{{ post.excerpt | strip_html }} {% endif %}
</p>
</div>
{% endfor %}
</div>
{% if paginator %}
<div class="pagination">
{% if paginator.next_page %}
<a
class="pagination-item older"
href="{{ paginator.next_page_path | relative_url }}"
>Older</a
>
{% else %}
<span class="pagination-item older">Older</span>
{% endif %} {% if paginator.previous_page %}
<a
class="pagination-item newer"
href="{{ paginator.previous_page_path | relative_url }}"
>Newer</a
>
{% else %}
<span class="pagination-item newer">Newer</span>
{% endif %}
</div>
{% endif %}
Yes, or at least it's possible, but unclear given what you've shared.
With Jekyll on your desktop, you are locally building an html directory which would be a static version of your site. This is very likely the _site folder. If this is what you did (successfully), then the contents of that directory are a complete website; *.html files, etc.. Copy the content of this folder to your Git Pages repo, and they should work as-is. _site is in .gitignore because it is a by-product of your code, and in a sense, a duplicate, just in different format.
The advantage of this route is you can view the built html and iterate on your code more quickly, without taking your site down or testing changes live. More to the point, you can open the _site folder and view index.html or similar in your browser to see how things are working. The Demo for this style wasn't working when I tried to access it, and I wasn't able to find the source code for the default implementation (which DID have a nav bar), to be able to tell you how they set it up.
The alternative route is to maintain your Git repo with Jekyll-themed files, and Github will build the site for you. Assuming up-to-date versions, this should be the same as what you did on your desktop.
For this route, I'd suggest reading documentation on how to add a menu/navigation to your _config.yml file. This is usually where the navigation is specified, but you can certainly override it or customize a navigation in supporting css files. This is also something that you'll want to consult documentation for.

Jekyll blog posts on non index.html pages

I have used the below code snippet from the Jekyll website to paginate Jekyll plog posts on my index.html page:
<div class="container">
<ul class="post-list">
<!-- This loops through the paginated posts -->
{% for post in paginator.posts %}
<h1>{{ post.title }}</h1>
<p class="author">
<span class="date">{{ post.date }}</span>
</p>
<div class="content">
{{ post.content }}
</div>
{% endfor %}
{% if paginator.total_pages > 1 %}
<div class="pagination">
{% if paginator.previous_page %}
« Prev
{% else %}
<span>« Prev</span>
{% endif %}
{% for page in (1..paginator.total_pages) %}
{% if page == paginator.page %}
<em>{{ page }}</em>
{% elsif page == 1 %}
{{ page }}
{% else %}
{{ page }}
{% endif %}
{% endfor %}
{% if paginator.next_page %}
Next »
{% else %}
<span>Next »</span>
{% endif %}
</div>
{% endif %}
</ul>
</div>
However when I try to add this to a /pages/Blog.html page it does not work. It does not show any of the posts in my _posts directory and instead produces and empty container. I am assuming it is a path issue.
I have added the YAML header to the Blog.html file as required. When page is rendered it produces an empty container.
If you want an url that looks like /pages/Blog/ for your posts listings :
activate pagination by setting a paginate: 5 in _config.yml
set paginate_path: pages/Blog/page:num in _config.yml
rename /pages/Blog.html to pages/Blog/index.html

In Jekyll How do I grab a post's first image?

In my index of blog posts I'd like to grab the first image from the post to display it in the index using just liquid so it works on github pages.
I have a feeling split is the way to go, but I'm not good with liquid.
I'd like to be able to get the image url and put it in a variable to style it.
The ideal solution would be something like:
{% for post in site.posts %}
<li>
{{post.content | first_image}}
</li>
{% endfor %}
Any ideas?
You can define a custom variable to your Front Matter called "image", so it's going to work like Wordpress's posts Featured Image:
---
image: featured-image.jpg
---
Note to remember where is your image saved. In my case, I created a directory called "imagens" (PT-BR here). Then, go to your index.html and add the image to your template, wherever you want. In my site it looks like this:
<ul class="post-list">
{% for post in site.posts %}
<li>
<h2>
<a class="post-link" href="{{ post.url | prepend: site.baseurl }}">{{ post.title }}</a>
</h2>
<span class="post-meta">{{ post.date | date: "%b %-d, %Y" }},</span>
<span class="post-meta">por</span>
<span class="post-meta">{{ post.author }}</span>
</li>
//IMAGE
<img src="{{ site.baseurl }}/imagens/{{ post.image }}">
//IMAGE
{{ post.excerpt }}
<a class="btn btn-default" href="{{ post.url | prepend: site.baseurl }}">Continuar lendo</a>
{% endfor %}
</ul>
That's it.
Some solutions to your problem :
1 - Use the Post Excerpt tag Documentation is here
Your post :
---
layout: post
title: Testing images
---
## Title
Intro Text
![Image alt]({{ site.baseurl }}/assets/img/image.jpg "image title")
More intro text
Some more text blah !
Your template :
<ul>
{% for post in site.posts %}
<li>
{{ post.title }}
{{ post.excerpt }}
</li>
{% endfor %}
</ul>
As your image tag appears before the excerpt_separator (\n\n = two newlines) it will be in the post excerpt.
2 - Use your post's Yaml front matter to store your image's datas
Post :
---
layout: post
title: Testing images
images:
- url: /assets/img/cypripedium-calceolum.jpg
alt: Cypripedium Calceolum
title: Cypripedium Calceolum
- url: /assets/img/hello-bumblebee.jpg
alt: Hello bumblebee !
title: Hello bumblebee !
---
Intro here yo ! <-- THIS IS THE EXCERPT
Post body begin, and first image not in excerpt
{% assign image = page.images[0] %} <-- first element of the array is zero
{% include image.html image=image %}
Some more text blah !
{% assign image = page.images[1] %}
{% include image.html image=image %}
_includes/image.html (centralized in an include for standardization, but can be in the template) :
<img src="{{ site.baseurl }}{{ include.image.url }}" alt="{{ include.image.alt }}" title="{{ include.image.title }}">
The index page :
<ul class="posts">
{% for post in site.posts %}
<li>
<span class="post-date">{{ post.date | date: "%b %-d, %Y" }}</span>
<a class="post-link" href="{{ post.url | prepend: site.baseurl }}">{{ post.title }}</a>
{{ post.excerpt }}
{% assign image = post.images[0] %}
{% include image.html image=image %}
</li>
{% endfor %}
</ul>
Got it to work. Not sure how it will scale, but this liquid code loops through all the posts and grabs the source for the first image from a post and displays that post. I tested it with multiple images and it works as expected.
<ul>
{% for post in site.posts %}
<li>
{% assign foundImage = 0 %}
{% assign images = post.content | split:"<img " %}
{% for image in images %}
{% if image contains 'src' %}
{% if foundImage == 0 %}
{% assign html = image | split:"/>" | first %}
<img {{ html }} />
{% assign foundImage = 1 %}
{% endif %}
{% endif %}
{% endfor %}
{{ post.title }}
</li>
{% endfor %}
</ul>
If you just need the image URL instead of the whole thing in img tag, you can use the following method.
Install Liquid filter match_regex:
gem install match_regex
Then add it to your Jekyll config:
plugins:
- match_regex
Create a capture snippet in your template:
{% capture post_first_image %}
{% assign hero_image = page.content | match_regex: '<img .*?src="([^"]+)"' %}
{% if hero_image == nil %}
{% assign hero_image = "/placeholder-image.png" | prepend: site_base %}
{% endif %}
{{ hero_image }}
{% endcapture %}
Template:
<meta property="og:image" content="{{ post_first_image | strip }}">
You can simply remove the if condition if you don't need placeholder image.
I've taken David's answer and found a way to get just the src attribute from the img tag.
{% assign foundImage = 0 %}
{% assign images = post.content | split:"<img " %}
{% for image in images %}
{% if image contains 'src' %}
{% if foundImage == 0 %}
{% assign html = image | split:"/>" | first %}
{% assign tags = html | split:" " %}
{% for tag in tags %}
{% if tag contains 'src' %}
<img {{ tag }} />
{% endif %}
{% endfor %}
{% assign foundImage = 1 %}
{% endif %}
{% endif %}
{% endfor %}