jekyll-theme-zer0 0.7.2 → 0.8.1

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +72 -0
  3. data/README.md +33 -4
  4. data/_plugins/preview_image_generator.rb +258 -0
  5. data/_plugins/theme_version.rb +88 -0
  6. data/assets/images/previews/git-workflow-best-practices-for-modern-teams.png +0 -0
  7. data/scripts/README.md +443 -0
  8. data/scripts/analyze-commits.sh +313 -0
  9. data/scripts/build +115 -0
  10. data/scripts/build.sh +33 -0
  11. data/scripts/build.sh.legacy +174 -0
  12. data/scripts/example-usage.sh +102 -0
  13. data/scripts/fix-markdown-format.sh +265 -0
  14. data/scripts/gem-publish.sh +42 -0
  15. data/scripts/gem-publish.sh.legacy +700 -0
  16. data/scripts/generate-preview-images.sh +846 -0
  17. data/scripts/install-preview-generator.sh +531 -0
  18. data/scripts/lib/README.md +263 -0
  19. data/scripts/lib/changelog.sh +313 -0
  20. data/scripts/lib/common.sh +154 -0
  21. data/scripts/lib/gem.sh +226 -0
  22. data/scripts/lib/git.sh +205 -0
  23. data/scripts/lib/preview_generator.py +646 -0
  24. data/scripts/lib/test/run_tests.sh +140 -0
  25. data/scripts/lib/test/test_changelog.sh +87 -0
  26. data/scripts/lib/test/test_gem.sh +68 -0
  27. data/scripts/lib/test/test_git.sh +82 -0
  28. data/scripts/lib/test/test_validation.sh +72 -0
  29. data/scripts/lib/test/test_version.sh +96 -0
  30. data/scripts/lib/validation.sh +139 -0
  31. data/scripts/lib/version.sh +178 -0
  32. data/scripts/release +240 -0
  33. data/scripts/release.sh +33 -0
  34. data/scripts/release.sh.legacy +342 -0
  35. data/scripts/setup.sh +155 -0
  36. data/scripts/test-auto-version.sh +260 -0
  37. data/scripts/test-mermaid.sh +251 -0
  38. data/scripts/test.sh +156 -0
  39. data/scripts/version.sh +152 -0
  40. metadata +37 -1
@@ -0,0 +1,313 @@
1
+ #!/bin/bash
2
+
3
+ # Commit Analysis Script for Automated Version Bumping
4
+ # Analyzes git commits to determine appropriate semantic version bump
5
+ # Usage: ./scripts/analyze-commits.sh [commit-range]
6
+ # Output: patch|minor|major|none
7
+
8
+ set -euo pipefail
9
+
10
+ # Colors for output
11
+ RED='\033[0;31m'
12
+ GREEN='\033[0;32m'
13
+ YELLOW='\033[1;33m'
14
+ BLUE='\033[0;34m'
15
+ CYAN='\033[0;36m'
16
+ NC='\033[0m' # No Color
17
+
18
+ # Default values
19
+ COMMIT_RANGE="${1:-HEAD~1..HEAD}"
20
+ DEBUG=${DEBUG:-false}
21
+
22
+ # Logging functions
23
+ log_debug() {
24
+ if [[ "$DEBUG" == "true" ]]; then
25
+ echo -e "${CYAN}[DEBUG]${NC} $1" >&2
26
+ fi
27
+ }
28
+
29
+ log_info() {
30
+ echo -e "${BLUE}[INFO]${NC} $1" >&2
31
+ }
32
+
33
+ log_warning() {
34
+ echo -e "${YELLOW}[WARNING]${NC} $1" >&2
35
+ }
36
+
37
+ log_error() {
38
+ echo -e "${RED}[ERROR]${NC} $1" >&2
39
+ }
40
+
41
+ # Function to analyze individual commit
42
+ analyze_commit() {
43
+ local commit_hash="$1"
44
+ local commit_message
45
+ local commit_files
46
+ local bump_level="none"
47
+
48
+ commit_message=$(git log --format="%s%n%b" -n 1 "$commit_hash")
49
+ commit_files=$(git diff-tree --no-commit-id --name-only -r "$commit_hash" 2>/dev/null || echo "")
50
+
51
+ log_debug "Analyzing commit: $commit_hash"
52
+ log_debug "Message: $(echo "$commit_message" | head -1)"
53
+
54
+ # Check for breaking changes (MAJOR)
55
+ if echo "$commit_message" | grep -qi "BREAKING CHANGE\|breaking:"; then
56
+ echo "major"
57
+ return 0
58
+ fi
59
+
60
+ # Check for major version indicators in commit message
61
+ if echo "$commit_message" | grep -qE "^(major|MAJOR|breaking|BREAKING)[\s:]"; then
62
+ echo "major"
63
+ return 0
64
+ fi
65
+
66
+ # Check commit message patterns for conventional commits
67
+ local subject_line=$(echo "$commit_message" | head -1)
68
+
69
+ # MAJOR changes
70
+ if echo "$subject_line" | grep -qE "^(revert|remove|delete)[\s:].*[Bb]reaking"; then
71
+ echo "major"
72
+ return 0
73
+ fi
74
+
75
+ # MINOR changes (new features)
76
+ if echo "$subject_line" | grep -qE "^(feat|feature|add|new)[\s:]"; then
77
+ echo "minor"
78
+ return 0
79
+ fi
80
+
81
+ # MINOR changes - significant additions
82
+ if echo "$subject_line" | grep -qE "^(enhance|improve|update)[\s:].*[Ff]eature"; then
83
+ echo "minor"
84
+ return 0
85
+ fi
86
+
87
+ # PATCH changes (bug fixes, small improvements)
88
+ if echo "$subject_line" | grep -qE "^(fix|bug|patch|hotfix|chore|docs|style|refactor|test|perf)[\s:]"; then
89
+ echo "patch"
90
+ return 0
91
+ fi
92
+
93
+ # PATCH changes - maintenance and small improvements
94
+ if echo "$subject_line" | grep -qE "^(update|improve|enhance|optimize|clean)[\s:]"; then
95
+ echo "patch"
96
+ return 0
97
+ fi
98
+
99
+ # File-based analysis for changes without conventional commit messages
100
+ if [[ -n "$commit_files" ]]; then
101
+ local critical_files=0
102
+ local feature_files=0
103
+ local patch_files=0
104
+
105
+ while IFS= read -r file; do
106
+ [[ -z "$file" ]] && continue
107
+
108
+ log_debug "Analyzing file: $file"
109
+
110
+ # Critical/breaking change files (MAJOR)
111
+ if echo "$file" | grep -qE "(Gemfile|gemspec|_config\.yml|docker-compose\.yml|Dockerfile)$"; then
112
+ ((critical_files++))
113
+ log_debug "Critical file detected: $file"
114
+
115
+ # Feature files (MINOR)
116
+ elif echo "$file" | grep -qE "(_layouts/|_includes/|assets/|pages/.*\.md$|\.rb$|\.js$)"; then
117
+ ((feature_files++))
118
+ log_debug "Feature file detected: $file"
119
+
120
+ # Documentation and minor files (PATCH)
121
+ elif echo "$file" | grep -qE "(README|CHANGELOG|\.md$|\.txt$|\.yml$|\.yaml$|test/)"; then
122
+ ((patch_files++))
123
+ log_debug "Patch file detected: $file"
124
+ fi
125
+ done <<< "$commit_files"
126
+
127
+ # Determine bump level based on file analysis
128
+ if [[ $critical_files -gt 0 ]]; then
129
+ # But only if there are significant changes to critical files
130
+ local lines_changed=$(git diff --shortstat "$commit_hash^" "$commit_hash" 2>/dev/null | grep -oE '[0-9]+ insertion|[0-9]+ deletion' | grep -oE '[0-9]+' | paste -sd+ | bc 2>/dev/null || echo "0")
131
+ if [[ $lines_changed -gt 10 ]]; then
132
+ echo "minor" # Significant changes to critical files = minor
133
+ return 0
134
+ else
135
+ echo "patch" # Small changes to critical files = patch
136
+ return 0
137
+ fi
138
+ elif [[ $feature_files -gt 0 ]]; then
139
+ echo "patch" # Changes to feature files without explicit feat: = patch
140
+ return 0
141
+ elif [[ $patch_files -gt 0 ]]; then
142
+ echo "patch"
143
+ return 0
144
+ fi
145
+ fi
146
+
147
+ # If we reach here, no clear classification - default to patch for any real changes
148
+ if [[ -n "$commit_files" ]]; then
149
+ echo "patch"
150
+ else
151
+ echo "none"
152
+ fi
153
+ }
154
+
155
+ # Function to determine highest bump level from multiple commits
156
+ determine_overall_bump() {
157
+ local commits=("$@")
158
+ local highest_bump="none"
159
+ local patch_count=0
160
+ local minor_count=0
161
+ local major_count=0
162
+
163
+ log_info "Analyzing ${#commits[@]} commits for version bump determination"
164
+
165
+ for commit in "${commits[@]}"; do
166
+ local bump_level
167
+ bump_level=$(analyze_commit "$commit")
168
+
169
+ log_debug "Commit $commit: $bump_level"
170
+
171
+ case "$bump_level" in
172
+ "major")
173
+ ((major_count++))
174
+ highest_bump="major"
175
+ ;;
176
+ "minor")
177
+ ((minor_count++))
178
+ if [[ "$highest_bump" != "major" ]]; then
179
+ highest_bump="minor"
180
+ fi
181
+ ;;
182
+ "patch")
183
+ ((patch_count++))
184
+ if [[ "$highest_bump" == "none" ]]; then
185
+ highest_bump="patch"
186
+ fi
187
+ ;;
188
+ esac
189
+ done
190
+
191
+ log_info "Bump analysis summary:"
192
+ log_info " - Major changes: $major_count"
193
+ log_info " - Minor changes: $minor_count"
194
+ log_info " - Patch changes: $patch_count"
195
+ log_info " - Overall recommendation: $highest_bump"
196
+
197
+ echo "$highest_bump"
198
+ }
199
+
200
+ # Main execution
201
+ main() {
202
+ local commit_range="$COMMIT_RANGE"
203
+
204
+ log_info "Analyzing commits in range: $commit_range"
205
+
206
+ # Validate git repository
207
+ if ! git rev-parse --git-dir > /dev/null 2>&1; then
208
+ log_error "Not in a git repository"
209
+ exit 1
210
+ fi
211
+
212
+ # Get list of commits in range
213
+ local commits
214
+ if ! commits=($(git rev-list --reverse "$commit_range" 2>/dev/null)); then
215
+ log_warning "No commits found in range: $commit_range"
216
+ echo "none"
217
+ exit 0
218
+ fi
219
+
220
+ if [[ ${#commits[@]} -eq 0 ]]; then
221
+ log_warning "No commits to analyze"
222
+ echo "none"
223
+ exit 0
224
+ fi
225
+
226
+ # Filter out merge commits and automated commits
227
+ local filtered_commits=()
228
+ for commit in "${commits[@]}"; do
229
+ local commit_subject
230
+ commit_subject=$(git log --format="%s" -n 1 "$commit")
231
+
232
+ # Skip merge commits
233
+ if echo "$commit_subject" | grep -qE "^Merge (branch|pull request|remote-tracking branch)"; then
234
+ log_debug "Skipping merge commit: $commit"
235
+ continue
236
+ fi
237
+
238
+ # Skip automated commits (version bumps, changelog updates)
239
+ if echo "$commit_subject" | grep -qE "^(chore: bump version|chore: update changelog|Automated|Auto-update)"; then
240
+ log_debug "Skipping automated commit: $commit"
241
+ continue
242
+ fi
243
+
244
+ # Skip commits that only modify ignored files
245
+ local commit_files
246
+ commit_files=$(git diff-tree --no-commit-id --name-only -r "$commit" 2>/dev/null || echo "")
247
+
248
+ local has_significant_files=false
249
+ while IFS= read -r file; do
250
+ [[ -z "$file" ]] && continue
251
+
252
+ # Skip if only changelog, version files, or workflow files changed
253
+ if ! echo "$file" | grep -qE "^(CHANGELOG\.md|lib/.*version\.rb|package\.json|\.github/workflows/)$"; then
254
+ has_significant_files=true
255
+ break
256
+ fi
257
+ done <<< "$commit_files"
258
+
259
+ if [[ "$has_significant_files" == "true" ]]; then
260
+ filtered_commits+=("$commit")
261
+ else
262
+ log_debug "Skipping commit with only version/changelog files: $commit"
263
+ fi
264
+ done
265
+
266
+ if [[ ${#filtered_commits[@]} -eq 0 ]]; then
267
+ log_info "No significant commits found after filtering"
268
+ echo "none"
269
+ exit 0
270
+ fi
271
+
272
+ log_info "Analyzing ${#filtered_commits[@]} significant commits (filtered from ${#commits[@]} total)"
273
+
274
+ # Determine the appropriate version bump
275
+ determine_overall_bump "${filtered_commits[@]}"
276
+ }
277
+
278
+ # Show usage if requested
279
+ if [[ "${1:-}" == "--help" ]] || [[ "${1:-}" == "-h" ]]; then
280
+ cat << EOF
281
+ Commit Analysis Script for Automated Version Bumping
282
+
283
+ USAGE:
284
+ $0 [commit-range]
285
+
286
+ ARGUMENTS:
287
+ commit-range Git commit range to analyze (default: HEAD~1..HEAD)
288
+
289
+ OUTPUT:
290
+ patch Bug fixes, documentation, small improvements
291
+ minor New features, enhancements
292
+ major Breaking changes, major refactors
293
+ none No version bump needed
294
+
295
+ EXAMPLES:
296
+ $0 # Analyze last commit
297
+ $0 HEAD~5..HEAD # Analyze last 5 commits
298
+ $0 v1.0.0..HEAD # Analyze since last tag
299
+
300
+ ENVIRONMENT:
301
+ DEBUG=true # Enable debug output
302
+
303
+ CONVENTIONAL COMMIT PATTERNS:
304
+ feat:, feature:, add: → minor
305
+ fix:, bug:, patch: → patch
306
+ BREAKING CHANGE, breaking: → major
307
+ chore:, docs:, style: → patch
308
+ EOF
309
+ exit 0
310
+ fi
311
+
312
+ # Execute main function
313
+ main "$@"
data/scripts/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/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/build # Build gem with current version
60
+ ./scripts/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 "$@"
data/scripts/build.sh ADDED
@@ -0,0 +1,33 @@
1
+ #!/bin/bash
2
+
3
+ # DEPRECATED: This script is deprecated and will be removed in v0.8.0
4
+ # Please use the new simplified build command instead.
5
+
6
+ set -e
7
+
8
+ # Colors
9
+ YELLOW='\033[1;33m'
10
+ CYAN='\033[0;36m'
11
+ NC='\033[0m'
12
+
13
+ echo -e "${YELLOW}╔════════════════════════════════════════════════════════════╗${NC}"
14
+ echo -e "${YELLOW}║ ⚠️ DEPRECATION WARNING ║${NC}"
15
+ echo -e "${YELLOW}╚════════════════════════════════════════════════════════════╝${NC}"
16
+ echo ""
17
+ echo -e "${YELLOW}This script (build.sh) is deprecated and will be removed in v0.8.0${NC}"
18
+ echo ""
19
+ echo -e "Please use the new simplified command instead:"
20
+ echo -e " ${CYAN}./scripts/build${NC} [options]"
21
+ echo ""
22
+ echo -e "The new command is:"
23
+ echo -e " ✅ Simpler and more focused"
24
+ echo -e " ✅ Uses modular libraries"
25
+ echo -e " ✅ Better error handling"
26
+ echo -e " ✅ Fully tested"
27
+ echo ""
28
+ echo -e "${YELLOW}Redirecting to new command in 3 seconds...${NC}"
29
+ sleep 3
30
+ echo ""
31
+
32
+ # Redirect to new command
33
+ exec "$(dirname "$0")/build" "$@"
@@ -0,0 +1,174 @@
1
+ #!/bin/bash
2
+
3
+ # Build and publish script for zer0-mistakes Jekyll theme
4
+ # Usage: ./scripts/build.sh [--publish] [--dry-run]
5
+
6
+ set -e
7
+
8
+ # Colors for output
9
+ RED='\033[0;31m'
10
+ GREEN='\033[0;32m'
11
+ YELLOW='\033[1;33m'
12
+ BLUE='\033[0;34m'
13
+ NC='\033[0m' # No Color
14
+
15
+ # Default values
16
+ PUBLISH=false
17
+ DRY_RUN=false
18
+
19
+ # Parse arguments
20
+ while [[ $# -gt 0 ]]; do
21
+ case $1 in
22
+ --publish)
23
+ PUBLISH=true
24
+ shift
25
+ ;;
26
+ --dry-run)
27
+ DRY_RUN=true
28
+ shift
29
+ ;;
30
+ *)
31
+ echo -e "${RED}Unknown option: $1${NC}"
32
+ exit 1
33
+ ;;
34
+ esac
35
+ done
36
+
37
+ # Function to log messages
38
+ log() {
39
+ echo -e "${GREEN}[BUILD]${NC} $1"
40
+ }
41
+
42
+ warn() {
43
+ echo -e "${YELLOW}[WARNING]${NC} $1"
44
+ }
45
+
46
+ error() {
47
+ echo -e "${RED}[ERROR]${NC} $1"
48
+ exit 1
49
+ }
50
+
51
+ info() {
52
+ echo -e "${BLUE}[INFO]${NC} $1"
53
+ }
54
+
55
+ # Check if gemspec exists
56
+ if [[ ! -f "jekyll-theme-zer0.gemspec" ]]; then
57
+ error "jekyll-theme-zer0.gemspec not found"
58
+ fi
59
+
60
+ # Check if package.json exists
61
+ if [[ ! -f "package.json" ]]; then
62
+ error "package.json not found"
63
+ fi
64
+
65
+ # Get version from package.json
66
+ VERSION=$(jq -r '.version' package.json)
67
+ if [[ "$VERSION" == "null" ]]; then
68
+ error "Could not read version from package.json"
69
+ fi
70
+
71
+ log "Building jekyll-theme-zer0 version $VERSION"
72
+
73
+ # Create build directory
74
+ log "Creating build directory..."
75
+ mkdir -p build
76
+
77
+ # Clean up old gem files
78
+ log "Cleaning up old gem files..."
79
+ rm -f jekyll-theme-zer0-*.gem
80
+ rm -f build/jekyll-theme-zer0-*.gem
81
+
82
+ # Validate dependencies
83
+ log "Checking dependencies..."
84
+ if ! command -v bundle &> /dev/null; then
85
+ error "Bundler is not installed. Run 'gem install bundler' first."
86
+ fi
87
+
88
+ if ! command -v jq &> /dev/null; then
89
+ error "jq is not installed. Run 'brew install jq' (macOS) or appropriate package manager."
90
+ fi
91
+
92
+ # Run bundle install to ensure dependencies are up to date
93
+ log "Installing/updating dependencies..."
94
+ if [[ "$DRY_RUN" != true ]]; then
95
+ bundle install
96
+ fi
97
+
98
+ # Validate gemspec
99
+ log "Validating gemspec..."
100
+ if [[ "$DRY_RUN" != true ]]; then
101
+ ruby -c jekyll-theme-zer0.gemspec > /dev/null
102
+ info "✓ Gemspec is valid"
103
+ fi
104
+
105
+ # Build the gem
106
+ log "Building gem..."
107
+ if [[ "$DRY_RUN" == true ]]; then
108
+ log "Dry run mode - would build jekyll-theme-zer0-${VERSION}.gem"
109
+ else
110
+ if gem build jekyll-theme-zer0.gemspec; then
111
+ # Move gem to build directory
112
+ mv jekyll-theme-zer0-${VERSION}.gem build/
113
+ info "✓ Successfully built jekyll-theme-zer0-${VERSION}.gem"
114
+ else
115
+ error "Failed to build gem"
116
+ fi
117
+ fi
118
+
119
+ # List gem contents for verification
120
+ if [[ "$DRY_RUN" != true ]] && [[ -f "build/jekyll-theme-zer0-${VERSION}.gem" ]]; then
121
+ log "Gem contents:"
122
+ # Use tar to list contents since gem contents only works for installed gems
123
+ tar -tzf build/jekyll-theme-zer0-${VERSION}.gem | head -20
124
+ echo "..."
125
+ echo "Total files: $(tar -tzf build/jekyll-theme-zer0-${VERSION}.gem | wc -l)"
126
+ fi
127
+
128
+ # Check if we should publish
129
+ if [[ "$PUBLISH" == true ]]; then
130
+ if [[ "$DRY_RUN" == true ]]; then
131
+ log "Dry run mode - would publish jekyll-theme-zer0-${VERSION}.gem to RubyGems"
132
+ else
133
+ log "Publishing gem to RubyGems..."
134
+
135
+ # Check if user is authenticated with RubyGems
136
+ if [[ ! -f ~/.gem/credentials ]]; then
137
+ error "Not authenticated with RubyGems. Run 'gem signin' first."
138
+ fi
139
+
140
+ # Check if this version already exists on RubyGems
141
+ if gem list --remote jekyll-theme-zer0 | grep -q "jekyll-theme-zer0 (${VERSION})"; then
142
+ warn "Version ${VERSION} already exists on RubyGems"
143
+ echo -e "${YELLOW}You need to bump the version first. Use ./scripts/version.sh --bump [--major|--minor|--patch]${NC}"
144
+ error "Cannot republish existing version ${VERSION}"
145
+ fi
146
+
147
+ # Confirm publication
148
+ echo -e "${YELLOW}Are you sure you want to publish jekyll-theme-zer0-${VERSION}.gem to RubyGems? (y/N)${NC}"
149
+ read -r response
150
+ if [[ "$response" =~ ^[Yy]$ ]]; then
151
+ if gem push build/jekyll-theme-zer0-${VERSION}.gem; then
152
+ info "✓ Successfully published jekyll-theme-zer0-${VERSION}.gem"
153
+ log "Gem is now available at: https://rubygems.org/gems/jekyll-theme-zer0"
154
+ else
155
+ error "Failed to publish gem"
156
+ fi
157
+ else
158
+ log "Publication cancelled"
159
+ fi
160
+ fi
161
+ else
162
+ log "Build complete! Gem file: jekyll-theme-zer0-${VERSION}.gem"
163
+ log "To publish, run: ./scripts/build.sh --publish"
164
+ fi
165
+
166
+ # Cleanup option
167
+ if [[ "$PUBLISH" == true ]] && [[ "$DRY_RUN" != true ]]; then
168
+ echo -e "${YELLOW}Remove local gem file? (y/N)${NC}"
169
+ read -r response
170
+ if [[ "$response" =~ ^[Yy]$ ]]; then
171
+ rm -f build/jekyll-theme-zer0-${VERSION}.gem
172
+ log "Local gem file removed"
173
+ fi
174
+ fi