Reputation: 1749
Hugo has a YouTube shortcode. I'd like to use it in conjunction with data templates to show a list of videos that is driven by the contents of a JSON file.
Ideally, in site/content/index.md
, I'd have something like this:
# Some YouTube videos
{{ range $.Site.Data.youtube.videos }}
{{< youtube .id >}}
{{ end }}
and in site/data/youtube.yml
, I'd have something like this:
---
videos:
- id: abc123
- id: xyz456
so that each of the video ids that I list in my .yml
file is rendered as an embedded YouTube video on my homepage.
The problem here is that I can't seem to use hugo functions like range
in .md
files. When I try this, the first code snippet just gets rendered as text, rather than being replaced with YouTube videos:
Fair enough, let's extract the code into a partial that lives in site/layouts/partials/youtube-list.html
:
{{ range $.Site.Data.youtube.videos }}
{{< youtube .id >}}
{{ end }}
Then we'll modify site/content/index.md
to reference the partial:
# Some YouTube Videos
{{ partial "youtube-list.html" . }}
Now, when I try to run the server, Hugo tells me that I can't use the <
character in a partial:
ERROR 2018/01/05 11:30:33 partials/youtube-list.html : template: partials/youtube-list.html:2: unexpected "<" in command
Great. I suppose I could create a custom shortcode instead, but they appear to have the same limitation - a shortcode cannot reference another shortcode:
ERROR 2018/01/05 11:32:39 shortcodes/youtube-list.html : template: shortcodes/youtube-list.html:3: unexpected "<" in command
I guess I could find the source for the YouTube shortcode in Hugo's GitHub repository and "borrow" it wholesale for use in my new shortcode, but that seems like unnecessary duplication of code.
tl;dr: Is there any way to combine data templates and shortcodes in Hugo so that the same shortcode is used to render each element in a list that is read from a data template?
Upvotes: 4
Views: 3986
Reputation: 59
may be use Inline Shortcodes :)
<!-- post.md -->
{{< my_shortcode.inline >}}
<pre>
{{ range $index, $element := .Site.Params }}
{{ $index }} : {{ $element }}
{{ end }}
</pre>
{{< /my_shortcode.inline >}}
found on Hugo's discourse page
Upvotes: 1
Reputation: 14353
It will not be possible to access a shortcode from within your partials the way you are trying to set it up.
Hugo allows you to call partials from your shortcodes as you have mentioned. Although the setup is not exactly the way you are trying to lay them out, you could create reusable partial components that would take $.Params and allow for close to what you are trying to accomplish.
Create a place for your partial components. In this example use layouts/partials/component
Make a youtube video template like you would in a shortcode but use the passed $.Params as the context for the component. We will see this in the example below.
layouts/partials/component/youtube.html
<div>
<iframe width="560" height="315" src="https://www.youtube.com/embed/{{ .id }}" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
</div>
Create the shortcode layouts/shortcodes/youtube-sc.html
{{ if .IsNamedParams }}
{{- partial "component/youtube" $.Params -}}
{{- end -}}
Call the shortcode from front matter markdown content/example.md
:
---
title: Youtube example
---
{{< youtube-sc id="2xkNJL4gJ9E" >}}
Reuse the layouts/partials/youtube.html
component in a list shortcode:
layouts/shortcodes/youtube-list.html
{{ if .IsNamedParams }}
{{ $data := index $.Site.Data.youtube $.Params.data }}
{{ range $data }}
<h2>Video is {{ .id }}</h2>
{{ partial "component/youtube" . }}
{{ end }}
{{- end -}}
Call the shortcode from front matter markdown content/example.md
:
---
title: Youtube List Example
---
{{< youtube-list data="videos" >}}
The data could include multiple lists and called based on the list of videos you want with {{< youtube-list data="others" >}}
using:
---
videos:
- id: 2xkNJL4gJ9E
- id: FyPgSuwIMWQ
others:
- id: ut1xtRZ1QOA
- id: sB0HLHjgQ7E
NOTE: This example assumes the use of NamedParams
in your shortcodes to make it cleaner. You could add data to the data
objects also and pass that into the shortcode's named params as well.
Upvotes: 3