How to render image using path from json in hugo - hugo

The project structures look like this.
/
|__ assets
| |__ imgs
| |__ pic-nodejs.jpg
| |__ pic-denojs.jpg
|
|__ data
| |__ products.json
|
|__ layouts
|__ _default
| |__ baseof.html
|
|__ partials
| |__ card.html
|
|__ index.html
The project goal is basically to display a list of products with a Bootstrap-ish card style in a grid layout.
Below are the snippets from the above files.
/data/products.json
[
{
"Uid": "110",
"Name": "Nodejs",
"Imgsrc": "imgs/pic-nodejs.jpg"
},
{
"Uid": "120",
"Name": "Denojs",
"Imgsrc": "imgs/pic-denojs.jpg"
}
]
index.html
{{ define "main" }}
<section>
{{ partial "card.html" . }}
</section>
{{ end }}
partials/card.html
{{ $data := getJSON "/data/products.json" }}
{{ range $data }}
<header>
<h2>{{ .Name }}</h2>
</header>
<img src={{ .Imgsrc }} alt={{ .Name }} />
{{ end }}
The expected output for card.html.
<section>
<header>
<h2>Nodejs</h2>
</header>
<img src="imgs/pic-nodejs.jpg" alt="Nodejs" />
</section>
I've got this instead.
<section>
<header>
<h2>Nodejs</h2>
</header>
<img src="" alt="Nodejs" />
</section>
No image being loaded.
Any idea how to do this?
I'm currently using HUGO v0.88.1 Extended.

Move the folder imgs inside static folder
check this branch of my repo

Related

Nested list of sections and content - Hugo

I have a series of nested sections that contain recipes, grouped by type of dish, e.g.:
content
└─ recipes
  ├─ _index.md
  ├─ bread
  │  ├─ _index.md
  │  ├─ beer_rolls.md
  │  ├─ ciabatta.md
  │  └─ potato_bread.md
├─ dessert
  │  ├─ _index.md
│  ├─ chocolate_brownies.md
│  ├─ elderberry_pie.md
│  └─ victoria_sponge_cake.md
└─ mains
├─ _index.md
├─ bean_chilli.md
├─ braised_leeks.md
└─ yorkshire_pudding.md
I want to write a list.html for content/recipes/_index.md, to produce a nested list that reflects the directory structure in recipes/, such that the first level of the list links to the subsection e.g. bread or dessert, and the second level of the list links to the individual recipes, e.g. bread/beer_rolls.md or mains_bean_chilli.md.
What does the list.html contain? Do I need to have multiple list.html files, one for each nested subsection?
With help from this example, I constructed the following system, which works well for me:
in layouts/recipes/list.html I included this:
{{ if (eq .Title "Recipes") }}
<ul class="postlist">
{{ range .Sections.ByTitle }}
<li>
{{ .Title }}
{{ partial "recursive.html" . }}
</li>
{{ end }}
</ul>
{{ else }}
<ul class="postlist">
{{ range .RegularPages }}
<li>
{{ .Title | markdownify }}
</li>
{{ end }}
</ul>
{{ end }}
And in layouts/partials/recursive.html I included this:
{{ $child_pages := union .Sections .Pages }}
<ul>
{{ range $child_pages.ByTitle }}
<li>
{{ .Title }}
{{ if or (.Sections) (.Pages) }}
{{ partial "recursive.html" . }}
{{ end }}
</li>
{{ end }}
</ul>
content/recipes/_index.md looks like this:
---
title: "Recipes"
---
and for example content/recipes/drinks/_index.md looks like this:
---
title: "Drinks"
---
This produces a page at ./recipes which contains a grouped list, where the first level includes links to further list pages (e.g. ./recipes/bread), which themselves contain links to the recipes in that group. All recipes are also listed below their parent group on ./recipes.

Hugo: do not escape HTML in a page .Title when generating <title> tag in the header.html partial

In my Hugo-based website, I often use <span> tags within my post titles. I am experiencing an issue where this HTML is always escaped in one particular context. As an example, take a post where the title given in the header of the Markdown file is as follows:
title: 'This is a title with Spanish: <span lang="es">Hola!</span>'
In the single.html partial of my Hugo theme, <h2 class="posttitle">{{ .Title | markdownify }}</h2> works correctly, it passes This is a title with Spanish: <span lang="es">Hola!</span> to the final HTML of the page.
However, in the header.html partial of my Hugo theme, <title>{{ .Title | markdownify }}</title> does not work. Instead, Hugo passes an escaped string to the final HTML of the page: <title>This is title with Spanish: <span lang="es">Hola!</span></title>
How can I achieve the same behavior in header.html as in single.html?
EDIT: My theme is exceedingly simple, the hugo-xmin theme with minimal changes. My theme’s header.html partial is as follows:
<!DOCTYPE html>
<html lang="{{ .Site.LanguageCode }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ .Title | markdownify }} | {{ .Site.Title }}</title>
<link rel="stylesheet" media="screen" href="{{ "/css/style.css" | relURL }}" />
<link rel="stylesheet" media="screen" href="{{ "/css/screen.css" | relURL }}" />
{{ partial "head_custom.html" . }}
</head>
<body>
<h1 id="sitetitle">.Site.Title</h1>
<p id="sitedescription">{{ $.Site.Params.description }}</p>
<nav>
<ul class="menu">
{{ range .Site.Menus.main }}
<li>{{ .Name }}</li>
{{ end }}
</ul>
<hr/>
</nav>
and my theme’s single.html file is as follows:
{{ partial "header.html" . }}
<main>
<div class="article-meta">
<h2 class="posttitle">{{ .Title | markdownify }}</h2>
Published on <time>{{ .Date.Format "2006-01-02" }}</time>
</div>
{{ .Content }}
</main>
{{ partial "footer.html" . }}
If you want to avoid escaping, you should use the safeHTML function.
{{ .Title | safeHTML }}
This is not a working solution. Even with this function placed into the header.html partial, the HTML continues to be escaped.
This could be an issue with an older version of Hugo, I am on v0.74.3 and it seems to be working as intended. You might want to upgrade if you're not on the latest version or check on the discourse if you are unable to upgrade.
I downloaded your nonworking-blog minimal example and was able to fix your issue by doing two things:
Put the following at the bottom of the config.toml:
[outputFormats]
[outputFormats.html]
isPlainText = true
Comment out line 34 in layouts/_default/list.html so it now looks like this:
{{/*
{{ template "_internal/pagination.html" . }}
*/}}
I did #2 because it was producing an error that I don't have time to look into now, but the key to solving your issue is outputFormats, which are discussed at https://gohugo.io/templates/output-formats/, especially this:
isPlainText
use Go’s plain text templates parser for the templates. Default: false.
If anyone knows how to fix the line-34 problem, I'd love to understand that.
BTW, I've been using isPlainText = true for more than a year on my Infinite Ink site and so far have not had any problems (but I do not use any {{ template … }} calls).

Hugo Page Resources - can't get a match

I want to write a generic shortcode for my hugo-powered webseite that adds a download section to my pages listing all the files in the downloads folder.
I have the website layed out like this:
.
├── content
│   └── press
│   ├── downloads
│ │ ├── presstext.pdf
│   │   └── presskit.zip
│   ├── _index.de.md
│   └── _index.en.md
└── layouts
   └── shortcodes
   └── downloads.html
My markdown file looks like this:
---
title: "Downloads"
date: 2019-10-26T09:59:26+01:00
draft: true
resources:
- src: downloads/presskit.zip
title: Presskit
params:
icon: pdf
- src: downloads/presstext.pdf
title: Presstext
params:
icon: pdf
---
Look at my awesome downloads:
{{< downloads >}}
And my shortcode looks like this:
<ul class="downloads">
{{ range .Page.Resources.Match "downloads/*" }}
<li>
<a target="_blank" href="{{ .Permalink }}">
<i class="far fa-file-{{ .Params.icon }}"></i> {{ .Title }}
</a>
</li>
{{ end }}
</ul>
But no document ever get's matched, so {{ range .Resources.Match "downloads/*" }} always returns empty. Am I overlooking something?
I already tried:
{{ range .Resources.Match "downloads/*" }}
{{ range .Resources.Match "/downloads/*" }}
{{ range .Resources.Match "**.zip" }}
{{ range .Resources.Match "**.pdf" }}
{{ range .Resources.Match "press/downloads/*" }}
{{ range .Resources.Match "/press/downloads/*" }}
Running on Hugo 0.59.0
I gave up on this and ended up doing this instead:
.
├── content
│ └── press
│ ├── presstext.pdf
│ ├── presskit.zip
│ ├── _index.de.md
│ └── _index.en.md
└── layouts
└── shortcodes
└── downloads.html
my markdown:
---
title: "Downloads"
date: 2019-10-26T09:59:26+01:00
draft: true
resources:
- src: presskit.zip
title: Press kit
params:
icon: archive
download: true
- src: presstext.pdf
title: Press text
params:
icon: pdf
download: true
---
Look at my awesome downloads:
{{< downloads >}}
Shortcode:
<ul class="downloads">
{{ range .Page.Resources }}
{{ if isset .Params "download" }}
<li>
<a target="_blank" href="{{ .Permalink }}">
<i class="far fa-file-{{ .Params.icon }}"></i> {{ .Title }}
</a>
</li>
{{ end }}
{{ end }}
</ul>
OK, this is an old one, but the right answer is that for branch bundles (_index.md) you can have resources ONLY in the same folder.
For leaf bundles (index.md) you can have resources in subfolders.
I guess it is because every subfolder in branch bundles is supposed to be a page with resources (leaf bundle).
Here is the source https://gohugo.io/content-management/page-bundles/ (see the table row Where can the Resources live?)

Hugo cannot convert type page.PagesGroup to Pages

I have a Hugo list template like this:
{{ range (.Paginate (.Data.Pages.GroupByDate "2006")).PageGroups }}
<h3>{{ .Key }}</h3>
<ul>
{{ range .Pages.ByWeight }}
<li>
{{ if .Draft }}{{ T "draft" }}: {{end}}{{ .Title | markdownify }}
<time class="date-meta">{{ .Date.Format "Jan 2" }}</time>
</li>
{{ end }}
</ul>
{{ end }}
When I run the site like this hugo server -D it works fine.
When I build the site I get:
execute of template failed: template: _default/list.html:15:14: executing "main" at <.Paginate>: error calling Paginate: cannot convert type page.PagesGroup to Pages
Turning on debug and verbose do not help. I have:
content
content/web
content/web/one.md
content/web/two.md
content/web/_index.md
content/web/three.md
content/about
content/about/index.md
What gives?
I encountered this error while writing a custom theme except it happened when running hugo -D or hugo server -D. As a workaround try wrapping it in an if condition to check .Data.Pages.
{{ if .Data.Pages }}
{{ range (.Paginate (.Data.Pages.GroupByDate "2006")).PageGroups }}
...
{{ end }}
{{ end }}

Resize image in Hugo (v 0.32.x) in markdown

I am trying to resize an image in Hugo (not using HTML / CSS), which is apparently available in the v 0.32 update. Beneath the "Image Processing" heading at the link in the last sentence, the following "Resize" method is described:
Resize to the given dimension, {{ $logo.Resize "200x" }} will resize to 200 pixels wide and preserve the aspect ratio. Use {{ $logo.Resize "200x100" }} to control both height and width.
I'm having some trouble implementing this in my Hugo site. In particular, I am using a .md file, and am trying to add an image which is stored somewhere else in the site's source files.
For example, here's how I would add the (not-resized) image in the .md file:
![pdf image](../static/_media/images/pdf.png)
How could I add this same file, resized to 50x50 pixels, using the resize method in the v0.32 release?
Using my newer version of Hugo (v0.53) I had to adapt the answer by JoostS a bit:
Created a page bundle
Modified the shortcode to look like this at the start:
{{ $original := .Page.Resources.GetMatch (print "images/" (.Get 0) "*") }}
You can not use it like this (in markdown). Resizing only works on resources. A resource is a file in the resource directory or a file in a page bundle. To access resources in markdown you will have to use a shortcode.
Note that you can define the static dir as the resources directory. Once you do that, you can just use the static directory and write something like:
(.Site.Resources.GetMatch "_media/images/pdf.png").Resize "50x50"
However, you should access this through a shortcode, like Talves did. I simplified his code a little for extra readability:
{{< imgresize "_media/images/pdf.png" >}}
Calling this shortcode (layouts/shortcodes/imgresize.html):
{{ $image := (.Site.Resources.GetMatch (.Get 0)).Resize "50x50" }}
<img src="{{ $image.RelPermalink }}">
As of 2022, if all you need is displaying the image in a different size, maybe Hugo’s Built-in "figure" Shortcode would do?
{{< figure src="/media/spf13.jpg" title="Steve Francia" >}}
You will need to make sure you have included your images within the content of your page usually at the level of the page itself unless you reference them using the answer I link in the note below.
NOTE: You can access resources from an outside section as in this answer
Write a shortcode
layouts/shortcodes/imgresize.html
{{ $original := .Page.Resources.GetByPrefix (.Get 0) }}
{{ $options := .Get 1 }}
{{ .Scratch.Set "image" ($original.Resize $options) }}
{{ $image := .Scratch.Get "image" }}
<img src="{{ $image.RelPermalink }}" width="{{ $image.Width }}" height="{{ $image.Height }}">
[Alternative] Shortcode accessing resource under content/media section
{{ $imagename := (.Get 0) }}
{{ $options := .Get 1 }}
{{ with .Site.GetPage "section" "media" }}
{{ $original := .Resources.GetByPrefix $imagename }}
{{ with ($original.Resize $options) }}
<img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}">
{{ end }}
{{ end }}
Call the shortcode from within the markdown of the page.
{{< imgresize pdf "50x50" >}}
pdf refers to the image by its name prefix to get the resource.
Using a sub folder page to access the resources
In the next example shortcode you must have a page at the same level as your images. Include an index.md at the same level (example: content/media/logos/index.md)
add layouts/shortcodes/logo-resize.html
{{ $imagename := (.Get 0) }}
{{ $options := .Get 1 }}
{{ with .Site.GetPage "page" "media/logos/index.md" }}
{{ $original := .Resources.GetByPrefix $imagename }}
{{ with ($original.Resize $options) }}
<img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}">
{{ end }}
{{ end }}
Call the shortcode
{{< logo-resize pdf "50x50" >}}
GitHub Example
If you're using Page Bundles you can reference any file in the page's folder, whether or not it is declared in front matter:
.
|- This is the Page (a folder)
|- index.md
|- photo1.jpg
\- photo2.jpg
INside index.md
{{< imgresize photo1.jpg "350x350" "Alternate Text" >}}
The shortcode (same as #Talves but uses GetMatch and Fit, and includes alternate text for image.)
{{ $original := .Page.Resources.GetMatch (.Get 0) }}
{{ $options := .Get 1 }}
{{ .Scratch.Set "image" ($original.Fit $options) }}
{{ $image := .Scratch.Get "image" }}
{{ $title := .Get 2 }}
<img src="{{ $image.RelPermalink }}" width="{{ $image.Width }}" height="{{ $image.Height }}" alt="{{ $title }}">
UPDATE! There is a new and better way: render hooks!
Create a render hook
For images in the markdown, you can use a ‘render hook’. This is a file that describes/overrides how markdown images are handled. To use the above approach in the render hook you should create the following file:
/layouts/_default/_markup/render-image.html
… and put this logic inside:
{{ if (resources.GetMatch .Destination) }}
<img src="
{{ ((resources.GetMatch .Destination).Fit `600x600 jpg Smart q50`).RelPermalink | safeURL }}
" alt="{{ .Text }}" />
{{ end }}
Note that we use ‘.Destination’ for the source of the original image and ‘.Text’ for the alt text defined in the markdown. Once you added the render hook all images in your Hugo project can and will be resized.
More info can be found at Hugo Codex and in the official docs.

Resources