jekyll-theme-zer0 0.7.2 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +272 -3
  3. data/README.md +83 -21
  4. data/_data/README.md +4 -5
  5. data/_includes/README.md +1 -1
  6. data/_includes/stats/README.md +14 -2
  7. data/_layouts/README.md +3 -3
  8. data/_plugins/preview_image_generator.rb +258 -0
  9. data/_plugins/theme_version.rb +88 -0
  10. data/_sass/core/_theme.scss +4 -1
  11. data/assets/images/previews/git-workflow-best-practices-for-modern-teams.png +0 -0
  12. data/scripts/README.md +443 -0
  13. data/scripts/analyze-commits.sh +313 -0
  14. data/scripts/bin/build +115 -0
  15. data/scripts/bin/release +240 -0
  16. data/scripts/bin/test +203 -0
  17. data/scripts/build +115 -0
  18. data/scripts/example-usage.sh +102 -0
  19. data/scripts/features/generate-preview-images +846 -0
  20. data/scripts/features/install-preview-generator +531 -0
  21. data/scripts/features/preview_generator.py +646 -0
  22. data/scripts/fix-markdown-format.sh +265 -0
  23. data/scripts/generate-preview-images.sh +791 -0
  24. data/scripts/install-preview-generator.sh +531 -0
  25. data/scripts/lib/README.md +291 -0
  26. data/scripts/lib/changelog.sh +313 -0
  27. data/scripts/lib/common.sh +154 -0
  28. data/scripts/lib/gem.sh +226 -0
  29. data/scripts/lib/git.sh +205 -0
  30. data/scripts/lib/preview_generator.py +646 -0
  31. data/scripts/lib/test/run_tests.sh +140 -0
  32. data/scripts/lib/test/test_changelog.sh +87 -0
  33. data/scripts/lib/test/test_gem.sh +68 -0
  34. data/scripts/lib/test/test_git.sh +82 -0
  35. data/scripts/lib/test/test_validation.sh +72 -0
  36. data/scripts/lib/test/test_version.sh +96 -0
  37. data/scripts/lib/validation.sh +139 -0
  38. data/scripts/lib/version.sh +178 -0
  39. data/scripts/release +240 -0
  40. data/scripts/setup.sh +155 -0
  41. data/scripts/test/integration/auto-version +243 -0
  42. data/scripts/test/integration/mermaid +252 -0
  43. data/scripts/test/lib/run_tests.sh +151 -0
  44. data/scripts/test/lib/test_changelog.sh +90 -0
  45. data/scripts/test/lib/test_gem.sh +71 -0
  46. data/scripts/test/lib/test_git.sh +85 -0
  47. data/scripts/test/lib/test_validation.sh +75 -0
  48. data/scripts/test/lib/test_version.sh +101 -0
  49. data/scripts/test/theme/validate +120 -0
  50. data/scripts/test-auto-version.sh +260 -0
  51. data/scripts/test-mermaid.sh +251 -0
  52. data/scripts/test.sh +156 -0
  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 +178 -0
  57. metadata +50 -2
@@ -0,0 +1,258 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # File: preview_image_generator.rb
5
+ # Path: _plugins/preview_image_generator.rb
6
+ # Purpose: Jekyll plugin for AI-powered preview image generation
7
+ #
8
+ # This plugin provides Jekyll integration for the preview image generator,
9
+ # including Liquid tags, filters, and hooks for automatic image generation.
10
+ #
11
+ # Usage in templates:
12
+ # {% preview_image_status %} - Shows missing preview count
13
+ # {{ page | preview_image_path }} - Returns the preview image path
14
+ # {{ page | has_preview_image }} - Returns true/false
15
+ #
16
+ # Configuration in _config.yml:
17
+ # preview_images:
18
+ # enabled: true
19
+ # provider: openai
20
+ # auto_generate: false # Set to true to generate during build (slow!)
21
+ # style: "retro pixel art, 8-bit video game aesthetic"
22
+ #
23
+
24
+ module Jekyll
25
+ module PreviewImageGenerator
26
+ # Configuration defaults
27
+ DEFAULTS = {
28
+ 'enabled' => true,
29
+ 'provider' => 'openai',
30
+ 'model' => 'dall-e-3',
31
+ 'size' => '1792x1024',
32
+ 'quality' => 'standard',
33
+ 'style' => 'retro pixel art, 8-bit video game aesthetic, vibrant colors, nostalgic, clean pixel graphics',
34
+ 'style_modifiers' => 'pixelated, retro gaming style, CRT screen glow effect, limited color palette',
35
+ 'output_dir' => 'assets/images/previews',
36
+ 'auto_generate' => false,
37
+ 'collections' => ['posts', 'docs', 'quickstart']
38
+ }.freeze
39
+
40
+ # Get configuration with defaults
41
+ def self.config(site)
42
+ site_config = site.config['preview_images'] || {}
43
+ DEFAULTS.merge(site_config)
44
+ end
45
+
46
+ # Check if a document has a preview image defined
47
+ def self.has_preview?(doc)
48
+ preview = doc.data['preview']
49
+ return false if preview.nil? || preview.to_s.strip.empty?
50
+
51
+ # Check if the preview file actually exists
52
+ site = doc.site
53
+ config = self.config(site)
54
+
55
+ # Build the full path
56
+ preview_path = if preview.start_with?('/')
57
+ File.join(site.source, preview)
58
+ elsif preview.start_with?('http')
59
+ return true # External URL, assume it exists
60
+ else
61
+ File.join(site.source, config['output_dir'], preview)
62
+ end
63
+
64
+ File.exist?(preview_path)
65
+ end
66
+
67
+ # Get the preview image path for a document
68
+ def self.preview_path(doc)
69
+ preview = doc.data['preview']
70
+ return nil if preview.nil? || preview.to_s.strip.empty?
71
+
72
+ site = doc.site
73
+ config = self.config(site)
74
+
75
+ # If it's already a full path or URL, return as-is
76
+ return preview if preview.start_with?('/') || preview.start_with?('http')
77
+
78
+ # Build relative path from output_dir
79
+ "#{config['output_dir']}/#{preview}"
80
+ end
81
+
82
+ # Get list of documents missing preview images
83
+ def self.missing_previews(site)
84
+ config = self.config(site)
85
+ missing = []
86
+
87
+ config['collections'].each do |collection_name|
88
+ collection = site.collections[collection_name]
89
+ next unless collection
90
+
91
+ collection.docs.each do |doc|
92
+ unless has_preview?(doc)
93
+ missing << {
94
+ 'path' => doc.relative_path,
95
+ 'title' => doc.data['title'] || File.basename(doc.relative_path),
96
+ 'collection' => collection_name
97
+ }
98
+ end
99
+ end
100
+ end
101
+
102
+ # Also check posts (which are special in Jekyll)
103
+ site.posts.docs.each do |doc|
104
+ unless has_preview?(doc)
105
+ missing << {
106
+ 'path' => doc.relative_path,
107
+ 'title' => doc.data['title'] || File.basename(doc.relative_path),
108
+ 'collection' => 'posts'
109
+ }
110
+ end
111
+ end
112
+
113
+ missing.uniq { |m| m['path'] }
114
+ end
115
+
116
+ # Generate a preview image filename from document
117
+ def self.generate_filename(doc)
118
+ # Use the document's slug or generate from title
119
+ slug = doc.data['slug'] || doc.basename_without_ext
120
+
121
+ # Sanitize the slug for use as filename
122
+ sanitized = slug.to_s.downcase
123
+ .gsub(/[^a-z0-9\-_]/, '-')
124
+ .gsub(/-+/, '-')
125
+ .gsub(/^-|-$/, '')
126
+
127
+ "#{sanitized}-preview.png"
128
+ end
129
+ end
130
+
131
+ # ==========================================================================
132
+ # Liquid Filters
133
+ # ==========================================================================
134
+
135
+ module PreviewImageFilters
136
+ # Check if a page/document has a preview image
137
+ # Usage: {{ page | has_preview_image }}
138
+ def has_preview_image(doc)
139
+ return false unless doc.is_a?(Hash) || doc.respond_to?(:data)
140
+
141
+ # Handle both Hash (from assign) and Document objects
142
+ if doc.is_a?(Hash)
143
+ preview = doc['preview']
144
+ !preview.nil? && !preview.to_s.strip.empty?
145
+ else
146
+ PreviewImageGenerator.has_preview?(doc)
147
+ end
148
+ end
149
+
150
+ # Get the preview image path
151
+ # Usage: {{ page | preview_image_path }}
152
+ def preview_image_path(doc)
153
+ return nil unless doc.is_a?(Hash) || doc.respond_to?(:data)
154
+
155
+ if doc.is_a?(Hash)
156
+ preview = doc['preview']
157
+ return nil if preview.nil? || preview.to_s.strip.empty?
158
+
159
+ # Get config from context if available
160
+ site_config = @context.registers[:site].config['preview_images'] || {}
161
+ output_dir = site_config['output_dir'] || 'assets/images/previews'
162
+
163
+ return preview if preview.start_with?('/') || preview.start_with?('http')
164
+ "#{output_dir}/#{preview}"
165
+ else
166
+ PreviewImageGenerator.preview_path(doc)
167
+ end
168
+ end
169
+
170
+ # Get suggested filename for a preview image
171
+ # Usage: {{ page | preview_filename }}
172
+ def preview_filename(doc)
173
+ return nil unless doc.respond_to?(:data) || doc.respond_to?(:basename_without_ext)
174
+ PreviewImageGenerator.generate_filename(doc)
175
+ end
176
+ end
177
+
178
+ # ==========================================================================
179
+ # Liquid Tags
180
+ # ==========================================================================
181
+
182
+ # Tag to display preview image status/count
183
+ # Usage: {% preview_image_status %}
184
+ class PreviewImageStatusTag < Liquid::Tag
185
+ def render(context)
186
+ site = context.registers[:site]
187
+ missing = PreviewImageGenerator.missing_previews(site)
188
+
189
+ if missing.empty?
190
+ "<span class=\"badge bg-success\">All preview images present</span>"
191
+ else
192
+ "<span class=\"badge bg-warning text-dark\">#{missing.length} missing preview images</span>"
193
+ end
194
+ end
195
+ end
196
+
197
+ # Tag to list missing preview images
198
+ # Usage: {% preview_images_missing %}
199
+ class PreviewImagesMissingTag < Liquid::Tag
200
+ def render(context)
201
+ site = context.registers[:site]
202
+ missing = PreviewImageGenerator.missing_previews(site)
203
+
204
+ return "<p>All documents have preview images!</p>" if missing.empty?
205
+
206
+ html = "<ul class=\"list-group\">\n"
207
+ missing.each do |item|
208
+ html += " <li class=\"list-group-item d-flex justify-content-between align-items-center\">\n"
209
+ html += " <span>#{item['title']}</span>\n"
210
+ html += " <span class=\"badge bg-secondary\">#{item['collection']}</span>\n"
211
+ html += " </li>\n"
212
+ end
213
+ html += "</ul>"
214
+ html
215
+ end
216
+ end
217
+
218
+ # ==========================================================================
219
+ # Generator Hook (optional auto-generation during build)
220
+ # ==========================================================================
221
+
222
+ class PreviewImageGeneratorHook < Generator
223
+ safe true
224
+ priority :low
225
+
226
+ def generate(site)
227
+ config = PreviewImageGenerator.config(site)
228
+
229
+ return unless config['enabled']
230
+
231
+ # Store missing previews in site data for access in templates
232
+ site.data['preview_images_missing'] = PreviewImageGenerator.missing_previews(site)
233
+ site.data['preview_images_config'] = config
234
+
235
+ # Log status
236
+ missing_count = site.data['preview_images_missing'].length
237
+ if missing_count > 0
238
+ Jekyll.logger.info "Preview Images:", "#{missing_count} documents missing preview images"
239
+ Jekyll.logger.info "Preview Images:", "Run 'scripts/generate-preview-images.sh' to generate them"
240
+ end
241
+
242
+ # Auto-generate is disabled by default (it's slow and requires API calls)
243
+ # Users should run the shell script manually or via CI/CD
244
+ if config['auto_generate']
245
+ Jekyll.logger.warn "Preview Images:", "Auto-generation is enabled but not implemented in plugin"
246
+ Jekyll.logger.warn "Preview Images:", "Use 'scripts/generate-preview-images.sh' instead"
247
+ end
248
+ end
249
+ end
250
+
251
+ # ==========================================================================
252
+ # Register Liquid components
253
+ # ==========================================================================
254
+
255
+ Liquid::Template.register_filter(PreviewImageFilters)
256
+ Liquid::Template.register_tag('preview_image_status', PreviewImageStatusTag)
257
+ Liquid::Template.register_tag('preview_images_missing', PreviewImagesMissingTag)
258
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # File: theme_version.rb
5
+ # Path: _plugins/theme_version.rb
6
+ # Purpose: Automatically extract theme version from gem specification
7
+ #
8
+ # This plugin runs during Jekyll build and extracts version information
9
+ # from the active theme's gemspec, making it available as site.theme_specs
10
+ #
11
+ # Usage in templates: {{ site.theme_specs | where: "name", "theme-name" | map: "version" | first }}
12
+ #
13
+
14
+ module Jekyll
15
+ class ThemeVersionGenerator < Generator
16
+ safe true
17
+ priority :high
18
+
19
+ def generate(site)
20
+ theme_specs = []
21
+
22
+ # Try to get version from remote_theme or local theme
23
+ if site.config['remote_theme']
24
+ # For remote themes, we'll rely on the theme-info.html to show "Latest"
25
+ # since we can't easily get the version without cloning the repo
26
+ remote_theme = site.config['remote_theme']
27
+ theme_specs << {
28
+ 'name' => remote_theme.split('/').last,
29
+ 'type' => 'remote',
30
+ 'repository' => remote_theme,
31
+ 'version' => 'latest'
32
+ }
33
+ elsif site.config['theme']
34
+ # For local gem themes, try to extract version from Gem specification
35
+ theme_name = site.config['theme']
36
+
37
+ begin
38
+ # Attempt to load the gem specification
39
+ require 'rubygems'
40
+ spec = Gem::Specification.find_by_name(theme_name)
41
+
42
+ if spec
43
+ theme_specs << {
44
+ 'name' => spec.name,
45
+ 'version' => spec.version.to_s,
46
+ 'type' => 'gem',
47
+ 'homepage' => spec.homepage,
48
+ 'summary' => spec.summary,
49
+ 'authors' => spec.authors
50
+ }
51
+ end
52
+ rescue Gem::LoadError
53
+ # Theme gem not found, just record basic info
54
+ theme_specs << {
55
+ 'name' => theme_name,
56
+ 'version' => 'unknown',
57
+ 'type' => 'gem'
58
+ }
59
+ end
60
+ end
61
+
62
+ # Also scan for jekyll-theme-* gems that might be installed
63
+ begin
64
+ Gem::Specification.each do |spec|
65
+ if spec.name =~ /^jekyll-theme-/
66
+ theme_specs << {
67
+ 'name' => spec.name,
68
+ 'version' => spec.version.to_s,
69
+ 'type' => 'gem',
70
+ 'homepage' => spec.homepage,
71
+ 'summary' => spec.summary
72
+ }
73
+ end
74
+ end
75
+ rescue => e
76
+ Jekyll.logger.warn "ThemeVersion:", "Could not scan gems: #{e.message}"
77
+ end
78
+
79
+ # Make theme specs available to templates
80
+ site.config['theme_specs'] = theme_specs
81
+
82
+ # Log the theme information
83
+ theme_specs.each do |spec|
84
+ Jekyll.logger.info "ThemeVersion:", "#{spec['name']} v#{spec['version']} (#{spec['type']})"
85
+ end
86
+ end
87
+ end
88
+ end
@@ -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