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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +272 -3
- data/README.md +83 -21
- data/_data/README.md +4 -5
- data/_includes/README.md +1 -1
- data/_includes/stats/README.md +14 -2
- data/_layouts/README.md +3 -3
- data/_plugins/preview_image_generator.rb +258 -0
- data/_plugins/theme_version.rb +88 -0
- data/_sass/core/_theme.scss +4 -1
- data/assets/images/previews/git-workflow-best-practices-for-modern-teams.png +0 -0
- data/scripts/README.md +443 -0
- data/scripts/analyze-commits.sh +313 -0
- data/scripts/bin/build +115 -0
- data/scripts/bin/release +240 -0
- data/scripts/bin/test +203 -0
- data/scripts/build +115 -0
- data/scripts/example-usage.sh +102 -0
- data/scripts/features/generate-preview-images +846 -0
- data/scripts/features/install-preview-generator +531 -0
- data/scripts/features/preview_generator.py +646 -0
- data/scripts/fix-markdown-format.sh +265 -0
- data/scripts/generate-preview-images.sh +791 -0
- data/scripts/install-preview-generator.sh +531 -0
- data/scripts/lib/README.md +291 -0
- data/scripts/lib/changelog.sh +313 -0
- data/scripts/lib/common.sh +154 -0
- data/scripts/lib/gem.sh +226 -0
- data/scripts/lib/git.sh +205 -0
- data/scripts/lib/preview_generator.py +646 -0
- data/scripts/lib/test/run_tests.sh +140 -0
- data/scripts/lib/test/test_changelog.sh +87 -0
- data/scripts/lib/test/test_gem.sh +68 -0
- data/scripts/lib/test/test_git.sh +82 -0
- data/scripts/lib/test/test_validation.sh +72 -0
- data/scripts/lib/test/test_version.sh +96 -0
- data/scripts/lib/validation.sh +139 -0
- data/scripts/lib/version.sh +178 -0
- data/scripts/release +240 -0
- data/scripts/setup.sh +155 -0
- data/scripts/test/integration/auto-version +243 -0
- data/scripts/test/integration/mermaid +252 -0
- data/scripts/test/lib/run_tests.sh +151 -0
- data/scripts/test/lib/test_changelog.sh +90 -0
- data/scripts/test/lib/test_gem.sh +71 -0
- data/scripts/test/lib/test_git.sh +85 -0
- data/scripts/test/lib/test_validation.sh +75 -0
- data/scripts/test/lib/test_version.sh +101 -0
- data/scripts/test/theme/validate +120 -0
- data/scripts/test-auto-version.sh +260 -0
- data/scripts/test-mermaid.sh +251 -0
- data/scripts/test.sh +156 -0
- data/scripts/utils/analyze-commits +300 -0
- data/scripts/utils/fix-markdown +251 -0
- data/scripts/utils/setup +137 -0
- data/scripts/version.sh +178 -0
- 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
|
data/_sass/core/_theme.scss
CHANGED
|
@@ -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
|