Issue with ``where`` that shows up with hugoThemes

Preface

I’ve got a bit of an odd issue. It shows up with hugoThemes repo but the same minimal test theme succeeds when used with hugoBasicExample directly. I’ve got public repos and document the issue below.

The Issue

First though, the code snippet and error message I get when running a test in the hugoThemes test repo.

  1. Get hugoThemes
    git clone https://github.com/gohugoio/hugoThemes.git
    
  2. Change to the directory mentioned in the hugoThemes documentation
    cd _script
    
  3. Use the reviewTheme.sh script to attempt to build the theme
    ./reviewTheme.sh https://github.com/danielfdickinson/hugoWhereIssue 2>&1 | tee build.log
    
  4. Observe the following error message:
    Building site for theme hugoWhereIssue using config "[hugoThemes dir]/_script/hugoThemeSite/config-hugoWhereIssue.toml" to ../themeSite/static/theme/hugoWhereIssue/
    Error: Error building site: failed to render pages: render of "page" failed: execute of template failed: template: _default/single.html:5:12: executing "_default/single.html" at <partial "header.html" .>: error calling partial: "[hugoThemes dir]/_script/review/hugoWhereIssue/layouts/partials/header.html:7:19": execute of template failed: template: partials/header.html:7:19: executing "partials/header.html" at <where .Site.Menus.main "URL" (.RelPermalink)>: error calling where: can't iterate over <nil>
    FAILED to create demo site for hugoWhereIssue
    
    NB The warnings (not shown here) about missing images for the themes showcase are irrelevant as the same message occurs with a theme which includes the wanted images.

The offending test code

{{ $curPage := . }}
{{ range .Site.Home.Pages }}
    {{ $rangePage := . }}
    {{ if not .Site.Menus.main }}
	    {{ errorf (printf "Could not find .Site.Menus.main from page '%s'" .) }}
    {{ end }}
    {{ if le (len (where .Site.Menus.main "URL" (.RelPermalink))) 0 }}
	    Empty menus on {{ . }}
    {{ else }}
    	  {{ range (where .Site.Menus.main "URL" (.RelPermalink)) }}
		      {{ .Name }} on {{ $rangePage }}
	      {{ end }}
    {{ end }}
{{ end }}

Attempting to reproduce with hugoBasicExample

This attempts to emulate what the hugoThemes script does in a more minimal fashion

  1. In your working directory clone hugoBasicExample
    git clone https://github.com/gohugoio/hugoBasicExample
    
  2. Also in your working directory, clone hugoWhereIssue
    git clone https://github.com/danielfdickinson/hugoWhereIssue menusIssue
    
  3. Create a subdir and change to it.
  4. Use the theme to create the site
    hugo server --source ../hugoBasicExample --themesDir .. --theme menusIssue --verbose --disableFastRender --ignoreCache
    
  5. It succeeds, although the following is output in resuling pages:
    Empty menus on Page(/archives.md) Empty menus on Page(/post/_index.md) About on Page(/about.md)
    

Huh?

Obviously I am missing some magic sauce from the hugoThemes repo to recreate the error. Any ideas?

A related note

This is what caused me to ask the following:

https://discourse.gohugo.io/t/main-menu-like-mainsections-or-is-removing-menus-planned/32027/5

Solution

Apparently hugoThemes applies your theme against the hugoThemes site itself, with a different config.

It turns out that I was incorrect in believing that .Site.Menus.main was guaranteed to be at least an empty slice.

If there is no menu in the config, then .Site.Menus is nil and where will fail.

Your answer marked as solution is wrong, or not the fault.

Your assumptions about “the dot” are. Look at the three lines I quoted.

On line 1 the dot (.) is the global dot (all site), on line 2 the dot is one single page from within the range. On line 3 you try to get the property site.menus.main from that single page (the current dot). You do NOT check the global site variable/function.

You can easily work over this by using site.Menus.main instead of .Site.Menus.main. site always returns the global site-context.

Search the forum for posts about site vs .Site, that is an often talked about problem. And I always suggest to read through @regis excellent Dot article (and all others he wrote too, not a single bomb in there):

2 Likes

Sorry, I was feeling ‘noisy’ and didn’t want to post the complete set of changes. I did end up realizing that .Site.Menus.main was wrong, but it is also true that site.menus.main was not being populated by a menu. If it would help for those looking through the forum, I can post the more complete details.

Although it won’t hurt to double check that code anyway to make sure I did get the scope and context right in the end.

Hmmm…it looks like I lost a change I know I had in the code, probably due to stashing and forgetting to bring to back or some silliness like that. Anyway I will review and report back.

Did you know that you can apply to add your theme without a demo? If this is for your “minimal bug sample repo” just add, that you don’t want the demo site enabled and leave it out. It’s too specific for that in my opinion.

For all other themes the rule is, if you have your own demo site running with the theme then add that as link to your PR/Issue in the hugoThemes repo and apply to not have a hugoThemes demo site added.

It’s good though to see if any arbitrary theme usage works and can show you where your theme needs improvement.

Speaking of which, I haven’t looked yet, but is there an easy way to find a bunch of open source sites that I can throw at the minimal bug sample repo? As you say that would be an excellent way to see where it needs improvement. I guess I have to see how many people tag their sites with hugo-site or some such in GitHub. (or have hugo and website that I can search for as tags).

Also, I know it needs more testing before I publish in the themes repo, even without a demo (which I didn’t know I could do, so thank you @davidsneighbour !). That will, however, allow me to keep the sample repo from needing to default to being a ‘real’ theme.

I actually had a problem with site not matching the page context’s .Site with the debug tables (was needing to compare the top-level passed in site to the current page’s .Site context in a cheap effort to avoid infinite recursion when expanding variables as an optional feature – that really hasn’t worked out the best, and mostly it’s best to just look at the current page context with the debug table at the moment. The expanding more levels down needs some love yet).

That made me leery of site, but that’s a special case and not relevant to this more usual case (and would save some contortions).

[trim noise]

All I’m really trying to do is end up with a combined set of list items (navigation links) that include the mainSections and main menu items without duplication. I wonder if I could create two slices of the results of GetPage on mainSections and the main menu and using some set logic to get the non-duplicating union. I’m thinking I may also want the top level RegularPages, but hat is less certain.

Bwah hah hah! (I hope…it seems to work for my tests of without menu, with duplicated item, and with no duplicates – am I missing something?)

{{- $curPage := . -}}
{{- $mainMenu := site.Menus.main -}}
{{- $sections := where site.Home.Pages "Section" "in" site.Params.mainSections -}}
{{- $menuPages := (slice) -}}
{{- range $mainMenu -}}
    {{- $menuPages = $menuPages | append (where site.Home.Pages "RelPermalink" .URL) -}}
 {{- end -}}
 {{- range (union $sections $menuPages) -}}
     <li class="list-item-test-min{{- if eq $curPage . }} current-menu-is-test-min{{- end -}}">
         <span class="link-wrapper-test-min"><a
            href="{{- .RelPermalink -}}" class="link-test-min">{{-
            partial "return-helpers/title" . -}}</a></span>
    </li>
{{- end -}}

@davidsneighbour I don’t suppose where can use eliminate the need for the range on mainMenu as far the .URL goes?

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.