Nav

Provide a helper to build menus and breadcrumbs.

Options See on deno.land

name string

The helper name

Default:
"nav"
order string

The default order for the children

Default:
"basename=asc-locale"

Description

This plugin registers the nav helper to build navigation stuff like menus and breadcrumbs in your pages.

Installation

Import this plugin in your _config.ts file to use it:

import lume from "lume/mod.ts";
import nav from "lume/plugins/nav.ts";

const site = lume();

site.use(nav(/* Options */));

export default site;

The function nav.menu() returns a tree object with the complete site structure using the pages' URLs to define the hierarchy. For example, let's say our site exports the following pages:

  • /
  • /articles/
  • /articles/first-article/
  • /articles/second-article/chapter-1/
  • /articles/second-article/chapter-2/

The object returned by nav.menu() would be like this:

{
  data: { basename: "", ...Data },
  children: [
    {
      data: { basename: "articles", ...Data },
      children: [
        {
          data: { basename: "first-article", ...Data },
        },
        {
          data: { basename: "second-article" },
          children: [
            {
              data: { basename: "chapter-1", ...Data },
            },
            {
              data: { basename: "chapter-2", ...Data },
            },
          ],
        },
      ],
    },
  ];
}

Some interesting things:

  • The data property contains the page data object. So you can access to any page variable like data.title or data.url.
  • The item with the basename second-article doesn't have more data because there isn't any page with the url /articles/second-article/. Note that there are pages inside this url (/articles/second-page/chapter-1/ and /articles/second-page/chapter-2/) that do have the data value.

You can use this object in your templates to build a menu recursively. For example in Vento:

<ul class="menu">
  {{ for item of nav.menu().children }}
    <li>
      {{ include "templates/menu_item.vto" { item } }}
    </li>
  {{ /for }}
</ul>
{{ if item.data.url }}
  <a href="{{ item.data.url }}">
    {{ item.data.title }}
  </a>
{{ else }}
  <span>{{ item.data.basename }}</span>
{{ /if }}

<ul>
  {{ for child of item.children }}
  <li>
    {{ include "templates/menu_item.vto" { item: child } }}
  </li>
  {{ /for }}
</ul>

Change the initial URL

If you want to start your menu from a specific page, just include it's url in the first argument:

nav.menu("/articles/");

Filtering and sorting

You can filter and sort the elements of the menu in the same way as the Search plugin. For example, let's build a menu with the english pages, sorted by URL:

nav.menu("/", "lang=en", "url=asc");

Export to JSON

The menu can be exported to JSON, useful to work with it in the frontend:

const menu = nav.menu();
JSON.stringify(menu);

Next and previous pages

Use the functions nav.nextPage() and nav.previousPage() to return the next and previous page of the menu relative to the current page.

For example, let's say we have the following tree structure created with nav.menu():

docs
  |__ getting-started
        |__ installation
        |__ configuration
  |__ plugins
        |__ prettier

The function nav.nextPage() returns the next page relative to the provided URL. For example:

const nextPage = nav.nextPage("/docs/getting-started/installation/");
console.log(nextPage.url); // /docs/getting-started/configuration/

If the page is the last sibling of the current section, it returns the first page of the next section:

const nextPage = nav.nextPage("/docs/getting-started/configuration/");
console.log(nextPage.url); // /docs/plugins/

If the current section has children, it returns the first child:

const nextPage = nav.nextPage("/docs/plugins/");
console.log(nextPage.url); // /docs/plugins/prettier/

The nav.previousPage() works similarly but in reverse order.

The first argument of these functions is the URL you want to use as current. Next arguments are the same as nav.menu(), so you can configure the base path, query and sort options to match the menu:

nav.menu("/", "lang=en", "url=asc");

nav.nextPage(url, "/", "lang=en", "url=asc");
nav.previousPage(url, "/", "lang=en", "url=asc");

The function nav.breadcrumb() returns an array of the parent items until the root. For example, the page /articles/second-article/chapter-2/ returns the following breadcrumb data:

[
  {
    slug: "chapter-2",
    data: Data,
  },
  {
    slug: "second-article",
    children: [...],
  },
  {
    slug: "articles",
    data: Data,
    children: [...],
  },
  {
    slug: "",
    data: Data,
    children: [...],
  }
]

We can use this data to generate the breadcrumb with the following Vento code:

<ul>
  {{ for item of nav.breadcrumb("/articles/second-article/chapter-2") }}
  <li>
    {{ if item.data }}
      <a href="{{ item.data.url }}">
        {{ item.data.title }}
      </a>
    {{ else }}
      <span>{{ item.slug }}</span>
    {{ /if }}
  </li>
  {{ /for }}
</ul>