jekyll-theme-zer0 0.17.2 → 0.18.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cdb1bbc3f82ba18d008ef8128592fadf16247cc1c45c6248a6f48d31c41f0c44
4
- data.tar.gz: b62640c64c7032103f03155fdf447942e4fed67195e3b5acc3eaad526b90558f
3
+ metadata.gz: e3cdc2d41bf042b7f0f71b9f43dd9347c43bbbbb500cf95ef6bf2deed492fcb5
4
+ data.tar.gz: cb4b0b4bf44a66294fb4d6fab901932fc4a024c2a8f4c9b46c0fcfe69895d825
5
5
  SHA512:
6
- metadata.gz: b9bcf7b150affaaba80d5787df4c1ca6fd5e7c46c8e2c6b0835dae371fa296f91915e72d5f49bb1c47482f8c0a10ed96f551ae95767831c107e93dc9ecfca395
7
- data.tar.gz: 9886baeb0f69e536ee19b59f13ac4ef6389cdae053e1427bb8b4e177a517aa735e40555b5d0fa0a7143caa0540d40f07d419313513f606998d402c1b1201bfd3
6
+ metadata.gz: 874947c58a3abea526c10aab5d5936a30705e6f87286e2779be094717f7297328adfbdff8a946dfa228969bd4d655bf75c7689f3a29b84e880ce078b74bbc4e9
7
+ data.tar.gz: ee12a3e265ead26b0566b6e8cecb1165fb8bf2b6bc7c3513cd15b4f9baa2d9acca2abfbc2e8e239284f4c5546bee100552991aa5d4b34827351b636fbb9df151
data/CHANGELOG.md CHANGED
@@ -1,5 +1,46 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.18.0] - 2026-01-19
4
+
5
+ ### Added
6
+ - **Search Modal**: New site-wide search popup with live results, keyboard shortcuts (`/`, `Cmd/Ctrl+K`), and offcanvas entry
7
+ - **Search Index**: Generated `search.json` index including page content for client-side search
8
+
9
+ ### Changed
10
+ - **Navigation**: Added search button to the main navbar with improved mobile layout support
11
+
12
+ ### Fixed
13
+ - **Search UX**: Highlight query matches and show content-based snippets where the match occurs
14
+
15
+ ## [0.17.5] - 2026-01-17
16
+
17
+ ### Changed
18
+ - Version bump: patch release
19
+
20
+ ### Commits in this release
21
+ - eeb8ea3 fix(ui): remove cursor tilt and prep v0.17.4
22
+
23
+ ## [0.17.4] - 2026-01-16
24
+
25
+ ### Changed
26
+ - Version bump: patch release
27
+
28
+ ### Fixed
29
+ - **UI/UX**: Removed cursor-based 3D parallax tilt effect on cards to prevent perspective shifts on hover
30
+ - **Config YAML**: Corrected anchor definitions used by gravatar and local repo settings to pass YAML validation
31
+
32
+ ### Commits in this release
33
+ - 226b0a5 chore(structure): reorganize root directory for better maintainability
34
+
35
+ ## [0.17.3] - 2026-01-15
36
+
37
+ ### Changed
38
+ - Version bump: patch release
39
+
40
+ ### Commits in this release
41
+ - a0c1df4 fix(ui): fix Mermaid dark mode and cookie banner rendering
42
+
43
+
3
44
  ## [0.17.2] - 2025-12-31
4
45
 
5
46
  ### Fixed
data/README.md CHANGED
@@ -569,7 +569,7 @@ graph LR
569
569
  | [🤖 Copilot Instructions]({{ site.resources.github_repo | default: '' | join: '' }}/blob/{{ site.branch }}/.github/copilot-instructions.md) | AI development guidelines |
570
570
  | [⌨️ Keyboard Navigation]({{ site.resources.github_repo | default: '' | join: '' }}/blob/{{ site.branch }}/docs/keyboard-navigation.md) | Accessibility shortcuts guide |
571
571
  | [📓 Jupyter Notebooks]({{ site.resources.github_repo | default: '' | join: '' }}/blob/{{ site.branch }}/docs/JUPYTER_NOTEBOOKS.md) | Notebook conversion documentation |
572
- | [📝 PRD](PRD.md) | Product requirements & roadmap |
572
+ | [📝 PRD](docs/PRD.md) | Product requirements & roadmap |
573
573
  | [🔒 Privacy Policy]({{ '/privacy-policy/' | relative_url }}) | GDPR/CCPA compliant privacy docs |
574
574
 
575
575
  ---
@@ -29,4 +29,7 @@
29
29
  crossorigin="anonymous"></script>
30
30
 
31
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>
32
+ <script type="module" src="{{ '/assets/js/modules/navigation/index.js' | relative_url }}"></script>
33
+
34
+ <!-- Search modal controller -->
35
+ <script src="{{ '/assets/js/search-modal.js' | relative_url }}"></script>
@@ -0,0 +1,56 @@
1
+ <!--
2
+ ===================================================================
3
+ SEARCH MODAL - Site-wide Search Popup
4
+ ===================================================================
5
+
6
+ File: search-modal.html
7
+ Path: _includes/components/search-modal.html
8
+ Purpose: Provide a modal search experience with keyboard shortcut support
9
+
10
+ Notes:
11
+ - Uses /sitemap/ for query-based search results
12
+ - Keyboard shortcut handled by navigation keyboard module ("/")
13
+ ===================================================================
14
+ -->
15
+
16
+ {%- assign ui_text = site.data.ui-text[site.locale] | default: site.data.ui-text.en -%}
17
+ {%- assign search_placeholder = ui_text.search_placeholder_text | default: "Enter your search term..." -%}
18
+
19
+ <div class="modal fade search-modal" id="siteSearchModal" tabindex="-1" aria-labelledby="siteSearchModalLabel" aria-hidden="true">
20
+ <div class="modal-dialog modal-dialog-centered">
21
+ <div class="modal-content">
22
+ <div class="modal-header">
23
+ <h5 class="modal-title" id="siteSearchModalLabel">
24
+ <i class="bi bi-search me-2"></i>Search
25
+ </h5>
26
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
27
+ </div>
28
+ <div class="modal-body">
29
+ <form action="{{ '/sitemap/' | relative_url }}" method="get" data-search-form>
30
+ <label class="visually-hidden" for="site-search-input">Search</label>
31
+ <div class="input-group">
32
+ <span class="input-group-text">
33
+ <i class="bi bi-search" aria-hidden="true"></i>
34
+ </span>
35
+ <input
36
+ id="site-search-input"
37
+ type="search"
38
+ name="q"
39
+ class="form-control"
40
+ placeholder="{{ search_placeholder }}"
41
+ autocomplete="off"
42
+ data-search-input
43
+ >
44
+ <button class="btn btn-primary" type="submit">Search</button>
45
+ </div>
46
+ <div class="form-text mt-2">
47
+ Press <kbd>/</kbd> or <kbd>⌘</kbd>/<kbd>Ctrl</kbd>+<kbd>K</kbd> to open search, <kbd>Esc</kbd> to close.
48
+ </div>
49
+ </form>
50
+ <div class="search-results mt-3" data-search-results>
51
+ <div class="text-muted small" data-search-empty>Start typing to see results.</div>
52
+ </div>
53
+ </div>
54
+ </div>
55
+ </div>
56
+ </div>
@@ -32,24 +32,23 @@
32
32
 
33
33
  <!-- Title Section -->
34
34
 
35
- <div class="navbar-brand">
36
- <a class="nav-link" href="{{ page.url | relative_url }}">
37
- <i class="d-sm-inline d-md-none {{ site.default_icon }} {{ site.default_icon }}-{{ site.title_icon | default: 'house' }}" aria-hidden="true"></i>
38
- <!-- Display name if there's enough space, else icon only -->
39
- <span class="d-none d-md-inline">
35
+ <div class="navbar-brand site-title">
36
+ <a class="nav-link" href="{{ '/' | relative_url }}">
37
+ <i class="d-none d-md-inline {{ site.default_icon }} {{ site.default_icon }}-{{ site.title_icon | default: 'house' }}" aria-hidden="true"></i>
38
+ <!-- Always show the title on mobile; truncate if space is tight -->
39
+ <span class="site-title-text">
40
40
  {{ site.title }}
41
41
  </span>
42
42
  </a>
43
43
  </div>
44
44
 
45
- <div class="navbar-brand">
46
- <!-- If a subtitle exists -->
47
- {%- if site.subtitle -%}
48
- <a class="nav-link" href="{{ page.url | relative_url }}">
49
- <i class="d-sm-inline d-md-none {{ site.default_icon }} {{ site.default_icon }}-{{ site.subtitle_icon | default: 'journal' }}" aria-hidden="true"></i>
50
- <span class="d-none d-md-inline">
45
+ <!-- If a subtitle exists -->
46
+ {%- if site.subtitle -%}
47
+ <div class="navbar-brand site-subtitle d-none d-lg-inline">
48
+ <a class="nav-link" href="{{ '/' | relative_url }}">
49
+ <span class="site-subtitle-text">
51
50
  {{ site.subtitle }}
52
51
  </span>
53
52
  </a>
54
- {% endif %}
55
- </div>
53
+ </div>
54
+ {% endif %}
@@ -60,39 +60,53 @@
60
60
  <!-- ========================== -->
61
61
  <!-- MAIN NAVIGATION CONTAINER -->
62
62
  <!-- ========================== -->
63
- <nav class="container-xl order-2 order-lg-1 grid gap-1">
63
+ <nav class="container-xl order-2 order-lg-1 grid gap-1 navbar-main">
64
64
 
65
65
  <!-- ========================== -->
66
66
  <!-- MOBILE MENU CONTROLS -->
67
67
  <!-- ========================== -->
68
68
 
69
69
  <!-- Left Sidebar Toggle - Mobile view only -->
70
+ {% assign sidebar_nav = page.sidebar.nav | default: nil %}
71
+ {% assign sidebar_has_content = false %}
72
+ {% if sidebar_nav %}
73
+ {% if sidebar_nav == "auto" or sidebar_nav == "categories" %}
74
+ {% assign sidebar_has_content = true %}
75
+ {% elsif site.data.navigation[sidebar_nav] %}
76
+ {% assign sidebar_has_content = true %}
77
+ {% endif %}
78
+ {% endif %}
79
+
80
+ {% if sidebar_has_content %}
70
81
  <div class="bd-navbar-toggle">
71
82
  <button class="navbar-toggler p-2"
72
83
  type="button"
73
84
  data-bs-toggle="offcanvas"
74
85
  data-bs-target="#bdSidebar"
75
86
  aria-controls="bdSidebar"
76
- aria-label="Toggle navigation">
87
+ aria-label="Toggle sidebar navigation">
77
88
  <span class="bi bi-list"></span>
78
89
  </button>
79
90
  </div>
91
+ {% endif %}
80
92
 
81
93
  <!-- ========================== -->
82
94
  <!-- BRAND AND HOME NAVIGATION -->
83
95
  <!-- ========================== -->
84
- <div class="container d-inline-flex text-center">
85
- <!-- Home Navigation Button -->
86
- {%- for home in site.data.navigation.home -%}
87
- <a class="btn" href="{{ home.url | relative_url }}">
88
- <i class="{{ site.default_icon}} {{ home.icon }}"></i>
89
- </a>
90
- {% endfor %}
96
+ <div class="navbar-brand-group d-inline-flex align-items-center gap-2">
97
+ <!-- Home Navigation Button (Desktop only) -->
98
+ <div class="navbar-home-links d-none d-lg-inline-flex">
99
+ {%- for home in site.data.navigation.home -%}
100
+ <a class="btn" href="{{ home.url | relative_url }}" aria-label="{{ home.title }}" title="{{ home.title }}">
101
+ <i class="{{ site.default_icon}} {{ home.icon }}"></i>
102
+ </a>
103
+ {% endfor %}
104
+ </div>
91
105
 
92
106
  <!-- Brand Logo Link to Root -->
93
107
  <!-- Logo path configured in _config.yml -->
94
108
  {% capture logo_path %}{{ site.logo }}{% endcapture %}
95
- <a class="navbar-brand" href="{{ site.baseurl }}/">
109
+ <a class="navbar-brand" href="{{ site.baseurl }}/" aria-label="Home">
96
110
  <img src="{{ logo_path | relative_url }}" alt="Logo" width="30" height="30">
97
111
  </a>
98
112
  </div>
@@ -113,8 +127,21 @@
113
127
  <!-- UTILITY CONTROLS -->
114
128
  <!-- ========================== -->
115
129
 
130
+ <!-- Search Modal Toggle -->
131
+ <button
132
+ class="btn nav-search-button"
133
+ type="button"
134
+ data-bs-toggle="modal"
135
+ data-bs-target="#siteSearchModal"
136
+ data-search-toggle
137
+ aria-label="Open search"
138
+ >
139
+ <i class="{{site.default_icon}} bi-search"></i>
140
+ <span class="d-none d-lg-inline ms-1">Search</span>
141
+ </button>
142
+
116
143
  <!-- Settings Modal Toggle -->
117
- <div class="btn"
144
+ <div class="btn d-none d-lg-flex nav-settings"
118
145
  data-bs-toggle="modal"
119
146
  data-bs-target="#info-section"
120
147
  aria-expanded="false"
@@ -18,6 +18,12 @@
18
18
  <!-- Main Navigation Body - Offcanvas -->
19
19
  <div class="offcanvas-body">
20
20
  <ul class="navbar-nav justify-content-lg-center text-start flex-grow-1">
21
+ <li class="nav-item d-lg-none">
22
+ <a class="nav-link" href="{{ '/' | relative_url }}">
23
+ <i class="{{site.default_icon}} bi-house me-2"></i>
24
+ Home
25
+ </a>
26
+ </li>
21
27
  {%- for link in site.data.navigation.main -%}
22
28
  {%- assign has_children = link.children and link.children.size > 0 -%}
23
29
 
@@ -81,6 +87,31 @@
81
87
  </li>
82
88
  {%- endif -%}
83
89
  {%- endfor -%}
90
+ <li class="nav-item d-lg-none">
91
+ <button
92
+ class="nav-link btn btn-link text-start w-100"
93
+ type="button"
94
+ data-bs-toggle="modal"
95
+ data-bs-target="#siteSearchModal"
96
+ data-search-toggle
97
+ aria-label="Open search"
98
+ >
99
+ <i class="{{site.default_icon}} bi-search me-2"></i>
100
+ Search
101
+ </button>
102
+ </li>
103
+ <li class="nav-item d-lg-none">
104
+ <button
105
+ class="nav-link btn btn-link text-start w-100"
106
+ type="button"
107
+ data-bs-toggle="modal"
108
+ data-bs-target="#info-section"
109
+ aria-controls="info-section"
110
+ >
111
+ <i class="{{site.default_icon}} bi-gear me-2"></i>
112
+ Settings
113
+ </button>
114
+ </li>
84
115
  </ul>
85
116
  </div>
86
117
  </div>
data/_layouts/root.html CHANGED
@@ -59,6 +59,9 @@
59
59
  <!-- Main site header with navigation, branding, and search functionality -->
60
60
  {% include core/header.html %}
61
61
 
62
+ <!-- Search modal (site-wide) -->
63
+ {% include components/search-modal.html %}
64
+
62
65
  <!-- Site-wide information banner or announcement section -->
63
66
  {% include components/info-section.html %}
64
67
 
data/_sass/custom.scss CHANGED
@@ -231,6 +231,21 @@ img {
231
231
  background-color: var(--bs-body-bg);
232
232
  }
233
233
 
234
+ #navbar .navbar-main {
235
+ align-items: center;
236
+ }
237
+
238
+ #navbar .site-title-text,
239
+ #navbar .site-subtitle-text {
240
+ display: inline-block;
241
+ }
242
+
243
+ #navbar .nav-search-button {
244
+ display: inline-flex;
245
+ align-items: center;
246
+ gap: 0.25rem;
247
+ }
248
+
234
249
  // Hidden state - slides up out of view
235
250
  // Using higher specificity to override Bootstrap's fixed-top
236
251
  #navbar.navbar-hidden {
@@ -244,6 +259,73 @@ img {
244
259
  }
245
260
  }
246
261
 
262
+ @media (max-width: 991.98px) {
263
+ #navbar .navbar-main {
264
+ display: flex;
265
+ align-items: center;
266
+ justify-content: space-between;
267
+ gap: 0.5rem;
268
+ padding-left: 0.5rem;
269
+ padding-right: 0.5rem;
270
+ }
271
+
272
+ #navbar .navbar-brand-group {
273
+ flex: 1 1 auto;
274
+ min-width: 0;
275
+ }
276
+
277
+ #navbar .site-title .nav-link {
278
+ padding: 0;
279
+ }
280
+
281
+ #navbar .site-title-text {
282
+ max-width: 45vw;
283
+ white-space: nowrap;
284
+ overflow: hidden;
285
+ text-overflow: ellipsis;
286
+ }
287
+
288
+ #navbar .navbar-brand img {
289
+ width: 28px;
290
+ height: 28px;
291
+ }
292
+
293
+ #navbar .navbar-toggler {
294
+ width: 2.5rem;
295
+ height: 2.5rem;
296
+ }
297
+
298
+ #navbar .nav-search-button {
299
+ width: 2.5rem;
300
+ height: 2.5rem;
301
+ padding: 0;
302
+ justify-content: center;
303
+ }
304
+ }
305
+
306
+ .search-modal .modal-content {
307
+ border-radius: 0.75rem;
308
+ }
309
+
310
+ .search-modal .input-group-text {
311
+ background-color: var(--bs-tertiary-bg);
312
+ border-color: var(--bs-border-color);
313
+ }
314
+
315
+ .search-modal kbd {
316
+ background-color: var(--bs-tertiary-bg);
317
+ color: var(--bs-body-color);
318
+ }
319
+
320
+ .search-modal .search-results {
321
+ max-height: 50vh;
322
+ overflow-y: auto;
323
+ }
324
+
325
+ .search-modal .list-group-item {
326
+ border-color: var(--bs-border-color-translucent);
327
+ }
328
+
247
329
  $enable-cssgrid: true;
248
330
  $enable-grid-classes: false;
249
331
 
@@ -103,6 +103,11 @@ export class KeyboardShortcuts {
103
103
  this._toggleToc();
104
104
  }
105
105
  break;
106
+ default:
107
+ if (event.code === 'Slash' && keys.search === '/') {
108
+ event.preventDefault();
109
+ this._focusSearch();
110
+ }
106
111
  }
107
112
  }
108
113
 
@@ -169,10 +174,12 @@ export class KeyboardShortcuts {
169
174
  */
170
175
  _focusSearch() {
171
176
  const searchInput = document.querySelector('#search-input, [data-search-input]');
172
- if (searchInput) {
177
+ const searchModal = searchInput?.closest('.modal');
178
+ const modalVisible = searchModal?.classList.contains('show');
179
+
180
+ if (searchInput && (!searchModal || modalVisible)) {
173
181
  searchInput.focus();
174
182
  } else {
175
- console.log('KeyboardShortcuts: Search not yet implemented');
176
183
  // Dispatch event so other modules can handle
177
184
  document.dispatchEvent(new CustomEvent('navigation:searchRequest'));
178
185
  }