From 8dbd68a3d8fa465521364afa11953b108721028a Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sun, 6 Nov 2022 00:23:05 -0700 Subject: [PATCH] Wrap up this blog post --- .../blog/2022/10/hugo-dictionary-api/index.md | 46 +++++++++++++------ 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/content/blog/2022/10/hugo-dictionary-api/index.md b/content/blog/2022/10/hugo-dictionary-api/index.md index f0ae5da..d903107 100644 --- a/content/blog/2022/10/hugo-dictionary-api/index.md +++ b/content/blog/2022/10/hugo-dictionary-api/index.md @@ -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