mirror of https://github.com/docker/docs.git
hugo: render site navigation using sections
Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
This commit is contained in:
parent
135870fc13
commit
c36309ed8a
|
@ -24,9 +24,12 @@ The website is built using [Hugo](https://gohugo.io/). The content is primarily
|
|||
Markdown files in the `/content` directory of this repository (with a few
|
||||
exceptions, see [Content not edited here](#content-not-edited-here)).
|
||||
|
||||
The structure of the sidebar navigation on the site is defined in
|
||||
[`/data/toc.yaml`](./data/toc.yaml). To rename or change the location of a page
|
||||
in the left-hand navigation, edit the `toc.yaml` file.
|
||||
The structure of the sidebar navigation on the site is defined by the site's
|
||||
section hierarchy in the `contents` directory. The titles of the pages are
|
||||
defined in the front matter of the Markdown files. You can use `title` and
|
||||
`linkTitle` to define the title of the page. `title` is used for the page
|
||||
title, and `linkTitle` is used for the sidebar title. If `linkTitle` is not
|
||||
defined, the `title` is used for both.
|
||||
|
||||
You must fork this repository to create a pull request to propose changes. For more details, see [Local setup](#local-setup).
|
||||
|
||||
|
|
|
@ -31,14 +31,6 @@
|
|||
@apply dark:hue-rotate-180 dark:invert dark:filter;
|
||||
}
|
||||
|
||||
.sidebar-hover {
|
||||
@apply hover:bg-gray-light-200 hover:dark:bg-gray-dark-200;
|
||||
}
|
||||
|
||||
.sidebar-underline {
|
||||
@apply underline decoration-blue-light decoration-4 underline-offset-4 dark:decoration-blue-dark;
|
||||
}
|
||||
|
||||
.bg-pattern-blue {
|
||||
background-color: theme(colors.white / 50%);
|
||||
background-image: url('/assets/images/bg-pattern-blue.webp');
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
function toggleMenuItem(event) {
|
||||
const section = event.currentTarget.parentElement;
|
||||
const icons = event.currentTarget.querySelectorAll(".icon-svg");
|
||||
const subsection = section.querySelector("ul");
|
||||
subsection.classList.toggle("hidden");
|
||||
icons.forEach(i => i.classList.toggle('hidden'))
|
||||
}
|
||||
|
||||
const sectiontree = document.querySelector("#sectiontree");
|
||||
if (sectiontree) {
|
||||
for (const button of sectiontree.querySelectorAll("button")) {
|
||||
button.addEventListener("click", toggleMenuItem);
|
||||
}
|
||||
}
|
2441
data/toc.yaml
2441
data/toc.yaml
File diff suppressed because it is too large
Load Diff
10
hugo.yaml
10
hugo.yaml
|
@ -120,19 +120,19 @@ params:
|
|||
menus:
|
||||
main:
|
||||
- name: Get started
|
||||
url: /get-started/
|
||||
pageRef: /get-started/
|
||||
weight: 1
|
||||
- name: Guides
|
||||
url: /guides/
|
||||
pageRef: /guides/
|
||||
weight: 2
|
||||
- name: Manuals
|
||||
url: /manuals/
|
||||
pageRef: /manuals/
|
||||
weight: 3
|
||||
- name: Reference
|
||||
url: /reference/
|
||||
pageRef: /reference/
|
||||
weight: 4
|
||||
- name: Learning paths
|
||||
url: /learning-paths/
|
||||
pageRef: /learning-paths/
|
||||
weight: 5
|
||||
|
||||
footer:
|
||||
|
|
|
@ -307,12 +307,16 @@
|
|||
"highlight",
|
||||
"hover:bg-blue-light-400",
|
||||
"hover:bg-gray-light-100",
|
||||
"hover:bg-gray-light-300",
|
||||
"hover:border-gray-light-200",
|
||||
"hover:dark:bg-gray-dark-300",
|
||||
"hover:dark:border-gray-dark",
|
||||
"hover:dark:text-blue-dark",
|
||||
"hover:drop-shadow-lg",
|
||||
"hover:opacity-75",
|
||||
"hover:opacity-90",
|
||||
"hover:text-black",
|
||||
"hover:text-blue-light",
|
||||
"hover:underline",
|
||||
"hub-api",
|
||||
"icon-lg",
|
||||
|
@ -451,9 +455,9 @@
|
|||
"scale-75",
|
||||
"scroll-mt-20",
|
||||
"scroll-mt-36",
|
||||
"select-none",
|
||||
"self-center",
|
||||
"shadow",
|
||||
"sidebar-hover",
|
||||
"sm:flex-row",
|
||||
"sm:grid-cols-2",
|
||||
"sm:items-center",
|
||||
|
|
|
@ -1,18 +1,7 @@
|
|||
{{ $scratch := partialCached "utils/tocparser.html" . . }}
|
||||
{{ $ctx := . }}
|
||||
|
||||
|
||||
<nav id="breadcrumbs" data-pagefind-ignore class="py-4 gap-4 flex items-center text-gray-light dark:text-gray-dark max-w-full min-w-0">
|
||||
{{ with ($scratch.GetSortedMapValues "sections") }}
|
||||
{{ range $i, $e := . }}
|
||||
{{- if $i -}}
|
||||
<span>/</span>
|
||||
{{- end -}}
|
||||
<a href="{{ $e.path }}" class="link truncate">{{ markdownify $e.title }}</a>
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- with $scratch.Get "lastsection" -}}
|
||||
<span>/</span>
|
||||
<span class="truncate">{{ markdownify .title }}</span>
|
||||
{{- end -}}
|
||||
{{ range .Ancestors.Reverse }}
|
||||
<a href="{{ .Permalink }}" class="link truncate">{{ markdownify .LinkTitle }}</a>
|
||||
<span>/</span>
|
||||
{{- end }}
|
||||
<span class="truncate">{{ markdownify .LinkTitle }}</span>
|
||||
</nav>
|
||||
|
|
|
@ -1,74 +1,78 @@
|
|||
{{/* Parse toc.yaml and store the resulting map to $scratch */}}
|
||||
{{ $scratch := partialCached "utils/tocparser.html" . . }}
|
||||
{{ $ctx := . }}
|
||||
|
||||
{{/* Get the name of the first section */}}
|
||||
{{ $firstSection := (index ($scratch.GetSortedMapValues "sections") 0).title }}
|
||||
|
||||
{{/* Render the top-nav in sidebar for small screens */}}
|
||||
<nav class="text-sm pb-4 gap-4 flex md:hidden flex-col justify-evenly">
|
||||
<div class="text-gray-light dark:text-gray-dark">Main sections</div>
|
||||
{{ range site.Menus.main }}
|
||||
<div class="pl-2 underline-offset-8 decoration-2 hover:underline decoration-blue-light dark:decoration-blue-dark hover:opacity-75
|
||||
{{- if eq $firstSection .Name }}
|
||||
{{- if or (page.IsDescendant .Page) (eq page .Page) }}
|
||||
underline
|
||||
{{- end }}">
|
||||
<a href="{{ .URL }}">{{ .Name }}</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
</nav>
|
||||
{{ if $firstSection }}
|
||||
{{ $allSections := slice }}
|
||||
{{ range $i, $e := ($scratch.GetSortedMapValues "sections") }}
|
||||
{{ $allSections = $allSections | append (index $e "title") }}
|
||||
{{ end }}
|
||||
<nav id="sectiontree" class="text-sm flex flex-col">
|
||||
<nav class="text-sm flex flex-col">
|
||||
<div class="block py-4 md:hidden text-gray-light dark:text-gray-dark">This section</div>
|
||||
{{/* The current page is in the table of contents */}}
|
||||
<ul>
|
||||
{{/* Walk the toc.yaml nodes under the current main section */}}
|
||||
{{ range (index site.Data.toc $firstSection) }}
|
||||
{{ template "tocRender" (dict "ctx" $ctx "entry" . "sections" $allSections) }}
|
||||
{{ end }}
|
||||
{{ template "renderSingle" .FirstSection }}
|
||||
{{ template "renderChildren" .FirstSection }}
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
{{ define "renderChildren" }}
|
||||
{{- range .Pages }}
|
||||
{{- if eq .Params.sitemap false }}
|
||||
{{- continue }}
|
||||
{{- end }}
|
||||
{{- if .IsSection }}
|
||||
{{- template "renderList" . }}
|
||||
{{- else }}
|
||||
{{- template "renderSingle" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
|
||||
{{/* Recursive template for sidebar items */}}
|
||||
{{ define "tocRender" }}
|
||||
{{ $ctx := .ctx }}
|
||||
{{ $sections := .sections }}
|
||||
{{ if .entry.sectiontitle }}
|
||||
{{ $expanded := in $sections .entry.sectiontitle }}
|
||||
{{/* .entry is a section */}}
|
||||
<li>
|
||||
{{/* See event handler in assets/js/src/sidebar.js */}}
|
||||
<button class="rounded px-4 sidebar-hover w-full flex items-center justify-between">
|
||||
<span class="py-2 truncate flex items-center gap-2">
|
||||
{{ markdownify .entry.sectiontitle }}
|
||||
</span>
|
||||
<span class="icon-svg {{ if $expanded }}hidden{{ end }}">
|
||||
{{ partialCached "icon" "expand_more" "expand_more" }}
|
||||
</span>
|
||||
<span class="icon-svg {{ if not $expanded }}hidden{{ end }}">
|
||||
{{ partialCached "icon" "expand_less" "expand_less" }}
|
||||
</span>
|
||||
</button>
|
||||
<ul class="{{if not $expanded}}hidden {{end}}ml-3">
|
||||
{{ range .entry.section }}
|
||||
{{ template "tocRender" (dict "entry" . "ctx" $ctx "sections" $sections ) }}
|
||||
{{ end }}
|
||||
</ul>
|
||||
</li>
|
||||
{{ else }}
|
||||
{{/* .entry is a page */}}
|
||||
{{ $isCurrent := eq (urls.Parse $ctx.Permalink).Path .entry.path }}
|
||||
<li class="pl-4 sidebar-hover rounded
|
||||
{{ if $isCurrent }} bg-gray-light-200 dark:bg-gray-dark-200{{ end }}">
|
||||
<a {{ if $isCurrent }}aria-current="page" {{ end }} class="py-2 w-full truncate block"
|
||||
href="{{ .entry.path }}" title="{{ markdownify .entry.title }}"
|
||||
><span class="flex items-center gap-2">{{ markdownify .entry.title }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{{ define "renderList" }}
|
||||
{{ $isCurrent := eq page . }}
|
||||
{{ $expanded := or $isCurrent (page.IsDescendant .) }}
|
||||
<li x-data="{ expanded: {{$expanded}} }">
|
||||
<div class="rounded px-4 w-full flex items-center justify-between{{ if $isCurrent }} bg-gray-light-200 dark:bg-gray-dark-200{{ end }}">
|
||||
<span class="py-2 truncate flex items-center gap-2">
|
||||
{{- if .Permalink }}
|
||||
{{/* If the link is not empty, use it */}}
|
||||
<a class="select-none hover:text-blue-light hover:dark:text-blue-dark"
|
||||
href="{{ .Permalink }}">{{ markdownify .LinkTitle }}</a>
|
||||
{{- else }}
|
||||
{{/* Otherwise, just expand the section */}}
|
||||
<button @click="expanded = !expanded"
|
||||
class="select-none hover:text-blue-light hover:dark:text-blue-dark">
|
||||
{{ markdownify .LinkTitle }}
|
||||
</button>
|
||||
{{- end }}
|
||||
</span>
|
||||
<button @click="expanded = !expanded" class="hover:bg-gray-light-300 hover:dark:bg-gray-dark-300 rounded">
|
||||
<span :class="{ 'hidden' : expanded }" class="icon-svg {{ if $expanded }}hidden{{ end }}">
|
||||
{{ partialCached "icon" "expand_more" "expand_more" }}
|
||||
</span>
|
||||
<span :class="{ 'hidden' : !expanded }" class="icon-svg {{ if not $expanded }}hidden{{ end }}">
|
||||
{{ partialCached "icon" "expand_less" "expand_less" }}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<ul :class="{ 'hidden' : !expanded }" class="{{if not $expanded}}hidden {{end}}ml-3">
|
||||
{{ template "renderChildren" . }}
|
||||
</ul>
|
||||
</li>
|
||||
{{ end }}
|
||||
|
||||
{{ define "renderSingle" }}
|
||||
{{ $isCurrent := eq page . }}
|
||||
<li class="pl-4 hover:text-blue-light hover:dark:text-blue-dark
|
||||
{{ if $isCurrent }} bg-gray-light-200 dark:bg-gray-dark-200{{ end }}">
|
||||
<a {{ if $isCurrent }}aria-current="page" {{ end }} class="py-2 w-full truncate block"
|
||||
href="{{ .Permalink }}" title="{{ markdownify .Title }}"
|
||||
><span class="flex items-center gap-2">{{ markdownify .LinkTitle }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{{ end }}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
{{ $scratch := partialCached "utils/tocparser.html" . . }}
|
||||
{{ $firstSection := (index ($scratch.GetSortedMapValues "sections") 0).title }}
|
||||
<div>
|
||||
<nav>
|
||||
<ul class="mt-1 box-content hidden gap-4 md:flex">
|
||||
{{ range site.Menus.main }}
|
||||
<li {{- if or (eq $firstSection .Name) }} class="border-b-4" {{- end }}>
|
||||
<li {{- if or (eq page .Page) (page.IsDescendant .Page) }} class="border-b-4" {{- end }}>
|
||||
<a class="block px-2 py-1" href="{{ .URL }}">{{ .Name }}</a>
|
||||
</li>
|
||||
{{ end }}
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
{{ $ctx := . }}
|
||||
{{ $scratch := newScratch }}
|
||||
{{ $toc := site.Data.toc }}
|
||||
{{ range $root, $section := $toc }}
|
||||
{{ if ne ($scratch.Get "match") true }}
|
||||
{{ $scratch.Set "depth" 1 }}
|
||||
{{ $rootSectionLink := "" }}
|
||||
{{ with (index $section 0) }}
|
||||
{{ if .path }}
|
||||
{{ $rootSectionLink = .path }}
|
||||
{{ else }}
|
||||
{{ $rootSectionLink = (index .section 0).path }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ $scratch.SetInMap "sections" "1" (dict "title" $root "path" $rootSectionLink) }}
|
||||
{{ template "tocWalk" (dict "scratch" $scratch "section" $section "ctx" $ctx) }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ define "tocWalk" }}
|
||||
{{ $ctx := .ctx }}
|
||||
{{ $scratch := .scratch }}
|
||||
{{ $scratch.Set "depth" (add ($scratch.Get "depth") 1) }}
|
||||
{{ range .section }}
|
||||
{{ if ne ($scratch.Get "match") true }}
|
||||
{{ if .path }}
|
||||
{{ $match := eq (urls.Parse .path).Path (urls.Parse $ctx.Permalink).Path }}
|
||||
{{ if $match }}
|
||||
{{ $scratch.Set "match" true }}
|
||||
{{ $scratch.Set "maxdepth" ($scratch.Get "depth") }}
|
||||
{{ $scratch.Set "lastsection" (dict "title" .title "path" .path) }}
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
{{ $sectionLink := (index .section 0).path }}
|
||||
{{ $scratch.SetInMap "sections" (string ($scratch.Get "depth")) (dict "title" .sectiontitle "path" $sectionLink) }}
|
||||
{{ template "tocWalk" (dict "scratch" $scratch "section" .section "ctx" $ctx) }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ $scratch.Set "depth" (sub ($scratch.Get "depth") 1) }}
|
||||
{{ end }}
|
||||
|
||||
{{ range $depth, $e := ($scratch.Get "sections") }}
|
||||
{{ if ge $depth ($scratch.Get "maxdepth") }}
|
||||
{{ $scratch.DeleteInMap "sections" $depth }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ return $scratch }}
|
|
@ -20,8 +20,6 @@
|
|||
</thead>
|
||||
<tbody>
|
||||
{{ range .Paginator.Pages }}
|
||||
{{ $scratch := partialCached "utils/tocparser.html" . . }}
|
||||
{{ $sections := $scratch.GetSortedMapValues "sections" }}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{ .Permalink }}" class="link">
|
||||
|
@ -30,10 +28,9 @@
|
|||
</td>
|
||||
<td>
|
||||
<span class="text-gray-light dark:text-gray-dark">
|
||||
{{ range $i, $e := $sections }}
|
||||
{{ if $i }} / {{ end }}
|
||||
{{ $e.title }}
|
||||
{{ end }}
|
||||
{{- range .Ancestors.Reverse }}
|
||||
{{ .Title }} /
|
||||
{{- end }}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
Loading…
Reference in New Issue