jekyll-imgflow 0.1.5

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 (39) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +661 -0
  3. data/README.md +214 -0
  4. data/lib/jekyll-imgflow/batch_manager.rb +263 -0
  5. data/lib/jekyll-imgflow/build_time_processor.rb +152 -0
  6. data/lib/jekyll-imgflow/config.rb +130 -0
  7. data/lib/jekyll-imgflow/filename_generator.rb +102 -0
  8. data/lib/jekyll-imgflow/helpers/http_downloader.rb +68 -0
  9. data/lib/jekyll-imgflow/hooks.rb +57 -0
  10. data/lib/jekyll-imgflow/html_generator.rb +335 -0
  11. data/lib/jekyll-imgflow/imgflow_tag.rb +247 -0
  12. data/lib/jekyll-imgflow/manifest_manager.rb +297 -0
  13. data/lib/jekyll-imgflow/operation_processor.rb +183 -0
  14. data/lib/jekyll-imgflow/parser.rb +199 -0
  15. data/lib/jekyll-imgflow/path_resolver.rb +130 -0
  16. data/lib/jekyll-imgflow/picture_tag_adaptor.rb +299 -0
  17. data/lib/jekyll-imgflow/picture_tag_preset_migrator.rb +210 -0
  18. data/lib/jekyll-imgflow/preset_manager.rb +149 -0
  19. data/lib/jekyll-imgflow/provider_registry.rb +106 -0
  20. data/lib/jekyll-imgflow/providers/base_provider.rb +198 -0
  21. data/lib/jekyll-imgflow/providers/flyimg.rb +187 -0
  22. data/lib/jekyll-imgflow/providers/imagemagick.rb +138 -0
  23. data/lib/jekyll-imgflow/providers/imgproxy.rb +164 -0
  24. data/lib/jekyll-imgflow/providers/libvips.rb +292 -0
  25. data/lib/jekyll-imgflow/providers/sharp.rb +213 -0
  26. data/lib/jekyll-imgflow/providers/weserv.rb +160 -0
  27. data/lib/jekyll-imgflow/tag_scanner.rb +227 -0
  28. data/lib/jekyll-imgflow/tags/base_tag.rb +52 -0
  29. data/lib/jekyll-imgflow/tags/crop_tag.rb +220 -0
  30. data/lib/jekyll-imgflow/tags/format_tag.rb +64 -0
  31. data/lib/jekyll-imgflow/tags/opacity_tag.rb +36 -0
  32. data/lib/jekyll-imgflow/tags/optimize_tag.rb +52 -0
  33. data/lib/jekyll-imgflow/tags/quality_tag.rb +31 -0
  34. data/lib/jekyll-imgflow/tags/resize_tag.rb +58 -0
  35. data/lib/jekyll-imgflow/tags/tag_registry.rb +70 -0
  36. data/lib/jekyll-imgflow/tags/watermark_tag.rb +51 -0
  37. data/lib/jekyll-imgflow/version.rb +5 -0
  38. data/lib/jekyll-imgflow.rb +30 -0
  39. metadata +261 -0
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_tag"
4
+
5
+ module JekyllImgFlow
6
+ module Tags
7
+ # Format tag - validates and processes format conversion
8
+ class FormatTag < BaseTag
9
+ def process(input_path, output_path, options = {})
10
+ formats = options[:formats] || [options[:format]]
11
+
12
+ # Handle case where formats is a single string instead of array
13
+ formats = Array(formats)
14
+
15
+ # Validate formats against unified config
16
+ validated_formats = formats.map { |format| validate_format(format) }
17
+ results = []
18
+
19
+ validated_formats.each do |format|
20
+ # Simple file extension replacement
21
+ last_dot = output_path.rindex(".")
22
+ format_output_path = if last_dot
23
+ output_path[0...last_dot] + ".#{format}"
24
+ else
25
+ output_path + ".#{format}"
26
+ end
27
+ ensure_output_dir(format_output_path)
28
+
29
+ # Reset provider operations before each format conversion
30
+ @provider.reset_operations
31
+ @provider.convert_format(format)
32
+ @provider.execute(input_path, format_output_path)
33
+ results << format_output_path
34
+ end
35
+
36
+ results
37
+ end
38
+
39
+ private
40
+
41
+ def validate_format(format)
42
+ raise ArgumentError, "Format cannot be nil" if format.nil?
43
+
44
+ # Get allowed formats from unified config (no fallback)
45
+ allowed_formats = @config.formats
46
+ raise ArgumentError, "No formats configured in unified config" unless allowed_formats
47
+
48
+ format_str = format.to_s.downcase
49
+
50
+ # Validate format is allowed in config
51
+ unless allowed_formats.include?(format_str)
52
+ raise ArgumentError,
53
+ "Invalid format: '#{format}'. Must be one of: #{allowed_formats.join(', ')}."
54
+ end
55
+
56
+ # Standardize format names (prefer canonical forms)
57
+ case format_str
58
+ when "jpeg" then "jpg" # Standardize to jpg
59
+ else format_str
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_tag"
4
+
5
+ module JekyllImgFlow
6
+ module Tags
7
+ # Opacity tag - validates and processes alpha channel manipulation
8
+ class OpacityTag < BaseTag
9
+ def process(input_path, output_path, options = {})
10
+ ensure_output_dir(output_path)
11
+
12
+ # Opacity must be explicitly provided (no default)
13
+ opacity = options[:opacity]
14
+ raise ArgumentError, "Opacity parameter is required" if opacity.nil?
15
+
16
+ validated_opacity = validate_opacity(opacity)
17
+
18
+ @provider.alpha_opacity = validated_opacity
19
+ @provider.execute(input_path, output_path)
20
+ output_path
21
+ end
22
+
23
+ private
24
+
25
+ def validate_opacity(value)
26
+ # Check if value is numeric before converting
27
+ raise ArgumentError, "Invalid opacity: '#{value}'. Must be between 0.01 and 0.99." unless value.to_s.match?(/\A\d*\.?\d+\z/)
28
+
29
+ opacity = value.to_f
30
+ raise ArgumentError, "Invalid opacity: '#{value}'. Must be between 0.01 and 0.99." unless opacity.between?(0.01, 0.99)
31
+
32
+ opacity
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_tag"
4
+
5
+ module JekyllImgFlow
6
+ module Tags
7
+ # Optimize tag - validates and processes optimization levels
8
+ class OptimizeTag < BaseTag
9
+ def process(input_path, output_path, options = {})
10
+ ensure_output_dir(output_path)
11
+
12
+ level = options[:level] || :medium
13
+ quality = translate_optimize_level_to_quality(level)
14
+
15
+ # Validate the translated quality
16
+ quality = validate_quality(quality)
17
+
18
+ @provider.quality = quality
19
+ @provider.execute(input_path, output_path)
20
+ end
21
+
22
+ private
23
+
24
+ def translate_optimize_level_to_quality(level)
25
+ # Use config optimize_qualities for single source of truth
26
+ optimize_configs = @provider.config.optimize_qualities || raise("No optimize_qualities configured")
27
+
28
+ level_key = level.to_s
29
+ quality = optimize_configs[level_key]
30
+
31
+ # Use configured value, or default quality for medium/high
32
+ if quality.nil? && %w[medium high].include?(level_key)
33
+ quality = @default_quality || raise("No default quality configured")
34
+ elsif quality.nil?
35
+ # Use default config for unknown levels
36
+ quality = optimize_configs["default"] || raise("No default optimize quality configured")
37
+ end
38
+
39
+ quality
40
+ end
41
+
42
+ def validate_quality(value)
43
+ return @default_quality if value.nil?
44
+
45
+ quality = value.to_i
46
+ raise ArgumentError, "Invalid quality: '#{value}'. Must be between 1 and 100." unless quality.between?(1, 100)
47
+
48
+ quality
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_tag"
4
+
5
+ module JekyllImgFlow
6
+ module Tags
7
+ # Quality tag - validates and processes quality settings
8
+ class QualityTag < BaseTag
9
+ def process(input_path, output_path, options = {})
10
+ ensure_output_dir(output_path)
11
+
12
+ # Validate quality (use default from config if not provided)
13
+ quality = validate_quality(options[:quality])
14
+
15
+ @provider.quality = quality
16
+ @provider.execute(input_path, output_path)
17
+ end
18
+
19
+ private
20
+
21
+ def validate_quality(value)
22
+ return @default_quality if value.nil?
23
+
24
+ quality = value.to_i
25
+ raise ArgumentError, "Invalid quality: '#{value}'. Must be between 1 and 100." unless quality.between?(1, 100)
26
+
27
+ quality
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_tag"
4
+
5
+ module JekyllImgFlow
6
+ module Tags
7
+ # Resize tag - validates and processes image resizing
8
+ class ResizeTag < BaseTag
9
+ def process(input_path, output_path, options = {})
10
+ ensure_output_dir(output_path)
11
+
12
+ # Validate inputs
13
+ width = validate_positive_integer(options[:width], "width")
14
+ height = validate_positive_integer(options[:height], "height")
15
+
16
+ # At least one dimension must be specified
17
+ raise ArgumentError, "Either width or height must be specified for resize operation." if width.nil? && height.nil?
18
+
19
+ # Get original dimensions
20
+ original_width, original_height = get_image_dimensions(input_path)
21
+
22
+ # Calculate missing dimension to maintain aspect ratio ONLY when one dimension is missing
23
+ if width.nil? && height
24
+ # Only height provided - calculate width to maintain aspect ratio
25
+ aspect_ratio = original_width.to_f / original_height
26
+ width = (height * aspect_ratio).round
27
+ elsif height.nil? && width
28
+ # Only width provided - calculate height to maintain aspect ratio
29
+ aspect_ratio = original_height.to_f / original_width
30
+ height = (width * aspect_ratio).round
31
+ end
32
+ # If both width and height are provided, use them as-is (allows aspect ratio changes)
33
+
34
+ # Calculate scale factors for provider
35
+ scale_x = width && original_width ? width.to_f / original_width : nil
36
+ scale_y = height && original_height ? height.to_f / original_height : nil
37
+
38
+ # Provider receives ALL data - provider chooses what to use
39
+ resize_data = {
40
+ original_width: original_width,
41
+ original_height: original_height,
42
+ target_width: width,
43
+ target_height: height,
44
+ scale_x: scale_x,
45
+ scale_y: scale_y
46
+ }
47
+
48
+ Jekyll.logger.debug "🔍 ResizeTag: About to execute provider - input: #{input_path}, output: #{output_path}"
49
+ @provider.resize(width, height, resize_data)
50
+ result = @provider.execute(input_path, output_path)
51
+ Jekyll.logger.debug "🔍 ResizeTag: Provider executed - result: #{result}, output exists: #{File.exist?(output_path)}"
52
+ result
53
+ end
54
+
55
+ # validate_positive_integer inherited from BaseTag
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_tag"
4
+
5
+ module JekyllImgFlow
6
+ module Tags
7
+ # Registry for managing tags
8
+ class TagRegistry
9
+ def self.register_tag(name, tag_class)
10
+ @tags ||= {}
11
+ @tags[name.to_sym] = tag_class
12
+ end
13
+
14
+ def self.get_tag(name)
15
+ @tags ||= {}
16
+ discover_tags unless @tags_discovered
17
+ @tags[name.to_sym]
18
+ end
19
+
20
+ def self.available_tags
21
+ @tags ||= {}
22
+ discover_tags unless @tags_discovered
23
+ @tags.keys
24
+ end
25
+
26
+ # Dynamic tag discovery
27
+ def self.discover_tags
28
+ return if @tags_discovered
29
+
30
+ @tags ||= {}
31
+ tags_dir = File.dirname(__FILE__)
32
+
33
+ Dir.glob(File.join(tags_dir, "*_tag.rb")).each do |file|
34
+ next if File.basename(file) == "base_tag.rb"
35
+
36
+ tag_name = File.basename(file, ".rb").gsub("_tag", "")
37
+ register_tag_from_file(tag_name)
38
+ end
39
+
40
+ @tags_discovered = true
41
+ Jekyll.logger.debug "ImgFlow:", "Discovered #{@tags.size} tags"
42
+ end
43
+
44
+ def self.register_tag_from_file(name)
45
+ class_name = "#{name.split('_').map(&:capitalize).join}Tag"
46
+
47
+ begin
48
+ require_relative "#{name}_tag"
49
+ tag_class = JekyllImgFlow::Tags.const_get(class_name)
50
+ register_tag name.to_sym, tag_class
51
+ Jekyll.logger.debug "ImgFlow:", "Registered tag: #{name} (#{class_name})"
52
+ rescue NameError => e
53
+ Jekyll.logger.warn "ImgFlow:", "Failed to load tag #{name}: #{e.message}"
54
+ rescue LoadError => e
55
+ Jekyll.logger.warn "ImgFlow:", "Failed to require tag #{name}: #{e.message}"
56
+ end
57
+ end
58
+
59
+ def self.tags_discovered?
60
+ @tags_discovered ||= false
61
+ end
62
+
63
+ # Force discovery (useful for testing)
64
+ def self.reset!
65
+ @tags = {}
66
+ @tags_discovered = false
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_tag"
4
+
5
+ module JekyllImgFlow
6
+ module Tags
7
+ # Watermark tag - validates and processes watermark operations
8
+ class WatermarkTag < BaseTag
9
+ def process(input_path, output_path, options = {})
10
+ ensure_output_dir(output_path)
11
+
12
+ watermark_path = options[:watermark]
13
+ position = options[:position] || :bottom_right
14
+ opacity = options[:opacity] || 0.7
15
+
16
+ # Validate and translate position for providers
17
+ translated_position = translate_watermark_position(position)
18
+ translated_opacity = validate_opacity(opacity)
19
+
20
+ @provider.add_watermark(watermark_path, position: translated_position,
21
+ opacity: translated_opacity)
22
+ @provider.execute(input_path, output_path)
23
+ output_path
24
+ end
25
+
26
+ private
27
+
28
+ def translate_watermark_position(position)
29
+ # Translate abstract positions to provider-specific values
30
+ case position
31
+ when :top_left then "northwest"
32
+ when :top_right then "northeast"
33
+ when :bottom_left then "southwest"
34
+ when :bottom_right then "southeast"
35
+ when :center then "center"
36
+ else position.to_s
37
+ end
38
+ end
39
+
40
+ def validate_opacity(value)
41
+ # Check if value is numeric before converting
42
+ raise ArgumentError, "Invalid opacity: '#{value}'. Must be between 0.0 and 1.0." unless value.to_s.match?(/\A\d*\.?\d+\z/)
43
+
44
+ opacity = value.to_f
45
+ raise ArgumentError, "Invalid opacity: '#{value}'. Must be between 0.0 and 1.0." unless opacity.between?(0.0, 1.0)
46
+
47
+ opacity
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JekyllImgFlow
4
+ VERSION = "0.1.5"
5
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "jekyll"
4
+ require "liquid"
5
+ require "json"
6
+ require "digest"
7
+ require "net/http"
8
+ require "uri"
9
+ require_relative "jekyll-imgflow/version"
10
+ require_relative "jekyll-imgflow/config"
11
+ require_relative "jekyll-imgflow/manifest_manager"
12
+ require_relative "jekyll-imgflow/tag_scanner"
13
+ require_relative "jekyll-imgflow/path_resolver"
14
+ require_relative "jekyll-imgflow/filename_generator"
15
+ require_relative "jekyll-imgflow/operation_processor"
16
+ require_relative "jekyll-imgflow/batch_manager"
17
+ require_relative "jekyll-imgflow/preset_manager"
18
+ require_relative "jekyll-imgflow/helpers/http_downloader"
19
+ require_relative "jekyll-imgflow/provider_registry"
20
+ require_relative "jekyll-imgflow/build_time_processor"
21
+ require_relative "jekyll-imgflow/parser"
22
+ require_relative "jekyll-imgflow/tags/tag_registry"
23
+ require_relative "jekyll-imgflow/html_generator"
24
+ require_relative "jekyll-imgflow/imgflow_tag"
25
+ require_relative "jekyll-imgflow/picture_tag_adaptor"
26
+ require_relative "jekyll-imgflow/picture_tag_preset_migrator"
27
+ require_relative "jekyll-imgflow/hooks"
28
+
29
+ module JekyllImgFlow
30
+ end
metadata ADDED
@@ -0,0 +1,261 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jekyll-imgflow
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.5
5
+ platform: ruby
6
+ authors:
7
+ - Svend Gundestrup
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 2026-07-29 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: fastimage
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '2.4'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '2.4'
26
+ - !ruby/object:Gem::Dependency
27
+ name: jekyll
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '4.0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '4.0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: bundler-audit
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '0.9'
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '0.9'
54
+ - !ruby/object:Gem::Dependency
55
+ name: rake
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '13.0'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '13.0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: reek
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '6.0'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '6.0'
82
+ - !ruby/object:Gem::Dependency
83
+ name: rspec
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '3.13'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '3.13'
96
+ - !ruby/object:Gem::Dependency
97
+ name: rubocop
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '1.88'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '1.88'
110
+ - !ruby/object:Gem::Dependency
111
+ name: rubocop-markdown
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '0.2'
117
+ type: :development
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '0.2'
124
+ - !ruby/object:Gem::Dependency
125
+ name: rubocop-performance
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '1.26'
131
+ type: :development
132
+ prerelease: false
133
+ version_requirements: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: '1.26'
138
+ - !ruby/object:Gem::Dependency
139
+ name: rubocop-rake
140
+ requirement: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: '0.7'
145
+ type: :development
146
+ prerelease: false
147
+ version_requirements: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - "~>"
150
+ - !ruby/object:Gem::Version
151
+ version: '0.7'
152
+ - !ruby/object:Gem::Dependency
153
+ name: rubocop-rspec
154
+ requirement: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - "~>"
157
+ - !ruby/object:Gem::Version
158
+ version: '3.10'
159
+ type: :development
160
+ prerelease: false
161
+ version_requirements: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - "~>"
164
+ - !ruby/object:Gem::Version
165
+ version: '3.10'
166
+ - !ruby/object:Gem::Dependency
167
+ name: simplecov
168
+ requirement: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - "~>"
171
+ - !ruby/object:Gem::Version
172
+ version: '1.0'
173
+ type: :development
174
+ prerelease: false
175
+ version_requirements: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - "~>"
178
+ - !ruby/object:Gem::Version
179
+ version: '1.0'
180
+ - !ruby/object:Gem::Dependency
181
+ name: yard
182
+ requirement: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - "~>"
185
+ - !ruby/object:Gem::Version
186
+ version: '0.9'
187
+ type: :development
188
+ prerelease: false
189
+ version_requirements: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - "~>"
192
+ - !ruby/object:Gem::Version
193
+ version: '0.9'
194
+ description: ImgFlow provides automatic image optimization for Jekyll with support
195
+ for multiple providers (Sharp, Imgproxy, ImageMagick, LibVips), multiple formats
196
+ (AVIF, WebP, PNG, JPG), and responsive image generation with modern picture tags.
197
+ email: svend@gundestrup.dk
198
+ executables: []
199
+ extensions: []
200
+ extra_rdoc_files: []
201
+ files:
202
+ - LICENSE
203
+ - README.md
204
+ - lib/jekyll-imgflow.rb
205
+ - lib/jekyll-imgflow/batch_manager.rb
206
+ - lib/jekyll-imgflow/build_time_processor.rb
207
+ - lib/jekyll-imgflow/config.rb
208
+ - lib/jekyll-imgflow/filename_generator.rb
209
+ - lib/jekyll-imgflow/helpers/http_downloader.rb
210
+ - lib/jekyll-imgflow/hooks.rb
211
+ - lib/jekyll-imgflow/html_generator.rb
212
+ - lib/jekyll-imgflow/imgflow_tag.rb
213
+ - lib/jekyll-imgflow/manifest_manager.rb
214
+ - lib/jekyll-imgflow/operation_processor.rb
215
+ - lib/jekyll-imgflow/parser.rb
216
+ - lib/jekyll-imgflow/path_resolver.rb
217
+ - lib/jekyll-imgflow/picture_tag_adaptor.rb
218
+ - lib/jekyll-imgflow/picture_tag_preset_migrator.rb
219
+ - lib/jekyll-imgflow/preset_manager.rb
220
+ - lib/jekyll-imgflow/provider_registry.rb
221
+ - lib/jekyll-imgflow/providers/base_provider.rb
222
+ - lib/jekyll-imgflow/providers/flyimg.rb
223
+ - lib/jekyll-imgflow/providers/imagemagick.rb
224
+ - lib/jekyll-imgflow/providers/imgproxy.rb
225
+ - lib/jekyll-imgflow/providers/libvips.rb
226
+ - lib/jekyll-imgflow/providers/sharp.rb
227
+ - lib/jekyll-imgflow/providers/weserv.rb
228
+ - lib/jekyll-imgflow/tag_scanner.rb
229
+ - lib/jekyll-imgflow/tags/base_tag.rb
230
+ - lib/jekyll-imgflow/tags/crop_tag.rb
231
+ - lib/jekyll-imgflow/tags/format_tag.rb
232
+ - lib/jekyll-imgflow/tags/opacity_tag.rb
233
+ - lib/jekyll-imgflow/tags/optimize_tag.rb
234
+ - lib/jekyll-imgflow/tags/quality_tag.rb
235
+ - lib/jekyll-imgflow/tags/resize_tag.rb
236
+ - lib/jekyll-imgflow/tags/tag_registry.rb
237
+ - lib/jekyll-imgflow/tags/watermark_tag.rb
238
+ - lib/jekyll-imgflow/version.rb
239
+ homepage: https://github.com/gundestrup/jekyll-imgflow
240
+ licenses:
241
+ - AGPL-3.0-or-later
242
+ metadata:
243
+ rubygems_mfa_required: 'true'
244
+ rdoc_options: []
245
+ require_paths:
246
+ - lib
247
+ required_ruby_version: !ruby/object:Gem::Requirement
248
+ requirements:
249
+ - - ">="
250
+ - !ruby/object:Gem::Version
251
+ version: 3.3.0
252
+ required_rubygems_version: !ruby/object:Gem::Requirement
253
+ requirements:
254
+ - - ">="
255
+ - !ruby/object:Gem::Version
256
+ version: '0'
257
+ requirements: []
258
+ rubygems_version: 3.6.2
259
+ specification_version: 4
260
+ summary: A modern, multi-provider, multi-format image optimization engine for Jekyll
261
+ test_files: []