vitals_image 0.2.0 → 0.5.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 +27 -1
- data/README.md +17 -5
- data/app/helpers/vitals_image/tag_helper.rb +6 -21
- data/app/models/vitals_image/source.rb +2 -2
- data/db/migrate/20210809171706_add_fingerprint_to_vitals_image_sources.rb +6 -0
- data/lib/vitals_image.rb +1 -2
- data/lib/vitals_image/cache.rb +11 -1
- data/lib/vitals_image/engine.rb +10 -9
- data/lib/vitals_image/gem_version.rb +1 -1
- data/lib/vitals_image/optimizer.rb +2 -7
- data/lib/vitals_image/optimizer/invariable.rb +40 -0
- data/lib/vitals_image/optimizer/url.rb +5 -1
- data/lib/vitals_image/optimizer/{active_storage.rb → variable.rb} +11 -15
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 070dabcbfcfe58cf4ad78ed7509cf16963484fa160db4358ed2f400a1a7d7925
|
4
|
+
data.tar.gz: cecf4c19afeed8df374686752e3ee7300ecbe6ced03c15781a9f0caa6134418b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 424b3c5908a10ee87df1e8174b786f30166af7b8fc28c4473ca77775dafb77fb1cce5780568a1098efac6898eb4b97584857ea122555d68f81ead1f6b1cfbb5c
|
7
|
+
data.tar.gz: 9510a8c14a5363997d6729933b3356f0bf7145410498e850ccd27d346fbde54e6bdf013e4b6b97afd557279f26dae4e082c07ad188ecdbcdb3e1e3b984c1655e
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,34 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.5]
|
4
|
+
|
5
|
+
- Add `domains` config to allow limiting from which domains images will be analyzed
|
6
|
+
- User `after_commit` to enqueued analyze job
|
7
|
+
|
8
|
+
## [0.4.1] - 2021-07-22
|
9
|
+
|
10
|
+
- Do not discard the specified `style` attribute
|
11
|
+
|
12
|
+
## [0.4.0] - 2021-07-06
|
13
|
+
|
14
|
+
- Fixed resize and pad in vips
|
15
|
+
- Fixed image quality in vips
|
16
|
+
- Reduced JPEG quality from 85 to 80
|
17
|
+
- Removed optimal quality
|
18
|
+
- Updated Vitals Image to 0.5
|
19
|
+
|
20
|
+
## [0.3.0] - 2021-05-22
|
21
|
+
|
22
|
+
- Redo the image helper
|
23
|
+
- Redo the active storage optimizer
|
24
|
+
|
25
|
+
## [0.2.1] - 2021-05-22
|
26
|
+
|
27
|
+
- Do not attempt to transform invariable images
|
28
|
+
|
3
29
|
## [0.2.0] - 2021-05-18
|
4
30
|
|
5
|
-
- Use the `
|
31
|
+
- Use the `optimal_quality` value of blob metadata instead of fixed `85` if its available;
|
6
32
|
- Remove some unecessary configs;
|
7
33
|
- Drop analyzers and use `active_analysis` gem instead;
|
8
34
|
- Use "retry once" strategy instead of `create_or_find_by`;
|
data/README.md
CHANGED
@@ -134,16 +134,30 @@ The following configuration options are available. The defaults were chosen for
|
|
134
134
|
| jpeg_optimization | see below | see below | Hash of options to pass to active storage when optimizing a JPEG. |
|
135
135
|
| png_optimization | see below | see below | Hash of options to pass to active storage when optimizing a PNG. |
|
136
136
|
| active_storage_route | `:inherited` | `:inherited` | Defines how urls of active storage images will be generated. If `inherited` it will use the same as active storage. Other valid options are `redirect`, `proxy` and `public`. Whatever is set here can be overriden in the helper. |
|
137
|
+
| domains | empty | - | Limits the domains that vitals image source can be created from |
|
137
138
|
|
139
|
+
Minimagick
|
138
140
|
```ruby
|
139
141
|
# jpeg_conversion
|
140
|
-
{
|
142
|
+
{ saver: { strip: true, quality: 85, interlace: "JPEG", sampling_factor: "4:2:0", colorspace: "sRGB", background: :white, flatten: true, alpha: :off }, format: "jpg" }
|
141
143
|
|
142
144
|
# jpeg_optimization:
|
143
|
-
{
|
145
|
+
{ saver: { strip: true, quality: 85, interlace: "JPEG", sampling_factor: "4:2:0", colorspace: "sRGB" } }
|
144
146
|
|
145
147
|
# png_optimization:
|
146
|
-
{ strip: true, quality: 00 }
|
148
|
+
{ saver: { strip: true, quality: 00 } }
|
149
|
+
```
|
150
|
+
|
151
|
+
Vips
|
152
|
+
```ruby
|
153
|
+
# jpeg_conversion
|
154
|
+
{ saver: { strip: true, quality: 85, interlace: true, optimize_coding: true, trellis_quant: true, quant_table: 3, background: 255 }, format: "jpg" }
|
155
|
+
|
156
|
+
# jpeg_optimization:
|
157
|
+
{ saver: { strip: true, quality: 85, interlace: true, optimize_coding: true, trellis_quant: true, quant_table: 3 } }
|
158
|
+
|
159
|
+
# png_optimization:
|
160
|
+
{ saver: { strip: true, compression: 9 } }
|
147
161
|
```
|
148
162
|
|
149
163
|
These can be configured in your environment files, just like any other rails settings:
|
@@ -151,8 +165,6 @@ These can be configured in your environment files, just like any other rails set
|
|
151
165
|
```
|
152
166
|
Rails.application.configure do |config|
|
153
167
|
config.vitals_image.image_library = :vips
|
154
|
-
config.vitals_image.mobile_width = 410
|
155
|
-
config.vitals_image.desktop_width = 1264
|
156
168
|
config.vitals_image.lazy_loading = :lozad
|
157
169
|
config.vitals_image.require_alt_attribute = true
|
158
170
|
config.vitals_image.check_for_white_background = true
|
@@ -6,32 +6,17 @@ module VitalsImage
|
|
6
6
|
source = image_url(source) if source.is_a?(String)
|
7
7
|
optimizer = VitalsImage::Base.optimizer(source, options)
|
8
8
|
|
9
|
-
if
|
10
|
-
vitals_image_invariable_tag(optimizer)
|
11
|
-
elsif optimizer.native_lazy_load?
|
12
|
-
vitals_image_variable_tag(optimizer)
|
13
|
-
else
|
14
|
-
vitals_image_lazy_tag(optimizer)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
def vitals_image_invariable_tag(optimizer)
|
20
|
-
image_tag optimizer.src, optimizer.html_options
|
21
|
-
end
|
22
|
-
|
23
|
-
def vitals_image_variable_tag(optimizer)
|
24
|
-
url = vitals_image_url(optimizer.src, optimizer.html_options)
|
25
|
-
image_tag url, optimizer.html_options
|
26
|
-
end
|
27
|
-
|
28
|
-
def vitals_image_lazy_tag(optimizer)
|
9
|
+
if optimizer.non_native_lazy_load?
|
29
10
|
url = vitals_image_url(optimizer.html_options["data"]["src"], optimizer.html_options)
|
30
11
|
optimizer.html_options["data"]["src"] = url
|
31
|
-
|
32
12
|
image_tag optimizer.src, optimizer.html_options
|
13
|
+
else
|
14
|
+
url = vitals_image_url(optimizer.src, optimizer.html_options)
|
15
|
+
image_tag url, optimizer.html_options
|
33
16
|
end
|
17
|
+
end
|
34
18
|
|
19
|
+
private
|
35
20
|
def vitals_image_url(source, options)
|
36
21
|
active_storage_route = options.delete("active_storage_route") || VitalsImage.active_storage_route
|
37
22
|
|
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
module VitalsImage
|
4
4
|
class Source < ActiveRecord::Base
|
5
|
-
store :metadata, accessors: [ :analyzed, :width, :height ], coder: ActiveRecord::Coders::JSON
|
5
|
+
store :metadata, accessors: [ :identified, :analyzed, :width, :height ], coder: ActiveRecord::Coders::JSON
|
6
6
|
|
7
|
-
|
7
|
+
after_create_commit -> { AnalyzeJob.perform_later(self) }
|
8
8
|
end
|
9
9
|
end
|
data/lib/vitals_image.rb
CHANGED
@@ -14,8 +14,6 @@ module VitalsImage
|
|
14
14
|
mattr_accessor :analyzers
|
15
15
|
mattr_accessor :image_library
|
16
16
|
|
17
|
-
mattr_accessor :mobile_width
|
18
|
-
mattr_accessor :desktop_width
|
19
17
|
mattr_accessor :resolution
|
20
18
|
mattr_accessor :lazy_loading
|
21
19
|
mattr_accessor :lazy_loading_placeholder
|
@@ -28,6 +26,7 @@ module VitalsImage
|
|
28
26
|
mattr_accessor :jpeg_optimization
|
29
27
|
mattr_accessor :png_optimization
|
30
28
|
mattr_accessor :active_storage_route
|
29
|
+
mattr_accessor :domains
|
31
30
|
|
32
31
|
mattr_accessor :skip_ssl_verification
|
33
32
|
end
|
data/lib/vitals_image/cache.rb
CHANGED
@@ -15,7 +15,7 @@ module VitalsImage
|
|
15
15
|
source = @store.read(key)
|
16
16
|
|
17
17
|
if source.blank?
|
18
|
-
source =
|
18
|
+
source = find_or_create_by(key)
|
19
19
|
expires_in = source.analyzed ? nil : 1.minute
|
20
20
|
@store.write(key, source, expires_in: expires_in)
|
21
21
|
end
|
@@ -25,6 +25,16 @@ module VitalsImage
|
|
25
25
|
end
|
26
26
|
|
27
27
|
private
|
28
|
+
def find_or_create_by(key)
|
29
|
+
uri = URI.parse(key)
|
30
|
+
|
31
|
+
if VitalsImage.domains.present? && !VitalsImage.domains.include?(uri.host)
|
32
|
+
Source.new(key: key, metadata: { identified: false })
|
33
|
+
else
|
34
|
+
Source.find_or_create_by(key: key) { |source| source.identified = true }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
28
38
|
def with_retry
|
29
39
|
yield
|
30
40
|
rescue ActiveRecord::RecordNotUnique
|
data/lib/vitals_image/engine.rb
CHANGED
@@ -19,15 +19,17 @@ require "vitals_image/errors"
|
|
19
19
|
require "vitals_image/optimizer"
|
20
20
|
require "vitals_image/optimizer/blank"
|
21
21
|
require "vitals_image/optimizer/url"
|
22
|
-
require "vitals_image/optimizer/
|
22
|
+
require "vitals_image/optimizer/variable"
|
23
|
+
require "vitals_image/optimizer/invariable"
|
23
24
|
|
24
25
|
module VitalsImage
|
25
26
|
class Engine < ::Rails::Engine
|
26
27
|
isolate_namespace VitalsImage
|
27
28
|
|
28
29
|
config.vitals_image = ActiveSupport::OrderedOptions.new
|
29
|
-
config.vitals_image.optimizers = [VitalsImage::Optimizer::Blank, VitalsImage::Optimizer::
|
30
|
+
config.vitals_image.optimizers = [VitalsImage::Optimizer::Blank, VitalsImage::Optimizer::Variable, VitalsImage::Optimizer::Invariable, VitalsImage::Optimizer::Url]
|
30
31
|
config.vitals_image.analyzers = [VitalsImage::Analyzer::UrlAnalyzer]
|
32
|
+
config.vitals_image.domains = []
|
31
33
|
|
32
34
|
config.eager_load_namespaces << VitalsImage
|
33
35
|
|
@@ -39,8 +41,6 @@ module VitalsImage
|
|
39
41
|
VitalsImage.optimizers = app.config.vitals_image.optimizers || []
|
40
42
|
VitalsImage.analyzers = app.config.vitals_image.analyzers || []
|
41
43
|
|
42
|
-
VitalsImage.mobile_width = app.config.vitals_image.mobile_width || :original
|
43
|
-
VitalsImage.desktop_width = app.config.vitals_image.desktop_width || :original
|
44
44
|
VitalsImage.resolution = app.config.vitals_image.resolution || 2
|
45
45
|
VitalsImage.lazy_loading = app.config.vitals_image.lazy_loading || :native
|
46
46
|
VitalsImage.lazy_loading_placeholder = app.config.vitals_image.lazy_loading_placeholder || VitalsImage::Base::TINY_GIF
|
@@ -53,6 +53,7 @@ module VitalsImage
|
|
53
53
|
VitalsImage.jpeg_conversion = app.config.vitals_image.jpeg_conversion
|
54
54
|
VitalsImage.jpeg_optimization = app.config.vitals_image.jpeg_optimization
|
55
55
|
VitalsImage.png_optimization = app.config.vitals_image.png_optimization
|
56
|
+
VitalsImage.domains = app.config.vitals_image.domains || []
|
56
57
|
|
57
58
|
VitalsImage.skip_ssl_verification = app.config.vitals_image.skip_ssl_verification || false
|
58
59
|
end
|
@@ -69,13 +70,13 @@ module VitalsImage
|
|
69
70
|
initializer "vitals_image.optimizations" do
|
70
71
|
config.after_initialize do |app|
|
71
72
|
if VitalsImage.image_library == :vips
|
72
|
-
VitalsImage.jpeg_conversion ||= { saver: { strip: true, quality:
|
73
|
-
VitalsImage.jpeg_optimization ||= { saver: { strip: true, quality:
|
73
|
+
VitalsImage.jpeg_conversion ||= { saver: { strip: true, quality: 80, interlace: true, optimize_coding: true, trellis_quant: true, quant_table: 3, background: 255 }, format: "jpg" }
|
74
|
+
VitalsImage.jpeg_optimization ||= { saver: { strip: true, quality: 80, interlace: true, optimize_coding: true, trellis_quant: true, quant_table: 3 } }
|
74
75
|
VitalsImage.png_optimization ||= { saver: { strip: true, compression: 9 } }
|
75
76
|
else
|
76
|
-
VitalsImage.jpeg_conversion ||= { saver: { strip: true, quality:
|
77
|
-
VitalsImage.jpeg_optimization ||= { saver: { strip: true, quality:
|
78
|
-
VitalsImage.png_optimization ||= { saver: { strip: true, quality:
|
77
|
+
VitalsImage.jpeg_conversion ||= { saver: { strip: true, quality: 80, interlace: "JPEG", sampling_factor: "4:2:0", colorspace: "sRGB", background: :white, flatten: true, alpha: :off }, format: "jpg" }
|
78
|
+
VitalsImage.jpeg_optimization ||= { saver: { strip: true, quality: 80, interlace: "JPEG", sampling_factor: "4:2:0", colorspace: "sRGB" } }
|
79
|
+
VitalsImage.png_optimization ||= { saver: { strip: true, quality: 75 } }
|
79
80
|
end
|
80
81
|
end
|
81
82
|
end
|
@@ -26,10 +26,10 @@ module VitalsImage
|
|
26
26
|
|
27
27
|
def html_options
|
28
28
|
@html_options ||= begin
|
29
|
-
html_options = @options.dup
|
29
|
+
html_options = @options.dup.except("lazy_load")
|
30
30
|
html_options["width"] = width
|
31
31
|
html_options["height"] = height
|
32
|
-
html_options["style"] = style
|
32
|
+
html_options["style"] = "#{style} #{html_options["style"]}".squish.presence
|
33
33
|
html_options["class"] = "vitals-image #{html_options["class"]}".squish
|
34
34
|
|
35
35
|
if non_native_lazy_load?
|
@@ -57,11 +57,6 @@ module VitalsImage
|
|
57
57
|
lazy_load? && VitalsImage.lazy_loading == :native
|
58
58
|
end
|
59
59
|
|
60
|
-
# Override this method in a concrete subclass. Have it return true the source is an active storage blob
|
61
|
-
def variable?
|
62
|
-
false
|
63
|
-
end
|
64
|
-
|
65
60
|
private
|
66
61
|
def style
|
67
62
|
if analyzed? && !requested_height
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module VitalsImage
|
4
|
+
class Optimizer::Invariable < Optimizer
|
5
|
+
def self.accept?(source)
|
6
|
+
source.respond_to?(:variable?) && !source.variable?
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
def source_url
|
11
|
+
@source
|
12
|
+
end
|
13
|
+
|
14
|
+
def style
|
15
|
+
if !analyzed?
|
16
|
+
# Do nothing
|
17
|
+
elsif !requested_height
|
18
|
+
"height:auto;"
|
19
|
+
elsif fixed_dimensions?
|
20
|
+
"object-fit: contain;"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def original_width
|
25
|
+
metadata[:width]
|
26
|
+
end
|
27
|
+
|
28
|
+
def original_height
|
29
|
+
metadata[:height]
|
30
|
+
end
|
31
|
+
|
32
|
+
def metadata
|
33
|
+
@source.metadata
|
34
|
+
end
|
35
|
+
|
36
|
+
def analyzed?
|
37
|
+
metadata[:analyzed]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -17,7 +17,7 @@ module VitalsImage
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def style
|
20
|
-
if !analyzed?
|
20
|
+
if !identified? || !analyzed?
|
21
21
|
# Do nothing
|
22
22
|
elsif !requested_height
|
23
23
|
"height:auto;"
|
@@ -26,6 +26,10 @@ module VitalsImage
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
+
def identified?
|
30
|
+
metadata.identified
|
31
|
+
end
|
32
|
+
|
29
33
|
def analyzed?
|
30
34
|
metadata.analyzed
|
31
35
|
end
|
@@ -1,13 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module VitalsImage
|
4
|
-
class Optimizer::
|
4
|
+
class Optimizer::Variable < Optimizer
|
5
5
|
def self.accept?(source)
|
6
|
-
source.
|
7
|
-
end
|
8
|
-
|
9
|
-
def variable?
|
10
|
-
true
|
6
|
+
source.respond_to?(:variable?) && source.variable?
|
11
7
|
end
|
12
8
|
|
13
9
|
private
|
@@ -65,31 +61,31 @@ module VitalsImage
|
|
65
61
|
end
|
66
62
|
|
67
63
|
def optimize_jpeg
|
68
|
-
@source.variant
|
64
|
+
@source.variant resize_and_flatten(VitalsImage.jpeg_optimization)
|
69
65
|
end
|
70
66
|
|
71
67
|
def optimize_png
|
72
68
|
if alpha? || !VitalsImage.convert_to_jpeg
|
73
|
-
@source.variant
|
69
|
+
@source.variant resize(VitalsImage.png_optimization)
|
74
70
|
else
|
75
|
-
@source.variant
|
71
|
+
@source.variant resize_and_flatten(VitalsImage.jpeg_conversion)
|
76
72
|
end
|
77
73
|
end
|
78
74
|
|
79
75
|
def optimize_generic
|
80
76
|
if alpha? || !VitalsImage.convert_to_jpeg
|
81
|
-
@source.variant
|
77
|
+
@source.variant resize
|
82
78
|
else
|
83
|
-
@source.variant
|
79
|
+
@source.variant resize_and_flatten(VitalsImage.jpeg_conversion)
|
84
80
|
end
|
85
81
|
end
|
86
82
|
|
87
|
-
def
|
88
|
-
|
89
|
-
defaults.merge
|
83
|
+
def resize_and_flatten(defaults = {})
|
84
|
+
resize = resize_mode != :resize_and_pad ? dimensions : dimensions.push(background: [255])
|
85
|
+
defaults.merge "#{resize_mode}": resize
|
90
86
|
end
|
91
87
|
|
92
|
-
def
|
88
|
+
def resize(defaults = {})
|
93
89
|
defaults.merge "#{resize_mode}": dimensions
|
94
90
|
end
|
95
91
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vitals_image
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Breno Gazzola
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-08-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activejob
|
@@ -128,14 +128,14 @@ dependencies:
|
|
128
128
|
requirements:
|
129
129
|
- - ">="
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: '0.
|
131
|
+
version: '0.5'
|
132
132
|
type: :runtime
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
136
|
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version: '0.
|
138
|
+
version: '0.5'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
140
|
name: sqlite3
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -243,6 +243,7 @@ files:
|
|
243
243
|
- app/views/layouts/vitals_image/application.html.erb
|
244
244
|
- config/routes.rb
|
245
245
|
- db/migrate/20210502132155_create_vitals_image_sources.rb
|
246
|
+
- db/migrate/20210809171706_add_fingerprint_to_vitals_image_sources.rb
|
246
247
|
- lib/tasks/vitals_image_tasks.rake
|
247
248
|
- lib/vitals_image.rb
|
248
249
|
- lib/vitals_image/analyzer.rb
|
@@ -253,9 +254,10 @@ files:
|
|
253
254
|
- lib/vitals_image/errors.rb
|
254
255
|
- lib/vitals_image/gem_version.rb
|
255
256
|
- lib/vitals_image/optimizer.rb
|
256
|
-
- lib/vitals_image/optimizer/active_storage.rb
|
257
257
|
- lib/vitals_image/optimizer/blank.rb
|
258
|
+
- lib/vitals_image/optimizer/invariable.rb
|
258
259
|
- lib/vitals_image/optimizer/url.rb
|
260
|
+
- lib/vitals_image/optimizer/variable.rb
|
259
261
|
- lib/vitals_image/test_case.rb
|
260
262
|
- lib/vitals_image/version.rb
|
261
263
|
homepage: https://github.com/FestaLab/vitals_image
|