Docs: Allow unlimited multi-level navigation (#1440)

* Remove `jekyll-default-layout` plugin

* Move docs/navigation-structure to docs/navigation

* Fix uses of line-nos in md files

* Update CHANGELOG.md

---------

Co-authored-by: Matt Wang <matt@matthewwang.me>
This commit is contained in:
Peter Mosses
2024-08-20 22:50:47 +02:00
committed by GitHub
parent a4e4e312aa
commit dd0b814bfd
45 changed files with 638 additions and 405 deletions

View File

@@ -0,0 +1,17 @@
---
title: Auxiliary Links
parent: Navigation
nav_order: 2
---
# Auxiliary Links
You can add a list of auxiliary links to your site, shown at the top right on all pages. You do this by including the `aux_links` [configuration option]({% link docs/configuration.md %}#aux-links) in your site's `_config.yml` file.
#### Example
```yaml
aux_links:
Just the Docs on GitHub:
- https://github.com/just-the-docs/just-the-docs
```

View File

@@ -0,0 +1,21 @@
---
title: Child Pages
parent: Navigation
nav_order: 4
---
# Child Pages
By default, all parent pages will automatically have a so-called 'Table of Contents' at the bottom, showing links to all their child pages.
To disable this automatic list, set `has_toc: false` in the parent page's front matter.
#### Example
```yaml
---
title: UI Components
nav_order: 3
has_toc: false
---
```

View File

@@ -0,0 +1,84 @@
---
title: In-Page Navigation
parent: Navigation
nav_order: 5
---
# In-Page Navigation
{: .no_toc }
## Table of Contents
{: .no_toc .text-delta }
1. TOC
{:toc}
To support in-page navigation, you can generate a *Table of Contents* (TOC) with links to headings, like the one shown above, as well as a link to the top of the page.
## Table of Contents
To generate a *Table of Contents* in a page, you use Kramdown's `{:toc}` method, immediately after the start of a list. This will automatically generate a list of anchor links to various sections of the page, based on headings and heading levels.
If you want to omit a particular heading from the TOC, follow it immediately by `{: .no_toc }` (possibly together with other CSS class names).
#### Example
{: .no_toc }
```markdown
# In-Page Navigation
{: .no_toc }
## Table of Contents
{: .no_toc .text-delta }
1. TOC
{:toc}
```
This example omits the top-level heading (`In-Page Navigation`) from the TOC, as well as the heading for the *Table of Contents* itself.
To get an unordered list, replace `1. TOC` by `- TOC` in the above example.
## Collapsible Table of Contents
You can make the Table of Contents collapsible using the `<details>` and `<summary>` elements, as in the following example.
#### Example
{: .no_toc }
```markdown
<details open markdown="block">
<summary>
Table of contents
</summary>
{: .text-delta }
1. TOC
{:toc}
</details>
```
The attribute `open` (which expands the Table of Contents by default) and the styling (here with `text-delta`) are optional.
{: .note }
`{:toc}` can be used only once on each page.
## Back to Top {#back-to-top-doc}
{: .warning }
The default id for a section with heading "Back to Top" is `"back-to-top"`.
To avoid invalid HTML, sites that set the `back_to_top` configuration variable
should override the default id for such sections. The Markdown source file for
the current page uses `## Back to Top {#back-to-top-doc}`.
You can add a link from the bottom of each page to its top. You do this by including the `back_to_top` configuration option in your site's `_config.yml` file, together with `back_to_top_text` for the anchor link.
### Example
{: .no_toc }
```yaml
back_to_top: true
back_to_top_text: "Back to top"
```
{: .warning }
Back-to-top links currently appear only when *other* configuration options require footer generation!

16
docs/navigation/index.md Normal file
View File

@@ -0,0 +1,16 @@
---
title: Navigation
nav_order: 5
---
# Navigation
The default page layout supports various navigation features:
* a **main navigation** panel, highlighting the currently selected page;
* a list of **auxiliary** links, shown on all pages;
* lists of **breadcrumbs**, shown on all except top level pages;
* optional lists of links to **child pages** (so-called 'tables of contents'); and
* section heading links for **in-page navigation**, with an optional **back-to-top** link.
See the following pages for how to specify these features, with illustrative examples.

View File

@@ -0,0 +1,51 @@
---
title: Ancestry
parent: Main Navigation
nav_order: 4
---
# Ancestry
If no two pages on your website have the same `title`, you only need to set the `parent` titles to fix the hierarchy. You can also have the same `title` on pages that have no children, provided that they have different parent pages.
If two parents have the same `title`, but different grandparents, you can set their `grand_parent` titles to distinguish between their parents. The `grand_parent` title needs to be the same as the `parent` of the `parent`.
#### Example
```yaml
---
title: T
parent: S
grand_parent: X
---
```
```yaml
---
title: T
parent: S
grand_parent: Y
---
```
The `ancestor` field of a page generalizes `grand_parent` to higher levels.
The following pages illustrate `parent` disambiguation using `grand_parent` and `ancestor` titles. Some descendants of both [Page X][X] and [Page Y][Y] have the same title, so references to those descendants as `parent` always require disambiguation.
- [X][X] is a parent page
- [S][XS] is the only child of [X][X]. The `parent` reference to [X][X] is unambiguous.
- [T][XT] is the only child of [S][XS]. Its `parent` is disambiguated by its `grand_parent`.
- [U][XU] is the only child of [T][XT]. Its `parent` is disambiguated by its `ancestor`.
- [Y][Y] is a sibling of [X][X].
- [S][YS] is the only child of [Y][Y]. The `parent` reference to [Y][Y] is unambiguous.
- [T][YT] is the only child of [S][YS]. Its `parent` is disambiguated by its `ancestor`
- [U][YU] is the only child of [T][YT]. Its `parent` is disambiguated by its `ancestor`.
[X]: {% link docs/navigation/main/x.md %}
[XS]: {% link docs/navigation/main/xs.md %}
[XT]: {% link docs/navigation/main/xt.md %}
[XU]: {% link docs/navigation/main/xu.md %}
[Y]: {% link docs/navigation/main/y.md %}
[YS]: {% link docs/navigation/main/ys.md %}
[YT]: {% link docs/navigation/main/yt.md %}
[YU]: {% link docs/navigation/main/yu.md %}

View File

@@ -0,0 +1,67 @@
---
title: Collections
parent: Main Navigation
nav_order: 5
---
# Collections
By default, the navigation includes only [normal pages](https://jekyllrb.com/docs/pages/).
However, you can configure Just the Docs to include also pages from [Jekyll collections](https://jekyllrb.com/docs/collections/).
{: .note }
> You store collection pages in directories that start with an underscore (`_`), e.g., `_tests`. You won't see your `tests` collection pages in the navigation if you store them in a `tests` directory![^1]
[^1]: You can optionally specify a directory to store all your collections. For example, if you specify `collections_dir: my_collections` in `_config.yml`, you should then store the pages of the `tests` collection in the `my_collections/_tests` directory.
#### Example
To define a Jekyll `tests` collection named `Tests` in your main navigation, store its pages in the `_tests` directory, and add the following to `_config.yml`:
```yaml
collections:
tests:
output: true
just_the_docs:
collections:
tests:
name: Tests
```
Together with the `name` to be used for a collection in the navigation, you can configure the following options:
* `nav_exclude: true` to exclude the entire collection from the main navigation
* `nav_fold: true` to fold the collection, instead of showing links to all its top-level pages[^2]
* `search_exclude: true` to exclude all the collection pages from search results
[^2]:
When JavaScript is disabled in the browser, all folded collections are automatically expanded,
since clicking expander symbols has no effect.
The main navigation for all your normal pages (if any) is displayed before those in collections. When *all* your pages are in a single collection, its name is not displayed.
You can configure multiple collections. This creates categories in the main navigation with the configured names.
#### Example
```yaml
collections:
tests:
output: true
tutorials:
output: true
just_the_docs:
collections:
tests:
name: Tests
search_exclude: true
tutorials:
name: Tutorials
nav_fold: true
```
The navigation for each collection is a separate name space for page titles: a page in one collection cannot be the `parent` of a page in a different collection, nor of a normal page.
----

View File

@@ -0,0 +1,29 @@
---
title: Excluding Pages
parent: Main Navigation
nav_order: 2
---
# Excluding Pages
For specific pages that you do not wish to include in the main navigation (e.g., a 404 page or a landing page) set `nav_exclude: true` in their front matter.
#### Example
```yaml
---
layout: default
title: 404
nav_exclude: true
permalink: /404
---
```
The `nav_exclude` parameter does not affect the [breadcrumbs]({% link docs/navigation/parents.md %}), nor the [lists of child pages]({% link docs/navigation/children.md %}), which you can use to access pages excluded from the main navigation.
Pages with no `title` are automatically excluded from the main navigation, except when they are in collections (where Jekyll provides default titles based on file names).
Child pages are automatically excluded from the main navigation when their parent page is excluded.
{: .warning }
It is currently possible to exclude all the child pages of a page from the main navigation by setting `has_children: false` in its front matter. However, the `has_children` parameter may be ignored altogether in a future release, so it is better to use the `nav_exclude` parameter on each child page.

View File

@@ -0,0 +1,33 @@
---
title: External Links
parent: Main Navigation
nav_order: 6
---
# External Links
To add external links to the navigation, add them to the `nav_external_links` [configuration]({% link docs/configuration.md %}) option in your site's `_config.yml` file.
External links will appear in the navigation after the links to ordinary pages, but before any collections.
#### Example
```yaml
# External navigation links
nav_external_links:
- title: Just the Docs on GitHub
url: https://github.com/just-the-docs/just-the-docs
hide_icon: false # set to true to hide the external link icon - defaults to false
opens_in_new_tab: false # set to true to open this link in a new tab - defaults to false
```
## Opening external links in a new tab
The external links are decorated by an icon, which distinguishes them from internal links.
You can suppress the icon by setting `hide_icon: true`.
By default, external links are not opened in a new tab. However, this can be enabled by:
1. setting `opens_in_new_tab: true` in the link's configuration object
2. setting the configuration option `nav_external_links_new_tab: true` in `_config.yml`
When they conflict, `opens_in_new_tab` takes precedence.

View File

@@ -0,0 +1,41 @@
---
title: Main Navigation
parent: Navigation
nav_order: 1
---
# Main Navigation
The main navigation for your Just the Docs site is at the left side of the page on large screens, and at the top (behind a tap) on small screens.
You need to specify the `title` of each page in its front matter. Page titles are independent of file names and directory structure. The navigation uses the title of the page as an anchor for links to the page.
By default, links to all pages appear in the main navigation at the top level, ordered alphabetically by their titles. By adding further fields to the front matter of individual pages, you can [change their order]({% link docs/navigation/main/order.md %}), [exclude pages]({% link docs/navigation/main/exclude.md %}), and change their [parent pages]({% link docs/navigation/main/levels.md %}).
{: .new-title }
> New (Multi-level)
>
> The main navigation can be structured as a multi-level menu of unlimited depth:
> pages can always have child pages.
For the construction of the navigation display to work (and to avoid potential confusion when browsing) ***the page titles on your site need to satisfy the following requirements:***
* Top-level pages must have different titles.
* Pages with the same parent must have different titles.
* The title of each page must be different from the titles of all its child pages, and from the titles of their child pages, etc.
{: .new-title }
> New (Multi-level)
>
> If *all* the pages of your site have different titles, you need only to specify the `title` of each page, and the `parent` title of each lower-level page.[^1]
[^1]: Previous versions of Just the Docs restricted the navigation to three levels. You also needed to specify `has_children: true` on all parent pages, and a `grand_parent` title on all grandchild pages. The `has_children` parameter is now redundant, and the `grand_parent` parameter can usually be omitted.
If your site has pages with the same title, you need to avoid confusion when you reference that title as `parent` on other pages. When the pages with the same title have different `parent` pages, you can distinguish between them using the `grand_parent` parameter.
{: .new-title }
> New (Multi-level)
>
> For deeper navigation structures, you can specify the title of a grandparent or higher level page as an `ancestor` title.
----

View File

@@ -0,0 +1,123 @@
---
title: Page Levels
parent: Main Navigation
nav_order: 3
---
# Page Levels
Sometimes you will want to create a page with many children. First, it is recommended that you store related pages together in a directory. For example, in these docs, we keep all of the written documentation pages in the `./docs` directory, and each of the sections in subdirectories like `./docs/ui-components` and `./docs/utilities`. This gives us an organization like this:
{: .lh-0 }
```
┌─ ...
├─ (Jekyll files)
├─ docs
├─ configuration.md
├─ ui-components
├─ index.md (parent page)
├─ buttons.md
├─ callouts.md
├─ code
├─ index.md (parent page)
└─ line-numbers.md
├─ labels.md
├─ tables.md
└─ typography.md
├─ ...
└─ MIGRATION.md
├─ index.md (home page)
├─ (Jekyll files)
└─ ...
```
#### Example
```yaml
---
title: UI Components
nav_order: 3
---
```
Here we're setting up the UI Components landing page that is available at URL `/docs/ui-components`, which is ordered second in the main navigation.
The navigation links for all pages with children come with an expander. When you click the expander, the display of the children is toggled, so you can expand or collapse all the children displays, regardless of which page is currently active.
## Child Pages
On child pages, simply set the `parent` front matter to the parent page's `title`, and set a navigation order (relative to pages having the same parent).
#### Example
```yaml
---
title: Buttons
parent: UI Components
nav_order: 2
---
```
The Buttons page appears as a child of UI Components and appears second in the UI Components pages.
{: .new-title }
> New (Multi-level)
>
> The `has_children` field is now redundant (and ignored, except when significant for backwards compatibility).
## Multi-level Child Pages
Child pages can themselves have children, to any number of levels.
#### Example
```yaml
---
title: Main Navigation
parent: Navigation
nav_order: 1
---
```
```yaml
---
title: Ancestry
parent: Main Navigation
nav_order: 4
---
```
```yaml
---
title: X
parent: Ancestry
---
```
```yaml
---
title: Y
parent: Ancestry
---
```
This creates the following navigation structure:
{: .lh-0 }
```
┌─ ...
├─ ...
├─ Navigation
├─ ...
├─ Main Navigation
├─ ...
├─ Ancestry
├─ X
└─ Y
├─ ...
└─ ...
├─ ...
└─ ...
├─ ...
└─ ...
```

View File

@@ -0,0 +1,35 @@
---
title: Ordering Pages
parent: Main Navigation
nav_order: 1
---
# Ordering Pages
To specify a page order, you can use the `nav_order` parameter in the front matter of the pages.
#### Example
```yaml
---
title: Customization
nav_order: 6
---
```
The parameter values determine the order of the top-level pages, and of child pages with the same parent. You can reuse the same parameter values (e.g., integers starting from 1) for the child pages of different parents.
The parameter values can be numbers (integers, floats[^floats]) and/or strings. When you omit `nav_order` parameters, they default to the titles of the pages, which are ordered alphabetically. Pages with numerical `nav_order` parameters always come before those with strings or default `nav_order` parameters. If you want to make the page order independent of the page titles, you can set explicit `nav_order` parameters on all pages.
{: .warning }
The order of pages with equal `nav_order` parameters is unstable: it may change with each build.
By default, all Capital letters come before all lowercase letters; you can add `nav_sort: case_insensitive` in the configuration file to ignore the case.[^case-insensitive]
Enclosing strings in quotation marks in front matter is optional, unless they contain "`[`", "`]`", "`{`", "`}`", "`,`", "`: `", or "` #`". Boolean, integer, and float values are treated as strings when enclosed in quotation marks.
----
[^floats]: Jekyll treats each integer *N* as equal to the corresponding float *N.0*.
[^case-insensitive]: *Note for users of previous versions of Just the Docs:* The option `nav_sort: case_insensitive` previously affected the ordering of numerical `nav_order` parameters: e.g., `10` came before `2`. Also, all pages with explicit `nav_order` parameters previously came before all pages with default parameters. Both were potentially confusing, and they have now been eliminated.

10
docs/navigation/main/x.md Normal file
View File

@@ -0,0 +1,10 @@
---
title: X
parent: Ancestry
---
# X
```yaml
title: X
parent: Ancestry
```

View File

@@ -0,0 +1,10 @@
---
title: S
parent: X
---
# S
```yaml
title: S
parent: X
```

View File

@@ -0,0 +1,12 @@
---
title: T
parent: S
grand_parent: X
---
# T
```yaml
title: T
parent: S
grand_parent: X
```

View File

@@ -0,0 +1,12 @@
---
title: U
parent: T
ancestor: X
---
# U
```yaml
title: U
parent: T
ancestor: X
```

10
docs/navigation/main/y.md Normal file
View File

@@ -0,0 +1,10 @@
---
title: Y
parent: Ancestry
---
# Y
```yaml
title: Y
parent: Ancestry
```

View File

@@ -0,0 +1,10 @@
---
title: S
parent: Y
---
# S
```yaml
title: S
parent: Y
```

View File

@@ -0,0 +1,12 @@
---
title: T
parent: S
ancestor: Y
---
# T
```yaml
title: T
parent: S
ancestor: Y
```

View File

@@ -0,0 +1,12 @@
---
title: U
parent: T
ancestor: Y
---
# U
```yaml
title: U
parent: T
ancestor: Y
```

View File

@@ -0,0 +1,11 @@
---
title: Breadcrumbs
parent: Navigation
nav_order: 3
---
# Breadcrumbs
When using the default layout, all pages except top-level pages will automatically have a list of 'breadcrumbs' at the top, linking to the parent page and to any higher-level ancestors.
The default layout does not provide an option to suppress the list of breadcrumbs. To do that, you would need to define a new layout, or override the file `_includes/components/breadcrumbs.html` (e.g., with an empty file).