jekyll-theme-zer0 0.10.4 → 0.15.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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +459 -0
  3. data/README.md +24 -8
  4. data/_data/navigation/about.yml +39 -11
  5. data/_data/navigation/docs.yml +53 -23
  6. data/_data/navigation/home.yml +27 -9
  7. data/_data/navigation/main.yml +27 -8
  8. data/_data/navigation/posts.yml +22 -6
  9. data/_data/navigation/quickstart.yml +8 -3
  10. data/_includes/README.md +2 -0
  11. data/_includes/components/js-cdn.html +4 -1
  12. data/_includes/components/post-card.html +2 -11
  13. data/_includes/components/preview-image.html +32 -0
  14. data/_includes/content/intro.html +5 -6
  15. data/_includes/core/footer.html +5 -3
  16. data/_includes/core/header.html +14 -0
  17. data/_includes/navigation/sidebar-categories.html +20 -9
  18. data/_includes/navigation/sidebar-folders.html +8 -7
  19. data/_includes/navigation/sidebar-right.html +16 -10
  20. data/_layouts/blog.html +15 -45
  21. data/_layouts/category.html +4 -24
  22. data/_layouts/collection.html +2 -12
  23. data/_layouts/default.html +1 -1
  24. data/_layouts/journals.html +2 -12
  25. data/_layouts/notebook.html +296 -0
  26. data/_sass/core/_docs.scss +1 -1
  27. data/_sass/custom.scss +55 -18
  28. data/_sass/notebooks.scss +458 -0
  29. data/assets/images/notebooks/test-notebook_files/test-notebook_4_0.png +0 -0
  30. data/assets/js/sidebar.js +511 -0
  31. data/scripts/README.md +128 -105
  32. data/scripts/analyze-commits.sh +9 -311
  33. data/scripts/bin/build +22 -22
  34. data/scripts/build +7 -111
  35. data/scripts/convert-notebooks.sh +415 -0
  36. data/scripts/features/validate_preview_urls.py +500 -0
  37. data/scripts/fix-markdown-format.sh +8 -262
  38. data/scripts/generate-preview-images.sh +7 -787
  39. data/scripts/install-preview-generator.sh +8 -528
  40. data/scripts/lib/README.md +5 -5
  41. data/scripts/lib/gem.sh +19 -7
  42. data/scripts/release +7 -236
  43. data/scripts/setup.sh +9 -153
  44. data/scripts/test-auto-version.sh +7 -256
  45. data/scripts/test-mermaid.sh +7 -287
  46. data/scripts/test.sh +9 -154
  47. metadata +9 -10
  48. data/scripts/features/preview_generator.py +0 -646
  49. data/scripts/lib/test/run_tests.sh +0 -140
  50. data/scripts/lib/test/test_changelog.sh +0 -87
  51. data/scripts/lib/test/test_gem.sh +0 -68
  52. data/scripts/lib/test/test_git.sh +0 -82
  53. data/scripts/lib/test/test_validation.sh +0 -72
  54. data/scripts/lib/test/test_version.sh +0 -96
  55. data/scripts/version.sh +0 -178
@@ -188,18 +188,8 @@ layout: default
188
188
  <div class="col">
189
189
  <div class="card h-100 border-0 shadow-sm">
190
190
  <a href="{{ rpost.url | relative_url }}" class="text-decoration-none">
191
- {% if rpost.preview %}
192
- {% if rpost.preview contains '/assets' %}
193
- <img src="{{ site.baseurl }}{{ rpost.preview }}"
194
- class="card-img-top" alt="{{ rpost.title }}" loading="lazy">
195
- {% else %}
196
- <img src="{{ site.baseurl }}/{{ site.public_folder }}/{{ rpost.preview }}"
197
- class="card-img-top" alt="{{ rpost.title }}" loading="lazy">
198
- {% endif %}
199
- {% else %}
200
- <img src="{{ site.baseurl }}/{{ site.public_folder }}{{ site.teaser }}"
201
- class="card-img-top" alt="Preview" loading="lazy">
202
- {% endif %}
191
+ {% assign rpost_img = rpost.preview | default: site.teaser %}
192
+ {% include components/preview-image.html src=rpost_img alt=rpost.title class="card-img-top" %}
203
193
  </a>
204
194
  <div class="card-body">
205
195
  <h6 class="card-title mb-1">
@@ -0,0 +1,296 @@
1
+ ---
2
+ layout: default
3
+ ---
4
+ <!--
5
+ ===================================================================
6
+ NOTEBOOK LAYOUT - Jupyter Notebook Display
7
+ ===================================================================
8
+
9
+ File: notebook.html
10
+ Path: _layouts/notebook.html
11
+ Inherits: default.html (which inherits root.html)
12
+ Purpose: Display Jupyter notebooks with code cells, outputs, and metadata
13
+
14
+ Template Logic:
15
+ - Displays notebook content with proper syntax highlighting
16
+ - Shows notebook metadata (kernel, execution count)
17
+ - Provides responsive code cells and output areas
18
+ - Integrates MathJax for mathematical notation
19
+ - Uses Schema.org TechArticle markup for SEO
20
+
21
+ Features:
22
+ - Syntax highlighting via Rouge (Jekyll default)
23
+ - MathJax support for LaTeX equations (already configured in theme)
24
+ - Responsive code blocks and outputs
25
+ - Execution count display
26
+ - Kernel and notebook metadata
27
+ - Bootstrap 5 styling for consistent appearance
28
+
29
+ Dependencies:
30
+ - MathJax 3 (loaded in _includes/core/head.html)
31
+ - Rouge syntax highlighter (Jekyll default)
32
+ - Bootstrap 5 components
33
+ ===================================================================
34
+ -->
35
+
36
+ <article id="main" class="notebook-article h-entry" role="main" itemscope itemtype="https://schema.org/TechArticle">
37
+
38
+ <!-- ================================ -->
39
+ <!-- NOTEBOOK HEADER -->
40
+ <!-- ================================ -->
41
+ <header class="notebook-header mb-4">
42
+ <h1 id="page-title" class="notebook-title p-name" itemprop="headline">
43
+ {{ page.title }}
44
+ </h1>
45
+
46
+ <!-- Notebook Metadata -->
47
+ <div class="notebook-meta text-muted mb-3">
48
+ <!-- Author -->
49
+ {% if page.author %}
50
+ <span class="notebook-author" itemprop="author" itemscope itemtype="https://schema.org/Person">
51
+ <i class="bi bi-person me-1"></i>
52
+ <span itemprop="name">{{ page.author }}</span>
53
+ </span>
54
+ <span class="mx-2">•</span>
55
+ {% endif %}
56
+
57
+ <!-- Publication Date -->
58
+ {% if page.date %}
59
+ <time class="notebook-date dt-published" datetime="{{ page.date | date_to_xmlschema }}" itemprop="datePublished">
60
+ <i class="bi bi-calendar me-1"></i>
61
+ {{ page.date | date: "%B %d, %Y" }}
62
+ </time>
63
+ <span class="mx-2">•</span>
64
+ {% endif %}
65
+
66
+ <!-- Reading Time -->
67
+ {% assign words = content | number_of_words %}
68
+ {% assign minutes = words | divided_by: 200 %}
69
+ {% if minutes < 1 %}{% assign minutes = 1 %}{% endif %}
70
+ <span class="reading-time">
71
+ <i class="bi bi-clock me-1"></i>
72
+ {{ minutes }} min read
73
+ </span>
74
+
75
+ <!-- Last Modified -->
76
+ {% if page.lastmod %}
77
+ <span class="mx-2">•</span>
78
+ <span class="notebook-updated" itemprop="dateModified" content="{{ page.lastmod | date_to_xmlschema }}">
79
+ <i class="bi bi-pencil me-1"></i>
80
+ Updated: {{ page.lastmod | date: "%B %d, %Y" }}
81
+ </span>
82
+ {% endif %}
83
+
84
+ <!-- Kernel Info -->
85
+ {% if page.jupyter_metadata %}
86
+ <span class="mx-2">•</span>
87
+ <span class="notebook-kernel">
88
+ <i class="bi bi-terminal me-1"></i>
89
+ Jupyter Notebook
90
+ </span>
91
+ {% endif %}
92
+ </div>
93
+
94
+ <!-- Tags -->
95
+ {% if page.tags and page.tags.size > 0 %}
96
+ <div class="notebook-tags mb-3">
97
+ {% for tag in page.tags %}
98
+ <a href="{{ site.baseurl }}/tags/{{ tag | slugify }}/" class="badge bg-secondary text-decoration-none me-1">
99
+ {{ tag }}
100
+ </a>
101
+ {% endfor %}
102
+ </div>
103
+ {% endif %}
104
+
105
+ <!-- Categories -->
106
+ {% if page.categories and page.categories.size > 0 %}
107
+ <div class="notebook-categories mb-3">
108
+ <i class="bi bi-folder me-1"></i>
109
+ {% for category in page.categories %}
110
+ <a href="{{ site.baseurl }}/categories/{{ category | slugify }}/" class="text-decoration-none">
111
+ {{ category }}
112
+ </a>
113
+ {% unless forloop.last %}<span class="mx-1">/</span>{% endunless %}
114
+ {% endfor %}
115
+ </div>
116
+ {% endif %}
117
+
118
+ <!-- Description -->
119
+ {% if page.description %}
120
+ <div class="notebook-description lead mb-4" itemprop="description">
121
+ {{ page.description }}
122
+ </div>
123
+ {% endif %}
124
+ </header>
125
+
126
+ <!-- ================================ -->
127
+ <!-- NOTEBOOK CONTENT -->
128
+ <!-- ================================ -->
129
+ <div class="notebook-content e-content" itemprop="articleBody">
130
+ {{ content }}
131
+ </div>
132
+
133
+ <!-- ================================ -->
134
+ <!-- NOTEBOOK FOOTER -->
135
+ <!-- ================================ -->
136
+ <footer class="notebook-footer mt-5 pt-4 border-top">
137
+
138
+ <!-- Share Buttons -->
139
+ {% if page.share != false %}
140
+ <div class="share-buttons mb-4">
141
+ <h5 class="mb-3">Share this notebook</h5>
142
+ <div class="d-flex gap-2">
143
+ <a href="https://twitter.com/intent/tweet?text={{ page.title | uri_escape }}&url={{ page.url | absolute_url | uri_escape }}"
144
+ class="btn btn-outline-primary btn-sm" target="_blank" rel="noopener noreferrer">
145
+ <i class="bi bi-twitter"></i> Twitter
146
+ </a>
147
+ <a href="https://www.linkedin.com/sharing/share-offsite/?url={{ page.url | absolute_url | uri_escape }}"
148
+ class="btn btn-outline-primary btn-sm" target="_blank" rel="noopener noreferrer">
149
+ <i class="bi bi-linkedin"></i> LinkedIn
150
+ </a>
151
+ <a href="mailto:?subject={{ page.title | uri_escape }}&body={{ page.url | absolute_url | uri_escape }}"
152
+ class="btn btn-outline-primary btn-sm">
153
+ <i class="bi bi-envelope"></i> Email
154
+ </a>
155
+ </div>
156
+ </div>
157
+ {% endif %}
158
+
159
+ <!-- Download Original Notebook -->
160
+ <div class="download-notebook mb-4">
161
+ <a href="{{ site.baseurl }}/pages/_notebooks/{{ page.slug }}.ipynb"
162
+ class="btn btn-outline-secondary btn-sm" download>
163
+ <i class="bi bi-download"></i> Download Original Notebook
164
+ </a>
165
+ </div>
166
+
167
+ <!-- Related Notebooks -->
168
+ {% if site.notebooks.size > 1 %}
169
+ <div class="related-notebooks mt-5">
170
+ <h5 class="mb-3">Related Notebooks</h5>
171
+ <div class="row">
172
+ {% assign related_count = 0 %}
173
+ {% for notebook in site.notebooks %}
174
+ {% if notebook.url != page.url and related_count < 3 %}
175
+ {% assign has_common_tag = false %}
176
+ {% for tag in page.tags %}
177
+ {% if notebook.tags contains tag %}
178
+ {% assign has_common_tag = true %}
179
+ {% endif %}
180
+ {% endfor %}
181
+
182
+ {% if has_common_tag %}
183
+ {% assign related_count = related_count | plus: 1 %}
184
+ <div class="col-md-4 mb-3">
185
+ <div class="card h-100">
186
+ <div class="card-body">
187
+ <h6 class="card-title">
188
+ <a href="{{ notebook.url | relative_url }}" class="text-decoration-none">
189
+ {{ notebook.title }}
190
+ </a>
191
+ </h6>
192
+ {% if notebook.description %}
193
+ <p class="card-text small text-muted">
194
+ {{ notebook.description | truncate: 100 }}
195
+ </p>
196
+ {% endif %}
197
+ </div>
198
+ </div>
199
+ </div>
200
+ {% endif %}
201
+ {% endif %}
202
+ {% endfor %}
203
+ </div>
204
+ </div>
205
+ {% endif %}
206
+ </footer>
207
+
208
+ <!-- ================================ -->
209
+ <!-- COMMENTS SECTION -->
210
+ <!-- ================================ -->
211
+ {% if page.comments != false and site.giscus.enabled %}
212
+ <div class="notebook-comments mt-5 pt-4 border-top">
213
+ <h5 class="mb-4">Comments</h5>
214
+ {% include content/giscus.html %}
215
+ </div>
216
+ {% endif %}
217
+
218
+ </article>
219
+
220
+ <!-- ================================ -->
221
+ <!-- NAVIGATION -->
222
+ <!-- ================================ -->
223
+ <!-- Previous/Next Notebook Navigation -->
224
+ {% assign notebooks = site.notebooks | sort: 'date' | reverse %}
225
+ {% assign current_index = nil %}
226
+ {% for notebook in notebooks %}
227
+ {% if notebook.url == page.url %}
228
+ {% assign current_index = forloop.index0 %}
229
+ {% break %}
230
+ {% endif %}
231
+ {% endfor %}
232
+
233
+ {% if current_index %}
234
+ {% assign last_index = notebooks.size | minus: 1 %}
235
+ <nav class="notebook-navigation mt-5" aria-label="Notebook navigation">
236
+ <ul class="pagination justify-content-between">
237
+ <li class="page-item {% if current_index == last_index %}disabled{% endif %}">
238
+ {% if current_index < last_index %}
239
+ {% assign next_index = current_index | plus: 1 %}
240
+ {% assign prev_notebook = notebooks[next_index] %}
241
+ <a class="page-link" href="{{ prev_notebook.url | relative_url }}" rel="prev">
242
+ <i class="bi bi-arrow-left me-2"></i>{{ prev_notebook.title | truncate: 50 }}
243
+ </a>
244
+ {% else %}
245
+ <span class="page-link disabled">
246
+ <i class="bi bi-arrow-left me-2"></i>No previous notebook
247
+ </span>
248
+ {% endif %}
249
+ </li>
250
+
251
+ <li class="page-item {% if current_index == 0 %}disabled{% endif %}">
252
+ {% if current_index > 0 %}
253
+ {% assign prev_index = current_index | minus: 1 %}
254
+ {% assign next_notebook = notebooks[prev_index] %}
255
+ <a class="page-link" href="{{ next_notebook.url | relative_url }}" rel="next">
256
+ {{ next_notebook.title | truncate: 50 }}<i class="bi bi-arrow-right ms-2"></i>
257
+ </a>
258
+ {% else %}
259
+ <span class="page-link disabled">
260
+ No next notebook<i class="bi bi-arrow-right ms-2"></i>
261
+ </span>
262
+ {% endif %}
263
+ </li>
264
+ </ul>
265
+ </nav>
266
+ {% endif %}
267
+
268
+ <!-- Schema.org metadata -->
269
+ <script type="application/ld+json">
270
+ {
271
+ "@context": "https://schema.org",
272
+ "@type": "TechArticle",
273
+ "headline": {{ page.title | jsonify }},
274
+ "description": {{ page.description | default: page.excerpt | jsonify }},
275
+ "author": {
276
+ "@type": "Person",
277
+ "name": {{ page.author | default: site.author.name | jsonify }}
278
+ },
279
+ "datePublished": {{ page.date | date_to_xmlschema | jsonify }},
280
+ {% if page.lastmod %}
281
+ "dateModified": {{ page.lastmod | date_to_xmlschema | jsonify }},
282
+ {% endif %}
283
+ "publisher": {
284
+ "@type": "Organization",
285
+ "name": {{ site.title | jsonify }},
286
+ "logo": {
287
+ "@type": "ImageObject",
288
+ "url": {{ site.logo | absolute_url | jsonify }}
289
+ }
290
+ },
291
+ "mainEntityOfPage": {
292
+ "@type": "WebPage",
293
+ "@id": {{ page.url | absolute_url | jsonify }}
294
+ }
295
+ }
296
+ </script>
@@ -1365,7 +1365,7 @@
1365
1365
  position: sticky;
1366
1366
  top: 5rem;
1367
1367
  right: 0;
1368
- // z-index: 2;
1368
+ z-index: 2;
1369
1369
  height: calc(100vh - 7rem);
1370
1370
  overflow-y: auto
1371
1371
  }
data/_sass/custom.scss CHANGED
@@ -1,3 +1,10 @@
1
+ // ==============================================================================
2
+ // CUSTOM STYLES - Zer0-Mistakes Theme Customizations
3
+ // ==============================================================================
4
+
5
+ // Import notebook-specific styles
6
+ @import "notebooks";
7
+
1
8
  html, body {
2
9
  max-width: 100%;
3
10
  // overflow-x: hidden;
@@ -37,7 +44,7 @@ html, body {
37
44
 
38
45
  @media (min-width: 992px) {
39
46
  .toc {
40
- position:-webkit-sticky;
47
+ position: -webkit-sticky;
41
48
  position: sticky;
42
49
  top: 5rem;
43
50
  right: 5rem;
@@ -100,30 +107,60 @@ html, body {
100
107
  }
101
108
 
102
109
 
103
- @media (min-width: 992px) {
104
- .sidebar {
105
- position:-webkit-sticky;
106
- position: sticky;
107
- top: 5rem;
108
- display: block !important;
109
- height: calc(100vh - 6rem);
110
- padding-left: .25rem;
111
- margin-left: -.25rem;
112
- overflow-y: auto
110
+ // Sidebar classes consolidated in _sass/core/_docs.scss for consistency
111
+
112
+ // ==============================================================================
113
+ // SIDEBAR & TOC ENHANCEMENTS
114
+ // ==============================================================================
115
+
116
+ // Mobile TOC FAB transitions and positioning
117
+ .bd-toc-toggle {
118
+ transition: all 0.3s ease;
119
+
120
+ &:hover {
121
+ transform: scale(1.05);
122
+ }
123
+
124
+ &:active {
125
+ transform: scale(0.95);
113
126
  }
114
127
  }
115
128
 
116
- @media (max-width: 991.98px) {
117
- .sidebar .offcanvas-lg {
118
- border-right-color:var(--bs-border-color);
119
- box-shadow: 0 1rem 3rem rgba(var(--bs-body-color-rgb), 0.175)
129
+ // Mobile FAB positioning (TOC button above back-to-top)
130
+ .bd-toc-fab {
131
+ // On mobile, ensure proper spacing above back-to-top button
132
+ @media (max-width: 991.98px) {
133
+ bottom: 90px !important; // 20px (back-to-top) + 56px (button height) + 14px (spacing)
120
134
  }
121
135
  }
122
136
 
123
- .bd-sidebar {
124
- grid-area: sidebar
137
+ // Active TOC link highlighting
138
+ .bd-toc nav a.active {
139
+ font-weight: 600;
140
+ background-color: rgba(var(--bs-primary-rgb), 0.1);
141
+ border-left-color: var(--bs-primary) !important;
142
+ }
143
+
144
+ // Smooth scroll behavior
145
+ html {
146
+ scroll-behavior: smooth;
147
+ }
148
+
149
+ // Category active state
150
+ .btn-toggle-nav a.active {
151
+ font-weight: 600;
152
+ background-color: rgba(var(--bs-primary-rgb), 0.1);
153
+ color: var(--bs-primary);
154
+ }
155
+
156
+ // Improve sidebar link hover states
157
+ .bd-sidebar .list-group-item:hover,
158
+ .bd-sidebar .list-group-item-action:hover {
159
+ background-color: rgba(var(--bs-primary-rgb), 0.05);
160
+ transition: background-color 0.2s ease;
125
161
  }
126
162
 
163
+ // ==============================================================================
127
164
  // https://designkojo.com/add-ellipse-truncated-text-css-single-line-and-multi-line-options
128
165
 
129
166
 
@@ -134,7 +171,7 @@ html, body {
134
171
  position: fixed; /* Fixed/sticky position */
135
172
  bottom: 20px; /* Place the button at the bottom of the page */
136
173
  right: 20px; /* Place the button 30px from the right */
137
- z-index: 99; /* Make sure it does not overlap */
174
+ z-index: 1020; /* Below TOC button (1030) but above other content */
138
175
  border: none; /* Remove borders */
139
176
  outline: none; /* Remove outline */
140
177
  background-color: $primary; /* Set a background color */