jekyll-theme-zer0 0.8.1 → 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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +308 -4
  3. data/README.md +58 -25
  4. data/_data/README.md +4 -5
  5. data/_includes/README.md +1 -1
  6. data/_includes/components/mermaid.html +98 -9
  7. data/_includes/content/intro.html +13 -1
  8. data/_includes/core/header.html +1 -1
  9. data/_includes/stats/README.md +14 -2
  10. data/_layouts/README.md +3 -3
  11. data/_layouts/category.html +16 -6
  12. data/_layouts/collection.html +8 -3
  13. data/_layouts/journals.html +8 -3
  14. data/_sass/core/_theme.scss +4 -1
  15. data/_sass/custom.scss +20 -12
  16. data/assets/images/previews/10-ai-tools-that-will-transform-your-productivity-.png +0 -0
  17. data/assets/images/previews/business.png +0 -0
  18. data/assets/images/previews/css-grid-mastery-build-any-layout-you-can-imagine.png +0 -0
  19. data/assets/images/previews/development.png +0 -0
  20. data/assets/images/previews/github-setup-deployment.png +0 -0
  21. data/assets/images/previews/jekyll-setup.png +0 -0
  22. data/assets/images/previews/machine-setup.png +0 -0
  23. data/assets/images/previews/published-documentation-library.png +0 -0
  24. data/assets/images/previews/quantum-computing-explained-from-qubits-to-quantum.png +0 -0
  25. data/assets/images/previews/science.png +0 -0
  26. data/assets/images/previews/technology.png +0 -0
  27. data/assets/images/previews/the-complete-guide-to-startup-funding-in-2025.png +0 -0
  28. data/assets/images/previews/the-remote-work-revolution-how-global-teams-are-re.png +0 -0
  29. data/assets/images/previews/tutorial.png +0 -0
  30. data/assets/images/previews/world-news.png +0 -0
  31. data/assets/images/previews/zer0-mistakes-news-network-building-dynamic-news-s.png +0 -0
  32. data/assets/images/previews/zer0-mistakes-quick-start-guide.png +0 -0
  33. data/assets/js/auto-hide-nav.js +79 -16
  34. data/scripts/bin/build +115 -0
  35. data/scripts/bin/release +240 -0
  36. data/scripts/bin/test +203 -0
  37. data/scripts/features/generate-preview-images +846 -0
  38. data/scripts/features/install-preview-generator +531 -0
  39. data/scripts/features/preview_generator.py +646 -0
  40. data/scripts/generate-preview-images.sh +38 -93
  41. data/scripts/lib/README.md +35 -7
  42. data/scripts/lib/preview_generator.py +37 -22
  43. data/scripts/test/integration/auto-version +243 -0
  44. data/scripts/test/integration/mermaid +252 -0
  45. data/scripts/test/lib/run_tests.sh +151 -0
  46. data/scripts/test/lib/test_changelog.sh +90 -0
  47. data/scripts/test/lib/test_gem.sh +71 -0
  48. data/scripts/test/lib/test_git.sh +85 -0
  49. data/scripts/test/lib/test_validation.sh +75 -0
  50. data/scripts/test/lib/test_version.sh +101 -0
  51. data/scripts/test/theme/validate +120 -0
  52. data/scripts/test-mermaid.sh +51 -11
  53. data/scripts/utils/analyze-commits +300 -0
  54. data/scripts/utils/fix-markdown +251 -0
  55. data/scripts/utils/setup +137 -0
  56. data/scripts/version.sh +26 -0
  57. metadata +37 -8
  58. data/scripts/build.sh +0 -33
  59. data/scripts/build.sh.legacy +0 -174
  60. data/scripts/gem-publish.sh +0 -42
  61. data/scripts/gem-publish.sh.legacy +0 -700
  62. data/scripts/release.sh +0 -33
  63. data/scripts/release.sh.legacy +0 -342
@@ -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
- <img src="{{ site.baseurl }}/{{ site.public_folder }}/{{ fpost.preview }}"
116
- class="card-img-top" alt="{{ fpost.title }}" loading="lazy">
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 }}/{{ site.teaser }}"
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
- <img src="{{ site.baseurl }}/{{ site.public_folder }}/{{ cpost.preview }}"
171
- class="card-img-top" alt="{{ cpost.title }}" loading="lazy">
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 }}/{{ site.teaser }}"
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>
@@ -84,10 +84,15 @@ layout: default
84
84
  <!-- ====================== -->
85
85
  <!-- Display preview image with fallback to site teaser -->
86
86
  {% if post.preview %}
87
- <img src="{{site.baseurl}}/{{ site.public_folder }}/{{ post.preview}}"
88
- class="card-img-top" alt="Preview image for {{ post.title }}">
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 }}/{{ site.teaser }}"
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
 
@@ -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
- <img src="{{ site.baseurl }}/{{ site.public_folder }}/{{ rpost.preview }}"
193
- class="card-img-top" alt="{{ rpost.title }}" loading="lazy">
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 }}/{{ site.teaser }}"
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>
@@ -1,8 +1,11 @@
1
+ // Import variables for standalone compilation
2
+ @import "variables";
3
+
1
4
  // # Font Settings ---------------------------------------------------------------
2
5
 
3
6
  // # Color Settings --------------------------------------------------------------
4
7
 
5
- // ## Color Schema Override
8
+ // ## Color Schema Override
6
9
  // https://meodai.github.io/poline/
7
10
 
8
11
  // Harbour Mirror
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
- // position: fixed;
182
- top: 0;
183
- width: 100%;
184
- transition: transform 0.3s;
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
- .fixed-navbar {
188
- position: fixed;
189
- top: 0;
190
- width: 100%;
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
- .hide-navbar {
195
- transform: translateY(-100%);
196
- top: 0px;
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
@@ -1,18 +1,81 @@
1
- // Hides the navbar when scrolling down half a page and shows it when scrolling up
2
- window.onload = function() {
3
- let lastScrollTop = 0;
4
- const navbar = document.getElementById('navbar');
5
-
6
- window.addEventListener('scroll', function() {
7
- let scrollTop = window.pageYOffset || document.documentElement.scrollTop;
8
- let halfPageHeight = window.innerHeight / 2;
9
-
10
- if (scrollTop > lastScrollTop && scrollTop > halfPageHeight) {
11
- navbar.classList.add('hide-navbar');
12
- navbar.classList.add('fixed-navbar');
13
- } else {
14
- navbar.classList.remove('hide-navbar');
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
+ })();
data/scripts/bin/build ADDED
@@ -0,0 +1,115 @@
1
+ #!/bin/bash
2
+
3
+ # Simplified build command for zer0-mistakes Jekyll theme
4
+ # Usage: ./scripts/build [options]
5
+ #
6
+ # Quick gem building without the full release workflow.
7
+
8
+ set -euo pipefail
9
+
10
+ # Get script and library directories
11
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
12
+ LIB_DIR="$SCRIPT_DIR/../lib"
13
+
14
+ # Source required libraries
15
+ source "$LIB_DIR/common.sh"
16
+ source "$LIB_DIR/validation.sh"
17
+ source "$LIB_DIR/version.sh"
18
+ source "$LIB_DIR/gem.sh"
19
+
20
+ # Parse arguments
21
+ while [[ $# -gt 0 ]]; do
22
+ case $1 in
23
+ --dry-run)
24
+ export DRY_RUN=true
25
+ shift
26
+ ;;
27
+ --verbose)
28
+ export VERBOSE=true
29
+ shift
30
+ ;;
31
+ --help|-h)
32
+ show_usage
33
+ exit 0
34
+ ;;
35
+ *)
36
+ error "Unknown option: $1 (use --help for usage)"
37
+ ;;
38
+ esac
39
+ done
40
+
41
+ # Show usage
42
+ show_usage() {
43
+ cat << EOF
44
+ 🔨 Simplified Build Command for zer0-mistakes
45
+
46
+ USAGE:
47
+ ./scripts/bin/build [OPTIONS]
48
+
49
+ DESCRIPTION:
50
+ Builds the Jekyll theme gem without running the full release workflow.
51
+ Useful for testing gem packaging or preparing for manual publication.
52
+
53
+ OPTIONS:
54
+ --dry-run Preview build without creating files
55
+ --verbose Show detailed debug output
56
+ --help, -h Show this help message
57
+
58
+ EXAMPLES:
59
+ ./scripts/bin/build # Build gem with current version
60
+ ./scripts/bin/build --dry-run # Preview what would be built
61
+ ./scripts/build --verbose # Build with debug output
62
+
63
+ ENVIRONMENT VARIABLES:
64
+ DRY_RUN=true Enable dry run mode
65
+ VERBOSE=true Enable debug output
66
+
67
+ OUTPUT:
68
+ Creates: jekyll-theme-zer0-VERSION.gem in current directory
69
+
70
+ For full release workflow, use: ./scripts/release
71
+ EOF
72
+ }
73
+
74
+ # Main build workflow
75
+ main() {
76
+ print_header "🔨 Gem Build"
77
+
78
+ # Step 1: Basic validation (no RubyGems auth needed for build)
79
+ step "Validating environment..."
80
+ validate_git_repo
81
+ validate_required_files
82
+ validate_gemspec
83
+ success "Environment validated"
84
+ echo ""
85
+
86
+ # Step 2: Get current version
87
+ step "Reading version..."
88
+ local version
89
+ version=$(get_current_version)
90
+ info "Current version: $version"
91
+ info "Gem file: jekyll-theme-zer0-${version}.gem"
92
+ echo ""
93
+
94
+ # Step 3: Build gem
95
+ build_gem "$version"
96
+ echo ""
97
+
98
+ # Success summary
99
+ if [[ "$DRY_RUN" != "true" ]]; then
100
+ print_summary "Build Complete" \
101
+ "✅ Built: jekyll-theme-zer0-${version}.gem" \
102
+ "" \
103
+ "Next steps:" \
104
+ " • Test: gem install jekyll-theme-zer0-${version}.gem" \
105
+ " • Publish: gem push jekyll-theme-zer0-${version}.gem" \
106
+ " • Or use: ./scripts/release for full workflow"
107
+ else
108
+ info "Dry run complete - no files created"
109
+ fi
110
+
111
+ success "Build completed successfully!"
112
+ }
113
+
114
+ # Run main function
115
+ main "$@"
@@ -0,0 +1,240 @@
1
+ #!/bin/bash
2
+
3
+ # Simplified release command for zer0-mistakes Jekyll theme
4
+ # Usage: ./scripts/release [patch|minor|major] [options]
5
+ #
6
+ # This replaces the complex gem-publish.sh with a clean, library-based approach.
7
+
8
+ set -euo pipefail
9
+
10
+ # Get script and library directories
11
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
12
+ LIB_DIR="$SCRIPT_DIR/../lib"
13
+
14
+ # Source all required libraries
15
+ source "$LIB_DIR/common.sh"
16
+ source "$LIB_DIR/validation.sh"
17
+ source "$LIB_DIR/version.sh"
18
+ source "$LIB_DIR/git.sh"
19
+ source "$LIB_DIR/changelog.sh"
20
+ source "$LIB_DIR/gem.sh"
21
+
22
+ # Show usage function
23
+ show_usage() {
24
+ cat << EOF
25
+ 🚀 Simplified Release Command for zer0-mistakes
26
+
27
+ USAGE:
28
+ ./scripts/bin/release [VERSION_TYPE] [OPTIONS]
29
+
30
+ VERSION TYPES:
31
+ patch Bump patch version (0.0.X) - Bug fixes (default)
32
+ minor Bump minor version (0.X.0) - New features
33
+ major Bump major version (X.0.0) - Breaking changes
34
+
35
+ OPTIONS:
36
+ --dry-run Preview changes without executing
37
+ --skip-tests Skip running test suite
38
+ --skip-publish Build but don't publish to RubyGems
39
+ --no-github-release Skip creating GitHub release
40
+ --non-interactive Run without confirmation prompts
41
+ --verbose Show detailed debug output
42
+ --help, -h Show this help message
43
+
44
+ EXAMPLES:
45
+ ./scripts/bin/release # Patch release (0.6.0 → 0.6.1)
46
+ ./scripts/bin/release minor # Minor release (0.6.0 → 0.7.0)
47
+ ./scripts/bin/release major --dry-run # Preview major release
48
+ ./scripts/bin/release patch --skip-tests # Quick release without tests
49
+
50
+ ENVIRONMENT VARIABLES:
51
+ DRY_RUN=true Enable dry run mode
52
+ INTERACTIVE=false Disable confirmation prompts
53
+ VERBOSE=true Enable debug output
54
+
55
+ WORKFLOW:
56
+ 1. Validate environment
57
+ 2. Calculate new version
58
+ 3. Generate changelog from commits
59
+ 4. Update version files
60
+ 5. Run tests (unless --skip-tests)
61
+ 6. Build gem
62
+ 7. Commit and tag
63
+ 8. Publish to RubyGems (unless --skip-publish)
64
+ 9. Create GitHub release (unless --no-github-release)
65
+ 10. Push changes to repository
66
+
67
+ For more information, see: scripts/lib/README.md
68
+ EOF
69
+ }
70
+
71
+ # Default configuration
72
+ VERSION_TYPE="patch"
73
+ SKIP_TESTS=false
74
+ SKIP_PUBLISH=false
75
+ SKIP_GITHUB_RELEASE=false
76
+ SHOW_HELP=false
77
+
78
+ # Parse arguments
79
+ for arg in "$@"; do
80
+ case $arg in
81
+ --help|-h)
82
+ SHOW_HELP=true
83
+ ;;
84
+ patch|minor|major)
85
+ VERSION_TYPE="$arg"
86
+ ;;
87
+ esac
88
+ done
89
+
90
+ # Show help if requested
91
+ if [[ "$SHOW_HELP" == "true" ]]; then
92
+ show_usage
93
+ exit 0
94
+ fi
95
+
96
+ # Parse remaining arguments
97
+ while [[ $# -gt 0 ]]; do
98
+ case $1 in
99
+ patch|minor|major)
100
+ # Already handled above
101
+ shift
102
+ ;;
103
+ --help|-h)
104
+ # Already handled above
105
+ shift
106
+ ;;
107
+ --dry-run)
108
+ export DRY_RUN=true
109
+ shift
110
+ ;;
111
+ --skip-tests)
112
+ SKIP_TESTS=true
113
+ shift
114
+ ;;
115
+ --skip-publish)
116
+ SKIP_PUBLISH=true
117
+ shift
118
+ ;;
119
+ --no-github-release)
120
+ SKIP_GITHUB_RELEASE=true
121
+ shift
122
+ ;;
123
+ --non-interactive)
124
+ export INTERACTIVE=false
125
+ shift
126
+ ;;
127
+ --verbose)
128
+ export VERBOSE=true
129
+ shift
130
+ ;;
131
+ *)
132
+ error "Unknown option: $1 (use --help for usage)"
133
+ ;;
134
+ esac
135
+ done
136
+
137
+ # Main release workflow
138
+ main() {
139
+ print_header "🚀 Release Automation"
140
+
141
+ # Show configuration
142
+ info "Version type: $VERSION_TYPE"
143
+ info "Dry run: ${DRY_RUN:-false}"
144
+ info "Interactive: ${INTERACTIVE:-true}"
145
+ echo ""
146
+
147
+ # Step 1: Validate environment
148
+ validate_environment "$SKIP_PUBLISH" "$SKIP_GITHUB_RELEASE"
149
+
150
+ # Step 2: Version calculation
151
+ step "Calculating new version..."
152
+ local current_version
153
+ current_version=$(get_current_version)
154
+ info "Current version: $current_version"
155
+
156
+ local new_version
157
+ new_version=$(calculate_new_version "$current_version" "$VERSION_TYPE")
158
+ info "New version: $new_version"
159
+
160
+ # Confirm before proceeding
161
+ if [[ "$INTERACTIVE" == "true" ]] && [[ "$DRY_RUN" != "true" ]]; then
162
+ echo ""
163
+ if ! confirm "Proceed with release $current_version → $new_version?"; then
164
+ warn "Release cancelled by user"
165
+ exit 0
166
+ fi
167
+ fi
168
+ echo ""
169
+
170
+ # Step 3: Generate changelog
171
+ step "Generating changelog..."
172
+ local last_tag
173
+ last_tag=$(get_last_version_tag)
174
+ generate_changelog "$new_version" "$last_tag" "HEAD"
175
+ echo ""
176
+
177
+ # Step 4: Update version files
178
+ update_version_files "$new_version"
179
+ echo ""
180
+
181
+ # Step 5: Run tests
182
+ if [[ "$SKIP_TESTS" != "true" ]]; then
183
+ run_tests
184
+ echo ""
185
+ else
186
+ warn "Skipping tests (--skip-tests specified)"
187
+ echo ""
188
+ fi
189
+
190
+ # Step 6: Build gem
191
+ build_gem "$new_version"
192
+ echo ""
193
+
194
+ # Step 7: Commit and tag
195
+ commit_and_tag "$new_version"
196
+ echo ""
197
+
198
+ # Step 8: Publish gem
199
+ if [[ "$SKIP_PUBLISH" != "true" ]]; then
200
+ publish_gem "$new_version"
201
+ echo ""
202
+ else
203
+ warn "Skipping RubyGems publication (--skip-publish specified)"
204
+ echo ""
205
+ fi
206
+
207
+ # Step 9: Create GitHub release
208
+ if [[ "$SKIP_GITHUB_RELEASE" != "true" ]]; then
209
+ create_github_release "$new_version"
210
+ echo ""
211
+ else
212
+ warn "Skipping GitHub release (--no-github-release specified)"
213
+ echo ""
214
+ fi
215
+
216
+ # Step 10: Push changes
217
+ push_changes
218
+ echo ""
219
+
220
+ # Step 11: Cleanup
221
+ cleanup_gem_files "$new_version"
222
+ echo ""
223
+
224
+ # Success summary
225
+ print_header "✅ Release Complete!"
226
+
227
+ print_summary "Release $new_version" \
228
+ "Version: $current_version → $new_version" \
229
+ "Type: $VERSION_TYPE bump" \
230
+ "Tag: v$new_version" \
231
+ "" \
232
+ "📦 RubyGems: https://rubygems.org/gems/jekyll-theme-zer0/versions/$new_version" \
233
+ "🏷️ GitHub: https://github.com/bamr87/zer0-mistakes/releases/tag/v$new_version" \
234
+ "📂 Repository: https://github.com/bamr87/zer0-mistakes"
235
+
236
+ success "Release workflow completed successfully!"
237
+ }
238
+
239
+ # Run main function
240
+ main "$@"