diff --git a/_includes/sidebar.html b/_includes/sidebar.html deleted file mode 100644 index 3334ec8a057..00000000000 --- a/_includes/sidebar.html +++ /dev/null @@ -1,15 +0,0 @@ -{% assign sidebar = site.data.sidebars[page.sidebar].entries %} - - diff --git a/_includes/sidebar_recursive.html b/_includes/sidebar_recursive.html deleted file mode 100644 index 9a3870d487c..00000000000 --- a/_includes/sidebar_recursive.html +++ /dev/null @@ -1,122 +0,0 @@ -{% comment %} - Recursive sidebar: renders nested doc nav from _data/sidebars via folder.folderitems. - Parameters: item (folder node), level (1–4), parent_id (element id for data-bs-parent accordion group). - Branch rows use BS5 Collapse (data-bs-toggle, .collapse.show); leaves are plain nav-links. - Active state compares page.url (no leading slash) to each item url. -{% endcomment %} - -{% assign page_url_clean = page.url | remove_first: "/" %} - -{% assign item = include.item %} -{% assign title = item.title %} -{% assign url = item.url %} -{% assign folderitems = item.folderitems %} -{% assign subfolders = item.subfolders %} -{% assign subfolderitems = item.subfolderitems %} - -{% assign is_branch = false %} -{% if include.level == 1 %} - {% if folderitems.size > 0 %} - {% assign is_branch = true %} - {% endif %} -{% elsif include.level == 3 %} - {% assign is_branch = true %} -{% endif %} - -{% if is_branch == false %} - {% assign current_url_clean = url | remove_first: "/" %} - -{% else %} - {% capture current_uid %}{{ include.level }}-{{ title | slugify }}{% endcapture %} - {% assign current_id = current_uid | prepend: "sb-" %} - - {% assign any_active = false %} - {% assign current_url_clean = url | remove_first: "/" %} - {% if page_url_clean == current_url_clean and current_url_clean != "" %}{% assign any_active = true %}{% endif %} - - {% if any_active == false %} - {% for fi in folderitems %} - {% assign fi_url = fi.url | remove_first: "/" %} - {% if page_url_clean == fi_url and fi_url != "" %}{% assign any_active = true %}{% break %}{% endif %} - {% for sf in fi.subfolders %} - {% for sfi in sf.subfolderitems %} - {% assign sfi_url = sfi.url | remove_first: "/" %} - {% if page_url_clean == sfi_url and sfi_url != "" %}{% assign any_active = true %}{% break %}{% endif %} - {% endfor %} - {% if any_active %}{% break %}{% endif %} - {% endfor %} - {% if any_active %}{% break %}{% endif %} - {% endfor %} - {% endif %} - - {% if any_active == false %} - {% for sf in subfolders %} - {% for sfi in sf.subfolderitems %} - {% assign sfi_url = sfi.url | remove_first: "/" %} - {% if page_url_clean == sfi_url and sfi_url != "" %}{% assign any_active = true %}{% break %}{% endif %} - {% endfor %} - {% if any_active %}{% break %}{% endif %} - {% endfor %} - {% endif %} - - {% if any_active == false %} - {% for sfi in subfolderitems %} - {% assign sfi_url = sfi.url | remove_first: "/" %} - {% if page_url_clean == sfi_url and sfi_url != "" %}{% assign any_active = true %}{% break %}{% endif %} - {% endfor %} - {% endif %} - - -{% endif %} diff --git a/layouts/partials/sidebar.html b/layouts/partials/sidebar.html new file mode 100644 index 00000000000..c6743085b7f --- /dev/null +++ b/layouts/partials/sidebar.html @@ -0,0 +1,33 @@ +{{- /* Renders the sidebar navigation. Reads the sidebar key from page + params, looks up the matching data file in data/sidebars/, and + delegates tree rendering to sidebar_recursive.html. */ -}} +{{- $sidebarKey := .Param "sidebar" | default "home_sidebar" -}} +{{- $sidebarKeyText := strings.TrimSpace (printf "%v" $sidebarKey) -}} +{{- $hasNoSidebar := or (eq $sidebarKeyText "nil") (eq $sidebarKeyText "") (eq $sidebarKeyText "false") -}} +{{- if not $hasNoSidebar -}} +{{- $sidebarData := index hugo.Data.sidebars $sidebarKey -}} +{{- $entries := slice -}} +{{- with $sidebarData.entries }}{{ $entries = . }}{{ end -}} +{{- $firstEntry := index $entries 0 -}} + +{{- if $firstEntry -}} + {{- $product := $firstEntry.product | default $firstEntry.title | default "" -}} + {{- $version := $firstEntry.version | default "" -}} + +{{- else -}} + {{- with $sidebarKey }} + + {{- end }} +{{- end -}} +{{- end -}} diff --git a/layouts/partials/sidebar_is_web.html b/layouts/partials/sidebar_is_web.html new file mode 100644 index 00000000000..ddf592e6822 --- /dev/null +++ b/layouts/partials/sidebar_is_web.html @@ -0,0 +1,5 @@ +{{- /* Returns truthy if the item should appear in web output + (i.e. its "output" field contains "web", defaulting to yes). */ -}} +{{- $output := "web" -}} +{{- with .output }}{{ $output = printf "%v" . }}{{ end -}} +{{- if in $output "web" -}}true{{- end -}} diff --git a/layouts/partials/sidebar_item_active.html b/layouts/partials/sidebar_item_active.html new file mode 100644 index 00000000000..fc7e479c899 --- /dev/null +++ b/layouts/partials/sidebar_item_active.html @@ -0,0 +1,43 @@ +{{- /* Recursively checks if any item in the given subtree matches the + current page. Returns truthy when a match is found, used to + expand parent collapse sections. Params: item, current. */ -}} +{{- $item := .item -}} +{{- $current := .current -}} +{{- $active := false -}} + +{{- with $item.url }} + {{- if partial "sidebar_page_matches_url.html" (dict "page" $current "url" .) }} + {{- $active = true -}} + {{- end }} +{{- end -}} + +{{- if not $active }} + {{- range $child := $item.folderitems }} + {{- if partial "sidebar_item_active.html" (dict "item" $child "current" $current) }} + {{- $active = true -}} + {{- end }} + {{- range $subfolder := $child.subfolders }} + {{- if partial "sidebar_item_active.html" (dict "item" $subfolder "current" $current) }} + {{- $active = true -}} + {{- end }} + {{- end }} + {{- end }} +{{- end -}} + +{{- if not $active }} + {{- range $subfolder := $item.subfolders }} + {{- if partial "sidebar_item_active.html" (dict "item" $subfolder "current" $current) }} + {{- $active = true -}} + {{- end }} + {{- end }} +{{- end -}} + +{{- if not $active }} + {{- range $child := $item.subfolderitems }} + {{- if partial "sidebar_item_active.html" (dict "item" $child "current" $current) }} + {{- $active = true -}} + {{- end }} + {{- end }} +{{- end -}} + +{{- if $active -}}true{{- end -}} diff --git a/layouts/partials/sidebar_page_matches_url.html b/layouts/partials/sidebar_page_matches_url.html new file mode 100644 index 00000000000..7072fe3a4ae --- /dev/null +++ b/layouts/partials/sidebar_page_matches_url.html @@ -0,0 +1,20 @@ +{{- /* Checks if a page matches a target URL. Compares against the page's + RelPermalink, front-matter url, permalink, and aliases for a + reliable match regardless of how the URL was defined. */ -}} +{{- $page := .page -}} +{{- $target := partial "sidebar_url_clean.html" .url -}} +{{- $matches := false -}} +{{- if and $page $target }} + {{- $urls := slice -}} + {{- with $page.RelPermalink }}{{ $urls = $urls | append . }}{{ end -}} + {{- with $page.Params.url }}{{ $urls = $urls | append . }}{{ end -}} + {{- with $page.Params.permalink }}{{ $urls = $urls | append . }}{{ end -}} + {{- with $page.Params.aliases }} + {{- range . }}{{ $urls = $urls | append . }}{{ end -}} + {{- end -}} + {{- range $urls }} + {{- $clean := partial "sidebar_url_clean.html" . -}} + {{- if eq $clean $target }}{{ $matches = true }}{{ end -}} + {{- end }} +{{- end -}} +{{- if $matches -}}true{{- end -}} diff --git a/layouts/partials/sidebar_recursive.html b/layouts/partials/sidebar_recursive.html new file mode 100644 index 00000000000..ed0de138968 --- /dev/null +++ b/layouts/partials/sidebar_recursive.html @@ -0,0 +1,83 @@ +{{- /* Recursively renders a sidebar tree node. + Leaf items become plain nav-links; branch items become collapsible + sections (Bootstrap 5 collapse). Params: item, current (page context), + level (nesting depth, 1-based), parentID (BS collapse parent). */ -}} +{{- $item := .item -}} +{{- $current := .current -}} +{{- $level := .level | default 1 -}} +{{- $parentID := .parentID | default "mysidebar" -}} +{{- $title := $item.title | default "" -}} +{{- $url := $item.url | default "" -}} +{{- $folderitems := $item.folderitems | default (slice) -}} +{{- $subfolders := $item.subfolders | default (slice) -}} +{{- $subfolderitems := $item.subfolderitems | default (slice) -}} +{{- $isBranch := false -}} +{{- if eq $level 1 }} + {{- if gt (len $folderitems) 0 }}{{ $isBranch = true }}{{ end -}} +{{- else if eq $level 3 }} + {{- $isBranch = true -}} +{{- end -}} +{{- $isActive := partial "sidebar_item_active.html" (dict "item" $item "current" $current) -}} +{{- $isCurrent := false -}} +{{- if $url }} + {{- $isCurrent = partial "sidebar_page_matches_url.html" (dict "page" $current "url" $url) -}} +{{- end -}} + +{{- if not $isBranch -}} + {{- $href := partial "sidebar_resolve_url.html" (dict "url" $url) -}} + +{{- else -}} + {{- $currentID := printf "sb-%d-%s" $level ($title | anchorize) -}} + {{- $nextLevel := add $level 1 -}} + +{{- end -}} diff --git a/layouts/partials/sidebar_resolve_url.html b/layouts/partials/sidebar_resolve_url.html new file mode 100644 index 00000000000..7c3d5f7c954 --- /dev/null +++ b/layouts/partials/sidebar_resolve_url.html @@ -0,0 +1,11 @@ +{{- /* Resolves a sidebar URL for use in href attributes. External URLs + (http, https, mailto, #) are returned as-is; internal paths + are passed through relURL. */ -}} +{{- $rawURL := .url | default "" -}} +{{- $isExternal := or (hasPrefix $rawURL "http://") (or (hasPrefix $rawURL "https://") (or (hasPrefix $rawURL "mailto:") (hasPrefix $rawURL "#"))) -}} + +{{- if $isExternal -}} + {{- $rawURL -}} +{{- else -}} + {{- $rawURL | relURL -}} +{{- end -}} diff --git a/layouts/partials/sidebar_url_clean.html b/layouts/partials/sidebar_url_clean.html new file mode 100644 index 00000000000..a6cc3b3a4b9 --- /dev/null +++ b/layouts/partials/sidebar_url_clean.html @@ -0,0 +1,8 @@ +{{- /* Normalises a URL for comparison: trims whitespace and strips + leading/trailing slashes so "docs/foo/" matches "docs/foo". */ -}} +{{- $url := "" -}} +{{- with . }}{{ $url = printf "%v" . }}{{ end -}} +{{- $url = strings.TrimSpace $url -}} +{{- $url = strings.TrimPrefix "/" $url -}} +{{- $url = strings.TrimSuffix "/" $url -}} +{{- $url -}}