Jekyll on github pages display division result as a fraction - jekyll

I'm building a blog running on jekyll and github pages.
I'm trying to display reading time of each post in this way: (assuming average reading speed is 180 words per minute)
{% for post in paginator.posts %}
{% capture readtime %}{{ post.content | number_of_words | plus:91 | divided_by:180 }}{% endcapture %}
...
{{ readtime }} min. read
{% endfor %}
When I test this code locally everything is fine. For a post with 200 words:
291 / 180 = 1.61(6)
jekyll generates the result:
1 min. read
But when I push this code to github pages, something weird happens. As a result of division I see some fraction which would give me the same result.
So jekyll on github generates the result:
97/60 min. read
In fact:
97 / 60 = 1.61(6)
What should I do to have the same result on github as I have locally?

This seems to be a bug.
This works
{% assign number = 200 %}
{{ number | divided_by: 10 }}
outputs : 20
This doesn't work
{% assign text = "a text with words" %}
{% assign division = text | number_of_words | divided_by: 3 %}
{{ division }}
outputs : 4/3
I have filled bugs in both Jekyll and Liquid repositories and I'll post here as soon as I have informations about the resolution.
Considering that this bug is reproduced on github page and knowing how serious is the github community I bet that we'll soon have this bug tackled.
Edit :
This is a Jekyll bug that is now fixed in master branch. We now have to wait for this commit to be realized in next Jekyll version, I suppose v2.1 and then bubble to Github pages.
Stay tuned.

Related

Get the read time for a specific post in Jekyll Pages from home page/ any other page

I am new to liquid and Jekyll, using the below code to calculate the post read time on the post page. But how should I calculate the reading time on the home page or any other page to display it below a post title?
When I use the same code on the homepage as well, I get different read times on the home page and inside that particular post.
I think I am not able to get the context of that post to count the number of words on some other page. Please suggest.
<span class="reading-time" title="Estimated read time">
{% assign words = content | number_of_words %}
{% if words < 360 %}
1 min
{% else %}
{{ words | divided_by:180 }} mins
{% endif %}
</span>
This is probably happening because, on the home page, you also have some HTML formatting your page.
Strictly speaking, you should indeed strip the HTML out of your content before counting the words, to have an accurate reading time.
So, using the strip_html filter could be a solution:
{% assign words = content | strip_html | number_of_words %}

How do I show a Jekyll Collection item on a specific date? (Liquid syntax issue?)

I guess the most basic question I have is why does using a number at the beginning of a Liquid if statement seem not to work.
This works:
{% if quip.show == "foo" %}
This does not:
{% if quip.show == "1" %}
…but of course there's a lot more to it, here's what I have going on.
I have a Jekyll Collection of little quips I want to show when the site builds on a specific date. A daily status type thing. I setup a collection with the files, made my template, things are marvelous. The issue is making it so only one shows up at a time on the assigned date.
My first thought was to add date: 2020-06-17 to the front matter then run a check to see if that matches today's date but that seems to be conflicting with the Jekyll implied date. So I changed the front matter tag to show: 2020-06-17 just to troubleshoot.
So now I have a for loop that shows all of my quips like this:
{% for quip in site.quips %}
(this is where my HTML is and it loops and renders each collection file perfectly)
{% if quip.show == "2020-06-17" %}
It's working. (this is where the quip HTML will go but I'm isolating it)
{% endif %}
{% endfor %}
That's all manual, the front matter literally says show: 2020-06-17 but obviously I'd like it to automatically get the date, more on that in a bit. …but it doesn't print "It's working.". Oddly, when I change the front matter to show: foo in one of my collection files it does show "It's working". Also, when I change it to just the number 1 it doesn't work. So it seems like Jekyll doesn't like numbers as the first character in a ``==`.
So basically this is what I would like to do:
I have a variable set using this:
{% capture my_var %}{{ "now" | date: "%Y-%m-%d"}}{% endcapture %}
I added this at the top of my page to grab the date (after some other things didn't seem to work)
…this outputs cleanly to 2020-06-17 (as confirmed by calling the variable and looking at the HTML output.)
So then I'd like to put this in my collection loop:
{% if quip.show == "{{ my_var }}" %}
It's Working
{% endif %}
(the quotes around {{ my var }} are tripping me up a bit because the compiler complains if they aren't there, but things don't reliably work without them. No clue there, not the main issue but one that I need to solve).
I mean, the idea is to wrap all of my quip template with this date detector if statement instead of printing "It's working" but that would be a nice proof of concept.
I'm really not opposed to using Jekyll's built in date frontmatter or even the filename -- there's only one per day. I've tried so many things and for some reason I just can't get this to work when I'm using a numeric value in the == statement.
Any help would be much appreciated.
This is happening because the front matter is YAML, and YAML might be more clever than you thought it would.
date: 2020-06-17
Is an actual valid date for YAML.
So if I JSON print such a date defined in a front matter, then, it would show as a date:
{{ quip.date | json }}
2020-06-17 00:00:00 +0200
So if you want to compare dates from the front matter and from the day, you'll have to format both dates.
{% assign now = "now" | date: "%Y-%m-%d" %}
{% assign show = quip.show | date: "%Y-%m-%d" %}
{% if show == now %}
<p class="fresh-from-the-day">quip.title</p>
{% endif %}

Trying to get a collection from a Front Matter value

Hi I'm new to Jekyll and have a basic blog set up. Now my idea is to loop through a collection per blog post to get some fancy HTML going on. Because as far as I'm aware you can't simply add HTML to the markdown.
// config.yml
collections:
- hollowknight
So I've set up a collection named hollowknight and I got a blog post about Hollow Knight.
In the Front Matter of the blog post I have collectionid: 'hollowknight'. And in the Layout I use for blog posts I tried the following:
// post.html
{% capture collection %}site.{{ page.collectionid }}{% endcapture %}
{% for section in collection %}
{{ section.title }}
{% endfor %}
So the idea was to set the collection variable to site.hollowknight as configured in the config and the Front Matter. I set up a single article inside the collection, but it isn't showing up.
Is there any way to realise this?
Edit: https://talk.jekyllrb.com/t/list-collection-with-name-from-front-matter/3619/6
Or is there a way to use paragraphs in the Front Matter, because then I could just use arrays and objects in the Front Matter of the posts to do my magic?
Edit: https://github.com/jekyll/jekyll/issues/246#issuecomment-1639375
Or am I just stretching to far from what Jekyll is supposed to be?
Edit
So I found out I was getting the collection the wrong way, https://talk.jekyllrb.com/t/list-collection-with-name-from-front-matter/3619/6.
{% for section in site.[page.collectionid] %}
{{ section.content | textilize }}
{% endfor %}
The only weird part is, everywhere I see | textilize being used but can't get it to work.
This is the final solutions:
{% for section in site.[page.collectionid] %}
{{ section.content | markdownify }}
{% endfor %}
It's markdownify instead of textilize.
Also I ended up using a Front Matter array with objects to loop through instead of a collection to keep it more organized.

Getting current url from a collection in Jekyll

If I want to get a page's url it's not exactly complicated:
page.url
However, what if I make a collection who's job it is to be used like an include instead of like a page?
If I make such a collection and ask for page.url it gives me the path to the collection instead of the path to the current url.
Is there a way to get the real current URL in Jekyll?
Edit: example
test.md:
---
title: Test page
permalink: /test/
---
Test page
{% for block in site.blocks %}
{% if block.whatever %}
{{ block.content }}
{% endif %}
{% endfor %}
_blocks/block.md:
---
whatever: true
---
{% page.relative_path %}
Got:
Test page
/_blocks/block.md
Expected:
Test page
test.md
I've been using jekyll for a short time and I'm relying on collections to build my first static portfolio site. So far all my attempts when trying to get the path to the current url simply fails.
In order to achieve the desired result, I've used Jekyll Liquid filters.
Here is how you'd get the expected result you as per your question:
test.md:
---
title: Test page
permalink: /test/
---
Test page
{% for block in site.blocks %}
{% if block.whatever %}
{{ block.content }}
{% endif %}
{% endfor %}
_blocks/block.md:
---
whatever: true
---
{{ page.relative_path | replace:'index.html', '' | remove: '_blocks/' | prepend: site.baseurl }}
Output on Test page
Test page
test.md
Update:
Perhaps the following is not the most straightforward method to get the path to the current url, but by defining relative_path: in the front-matter definitions of a document you'd also get the result you expect, of course this is something required on a per page basis.
---
whatever: true
relative_path: test.md
---
{% page.relative_path %}
So in this very specific case
{% page.relative_path %}
should output
test.md
A Jekyll's doc reminder:
As per Jekyll's doc, when you create a collection it becomes available via the site Liquid variable, pretty much like site.posts and site.pages, so you're able to use the available filters in most cases.
I hope it helps!

Strip url to 1 word in Jekyll

I am building a Jekyll blog, and I have come across an issue with permalinks.
My permalinks to blog posts are set like this in
_config.yml:
permalink: /:page/:categories/:title
It outputs like this when navigating to a blog post:
http://localhost:4000/blog/travel/netherlands-trip-prequesites/
I have some static pages in the site: Blog, Travel
The variable page.url outputs this url: /blog/travel/netherlands-trip-prequesites
The code my navigation bar uses to highlight the current page (giving it an "active" class):
{% assign url = page.url|remove:'index.html' %}
{% for nav in site.navigation %}
{% if nav.href == url %}
<li class="active">{{nav.name}}</li>
{% else %}
<li>{{nav.name}}</li>
{% endif %}
{%endfor%}
It works great when navigating to static pages, however when I click a blog post it doesn't highlight the correct static page. (ex.: If i navigate to a blog post with the url /blog/smth/title it should automatically highlight "Blog" in my navigation. When I navigate to /travel/smth/title it should highlight "Travel")
What I'd like to do is to strip down the output of page.url to its first part. For example I'd like to stip the following output
/blog/travel/netherlands-trip-prequesites
down to
/blog/
Why? So I can use it to check which static page it belongs to and highlight it accordigly.
The easiest way is to use split:
{{ page.url | split:'/' | first }}
That will give you the URL content up to the first / character.
I managed to solve it with three filters:
{{ page.url | replace:'/',' ' | truncatewords: 1 | remove:'...' }}
page.url outputs: /page/cat/title, then replace removes the forward slashes producing: page cat title. truncatewords truncates the string down to one word, producing: page... (for some reason three dots gets inserted after the remaining word). After all this I only needed to remove those dots with remove and voilá, my final string: page.
Hope this helps someone.
The answer provided by PeterInvincible was almost perfect, however, there's no need to get piping to remove involved...
The following also will produce desired output
{{ page.url | replace:'/',' ' | truncatewords: 1,"" }}
And to save it to a variable use capture redirection
{{ capture url_base }}{{ page.url | replace:'/',' ' | truncatewords: 1,"" }}{{ endcapture }}
Which can be called via {{url_base}} or mixed with other processing calls.
Also for file paths instead of URLs page.dir works well if you're not using permalink settings for layout, check the gh-pages branch (specifically _includes/nav_gen.html for functional, though rough'round the edges, example) for hosted examples of similar code examples related to liquid syntax and other magic.
Edits & Updates
The above linked script is now live/mostly-working/modular and auto-serving parsed sub-directories viewed currently at the related https://s0ands0.github.io/Perinoid_Pipes/ project site providing examples of recursive parsing of directories. Including and modding for nearly any theme should be possible just check the commented section at the top for currently recognized commands that maybe passed at inclusion call... on that note of inclusion and modularization here's how to turn the above example code for directory parsing into a function
{% comment %}
# Save this to _include/dir_path_by_numbers.html
# import with the following assigning arguments if needed
# {% include dir_path_by_numbers.html directory_argument_path="blog" directory_argument_depth=1 %}
{% endcomment %}
{% assign default_arg_directory_path = page.url %}
{% assign default_arg_directory_depth = 1 %}
{% if directory_argument_path %}
{% assign directory_to_inspect = directory_argument_path %}
{% else %}
{% assign directory_to_inspect = default_arg_directory_path %}
{% endif %}
{% if directory_argument_depth %}
{% assign directory_to_inspect_depth = directory_argument_path %}
{% else %}
{% assign directory_to_inspect_depth = default_arg_directory_depth %}
{% endif %}
{% comment %}
# Defaults read and assigned now to output results
{% endcomment %}
{{ directory_to_inspect_depth | replace:'/',' ' | truncatewords: directory_to_inspect_depth,"" | remove_first: '/' | replace:' ','/' }}
The above should output directory path lengths of whatever size desired and maybe included as shown previously or if feeling adventurous try what's shown below; though for looping and recursive features look to the linked script for how I've worked around stack size restrictions.
{% capture dir_sub_path %}{{include dir_path_by_numbers.html directory_argument_path="blog" directory_argument_depth=1}}{% endcapture %}
Note above is just speculation, untested, and maybe more buggy than scripts tested and hosted publicly... in other words inspiration.
Simplest way would be using
if page.url contains
example:
<li class="{% if page.url contains '/docs/' %}current{% endif %}">
Docs