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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +82 -10
- data/README.md +7 -7
- data/_data/authors.yml +2 -2
- data/_data/features.yml +676 -0
- data/_data/navigation/README.md +54 -0
- data/_data/navigation/about.yml +7 -5
- data/_data/navigation/docs.yml +77 -31
- data/_data/navigation/home.yml +4 -3
- data/_data/navigation/main.yml +16 -7
- data/_data/navigation/quickstart.yml +4 -2
- data/_includes/components/js-cdn.html +2 -2
- data/_includes/landing/landing-install-cards.html +8 -8
- data/_includes/landing/landing-quick-links.html +4 -4
- data/_includes/navigation/breadcrumbs.html +29 -6
- data/_includes/navigation/nav-tree.html +181 -0
- data/_includes/navigation/navbar.html +262 -9
- data/_includes/navigation/sidebar-left.html +22 -23
- data/_layouts/default.html +1 -1
- data/_layouts/landing.html +1 -1
- data/_layouts/notebook.html +4 -4
- data/_layouts/root.html +2 -2
- data/_sass/core/_nav-tree.scss +145 -0
- data/_sass/custom.scss +3 -0
- data/assets/js/modules/navigation/config.js +149 -0
- data/assets/js/modules/navigation/focus.js +189 -0
- data/assets/js/modules/navigation/gestures.js +179 -0
- data/assets/js/modules/navigation/index.js +227 -0
- data/assets/js/modules/navigation/keyboard.js +237 -0
- data/assets/js/modules/navigation/scroll-spy.js +219 -0
- data/assets/js/modules/navigation/sidebar-state.js +267 -0
- data/assets/js/modules/navigation/smooth-scroll.js +153 -0
- data/scripts/migrate-nav-modes.sh +146 -0
- metadata +15 -3
- data/assets/js/sidebar.js +0 -511
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ===================================================================
|
|
3
|
+
* SIDEBAR STATE - Persistence and State Management
|
|
4
|
+
* ===================================================================
|
|
5
|
+
*
|
|
6
|
+
* File: sidebar-state.js
|
|
7
|
+
* Path: assets/js/modules/navigation/sidebar-state.js
|
|
8
|
+
* Purpose: Manage and persist navigation state across page loads
|
|
9
|
+
*
|
|
10
|
+
* Features:
|
|
11
|
+
* - Persist expanded/collapsed state of tree nodes in localStorage
|
|
12
|
+
* - Emit custom events for state changes
|
|
13
|
+
* - Restore state on page load
|
|
14
|
+
* - Track sidebar open/close state
|
|
15
|
+
*
|
|
16
|
+
* Usage:
|
|
17
|
+
* import { SidebarState } from './sidebar-state.js';
|
|
18
|
+
* const state = new SidebarState();
|
|
19
|
+
* state.setExpanded('docs-section', true);
|
|
20
|
+
*
|
|
21
|
+
* ===================================================================
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { config } from './config.js';
|
|
25
|
+
|
|
26
|
+
export class SidebarState {
|
|
27
|
+
constructor() {
|
|
28
|
+
this._storagePrefix = config.state.storagePrefix;
|
|
29
|
+
this._expandedNodes = new Set();
|
|
30
|
+
|
|
31
|
+
this._init();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Initialize state management
|
|
36
|
+
* @private
|
|
37
|
+
*/
|
|
38
|
+
_init() {
|
|
39
|
+
// Load persisted state
|
|
40
|
+
this._loadState();
|
|
41
|
+
|
|
42
|
+
// Listen for collapse events from Bootstrap
|
|
43
|
+
this._setupCollapseListeners();
|
|
44
|
+
|
|
45
|
+
// Restore expanded states on page load
|
|
46
|
+
this._restoreExpandedStates();
|
|
47
|
+
|
|
48
|
+
console.log('SidebarState: Initialized');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Load state from localStorage
|
|
53
|
+
* @private
|
|
54
|
+
*/
|
|
55
|
+
_loadState() {
|
|
56
|
+
try {
|
|
57
|
+
const key = this._storagePrefix + config.state.keys.expandedNodes;
|
|
58
|
+
const stored = localStorage.getItem(key);
|
|
59
|
+
if (stored) {
|
|
60
|
+
const parsed = JSON.parse(stored);
|
|
61
|
+
this._expandedNodes = new Set(parsed);
|
|
62
|
+
}
|
|
63
|
+
} catch (error) {
|
|
64
|
+
console.warn('SidebarState: Could not load state from localStorage', error);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Save state to localStorage
|
|
70
|
+
* @private
|
|
71
|
+
*/
|
|
72
|
+
_saveState() {
|
|
73
|
+
try {
|
|
74
|
+
const key = this._storagePrefix + config.state.keys.expandedNodes;
|
|
75
|
+
const value = JSON.stringify([...this._expandedNodes]);
|
|
76
|
+
localStorage.setItem(key, value);
|
|
77
|
+
} catch (error) {
|
|
78
|
+
console.warn('SidebarState: Could not save state to localStorage', error);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Setup listeners for Bootstrap collapse events
|
|
84
|
+
* @private
|
|
85
|
+
*/
|
|
86
|
+
_setupCollapseListeners() {
|
|
87
|
+
// Listen for collapse show events
|
|
88
|
+
document.addEventListener('show.bs.collapse', (event) => {
|
|
89
|
+
const nodeId = event.target.id;
|
|
90
|
+
if (nodeId && this._isNavNode(event.target)) {
|
|
91
|
+
this.setExpanded(nodeId, true);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Listen for collapse hide events
|
|
96
|
+
document.addEventListener('hide.bs.collapse', (event) => {
|
|
97
|
+
const nodeId = event.target.id;
|
|
98
|
+
if (nodeId && this._isNavNode(event.target)) {
|
|
99
|
+
this.setExpanded(nodeId, false);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Check if element is a navigation node
|
|
106
|
+
* @private
|
|
107
|
+
* @param {Element} element
|
|
108
|
+
* @returns {boolean}
|
|
109
|
+
*/
|
|
110
|
+
_isNavNode(element) {
|
|
111
|
+
// Check if element is within sidebar or has nav-related classes
|
|
112
|
+
return element.closest('.bd-sidebar, .nav-tree, [data-nav-tree]') !== null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Restore expanded states from persisted data
|
|
117
|
+
* @private
|
|
118
|
+
*/
|
|
119
|
+
_restoreExpandedStates() {
|
|
120
|
+
// Wait for DOM to be ready
|
|
121
|
+
requestAnimationFrame(() => {
|
|
122
|
+
this._expandedNodes.forEach(nodeId => {
|
|
123
|
+
const element = document.getElementById(nodeId);
|
|
124
|
+
if (element && typeof bootstrap !== 'undefined') {
|
|
125
|
+
// Show the collapse without animation
|
|
126
|
+
element.classList.add('show');
|
|
127
|
+
|
|
128
|
+
// Update the toggle button state
|
|
129
|
+
const toggle = document.querySelector(`[data-bs-target="#${nodeId}"]`);
|
|
130
|
+
if (toggle) {
|
|
131
|
+
toggle.classList.remove('collapsed');
|
|
132
|
+
toggle.setAttribute('aria-expanded', 'true');
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Set expanded state for a node
|
|
141
|
+
* @param {string} nodeId - The ID of the collapse element
|
|
142
|
+
* @param {boolean} expanded - Whether the node should be expanded
|
|
143
|
+
*/
|
|
144
|
+
setExpanded(nodeId, expanded) {
|
|
145
|
+
if (expanded) {
|
|
146
|
+
this._expandedNodes.add(nodeId);
|
|
147
|
+
} else {
|
|
148
|
+
this._expandedNodes.delete(nodeId);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
this._saveState();
|
|
152
|
+
|
|
153
|
+
// Dispatch custom event
|
|
154
|
+
document.dispatchEvent(new CustomEvent('navigation:toggle', {
|
|
155
|
+
detail: {
|
|
156
|
+
nodeId: nodeId,
|
|
157
|
+
expanded: expanded
|
|
158
|
+
}
|
|
159
|
+
}));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Check if a node is expanded
|
|
164
|
+
* @param {string} nodeId
|
|
165
|
+
* @returns {boolean}
|
|
166
|
+
*/
|
|
167
|
+
isExpanded(nodeId) {
|
|
168
|
+
return this._expandedNodes.has(nodeId);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Expand all nodes
|
|
173
|
+
*/
|
|
174
|
+
expandAll() {
|
|
175
|
+
const collapses = document.querySelectorAll('.bd-sidebar .collapse, .nav-tree .collapse');
|
|
176
|
+
collapses.forEach(collapse => {
|
|
177
|
+
if (collapse.id) {
|
|
178
|
+
this._expandedNodes.add(collapse.id);
|
|
179
|
+
if (typeof bootstrap !== 'undefined') {
|
|
180
|
+
const bsCollapse = bootstrap.Collapse.getOrCreateInstance(collapse, { toggle: false });
|
|
181
|
+
bsCollapse.show();
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
this._saveState();
|
|
186
|
+
|
|
187
|
+
document.dispatchEvent(new CustomEvent('navigation:expandAll'));
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Collapse all nodes
|
|
192
|
+
*/
|
|
193
|
+
collapseAll() {
|
|
194
|
+
const collapses = document.querySelectorAll('.bd-sidebar .collapse.show, .nav-tree .collapse.show');
|
|
195
|
+
collapses.forEach(collapse => {
|
|
196
|
+
if (collapse.id) {
|
|
197
|
+
this._expandedNodes.delete(collapse.id);
|
|
198
|
+
if (typeof bootstrap !== 'undefined') {
|
|
199
|
+
const bsCollapse = bootstrap.Collapse.getInstance(collapse);
|
|
200
|
+
if (bsCollapse) {
|
|
201
|
+
bsCollapse.hide();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
this._saveState();
|
|
207
|
+
|
|
208
|
+
document.dispatchEvent(new CustomEvent('navigation:collapseAll'));
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Expand path to a specific element (expand all parents)
|
|
213
|
+
* @param {string} targetId - The ID of the target element to reveal
|
|
214
|
+
*/
|
|
215
|
+
expandPathTo(targetId) {
|
|
216
|
+
const target = document.getElementById(targetId);
|
|
217
|
+
if (!target) return;
|
|
218
|
+
|
|
219
|
+
// Find all parent collapses
|
|
220
|
+
let parent = target.closest('.collapse');
|
|
221
|
+
while (parent) {
|
|
222
|
+
if (parent.id) {
|
|
223
|
+
this.setExpanded(parent.id, true);
|
|
224
|
+
if (typeof bootstrap !== 'undefined') {
|
|
225
|
+
const bsCollapse = bootstrap.Collapse.getOrCreateInstance(parent, { toggle: false });
|
|
226
|
+
bsCollapse.show();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
parent = parent.parentElement?.closest('.collapse');
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Get all expanded node IDs
|
|
235
|
+
* @returns {string[]}
|
|
236
|
+
*/
|
|
237
|
+
getExpandedNodes() {
|
|
238
|
+
return [...this._expandedNodes];
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Clear all persisted state
|
|
243
|
+
*/
|
|
244
|
+
clearState() {
|
|
245
|
+
this._expandedNodes.clear();
|
|
246
|
+
|
|
247
|
+
try {
|
|
248
|
+
Object.values(config.state.keys).forEach(key => {
|
|
249
|
+
localStorage.removeItem(this._storagePrefix + key);
|
|
250
|
+
});
|
|
251
|
+
} catch (error) {
|
|
252
|
+
console.warn('SidebarState: Could not clear localStorage', error);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
document.dispatchEvent(new CustomEvent('navigation:stateCleared'));
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Cleanup
|
|
260
|
+
*/
|
|
261
|
+
destroy() {
|
|
262
|
+
// State is persisted, nothing to clean up
|
|
263
|
+
console.log('SidebarState: Destroyed');
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export default SidebarState;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ===================================================================
|
|
3
|
+
* SMOOTH SCROLL - Enhanced Anchor Navigation
|
|
4
|
+
* ===================================================================
|
|
5
|
+
*
|
|
6
|
+
* File: smooth-scroll.js
|
|
7
|
+
* Path: assets/js/modules/navigation/smooth-scroll.js
|
|
8
|
+
* Purpose: Smooth scrolling to anchor links with header offset
|
|
9
|
+
*
|
|
10
|
+
* Features:
|
|
11
|
+
* - Smooth scroll with configurable offset for fixed headers
|
|
12
|
+
* - URL hash update without page jump
|
|
13
|
+
* - Closes mobile offcanvas after navigation
|
|
14
|
+
* - Accessibility-focused with proper focus management
|
|
15
|
+
*
|
|
16
|
+
* Usage:
|
|
17
|
+
* import { SmoothScroll } from './smooth-scroll.js';
|
|
18
|
+
* const smoothScroll = new SmoothScroll();
|
|
19
|
+
*
|
|
20
|
+
* ===================================================================
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { config, isBelowBreakpoint } from './config.js';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get all elements safely
|
|
27
|
+
* @param {string} selector - CSS selector
|
|
28
|
+
* @returns {NodeList}
|
|
29
|
+
*/
|
|
30
|
+
function getElements(selector) {
|
|
31
|
+
try {
|
|
32
|
+
return document.querySelectorAll(selector);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.warn(`SmoothScroll: Elements not found - ${selector}`);
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export class SmoothScroll {
|
|
40
|
+
constructor() {
|
|
41
|
+
this.tocLinks = getElements(config.selectors.tocLinks);
|
|
42
|
+
this._init();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Initialize click handlers
|
|
47
|
+
* @private
|
|
48
|
+
*/
|
|
49
|
+
_init() {
|
|
50
|
+
this.tocLinks.forEach(link => {
|
|
51
|
+
link.addEventListener('click', e => this._handleClick(e));
|
|
52
|
+
});
|
|
53
|
+
console.log(`SmoothScroll: Initialized with ${this.tocLinks.length} links`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Handle click on TOC link
|
|
58
|
+
* @private
|
|
59
|
+
* @param {Event} event
|
|
60
|
+
*/
|
|
61
|
+
_handleClick(event) {
|
|
62
|
+
const href = event.currentTarget.getAttribute('href');
|
|
63
|
+
|
|
64
|
+
if (!href || !href.startsWith('#')) return;
|
|
65
|
+
|
|
66
|
+
event.preventDefault();
|
|
67
|
+
|
|
68
|
+
const targetId = href.substring(1);
|
|
69
|
+
const targetElement = document.getElementById(targetId);
|
|
70
|
+
|
|
71
|
+
if (!targetElement) {
|
|
72
|
+
console.warn(`SmoothScroll: Target element #${targetId} not found`);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Scroll to target
|
|
77
|
+
this.scrollToElement(targetElement);
|
|
78
|
+
|
|
79
|
+
// Update URL without jumping
|
|
80
|
+
if (history.pushState) {
|
|
81
|
+
history.pushState(null, null, href);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Close mobile offcanvas if open
|
|
85
|
+
this._closeMobileOffcanvas();
|
|
86
|
+
|
|
87
|
+
// Dispatch custom event
|
|
88
|
+
document.dispatchEvent(new CustomEvent('navigation:scroll', {
|
|
89
|
+
detail: {
|
|
90
|
+
targetId: targetId,
|
|
91
|
+
targetElement: targetElement
|
|
92
|
+
}
|
|
93
|
+
}));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Scroll to an element with offset
|
|
98
|
+
* @param {Element} element - Target element
|
|
99
|
+
* @param {number} [offset] - Optional custom offset
|
|
100
|
+
*/
|
|
101
|
+
scrollToElement(element, offset = config.smoothScroll.offset) {
|
|
102
|
+
const elementPosition = element.getBoundingClientRect().top;
|
|
103
|
+
const offsetPosition = elementPosition + window.pageYOffset - offset;
|
|
104
|
+
|
|
105
|
+
window.scrollTo({
|
|
106
|
+
top: offsetPosition,
|
|
107
|
+
behavior: config.smoothScroll.behavior
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// Update focus for accessibility
|
|
111
|
+
element.setAttribute('tabindex', '-1');
|
|
112
|
+
element.focus({ preventScroll: true });
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Scroll to element by ID
|
|
117
|
+
* @param {string} id - Element ID (without #)
|
|
118
|
+
* @param {number} [offset] - Optional custom offset
|
|
119
|
+
*/
|
|
120
|
+
scrollToId(id, offset) {
|
|
121
|
+
const element = document.getElementById(id);
|
|
122
|
+
if (element) {
|
|
123
|
+
this.scrollToElement(element, offset);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Close mobile offcanvas if viewport is below lg breakpoint
|
|
129
|
+
* @private
|
|
130
|
+
*/
|
|
131
|
+
_closeMobileOffcanvas() {
|
|
132
|
+
if (!isBelowBreakpoint('lg')) return;
|
|
133
|
+
|
|
134
|
+
const tocOffcanvas = document.getElementById('tocContents');
|
|
135
|
+
if (tocOffcanvas && typeof bootstrap !== 'undefined') {
|
|
136
|
+
const bsOffcanvas = bootstrap.Offcanvas.getInstance(tocOffcanvas);
|
|
137
|
+
if (bsOffcanvas) {
|
|
138
|
+
bsOffcanvas.hide();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Cleanup event listeners
|
|
145
|
+
*/
|
|
146
|
+
destroy() {
|
|
147
|
+
// Note: We'd need to store bound handlers to properly remove them
|
|
148
|
+
// For now, this is a no-op since the page will reload anyway
|
|
149
|
+
console.log('SmoothScroll: Destroyed');
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export default SmoothScroll;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ===================================================================
|
|
3
|
+
# MIGRATE NAV MODES - Update Front Matter Navigation Values
|
|
4
|
+
# ===================================================================
|
|
5
|
+
#
|
|
6
|
+
# File: migrate-nav-modes.sh
|
|
7
|
+
# Path: scripts/migrate-nav-modes.sh
|
|
8
|
+
# Purpose: Update front matter nav values from old to new modes
|
|
9
|
+
#
|
|
10
|
+
# Migration Map:
|
|
11
|
+
# dynamic → auto
|
|
12
|
+
# searchCats → categories
|
|
13
|
+
# docs → tree
|
|
14
|
+
# about → tree
|
|
15
|
+
# quickstart → tree
|
|
16
|
+
# main → tree
|
|
17
|
+
#
|
|
18
|
+
# Usage:
|
|
19
|
+
# ./scripts/migrate-nav-modes.sh # Dry run (preview changes)
|
|
20
|
+
# ./scripts/migrate-nav-modes.sh --apply # Apply changes
|
|
21
|
+
#
|
|
22
|
+
# ===================================================================
|
|
23
|
+
|
|
24
|
+
set -eo pipefail
|
|
25
|
+
|
|
26
|
+
# Colors for output
|
|
27
|
+
RED='\033[0;31m'
|
|
28
|
+
GREEN='\033[0;32m'
|
|
29
|
+
YELLOW='\033[1;33m'
|
|
30
|
+
BLUE='\033[0;34m'
|
|
31
|
+
NC='\033[0m' # No Color
|
|
32
|
+
|
|
33
|
+
# Script configuration
|
|
34
|
+
PAGES_DIR="pages"
|
|
35
|
+
DRY_RUN=true
|
|
36
|
+
|
|
37
|
+
# Parse arguments
|
|
38
|
+
if [[ "${1:-}" == "--apply" ]]; then
|
|
39
|
+
DRY_RUN=false
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
|
|
43
|
+
echo -e "${BLUE} Navigation Mode Migration Script${NC}"
|
|
44
|
+
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
|
|
45
|
+
echo ""
|
|
46
|
+
|
|
47
|
+
if $DRY_RUN; then
|
|
48
|
+
echo -e "${YELLOW}Running in DRY RUN mode. No files will be modified.${NC}"
|
|
49
|
+
echo -e "${YELLOW}Use --apply to make actual changes.${NC}"
|
|
50
|
+
else
|
|
51
|
+
echo -e "${RED}Running in APPLY mode. Files will be modified.${NC}"
|
|
52
|
+
fi
|
|
53
|
+
echo ""
|
|
54
|
+
|
|
55
|
+
# Migration patterns (old → new)
|
|
56
|
+
# Using simple arrays instead of associative arrays for compatibility
|
|
57
|
+
OLD_PATTERNS=("nav: dynamic" "nav: searchCats")
|
|
58
|
+
NEW_PATTERNS=("nav: auto" "nav: categories")
|
|
59
|
+
|
|
60
|
+
# Files that explicitly set nav values (not inherited from _config.yml)
|
|
61
|
+
EXPLICIT_NAV_PATTERNS=(
|
|
62
|
+
"nav: dynamic"
|
|
63
|
+
"nav: searchCats"
|
|
64
|
+
"nav: docs"
|
|
65
|
+
"nav: about"
|
|
66
|
+
"nav: quickstart"
|
|
67
|
+
"nav: main"
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
# Count changes
|
|
71
|
+
TOTAL_FILES=0
|
|
72
|
+
TOTAL_CHANGES=0
|
|
73
|
+
|
|
74
|
+
echo -e "${BLUE}Scanning for files with explicit nav values...${NC}"
|
|
75
|
+
echo ""
|
|
76
|
+
|
|
77
|
+
# Find all markdown files
|
|
78
|
+
while IFS= read -r -d '' file; do
|
|
79
|
+
file_changes=0
|
|
80
|
+
|
|
81
|
+
# Check if file has any nav patterns
|
|
82
|
+
for pattern in "${EXPLICIT_NAV_PATTERNS[@]}"; do
|
|
83
|
+
if grep -q "$pattern" "$file" 2>/dev/null; then
|
|
84
|
+
((file_changes++)) || true
|
|
85
|
+
fi
|
|
86
|
+
done
|
|
87
|
+
|
|
88
|
+
if [[ $file_changes -gt 0 ]]; then
|
|
89
|
+
((TOTAL_FILES++)) || true
|
|
90
|
+
echo -e "${GREEN}Found:${NC} $file"
|
|
91
|
+
|
|
92
|
+
# Show what would change
|
|
93
|
+
for i in "${!OLD_PATTERNS[@]}"; do
|
|
94
|
+
old_pattern="${OLD_PATTERNS[$i]}"
|
|
95
|
+
new_pattern="${NEW_PATTERNS[$i]}"
|
|
96
|
+
if grep -q "$old_pattern" "$file" 2>/dev/null; then
|
|
97
|
+
echo -e " ${YELLOW}Change:${NC} '$old_pattern' → '$new_pattern'"
|
|
98
|
+
((TOTAL_CHANGES++)) || true
|
|
99
|
+
|
|
100
|
+
if ! $DRY_RUN; then
|
|
101
|
+
# Apply the change using sed
|
|
102
|
+
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
103
|
+
sed -i '' "s/$old_pattern/$new_pattern/g" "$file"
|
|
104
|
+
else
|
|
105
|
+
sed -i "s/$old_pattern/$new_pattern/g" "$file"
|
|
106
|
+
fi
|
|
107
|
+
fi
|
|
108
|
+
fi
|
|
109
|
+
done
|
|
110
|
+
|
|
111
|
+
# Check for named nav files that should use tree mode
|
|
112
|
+
# Note: These are trickier because we want to keep the YAML file reference
|
|
113
|
+
# but change how the template interprets them
|
|
114
|
+
for named_nav in "docs" "about" "quickstart" "main"; do
|
|
115
|
+
if grep -q "nav: $named_nav" "$file" 2>/dev/null; then
|
|
116
|
+
echo -e " ${BLUE}Note:${NC} 'nav: $named_nav' - YAML file will be used with tree mode"
|
|
117
|
+
# No automatic migration - sidebar-left.html handles this via fallthrough
|
|
118
|
+
fi
|
|
119
|
+
done
|
|
120
|
+
|
|
121
|
+
echo ""
|
|
122
|
+
fi
|
|
123
|
+
done < <(find "$PAGES_DIR" -name "*.md" -print0 2>/dev/null)
|
|
124
|
+
|
|
125
|
+
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
|
|
126
|
+
echo -e "${BLUE} Summary${NC}"
|
|
127
|
+
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
|
|
128
|
+
echo ""
|
|
129
|
+
echo -e "Files scanned: ${GREEN}$(find "$PAGES_DIR" -name "*.md" 2>/dev/null | wc -l | tr -d ' ')${NC}"
|
|
130
|
+
echo -e "Files affected: ${GREEN}$TOTAL_FILES${NC}"
|
|
131
|
+
echo -e "Changes made: ${GREEN}$TOTAL_CHANGES${NC}"
|
|
132
|
+
echo ""
|
|
133
|
+
|
|
134
|
+
if $DRY_RUN; then
|
|
135
|
+
echo -e "${YELLOW}This was a dry run. To apply changes, run:${NC}"
|
|
136
|
+
echo -e " ${GREEN}./scripts/migrate-nav-modes.sh --apply${NC}"
|
|
137
|
+
else
|
|
138
|
+
echo -e "${GREEN}Migration complete!${NC}"
|
|
139
|
+
fi
|
|
140
|
+
|
|
141
|
+
echo ""
|
|
142
|
+
echo -e "${BLUE}Navigation Mode Reference:${NC}"
|
|
143
|
+
echo " auto - Auto-generated from collection documents"
|
|
144
|
+
echo " tree - YAML-defined hierarchical navigation"
|
|
145
|
+
echo " categories - Category-based grouping"
|
|
146
|
+
echo ""
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jekyll-theme-zer0
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.17.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Amr Abdel
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-12-
|
|
11
|
+
date: 2025-12-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: jekyll
|
|
@@ -80,9 +80,11 @@ files:
|
|
|
80
80
|
- _data/README.md
|
|
81
81
|
- _data/authors.yml
|
|
82
82
|
- _data/content_statistics.yml
|
|
83
|
+
- _data/features.yml
|
|
83
84
|
- _data/generate_statistics.rb
|
|
84
85
|
- _data/generate_statistics.sh
|
|
85
86
|
- _data/github-actions-example.yml
|
|
87
|
+
- _data/navigation/README.md
|
|
86
88
|
- _data/navigation/about.yml
|
|
87
89
|
- _data/navigation/docs.yml
|
|
88
90
|
- _data/navigation/home.yml
|
|
@@ -127,6 +129,7 @@ files:
|
|
|
127
129
|
- _includes/landing/landing-install-cards.html
|
|
128
130
|
- _includes/landing/landing-quick-links.html
|
|
129
131
|
- _includes/navigation/breadcrumbs.html
|
|
132
|
+
- _includes/navigation/nav-tree.html
|
|
130
133
|
- _includes/navigation/nav_list.html
|
|
131
134
|
- _includes/navigation/navbar.html
|
|
132
135
|
- _includes/navigation/sidebar-categories.html
|
|
@@ -157,6 +160,7 @@ files:
|
|
|
157
160
|
- _plugins/preview_image_generator.rb
|
|
158
161
|
- _plugins/theme_version.rb
|
|
159
162
|
- _sass/core/_docs.scss
|
|
163
|
+
- _sass/core/_nav-tree.scss
|
|
160
164
|
- _sass/core/_syntax.scss
|
|
161
165
|
- _sass/core/_theme.scss
|
|
162
166
|
- _sass/core/_variables.scss
|
|
@@ -202,12 +206,19 @@ files:
|
|
|
202
206
|
- assets/js/color-modes.js
|
|
203
207
|
- assets/js/docs.min.js
|
|
204
208
|
- assets/js/halfmoon.js
|
|
209
|
+
- assets/js/modules/navigation/config.js
|
|
210
|
+
- assets/js/modules/navigation/focus.js
|
|
211
|
+
- assets/js/modules/navigation/gestures.js
|
|
212
|
+
- assets/js/modules/navigation/index.js
|
|
213
|
+
- assets/js/modules/navigation/keyboard.js
|
|
214
|
+
- assets/js/modules/navigation/scroll-spy.js
|
|
215
|
+
- assets/js/modules/navigation/sidebar-state.js
|
|
216
|
+
- assets/js/modules/navigation/smooth-scroll.js
|
|
205
217
|
- assets/js/myScript.js
|
|
206
218
|
- assets/js/nanobar.min.js
|
|
207
219
|
- assets/js/particles-source.js
|
|
208
220
|
- assets/js/particles.js
|
|
209
221
|
- assets/js/side-bar-folders.js
|
|
210
|
-
- assets/js/sidebar.js
|
|
211
222
|
- assets/particles.json
|
|
212
223
|
- scripts/README.md
|
|
213
224
|
- scripts/analyze-commits.sh
|
|
@@ -231,6 +242,7 @@ files:
|
|
|
231
242
|
- scripts/lib/preview_generator.py
|
|
232
243
|
- scripts/lib/validation.sh
|
|
233
244
|
- scripts/lib/version.sh
|
|
245
|
+
- scripts/migrate-nav-modes.sh
|
|
234
246
|
- scripts/release
|
|
235
247
|
- scripts/setup.sh
|
|
236
248
|
- scripts/test-auto-version.sh
|