Jekyll equivalent of Hugo's "with" - jekyll

In Hugo, one can use with to avoid repeating variable names.
{{ with .Site.Params.foo }}
<p>{{ .bar }}</p>
{{ end }}
This is almost equivalent to
<p>{{ .Site.Params.foo.bar }}</p>
What would be its equivalent in Jekyll?
My try:
{%- assign tempvar = .Site.Params.foo -%}
<p>{{ tempvar.bar }}</p>

This should work:
{%- assign tempvar = site.foo -%}
<p>{{ tempvar.bar }}</p>

Based on your follow up comment to the question, it looks like you are seeking a way to check if a variable only contains a desired key:value pair. Here is one way to check if a variable contains only the desired key.
{% assign numOfKeys = page | size %}
{% assign sizeOfGold = page.gold | size %}
<!-- Print out the page object for debugging purposes -->
{{ page | inspect }}
{% if numOfKeys == 1 %}
{% if sizeOfGold > 0 %}
{% for x in page.gold %}
<!-- Logic -->
{% endfor %}
{% endif %}
{% endif %}

Related

How to use a Jinja variable inside of sphinx ref directive or head tag?

I'm using sphinx and auto-summary to create my documentation. However, for each module a I want to generate customized list of references. However, to do that, I need to pass the objname to ref directive. How can I achieve that?
{{ fullname | escape | underline}}
.. automodule:: {{ fullname }}
Items
-----
{% block classestab %}
{% if classes %}
{% for objname in classes %}
- :ref:` {{objname}} <{{objname}}>`_ // doesn't work
{%- endfor %}
{% endif %}
{% endblock %}
I've also trying to use a jinja variable to create headings for my documentation. However I don't know to achieve this. The code below will not work of course
{% block table %}
{% if classes %}
{% for objname in classes %}
{{objname}}
===========
{%- endfor %}
{% endif %}
{% endblock %}

Listing all the key-value properites in site.pages

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.

In my Jekyll include file how do I get the markdown for a post?

Is there a way to get ahold of a posts markdown in an include file?
My include file has this code: {{workingPost.content}}
When I include this in a markdown file I get the HTML. I pass that to another include that expects markdown and instead this is passing HTML.
Is there a way to access the markdown instead of the HTML for the post?
As requested here are the code files. What they do is get a featured post for the right hand side of the site like this. In that link the code is static HTML. I want to update it to make it dynamic via the following code. I already have the first image grabbing code working when it receives markdown. I'd like to use that code to grab the first image from the post here too, but by the time the code gets it the markdown has been turned into HTML.
Include file timely.html
{% assign workingPost = nil %}
{% for page in site.posts %}
{% if page.title == 'We Convert All Dollars To Bitcoin' %}
{% assign workingPost = page %}
{% endif %}
{% endfor %}
<div class="panel panel-default">
<div class="panel-heading text-center">
<h3 class="panel-title">Popular</h3>
</div>
<div class="panel-body">
<a href="{{workingPost.url}}">
{% assign workingPostContent = workingPost.content %}
{% include first-post-image-src2.html param=workingPostContent %}
<img src="{% include first-post-image-src2.html param=workingPostContent %}" alt="{{workingPost.title}}">
<p>{{workingPost.excerpt}}</p>
<p class="btn btn-md btn-success" role="button">READ POST</p>
<br>
<br>
</a>
</div>
</div>
include file first-post-image-src2.html
{% capture result %}
{% assign htmlAgain= 'empty' %}
{% assign foundImageAgain = 0 %}
{% assign imagesAgain = include.param | split:"![" %}
{% for imageAgain in imagesAgain %}
{% if imageAgain contains '](' %}
{% if foundImageAgain == 0 %}
{% assign htmlAgain = imageAgain | split:"](" %}
{% assign htmlAgain = htmlAgain[1] %}
{% assign htmlAgain = htmlAgain | split:")" | first %}
{% assign foundImageAgain = 1 %}
{% endif %}
{% endif %}
{% endfor %}
{%endcapture%}{{site.url}}{{htmlAgain|strip}}
Yes translating from markdown to html is one of the first thinks made when Jekyll build. So, no way to grab the markdown in an include. The only way to bypass this limitation is to do it with a plugin. But it's not the subject.
Now back to you code. It's to complicated and fragile.
Jekyll has all the needed functionalities to do what you want to do. Don't try to do data processing with liquid. Use the tags and filters and you will not have to fear a Gem upgrade that will break your site and bring you to a really difficult debugging.
eg : somewhere in your code, you're processing a string with a | split:"/>" filter that rely on how kramdown is rendering ìmg tag. If one day they decide to remove this useless closing slash, your code will break.
The way you can go : put all the datas in your post, in the simplest form possible, and then use them with simple Jekyll tags and filter.
The idea is to use yaml Front Matter custom variables and Jekyll post or page excerpt functionalities.
In your _config.yml, define a new excerpt separator :
excerpt_separator: "<!-- excerpt end -->" # default is "\n\n" = two new lines
In all your posts :
---
excerpt_image_src: "/images/dollarsToBitcoins.jpg"
excerpt_image_alt: "Bitcoin Bulls converts dollars to bitcoins."
popular : true # I'll explain that latter
---
Bitcoin Bulls customers pay in USD but those dollars are all converted to bitcoin.
<!-- excerpt end -->
Bulls, I'm excited to announce...
In default.html
{% if page.is_post %}
<link rel="alternate" type="application/atom+xml" title="{{ site.name }} — Atom" href="{{ site.url }}/blog/feed.atom" />
<meta property="og:image" content="{{ site.url }}{{ page.excerpt_image_src | strip_newlines }}" />
<meta property="og:description" content="{{page.excerpt}}" />
{% else %}
In _includes/timely.html :
<div class="panel panel-default">
<div class="panel-heading text-center">
<h3 class="panel-title">Popular</h3>
</div>
{% for p in site.posts %}{% if p.popular == true %}
<div class="panel-body">
<a href="{{p.url}}">
<img src="{{p.excerpt_image_src}}" alt="{{excerpt_image_alt}}">
<p>{{p.excerpt}}</p>
<p class="btn btn-md btn-success" role="button">READ POST</p><br><br>
</a>
</div>
{% endif %}{% endfor %}
</div>
Note the {% if p.popular == true %} that filter posts with a front matter variable popular: true.
In _includes/blog-post.html :
<li>
<a href="{{ post.url }}">
<p>{{post.date | date: "%B %d, %Y" }}</p>
<img src="{{post.excerpt_image_src}}" alt="{{post.excerpt_image_alt}}">
<!-- No need to wrap excerpt in <p> tag, Jekyll does it.
If you want to put your own tag :
<div>{{ post.excerpt | strip_html }}</div> -->
{{ post.excerpt }}
<p class="btn btn-md btn-success" role="button">READ POST</p><br><br>
</a>
</li>
In _layouts/post.html :
<h1>{{page.title}}</h1>
<div style="color:#666;">by David Smith on {{page.date | date: "%B %d, %Y" }}</div>
{% if page.excerpt_image_src %}
<p><img src="{{page.excerpt_image_src}}" alt="{{page.excerpt_image_alt}}"></p>
{% endif %}
{{ page.content | remove: page.excerpt | markdownify }}
<br>
As you're not actually displaying post excerpt in post page, it's {{ page.content | remove: page.excerpt | markdownify }}. If you want to display excerpt it's : {{ page.content | markdownify }}
I don't know why but page.content return mardown and not html, so the filter | markdownify to transform markdown to html.
Et voila ! Long live Bitcoinbulls !
The markdown isn't available. It is rendered earlier and not available.
From this answer it sounds like the markdown isn't available.
In my case I made my first-post-image-src2.html include handle the case where it gets markdown or HTML like this:
{% capture result %}
{% assign htmlAgain= 'empty' %}
{% assign foundImageAgain = 0 %}
{% if include.param contains '![' %}
{% assign imagesAgain = include.param | split:"![" %}
{% for imageAgain in imagesAgain %}
{% if imageAgain contains '](' %}
{% if foundImageAgain == 0 %}
{% assign htmlAgain = imageAgain | split:"](" %}
{% assign htmlAgain = htmlAgain[1] %}
{% assign htmlAgain = htmlAgain | split:")" | first %}
{% assign foundImageAgain = 1 %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% if foundImageAgain ==0 %}
{% assign imagesAgain = include.param | split:"<img" %}
{% for imageAgain in imagesAgain %}
{% if imageAgain contains 'src="' %}
{% if foundImageAgain == 0 %}
{% assign htmlAgain = imageAgain | split:'src="' %}
{% assign htmlAgain = htmlAgain[1] %}
{% assign htmlAgain = htmlAgain | split:'"' | first %}
{% assign foundImageAgain = 1 %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{%endcapture%}{{site.url}}{{htmlAgain|strip}}

Output Markup Inside of Tag Markup

My question is how can I rewrite this output markup (which does work)
{{ forloop.index0 | modulo:4 }}
so that it can be used inside of a tag markup (which doesn't work).
{% if forloop.index0 | modulo:4 == 0 %}
This is what ended up working (David helped me get started).
{% assign mod = forloop.index0 | modulo:4 %}
{% if mod == 0 %}
<!-- Do stuff -->
{% endif %}
Edited answer :
For this example I use a custom array, but the array can be site.pages or site.posts or site.data.somedatas.
{% assign words = "zero,one,two,three,four,five" | split: ',' %}
Then process the words array :
<ol>
{% for word in words %}
{% comment %} Here we assign the filtered array to myTest {% endcomment %}
{% assign myTest = forloop.index0 | modulo:4 %}
{% comment %} then we process the filtered array {% endcomment %}
{% if myTest == 0 %}
<li>
<h4>Test passing (index = {{ forloop.index0 }} >> modulo = {{ myTest }})</h4>
</li>
{% else %}
<li>
<h4>test NOT passing (index = {{ forloop.index0 }} >> modulo = {{ myTest }})</h4>
</li>
{% endif %}
{% endfor %}
</ol>
This works on Jekyll 2.2.0, the current Github pages version.

Jekyll Loop breaks on second iteration

I'm looping through two products - on the post view page I pull in a secondary post (in the example, a related recipe) which parses just fine on the first product page - on the second product page just {{ post.content }} won't parse. I can hack it with {{ post.content | markdownify }} - but I'd like to know why it's breaking. Here's the relevant code:
{% for post in site.categories.recipe %}
{% if post.products contains page.title and post.featured %}
<div class="row">
<div class="four columns">
<h4>{{ post.title }}</h4>
<ul>
<li>Serves {{ post.serves }}</li>
<li>Prep: {{ post.time }}</li>
<li>Share</li>
</ul>
{{ post.content }}
...
<!-- All tags are closed, the rest just isn't relevant -->
{% endif %}
{% endfor %}
Please find my solution with counter
<pre>
{% assign counter=0 %}
{% for post in site.posts%}
{% if post.category == 'blog' and counter < 2 %}
{% assign counter=counter | plus:1 %}
{{post.content}}
{% endif %}
{% endfor %}
</pre>
The markdownify filter is probably making it work because there might be special characters that aren't encoded in the content you're pulling from. I always forget to make my & into &.
If you're using the default Markdown interpreter Maruku, here's a list of the entities that might be giving you problems and their encoded equivalent. http://maruku.rubyforge.org/entity_test.html and more info on Maruku. http://maruku.rubyforge.org/maruku.html