Using map in liquid templates - jekyll

I recently upgraded Jekyll, and map doesn't seem to work in my liquid templates anymore. Before I had
{{ page.categories | map: "capitalize" | join ", " }}
which worked as expected, producing
Programming, Ember, d3
but now it produces
, ,
There is a array_to_sentence_string function included in Jekyll, but this doesn't capitalize the categories.
Has anybody else run into this problem?

First, please update to Jekyll's latest version in case you didn't already. The guys working on it are constantly fixing bugs and improving it.
Well, I got it working here. I created a new Jekyll site using jekyll new test and modified my index.html:
---
layout: default
title: Your New Jekyll Site
categories: [my, new, site]
---
<p>{{ page.categories | map: "capitalize" | join: ", " }}</p>
When I build it, My, New, Site is appearing correctly. So, try to use correct YAML array syntax ([..., ..., ...]), upgrade to latest version of Jekyll and it should work. :)

Related

Localize Jekyll 4.3.2 date

I am trying to localize a date in Jekyll. All information I find seems to be related to plugins that are no longer maintained, don't work, or to something that seems to have existed in Jekyll built-in earlier.
I have post with matter containing a list of dates:
---
events:
- 2023-07-15
---
To display this in a friendly manner, I use:
{% assign friendly_date = e | date: "%A %e %B %Y" %}
This displays the weekday & month in English, but our website is in Dutch.
So how can we force this to be in Dutch?
Can you tell Jekyll to localize by default in Dutch?
Can you force it in the CI/CD pipeline perhaps, that would also work (using GitLab)?
I did find some plugins for multilingual websites, but that all seems overcomplicated since our website is in one single language.

Why is salt['slsutil.banner'] returning None whatever arguments I pass?

I'm using saltstack to manage my personal config. In particular I'm managing my ~/.profile programatically. I have various things throughout the setup which append text (mostly env var exports) to it, and they all work exactly as expected. I want to to use slsutil.banner to prepend a banner saying that the file is managed programatically by salt, and not to touch it by hand. So I have in my profile/init.sls:
profile-managed-banner:
file.prepend:
- name: {{ pillar['profile_file'] }}
- text: {{ salt['slsutil.banner']() }}
This should write the default banner to the beginning of the file.
When I then run run salt-call (the setup is masterless. Running salt-call as sudo if that's at all relevant) I get:
ID: profile-managed-banner
Function: file.prepend
Name: /home/modallyFragile/.saltProfile
Result: True
Comment: File /home/modallyFragile/.saltProfile is in correct state
Started: 15:59:07.760790
Duration: 1.757 ms
Changes:
So clearly salt can find and use all the functions (or at least it thinks it can) and the the file is having something prepended to it. If I check the file though, I get this:
None
[ ... further config here]
If I substitute the templating for a string (so - text: some string here) it works as expected (prepends 'some string' to the file). So the probelm is with the templating slsutil.banner then. I've tried passing (various combinations of) arguments explicitly and nothing seems to help.
Why might this be happening and what can I do about it? Failing anything more substantive, what could I do to further diagnose the problem (I'm pretty new to saltstack, is there a particular log I should be checking with all the relevant info, etc. etc.)?
I can't find any issues or problems by searching (github or more generally), so I'm drawing a blank. Literally any suggestions would be really helpful. Thanks!
Adding this as an answer. As per the official documentation:
Create a standardized comment block to include in a templated file.
And this does work inside a templated file.
Just for example files/user-profile.j2:
{{ salt.slsutil.banner() }}
# the default umask is set in /etc/profile; for setting the umask
# for ssh logins, install and configure the libpam-umask package.
umask 022
PATH=$PATH:/my/local/bin
Used in a setup.sls:
create-user-profile:
file.managed:
- name: /home/user1/.profile
- source: salt://files/user-profile.j2
- template: jinja
Will create a file /home/user1/.profile with a default banner at the top and the remaining content as it is.
Then it starts making sense. If you want a banner on file that "it is managed by Salt", then the file should be managed by Salt (as template). Prepending the banner in a remote file, leaving the remaining file contents unmanaged contradicts the purpose of the banner.
So if you want a banner in the file, you can manage the ~/.profile file as a template, and write it to minions as above.
Update:
It might be worth reporting this as an issue if we want a custom banner prepended to a file without managing it.
The problem is that your Jinja, once rendered, produces invalid or incorrect YAML. In this case, what is happening is that the slsutil.banner() function returns several lines that all start with '#'. The YAML renderer considers them comments and throws them out.
The solution is to escape the comment characters so they are properly interpreted by the YAML renderer. Fortunately, Salt comes with a very helpful Jinja filter that does this for you: yaml_encode. Your state works fine with this small change.
profile-managed-banner:
file.prepend:
- name: {{ pillar['profile_file'] }}
- text: {{ salt['slsutil.banner']() | yaml_encode }}

add subfolders to _includes directory in Jekyll

I'm trying to add folders inside the "_includes" directory on Jekyll. It doesn't work. I've tried adding an underscore to the folder but it doesn't work either. What am I doing wrong? I'm using Jekyll 3.7.0
The most useful link I found about it was this one
Here are some screenshots:
And the stacktrace is:
Incremental build: disabled. Enable with --incremental
Generating...
Pagination: Pagination is enabled, but I couldn't find an index.html page to use as the pagination template. Skipping pagination.
Liquid Exception: Could not locate the included file 'sidebar.html' in any of [".../_includes"]. Ensure it exists in one of those directories and, if it is a symlink, does not point outside your site source. in /_layouts/page.html
jekyll 3.7.0 | Error: Could not locate the included file 'sidebar.html' in any of [".../_includes"]. Ensure it exists in one of those directories and, if it is a symlink, does not point outside your site source.
I think I'm supposed to be able to use sub-directories. What am I doing wrong? Thank you in advance!
Apparently, I found the problem. I don't know why but Jekyll is somehow able to parse comments. It detected I had commented a piece of code referencing the old sidebar.html.
As #DavidJaquel mentions in a comment below, HTML comments <!-- --> are not stopping Liquid to parse our page content, so we should be using Liquid syntax:
{% comment %}
...
{% endcomment %}

How to paginate posts by author

What I'm trying to do
Jekyll can use front matter variables like tags and categories and access them with site.tags and site.categories to iterate over them using liquid.
Now my problem is that I can't do this with a custom front matter variable like author (as in site.authors) because Jekyll will not store it in a list format. This makes it very hard to paginate it.
The problem
Every solution I have looked at i.e.
how to handle multiple authors in Jekyll
adding authors to Jekyll
jekyll-author
requires me to hardcode a list of authors to _config.yml or some other .yml (i.e. in _data/authors.yml).
The problem here is that I don't use a fixed list of authors. The authors list needs to get updated when I throw in another post with a front-matter tag author: exampleAuthor or a list of authors (as in multiple authors per post, as currently only possible with categories and tags as well), while the server is running. It works with tags and categories splendidly, but not with custom tags like authors.
The easiest solution would to have a site.authors list to iterate over and just extending it with a ruby plugin.
I haven't found a plugin that provides me with a solution and thinking this was a common problem that I'm probably not the first to have.
What I tried
I then looked at writing my own ruby plugin (Which is hard on it's own because of the lack of documentation. Maybe I'm to dumb to google, but the resources I found where very limited and hardly enough to guide you through the process) but there has to be a reason why this is so hard to do that makes all the existing solutions require hard-coding the author list in a .yml (or .json, but most people go with .yml for some reason).
Doing this is out of the question for me, since I want to only throw in posts with author names in it later on and manipulating a .yml (I am under the impression that .yml-files don't get compiled once the server is started, like _config.yml, correct me if I'm wrong) would be counterproductive because it requires you to restart the server to have them compiled.
Even very advanced plugins like jekyll-paginate-v2 (which I use successfully to paginate posts by tags and categories) don't have a solution to this, as shown by this issue. As per this issue, it is getting recommended to misuse the category variable to paginate by author. In my opinion, that is desperate workaround and too hacky to be considered.
I have found suggestions that it could also be done with collections, but this would again
requiring to hard-coding the author list (again, I don't want that. I don't have a fixed list of authors. All of the author information has to come from the front-matter in the /_posts directory .md files)
As of now I don't see how it can be done with collections.
However I'm open to suggestions.
Edit: I found this dated issue on Jekylls github page which highlights that people are trying to do the same but to no avail.
Has this become viable in the last 4 years?
For someone still looking for a way to
Generate author pages automatically just by dropping author: name to post front matter,
Have pagination on the author pages (a good optimization).
I built a plugin jekyll-auto-authors that works in sync with jekyll-paginate-v2 to enable author auto pages along with pagination.
I wrote this guide and made this video to help with the setup.
The bare minimum setup instructions:
Install the plugin:
group :jekyll_plugins do
# other gems
gem "jekyll-paginate-v2" # reqiured for jekyll-auto-authors to work
gem "jekyll-auto-authors"
end
Enable it:
plugins:
# other plugins
- jekyll-paginate-v2
- jekyll-auto-authors
Make a data file with author data, for example using _data/authors.yml:
johndoe:
name: "John Doe"
bio: "John Doe is a software engineer."
email: "john#example.com"
socials:
github: "john-doe"
twitter: "john_doe"
janedoe:
name: "Jane Doe"
bio: "Jane Doe is a systems engineer."
email: "jane#example.com"
socials:
github: "jane-doe"
twitter: "jane_doe"
Make a layout for the author page, let's say _layout/author.html. Example layout can be taken from the article.
Enable pagination and auto pages for authors in _config.yml file:
pagination:
enabled: true
per_page: 9
permalink: '/page/:num/'
title: ':title - page :num'
sort_field: 'date'
sort_reverse: true
autopages:
enabled: true
# enable auto pages for tags/categories/collections as per need. Disabling for this demo.
tags:
enabled: false
categories:
enabled: false
collections:
enabled: false
authors:
enabled: true # adding false here stops the auto-generation
data: '_data/authors.yml' # Data file with the author details
layouts:
- 'author.html' # We'll define this layout later, will be used for each author
title: 'Posts by :author'
permalink: '/author/:author/'
slugify:
mode: 'default' # choose from [raw, default, pretty, ascii or latin]
cased: true # if true, the uppercase letters in slug will be converted to lowercase ones.
That's the initial setup!
Now drop in the author value in the front matter of posts:
---
# other configs
author: johndoe
---
This will generate a page as defined in the permalink block of the auto pages configuration. If there's pagination enabled, and per_page value is exceeded, the additional pages will be generated in /page/:num/ format.
To render the author values, the plugin exposes page.pagination.author_data value
{% assign author = page.pagination.author_data %}
<!-- Use {{ author.name }} or any such value, as defined inside the data file -->
To show next and previous buttons, you can use this logic that paginator exposes:
{% if paginator.total_pages > 1 %}
<ul>
{% if paginator.previous_page %}
<li>
Newer
</li>
{% endif %}
{% if paginator.next_page %}
<li>
Older
</li>
{% endif %}
</ul>
{% endif %}
The initial setup is overwhelming, but once done you can then just drop in author data inside _data/authors.yml file and add author: value inside post frontmatter and it is fairly easy then!
P.S. I developed this solution for Genics Blog as managing multiple authors got hard. To learn how I've implemented it at Genics, please check out the theme-files repository.
Update
I released v1.0.1 just now, which makes adding the data parameter to author autopage configuration optional.
If data isn't defined, you can still access the author username string with page.pagination.author. You can use it to show the username on the page.
If data is defined, page.pagination.author_data variable is available. This would be a hashmap that has data as defined in the data file.
This means that you just have to:
Add and enable the plugin.
Set up pagination and author pages config.
Make a layout file.
And you can just drop in author: username to post files to generate autopages for them with pagination!
Adding authors to Jekyll posts is easy with collections. Here's a proof of concept for you. Specifically, in this commit I add everything you need for it.
As for your question about pagination, will need to use a pagination plugin (paginate-v2 is good), as I believe the built in pagination only supports the posts collection.

Jekyll variable site.static_files is null

I have an ultra simple Jekyll site that builds without error and Jekyll variables seem to be populated as expected except site.static_files which is null, despite there being a bunch of static files.
Here is a link to the source code. And here is a link to the output.
Edit:
Github pages uses Jekyll 1.5 and static_files are only available since version 2.0.0 (see history)
Edit #2 08-24-14
Github is currently at 2.2.0, so we can use site.static_files