Generate index.json based on sections and subsections

To generate an index.json of regular pages we can use:

layouts/_default/index.json

{{- $.Scratch.Add "index" slice -}}
{{- range .Site.RegularPages -}}
    {{- $.Scratch.Add "index" (dict "title" .Title "tags" .Params.tags "categories" .Params.categories "contents" .Plain "permalink" .Permalink) -}}
{{- end -}}
{{- $.Scratch.Get "index" | jsonify -}}

My website consists only of highly nested sections. I tried to merge the code above with the code from this post:

layouts/_default/index.json

{{- $.Scratch.Add "index" slice -}}
{{ partial "search/json.html" . }}
{{- $.Scratch.Get "index" | jsonify -}}

layouts/partial/search/json.html

{{ $child_pages := union .Sections .Pages }}
{{ range $child_pages }}
  {{- .Scratch.Add "index" (dict "title" .Title "tags" .Params.tags "categories" .Params.categories "contents" .Plain "permalink" .Permalink) -}}
  {{ partial "search/json.html" . }}
{{ end }}

Of course I added

[outputs]
  home = ["HTML", "RSS", "JSON"]

to my config.toml and the json file gets generated…but it is empty. Anyone has an idea why?

I think the thing with scratches is, that the one from your index.json does not exist inside of search/json. Try putting all into one single file and it should work. But that is an uneducated guess only…

Have a look at GitHub - kaushalmodi/hugo-debugprint: Hugo "debugprint.html" partial - you could use it like:

{{ partial "debugprint" . }}

and see what the contents of your variables is.

Based on your suggestion I remember the answer of the post “How to build one collection for all nested sections?” which I modified to:

layouts/_default/index.json

{{- $.Scratch.Add "index" slice -}}
{{- range .Site.Sections -}}
    {{- $.Scratch.Add "index" (dict "title" .Title "tags" .Params.tags "categories" .Params.categories "contents" .Plain "permalink" .Permalink) -}}
    {{ template "subpages" . }}
{{- end -}}
{{- $.Scratch.Get "index" | jsonify -}}

{{ define "subpages" }}
  {{ if .Pages }}
    {{ range .Pages}}
      {{ if eq .Kind "section" }}{{- .Scratch.Add "index" (dict "title" .Title "tags" .Params.tags "categories" .Params.categories "contents" .Plain "permalink" .Permalink) -}}{{ end }}
      {{ template "subpages" . }}
    {{ end }}
  {{ end }}
{{ end }}

Now the index.json is not empty anymore BUT only the first level sections are included in the index file. I think the problem is the .Scatch.Add part inside the range. I have to improve the scoping somehow.

.Site.Sections are the first level foldernames :wink:

Try .Site.RegularPages or .Site.Pages

Note: I am not sure what is going on there, what do you want to list? all pages? use .Site.Pages and range one time through. All posts (main section content)? Use .Site.RegularPages and range one time through that one. Site.Sections is a list of sections and in the second loop you try to get the pages of that section… That’s double the work for the same result (and it does not work it seems :wink: )

I want to generate an index.json for site search.

My website structure is something like:

section-1/_index.md
- subsection-1/_index.md
- subsection-2/_index.md
section-2/_index.md
- subsection-1/_index.md
- subsection-2/_index.md

…highly nested sections.

Try replacing .Pages in your second loop with .RegularPagesRecursive and see what’s happening. It might help if you had some kind of sample content in a repo somewhere so we can wrap our heads around this. If I get it right what you want is basically like a directory of contents recursive through all levels, like in a scientific book with differing levels of depth.

Don’t ask me why but the following is working like a charm:

{{- $.Scratch.Add "index" slice -}}
{{- range .Site.Pages -}}
    {{- $.Scratch.Add "index" (dict "title" .Title "tags" .Params.tags "categories" .Params.categories "contents" .Plain "permalink" .Permalink) -}}
{{- end -}}
{{- $.Scratch.Get "index" | jsonify -}}

Thank you for your suggestions, @davidsneighbour. Your help is always highly appreciated :slightly_smiling_face:

PS: My index.json has 1224 elements and a filesize of 4 mb. Now I can finally set up one of the alternatives search engines :yum:

1 Like

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