Creating partials and shortcodes (a recommendation)
tl;dr
Make a partial that expects to receive a dictionary as the argument. The dictionary should contain (dict "page" $.Page "site" $.Site)
as a minimum if indeed the partial uses those objects. You can then refer to the $.Page
using .page
in the partial.
Make a shortcode with the same filename that contains
{{- partial (printf "%s.html" .Name) (merge .Params (dict "page" $.Page "site" $.Site)) -}}
Recommended way to pass parameters to partials
Partials are chunks of HTML with Hugo commands in. They can be called from other HTML templates or other partials (which are bits of template) but not directly from markdown content (but follow this guide and you can!).
When calling a partial, you can only pass it one argument, which traditionally is “.
” – that is (usually) a reference to the current $.Page
(be careful though because if you’re in a loop, .
might be the current value in the loop so cutting and pasting code in and out of loops can break things). This one parameter can be quite limiting, so for a number of partials written for this site the partial expects to receive a dict
object (i.e. a hash), which is the recommended way to provide a partial with multiple arguments.
For our purposes, this should have as a minimum:
(dict "page" $.Page "site" $.Site)
which ensures that the partial has access to the $.Page object in the .page
key and to the $.Site object with .site
. You can also obviously pass it other parameter values with other parameter keys.
If you want to make parameters optional (I recommend this) then assign the value to a variable using default
at the top of the partial use something like:
{{- $page := .page -}}
{{- $mandatoryparam1 := .manadatoryparam1 -}}
{{- $optionalparam := default defaultval .optionalparam -}}
default
stops hugo from complaining about a missing index.
Your template could call the partial themes/jalview/layouts/partials/mything.html
with something like
{{ partial "mything.html" (dict "page" $.Page "site" $.Site "manadatoryparam1" $val1) }}
(and you could add in the "optionalparam"
key with value if you wanted to).
We now have a cunning trick to make a partial that operates like this also work as a shortcode, with attribute style key=val
pairs, and with almost no extra work at all!
Using a Shortcode to call your partial
Shortcodes are similar to partials, but can be called directly from markdown content, e.g. a shortcode saved as themes/jalview/layouts/shortcodes/mything.html
can be called in the markdown, with extra parameters provided in a neat attribute style, e.g.
{{% myshortcode key1="val1" key2="val2" %}}
or
{{< myshortcode key1="val1" key2="val2" >}}
If we make a shortcode that calls the partial (with the partial
function) it can also supply a dict
of parameters. We can completely automate this with a shortcode saved in a file of the same name as the partial you want it to call (but in the shortcodes
folder), that looks like this:
{{- partial (printf "%s.html" .Name) (merge .Params (dict "page" $.Page "site" $.Site)) -}}
This one line of code is saved as a shortcode called themes/jalview/layouts/shortcodes/shortcode_to_partial.html
so you can just copy that (you don’t need to edit it!) to mything.html
with
cd themes/jalview/layouts/shortcodes
cp shortcode_to_partial.html mything.html
I’d say make a symbolic link but this might not be preserved through git on all platforms.
You can now use your partial in markdown content by calling this shortcode, e.g.
{{% mything mandatoryparam1="windows" optionalparam=true %}}
What does this shortcode do?
- First of all it uses the
partial
function to call the partial with the filename given next… - The next parameter,
(printf "%s.html" .Name)
, simply takes the shortcode name (which is the filename without the.html
) and adds on a.html
, i.e. it’s the same filename as the shortcode, but because we’re giving this to thepartial
function, this time it refers to the partial with the same filename. - The final argument is a merging of two dictionaries.
.Params
is the dict of attribute stylekey="val"
pairs that you use in the markdown when calling the shortcode, and the second dictionary is just(dict "page" $.Page "site" $.Site)
to ensure the page and site get sent with the correct parameter names (assuming you’ve followed the guidelines above for creating your partial).
Shortcode with .Inner
text
If you want to use a shortcode block with inner text, say something like
{{<mything key="val">}}
Here's some stuff to format as a mything!
{{</mything>}}
Then use a shortcode containing
{{- partial (printf "%s.html" .Name) (merge .Params (dict "page" $.Page "site" $.Site "text" (trim .Inner " \n"))) -}}
which will also send the inner text to the partial with the key “text” (the partial can then get at this with .text
). The above code is in the file shortcode_to_partial_with_text.html
).
The reason for not using this code with the "text"
parameter for every partial (which could just ignore the .text
value if not wanted) is that the mere act of looking at .Inner
seems to make Hugo expect an ending {{</mything>}}
in the markdown. Unless there is one the rest of your document’s content gets missed!