vitals_image 0.2.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 39aa736f9e99bbf581d7e5b2f27df977921428c7aaf95846189475fd5ecc28ca
4
- data.tar.gz: e879218f0859db14a8879ef761b88930758e73302d9b1e0e88e4fb7c7e3251a6
3
+ metadata.gz: 070dabcbfcfe58cf4ad78ed7509cf16963484fa160db4358ed2f400a1a7d7925
4
+ data.tar.gz: cecf4c19afeed8df374686752e3ee7300ecbe6ced03c15781a9f0caa6134418b
5
5
  SHA512:
6
- metadata.gz: e6a8f4819b849d25306338f00a3a3691e59acbe12417cfb88b5c5a722914b1d34bdfb792776e51a22f7d4efbed37030f8c35203ca8d4a362e8c0e4213d5776fa
7
- data.tar.gz: 5058ad30a14d2edcb8ac744e5d8bb8130c66e0e874a3c088fb15ac297ba5911b8f9e95b19f7f67dbceb8f1a46201a2ed8f56c4b2e9271d7d19ad79476d637bab
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 `optimial_quality` value of blob metadata instead of fixed `85` if its available;
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
- { sampling_factor: "4:2:0", strip: true, interlace: "JPEG", colorspace: "sRGB", quality: 85, format: "jpg", background: :white, flatten: true, alpha: :off }
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
- { sampling_factor: "4:2:0", strip: true, interlace: "JPEG", colorspace: "sRGB", quality: 85 }
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 !optimizer.variable?
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, default: "{ analyzed: false }"
5
+ store :metadata, accessors: [ :identified, :analyzed, :width, :height ], coder: ActiveRecord::Coders::JSON
6
6
 
7
- after_create -> { AnalyzeJob.perform_later(self) }
7
+ after_create_commit -> { AnalyzeJob.perform_later(self) }
8
8
  end
9
9
  end
@@ -0,0 +1,6 @@
1
+ class AddFingerprintToVitalsImageSources < ActiveRecord::Migration[6.1]
2
+ def change
3
+ add_column :vitals_image_sources, :fingerprint, :string
4
+ add_index :vitals_image_sources, :fingerprint, unique: true
5
+ end
6
+ 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
@@ -15,7 +15,7 @@ module VitalsImage
15
15
  source = @store.read(key)
16
16
 
17
17
  if source.blank?
18
- source = Source.find_or_create_by(key: key)
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
@@ -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/active_storage"
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::ActiveStorage, VitalsImage::Optimizer::Url]
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: 85, interlace: true, optimize_coding: true, trellis_quant: true, quant_table: 3, background: 255 }, format: "jpg" }
73
- VitalsImage.jpeg_optimization ||= { saver: { strip: true, quality: 85, interlace: true, optimize_coding: true, trellis_quant: true, quant_table: 3 } }
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: 85, interlace: "JPEG", sampling_factor: "4:2:0", colorspace: "sRGB", background: :white, flatten: true, alpha: :off }, format: "jpg" }
77
- VitalsImage.jpeg_optimization ||= { saver: { strip: true, quality: 85, interlace: "JPEG", sampling_factor: "4:2:0", colorspace: "sRGB" } }
78
- VitalsImage.png_optimization ||= { saver: { strip: true, quality: 00 } }
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
@@ -8,7 +8,7 @@ module VitalsImage
8
8
 
9
9
  module VERSION
10
10
  MAJOR = 0
11
- MINOR = 2
11
+ MINOR = 5
12
12
  TINY = 0
13
13
  PRE = nil
14
14
 
@@ -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::ActiveStorage < Optimizer
4
+ class Optimizer::Variable < Optimizer
5
5
  def self.accept?(source)
6
- source.is_a?(::ActiveStorage::Attached) || source.is_a?(::ActiveStorage::Attachment) || source.is_a?(::ActiveStorage::Blob)
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 optimizations_with_optimal_quality(VitalsImage.jpeg_optimization)
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 optimizations(VitalsImage.png_optimization)
69
+ @source.variant resize(VitalsImage.png_optimization)
74
70
  else
75
- @source.variant optimizations_with_optimal_quality(VitalsImage.jpeg_conversion)
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 optimizations
77
+ @source.variant resize
82
78
  else
83
- @source.variant optimizations_with_optimal_quality(VitalsImage.jpeg_conversion)
79
+ @source.variant resize_and_flatten(VitalsImage.jpeg_conversion)
84
80
  end
85
81
  end
86
82
 
87
- def optimizations_with_optimal_quality(defaults = {})
88
- quality = @source.metadata[:optimal_quality] || defaults[:saver][:quality]
89
- defaults.merge quality: quality, "#{resize_mode}": dimensions
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 optimizations(defaults = {})
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.2.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-06-18 00:00:00.000000000 Z
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.3'
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.3'
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