jekyll-theme-zer0 0.10.0 → 0.10.3
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 +107 -0
- data/_includes/components/mermaid.html +98 -9
- data/_includes/content/intro.html +13 -1
- data/_includes/core/header.html +1 -1
- data/_layouts/category.html +16 -6
- data/_layouts/collection.html +8 -3
- data/_layouts/journals.html +8 -3
- data/_sass/custom.scss +20 -12
- data/assets/images/previews/10-ai-tools-that-will-transform-your-productivity-.png +0 -0
- data/assets/images/previews/business.png +0 -0
- data/assets/images/previews/css-grid-mastery-build-any-layout-you-can-imagine.png +0 -0
- data/assets/images/previews/development.png +0 -0
- data/assets/images/previews/github-setup-deployment.png +0 -0
- data/assets/images/previews/jekyll-setup.png +0 -0
- data/assets/images/previews/machine-setup.png +0 -0
- data/assets/images/previews/published-documentation-library.png +0 -0
- data/assets/images/previews/quantum-computing-explained-from-qubits-to-quantum.png +0 -0
- data/assets/images/previews/science.png +0 -0
- data/assets/images/previews/technology.png +0 -0
- data/assets/images/previews/the-complete-guide-to-startup-funding-in-2025.png +0 -0
- data/assets/images/previews/the-remote-work-revolution-how-global-teams-are-re.png +0 -0
- data/assets/images/previews/tutorial.png +0 -0
- data/assets/images/previews/world-news.png +0 -0
- data/assets/images/previews/zer0-mistakes-news-network-building-dynamic-news-s.png +0 -0
- data/assets/images/previews/zer0-mistakes-quick-start-guide.png +0 -0
- data/assets/js/auto-hide-nav.js +79 -16
- data/scripts/lib/preview_generator.py +37 -22
- data/scripts/test-mermaid.sh +51 -11
- metadata +18 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d85d69f52f828fb686300bac5c2312c0c8bfbd1eed9059fab3c071073efb003b
|
|
4
|
+
data.tar.gz: dd68d098ec262a62b7ab3c50163830467fdaa36fe3cbba9c00941e6893f334bd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c352ba15e82dfdeb1945caddbc35fff0dc7c8d26431d1d73f5ba66fb51055fa0ba046bdcde3f4c4e48d5ddcafc8bcdca50ce43b39a656e85ba95af656a274b21
|
|
7
|
+
data.tar.gz: a52ea996e45089efcb33286a86555e6f340d93273e45552455e2b5331564fe0ce3cbc781246372d1fac567f5a974cb4cf6b5613caa9a798eec7d1a69587459a4
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,112 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.10.3] - 2025-11-29
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **New: AI-Generated Preview Images** - 17 new preview images for posts and collections
|
|
8
|
+
- Business, Development, Science, Technology, Tutorial, World category index pages
|
|
9
|
+
- Individual post previews: startup funding, quantum computing, AI tools, CSS grid, remote work
|
|
10
|
+
- Quickstart guide previews: GitHub setup, Jekyll setup, machine setup
|
|
11
|
+
- Documentation and blog index previews
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- **Improved: Preview Image Path Handling** (`_layouts/journals.html`, `_layouts/category.html`, `_layouts/collection.html`)
|
|
16
|
+
- Layouts now support both absolute paths (`/assets/...`) and relative paths
|
|
17
|
+
- Conditional logic detects path type and constructs URL correctly
|
|
18
|
+
- Eliminates double-slash issues in image URLs
|
|
19
|
+
|
|
20
|
+
- **Improved: Intro Section Preview Image Logic** (`_includes/content/intro.html`)
|
|
21
|
+
- Smart path detection for preview images (absolute vs relative)
|
|
22
|
+
- Handles URLs with `://` schemes, paths starting with `/`, and relative filenames
|
|
23
|
+
- Cleaner Liquid template logic with proper variable assignment
|
|
24
|
+
|
|
25
|
+
- **Improved: Docker Development Setup** (`docker-compose.yml`, `docker/Dockerfile`)
|
|
26
|
+
- Command now runs `bundle install` before Jekyll serve (fixes volume mount overwrites)
|
|
27
|
+
- Dockerfile copies gemspec and lib/ for proper dependency resolution
|
|
28
|
+
- More reliable container startup with dependency installation
|
|
29
|
+
|
|
30
|
+
- **Improved: Preview Image Generator** (`scripts/lib/preview_generator.py`)
|
|
31
|
+
- Switched from OpenAI SDK to direct HTTP API calls
|
|
32
|
+
- Eliminates SDK dependency - only requires `requests` package
|
|
33
|
+
- Better error handling with HTTP status code parsing
|
|
34
|
+
- Added request timeouts (120s for generation, 60s for download)
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
|
|
38
|
+
- **Fixed: Asset Paths in Config** (`_config.yml`)
|
|
39
|
+
- Corrected `teaser` and `info_banner` paths to use `/assets/images/` prefix
|
|
40
|
+
- Images now load correctly across all pages
|
|
41
|
+
|
|
42
|
+
- **Fixed: Preview Image Double-Slash URLs**
|
|
43
|
+
- Removed extra `/` between `public_folder` and `site.teaser` in fallback images
|
|
44
|
+
- All layouts now generate clean, valid image URLs
|
|
45
|
+
|
|
46
|
+
## [0.10.2] - 2025-11-28
|
|
47
|
+
|
|
48
|
+
### Added
|
|
49
|
+
|
|
50
|
+
- **Enhanced: Navbar Auto-Hide on Scroll** (`assets/js/auto-hide-nav.js`)
|
|
51
|
+
- Navbar hides when scrolling down past 100px threshold
|
|
52
|
+
- Navbar reappears immediately when scrolling up
|
|
53
|
+
- Automatic body padding to prevent content jump under fixed navbar
|
|
54
|
+
- Performance-optimized with `requestAnimationFrame` throttling
|
|
55
|
+
- Respects `prefers-reduced-motion` accessibility setting
|
|
56
|
+
|
|
57
|
+
### Changed
|
|
58
|
+
|
|
59
|
+
- **Improved: Header Positioning** (`_includes/core/header.html`)
|
|
60
|
+
- Changed from `z-1` to Bootstrap's `fixed-top` class
|
|
61
|
+
- Provides proper z-index (1030) and fixed positioning
|
|
62
|
+
|
|
63
|
+
- **Refactored: Navbar CSS** (`_sass/custom.scss`)
|
|
64
|
+
- Replaced broken `.hide-navbar` and `.fixed-navbar` classes
|
|
65
|
+
- New `.navbar-hidden` class with `translateY(-100%)` transform
|
|
66
|
+
- Added `!important` to override Bootstrap's `fixed-top` positioning
|
|
67
|
+
- Added explicit background color for opaque navbar
|
|
68
|
+
- Added `prefers-reduced-motion` media query for accessibility
|
|
69
|
+
|
|
70
|
+
### Fixed
|
|
71
|
+
|
|
72
|
+
- **Fixed: Navbar Blocking Content on Scroll Up**
|
|
73
|
+
- Content no longer obscured when scrolling back to top
|
|
74
|
+
- Body padding dynamically calculated based on navbar height
|
|
75
|
+
|
|
76
|
+
## [0.10.1] - 2025-11-28
|
|
77
|
+
|
|
78
|
+
### Added
|
|
79
|
+
|
|
80
|
+
- **Enhanced: Mermaid v2.1 - GitHub Pages Compatible** (`_includes/components/mermaid.html`)
|
|
81
|
+
- Client-side conversion of native markdown ` ```mermaid ` code blocks to rendered diagrams
|
|
82
|
+
- Full GitHub Pages compatibility without custom plugins (all processing client-side)
|
|
83
|
+
- CSS to hide code blocks during conversion (prevents flash of unstyled content)
|
|
84
|
+
- Print styles and improved responsive design
|
|
85
|
+
- Documented dual syntax support (native markdown and HTML div)
|
|
86
|
+
|
|
87
|
+
### Changed
|
|
88
|
+
|
|
89
|
+
- **Improved: Mermaid Configuration** (`_config.yml`)
|
|
90
|
+
- Added clear comments explaining GitHub Pages compatibility
|
|
91
|
+
- Documented that `jekyll-mermaid` plugin is optional
|
|
92
|
+
- Updated usage instructions for both syntax options
|
|
93
|
+
|
|
94
|
+
- **Improved: Mermaid Documentation**
|
|
95
|
+
- `docs/jekyll/mermaid.md`: Added native markdown syntax as recommended option
|
|
96
|
+
- `docs/jekyll/mermaid-native-markdown.md`: Fixed documentation about front matter requirements
|
|
97
|
+
- Added GitHub Pages compatibility badges to documentation
|
|
98
|
+
|
|
99
|
+
### Fixed
|
|
100
|
+
|
|
101
|
+
- **Fixed: Native Markdown Mermaid Syntax Not Rendering**
|
|
102
|
+
- ` ```mermaid ` code blocks now properly convert to diagrams via JavaScript
|
|
103
|
+
- Works with GitHub Pages remote_theme deployment
|
|
104
|
+
|
|
105
|
+
- **Fixed: Mermaid Test Script** (`scripts/test-mermaid.sh`)
|
|
106
|
+
- Corrected file path references from `pages/_docs/jekyll/` to `docs/jekyll/`
|
|
107
|
+
- Fixed SIGPIPE issues with `curl | grep` pipelines causing false test failures
|
|
108
|
+
- All 21 tests now pass successfully
|
|
109
|
+
|
|
3
110
|
## [0.10.0] - 2025-11-28
|
|
4
111
|
|
|
5
112
|
### Added
|
|
@@ -1,21 +1,39 @@
|
|
|
1
1
|
<!--
|
|
2
2
|
===================================================================
|
|
3
|
-
MERMAID DIAGRAM INTEGRATION
|
|
3
|
+
MERMAID DIAGRAM INTEGRATION (v2.1 - GitHub Pages Compatible)
|
|
4
4
|
===================================================================
|
|
5
5
|
|
|
6
6
|
File: mermaid.html
|
|
7
7
|
Path: _includes/components/mermaid.html
|
|
8
8
|
Purpose: Load and initialize Mermaid.js for diagram rendering
|
|
9
9
|
|
|
10
|
-
Usage:
|
|
10
|
+
Usage (Two syntaxes supported):
|
|
11
|
+
|
|
12
|
+
1. Native Markdown Code Blocks (Recommended):
|
|
13
|
+
```mermaid
|
|
14
|
+
graph TD
|
|
15
|
+
A[Start] -> B[End]
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
2. HTML Div Syntax:
|
|
19
|
+
<div class="mermaid">
|
|
20
|
+
graph TD
|
|
21
|
+
A[Start] -- > B[End]
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
Requirements:
|
|
11
25
|
- Set 'mermaid: true' in page front matter
|
|
12
|
-
- Use <div class="mermaid">...</div> syntax in content
|
|
13
26
|
- Supports all Mermaid diagram types (flowcharts, sequence, gantt, etc.)
|
|
14
27
|
|
|
15
28
|
Configuration:
|
|
16
|
-
-
|
|
29
|
+
- Mermaid v10 via CDN (latest stable)
|
|
17
30
|
- Forest theme for dark mode compatibility
|
|
18
|
-
-
|
|
31
|
+
- Client-side code block conversion for GitHub Pages compatibility
|
|
32
|
+
|
|
33
|
+
GitHub Pages Compatibility:
|
|
34
|
+
- No custom plugins required (jekyll-mermaid is optional)
|
|
35
|
+
- All processing done client-side via JavaScript
|
|
36
|
+
- Works with remote_theme on GitHub Pages
|
|
19
37
|
|
|
20
38
|
Documentation:
|
|
21
39
|
- https://mermaid.js.org/
|
|
@@ -29,9 +47,51 @@
|
|
|
29
47
|
<!-- Initialize Mermaid with custom configuration -->
|
|
30
48
|
<script>
|
|
31
49
|
document.addEventListener('DOMContentLoaded', function() {
|
|
50
|
+
// ============================================================
|
|
51
|
+
// Step 1: Convert native markdown code blocks to mermaid divs
|
|
52
|
+
// This enables ```mermaid syntax to work with GitHub Pages
|
|
53
|
+
// ============================================================
|
|
54
|
+
|
|
55
|
+
// Find all code blocks with language-mermaid class (from ```mermaid)
|
|
56
|
+
var codeBlocks = document.querySelectorAll('pre > code.language-mermaid, code.language-mermaid');
|
|
57
|
+
|
|
58
|
+
codeBlocks.forEach(function(codeBlock) {
|
|
59
|
+
// Get the mermaid content (decode HTML entities)
|
|
60
|
+
var content = codeBlock.textContent || codeBlock.innerText;
|
|
61
|
+
|
|
62
|
+
// Create a new mermaid div
|
|
63
|
+
var mermaidDiv = document.createElement('div');
|
|
64
|
+
mermaidDiv.className = 'mermaid';
|
|
65
|
+
mermaidDiv.textContent = content;
|
|
66
|
+
|
|
67
|
+
// Replace the pre/code block with the mermaid div
|
|
68
|
+
var preElement = codeBlock.closest('pre');
|
|
69
|
+
if (preElement && preElement.parentNode) {
|
|
70
|
+
preElement.parentNode.replaceChild(mermaidDiv, preElement);
|
|
71
|
+
} else if (codeBlock.parentNode) {
|
|
72
|
+
codeBlock.parentNode.replaceChild(mermaidDiv, codeBlock);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Also handle pre elements that might have data-language="mermaid"
|
|
77
|
+
var preBlocks = document.querySelectorAll('pre[data-language="mermaid"]');
|
|
78
|
+
preBlocks.forEach(function(preBlock) {
|
|
79
|
+
var content = preBlock.textContent || preBlock.innerText;
|
|
80
|
+
var mermaidDiv = document.createElement('div');
|
|
81
|
+
mermaidDiv.className = 'mermaid';
|
|
82
|
+
mermaidDiv.textContent = content;
|
|
83
|
+
if (preBlock.parentNode) {
|
|
84
|
+
preBlock.parentNode.replaceChild(mermaidDiv, preBlock);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// ============================================================
|
|
89
|
+
// Step 2: Initialize Mermaid with custom configuration
|
|
90
|
+
// ============================================================
|
|
91
|
+
|
|
32
92
|
mermaid.initialize({
|
|
33
|
-
startOnLoad:
|
|
34
|
-
theme: 'forest',
|
|
93
|
+
startOnLoad: false, // We'll manually run after conversion
|
|
94
|
+
theme: 'forest', // Options: default, forest, dark, neutral, base
|
|
35
95
|
themeVariables: {
|
|
36
96
|
primaryColor: '#007bff',
|
|
37
97
|
primaryTextColor: '#fff',
|
|
@@ -69,9 +129,20 @@
|
|
|
69
129
|
fontSize: 11,
|
|
70
130
|
numberSectionStyles: 4,
|
|
71
131
|
axisFormat: '%Y-%m-%d'
|
|
72
|
-
}
|
|
132
|
+
},
|
|
133
|
+
securityLevel: 'loose' // Required for some advanced features
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// ============================================================
|
|
137
|
+
// Step 3: Render all mermaid diagrams
|
|
138
|
+
// ============================================================
|
|
139
|
+
|
|
140
|
+
// Run mermaid to render all .mermaid divs
|
|
141
|
+
mermaid.run().then(function() {
|
|
142
|
+
console.log('Mermaid.js: All diagrams rendered successfully');
|
|
143
|
+
}).catch(function(error) {
|
|
144
|
+
console.warn('Mermaid.js: Some diagrams failed to render', error);
|
|
73
145
|
});
|
|
74
|
-
console.log('Mermaid.js initialized successfully');
|
|
75
146
|
});
|
|
76
147
|
</script>
|
|
77
148
|
|
|
@@ -80,10 +151,12 @@
|
|
|
80
151
|
|
|
81
152
|
<!-- Custom CSS for Mermaid diagrams -->
|
|
82
153
|
<style>
|
|
154
|
+
/* Mermaid container styling */
|
|
83
155
|
.mermaid {
|
|
84
156
|
text-align: center;
|
|
85
157
|
margin: 2rem auto;
|
|
86
158
|
background-color: transparent;
|
|
159
|
+
overflow-x: auto;
|
|
87
160
|
}
|
|
88
161
|
|
|
89
162
|
/* Ensure diagrams are responsive */
|
|
@@ -92,10 +165,26 @@
|
|
|
92
165
|
height: auto;
|
|
93
166
|
}
|
|
94
167
|
|
|
168
|
+
/* Hide code blocks before conversion (prevent flash of unstyled content) */
|
|
169
|
+
pre > code.language-mermaid,
|
|
170
|
+
code.language-mermaid {
|
|
171
|
+
display: block;
|
|
172
|
+
opacity: 0;
|
|
173
|
+
transition: opacity 0.2s;
|
|
174
|
+
}
|
|
175
|
+
|
|
95
176
|
/* Dark mode compatibility */
|
|
96
177
|
@media (prefers-color-scheme: dark) {
|
|
97
178
|
.mermaid {
|
|
98
179
|
filter: brightness(0.9);
|
|
99
180
|
}
|
|
100
181
|
}
|
|
182
|
+
|
|
183
|
+
/* Print styles */
|
|
184
|
+
@media print {
|
|
185
|
+
.mermaid svg {
|
|
186
|
+
max-width: 100% !important;
|
|
187
|
+
page-break-inside: avoid;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
101
190
|
</style>
|
|
@@ -15,8 +15,20 @@
|
|
|
15
15
|
|
|
16
16
|
<!-- Intro Section -->
|
|
17
17
|
|
|
18
|
+
{% comment %}
|
|
19
|
+
Determine the preview image path. If page.preview starts with '/' or 'http',
|
|
20
|
+
use it directly. Otherwise, prepend the public folder path.
|
|
21
|
+
{% endcomment %}
|
|
22
|
+
{% assign preview_image = page.preview | default: site.info_banner %}
|
|
23
|
+
{% assign preview_first_char = preview_image | slice: 0 %}
|
|
24
|
+
{% if preview_image contains '://' or preview_first_char == '/' %}
|
|
25
|
+
{% assign preview_path = preview_image %}
|
|
26
|
+
{% else %}
|
|
27
|
+
{% assign preview_path = '/' | append: site.public_folder | append: '/' | append: preview_image %}
|
|
28
|
+
{% endif %}
|
|
29
|
+
|
|
18
30
|
<div class="bd-intro pt-5 ps-lg-2 position-relative" style="
|
|
19
|
-
background: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url('{{site.baseurl
|
|
31
|
+
background: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url('{{ site.baseurl }}{{ preview_path }}') no-repeat center center / cover;
|
|
20
32
|
color: #fff;">
|
|
21
33
|
|
|
22
34
|
<br>
|
data/_includes/core/header.html
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
===================================================================
|
|
29
29
|
-->
|
|
30
30
|
|
|
31
|
-
<header id="navbar" class="container-fluid text-center
|
|
31
|
+
<header id="navbar" class="container-fluid text-center fixed-top" role="navigation">
|
|
32
32
|
|
|
33
33
|
<!-- ================================ -->
|
|
34
34
|
<!-- TOP NAVIGATION BAR -->
|
data/_layouts/category.html
CHANGED
|
@@ -112,10 +112,15 @@ layout: default
|
|
|
112
112
|
{% endif %}
|
|
113
113
|
<a href="{{ fpost.url | relative_url }}" class="text-decoration-none">
|
|
114
114
|
{% if fpost.preview %}
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
{% if fpost.preview contains '/assets' %}
|
|
116
|
+
<img src="{{ site.baseurl }}{{ fpost.preview }}"
|
|
117
|
+
class="card-img-top" alt="{{ fpost.title }}" loading="lazy">
|
|
118
|
+
{% else %}
|
|
119
|
+
<img src="{{ site.baseurl }}/{{ site.public_folder }}/{{ fpost.preview }}"
|
|
120
|
+
class="card-img-top" alt="{{ fpost.title }}" loading="lazy">
|
|
121
|
+
{% endif %}
|
|
117
122
|
{% else %}
|
|
118
|
-
<img src="{{ site.baseurl }}/{{ site.public_folder }}
|
|
123
|
+
<img src="{{ site.baseurl }}/{{ site.public_folder }}{{ site.teaser }}"
|
|
119
124
|
class="card-img-top" alt="Preview" loading="lazy">
|
|
120
125
|
{% endif %}
|
|
121
126
|
</a>
|
|
@@ -167,10 +172,15 @@ layout: default
|
|
|
167
172
|
{% endif %}
|
|
168
173
|
<a href="{{ cpost.url | relative_url }}" class="text-decoration-none">
|
|
169
174
|
{% if cpost.preview %}
|
|
170
|
-
|
|
171
|
-
|
|
175
|
+
{% if cpost.preview contains '/assets' %}
|
|
176
|
+
<img src="{{ site.baseurl }}{{ cpost.preview }}"
|
|
177
|
+
class="card-img-top" alt="{{ cpost.title }}" loading="lazy">
|
|
178
|
+
{% else %}
|
|
179
|
+
<img src="{{ site.baseurl }}/{{ site.public_folder }}/{{ cpost.preview }}"
|
|
180
|
+
class="card-img-top" alt="{{ cpost.title }}" loading="lazy">
|
|
181
|
+
{% endif %}
|
|
172
182
|
{% else %}
|
|
173
|
-
<img src="{{ site.baseurl }}/{{ site.public_folder }}
|
|
183
|
+
<img src="{{ site.baseurl }}/{{ site.public_folder }}{{ site.teaser }}"
|
|
174
184
|
class="card-img-top" alt="Preview" loading="lazy">
|
|
175
185
|
{% endif %}
|
|
176
186
|
</a>
|
data/_layouts/collection.html
CHANGED
|
@@ -84,10 +84,15 @@ layout: default
|
|
|
84
84
|
<!-- ====================== -->
|
|
85
85
|
<!-- Display preview image with fallback to site teaser -->
|
|
86
86
|
{% if post.preview %}
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
{% if post.preview contains '/assets' %}
|
|
88
|
+
<img src="{{ site.baseurl }}{{ post.preview }}"
|
|
89
|
+
class="card-img-top" alt="Preview image for {{ post.title }}">
|
|
90
|
+
{% else %}
|
|
91
|
+
<img src="{{ site.baseurl }}/{{ site.public_folder }}/{{ post.preview }}"
|
|
92
|
+
class="card-img-top" alt="Preview image for {{ post.title }}">
|
|
93
|
+
{% endif %}
|
|
89
94
|
{% else %}
|
|
90
|
-
<img src="{{site.baseurl}}/{{ site.public_folder }}
|
|
95
|
+
<img src="{{ site.baseurl }}/{{ site.public_folder }}{{ site.teaser }}"
|
|
91
96
|
class="card-img-top" alt="Default preview image">
|
|
92
97
|
{% endif %}
|
|
93
98
|
|
data/_layouts/journals.html
CHANGED
|
@@ -189,10 +189,15 @@ layout: default
|
|
|
189
189
|
<div class="card h-100 border-0 shadow-sm">
|
|
190
190
|
<a href="{{ rpost.url | relative_url }}" class="text-decoration-none">
|
|
191
191
|
{% if rpost.preview %}
|
|
192
|
-
|
|
193
|
-
|
|
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 %}
|
|
194
199
|
{% else %}
|
|
195
|
-
<img src="{{ site.baseurl }}/{{ site.public_folder }}
|
|
200
|
+
<img src="{{ site.baseurl }}/{{ site.public_folder }}{{ site.teaser }}"
|
|
196
201
|
class="card-img-top" alt="Preview" loading="lazy">
|
|
197
202
|
{% endif %}
|
|
198
203
|
</a>
|
data/_sass/custom.scss
CHANGED
|
@@ -177,23 +177,31 @@ img {
|
|
|
177
177
|
height: auto;
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
+
// ============================================
|
|
181
|
+
// NAVBAR - Fixed positioning with auto-hide
|
|
182
|
+
// ============================================
|
|
183
|
+
// Uses Bootstrap's fixed-top class for positioning (z-index: 1030)
|
|
184
|
+
// JavaScript adds/removes .navbar-hidden class on scroll
|
|
185
|
+
|
|
180
186
|
#navbar {
|
|
181
|
-
//
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
187
|
+
// Transition for smooth hide/show animation
|
|
188
|
+
transition: transform 0.3s ease-in-out !important;
|
|
189
|
+
|
|
190
|
+
// Ensure navbar background is opaque
|
|
191
|
+
background-color: var(--bs-body-bg);
|
|
185
192
|
}
|
|
186
193
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
transition: transform 0.3s;
|
|
194
|
+
// Hidden state - slides up out of view
|
|
195
|
+
// Using higher specificity to override Bootstrap's fixed-top
|
|
196
|
+
#navbar.navbar-hidden {
|
|
197
|
+
transform: translateY(-100%) !important;
|
|
192
198
|
}
|
|
193
199
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
200
|
+
// Respect user's motion preferences
|
|
201
|
+
@media (prefers-reduced-motion: reduce) {
|
|
202
|
+
#navbar {
|
|
203
|
+
transition: none !important;
|
|
204
|
+
}
|
|
197
205
|
}
|
|
198
206
|
|
|
199
207
|
$enable-cssgrid: true;
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/assets/js/auto-hide-nav.js
CHANGED
|
@@ -1,18 +1,81 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Auto-hide navbar on scroll
|
|
3
|
+
*
|
|
4
|
+
* Behavior:
|
|
5
|
+
* - Navbar is fixed at top and visible by default
|
|
6
|
+
* - Hides when scrolling DOWN past a threshold (100px)
|
|
7
|
+
* - Reappears when scrolling UP
|
|
8
|
+
* - Respects prefers-reduced-motion accessibility setting
|
|
9
|
+
* - Adds body padding to prevent content jump
|
|
10
|
+
*/
|
|
11
|
+
(function() {
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
// Configuration
|
|
15
|
+
const SCROLL_THRESHOLD = 100; // Pixels before hide/show triggers
|
|
16
|
+
const SCROLL_DELTA = 5; // Minimum scroll distance to trigger change
|
|
17
|
+
|
|
18
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
19
|
+
const navbar = document.getElementById('navbar');
|
|
20
|
+
if (!navbar) return;
|
|
21
|
+
|
|
22
|
+
let lastScrollTop = 0;
|
|
23
|
+
let ticking = false;
|
|
24
|
+
|
|
25
|
+
// Check for reduced motion preference
|
|
26
|
+
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
27
|
+
|
|
28
|
+
// Calculate and set body padding to prevent content jump
|
|
29
|
+
function updateBodyPadding() {
|
|
30
|
+
const navbarHeight = navbar.offsetHeight;
|
|
31
|
+
document.body.style.paddingTop = navbarHeight + 'px';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Initial padding setup
|
|
35
|
+
updateBodyPadding();
|
|
36
|
+
|
|
37
|
+
// Update padding on window resize
|
|
38
|
+
window.addEventListener('resize', updateBodyPadding, { passive: true });
|
|
39
|
+
|
|
40
|
+
// Scroll handler
|
|
41
|
+
function handleScroll() {
|
|
42
|
+
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
43
|
+
const scrollDelta = scrollTop - lastScrollTop;
|
|
44
|
+
|
|
45
|
+
// Only trigger if scroll delta exceeds minimum threshold
|
|
46
|
+
if (Math.abs(scrollDelta) < SCROLL_DELTA) {
|
|
47
|
+
ticking = false;
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (scrollDelta > 0 && scrollTop > SCROLL_THRESHOLD) {
|
|
52
|
+
// Scrolling DOWN past threshold - hide navbar
|
|
53
|
+
navbar.classList.add('navbar-hidden');
|
|
54
|
+
} else if (scrollDelta < 0) {
|
|
55
|
+
// Scrolling UP - show navbar
|
|
56
|
+
navbar.classList.remove('navbar-hidden');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Always show navbar when at top of page
|
|
60
|
+
if (scrollTop <= 0) {
|
|
61
|
+
navbar.classList.remove('navbar-hidden');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
lastScrollTop = Math.max(0, scrollTop);
|
|
65
|
+
ticking = false;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Optimized scroll listener using requestAnimationFrame
|
|
69
|
+
window.addEventListener('scroll', function() {
|
|
70
|
+
if (!ticking) {
|
|
71
|
+
window.requestAnimationFrame(handleScroll);
|
|
72
|
+
ticking = true;
|
|
73
|
+
}
|
|
74
|
+
}, { passive: true });
|
|
75
|
+
|
|
76
|
+
// Disable animations if user prefers reduced motion
|
|
77
|
+
if (prefersReducedMotion) {
|
|
78
|
+
navbar.style.transition = 'none';
|
|
15
79
|
}
|
|
16
|
-
lastScrollTop = scrollTop;
|
|
17
80
|
});
|
|
18
|
-
}
|
|
81
|
+
})();
|
|
@@ -234,13 +234,13 @@ class PreviewGenerator:
|
|
|
234
234
|
return safe_name[:50] # Limit length
|
|
235
235
|
|
|
236
236
|
def generate_image_openai(self, prompt: str, output_path: Path) -> GenerationResult:
|
|
237
|
-
"""Generate image using OpenAI DALL-E."""
|
|
238
|
-
if not
|
|
237
|
+
"""Generate image using OpenAI DALL-E via HTTP API (no SDK required)."""
|
|
238
|
+
if not HAS_REQUESTS:
|
|
239
239
|
return GenerationResult(
|
|
240
240
|
success=False,
|
|
241
241
|
image_path=None,
|
|
242
242
|
preview_url=None,
|
|
243
|
-
error="
|
|
243
|
+
error="requests package not installed. Run: pip install requests",
|
|
244
244
|
prompt_used=prompt,
|
|
245
245
|
)
|
|
246
246
|
|
|
@@ -255,8 +255,6 @@ class PreviewGenerator:
|
|
|
255
255
|
)
|
|
256
256
|
|
|
257
257
|
try:
|
|
258
|
-
client = OpenAI(api_key=api_key)
|
|
259
|
-
|
|
260
258
|
self.debug(f"Generating with prompt: {prompt[:200]}...")
|
|
261
259
|
|
|
262
260
|
# Parse size
|
|
@@ -267,27 +265,29 @@ class PreviewGenerator:
|
|
|
267
265
|
}
|
|
268
266
|
size = size_map.get(self.image_size, "1024x1024")
|
|
269
267
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
268
|
+
# Use HTTP API directly instead of SDK
|
|
269
|
+
response = requests.post(
|
|
270
|
+
"https://api.openai.com/v1/images/generations",
|
|
271
|
+
headers={
|
|
272
|
+
"Authorization": f"Bearer {api_key}",
|
|
273
|
+
"Content-Type": "application/json",
|
|
274
|
+
},
|
|
275
|
+
json={
|
|
276
|
+
"model": "dall-e-3",
|
|
277
|
+
"prompt": prompt,
|
|
278
|
+
"size": size,
|
|
279
|
+
"quality": "standard",
|
|
280
|
+
"n": 1,
|
|
281
|
+
},
|
|
282
|
+
timeout=120, # 2 minute timeout for image generation
|
|
276
283
|
)
|
|
284
|
+
response.raise_for_status()
|
|
277
285
|
|
|
278
|
-
|
|
286
|
+
data = response.json()
|
|
287
|
+
image_url = data['data'][0]['url']
|
|
279
288
|
|
|
280
289
|
# Download image
|
|
281
|
-
|
|
282
|
-
return GenerationResult(
|
|
283
|
-
success=False,
|
|
284
|
-
image_path=None,
|
|
285
|
-
preview_url=image_url,
|
|
286
|
-
error="requests package not installed. Run: pip install requests",
|
|
287
|
-
prompt_used=prompt,
|
|
288
|
-
)
|
|
289
|
-
|
|
290
|
-
img_response = requests.get(image_url)
|
|
290
|
+
img_response = requests.get(image_url, timeout=60)
|
|
291
291
|
img_response.raise_for_status()
|
|
292
292
|
|
|
293
293
|
output_path.write_bytes(img_response.content)
|
|
@@ -300,6 +300,21 @@ class PreviewGenerator:
|
|
|
300
300
|
prompt_used=prompt,
|
|
301
301
|
)
|
|
302
302
|
|
|
303
|
+
except requests.exceptions.HTTPError as e:
|
|
304
|
+
error_msg = str(e)
|
|
305
|
+
try:
|
|
306
|
+
error_data = e.response.json()
|
|
307
|
+
if 'error' in error_data:
|
|
308
|
+
error_msg = error_data['error'].get('message', str(e))
|
|
309
|
+
except:
|
|
310
|
+
pass
|
|
311
|
+
return GenerationResult(
|
|
312
|
+
success=False,
|
|
313
|
+
image_path=None,
|
|
314
|
+
preview_url=None,
|
|
315
|
+
error=error_msg,
|
|
316
|
+
prompt_used=prompt,
|
|
317
|
+
)
|
|
303
318
|
except Exception as e:
|
|
304
319
|
return GenerationResult(
|
|
305
320
|
success=False,
|
data/scripts/test-mermaid.sh
CHANGED
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
# --docker Test Docker container
|
|
14
14
|
###############################################################################
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
# Note: Removed -e flag to avoid SIGPIPE issues with pipelines (curl | grep)
|
|
17
|
+
set -uo pipefail
|
|
17
18
|
|
|
18
19
|
# Colors for output
|
|
19
20
|
RED='\033[0;31m'
|
|
@@ -132,24 +133,63 @@ test_url() {
|
|
|
132
133
|
test_mermaid_script() {
|
|
133
134
|
local url="$1"
|
|
134
135
|
local description="$2"
|
|
136
|
+
local response
|
|
137
|
+
local count
|
|
135
138
|
|
|
136
|
-
|
|
139
|
+
TOTAL_TESTS=$((TOTAL_TESTS + 1))
|
|
140
|
+
response=$(curl -s "$url" 2>/dev/null) || true
|
|
141
|
+
count=$(echo "$response" | grep -c 'mermaid.min.js' || true)
|
|
142
|
+
if [ "$count" -gt 0 ]; then
|
|
143
|
+
TESTS_PASSED=$((TESTS_PASSED + 1))
|
|
144
|
+
log_success "$description"
|
|
145
|
+
return 0
|
|
146
|
+
else
|
|
147
|
+
TESTS_FAILED=$((TESTS_FAILED + 1))
|
|
148
|
+
log_error "$description"
|
|
149
|
+
return 1
|
|
150
|
+
fi
|
|
137
151
|
}
|
|
138
152
|
|
|
139
153
|
# Test Mermaid initialization
|
|
140
154
|
test_mermaid_init() {
|
|
141
155
|
local url="$1"
|
|
142
156
|
local description="$2"
|
|
157
|
+
local response
|
|
158
|
+
local count
|
|
143
159
|
|
|
144
|
-
|
|
160
|
+
TOTAL_TESTS=$((TOTAL_TESTS + 1))
|
|
161
|
+
response=$(curl -s "$url" 2>/dev/null) || true
|
|
162
|
+
count=$(echo "$response" | grep -c 'mermaid.initialize' || true)
|
|
163
|
+
if [ "$count" -gt 0 ]; then
|
|
164
|
+
TESTS_PASSED=$((TESTS_PASSED + 1))
|
|
165
|
+
log_success "$description"
|
|
166
|
+
return 0
|
|
167
|
+
else
|
|
168
|
+
TESTS_FAILED=$((TESTS_FAILED + 1))
|
|
169
|
+
log_error "$description"
|
|
170
|
+
return 1
|
|
171
|
+
fi
|
|
145
172
|
}
|
|
146
173
|
|
|
147
174
|
# Test diagram rendering
|
|
148
175
|
test_diagram_rendering() {
|
|
149
176
|
local url="$1"
|
|
150
177
|
local description="$2"
|
|
178
|
+
local response
|
|
179
|
+
local count
|
|
151
180
|
|
|
152
|
-
|
|
181
|
+
TOTAL_TESTS=$((TOTAL_TESTS + 1))
|
|
182
|
+
response=$(curl -s "$url" 2>/dev/null) || true
|
|
183
|
+
count=$(echo "$response" | grep -c 'class="mermaid"' || true)
|
|
184
|
+
if [ "$count" -gt 0 ]; then
|
|
185
|
+
TESTS_PASSED=$((TESTS_PASSED + 1))
|
|
186
|
+
log_success "$description"
|
|
187
|
+
return 0
|
|
188
|
+
else
|
|
189
|
+
TESTS_FAILED=$((TESTS_FAILED + 1))
|
|
190
|
+
log_error "$description"
|
|
191
|
+
return 1
|
|
192
|
+
fi
|
|
153
193
|
}
|
|
154
194
|
|
|
155
195
|
# Main test execution
|
|
@@ -165,9 +205,9 @@ main() {
|
|
|
165
205
|
log_info "Testing core files..."
|
|
166
206
|
|
|
167
207
|
test_file_exists "_includes/components/mermaid.html" "Mermaid include file exists"
|
|
168
|
-
test_file_exists "
|
|
169
|
-
test_file_exists "
|
|
170
|
-
test_file_exists "
|
|
208
|
+
test_file_exists "docs/jekyll/mermaid.md" "Main documentation exists"
|
|
209
|
+
test_file_exists "docs/jekyll/mermaid-test-suite.md" "Test suite exists"
|
|
210
|
+
test_file_exists "docs/jekyll/jekyll-diagram-with-mermaid.md" "Tutorial exists"
|
|
171
211
|
|
|
172
212
|
# Configuration tests
|
|
173
213
|
log_info "Testing configuration..."
|
|
@@ -188,10 +228,10 @@ main() {
|
|
|
188
228
|
# Documentation tests
|
|
189
229
|
log_info "Testing documentation..."
|
|
190
230
|
|
|
191
|
-
test_file_content "
|
|
192
|
-
test_file_content "
|
|
193
|
-
test_file_content "
|
|
194
|
-
test_file_content "
|
|
231
|
+
test_file_content "docs/jekyll/mermaid.md" "mermaid: true" "Main docs have front matter"
|
|
232
|
+
test_file_content "docs/jekyll/mermaid-test-suite.md" "mermaid: true" "Test suite has front matter"
|
|
233
|
+
test_file_content "docs/jekyll/mermaid.md" "graph TD" "Main docs have examples"
|
|
234
|
+
test_file_content "docs/jekyll/mermaid-test-suite.md" "graph TD" "Test suite has examples"
|
|
195
235
|
|
|
196
236
|
# Server tests (if not quick mode)
|
|
197
237
|
if [ "$QUICK" = false ]; then
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jekyll-theme-zer0
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.10.
|
|
4
|
+
version: 0.10.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Amr Abdel
|
|
@@ -161,7 +161,24 @@ files:
|
|
|
161
161
|
- assets/images/gravatar-small.png
|
|
162
162
|
- assets/images/gravatar.png
|
|
163
163
|
- assets/images/info-banner-mountain-wizard.png
|
|
164
|
+
- assets/images/previews/10-ai-tools-that-will-transform-your-productivity-.png
|
|
165
|
+
- assets/images/previews/business.png
|
|
166
|
+
- assets/images/previews/css-grid-mastery-build-any-layout-you-can-imagine.png
|
|
167
|
+
- assets/images/previews/development.png
|
|
164
168
|
- assets/images/previews/git-workflow-best-practices-for-modern-teams.png
|
|
169
|
+
- assets/images/previews/github-setup-deployment.png
|
|
170
|
+
- assets/images/previews/jekyll-setup.png
|
|
171
|
+
- assets/images/previews/machine-setup.png
|
|
172
|
+
- assets/images/previews/published-documentation-library.png
|
|
173
|
+
- assets/images/previews/quantum-computing-explained-from-qubits-to-quantum.png
|
|
174
|
+
- assets/images/previews/science.png
|
|
175
|
+
- assets/images/previews/technology.png
|
|
176
|
+
- assets/images/previews/the-complete-guide-to-startup-funding-in-2025.png
|
|
177
|
+
- assets/images/previews/the-remote-work-revolution-how-global-teams-are-re.png
|
|
178
|
+
- assets/images/previews/tutorial.png
|
|
179
|
+
- assets/images/previews/world-news.png
|
|
180
|
+
- assets/images/previews/zer0-mistakes-news-network-building-dynamic-news-s.png
|
|
181
|
+
- assets/images/previews/zer0-mistakes-quick-start-guide.png
|
|
165
182
|
- assets/images/wizard-on-journey.png
|
|
166
183
|
- assets/images/zer0-checkpoint-1.png
|
|
167
184
|
- assets/images/zer0-checkpoint-2.png
|