Wrap up this blog post

This commit is contained in:
Eryn Wells 2022-11-06 00:23:05 -07:00
parent 3d96dcf0c8
commit 8dbd68a3d8

View file

@ -1,9 +1,10 @@
---
title: "Hugo Dictionary API"
title: "Hugo's Dictionary API"
date: 2022-10-13T10:19:02-07:00
draft: true
categories: ["Tech"]
tags: ["Hugo", "Web"]
tags: ["Hugo", "Web", "API Design"]
series: "Erynwells.me Development"
---
Hugo's templating system has support for dictionaries. Unfortunately the API for
@ -17,8 +18,10 @@ Here's a quick summary of what I found.
## Creating Dictionaries
The function to create a dictionary is called [`dict`][dict] and it takes a
variable number of arguments that alternate between keys and values. Keys must
be strings (or string slices) and values can be anything. So this:
variable number of arguments that alternate between keys and values. It reminds
me of this [bizarre and backwards NSDictionary API][nsdictionary-init] in Apple's
Foundation framework. Keys must be strings (or string slices) and values can be
anything. So this:
{{< figures/code >}}
```go-html-template
@ -34,8 +37,7 @@ creates a structure that looks like this JSON object:
```
{{< /figures/code >}}
For completeness, you can also create an empty dictionary by calling `dict` with
no arguments.
You can also create an empty dictionary by calling `dict` with no arguments.
{{< figures/code >}}
```go-html-template
@ -60,14 +62,16 @@ If you want to get a value with a key you get at render time, you can use the
{{< figures/code >}}
```go-html-template
{{ $item := index "b" (dict "a" 1 "b" 2 "c" 3) }}
{{ $key := "b" }}
{{ $item := index $key (dict "a" 1 "b" 2 "c" 3) }}
```
{{< /figures/code >}}
`index` doesn't make much sense to me as a verb for accessing values in a
dictionary. It sounds more like an array function. I would like to see another
function with a more dictionary-sounding name, like `get` or `value` or `item`,
even if it were just an alias for `index` underneath.
dictionary. It sounds more like an array function, and indeed it's the function
that gives you access to items in arrays. I would like to see another function
with a more dictionary-sounding name, like `get` or `value` or `item`, even if
it were just an alias for `index` underneath.
## Adding Items to a Dictionary
@ -100,9 +104,8 @@ For the previously mentioned template changes I was making, I was updating the
one section per tag, and a list of all the posts with that tag underneath.
My categories are high level groups like "Tech," "Music," and "Travel." Tags are
more specific topics for the post like "Web" or "Compositions." By my own
policy, pages should only ever have one category but they can have multiple
tags.
more specific topics for the post like "Web" or "Compositions." Pages only ever
have one category but they can have multiple tags.
A `terms` template lets you access an array of terms, and the pages associated
with those terms. You can access the tags attached to a page with the
@ -111,7 +114,7 @@ with those terms. You can access the tags attached to a page with the
{{< figures/code >}}
```go-html-template
{{- $pagesByTag := dict -}}
{{- range $page := .Pages }}
{{- range $page := .Pages -}}
{{- range $tag := .GetTerms "tags" -}}
{{- $tagName := $tag.Name -}}
{{- if not (in $pagesByTag $tagName) -}}
@ -128,7 +131,22 @@ with those terms. You can access the tags attached to a page with the
```
{{< /figures/code >}}
`$pagesByTag` is my empty dictionary. It will hold tag names as keys, each
pointing to a slice (array) of page objects. For each page, I get its list of
tags. For each tag, I check `$pagesByTag` to see if it already has a key/value
pair for that tag. If not, I create a new entry in `$pagesByTag` with `merge`.
If it does already, I get the slice for that tag with `index`, add the Page to
the slice with `append`, and then merge the updated slice back into
`$pagesByTag` with `merge`.
It's not too bad once it's all spelled out, but it does feel like more work than
it should take for such simple operations.
I think this API could be improved substantially with some new functions that
operate specifically on dictionaries and that have clear names that describe
what they do.
[dict]: https://gohugo.io/functions/dict/
[index]: https://gohugo.io/functions/index-function/
[merge]: https://gohugo.io/functions/merge/
[nsdictionary-init]: https://developer.apple.com/documentation/foundation/nsdictionary/1574181-dictionarywithobjectsandkeys?language=objc