Hugo Prev Next By Traversal Across Sections

Overview

This Hugo template returns the previous/next item based on the way of depth-first search and pre-order.

There are two template functions.

  • Next (Heavier) item: Returns the adjacent item in the direction of the arrow in the picture above from the given item.
  • Previous (Lighter) item: Returns the adjacent item in the opposite direction of the arrow in the picture above from the given item.

With this, we can iterate through all items on the site with just one function for each previous/backward direction.

I think it will be useful for people who need to navigate between sections or who frequently change the structure of a document.

Note

  • While the target of PrevInSection / NextInSection provided by Hugo is only pages, not sections, the target of these template functions is both pages and sections.
    • This template function was created with technical documentation navigation in mind. In a technical document site, the subdocument list page corresponding to the Hugo section usually contains introduction or overview information about the subitems. I didn’t want this information to be skipped when navigating the site in a before/after fashion.
  • The entire depth-first search is not actually performed. Each item simply finds and returns only the items before/after itself.

Usage

Repository: https://github.com/hyaniner/hugo_prev_next_traversal_across_sections

  • Paste the above repository as a folder into the root directory of the Hugo project.
  • Call it on the template as below.
    • Previous item (direction of smaller weight value) :
      1
      
      {{ partial "navigation/traversal_across_sections/lighter.hugo" . }}
    • Next item (direction of larger weight value) :
      1
      
      {{ partial "navigation/traversal_across_sections/heavier.hugo" . }}
    • The default path is set as hugo_project_root/layouts/partials/navigation/traversal_across_sections/. If you want to place the files at hugo_project_root/layouts/partials/, then you have to delete the part navigation/traversal_across_sections/ from the codes to use.

License: Apache License 2.0.

Details

Motivation

We can also do the above traversal using the functions provided by Hugo . However, the blue arrow and green arrow parts need different functions, and the part with the red arrow does not have a function provided by Hugo , so the user must implement it themself. This template serves to integrate the means required for the traversal shown in the figure by direction.

How to work

This template works like the below:

  • Previous Item (direction of smaller weight value)
    • If the current item is the first item in the section it belongs, return its parent item.
    • If the current item is not the first item in the section it belongs, find the previous item in the current section.
      • If the found result does not have children, return that.
      • If the found result has a child, find its last child recursively until there is no more child item. And return the last child that does not have a child.
  • Next item (direction of larger weight value)
    • If there is a child of the current item, return that first child item.
    • If there is no child of the current item,
      • If there is the next item in the section that the current item belongs to, return that next item.
      • If there is no next item in the section that the current item belongs to, find recursively parents until there is a parent that has the next item.
        • If the parent that has the next item is found, Return the next item of that parent item
        • If this finding arrives at the home, return the home.

In this way, no matter where we call it in the directory structure, we can find the previous/next item in a consistent way.

For reference

  • if the current item is Home, Home itself is returned.
  • If we find an item in the lighter direction from the first child of Home, or if we find an item in the heavier direction from the last item in the directory structure of the site, Home is returned as a result.

About the name

Originally, the name of this was “DFS Previous/Next”. But after I made up his name, I felt uncomfortable for a long time.

This template finds the previous/next item based on the depth-first search direction - more precisely, the pre-order direction. However, the implementation itself does not include the traditional algorithms used for depth-first search or pre-order traversal. Typical descriptions of the algorithm is aimed, usually, at starting from the root node and traversing the entire node. However, here, we only need to find the previous and next items from the current item.

I have seen a code in the Relearn theme that starts by going through the items of the entire site, analyzing the structure, and creating a dictionary collection of previous/next items in the scratch pad. After seeing that code, I also thought about creating data for the entire site and then reading it. However, I thought that if this processing were to run in parallel on each page, it would be better to have each page perform only as much processing as needed. If there are some things like an “important topic section” in the site, and if I want to include links such as “to the next important topic section start page” or “to the previous important topic section start page” for each page, it would be better to process the entire structure first. But I didn’t think this site needed a feature like that yet.

So, if I implement this by getting the items before and after each item, what should the appropriate name be? At first, the words I used when searching for this feature were “prev/next across sections”

So I changed the name to “Prev Next By Traversal Across Sections".

lighter/heavier, instead of prev/next

There is a sad story in the Prev/Next of Hugo. (Link) It makes me have a lot of thought, but I understand that backward compatibility is not an easy topic. This code runs based on weight. And, it was created with the assumption that it would be used in technical documents, not blogs. So, instead of Previous and Next, I modified the code to use the words lighter and heavier.

etc

I post the code for others who might met a similar situation.

It would be nice if someone said, “Actually, it’s simpler if you use this feature of Hugo.”

tags