Listing all the key-value properites in site.pages - jekyll

On my blog, I have a debug page which lists several things, including all the properties for each page in site.pages, like so:
{%- for page in site.pages -%}
<strong>{{ page.path }}:</strong><br>
<table>
{% for key_value in page %}
{% if key_value[0] == "content" %}
<tr><td>content</td><td>[{{ key_value[1] | size }} characters]</td></tr>
{% else %}
<tr><td>{{ key_value[0] }}</td><td><span>{{ key_value[1] }}</span></td></tr>
{% endif %}
{% endfor %}
</table>
{%- endfor -%}
This produces output like this:
So far, so good.
Now, I want to do the exact same thing with site.posts, but it doesn't work.
In particular, key_value[0] and key_value[1] don't have any value. The iteration does produce something, but it is not a key an value.
For example, the following produces a list of key names:
{%- for pp in site.posts -%}
<strong>{{ pp.path }}:</strong><br>
{% for kv in pp %}
{% capture cap %}{{ kv }}{% endcapture %}
<div>{{ cap }}</div>
{% endfor %}
<br>
{%- endfor -%}
like so:
I can't seem to get the content of the properties in a generic way, however. I guess the type of the things in the site.posts is not the same as sites.pages, in particular not a simple liquid dictionary.
I've tried messing around with to_liquid mentioned here without luck.

Related

Jekyll nested include with for loop

I'd like to use a {% for %} loop in an included file, to avoid repeating logic to create the loop array (it's an assign with multiple where_exps).
But I'd like to use different content depending on where I include the loop, so sometimes I will do this:
{% for i in a %}
<li>{{ i.name }}</li>
{% endfor %}
and sometimes:
{% for i in a %}
<loc>{{ i.url }}</loc>
{% endfor %}
How can I achieve this? So far I have to put each of the inner contents in their own template, so I would have files like below, but I'd like to avoid the extra template files, and just keep that content in the appropriate main file:
html_template.html:
<li>{{ i.name }}</li>
xml_template.xml:
<loc>{{ i.url }}</loc>
page_loop.html:
{% assign a = "logic I don't want to repeat" %}
{% for i in a %}
{% include {{ include.inner_template }} %}
{% endfor %}
html_main.html:
{% include page_loop.html inner_template="html_template.html" %}
xml_main.xml:
{% include page_loop.html inner_template="xml_template.xml" %}
It would probably be another more elegant (?) solution developing a plugin, but quickly modifying your code, in _includes/page_loop.html:
{% assign a = "something" %}
{% for i in a %}
{%if include.type == "name"%}
<li>{{ i.name }}</li>
{%else if include.type == "url"%}
<loc>{{ i.url }}</loc>
{%endif %}
{% endfor %}
Then each time you include page_loop.html pass an additional parameter specifying which type of output you want:
{% include page_loop.html type="name" %}
or
{% include page_loop.html type="url" %}

How to get content from another page in Jekyll?

I want to display some pages of my Jekyll website in my Home page. How can I accomplish this?
Currently I am trying to do the following:
{% assign sorted = (site.pages | sort: 'order_home') %}
{% for my_page in sorted %}
{% if my_page.order_home %}
{{ my_page }}
{% endif %}
{% endfor %}
However, what happens is that content is exhibited in the following form:
{"layout"=>"page", "title"=>"Blog", "permalink"=>"/blog/", "comments"=>false, "order_nav"=>4, "order_home"=>3, "content"=>"
\n{% for category in site.categories reversed %}\n
\n {% capture category_name %}{{ category | first }}{% endcapture %}\n
\n\n
{{ category_name }}
\n \n {% for post in site.categories[category_name] %}\n
\n
{{post.title}}
\n
\n {% endfor %}\n
\n{% endfor %}\n
\n", "dir"=>"/blog/", "name"=>"posts.md", "path"=>"posts.md", "url"=>"/blog/"}
I would like to make the content appear as if it was the rendered page itself, with the {{...}} blocks correctly processed. Any idea on how to do this?
Thanks!
Just add .content to my_page. This results in the following code:
{% assign sorted = (site.pages | sort: 'order_home') %}
{% for my_page in sorted %}
{% if my_page.order_home %}
{{ my_page.content }}
{% endif %}
{% endfor %}

Liquid markup sorting the output

I am trying to display a list of all articles using liquid markup. I've got this code which displays them properly, however I want to be able to sort by the modified date descending (most recent article on top). How can this be accomplished?
I was thinking that perhaps I need to create a new array with all articles in it and then sort that, but I am not sure how to do that. Also note that I want to sort ALL of my articles by date, not just within each folder.
{% for category in portal.solution_categories %}
{% if category.folders_count > 0 %}
{% for folder in category.folders %}
{% for article in folder.articles %}
{{ article.title }} - {{ article.modified_on | short_day_with_time }} <br>
{% endfor %}
{% endfor %}
{% endif %}
{% endfor %}
Thanks!
You can use a variable to sort the list of articles and then iterate that variable.
{% for category in portal.solution_categories %}
{% if category.folders_count > 0 %}
{% for folder in category.folders %}
{% assign sorted = (folder.articles | sort:date) %}
{% for article in sorted %}
{{ article.title }} - {{ article.modified_on | short_day_with_time }} <br>
{% endfor %}
{% endfor %}
{% endif %}
{% endfor %}

How to check if a value is present in a list?

I would like to get the list of posts having a specific tag in their front matter (*)
I tried the code below, which iterates over all the tags of the current post pages (the current tag is t), then iterates over all the posts (p) to check if they have this tag (and just outputs the title, for debugging reasons):
{% for t in page.tags %}
{% for p in site.posts %}
{% if t in p.tags %}
{{ p.title }}
{% endif %}
{% endfor %}
{% endfor %}
The line {% if t in p.tags %} seems to fail (I come form a Python background so I gave it a try) and I cannot find the in operator in liquid. Does it exits?
(*) I am mentioning what I want to achieve in case there is a more straightforward way to do that but I am still interested in the general question.
Following your example it can be done with the contains tag:
contains can also check for the presence of a string in an array of
strings.
{% if product.tags contains "outdoor" %}
This product is great for
using outdoors!
{% endif %}
So to get the list of posts having a specific tag in their front matter (in this case the posts with the tag mytag):
{% assign posts_with_mytag = site.posts | where_exp:"item",
"item.tags contains 'mytag'" %}
{% for post in posts_with_mytag %}
{{post.title}}
{% endfor %}
Following-up on #maracuny's answer, the corrected code from my question for completeness:
{% for t in page.tags %}
{% for p in site.posts %}
{% if p.tags contains t %}
{{ p.title }}
{% endif %}
{% endfor %}
{% endfor %}

include_relative post.path jekyll

I'm trying to put a number of related posts on a single page. The problem is that the included posts are all textile pages, using some {% highlight %} tags. When I try to include then via post.content, they don't get textilized (e.g, I see "{% highlight..." on the page).
I've tried a few different things:
This never gets textilized:
{% for post in site.tags.my_tag %}
{{ post.content | textilize }}
{% endfor %}
This (based on http://nateeagle.com/2011/08/31/jekyll-not-parsing-includes/) returns no content:
{% for post in site.tags.apidocs %}
{% capture included_post %}
{{% include_relative post.path %}}
{% endcapture %}
{{ included_post | textilize }}
{% endfor %}
Any ideas?
Bradley
Try
{% include_relative {{post.path}} %}