I need to display the following Jekyll front-matter in two different formats: military format for a JS library and standard format for display. It seems to be way more complicated than it should be. Any ideas? I'm open to changing the format of the yaml as well if there's a better way to specify it.
---
layout: event
title: Big Air Trampoline Park Field Trip
start: "13:00"
end: "15:00"
I ended up creating an include for this, hopefully someone will suggest a better approach:
{% assign times = include.param | split: ':' %}
{% assign h = times[0] | modulo:12 %}
{% assign hh = times[0] | modulo:24 %}
{% if h == 0 %}12{% else %}{{h}}{% endif %}:{{times[1]}}
{% if h == hh %}am{% else %}pm{% endif %}
I call it like this:
{% include display_time.html param=event.start %}
Related
In my Jinja template, model.DataType value can be user defined or built in. My requirenement is if model.DataType start with the three letters ARR, then do a specific operation.
Example of values:
ARRstruct124
ARR_int123
ARR123123
CCHAR
UUINT
etc.
{% set evenDataType = model.eventDataType %}
{%if evenDataType | regex_match('^ARR', ignorecase=False) %}
// do the operation
{%else%}
// do the operation
{% endif %}
With this template, I am getting the error
{%if evenDataType | regex_match('^ARR', ignorecase=False) %}
jinja2.exceptions.TemplateAssertionError: no filter named 'regex_match'
There is indeed no regex_match filter in the Jinja builtin filters. You might have found some examples using it, but this is an additional filter provided by Ansible, so it won't work outside of Ansible.
This said, your requirement does not need a regex to be fulfilled, you can use the startswith() method of a Python string.
So, you template should be:
{% set evenDataType = model.eventDataType %}
{% if evenDataType.startswith('ARR') %}
`evenDataType` starts with 'ARR'
{% else %}
`evenDataType` does not starts with 'ARR'
{% endif %}
I am attempting to create a related posts section. I have used loops and conditionals to achieve this before, but I wanted a more efficient and cleaner method. I used include variables to achieve a similar result, but for whatever reason if I attempt to use a post's front matter, I get an empty result. Example:
---
categories:
- Featured
---
{% assign featured-posts = site.posts | where: "categories", page.categories %}
{% assign featured-posts = site.posts | where: "categories", page.categories %}
where filter looks for a string in a string or in an array.
Here page.categories is an array to look for in an array. This will return an empty array.
My shortest way to get related posts with at least one common category.
{% assign related-posts = "" | split: "" %}
{% for c in page.categories %}
{% assign related-posts = related-posts | concat: site.categories[c] | uniq %}
{% endfor %}
I have a collection in Jekyll which I want to sort. Sorting by title is easy of course.
<ul>
{% for note in site.note | sort: "title" %}
<li>{{note.path | git_mod }}: {{ note. title }}</li>
{% endfor %}
</ul>
I want to sort by date. But since collections don't have a date, I have a custom Liquid filter which takes the path of the item, and gets its last modified time in Git. You can see that in the code above, where I pass the path to git_mod. I can verify that this works, because when I print out the list, I get the correct last modified times, and it is a full date. (In practice, I also pass it to date_as_string.)
But I can't sort by that value because Liquid doesn't know about it, since it is a value already in each item in the site.note collection. How can I sort by that value? I was thinking something like this, but it doesn't work:
<ul>
{% for note in site.note | sort: path | date_mod %}
<li>{{note.path | git_mod }}: {{ note. title }}</li>
{% endfor %}
</ul>
I've also tried variants like: {% for note in site.note | sort: (note.path | git_mod) %}
None of these throw an error, but none of them work either.
This is a case where you can use Jekyll hooks.
You can create a _plugins/git_mod.rb
Jekyll::Hooks.register :documents, :pre_render do |document, payload|
# as posts are also a collection only search Note collection
isNote = document.collection.label == 'note'
# compute anything here
git_mod = ...
# inject your value in dacument's data
document.data['git_mod'] = git_mod
end
You then will be able to sort by git_mod key
{% assign sortedNotes = site.note | sort: 'git_mod' %}
{% for note in sortedNotes %}
....
Note that you cannot sort in a for loop. You first need to sort in an assign, then loop.
In my markdown header I have added a custom line:
---
layout: docs
title: "My title"
date: 2015-09-18 22:40:58
permalink: /some/url/
custom: valueA valueB <---
---
And I managed to write the following template which processes these values:
{% capture custo %}{{page.custom}}{% endcapture %}
{% assign cust = custo|split: %}
{% for cus in cust%}
<code>{{ cus }}</code>
{% endfor %}
However, this seems much too complex to me. I have tried
moving the assignment directly into for, which compiles but just outputs everything as one value, not as separate ones
{% for cus in custo|split: %}
getting rid of capture, but I get undefined method 'split' for nil:NilClass doing
{% assign cust = page.custom|split: %}
Can my template be simplified or does it need to be that way? Or is it even the wrong approach?
Doing more research on this, I found out that the header is not only a header but actually YML. Therefore I can do
---
layout: docs
title: "My title"
date: 2015-09-18 22:40:58
permalink: /some/url/
custom:
1: valueA
2: valueB
---
and then use an ordinary loop
{% for cus in page.custom %}
<code>{{ cus[1] }}</code>
{% endfor %}
I'm using jekyll-bootstrap to maintain a blog on GitHub.
I'd like to have a sorted tags_list. The tag with the most posts comes first. Then I can have a display that shows the first tags with bigger font-size and last tags with smaller font-size. And I also want a splice function.
If in python/Jinja2, I'd like some code like this:
{% for tag in sorted_tags[:10] %}
<li style="font-size:{{ tag.count }}px;">{{ tag.name }}</li>
{% endfor %}
What's the equivalent implementation in ruby/jekyll?
This is how I'm sorting by the number of posts in a tag (descending), without any plugins (i.e. GitHub Pages compatible).
It also works when your tag names contain spaces; only , and : are forbidden characters (but you can easily change those).
{% capture counts_with_tags_string %}{% for tag in site.tags %}{{ tag[1] | size | prepend:"000000" | slice:-6,6 }}:{{ tag[0] }}{% unless forloop.last %},{% endunless %}{% endfor %}{% endcapture %}
{% assign counts_with_tags = counts_with_tags_string | split:"," | sort | reverse %}
<ol>
{% for count_with_tag in counts_with_tags %}
{% assign tag = count_with_tag | split:":" | last %}
{% assign count = site.tags[tag] | size %}
<li>{{ tag }} ({{ count }})</li>
{% endfor %}
</ol>
It's super gross. What it does:
counts_with_tags_string is set to a string like 000005:first_tag,000010:second_tag,000002:third_tag. The zero-padded numbers are generated using the filter chain | prepend:"000000" | slice:-6,6.
This is split on commas and sorted lexicographically, which works because of the zero padding. The result is assigned to counts_with_tags.
Finally, we iterate over the elements and split each on : to find the original tag name. We could find the count in the same way, but because it's zero padded, it's easier to look it up using site.tags[tag] | size instead.
I thought that the tags array is sorted. Assuming so, you can do this:
{% for tag in site.tags %}
<li style="font-size: {{ tag[1].size }}px">{{ tag[0] }}</li>
{% endfor %}
That feels a little hacky, but it should work. Unfortunately, Liquid doesn't currently allow you to sort arrays within your templates. If you want to do any sorting on the array, you'd probably have to write a plugin to do so - it shouldn't be too complex. In fact, there's an existing plugin for sorting accessors that may do it: https://github.com/krazykylep/Jekyll-Sort
I only needed to do this in one place, on the page where my list of Tags was listed, so I wrote it as a Jekyll filter:
tag_index.html
<h2>Posts by Tag</h2>
<ul class="tags-list">
{{ site.tags | render_tags_list }}
</ul>
_plugins/filters.rb
module Jekyll
module Filters
def render_tags_list(tags)
sorted_tags = tags.keys.sort_by! { |tag| tag.downcase }
str = ''
sorted_tags.each { |tag|
str << '<li>' + tags[tag].size.to_s + ' - ' + tag + '</li>'
}
str
end
end
end
You could certainly just allow the filter to return sorted_tags above if you wanted to keep a better separation between "view" logic and programming logic, but my case was very simple. Trying to re-access a hash value by a specific key using Liquid templating wasn't a very concise process, or maybe I was just doing it wrong, but was much easier in Ruby.
I'm hosting my blog on github and wanted a solution to sorting a tag list that did not involve any jekyll plugins since Github doesn't allow for custom plugins (jekyll bootstrap attempts this as well). My post here doesn't really answer the question since I sort by tag name, and NOT by size. You can adapt this method to output the tag size as well in the string and then do some fancier spliting to get a different sort order (but it will be messy)
I was able to do this with the following code:
{% capture tagString %}{% for tag in site.tags %}{{ tag[0] }}{% unless forloop.last %}|{% endunless %}{% endfor %}{% endcapture %}
{% assign tags = tagString | split: '|' | sort: 'downcase' %}
<div id="cloud">
{% for tag in tags %}
{% assign number = site.tags[tag].size %}
{% assign slug = tag | downcase | replace: ' ', '_' %}
<span class="{% if number == 1 %}small{% elsif number <= 5 %}medium{% elsif number <= 10 %}large{% else %}huge{% endif %}">
{{ tag | downcase }}
</span>
{% endfor %}
</div>
It's kind of odd since I capture a string of tags (using | as separator) and then use that to create an array. After that point (in the loop) I can refer to the tag as tag and the list of sites that use that tag as site.tags[tag].
I use this on my blog:
https://github.com/kelsin/kelsin.github.io/blob/master/tags/index.html
The rest of the code is just how I've chosen to make a tag cloud on my tag page. Hope this helps someone else looking for a solution (without plugins)!