Unable to get partial to return images generated from title - Hugo - html

Based on this blogpost, I am trying to generate a pseudo-random thumbnail for each new post. First, in my data folder I have a bg.json which contains information about the colours and SVGs like so:
{
"colours": [
"#dfe6e9",
"#00b894"
],
"patterns": [
"data:image/svg+xml..."
]
}
Next, in the partials folder, I created a new partial called thumbnail.html which contains the following code:
{{ $hash := split (md5 .Title) "" }}
{{ $totalColours := len .Site.Data.bg.colours }}
{{ $primaryIndex := index $hash 1 }}
{{ $basedPrimaryIndex := printf "%x" $primaryIndex }}
{{ $modIndex := mod $basedPrimaryIndex $totalColours }}
{{ $primary := index .Site.Data.bg.colours $modIndex }}
{{ $secondaryIndex := index $hash 2 }}
{{ $basedSecondaryIndex := printf "%x" $secondaryIndex }}
{{ $modIndex := mod $basedSecondaryIndex $totalColours }}
{{ $secondary := index .Site.Data.bg.colours $modIndex }}
{{ $bgIndex := mod (printf "%x" (index $hash 0)) (len .Site.Data.bg.patterns) }}
{{ $bg := replace (replace (replace (replace (index .Site.Data.bg.patterns $bgIndex) "%3C" "<") "%3E" ">") "%23" "" | safeHTML) "data:image/svg+xml," "" }}
{{ $colouredBg := replace $bg "9C92AC" $secondary }}
<style>
.post__header {
--color: {{ $primary }};
--bg: url("data:image/svg+xml;charset=utf-8;base64,{{ base64Encode $colouredBg }}");
}
</style>
My theme generates portfolio cards in another partial called portfolio.html. I looked through the file and replaced the original img src with a path to my partial like so:
<div class="box-masonry">
{{ if and (isset .Params "image") .Params.image }}
{{ if eq .Params.showonlyimage true }}
<a href="{{ .Permalink }}" title="" class="box-masonry-image with-hover-overlay">
{{ else }}
<a href="{{ .Permalink }}" title="" class="box-masonry-image with-hover-overlay with-hover-icon">
{{ end }}
<img src="{{ partial "thumbnail.html" . }}" alt="" class="img-responsive">
</a>
(...)
However, I am not seeing any images when I run my hugo server. I thought this would be the neatest way to approach things, but I think the post title (which is hashed to pick a random palette/pattern) is not being passed. How can I fix this?
My repo is hosted here: https://github.com/thedivtagguy/archives
The repo for the original blogpost's code is hosted here: https://github.com/trys/random-to-a-point

Related

Hugo/Docsy: execute of template failed at <.url>: can’t evaluate field url in type bool

I am developing a static web application using Hugo with Docsy theme. I would like to add an condition within Docsy Partials code where I would like to append the mailTo: word to my .url if the .mail is set to true, when I try to do this then I get the following error:
/themes/docsy/layouts/partials/footer.html:36:34": execute of template failed at <.url>: can’t evaluate field url in type bool
Following is the code I am adding to my partials:
{{ $myUrl := "" }}
{{ with .mail }}
{{ $myUrl = print "mailTo:" .url }}
{{ else }}
{{ $myUrl = .url }}
{{ end }}
{{ $myUrl }}
If I add some test then everything would work perfectly:
{{ with .mail }}
TRUE
{{ else }}
FALSE
{{ end }}
I am quite new to the Hugo and Docsy theme so finding difficult to understand and fix it. Any help would be really appreciated.
You are not using with correct here: https://gohugo.io/functions/with/. I think you should use if here.

Concatenate optional variables in Jinja without duplicating whitespace

Question
I want to concatenate variables in Jinja by separating them with exactly one space (' ') where some of the variables might be undefined (not known to the template which ones).
import jinja2
template = jinja2.Template('{{ title }} {{ first }} {{ middle }} {{ last }}')
result = template.render(first='John', last='Doe') # result == ' John Doe'
I've been searching for a template string alternative that returns 'John Doe' instead of ' John Doe' in this case.
First attempt
Use
{{ [title, first, middle, last]|reject("undefined")|join(" ") }}
as template (which actually works), however
it's confusing
once I want to use a macro on one of the arguments (that e.g. puts middle in brackets if it is not undefined) and therefore return an empty string instead of Undefined this stops working.
2nd attempt
Replace multiple spaces with one space
{% filter replace(" ", " ") -%}
{{ title }} {{ first }} {{ middle }} {{ last }}
{%- endfilter %}
which actually only would work in all cases with a regular expression search/replace like
{% filter regex_replace(" +", " ") -%}
{{ title }} {{ first }} {{ middle }} {{ last }}
{%- endfilter %}
but regex_replace is not built-in (but could be provided by a custom regular expression filter).
Still I would not consider this to be optimal as double spaces in the content of variables would be replaced as well.
you dont use the power of jinja2/python, use the if else and test if a variable is defined:
import jinja2
template = "{{ title ~ ' ' if title is defined else '' }}"
template += "{{first ~ ' ' if first is defined else '' }}"
template += "{{ middle ~ ' ' if middle is defined else '' }}"
template += "{{ last if last is defined else '' }}"
template = jinja2.Template(template)
result = template.render(first='John', last='Doe')
print("----------")
print(result)
print("----------")
result:
----------
John Doe
----------
if you want to use regex, use :
import re
:
:
template = jinja2.Template("{{ title }} {{ first }} {{ middle }} {{ last }}")
result = template.render(first='John', last='Doe')
result = re.sub(" +", " ", result.strip())
strip() deletes any leading and trailing whitespaces including tabs (\t)
or a mixed of both solutions to avoid to suppress spaces not wanted
import jinja2
template = "{{ title ~ ' ' if title is defined else '' }}"
template += "{{first ~ ' ' if first is defined else '' }}"
template += "{{ middle ~ ' ' if middle is defined else '' }}"
template += "{{ last if last is defined else '' }}"
template = jinja2.Template(template)
result = template.render(first='John', last='Doe').strip()
A variant of the accepted answer is to use a joiner in the Jinja template:
{%- set space = joiner(" ") %}
{%- if title %}{{ space() }}{{ title }}{% endif %}
{%- if first %}{{ space() }}{{ first }}{% endif %}
{%- if middle %}{{ space() }}{{ middle }}{% endif %}
{%- if last %}{{ space() }}{{ last }}{% endif %}
This works without any extensions, custom filters or post-processing but is relatively verbose.

Jinja2 go-to-column

I am using Jinja2 to perform code generation.
Besides the trivial problem to generate correctly indented code I also would like to perform certain in-line alignments; example use-cases would be:
start inline comments at a certain column
align operators in assignment series
A small excerpt of (1) would be:
Sound_Chime_t chime_array[] = {
{%- for k, cmd in commands.items() %}
{
"{{ cmd['Sound Command'] }}", // command
"{{ cmd['tag'] }}", // tag
{{ cmd['Priority'] }}, // priority
{{ cmd['Mix'] }}, // mix
{{ cmd['Loop'] }}, // loop
{{ cmd['region'] }}, // region
"{{ cmd['Sound File']}}" // filename
}{{ ',' if not loop.last else '' }}
{%- endfor %}
};
Of course //... is nicely aligned in template, but it won't be in generated code.
Is there some (not too convoluted) way to obtain this?
You can align the comments using two .format() calls. The second one is required by the occasional quotation marks and commas after a value. This will pad the values to 20:
Sound_Chime_t chime_array[] = {
{%- for k, cmd in commands.items() %}
{
{{ '{:<20} // command'.format('"{}",'.format(cmd['Sound Command'])) }}
{{ '{:<20} // tag'.format('"{},"'.format(cmd['tag'])) }}
{{ '{:<20} // priority'.format('{},'.format(cmd['Priority'])) }}
{{ '{:<20} // mix'.format('{},'.format(cmd['Mix'])) }}
{{ '{:<20} // loop'.format('{},'.format(cmd['Loop'])) }}
{{ '{:<20} // region'.format('{},'.format(cmd['region'])) }}
{{ '{:<20} // filename'.format('"{}"'.format(cmd['Sound File'])) }}
}{{ ',' if not loop.last else '' }}
{%- endfor %}
};

How to use hugo's front matter variable to sort my taxonomy

I was trying to sort the hugo's categories on taxonomy.
So I defined a custom front-matter variable 'root', Planning to use the root's value as the first-level directory. And the categories as the subdirectory.
But when I using .Params.root to access the variable I can't get the right value, it just returns null. So what's caused this problem? Does it caused by that the taxonomy didn't af specific detailed page or the way of mine to access the variable are wrong?
I know that I can define a data file to achieve the effects I want but I just wanna figured a way to use the front-matter variable.
{{ partial "head.html" . }}
{{ partial "header.html" . }}
{{ $termName := .Data.Plural }}
{{ $terms := .Data.Terms.ByCount }}
{{ $length := len $terms }}
{{ $type := .Type }}
{{ $root := .Params.root}}
<!-- Categories Page -->
<div class="post {{.Data.Plural}}">
<!--<h2 class="post-title" style="text-align:right;padding-bottom:2em">- {{ .Data.Plural | humanize }} -</h2>
-->
{{ if and $.Site.Taxonomies.categories (eq $termName "categories") }}
<p>{{ $root }}</p>
<div class="categories-card">
{{ range $terms }}
{{ $term := .Term }}
{{ $pages := .Pages }}
{{ with $.Site.GetPage "taxonomy" (printf "%s/%s" $type $term) }}
<div class="card-item">
<div class="categories" >
<h3> <i class="fas fa-folder" style="padding-right: 3px"></i> {{ $term | humanize }} </h3>
{{ range first 5 $pages }}
<article class="archive-item">
{{ .Title }}
</article>
{{ end }}
{{ if gt (len $pages) 5 }}
<span class="more-post">
More >>
</span>
{{ end }}
</div>
</div>
{{ end }}
{{ end }}
</div> <!-- //categories-card -->
<!-- Tag cloud Page -->
{{ else if and $.Site.Taxonomies.tags (eq $termName "tags") }}
<div class="tag-cloud-tags">
{{ range $.Site.Taxonomies.tags.ByCount }}
{{ if .Name }}
{{ .Name }} <small>({{ .Count }})</small>
{{ end }}
{{end}}
</div>
{{ end }}
</div>
</div>
{{ partial "footer.html" . }}
{{ partial "analytics.html" . }}

Nesting variables in Jekyll/Liquid

Assumption - From what I understand, Liquid works in a way that the variable page.my_key can be compared to a PHP array with name page and key my_key: $page['my_key']. Following this same logic we could compare {{ page.my_key }} with echo $page['my_key'].
And we could compare this front matter:
----
my_key: my_value
----
to this PHP code:
$page['my_key'] = "my_value";
Question - I would like to do something like this:
$page['my_key'] = "my_value";
$page['my_key2'] = "my_value2";
$key = "my_key";
echo $page[$key];
All I can think of is:
----
my_key: my_value
my_key2: my_value2
----
{% assign key = 'my_key' %}
{{ page.{{ key }} }}
However, that does not work... Is something like this possible, though?
Beware : array and hash are two different animals.
Just create a array-hash.md (note I wrote it in markdown for brevity) page in your jekyll. Paste this code. And you will understand how they are different and how to access their items.
---
layout: default
title: array-hash
myArray:
- item 1
- item 2
- one more
# or
myArray2: [ item 1, item 2, one more item ]
myHash:
item1: toto
"item 2": titi
item 3: yoyo
---
{% comment %} +++ Shortcuts
a = page.myArray
h = page.MyHash
h2 = page.myArray2
{% endcomment %}
{% assign a = page.myArray %}
{% assign a2 = page.myArray2 %}
{% assign h = page.myHash %}
## Arrays
page.myArray : {{ a }}
page.myArray with inspect : {{ a | inspect }}
page.myArray with join : {{ a | join:", " }}
page.myArray2 : {{ a2 | inspect }}
### Looping the array
<ul>
{% for item in a %}
<li>{{ item | inspect }}</li>
{% endfor %}
</ul>
### Targeting a specific item in the array
{% comment %} arrays start at zero {% endcomment %}
second element in the array = {{ a[1] }}
Note that {% raw %}{{ a["1"] }}{% endraw %} will not work. You need to pass
an integer and not a string.
Test (not working) : { a["1"] }
## Hashes
page.myHash : {{ h }}
#### looping the hash
{% for item in h %}
{{ item | inspect }}
{% endfor %}
You note that in the loop we get arrays that returns **key as item[0]**
and **value as item[1]**
The loop can then look like :
<ul>
{% for item in h %}
<li>{{ item[0] }} : {{ item[1] }}</li>
{% endfor %}
</ul>
### Targeting a specific item in the hash
**Item1** due to the absence of space in the key name, can both me accessed
by dot notation (h.item1) or bracket notation (h["item1"]).
hash.item1 : {{ h.item1 }}
hash["item1"] : {{ h.["item1"] }}
Item 2 and 3, containing a space in their key string can only be accessed with
bracket notation :
hash.item 2 (not working) : {{ h.item 2 }}
hash["item 2"] : {{ h.["item 2"] }}
hash.item 3 (not working) : {{ h.item 3 }}
hash["item 3"] : {{ h.["item 3"] }}
I think I found the solution:
----
my_key: my_value
my_key2: my_value2
----
{% assign key = 'my_key' %}
{{ page[key] }}
Found it here.