jekyll find filename portion of page url - jekyll

I need to extract the filename portion of the page url, that is from a post saved in 2011-12-31-new-years-eve-is-awesome.md I would like to just the part new-years-eve-is-awesome .
Unfortunately post_url contains also the directory tree 2011/12/31/
This page https://jekyllrb.com/docs/permalinks/ seems to suggest that defining
---
shorttitle: :title
---
in the front matter should work but that produces an empty string from {{ post.shorttitle }}

Here is my solution so far. Perhaps there is a variable left in the code but it's not documented, therefore I just filter the post URL:
{% assign spliturl = post.url | split: '/' %}
{% assign postname = spliturl[4] | replace: '.html', '' %}
{{ postname }}

Related

Jekyll - Evaluate a string before assignment

I need to capture a string into a variable tag, then use this variable in site.tags.tag. The code is:
{% capture tag %}programming{% endcapture %}
{{ tag }}
{%- assign titles = site.tags.tag | map: "title" -%}
{{ titles }}
This code only prints prints:
programming
But if I replace site.tags.tag with either site.tags.programming or site.tags.'programming' I get the desired output:
programming
title1 title2
Is there a way to evaluate the variable tag before the assignment? After reading a similar question I tried site.tags.{{tag}} but it didn't work.
site.tags[tag] might be what you're looking for.

How to pass variables from layout to page in Liquid?

I try to create a global variable in layout and call it in pages
E.g:
<!-- _layouts/post.html -->
{% assign filename = page.url | split: '/' | last | replace: '.html', '' %}
{{ content }}
in post page:
<!-- SomePage.html -->
<h1>Page Name: {{ filename }}</h1> //-> # Page Name: SomePage
The page name should be printed but I do not know how to do it
Any ideas?
I guess you are misusing Jekyll as it is not suppose to work like that. It should be used other way around. Templates are designed to show pages with variables, so that you follow many to one relation pages in templates.
The idea is to put repetitive part of your pages in your layout. So you should have your layout defined like this:
<!-- _layouts/post.html -->
{% assign filename = page.url | split: '/' | last | replace: '.html', '' %}
<h1>{{ filename }}</h1>
{{ content }}
Then you don't have to write that part in your every page, but it is handled automatically for you.

Why does this jekyll template not work?

Short Version:
Why does the following code not produce an output when navbox.next_article is the string '2018-01-05-man-command'?!
{% capture np %} {{ site.posts | where:"post","navbox.next_article contains post.title" }} {% endcapture %}
The next post is {{ np.title }}
Details
My post 2018-01-05-man-command.md has a YAML front matter:
---
layout : post
title : 'Man Command'
tags : [RHCSA, RHCSA_mod, Using Essential Tools, Man Command]
categories: [RHCSA]
navbox:
# prev_article:
next_article: 2018-01-05-understanding-globbing-and-wildcards
---
This is accessed by the _includes/post.html file through:
{% unless include.excerpt %}
{{ post.content }}
{% include navbox.html navbox=page.navbox %}
{% endunless %}
This is used by the _layout/post.html which sets the layout for the post:
{% include post.html post=page link_title=false %}
My navbox.html contains:
{% assign navbox = include.navbox %}
{% capture np %} {{ site.posts | where:"post","navbox.next_article contains post.title" }} {% endcapture %}
The next post is {{ np.title }}
However, all I get when I run bundle exec jekyll serve is:
The next post is
Why does that line not work? I'm new to jekyll so it's possible I've made a blunder somewhere that's intuitive to most. Please tell me what I can fix.
I believe that the capture tag only captures strings, not posts. See here for more info.
I'm not convinced that a where filter supports the contains syntax you're using. See here for more info.
On top of that, where returns an array. You have to get the first item from that array.
You need to fix these issues. Use an assign instead of a capture to store a post. And change your where filter to not use the contains syntax, which isn't valid. (Unless it's been added since the issue I just linked.)
Here is how I've done it:
{% assign post = site.posts | where:"url", targetUrl | first %}

Output link to "parent page"?

I have a collection _colletion. In there is a file _collection/path/topic.md and a folder _collection/path/topic/ that includes lots of .md files with content. The permalinks for these files are /path/topic and /path/topic/file-x - so a parent page with a folder with the same name with multiple random pages in it.
Now I want to output a link to /path/topic in all these .md files with the title of topic.md as link text:
---
title: This is the page title defined in topic.md
---
should become
This is the page title defined in topic.md
How do I do that most easily?
Can I somehow access the folder name topic of the .md files and use this to read topic.md and output it's title and also generate a link to it?
My current manual "solution" (or workaround):
Add a parent entry to the frontmatter of all pages in /topic/ that contains the title and relative URL for the topic.md:
parent: ['Topic Title', '../topic']
In the template of the pages:
{% if page.parent %}
<p>« {{ page.parent[0] }}</p>
{% endif %}
Works, but of course duplicates this information n times and has to be maintained manually.
How about this (option 1)?
{% assign pageurl_array = page.url | split: "/" %}
{% assign path = pageurl_array[0] %}
{% assign topic = pageurl_array[1] %}
<p>« <a href="{{ path }}/{{ topic }}/{{ topic }}.html">
{{ topic | capitalize | replace: "-", " " }}
</a></p>
If you do not mind crazy build times, do this (option 2):
{% assign pageurl_array = page.url | split: "/" %}
{% assign path = pageurl_array[0] %}
{% assign topic = pageurl_array[1] %}
{% capture parent_url %}{{ path }}/{{ topic }}/{{ topic }}.html{% endcapture %}
<p>« <a href="{{ parent_url }}">
{% for i in site.pages %}
{% if i.url == parent_url %}
{{ i.title }}
{% endif %}
{% endfor %}
</a></p>
I would go for the first option (much faster) and use this javascript to get the capitals and special characters right:
$('a').each( function() {
var str = $(this).html();
str = str.replace('Topic from url', 'Topic from URL');
$(this).html(str);
});
I admit that the javascript solution is far from pretty, but it solves the build time problem pretty well.
Note that Jekyll is pretty slow. I would advice you to dig into Hugo if you require faster build times.
During discussion in the comments on my question and the other answers I noticed that what I wanted to build was actually a very common thing: A breadcrumb navigation! Just a very "small" one, with only one level.
With this newfound knowledge I could google "breadcrumb" plugins for Jekyll:
This solution uses the path of the page to extract the "crumbs":
https://www.mikestowe.com/blog/2017/08/adding-breadcrumbs-in-jekyll.php
It uses the folder name for the link text.
Another similar implementation:
https://stackoverflow.com/a/9633517/252627
Another one:
https://stackoverflow.com/a/37448941/252627
So no title link text in all of these.
This solution actually reads the page title, but can also read breadcrumb frontmatter from the pages, and uses these as link text:
https://github.com/comsysto/jekyll-breadcrumb-for-github-pages/
https://comsysto.com/blog-post/automatic-breadcrumb-for-jekyll-on-github-pages
https://gist.github.com/csgruenebe/8f7beef9858c1b8625d6
This one might be a valid solution.
There are also real plugins (that unfortunately don't work with Github Pages):
https://github.com/git-no/jekyll-breadcrumbs
My solution, based on JoostS code:
{% assign url = page.url | remove:'.html' | split: "/" %}
{% assign path = url | pop %}
{% if path.size == 1 %}
<a class="back" href="/home/">home</a>
{% else %}
<a class="back" href="/{% for dir in path offset: 1 %}{{ dir | append: "/" }}{% endfor %}">{{ path | last }}</a>
{% endif %}```

Liquid Template: Append variable to data object

I have the following structure in my Jekyll app:
_data/
test.json
items/
test/
index.html
I am using the following to grab just the name of the ending folder name of my item:
{% assign listing = {{ page.url | remove: 'items/' | replace:'/',' ' | truncatewords: 1 | remove:'...' | escape }} %}
What I'm then trying to do is access the data file which the matching folder name from the _data directory.
I've gotten it to:
{{ site.data.{{ listing }} }}
which allows me to see the data, but I can't actually go inside the JSON object to grab a specific item, like {{ site.data.{{ listing }}.test }} does not work. Any help would be greatly appreciated. Thanks!
Use some brackets like this :
{% assign datas = site.data[{{listing}}] %}
You can now access datas.test.