jekyll-theme-zer0 0.16.0 → 0.17.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.
@@ -0,0 +1,54 @@
1
+ # Navigation Data Schema Documentation
2
+ # ===================================
3
+ #
4
+ # This directory contains YAML navigation data files used by the sidebar
5
+ # and navbar components. All files follow a standardized schema.
6
+ #
7
+ # ## Schema Definition
8
+ #
9
+ # Each navigation item can have the following properties:
10
+ #
11
+ # ```yaml
12
+ # - title: string # Required - Display text
13
+ # url: string # Optional - Link URL (relative to site root)
14
+ # icon: string # Optional - Bootstrap Icons class (e.g., "bi-folder")
15
+ # description: string # Optional - Tooltip or description text
16
+ # expanded: boolean # Optional - Default expanded state (default: false)
17
+ # children: array # Optional - Nested navigation items (recursive)
18
+ # ```
19
+ #
20
+ # ## Navigation Modes
21
+ #
22
+ # The sidebar supports three navigation modes set via `page.sidebar.nav`:
23
+ #
24
+ # 1. **auto** - Auto-generates from collection documents
25
+ # 2. **tree** - Uses YAML data from this directory
26
+ # 3. **categories** - Groups by Jekyll categories
27
+ #
28
+ # ## Available Files
29
+ #
30
+ # - main.yml - Primary site navigation (navbar)
31
+ # - docs.yml - Documentation section navigation
32
+ # - about.yml - About section navigation
33
+ # - quickstart.yml - Quick start guide navigation
34
+ # - home.yml - Homepage quick links
35
+ # - posts.yml - Blog category navigation
36
+ #
37
+ # ## Example Usage
38
+ #
39
+ # In page front matter:
40
+ # ```yaml
41
+ # sidebar:
42
+ # nav: docs # Uses _data/navigation/docs.yml
43
+ # ```
44
+ #
45
+ # ## Schema Validation
46
+ #
47
+ # Navigation YAML is validated at build time by _plugins/navigation_validator.rb
48
+ # Invalid schemas will produce build warnings.
49
+ #
50
+ # ## Migration Notes (v2.0)
51
+ #
52
+ # - Renamed `sublinks` to `children` for consistency with tree terminology
53
+ # - Added `expanded` property for default state
54
+ # - Navigation modes changed: dynamic→auto, searchCats→categories
@@ -1,11 +1,13 @@
1
1
  # About Navigation Configuration
2
- # Used by: About section sidebar and related pages
2
+ # Used by: About section sidebar (nav: tree)
3
3
  # Purpose: Navigation for about pages, features, settings, and site info
4
+ # Schema: See README.md for full documentation
4
5
 
5
6
  - title: About
6
7
  icon: bi-info-circle
7
8
  url: /about/
8
- sublinks:
9
+ expanded: true
10
+ children:
9
11
  - title: Overview
10
12
  url: /about/
11
13
  - title: Features
@@ -16,7 +18,7 @@
16
18
  - title: Site Info
17
19
  icon: bi-bar-chart
18
20
  url: /about/stats/
19
- sublinks:
21
+ children:
20
22
  - title: Statistics
21
23
  url: /about/stats/
22
24
  - title: Site Map
@@ -27,14 +29,14 @@
27
29
  - title: Settings
28
30
  icon: bi-gear
29
31
  url: /about/config/
30
- sublinks:
32
+ children:
31
33
  - title: Configuration
32
34
  url: /about/config/
33
35
 
34
36
  - title: Legal
35
37
  icon: bi-file-text
36
38
  url: /terms-of-service/
37
- sublinks:
39
+ children:
38
40
  - title: Terms of Service
39
41
  url: /terms-of-service/
40
42
  - title: Privacy Policy
@@ -1,57 +1,103 @@
1
1
  # Documentation Navigation Configuration
2
- # Used by: Docs sidebar and documentation pages
3
- # Purpose: Organize documentation by topic area
2
+ # Used by: Docs sidebar (nav: tree)
3
+ # Purpose: Organize documentation by topic area for _docs collection
4
+ # Schema: See README.md for full documentation
4
5
 
6
+ # ============================================================
7
+ # Getting Started
8
+ # ============================================================
9
+ - title: Getting Started
10
+ icon: bi-rocket-takeoff
11
+ url: /docs/
12
+ expanded: true
13
+ children:
14
+ - title: Documentation Home
15
+ url: /docs/
16
+ - title: Installation
17
+ url: /docs/installation/
18
+ - title: Troubleshooting
19
+ url: /docs/troubleshooting/
20
+
21
+ # ============================================================
22
+ # Core Technologies
23
+ # ============================================================
5
24
  - title: Jekyll
6
25
  icon: bi-journal-code
7
26
  url: /docs/jekyll/
8
- sublinks:
9
- - title: Jekyll Guide
27
+ children:
28
+ - title: Jekyll Overview
10
29
  url: /docs/jekyll/
11
- - title: Mermaid Diagrams
12
- url: /docs/jekyll/mermaid-native-markdown/
13
- - title: Math with MathJax
14
- url: /docs/jekyll/jekyll-math-symbols-with-mathjax/
30
+ - title: Configuration
31
+ url: /docs/jekyll/jekyll-config/
32
+ - title: Front Matter
33
+ url: /docs/front-matter/
15
34
  - title: Liquid Templating
16
35
  url: /docs/jekyll/jekyll-liquid/
17
- - title: Frontmatter CMS
18
- url: /docs/jekyll/jekyll-frontmatter-cms/
19
36
  - title: Syntax Highlighting
20
37
  url: /docs/jekyll/jekyll-highlighting/
38
+ - title: Performance
39
+ url: /docs/jekyll/jekyll-performance-optimization/
40
+ - title: Security
41
+ url: /docs/jekyll/jekyll-security/
42
+
43
+ - title: Ruby & Bundler
44
+ icon: bi-gem
45
+ url: /docs/ruby/
46
+ children:
47
+ - title: Ruby Overview
48
+ url: /docs/ruby/
49
+ - title: Ruby 101
50
+ url: /docs/ruby-101/
51
+
52
+ - title: Liquid
53
+ icon: bi-droplet
54
+ url: /docs/liquid/
55
+ children:
56
+ - title: Liquid Overview
57
+ url: /docs/liquid/
21
58
 
59
+ - title: Docker
60
+ icon: bi-box-seam
61
+ url: /docs/docker/
62
+ children:
63
+ - title: Docker Overview
64
+ url: /docs/docker/
65
+
66
+ - title: Bootstrap
67
+ icon: bi-bootstrap
68
+ url: /docs/bootstrap/
69
+ children:
70
+ - title: Bootstrap Overview
71
+ url: /docs/bootstrap/
72
+
73
+ # ============================================================
74
+ # Theme Features
75
+ # ============================================================
22
76
  - title: Features
23
77
  icon: bi-stars
24
- url: /about/features/
25
- sublinks:
78
+ url: /features/
79
+ children:
26
80
  - title: All Features
27
- url: /about/features/
81
+ url: /features/
82
+ - title: Mermaid Diagrams
83
+ url: /docs/jekyll/mermaid-native-markdown/
84
+ - title: Math with MathJax
85
+ url: /docs/jekyll/jekyll-math-symbols-with-mathjax/
28
86
  - title: Preview Image Generator
29
87
  url: /docs/features/preview-image-generator/
30
- - title: Statistics Dashboard
31
- url: /about/features/statistics-dashboard/
32
- - title: AI Development Guide
33
- url: /about/features/ai-development-guide/
88
+ - title: Frontmatter CMS
89
+ url: /docs/jekyll/jekyll-frontmatter-cms/
34
90
 
91
+ # ============================================================
92
+ # Deployment
93
+ # ============================================================
35
94
  - title: Deployment
36
95
  icon: bi-cloud-upload
37
96
  url: /quickstart/github-setup/
38
- sublinks:
97
+ children:
39
98
  - title: GitHub Pages
40
99
  url: /quickstart/github-setup/
41
100
  - title: Netlify
42
101
  url: /docs/jekyll/deploying-jekyll-website-to-netlify/
43
102
  - title: Custom Domain
44
103
  url: /docs/jekyll/deploying-personal-website-with-custom-domain/
45
-
46
- - title: Configuration
47
- icon: bi-gear
48
- url: /about/config/
49
- sublinks:
50
- - title: Site Config
51
- url: /about/config/
52
- - title: Jekyll Config
53
- url: /docs/jekyll/jekyll-config/
54
- - title: Performance
55
- url: /docs/jekyll/jekyll-performance-optimization/
56
- - title: Security
57
- url: /docs/jekyll/jekyll-security/
@@ -1,11 +1,12 @@
1
1
  # Home Navigation Configuration
2
2
  # Used by: Header navigation and homepage quick links
3
3
  # Purpose: Quick access links for the home/landing area
4
+ # Schema: See README.md for full documentation
4
5
 
5
6
  - title: Home
6
7
  icon: bi-house
7
8
  url: /
8
- sublinks:
9
+ children:
9
10
  - title: Blog
10
11
  url: /blog/
11
12
  - title: Quick Start
@@ -14,7 +15,7 @@
14
15
  - title: Discover
15
16
  icon: bi-compass
16
17
  url: /sitemap/
17
- sublinks:
18
+ children:
18
19
  - title: Site Map
19
20
  url: /sitemap/
20
21
  - title: Categories
@@ -25,7 +26,7 @@
25
26
  - title: Connect
26
27
  icon: bi-envelope
27
28
  url: /contact/
28
- sublinks:
29
+ children:
29
30
  - title: Contact
30
31
  url: /contact/
31
32
  - title: About
@@ -1,11 +1,12 @@
1
1
  # Main Navigation Configuration
2
2
  # Used by: _includes/navigation/navbar.html
3
- # Purpose: Primary site navigation with dropdown sublinks
3
+ # Purpose: Primary site navigation with dropdown children
4
+ # Schema: See README.md for full documentation
4
5
 
5
6
  - title: Quick Start
6
7
  icon: bi-rocket-takeoff
7
8
  url: /quickstart/
8
- sublinks:
9
+ children:
9
10
  - title: Machine Setup
10
11
  url: /quickstart/machine-setup/
11
12
  - title: Jekyll Setup
@@ -16,7 +17,7 @@
16
17
  - title: Blog
17
18
  icon: bi-journal-text
18
19
  url: /blog/
19
- sublinks:
20
+ children:
20
21
  - title: All Posts
21
22
  url: /posts/
22
23
  - title: Categories
@@ -27,18 +28,26 @@
27
28
  - title: Docs
28
29
  icon: bi-journal-bookmark
29
30
  url: /docs/
30
- sublinks:
31
+ children:
32
+ - title: Documentation Home
33
+ url: /docs/
34
+ - title: Installation
35
+ url: /docs/installation/
31
36
  - title: Jekyll Guide
32
37
  url: /docs/jekyll/
38
+ - title: Docker
39
+ url: /docs/docker/
33
40
  - title: Features
34
- url: /about/features/
41
+ url: /features/
42
+ - title: Troubleshooting
43
+ url: /docs/troubleshooting/
35
44
 
36
45
  - title: About
37
46
  icon: bi-info-circle
38
47
  url: /about/
39
- sublinks:
48
+ children:
40
49
  - title: Features
41
- url: /about/features/
50
+ url: /features/
42
51
  - title: Statistics
43
52
  url: /about/stats/
44
53
  - title: Config
@@ -1,12 +1,14 @@
1
1
  # Quick Start Navigation Configuration
2
- # Used by: Quick Start sidebar and related pages
2
+ # Used by: Quick Start sidebar (nav: tree)
3
3
  # Purpose: Step-by-step guide navigation for new users
4
4
  # Order: Overview → Machine → Jekyll → GitHub → Personalization
5
+ # Schema: See README.md for full documentation
5
6
 
6
7
  - title: "Quick Start"
7
8
  icon: bi-flag
8
9
  url: /quickstart/
9
- sublinks:
10
+ expanded: true
11
+ children:
10
12
  - title: "1. Machine Setup"
11
13
  url: /quickstart/machine-setup/
12
14
  icon: bi-laptop
@@ -28,5 +28,5 @@
28
28
  integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
29
29
  crossorigin="anonymous"></script>
30
30
 
31
- <!-- Sidebar Navigation Enhancements - Deferred for performance -->
32
- <script defer src="{{ '/assets/js/sidebar.js' | relative_url }}"></script>
31
+ <!-- Navigation ES6 Modules - Enhanced sidebar, scroll spy, keyboard shortcuts, gestures -->
32
+ <script type="module" src="{{ '/assets/js/modules/navigation/index.js' | relative_url }}"></script>
@@ -8,7 +8,7 @@
8
8
  <div class="card-body p-4 d-flex flex-column text-center">
9
9
  <p class="card-text mb-3">Install the theme as a Ruby gem for classic Jekyll workflows.</p>
10
10
  <pre class="bg-dark text-light p-3 rounded mb-3 small text-start overflow-auto"><code>gem install {{ site.resources.rubygems.name | default: 'zer0-mistakes' }}</code></pre>
11
- <a class="btn btn-outline-primary btn-sm mt-auto" href="{{ site.resources.rubygems.url | default: '#' }}" target="_blank" rel="noopener">View on RubyGems</a>
11
+ <a class="btn btn-outline-primary btn-sm mt-auto" href="{{ site.resources.rubygems.url | default: '' | join: '' | default: '#' }}" target="_blank" rel="noopener">View on RubyGems</a>
12
12
  </div>
13
13
  </div>
14
14
  </div>
@@ -20,9 +20,9 @@
20
20
  </div>
21
21
  <div class="card-body p-4 d-flex flex-column text-center">
22
22
  <p class="card-text mb-3">Run locally with zero Ruby setup using Docker.</p>
23
- <pre class="bg-dark text-light p-3 rounded mb-3 small text-start overflow-auto"><code>docker pull {{ site.resources.docker.image | default: 'bamr87/zer0-mistakes' }}
24
- docker run -p 4000:4000 {{ site.resources.docker.image | default: 'bamr87/zer0-mistakes' }}</code></pre>
25
- <a class="btn btn-outline-info btn-sm mt-auto" href="{{ site.resources.docker.hub_url | default: '#' }}" target="_blank" rel="noopener">View on Docker Hub</a>
23
+ <pre class="bg-dark text-light p-3 rounded mb-3 small text-start overflow-auto"><code>docker pull {{ site.resources.docker.image | default: '' | join: '' | default: 'bamr87/zer0-mistakes' }}
24
+ docker run -p 4000:4000 {{ site.resources.docker.image | default: '' | join: '' | default: 'bamr87/zer0-mistakes' }}</code></pre>
25
+ <a class="btn btn-outline-info btn-sm mt-auto" href="{{ site.resources.docker.hub_url | default: '' | join: '' | default: '#' }}" target="_blank" rel="noopener">View on Docker Hub</a>
26
26
  </div>
27
27
  </div>
28
28
  </div>
@@ -34,11 +34,11 @@ docker run -p 4000:4000 {{ site.resources.docker.image | default: 'bamr87/zer0-m
34
34
  </div>
35
35
  <div class="card-body p-4 d-flex flex-column text-center">
36
36
  <p class="card-text mb-3">Improve the theme by forking the repo and opening a PR.</p>
37
- <pre class="bg-dark text-light p-3 rounded mb-3 small text-start overflow-auto"><code>git clone {{ site.resources.github_repo | default: site.github.repository_url }}
37
+ <pre class="bg-dark text-light p-3 rounded mb-3 small text-start overflow-auto"><code>git clone {{ site.resources.github_repo | default: '' | join: '' | default: site.github.repository_url }}
38
38
  cd {{ site.local_repo | default: site.repository_name | default: 'repo' }}
39
- git remote add upstream {{ site.resources.github_repo | default: site.github.repository_url }}
39
+ git remote add upstream {{ site.resources.github_repo | default: '' | join: '' | default: site.github.repository_url }}
40
40
  git checkout -b feature/your-change</code></pre>
41
- <a class="btn btn-outline-secondary btn-sm mt-auto" href="{{ site.resources.github_fork | default: site.github.repository_url | append: '/fork' }}" target="_blank" rel="noopener">Fork on GitHub</a>
41
+ <a class="btn btn-outline-secondary btn-sm mt-auto" href="{{ site.resources.github_fork | default: '' | join: '' | default: site.github.repository_url | append: '/fork' }}" target="_blank" rel="noopener">Fork on GitHub</a>
42
42
  </div>
43
43
  </div>
44
44
  </div>
@@ -46,7 +46,7 @@ git checkout -b feature/your-change</code></pre>
46
46
 
47
47
  <!-- Contributing guide call-to-action placed below all cards -->
48
48
  <div class="text-center mt-4">
49
- <a class="btn btn-outline-secondary" href="{{ site.resources.contributing | default: '#' }}" target="_blank" rel="noopener">
49
+ <a class="btn btn-outline-secondary" href="{{ site.resources.contributing | default: '' | join: '' | default: '#' }}" target="_blank" rel="noopener">
50
50
  <i class="bi bi-journal-text me-2"></i>Read the Contributing Guide
51
51
  </a>
52
52
  </div>
@@ -3,22 +3,22 @@
3
3
  <div class="container-xl px-4 px-md-5">
4
4
  <div class="row g-3 justify-content-center text-center align-items-center">
5
5
  <div class="col-6 col-md-3 d-flex justify-content-center">
6
- <a class="btn btn-outline-light btn-sm w-100" href="{{ site.resources.github_repo | default: site.github.repository_url | default: '/' }}" target="_blank" rel="noopener">
6
+ <a class="btn btn-outline-light btn-sm w-100" href="{{ site.resources.github_repo | default: '' | join: '' | default: site.github.repository_url | default: '/' }}" target="_blank" rel="noopener">
7
7
  <i class="bi bi-github me-2"></i> GitHub
8
8
  </a>
9
9
  </div>
10
10
  <div class="col-6 col-md-3 d-flex justify-content-center">
11
- <a class="btn btn-outline-light btn-sm w-100" href="{{ site.resources.rubygems.url | default: '#' }}" target="_blank" rel="noopener">
11
+ <a class="btn btn-outline-light btn-sm w-100" href="{{ site.resources.rubygems.url | default: '' | join: '' | default: '#' }}" target="_blank" rel="noopener">
12
12
  <i class="bi bi-gem me-2"></i> RubyGems
13
13
  </a>
14
14
  </div>
15
15
  <div class="col-6 col-md-3 d-flex justify-content-center">
16
- <a class="btn btn-outline-light btn-sm w-100" href="{{ site.resources.docker.hub_url | default: '#' }}" target="_blank" rel="noopener">
16
+ <a class="btn btn-outline-light btn-sm w-100" href="{{ site.resources.docker.hub_url | default: '' | join: '' | default: '#' }}" target="_blank" rel="noopener">
17
17
  <i class="bi bi-box-seam me-2"></i> Docker Hub
18
18
  </a>
19
19
  </div>
20
20
  <div class="col-6 col-md-3 d-flex justify-content-center">
21
- <a class="btn btn-outline-light btn-sm w-100" href="{{ site.resources.github_fork | default: site.github.repository_url | append: '/fork' }}" target="_blank" rel="noopener">
21
+ <a class="btn btn-outline-light btn-sm w-100" href="{{ site.resources.github_fork | default: '' | join: '' | default: site.github.repository_url | append: '/fork' }}" target="_blank" rel="noopener">
22
22
  <i class="bi bi-git me-2"></i> Fork Project
23
23
  </a>
24
24
  </div>
@@ -10,14 +10,37 @@
10
10
  <ol itemscope itemtype="https://schema.org/BreadcrumbList">
11
11
  <i class="bi bi-folder"></i>
12
12
  {% assign crumbs = page.url | remove:'/index.html' | split: '/' %}
13
- <a href="/">root</a>
14
- {% for crumb in crumbs offset: 1 %}
15
- {% if forloop.last %}
16
- / {{ page.title }}
13
+ {% assign section = crumbs[1] | default: '' %}
14
+ <a href="{{ '/' | relative_url }}">root</a>
15
+
16
+ {% comment %}
17
+ Avoid linking to intermediate directories that don't have index pages.
18
+ Example: posts are /posts/YYYY/MM/DD/slug/ (only /posts/ and the leaf page exist).
19
+ {% endcomment %}
20
+ {% if section == 'posts' %}
21
+ / <a href="{{ '/posts/' | relative_url }}">Posts</a>
22
+ / {{ page.title }}
23
+ {% elsif section == 'notebooks' %}
24
+ / <a href="{{ '/notebooks/' | relative_url }}">Notebooks</a>
25
+ / {{ page.title }}
26
+ {% elsif section == 'notes' %}
27
+ / <a href="{{ '/notes/' | relative_url }}">Notes</a>
28
+ / {{ page.title }}
29
+ {% elsif section == 'docs' %}
30
+ / <a href="{{ '/docs/' | relative_url }}">Docs</a>
31
+ / {{ page.title }}
17
32
  {% else %}
18
- / <a href="{% assign crumb_limit = forloop.index | plus: 1 %}{% for crumb in crumbs limit: crumb_limit %}{{ crumb | append: '/' }}{% endfor %}">{{ crumb | replace:'-',' ' | remove:'.html' | capitalize }}</a>
33
+ {% for crumb in crumbs offset: 1 %}
34
+ {% if forloop.last %}
35
+ / {{ page.title }}
36
+ {% elsif forloop.first %}
37
+ / <a href="{{ '/' | append: crumb | append: '/' | relative_url }}">{{ crumb | replace:'-',' ' | remove:'.html' | capitalize }}</a>
38
+ {% else %}
39
+ {% comment %} Keep intermediate crumbs as plain text to avoid dead links {% endcomment %}
40
+ / {{ crumb | replace:'-',' ' | remove:'.html' | capitalize }}
41
+ {% endif %}
42
+ {% endfor %}
19
43
  {% endif %}
20
- {% endfor %}
21
44
  </ol>
22
45
  </nav>
23
46
  <!-- Secret Search bar -->
@@ -0,0 +1,181 @@
1
+ <!--
2
+ ===================================================================
3
+ NAV TREE - Flat YAML Navigation Renderer
4
+ ===================================================================
5
+
6
+ File: nav-tree.html
7
+ Path: _includes/navigation/nav-tree.html
8
+ Purpose: Render hierarchical navigation from YAML data files
9
+
10
+ Parameters:
11
+ - nav: Name of navigation file in _data/navigation/ (e.g., "docs", "main")
12
+
13
+ Data Schema (expected in _data/navigation/*.yml):
14
+ - title: string (required) - Display text
15
+ - url: string (optional) - Link URL
16
+ - icon: string (optional) - Bootstrap Icons class (e.g., "bi-folder")
17
+ - expanded: boolean (optional) - Default expanded state (default: false)
18
+ - children: array (optional) - Nested navigation items (max 2 levels)
19
+
20
+ Note: This implementation supports 2 levels of nesting to avoid Jekyll's
21
+ include depth limit. For deeper nesting, consider a plugin approach.
22
+
23
+ Dependencies:
24
+ - site.data.navigation[nav]: Navigation YAML data
25
+ - Bootstrap 5 collapse component
26
+ - Bootstrap Icons for visual indicators
27
+
28
+ Usage:
29
+ include navigation/nav-tree.html nav="docs"
30
+ ===================================================================
31
+ -->
32
+
33
+ {% assign navigation = site.data.navigation[include.nav] %}
34
+
35
+ {% if navigation %}
36
+ <ul class="list-unstyled fw-normal pb-2 small nav-tree-root">
37
+ {% for item in navigation %}
38
+ {% assign item_id = item.title | slugify | prepend: "nav-" %}
39
+ {% assign is_active = page.url == item.url %}
40
+ {% assign is_expanded = item.expanded | default: false %}
41
+ {% assign has_children = item.children and item.children.size > 0 %}
42
+
43
+ <li class="mb-1 nav-tree-item" data-depth="0">
44
+ {% if has_children %}
45
+ <!-- Parent item with children - collapsible -->
46
+ <div class="d-flex align-items-center">
47
+ {% if item.url %}
48
+ <a href="{{ item.url | relative_url }}"
49
+ class="nav-tree-link flex-grow-1 d-inline-flex align-items-center rounded py-1 px-2 text-decoration-none{% if is_active %} active{% endif %}">
50
+ {% if item.icon %}<i class="{{ item.icon }} me-2"></i>{% endif %}
51
+ <span>{{ item.title }}</span>
52
+ </a>
53
+ <button class="btn btn-sm btn-link nav-tree-toggle p-1{% unless is_expanded %} collapsed{% endunless %}"
54
+ type="button"
55
+ data-bs-toggle="collapse"
56
+ data-bs-target="#{{ item_id }}"
57
+ aria-expanded="{{ is_expanded }}"
58
+ aria-controls="{{ item_id }}"
59
+ aria-label="Toggle {{ item.title }} submenu">
60
+ <i class="bi bi-chevron-down"></i>
61
+ </button>
62
+ {% else %}
63
+ <button class="btn btn-link nav-tree-toggle w-100 d-flex align-items-center text-start fw-semibold py-1 px-2{% unless is_expanded %} collapsed{% endunless %}"
64
+ type="button"
65
+ data-bs-toggle="collapse"
66
+ data-bs-target="#{{ item_id }}"
67
+ aria-expanded="{{ is_expanded }}"
68
+ aria-controls="{{ item_id }}">
69
+ {% if item.icon %}<i class="{{ item.icon }} me-2"></i>{% endif %}
70
+ <span class="flex-grow-1">{{ item.title }}</span>
71
+ <i class="bi bi-chevron-down nav-tree-chevron"></i>
72
+ </button>
73
+ {% endif %}
74
+ </div>
75
+
76
+ <!-- Children container (Level 1) -->
77
+ <div class="collapse{% if is_expanded %} show{% endif %}" id="{{ item_id }}">
78
+ <ul class="list-unstyled fw-normal ps-3 nav-tree-children">
79
+ {% for child in item.children %}
80
+ {% assign child_id = child.title | slugify | prepend: "nav-" %}
81
+ {% assign child_active = page.url == child.url %}
82
+ {% assign child_expanded = child.expanded | default: false %}
83
+ {% assign child_has_children = child.children and child.children.size > 0 %}
84
+
85
+ <li class="mb-1 nav-tree-item" data-depth="1">
86
+ {% if child_has_children %}
87
+ <!-- Level 1 parent with children -->
88
+ <div class="d-flex align-items-center">
89
+ {% if child.url %}
90
+ <a href="{{ child.url | relative_url }}"
91
+ class="nav-tree-link flex-grow-1 d-inline-flex align-items-center rounded py-1 px-2 text-decoration-none{% if child_active %} active{% endif %}">
92
+ {% if child.icon %}<i class="{{ child.icon }} me-2"></i>{% endif %}
93
+ <span>{{ child.title }}</span>
94
+ </a>
95
+ <button class="btn btn-sm btn-link nav-tree-toggle p-1{% unless child_expanded %} collapsed{% endunless %}"
96
+ type="button"
97
+ data-bs-toggle="collapse"
98
+ data-bs-target="#{{ child_id }}"
99
+ aria-expanded="{{ child_expanded }}"
100
+ aria-controls="{{ child_id }}">
101
+ <i class="bi bi-chevron-down"></i>
102
+ </button>
103
+ {% else %}
104
+ <button class="btn btn-link nav-tree-toggle w-100 d-flex align-items-center text-start py-1 px-2{% unless child_expanded %} collapsed{% endunless %}"
105
+ type="button"
106
+ data-bs-toggle="collapse"
107
+ data-bs-target="#{{ child_id }}"
108
+ aria-expanded="{{ child_expanded }}"
109
+ aria-controls="{{ child_id }}">
110
+ {% if child.icon %}<i class="{{ child.icon }} me-2"></i>{% endif %}
111
+ <span class="flex-grow-1">{{ child.title }}</span>
112
+ <i class="bi bi-chevron-down nav-tree-chevron"></i>
113
+ </button>
114
+ {% endif %}
115
+ </div>
116
+
117
+ <!-- Children container (Level 2) -->
118
+ <div class="collapse{% if child_expanded %} show{% endif %}" id="{{ child_id }}">
119
+ <ul class="list-unstyled fw-normal ps-3 nav-tree-children">
120
+ {% for grandchild in child.children %}
121
+ {% assign gc_active = page.url == grandchild.url %}
122
+ <li class="mb-1 nav-tree-item" data-depth="2">
123
+ {% if grandchild.url %}
124
+ <a href="{{ grandchild.url | relative_url }}"
125
+ class="nav-tree-link d-inline-flex align-items-center rounded py-1 px-2 text-decoration-none{% if gc_active %} active{% endif %}">
126
+ {% if grandchild.icon %}<i class="{{ grandchild.icon }} me-2"></i>{% endif %}
127
+ <span>{{ grandchild.title }}</span>
128
+ </a>
129
+ {% else %}
130
+ <span class="nav-tree-text d-inline-flex align-items-center py-1 px-2 text-muted">
131
+ {% if grandchild.icon %}<i class="{{ grandchild.icon }} me-2"></i>{% endif %}
132
+ <span>{{ grandchild.title }}</span>
133
+ </span>
134
+ {% endif %}
135
+ </li>
136
+ {% endfor %}
137
+ </ul>
138
+ </div>
139
+ {% else %}
140
+ <!-- Level 1 leaf item -->
141
+ {% if child.url %}
142
+ <a href="{{ child.url | relative_url }}"
143
+ class="nav-tree-link d-inline-flex align-items-center rounded py-1 px-2 text-decoration-none{% if child_active %} active{% endif %}">
144
+ {% if child.icon %}<i class="{{ child.icon }} me-2"></i>{% endif %}
145
+ <span>{{ child.title }}</span>
146
+ </a>
147
+ {% else %}
148
+ <span class="nav-tree-text d-inline-flex align-items-center py-1 px-2 text-muted">
149
+ {% if child.icon %}<i class="{{ child.icon }} me-2"></i>{% endif %}
150
+ <span>{{ child.title }}</span>
151
+ </span>
152
+ {% endif %}
153
+ {% endif %}
154
+ </li>
155
+ {% endfor %}
156
+ </ul>
157
+ </div>
158
+ {% else %}
159
+ <!-- Root level leaf item -->
160
+ {% if item.url %}
161
+ <a href="{{ item.url | relative_url }}"
162
+ class="nav-tree-link d-inline-flex align-items-center rounded py-1 px-2 text-decoration-none{% if is_active %} active{% endif %}">
163
+ {% if item.icon %}<i class="{{ item.icon }} me-2"></i>{% endif %}
164
+ <span>{{ item.title }}</span>
165
+ </a>
166
+ {% else %}
167
+ <span class="nav-tree-text d-inline-flex align-items-center py-1 px-2 text-muted">
168
+ {% if item.icon %}<i class="{{ item.icon }} me-2"></i>{% endif %}
169
+ <span>{{ item.title }}</span>
170
+ </span>
171
+ {% endif %}
172
+ {% endif %}
173
+ </li>
174
+ {% endfor %}
175
+ </ul>
176
+ {% else %}
177
+ <p class="text-muted small">
178
+ <i class="bi bi-exclamation-triangle me-1"></i>
179
+ Navigation "{{ include.nav }}" not found in _data/navigation/
180
+ </p>
181
+ {% endif %}