jekyll-theme-zer0 1.24.0 → 1.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +124 -0
- data/README.md +4 -4
- data/_data/authors.yml +1 -0
- data/_data/backlog.yml +26 -1
- data/_data/features.yml +73 -45
- data/_data/feedback_types.yml +148 -0
- data/_data/navigation/README.md +16 -6
- data/_data/navigation/main.yml +0 -8
- data/_data/roadmap.yml +1 -0
- data/_includes/README.md +10 -7
- data/_includes/analytics/google-analytics.html +1 -0
- data/_includes/analytics/google-tag-manager-body.html +1 -0
- data/_includes/analytics/google-tag-manager-head.html +1 -0
- data/_includes/analytics/posthog.html +1 -0
- data/_includes/components/README.md +3 -1
- data/_includes/components/admin-links.html +63 -0
- data/_includes/components/admin-tabs.html +1 -0
- data/_includes/components/ai-chat.html +27 -5
- data/_includes/components/author-eeat.html +1 -0
- data/_includes/components/background-customizer.html +1 -0
- data/_includes/components/background-settings.html +36 -37
- data/_includes/components/component-showcase.html +1 -0
- data/_includes/components/cookie-consent.html +1 -0
- data/_includes/components/dev-shortcuts.html +1 -8
- data/_includes/components/env-switcher.html +90 -138
- data/_includes/components/feature-card.html +1 -1
- data/_includes/components/halfmoon.html +22 -41
- data/_includes/components/info-section.html +127 -130
- data/_includes/components/mermaid.html +1 -0
- data/_includes/components/nanobar.html +1 -0
- data/_includes/components/page-feedback.html +252 -0
- data/_includes/components/post-type-badge.html +1 -0
- data/_includes/components/preview-image.html +1 -0
- data/_includes/components/search-modal.html +1 -0
- data/_includes/components/searchbar.html +1 -0
- data/_includes/components/shortcuts-modal.html +1 -0
- data/_includes/components/theme-info.html +21 -30
- data/_includes/components/theme-preview-gallery.html +1 -0
- data/_includes/content/backlinks.html +1 -0
- data/_includes/content/giscus.html +1 -0
- data/_includes/content/intro.html +20 -62
- data/_includes/content/jsonld-faq.html +1 -0
- data/_includes/content/seo.html +1 -0
- data/_includes/content/sitemap.html +1 -0
- data/_includes/content/toc.html +1 -0
- data/_includes/core/color-mode-init.html +1 -0
- data/_includes/core/console-capture.html +89 -0
- data/_includes/core/footer.html +1 -0
- data/_includes/core/head.html +5 -0
- data/_includes/core/header.html +5 -15
- data/_includes/navigation/admin-nav.html +1 -0
- data/_includes/navigation/breadcrumbs.html +1 -0
- data/_includes/navigation/local-graph-fab.html +3 -9
- data/_includes/navigation/local-graph.html +4 -9
- data/_includes/navigation/navbar.html +1 -0
- data/_includes/navigation/sidebar-categories.html +56 -14
- data/_includes/navigation/sidebar-config.html +115 -0
- data/_includes/navigation/sidebar-folders.html +168 -62
- data/_includes/navigation/sidebar-left.html +29 -52
- data/_includes/navigation/sidebar-nav.html +30 -0
- data/_includes/navigation/sidebar-right.html +1 -0
- data/_includes/navigation/toc-fab.html +3 -9
- data/_includes/navigation/unified-drawer.html +7 -14
- data/_includes/obsidian/full-graph.html +1 -0
- data/_includes/setup/wizard.html +1 -0
- data/_includes/stats/stats-categories.html +1 -0
- data/_includes/stats/stats-header.html +1 -0
- data/_includes/stats/stats-metrics.html +1 -0
- data/_includes/stats/stats-overview.html +1 -0
- data/_includes/stats/stats-tags.html +1 -0
- data/_layouts/admin.html +1 -0
- data/_layouts/article.html +1 -0
- data/_layouts/author.html +1 -0
- data/_layouts/authors.html +1 -0
- data/_layouts/collection.html +1 -0
- data/_layouts/default.html +14 -37
- data/_layouts/home.html +1 -0
- data/_layouts/index.html +1 -0
- data/_layouts/landing.html +1 -0
- data/_layouts/news.html +1 -0
- data/_layouts/note.html +1 -0
- data/_layouts/notebook.html +1 -0
- data/_layouts/root.html +6 -2
- data/_layouts/search.html +1 -0
- data/_layouts/section.html +1 -0
- data/_layouts/setup.html +1 -0
- data/_layouts/sitemap-collection.html +1 -0
- data/_layouts/stats.html +1 -0
- data/_layouts/tag.html +1 -0
- data/_layouts/welcome.html +1 -0
- data/_plugins/author_pages_generator.rb +1 -0
- data/_plugins/obsidian_links.rb +1 -0
- data/_plugins/preview_image_generator.rb +1 -0
- data/_plugins/search_and_sitemap_generator.rb +1 -0
- data/_plugins/theme_version.rb +1 -0
- data/_sass/components/_author.scss +12 -1
- data/_sass/components/_footer.scss +22 -0
- data/_sass/components/_page-feedback.scss +276 -0
- data/_sass/components/_ui-enhancements.scss +9 -0
- data/_sass/core/_docs-layout.scss +3 -78
- data/_sass/core/_navbar.scss +10 -27
- data/_sass/core/_obsidian.scss +2 -2
- data/_sass/core/code-copy.scss +10 -0
- data/_sass/custom.scss +1 -0
- data/_sass/notebooks.scss +1 -0
- data/_sass/theme/_backgrounds.scss +7 -2
- data/_sass/tokens/_layers.scss +4 -0
- data/_sass/utilities/_layout.scss +11 -0
- data/assets/css/main.scss +3 -1
- data/assets/js/ai-chat.js +1 -0
- data/assets/js/author-profile.js +1 -0
- data/assets/js/auto-hide-nav.js +1 -0
- data/assets/js/back-to-top.js +1 -0
- data/assets/js/background-customizer.js +1 -0
- data/assets/js/code-copy.js +1 -0
- data/assets/js/halfmoon.js +23 -22
- data/assets/js/modules/navigation/gestures.js +1 -0
- data/assets/js/modules/navigation/keyboard.js +1 -0
- data/assets/js/modules/navigation/scroll-spy.js +1 -0
- data/assets/js/modules/navigation/sidebar-state.js +1 -0
- data/assets/js/modules/navigation/sidebar-visibility.js +1 -0
- data/assets/js/modules/navigation/smooth-scroll.js +1 -0
- data/assets/js/modules/theme/appearance.js +52 -16
- data/assets/js/nanobar-init.js +1 -0
- data/assets/js/navigation.js +1 -0
- data/assets/js/obsidian-graph.js +1 -0
- data/assets/js/obsidian-wiki-links.js +1 -0
- data/assets/js/page-feedback.js +660 -0
- data/assets/js/palette-generator.js +1 -0
- data/assets/js/particles-source.js +1 -0
- data/assets/js/search-modal.js +1 -0
- data/assets/js/setup-wizard.js +1 -0
- data/assets/js/share-actions.js +1 -0
- data/assets/js/skin-editor.js +1 -0
- data/assets/js/table-copy.js +1 -0
- data/assets/js/theme-customizer.js +1 -0
- data/scripts/analyze-commits.sh +1 -0
- data/scripts/bin/giscus-discussions +1 -0
- data/scripts/bin/install +1 -0
- data/scripts/bin/validate +1 -0
- data/scripts/build +1 -0
- data/scripts/content-review.rb +1 -0
- data/scripts/convert-notebooks.sh +4 -3
- data/scripts/fix-markdown-format.sh +1 -0
- data/scripts/generate-preview-images.sh +1 -0
- data/scripts/generate-roadmap.sh +1 -0
- data/scripts/install-preview-generator.sh +1 -0
- data/scripts/release +1 -0
- data/scripts/requirements.txt +11 -0
- data/scripts/setup.sh +1 -0
- data/scripts/tag-features +136 -0
- data/scripts/validate-features.rb +7 -0
- data/scripts/vendor-install.sh +1 -0
- metadata +13 -4
- data/_data/prompts.yml +0 -302
- data/_plugins/admin_page_urls.rb +0 -16
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
{%- comment -%}
|
|
2
|
+
Component: sidebar-config
|
|
3
|
+
Path: _includes/navigation/sidebar-config.html
|
|
4
|
+
Purpose: Resolve the effective left-sidebar configuration for the
|
|
5
|
+
current page. Jekyll `assign`s inside an include propagate to
|
|
6
|
+
the including template, so this is the single source of truth
|
|
7
|
+
shared by _layouts/default.html, _includes/core/header.html,
|
|
8
|
+
navigation/sidebar-left.html and navigation/unified-drawer.html
|
|
9
|
+
(previously each duplicated this logic and drifted).
|
|
10
|
+
Params: none — reads page / collection / site state.
|
|
11
|
+
Sets (caller scope):
|
|
12
|
+
sidebar_enabled — false when the page opts out entirely
|
|
13
|
+
(`sidebar: false`, or featured/breaking
|
|
14
|
+
post_type with no explicit setting)
|
|
15
|
+
sidebar_nav — resolved concrete mode: "collection",
|
|
16
|
+
"categories", "tags", or the name of a
|
|
17
|
+
_data/navigation/*.yml file (nil = none)
|
|
18
|
+
sidebar_has_content — true only when sidebar_nav will actually
|
|
19
|
+
render items (gates the left column and
|
|
20
|
+
the mobile toggle)
|
|
21
|
+
sidebar_title — heading text for the sidebar panel
|
|
22
|
+
sidebar_icon — Bootstrap Icons class for the heading
|
|
23
|
+
Config precedence (most specific wins):
|
|
24
|
+
1. page.sidebar (false | true | {nav, title, icon, ...})
|
|
25
|
+
2. `sidebar:` metadata on the page's collection (_config.yml
|
|
26
|
+
`collections.<label>.sidebar.{nav,title,icon}`)
|
|
27
|
+
3. site.sidebar ({nav, title, icon} in _config.yml)
|
|
28
|
+
Notes: `nav: auto` picks the best mode for the page's collection —
|
|
29
|
+
a curated _data/navigation/<collection>.yml wins, then the
|
|
30
|
+
live "collection" folder tree, then post "categories".
|
|
31
|
+
{%- endcomment -%}
|
|
32
|
+
|
|
33
|
+
{%- comment -%} 1. Visibility: page.sidebar wins; featured/breaking posts default off {%- endcomment -%}
|
|
34
|
+
{%- assign sidebar_enabled = true -%}
|
|
35
|
+
{%- if page.sidebar == false -%}
|
|
36
|
+
{%- assign sidebar_enabled = false -%}
|
|
37
|
+
{%- elsif page.sidebar == nil -%}
|
|
38
|
+
{%- if page.post_type == "featured" or page.post_type == "breaking" -%}
|
|
39
|
+
{%- assign sidebar_enabled = false -%}
|
|
40
|
+
{%- endif -%}
|
|
41
|
+
{%- endif -%}
|
|
42
|
+
|
|
43
|
+
{%- comment -%} 2. Collection-level sidebar metadata (optional) {%- endcomment -%}
|
|
44
|
+
{%- assign sidebar_collection_cfg = nil -%}
|
|
45
|
+
{%- if page.collection -%}
|
|
46
|
+
{%- assign _sidebar_coll = site.collections | where: "label", page.collection | first -%}
|
|
47
|
+
{%- if _sidebar_coll -%}
|
|
48
|
+
{%- assign sidebar_collection_cfg = _sidebar_coll.sidebar -%}
|
|
49
|
+
{%- endif -%}
|
|
50
|
+
{%- endif -%}
|
|
51
|
+
|
|
52
|
+
{%- comment -%} 3. Nav mode: page → collection metadata → site default {%- endcomment -%}
|
|
53
|
+
{%- assign sidebar_nav = nil -%}
|
|
54
|
+
{%- if sidebar_enabled -%}
|
|
55
|
+
{%- if page.sidebar.nav -%}
|
|
56
|
+
{%- assign sidebar_nav = page.sidebar.nav -%}
|
|
57
|
+
{%- elsif sidebar_collection_cfg.nav -%}
|
|
58
|
+
{%- assign sidebar_nav = sidebar_collection_cfg.nav -%}
|
|
59
|
+
{%- elsif site.sidebar.nav -%}
|
|
60
|
+
{%- assign sidebar_nav = site.sidebar.nav -%}
|
|
61
|
+
{%- endif -%}
|
|
62
|
+
{%- endif -%}
|
|
63
|
+
|
|
64
|
+
{%- comment -%} 4. "auto" → concrete mode based on the page's collection {%- endcomment -%}
|
|
65
|
+
{%- if sidebar_nav == "auto" -%}
|
|
66
|
+
{%- assign sidebar_nav = nil -%}
|
|
67
|
+
{%- if page.collection -%}
|
|
68
|
+
{%- if site.data.navigation[page.collection] -%}
|
|
69
|
+
{%- assign sidebar_nav = page.collection -%}
|
|
70
|
+
{%- else -%}
|
|
71
|
+
{%- assign sidebar_nav = "collection" -%}
|
|
72
|
+
{%- endif -%}
|
|
73
|
+
{%- elsif site.categories.size > 0 -%}
|
|
74
|
+
{%- assign sidebar_nav = "categories" -%}
|
|
75
|
+
{%- endif -%}
|
|
76
|
+
{%- endif -%}
|
|
77
|
+
|
|
78
|
+
{%- comment -%} 5. Content gate — never reserve an empty left column {%- endcomment -%}
|
|
79
|
+
{%- assign sidebar_has_content = false -%}
|
|
80
|
+
{%- if sidebar_nav -%}
|
|
81
|
+
{%- case sidebar_nav -%}
|
|
82
|
+
{%- when "collection" -%}
|
|
83
|
+
{%- if page.sidebar.collection or page.collection -%}
|
|
84
|
+
{%- assign sidebar_has_content = true -%}
|
|
85
|
+
{%- endif -%}
|
|
86
|
+
{%- when "categories" -%}
|
|
87
|
+
{%- if site.categories.size > 0 -%}
|
|
88
|
+
{%- assign sidebar_has_content = true -%}
|
|
89
|
+
{%- endif -%}
|
|
90
|
+
{%- when "tags" -%}
|
|
91
|
+
{%- if site.tags.size > 0 -%}
|
|
92
|
+
{%- assign sidebar_has_content = true -%}
|
|
93
|
+
{%- endif -%}
|
|
94
|
+
{%- else -%}
|
|
95
|
+
{%- if site.data.navigation[sidebar_nav] -%}
|
|
96
|
+
{%- assign sidebar_has_content = true -%}
|
|
97
|
+
{%- endif -%}
|
|
98
|
+
{%- endcase -%}
|
|
99
|
+
{%- endif -%}
|
|
100
|
+
|
|
101
|
+
{%- comment -%} 6. Panel heading text + icon (page → collection → site → theme default) {%- endcomment -%}
|
|
102
|
+
{%- assign sidebar_title = site.sidebar.title | default: "Browse docs" -%}
|
|
103
|
+
{%- assign sidebar_icon = site.sidebar.icon | default: "bi-journal-bookmark" -%}
|
|
104
|
+
{%- if sidebar_collection_cfg.title -%}
|
|
105
|
+
{%- assign sidebar_title = sidebar_collection_cfg.title -%}
|
|
106
|
+
{%- endif -%}
|
|
107
|
+
{%- if sidebar_collection_cfg.icon -%}
|
|
108
|
+
{%- assign sidebar_icon = sidebar_collection_cfg.icon -%}
|
|
109
|
+
{%- endif -%}
|
|
110
|
+
{%- if page.sidebar.title -%}
|
|
111
|
+
{%- assign sidebar_title = page.sidebar.title -%}
|
|
112
|
+
{%- endif -%}
|
|
113
|
+
{%- if page.sidebar.icon -%}
|
|
114
|
+
{%- assign sidebar_icon = page.sidebar.icon -%}
|
|
115
|
+
{%- endif -%}
|
|
@@ -1,68 +1,174 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
1
|
+
{% comment %} Feature: ZER0-008 {% endcomment %}
|
|
2
|
+
{%- comment -%}
|
|
3
|
+
Component: sidebar-folders
|
|
4
|
+
Path: _includes/navigation/sidebar-folders.html
|
|
5
|
+
Purpose: "collection" sidebar mode — live folder tree of a collection's
|
|
6
|
+
documents, grouped by sub-folder into collapsible sections.
|
|
7
|
+
Zero-config: any collection gets a usable sidebar without a
|
|
8
|
+
curated _data/navigation/*.yml file.
|
|
9
|
+
Params: collection (string, optional) — collection label to list
|
|
10
|
+
(default: page.sidebar.collection, then page.collection)
|
|
11
|
+
sort (string, optional) — "path" | "title" | "date"
|
|
12
|
+
(default: page.sidebar.sort, then "path")
|
|
13
|
+
Front matter (page.sidebar hash, all optional):
|
|
14
|
+
collection — list a different collection than the page's own
|
|
15
|
+
sort — see above; "date" needs date/lastmod front matter
|
|
16
|
+
reverse — true to reverse the sort (e.g. newest-first)
|
|
17
|
+
expand — true to expand every folder group
|
|
18
|
+
(default: only the group containing the page)
|
|
19
|
+
Per-document opt-out: set `sidebar_exclude: true` in a doc's front matter
|
|
20
|
+
to hide it from this tree.
|
|
21
|
+
Collection metadata (optional, in _config.yml `collections.<label>:`):
|
|
22
|
+
title — heading text (default: humanized label)
|
|
23
|
+
icon — Bootstrap Icons class (default: bi-folder2-open)
|
|
24
|
+
Depends on: site.collections, Bootstrap 5 collapse, Bootstrap Icons,
|
|
25
|
+
nav-tree styles (_sass/core/_nav-tree.scss)
|
|
26
|
+
Notes: A folder's index.* doc becomes the folder link itself (link +
|
|
27
|
+
separate collapse toggle, mirroring nav-tree.html). Groups
|
|
28
|
+
containing the current page start expanded so the active link
|
|
29
|
+
is always visible. Folder names are humanized (hyphens/
|
|
30
|
+
underscores → spaces). Nested sub-folders render as their own
|
|
31
|
+
"parent / child" groups.
|
|
32
|
+
{%- endcomment -%}
|
|
27
33
|
|
|
28
|
-
{
|
|
34
|
+
{%- assign _coll_label = include.collection | default: page.sidebar.collection | default: page.collection -%}
|
|
35
|
+
{%- assign _coll = site.collections | where: "label", _coll_label | first -%}
|
|
29
36
|
|
|
30
|
-
{
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
37
|
+
{%- if _coll -%}
|
|
38
|
+
{%- assign _sort = include.sort | default: page.sidebar.sort | default: "path" -%}
|
|
39
|
+
{%- assign _docs = _coll.docs | where_exp: "d", "d.sidebar_exclude != true" -%}
|
|
40
|
+
{%- case _sort -%}
|
|
41
|
+
{%- when "title" -%}
|
|
42
|
+
{%- assign _docs = _docs | sort_natural: "title" -%}
|
|
43
|
+
{%- when "date" -%}
|
|
44
|
+
{%- assign _docs = _docs | sort: "date", "first" -%}
|
|
45
|
+
{%- else -%}
|
|
46
|
+
{%- assign _docs = _docs | sort: "path" -%}
|
|
47
|
+
{%- endcase -%}
|
|
48
|
+
{%- if page.sidebar.reverse == true -%}
|
|
49
|
+
{%- assign _docs = _docs | reverse -%}
|
|
50
|
+
{%- endif -%}
|
|
51
|
+
|
|
52
|
+
{%- comment -%}
|
|
53
|
+
Group documents by their directory relative to the collection folder.
|
|
54
|
+
Splitting on "_<label>/" works with and without a collections_dir prefix
|
|
55
|
+
in doc.path. Root-level docs land in the "" group.
|
|
56
|
+
{%- endcomment -%}
|
|
57
|
+
{%- capture _coll_prefix -%}_{{ _coll_label }}/{%- endcapture -%}
|
|
58
|
+
{%- assign _groups = _docs | group_by_exp: "d", "d.path | split: _coll_prefix | last | split: '/' | pop | join: '/'" | sort: "name" -%}
|
|
59
|
+
|
|
60
|
+
{%- assign _coll_title = _coll.title -%}
|
|
61
|
+
{%- unless _coll_title -%}
|
|
62
|
+
{%- assign _coll_title = _coll_label | replace: "-", " " | replace: "_", " " | capitalize -%}
|
|
63
|
+
{%- endunless -%}
|
|
64
|
+
{%- assign _coll_icon = _coll.icon | default: "bi-folder2-open" -%}
|
|
65
|
+
{%- assign _expand_all = page.sidebar.expand | default: false -%}
|
|
66
|
+
|
|
67
|
+
<div class="sidebar-collection w-100">
|
|
68
|
+
<h2 class="sidebar-collection-heading h6 text-uppercase text-body-secondary fw-semibold mb-3 d-flex align-items-center gap-2">
|
|
69
|
+
<i class="bi {{ _coll_icon }}" aria-hidden="true"></i>
|
|
70
|
+
<span>{{ _coll_title }}</span>
|
|
34
71
|
</h2>
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
{
|
|
53
|
-
{
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
72
|
+
|
|
73
|
+
<ul class="list-unstyled nav-tree-root mb-0">
|
|
74
|
+
{%- for group in _groups -%}
|
|
75
|
+
{%- if group.name == "" or group.name == nil -%}
|
|
76
|
+
{%- comment -%} Collection-root documents: flat depth-0 links {%- endcomment -%}
|
|
77
|
+
{%- for doc in group.items -%}
|
|
78
|
+
{%- assign _doc_title = doc.title -%}
|
|
79
|
+
{%- unless _doc_title -%}
|
|
80
|
+
{%- assign _doc_title = doc.path | split: "/" | last | split: "." | first | replace: "-", " " | replace: "_", " " | capitalize -%}
|
|
81
|
+
{%- endunless -%}
|
|
82
|
+
<li class="nav-tree-item" data-depth="0">
|
|
83
|
+
<a href="{{ doc.url | relative_url }}"
|
|
84
|
+
class="nav-tree-link d-flex align-items-start rounded py-1 px-2 text-decoration-none{% if page.url == doc.url %} active{% endif %}"{% if page.url == doc.url %} aria-current="page"{% endif %}>
|
|
85
|
+
<i class="bi bi-file-earmark-text me-2 flex-shrink-0" aria-hidden="true"></i>
|
|
86
|
+
<span>{{ _doc_title }}</span>
|
|
87
|
+
</a>
|
|
88
|
+
</li>
|
|
89
|
+
{%- endfor -%}
|
|
90
|
+
{%- else -%}
|
|
91
|
+
{%- assign _group_id = group.name | slugify | prepend: "sidebar-coll-" -%}
|
|
92
|
+
{%- assign _group_title = group.name | replace: "-", " " | replace: "_", " " | replace: "/", " / " | capitalize -%}
|
|
93
|
+
{%- assign _group_index = group.items | where_exp: "d", "d.path contains '/index.'" | first -%}
|
|
94
|
+
{%- assign _active_here = group.items | where: "url", page.url | size -%}
|
|
95
|
+
{%- if _expand_all or _active_here > 0 -%}
|
|
96
|
+
{%- assign _expanded = true -%}
|
|
97
|
+
{%- else -%}
|
|
98
|
+
{%- assign _expanded = false -%}
|
|
99
|
+
{%- endif -%}
|
|
100
|
+
|
|
101
|
+
{%- assign _group_size = group.items | size -%}
|
|
102
|
+
{%- if _group_index and _group_size == 1 -%}
|
|
103
|
+
{%- comment -%} Folder holds only its index doc — plain leaf, no toggle {%- endcomment -%}
|
|
104
|
+
<li class="nav-tree-item sidebar-collection-group" data-depth="0">
|
|
105
|
+
<a href="{{ _group_index.url | relative_url }}"
|
|
106
|
+
class="nav-tree-link d-flex align-items-start rounded py-1 px-2 text-decoration-none{% if page.url == _group_index.url %} active{% endif %}"{% if page.url == _group_index.url %} aria-current="page"{% endif %}>
|
|
107
|
+
<i class="bi bi-folder2 me-2 flex-shrink-0" aria-hidden="true"></i>
|
|
108
|
+
<span>{{ _group_title }}</span>
|
|
109
|
+
</a>
|
|
110
|
+
</li>
|
|
111
|
+
{%- else -%}
|
|
112
|
+
<li class="nav-tree-item sidebar-collection-group" data-depth="0">
|
|
113
|
+
{%- if _group_index -%}
|
|
114
|
+
{%- comment -%} Folder index doc → folder name links to it, chevron toggles {%- endcomment -%}
|
|
115
|
+
<div class="d-flex align-items-center">
|
|
116
|
+
<a href="{{ _group_index.url | relative_url }}"
|
|
117
|
+
class="nav-tree-link flex-grow-1 d-inline-flex align-items-center rounded py-1 px-2 text-decoration-none{% if page.url == _group_index.url %} active{% endif %}"{% if page.url == _group_index.url %} aria-current="page"{% endif %}>
|
|
118
|
+
<i class="bi bi-folder2 me-2" aria-hidden="true"></i>
|
|
119
|
+
<span>{{ _group_title }}</span>
|
|
120
|
+
</a>
|
|
121
|
+
<button class="btn btn-sm btn-link nav-tree-toggle p-1{% unless _expanded %} collapsed{% endunless %}"
|
|
122
|
+
type="button"
|
|
123
|
+
data-bs-toggle="collapse"
|
|
124
|
+
data-bs-target="#{{ _group_id }}"
|
|
125
|
+
aria-expanded="{{ _expanded }}"
|
|
126
|
+
aria-controls="{{ _group_id }}"
|
|
127
|
+
aria-label="Toggle {{ _group_title }} section">
|
|
128
|
+
<i class="bi bi-chevron-down nav-tree-chevron" aria-hidden="true"></i>
|
|
129
|
+
</button>
|
|
130
|
+
</div>
|
|
131
|
+
{%- else -%}
|
|
132
|
+
<button class="btn btn-link nav-tree-toggle w-100 d-flex align-items-center text-start py-1 px-2{% unless _expanded %} collapsed{% endunless %}"
|
|
133
|
+
type="button"
|
|
134
|
+
data-bs-toggle="collapse"
|
|
135
|
+
data-bs-target="#{{ _group_id }}"
|
|
136
|
+
aria-expanded="{{ _expanded }}"
|
|
137
|
+
aria-controls="{{ _group_id }}">
|
|
138
|
+
<i class="bi bi-folder2 me-2" aria-hidden="true"></i>
|
|
139
|
+
<span class="flex-grow-1">{{ _group_title }}</span>
|
|
140
|
+
<i class="bi bi-chevron-down nav-tree-chevron" aria-hidden="true"></i>
|
|
141
|
+
</button>
|
|
142
|
+
{%- endif -%}
|
|
143
|
+
|
|
144
|
+
<div class="collapse{% if _expanded %} show{% endif %}" id="{{ _group_id }}">
|
|
145
|
+
<ul class="list-unstyled nav-tree-children mb-0">
|
|
146
|
+
{%- for doc in group.items -%}
|
|
147
|
+
{%- unless _group_index and doc.path == _group_index.path -%}
|
|
148
|
+
{%- assign _doc_title = doc.title -%}
|
|
149
|
+
{%- unless _doc_title -%}
|
|
150
|
+
{%- assign _doc_title = doc.path | split: "/" | last | split: "." | first | replace: "-", " " | replace: "_", " " | capitalize -%}
|
|
151
|
+
{%- endunless -%}
|
|
152
|
+
<li class="nav-tree-item" data-depth="1">
|
|
153
|
+
<a href="{{ doc.url | relative_url }}"
|
|
154
|
+
class="nav-tree-link d-flex align-items-start rounded py-1 px-2 text-decoration-none{% if page.url == doc.url %} active{% endif %}"{% if page.url == doc.url %} aria-current="page"{% endif %}>
|
|
155
|
+
<i class="bi bi-file-earmark-text me-2 flex-shrink-0" aria-hidden="true"></i>
|
|
156
|
+
<span>{{ _doc_title }}</span>
|
|
157
|
+
</a>
|
|
158
|
+
</li>
|
|
159
|
+
{%- endunless -%}
|
|
160
|
+
{%- endfor -%}
|
|
161
|
+
</ul>
|
|
162
|
+
</div>
|
|
163
|
+
</li>
|
|
164
|
+
{%- endif -%}
|
|
165
|
+
{%- endif -%}
|
|
166
|
+
{%- endfor -%}
|
|
62
167
|
</ul>
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
168
|
+
</div>
|
|
169
|
+
{%- else -%}
|
|
170
|
+
<p class="text-body-secondary small mb-0">
|
|
171
|
+
<i class="bi bi-info-circle me-1" aria-hidden="true"></i>
|
|
66
172
|
No collection found for this page.
|
|
67
173
|
</p>
|
|
68
|
-
{
|
|
174
|
+
{%- endif -%}
|
|
@@ -1,32 +1,36 @@
|
|
|
1
|
-
|
|
1
|
+
{% comment %} Feature: ZER0-008 {% endcomment %}
|
|
2
|
+
<!--
|
|
2
3
|
===================================================================
|
|
3
4
|
SIDEBAR LEFT - Dynamic Navigation Sidebar
|
|
4
5
|
===================================================================
|
|
5
|
-
|
|
6
|
-
File: sidebar-left.html
|
|
6
|
+
|
|
7
|
+
File: sidebar-left.html
|
|
7
8
|
Path: _includes/navigation/sidebar-left.html
|
|
8
|
-
Purpose: Left sidebar
|
|
9
|
-
|
|
9
|
+
Purpose: Left sidebar panel (responsive offcanvas) around the resolved
|
|
10
|
+
sidebar navigation content
|
|
11
|
+
|
|
10
12
|
Template Logic:
|
|
11
13
|
- Responsive offcanvas sidebar for mobile devices
|
|
12
|
-
-
|
|
13
|
-
*
|
|
14
|
-
|
|
15
|
-
*
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
14
|
+
- Mode resolution + rendering are delegated to shared includes:
|
|
15
|
+
* navigation/sidebar-config.html — resolves sidebar_nav / title / icon
|
|
16
|
+
from page.sidebar → collection `sidebar:` metadata → site.sidebar
|
|
17
|
+
* navigation/sidebar-nav.html — renders the resolved mode
|
|
18
|
+
|
|
19
|
+
Navigation modes (page.sidebar.nav — see sidebar-config.html):
|
|
20
|
+
- "auto": best mode for the page's collection (curated data file →
|
|
21
|
+
collection folder tree → post categories)
|
|
22
|
+
- "collection": live folder tree of the page's (or a named) collection
|
|
23
|
+
- "categories" / "tags": posts grouped by taxonomy term
|
|
24
|
+
- any other value: _data/navigation/<value>.yml rendered by nav-tree.html
|
|
25
|
+
|
|
26
|
+
Configuration:
|
|
27
|
+
- Heading text/icon: page.sidebar.title/icon → collection metadata →
|
|
28
|
+
site.sidebar.title/icon → "Browse docs"
|
|
27
29
|
===================================================================
|
|
28
30
|
-->
|
|
29
31
|
|
|
32
|
+
{% include navigation/sidebar-config.html %}
|
|
33
|
+
|
|
30
34
|
<!-- ================================ -->
|
|
31
35
|
<!-- SIDEBAR NAVIGATION CONTAINER -->
|
|
32
36
|
<!-- ================================ -->
|
|
@@ -45,7 +49,7 @@
|
|
|
45
49
|
<!-- ========================== -->
|
|
46
50
|
<!-- Mobile-only header with close button -->
|
|
47
51
|
<div class="offcanvas-header">
|
|
48
|
-
<h2 class="offcanvas-title h5 mb-0" id="bdSidebarOffcanvasLabel">
|
|
52
|
+
<h2 class="offcanvas-title h5 mb-0" id="bdSidebarOffcanvasLabel">{{ sidebar_title }}</h2>
|
|
49
53
|
<div class="d-flex align-items-center gap-1">
|
|
50
54
|
<button type="button"
|
|
51
55
|
class="btn btn-sm btn-link text-body-secondary bd-sidebar-visibility-toggle d-lg-none px-2"
|
|
@@ -67,8 +71,8 @@
|
|
|
67
71
|
|
|
68
72
|
<div class="bd-sidebar-desktop-header mb-3 d-none d-lg-flex align-items-center justify-content-between gap-2 w-100">
|
|
69
73
|
<strong class="d-flex align-items-center mb-0">
|
|
70
|
-
<i class="bi
|
|
71
|
-
|
|
74
|
+
<i class="bi {{ sidebar_icon }} me-2" aria-hidden="true"></i>
|
|
75
|
+
{{ sidebar_title }}
|
|
72
76
|
</strong>
|
|
73
77
|
<button type="button"
|
|
74
78
|
class="btn btn-sm btn-link text-body-secondary bd-sidebar-visibility-toggle d-none d-lg-inline-flex flex-shrink-0 px-1"
|
|
@@ -81,35 +85,8 @@
|
|
|
81
85
|
</button>
|
|
82
86
|
</div>
|
|
83
87
|
|
|
84
|
-
<!--
|
|
85
|
-
|
|
86
|
-
<!-- ========================== -->
|
|
87
|
-
<!-- Auto-generates folder structure from collection documents -->
|
|
88
|
-
{% if page.sidebar.nav == "auto" %}
|
|
89
|
-
<div class="list-group nav-tree" id="sidebar-content" data-nav-tree>
|
|
90
|
-
{% assign folders = site.pages | where_exp: "item", "item.path contains 'index.md'" | sort: 'path' %}
|
|
91
|
-
{% include navigation/sidebar-folders.html folders=folders %}
|
|
92
|
-
</div>
|
|
88
|
+
<!-- Resolved navigation content (see navigation/sidebar-nav.html) -->
|
|
89
|
+
{% include navigation/sidebar-nav.html id="sidebar-content" %}
|
|
93
90
|
|
|
94
|
-
<!-- ========================== -->
|
|
95
|
-
<!-- CATEGORIES MODE -->
|
|
96
|
-
<!-- ========================== -->
|
|
97
|
-
<!-- Creates navigation from Jekyll post/page categories -->
|
|
98
|
-
{% elsif page.sidebar.nav == "categories" %}
|
|
99
|
-
<div class="nav-tree nav-tree--categories" id="sidebar-content" data-nav-tree>
|
|
100
|
-
{% assign categories = site.categories | sort %}
|
|
101
|
-
{% include navigation/sidebar-categories.html categories=categories %}
|
|
102
|
-
</div>
|
|
103
|
-
|
|
104
|
-
<!-- ========================== -->
|
|
105
|
-
<!-- TREE MODE: YAML Navigation -->
|
|
106
|
-
<!-- ========================== -->
|
|
107
|
-
<!-- Uses predefined YAML navigation structure from _data files -->
|
|
108
|
-
{% elsif page.sidebar.nav %}
|
|
109
|
-
<nav class="w-100 nav-tree" data-nav-tree>
|
|
110
|
-
{% include navigation/nav-tree.html nav=page.sidebar.nav %}
|
|
111
|
-
</nav>
|
|
112
|
-
{% endif %}
|
|
113
|
-
|
|
114
91
|
</div>
|
|
115
92
|
</div>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{%- comment -%}
|
|
2
|
+
Component: sidebar-nav
|
|
3
|
+
Path: _includes/navigation/sidebar-nav.html
|
|
4
|
+
Purpose: Render the resolved sidebar navigation content for the current
|
|
5
|
+
page. Expects navigation/sidebar-config.html to have been
|
|
6
|
+
included first in the same render context (it sets
|
|
7
|
+
`sidebar_nav`). Shared by navigation/sidebar-left.html and
|
|
8
|
+
navigation/unified-drawer.html so desktop sidebar and mobile
|
|
9
|
+
drawer can never drift apart.
|
|
10
|
+
Params: id (string, optional) — id attribute for the content wrapper
|
|
11
|
+
Depends on: navigation/sidebar-config.html (resolver),
|
|
12
|
+
navigation/sidebar-folders.html ("collection" mode),
|
|
13
|
+
navigation/sidebar-categories.html ("categories"/"tags" modes),
|
|
14
|
+
navigation/nav-tree.html (curated _data/navigation/*.yml modes)
|
|
15
|
+
Notes: Renders nothing when sidebar_nav is nil or its data is empty —
|
|
16
|
+
callers gate the surrounding column on `sidebar_has_content`.
|
|
17
|
+
{%- endcomment -%}
|
|
18
|
+
{%- if sidebar_nav == "collection" -%}
|
|
19
|
+
<div class="nav-tree"{% if include.id %} id="{{ include.id }}"{% endif %} data-nav-tree>
|
|
20
|
+
{% include navigation/sidebar-folders.html %}
|
|
21
|
+
</div>
|
|
22
|
+
{%- elsif sidebar_nav == "categories" or sidebar_nav == "tags" -%}
|
|
23
|
+
<div class="nav-tree nav-tree--categories"{% if include.id %} id="{{ include.id }}"{% endif %} data-nav-tree>
|
|
24
|
+
{% include navigation/sidebar-categories.html taxonomy=sidebar_nav %}
|
|
25
|
+
</div>
|
|
26
|
+
{%- elsif sidebar_nav -%}
|
|
27
|
+
<nav class="w-100 nav-tree"{% if include.id %} id="{{ include.id }}"{% endif %} data-nav-tree aria-label="Section navigation">
|
|
28
|
+
{% include navigation/nav-tree.html nav=sidebar_nav %}
|
|
29
|
+
</nav>
|
|
30
|
+
{%- endif -%}
|
|
@@ -3,15 +3,9 @@
|
|
|
3
3
|
footer stacking context with back-to-top and does not cover the powered-by
|
|
4
4
|
row when the user scrolls to the page bottom.
|
|
5
5
|
{%- endcomment -%}
|
|
6
|
-
{%-
|
|
7
|
-
{%-
|
|
8
|
-
|
|
9
|
-
{%- assign _effective_sidebar = false -%}
|
|
10
|
-
{%- else -%}
|
|
11
|
-
{%- assign _effective_sidebar = true -%}
|
|
12
|
-
{%- endif -%}
|
|
13
|
-
{%- endif -%}
|
|
14
|
-
{%- if _effective_sidebar != false -%}
|
|
6
|
+
{%- comment -%} Shared visibility resolver — sets sidebar_enabled {%- endcomment -%}
|
|
7
|
+
{%- include navigation/sidebar-config.html -%}
|
|
8
|
+
{%- if sidebar_enabled -%}
|
|
15
9
|
<div class="position-fixed bd-toc-fab d-lg-none" id="tocFab">
|
|
16
10
|
<button class="btn btn-primary rounded-circle shadow-lg p-0 bd-toc-toggle"
|
|
17
11
|
type="button"
|
|
@@ -60,20 +60,13 @@
|
|
|
60
60
|
<div class="offcanvas-body tab-content overflow-auto">
|
|
61
61
|
<div class="tab-pane fade show active" id="zer0-drawer-pane-browse"
|
|
62
62
|
role="tabpanel" aria-labelledby="zer0-drawer-tab-browse">
|
|
63
|
-
{%-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
{%-
|
|
69
|
-
|
|
70
|
-
{% assign categories = site.categories | sort %}
|
|
71
|
-
{% include navigation/sidebar-categories.html categories=categories %}
|
|
72
|
-
</div>
|
|
73
|
-
{%- elsif page.sidebar.nav -%}
|
|
74
|
-
<nav aria-label="Section navigation">
|
|
75
|
-
{% include navigation/nav-tree.html nav=page.sidebar.nav %}
|
|
76
|
-
</nav>
|
|
63
|
+
{%- comment -%}
|
|
64
|
+
Same resolver + renderer as sidebar-left.html so the drawer's Browse
|
|
65
|
+
tab can never drift from the desktop sidebar.
|
|
66
|
+
{%- endcomment -%}
|
|
67
|
+
{% include navigation/sidebar-config.html %}
|
|
68
|
+
{%- if sidebar_has_content -%}
|
|
69
|
+
{% include navigation/sidebar-nav.html %}
|
|
77
70
|
{%- else -%}
|
|
78
71
|
<p class="text-body-secondary small mb-0">No sidebar configured for this page.</p>
|
|
79
72
|
{%- endif -%}
|
data/_includes/setup/wizard.html
CHANGED
data/_layouts/admin.html
CHANGED
data/_layouts/article.html
CHANGED
data/_layouts/author.html
CHANGED
data/_layouts/authors.html
CHANGED