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,531 @@
1
+ #!/bin/bash
2
+ #
3
+ # Script Name: install-preview-generator.sh
4
+ # Description: Install the AI Preview Image Generator feature into a Jekyll site
5
+ # using the zer0-mistakes theme. This script copies required files,
6
+ # updates configuration, and sets up environment variables.
7
+ #
8
+ # Usage:
9
+ # curl -fsSL https://raw.githubusercontent.com/bamr87/zer0-mistakes/main/scripts/install-preview-generator.sh | bash
10
+ # OR
11
+ # ./scripts/install-preview-generator.sh [options]
12
+ #
13
+ # Options:
14
+ # -h, --help Show this help message
15
+ # -d, --dry-run Preview what would be installed (no changes)
16
+ # -f, --force Overwrite existing files
17
+ # -p, --provider PROVIDER Set default AI provider (openai, stability, local)
18
+ # --no-config Skip _config.yml modification
19
+ # --no-tasks Skip VS Code tasks installation
20
+ #
21
+ # Requirements:
22
+ # - Jekyll site using zer0-mistakes theme
23
+ # - curl and jq installed
24
+ # - Git repository (for version tracking)
25
+ #
26
+
27
+ set -euo pipefail
28
+
29
+ # =============================================================================
30
+ # Configuration
31
+ # =============================================================================
32
+
33
+ SCRIPT_NAME="install-preview-generator.sh"
34
+ VERSION="1.0.0"
35
+
36
+ # Repository URLs
37
+ REPO_OWNER="bamr87"
38
+ REPO_NAME="zer0-mistakes"
39
+ REPO_URL="https://github.com/${REPO_OWNER}/${REPO_NAME}"
40
+ RAW_URL="https://raw.githubusercontent.com/${REPO_OWNER}/${REPO_NAME}/main"
41
+
42
+ # Files to install
43
+ declare -a SCRIPT_FILES=(
44
+ "scripts/generate-preview-images.sh"
45
+ "scripts/lib/preview_generator.py"
46
+ )
47
+
48
+ declare -a PLUGIN_FILES=(
49
+ "_plugins/preview_image_generator.rb"
50
+ )
51
+
52
+ # Default options
53
+ DRY_RUN=false
54
+ FORCE=false
55
+ DEFAULT_PROVIDER="openai"
56
+ INSTALL_CONFIG=true
57
+ INSTALL_TASKS=true
58
+
59
+ # Colors for output
60
+ RED='\033[0;31m'
61
+ GREEN='\033[0;32m'
62
+ YELLOW='\033[1;33m'
63
+ BLUE='\033[0;34m'
64
+ CYAN='\033[0;36m'
65
+ NC='\033[0m'
66
+
67
+ # =============================================================================
68
+ # Logging Functions
69
+ # =============================================================================
70
+
71
+ log() { echo -e "${GREEN}[✓]${NC} $1"; }
72
+ info() { echo -e "${BLUE}[ℹ]${NC} $1"; }
73
+ step() { echo -e "${CYAN}[→]${NC} $1"; }
74
+ warn() { echo -e "${YELLOW}[⚠]${NC} $1"; }
75
+ error() { echo -e "${RED}[✗]${NC} $1" >&2; }
76
+ dry_run_log() { echo -e "${YELLOW}[DRY-RUN]${NC} $1"; }
77
+
78
+ # =============================================================================
79
+ # Helper Functions
80
+ # =============================================================================
81
+
82
+ show_help() {
83
+ cat << EOF
84
+ ${CYAN}═══════════════════════════════════════════════════════════════════${NC}
85
+ ${GREEN}AI Preview Image Generator Installer${NC}
86
+ ${BLUE}Part of the zer0-mistakes Jekyll theme${NC}
87
+ ${CYAN}═══════════════════════════════════════════════════════════════════${NC}
88
+
89
+ ${YELLOW}USAGE:${NC}
90
+ $SCRIPT_NAME [OPTIONS]
91
+
92
+ ${YELLOW}OPTIONS:${NC}
93
+ -h, --help Show this help message
94
+ -d, --dry-run Preview what would be installed (no changes)
95
+ -f, --force Overwrite existing files
96
+ -p, --provider PROVIDER Set default AI provider (openai, stability, local)
97
+ --no-config Skip _config.yml modification
98
+ --no-tasks Skip VS Code tasks installation
99
+
100
+ ${YELLOW}EXAMPLES:${NC}
101
+ # Install with defaults
102
+ ./$SCRIPT_NAME
103
+
104
+ # Preview installation
105
+ ./$SCRIPT_NAME --dry-run
106
+
107
+ # Install with Stability AI as default provider
108
+ ./$SCRIPT_NAME --provider stability
109
+
110
+ # Force reinstall
111
+ ./$SCRIPT_NAME --force
112
+
113
+ ${YELLOW}REMOTE INSTALLATION:${NC}
114
+ curl -fsSL ${RAW_URL}/scripts/$SCRIPT_NAME | bash
115
+
116
+ ${YELLOW}AFTER INSTALLATION:${NC}
117
+ 1. Set your API key in .env file:
118
+ OPENAI_API_KEY=your-key-here
119
+
120
+ 2. Generate preview images:
121
+ ./scripts/generate-preview-images.sh --list-missing
122
+ ./scripts/generate-preview-images.sh --dry-run
123
+ ./scripts/generate-preview-images.sh
124
+
125
+ ${YELLOW}DOCUMENTATION:${NC}
126
+ ${REPO_URL}/blob/main/docs/features/preview-image-generator.md
127
+
128
+ EOF
129
+ }
130
+
131
+ # Check if we're in a Jekyll site
132
+ check_jekyll_site() {
133
+ if [[ ! -f "_config.yml" ]]; then
134
+ error "Not a Jekyll site (no _config.yml found)"
135
+ error "Please run this script from your Jekyll site root directory"
136
+ exit 1
137
+ fi
138
+ log "Found Jekyll site"
139
+ }
140
+
141
+ # Check dependencies
142
+ check_dependencies() {
143
+ local missing=()
144
+
145
+ for cmd in curl jq; do
146
+ if ! command -v "$cmd" &> /dev/null; then
147
+ missing+=("$cmd")
148
+ fi
149
+ done
150
+
151
+ if [[ ${#missing[@]} -gt 0 ]]; then
152
+ error "Missing required dependencies: ${missing[*]}"
153
+ info "Install them with:"
154
+ info " macOS: brew install ${missing[*]}"
155
+ info " Ubuntu: sudo apt-get install ${missing[*]}"
156
+ exit 1
157
+ fi
158
+
159
+ log "All dependencies satisfied"
160
+ }
161
+
162
+ # Download a file from the repository
163
+ download_file() {
164
+ local remote_path="$1"
165
+ local local_path="$2"
166
+ local url="${RAW_URL}/${remote_path}"
167
+
168
+ if [[ "$DRY_RUN" == true ]]; then
169
+ dry_run_log "Would download: $url → $local_path"
170
+ return 0
171
+ fi
172
+
173
+ # Create directory if needed
174
+ local dir=$(dirname "$local_path")
175
+ if [[ ! -d "$dir" ]]; then
176
+ mkdir -p "$dir"
177
+ fi
178
+
179
+ # Check if file exists and not forcing
180
+ if [[ -f "$local_path" && "$FORCE" != true ]]; then
181
+ warn "File exists, skipping: $local_path (use --force to overwrite)"
182
+ return 0
183
+ fi
184
+
185
+ step "Downloading: $remote_path"
186
+ if curl -fsSL "$url" -o "$local_path"; then
187
+ log "Installed: $local_path"
188
+
189
+ # Make scripts executable
190
+ if [[ "$local_path" == *.sh ]]; then
191
+ chmod +x "$local_path"
192
+ fi
193
+ return 0
194
+ else
195
+ error "Failed to download: $url"
196
+ return 1
197
+ fi
198
+ }
199
+
200
+ # Add configuration to _config.yml
201
+ update_config() {
202
+ if [[ "$INSTALL_CONFIG" != true ]]; then
203
+ info "Skipping config update (--no-config)"
204
+ return 0
205
+ fi
206
+
207
+ # Check if preview_images section already exists
208
+ if grep -q "^preview_images:" "_config.yml" 2>/dev/null; then
209
+ warn "preview_images section already exists in _config.yml"
210
+ info "You may need to merge settings manually"
211
+ return 0
212
+ fi
213
+
214
+ if [[ "$DRY_RUN" == true ]]; then
215
+ dry_run_log "Would add preview_images config to _config.yml"
216
+ return 0
217
+ fi
218
+
219
+ step "Adding preview_images configuration to _config.yml"
220
+
221
+ cat >> "_config.yml" << EOF
222
+
223
+ # =============================================================================
224
+ # AI Preview Image Generator Configuration
225
+ # Feature: ZER0-003
226
+ # Documentation: ${REPO_URL}/blob/main/docs/features/preview-image-generator.md
227
+ # =============================================================================
228
+ preview_images:
229
+ enabled: true
230
+ provider: ${DEFAULT_PROVIDER} # openai, stability, or local
231
+ model: dall-e-3 # OpenAI model to use
232
+ size: "1792x1024" # Landscape banner size
233
+ quality: standard # standard or hd
234
+ style: "retro pixel art, 8-bit video game aesthetic, vibrant colors, nostalgic, clean pixel graphics"
235
+ style_modifiers: "pixelated, retro gaming style, CRT screen glow effect, limited color palette"
236
+ output_dir: assets/images/previews # Where to save generated images
237
+ auto_generate: false # Generate during build (slow, use script instead)
238
+ collections: # Collections to scan for missing previews
239
+ - posts
240
+ - docs
241
+ - quickstart
242
+ EOF
243
+
244
+ log "Added preview_images configuration"
245
+ }
246
+
247
+ # Create .env.example if it doesn't exist
248
+ create_env_example() {
249
+ local env_example=".env.example"
250
+
251
+ if [[ -f "$env_example" ]]; then
252
+ # Check if our keys are already there
253
+ if grep -q "OPENAI_API_KEY" "$env_example"; then
254
+ info ".env.example already contains preview generator keys"
255
+ return 0
256
+ fi
257
+ fi
258
+
259
+ if [[ "$DRY_RUN" == true ]]; then
260
+ dry_run_log "Would add API keys to .env.example"
261
+ return 0
262
+ fi
263
+
264
+ step "Updating .env.example"
265
+
266
+ cat >> "$env_example" << 'EOF'
267
+
268
+ # AI Preview Image Generator API Keys
269
+ # Get your key from: https://platform.openai.com/api-keys
270
+ OPENAI_API_KEY=your-openai-api-key-here
271
+
272
+ # Stability AI (alternative provider)
273
+ # Get your key from: https://platform.stability.ai/
274
+ STABILITY_API_KEY=your-stability-api-key-here
275
+ EOF
276
+
277
+ log "Updated .env.example"
278
+ }
279
+
280
+ # Update .gitignore
281
+ update_gitignore() {
282
+ local gitignore=".gitignore"
283
+
284
+ if [[ ! -f "$gitignore" ]]; then
285
+ touch "$gitignore"
286
+ fi
287
+
288
+ # Check if .env is already ignored
289
+ if grep -q "^\.env$" "$gitignore" 2>/dev/null; then
290
+ info ".env already in .gitignore"
291
+ return 0
292
+ fi
293
+
294
+ if [[ "$DRY_RUN" == true ]]; then
295
+ dry_run_log "Would add .env to .gitignore"
296
+ return 0
297
+ fi
298
+
299
+ step "Adding .env to .gitignore"
300
+ echo ".env" >> "$gitignore"
301
+ log "Updated .gitignore"
302
+ }
303
+
304
+ # Install VS Code tasks
305
+ install_vscode_tasks() {
306
+ if [[ "$INSTALL_TASKS" != true ]]; then
307
+ info "Skipping VS Code tasks (--no-tasks)"
308
+ return 0
309
+ fi
310
+
311
+ local tasks_file=".vscode/tasks.json"
312
+
313
+ if [[ "$DRY_RUN" == true ]]; then
314
+ dry_run_log "Would create/update VS Code tasks in $tasks_file"
315
+ return 0
316
+ fi
317
+
318
+ step "Installing VS Code tasks"
319
+
320
+ # Create .vscode directory if needed
321
+ mkdir -p .vscode
322
+
323
+ # If tasks.json doesn't exist, create a new one
324
+ if [[ ! -f "$tasks_file" ]]; then
325
+ cat > "$tasks_file" << 'EOF'
326
+ {
327
+ "version": "2.0.0",
328
+ "tasks": []
329
+ }
330
+ EOF
331
+ fi
332
+
333
+ # Check if our tasks already exist
334
+ if grep -q "Preview Images:" "$tasks_file" 2>/dev/null; then
335
+ warn "Preview image tasks already exist in tasks.json"
336
+ return 0
337
+ fi
338
+
339
+ # Add our tasks using jq
340
+ local new_tasks='[
341
+ {
342
+ "label": "🖼️ Preview Images: List Missing",
343
+ "type": "shell",
344
+ "command": "./scripts/generate-preview-images.sh",
345
+ "args": ["--list-missing"],
346
+ "group": "test",
347
+ "problemMatcher": []
348
+ },
349
+ {
350
+ "label": "🖼️ Preview Images: Dry Run",
351
+ "type": "shell",
352
+ "command": "./scripts/generate-preview-images.sh",
353
+ "args": ["--dry-run", "--verbose"],
354
+ "group": "test",
355
+ "problemMatcher": []
356
+ },
357
+ {
358
+ "label": "🖼️ Preview Images: Generate for Posts",
359
+ "type": "shell",
360
+ "command": "./scripts/generate-preview-images.sh",
361
+ "args": ["--collection", "posts", "--verbose"],
362
+ "group": "build",
363
+ "problemMatcher": []
364
+ },
365
+ {
366
+ "label": "🖼️ Preview Images: Generate All",
367
+ "type": "shell",
368
+ "command": "./scripts/generate-preview-images.sh",
369
+ "args": ["--verbose"],
370
+ "group": "build",
371
+ "problemMatcher": []
372
+ }
373
+ ]'
374
+
375
+ # Merge tasks
376
+ local temp_file=$(mktemp)
377
+ jq --argjson new "$new_tasks" '.tasks += $new' "$tasks_file" > "$temp_file" && mv "$temp_file" "$tasks_file"
378
+
379
+ log "Added VS Code tasks"
380
+ }
381
+
382
+ # Create output directory
383
+ create_output_directory() {
384
+ local output_dir="assets/images/previews"
385
+
386
+ if [[ -d "$output_dir" ]]; then
387
+ info "Output directory already exists: $output_dir"
388
+ return 0
389
+ fi
390
+
391
+ if [[ "$DRY_RUN" == true ]]; then
392
+ dry_run_log "Would create directory: $output_dir"
393
+ return 0
394
+ fi
395
+
396
+ step "Creating output directory: $output_dir"
397
+ mkdir -p "$output_dir"
398
+
399
+ # Add a placeholder .gitkeep
400
+ touch "$output_dir/.gitkeep"
401
+
402
+ log "Created output directory"
403
+ }
404
+
405
+ # Print post-installation instructions
406
+ print_instructions() {
407
+ echo ""
408
+ echo -e "${CYAN}═══════════════════════════════════════════════════════════════════${NC}"
409
+ echo -e " ${GREEN}✓ AI Preview Image Generator Installed Successfully!${NC}"
410
+ echo -e "${CYAN}═══════════════════════════════════════════════════════════════════${NC}"
411
+ echo ""
412
+ echo -e "${YELLOW}NEXT STEPS:${NC}"
413
+ echo ""
414
+ echo " 1. ${BLUE}Set up your API key:${NC}"
415
+ echo " cp .env.example .env"
416
+ echo " # Edit .env and add your OPENAI_API_KEY"
417
+ echo ""
418
+ echo " 2. ${BLUE}Check for missing preview images:${NC}"
419
+ echo " ./scripts/generate-preview-images.sh --list-missing"
420
+ echo ""
421
+ echo " 3. ${BLUE}Preview what would be generated:${NC}"
422
+ echo " ./scripts/generate-preview-images.sh --dry-run --verbose"
423
+ echo ""
424
+ echo " 4. ${BLUE}Generate preview images:${NC}"
425
+ echo " ./scripts/generate-preview-images.sh"
426
+ echo ""
427
+ echo -e "${YELLOW}VS CODE USERS:${NC}"
428
+ echo " Use Command Palette (Cmd+Shift+P) → Tasks: Run Task"
429
+ echo " Look for tasks starting with '🖼️ Preview Images:'"
430
+ echo ""
431
+ echo -e "${YELLOW}DOCUMENTATION:${NC}"
432
+ echo " ${REPO_URL}/blob/main/docs/features/preview-image-generator.md"
433
+ echo ""
434
+ echo -e "${YELLOW}CONFIGURATION:${NC}"
435
+ echo " Edit 'preview_images' section in _config.yml to customize settings"
436
+ echo ""
437
+ }
438
+
439
+ # =============================================================================
440
+ # Main Installation
441
+ # =============================================================================
442
+
443
+ main() {
444
+ echo ""
445
+ echo -e "${CYAN}═══════════════════════════════════════════════════════════════════${NC}"
446
+ echo -e " ${GREEN}AI Preview Image Generator Installer v${VERSION}${NC}"
447
+ echo -e " ${BLUE}zer0-mistakes Jekyll Theme Feature${NC}"
448
+ echo -e "${CYAN}═══════════════════════════════════════════════════════════════════${NC}"
449
+ echo ""
450
+
451
+ if [[ "$DRY_RUN" == true ]]; then
452
+ warn "DRY RUN MODE - No changes will be made"
453
+ echo ""
454
+ fi
455
+
456
+ # Validation
457
+ check_jekyll_site
458
+ check_dependencies
459
+ echo ""
460
+
461
+ # Installation steps
462
+ info "Installing scripts..."
463
+ for file in "${SCRIPT_FILES[@]}"; do
464
+ download_file "$file" "$file"
465
+ done
466
+ echo ""
467
+
468
+ info "Installing Jekyll plugin..."
469
+ for file in "${PLUGIN_FILES[@]}"; do
470
+ download_file "$file" "$file"
471
+ done
472
+ echo ""
473
+
474
+ info "Setting up configuration..."
475
+ update_config
476
+ create_env_example
477
+ update_gitignore
478
+ create_output_directory
479
+ echo ""
480
+
481
+ info "Setting up development tools..."
482
+ install_vscode_tasks
483
+ echo ""
484
+
485
+ if [[ "$DRY_RUN" != true ]]; then
486
+ print_instructions
487
+ else
488
+ echo ""
489
+ echo -e "${YELLOW}DRY RUN COMPLETE${NC}"
490
+ echo "Run without --dry-run to perform actual installation"
491
+ echo ""
492
+ fi
493
+ }
494
+
495
+ # =============================================================================
496
+ # Parse Arguments
497
+ # =============================================================================
498
+
499
+ while [[ $# -gt 0 ]]; do
500
+ case $1 in
501
+ -h|--help)
502
+ show_help
503
+ exit 0
504
+ ;;
505
+ -d|--dry-run)
506
+ DRY_RUN=true
507
+ ;;
508
+ -f|--force)
509
+ FORCE=true
510
+ ;;
511
+ -p|--provider)
512
+ DEFAULT_PROVIDER="$2"
513
+ shift
514
+ ;;
515
+ --no-config)
516
+ INSTALL_CONFIG=false
517
+ ;;
518
+ --no-tasks)
519
+ INSTALL_TASKS=false
520
+ ;;
521
+ *)
522
+ error "Unknown option: $1"
523
+ show_help
524
+ exit 1
525
+ ;;
526
+ esac
527
+ shift
528
+ done
529
+
530
+ # Run main installation
531
+ main