imgix 2.1.0 → 4.0.3

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.
data/lib/imgix/client.rb CHANGED
@@ -1,95 +1,106 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'digest'
4
- require 'addressable/uri'
5
- require 'zlib'
6
- require 'net/http'
7
- require 'uri'
3
+ require "digest"
4
+ require "net/http"
5
+ require "uri"
6
+ require "json"
8
7
 
9
8
  module Imgix
10
9
  class Client
11
- DEFAULTS = { use_https: true, shard_strategy: :crc }
10
+ DEFAULTS = { use_https: true }.freeze
12
11
 
13
12
  def initialize(options = {})
14
13
  options = DEFAULTS.merge(options)
14
+ @domain = options[:domain]
15
+
16
+ validate_domain!
15
17
 
16
- deprecate_warning!(options[:host],options[:hosts])
17
- @hosts = Array(options[:host]) + Array(options[:hosts]) and validate_hosts!
18
18
  @secure_url_token = options[:secure_url_token]
19
19
  @api_key = options[:api_key]
20
20
  @use_https = options[:use_https]
21
- @shard_strategy = options[:shard_strategy] and validate_strategy!
22
21
  @include_library_param = options.fetch(:include_library_param, true)
23
22
  @library = options.fetch(:library_param, "rb")
24
23
  @version = options.fetch(:library_version, Imgix::VERSION)
25
24
  end
26
25
 
27
26
  def path(path)
28
- p = Path.new(prefix(path), @secure_url_token, path)
27
+ p = Path.new(prefix, @secure_url_token, path)
29
28
  p.ixlib("#{@library}-#{@version}") if @include_library_param
30
29
  p
31
30
  end
32
31
 
33
32
  def purge(path)
34
- raise "Authentication token required" unless !!(@api_key)
35
- url = prefix(path)+path
36
- uri = URI.parse('https://api.imgix.com/v2/image/purger')
37
- req = Net::HTTP::Post.new(uri.path, {"User-Agent" => "imgix #{@library}-#{@version}"})
38
- req.basic_auth @api_key, ''
39
- req.set_form_data({'url' => url})
40
- sock = Net::HTTP.new(uri.host, uri.port)
41
- sock.use_ssl = true
42
- res = sock.start {|http| http.request(req) }
43
- res
44
- end
33
+ api_key_error = "A valid API key is required to send purge requests"
34
+ raise api_key_error if @api_key.nil?
45
35
 
46
- def prefix(path)
47
- "#{@use_https ? 'https' : 'http'}://#{get_host(path)}"
48
- end
36
+ endpoint = URI.parse("https://api.imgix.com/api/v1/purge")
37
+ # Ensure the path has been prefixed with '/'.
38
+ path = path.start_with?("/") ? path : "/#{path}"
39
+ url = prefix + path
49
40
 
50
- def get_host(path)
51
- host = host_for_crc(path) if @shard_strategy == :crc
52
- host = host_for_cycle if @shard_strategy == :cycle
53
- host
54
- end
41
+ req = create_request(endpoint, url, :json_data_from)
55
42
 
56
- def host_for_crc(path)
57
- crc = Zlib.crc32(path)
58
- index = crc % @hosts.length - 1
59
- @hosts[index]
43
+ sock = Net::HTTP.new(endpoint.host, endpoint.port)
44
+ sock.use_ssl = true
45
+ sock.start { |http| http.request(req) }
60
46
  end
61
47
 
62
- def host_for_cycle
63
- if not defined? @hosts_cycle
64
- @hosts_cycle = @hosts.cycle
65
- end
66
- @hosts_cycle.next
48
+ def prefix
49
+ "#{@use_https ? 'https' : 'http'}://#{@domain}"
67
50
  end
68
51
 
69
52
  private
70
53
 
71
- def validate_strategy!
72
- unless STRATEGIES.include?(@shard_strategy)
73
- raise ArgumentError.new("#{@shard_strategy} is not supported")
54
+ # Create a request object by specifying it's endpoint, resource, and
55
+ # an optional data_fmt.
56
+ #
57
+ # `endpoint` must be a valid URI object
58
+ # `resource` must be a valid URL designating the resource to be purged
59
+ # `data_fmt` must be a valid method or Proc object
60
+ #
61
+ # Specify a `data_fmt` method when a resource (URL) requires
62
+ # additional formatting before being included in the request body.
63
+ # By default, the data format is specified by the `json_data_from`
64
+ # method.
65
+ def create_request(endpoint, resource, data_fmt = :json_data_from)
66
+ req = Net::HTTP::Post.new(endpoint.path)
67
+ req["Content-Type"] = "application/vnd.api+json"
68
+ req["Authorization"] = "Bearer #{@api_key}"
69
+ req["User-Agent"] = "imgix #{@library}-#{@version}"
70
+
71
+ if data_fmt.is_a?(Proc)
72
+ req.body = data_fmt.call(resource)
73
+ elsif data_fmt.is_a?(Symbol)
74
+ req.body = send(data_fmt, resource)
75
+ else
76
+ fmt_arg_error = "`fmt' is required to be of class Symbol or " \
77
+ "Proc but was found to be\n\s\sof class #{data_fmt.class}\n"
78
+ raise ArgumentError, fmt_arg_error
74
79
  end
80
+
81
+ req
75
82
  end
76
83
 
77
- def validate_hosts!
78
- unless @hosts.length > 0
79
- raise ArgumentError, "The :host or :hosts option must be specified"
80
- end
81
- @hosts.each do |host|
82
- if host.match(DOMAIN_REGEX) == nil
83
- raise ArgumentError, "Domains must be passed in as fully-qualified domain names and should not include a protocol or any path element, i.e. \"example.imgix.net\"."
84
- end
85
- end
84
+ def json_data_from(url)
85
+ {
86
+ data: {
87
+ attributes: {
88
+ url: url
89
+ },
90
+ type: "purges"
91
+ }
92
+ }.to_json
86
93
  end
87
94
 
88
- def deprecate_warning!(host, hosts)
89
- has_many_domains = (host.kind_of?(Array) && host.length > 1 ) || (hosts.kind_of?(Array) && hosts.length > 1)
90
- if has_many_domains
91
- warn "Warning: Domain sharding has been deprecated and will be removed in the next major version."
92
- end
95
+ def validate_domain!
96
+ domain_error = "The :domain option must be specified"
97
+ raise ArgumentError, domain_error if @domain.nil?
98
+
99
+ domain_error = "Domains must be passed in as fully-qualified"\
100
+ "domain names and should not include a protocol"\
101
+ 'or any path element, i.e. "example.imgix.net"'\
102
+
103
+ raise ArgumentError, domain_error if @domain.match(DOMAIN_REGEX).nil?
93
104
  end
94
105
  end
95
106
  end
data/lib/imgix/path.rb CHANGED
@@ -1,82 +1,125 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'base64'
4
- require 'cgi/util'
5
- require 'erb'
6
- require 'imgix/param_helpers'
3
+ require "base64"
4
+ require "cgi/util"
5
+ require "erb"
7
6
 
8
7
  module Imgix
9
8
  class Path
10
- include ParamHelpers
11
9
 
12
- ALIASES = {
13
- width: :w,
14
- height: :h,
15
- rotation: :rot,
16
- noise_reduction: :nr,
17
- sharpness: :sharp,
18
- exposure: :exp,
19
- vibrance: :vib,
20
- saturation: :sat,
21
- brightness: :bri,
22
- contrast: :con,
23
- highlight: :high,
24
- shadow: :shad,
25
- gamma: :gam,
26
- pixelate: :px,
27
- halftone: :htn,
28
- watermark: :mark,
29
- text: :txt,
30
- format: :fm,
31
- quality: :q
32
- }
33
-
34
- def initialize(prefix, secure_url_token, path = '/')
10
+ def initialize(prefix, secure_url_token, path = "/")
35
11
  @prefix = prefix
36
12
  @secure_url_token = secure_url_token
37
13
  @path = path
38
14
  @options = {}
39
-
40
- @path = CGI.escape(@path) if /^https?/ =~ @path
41
- @path = "/#{@path}" if @path[0] != '/'
42
15
  end
43
16
 
44
17
  def to_url(opts = {})
18
+ sanitized_path = sanitize_path(@path)
45
19
  prev_options = @options.dup
46
20
  @options.merge!(opts)
47
21
 
48
- url = @prefix + path_and_params
22
+ current_path_and_params = path_and_params(sanitized_path)
23
+ url = @prefix + current_path_and_params
49
24
 
50
25
  if @secure_url_token
51
- url += (has_query? ? '&' : '?') + "s=#{signature}"
26
+ url += (has_query? ? "&" : "?") + "s=#{signature(current_path_and_params)}"
52
27
  end
53
28
 
54
29
  @options = prev_options
55
- return url
30
+ url
56
31
  end
57
32
 
58
33
  def defaults
59
34
  @options = {}
60
- return self
35
+ self
36
+ end
37
+
38
+ def ixlib(lib_version)
39
+ @options[:ixlib] = lib_version
61
40
  end
62
41
 
42
+ def ixlib=(lib_version)
43
+ @options[:ixlib] = lib_version
44
+ end
45
+
46
+ def to_srcset(options: {}, **params)
47
+ prev_options = @options.dup
48
+ @options.merge!(params)
49
+
50
+ width = @options[:w]
51
+ height = @options[:h]
52
+ aspect_ratio = @options[:ar]
53
+
54
+ srcset = if width || height
55
+ build_dpr_srcset(options: options, params: @options)
56
+ else
57
+ build_srcset_pairs(options: options, params: @options)
58
+ end
59
+
60
+ @options = prev_options
61
+ srcset
62
+ end
63
+
64
+ ALIASES = {
65
+ width: :w,
66
+ height: :h,
67
+ rotation: :rot,
68
+ noise_reduction: :nr,
69
+ sharpness: :sharp,
70
+ exposure: :exp,
71
+ vibrance: :vib,
72
+ saturation: :sat,
73
+ brightness: :bri,
74
+ contrast: :con,
75
+ highlight: :high,
76
+ shadow: :shad,
77
+ gamma: :gam,
78
+ pixelate: :px,
79
+ halftone: :htn,
80
+ watermark: :mark,
81
+ text: :txt,
82
+ format: :fm,
83
+ quality: :q,
84
+ fill_color: :fillcolor
85
+ }.freeze
86
+
87
+ # Define query parameters on a Path (via method_missing).
88
+ # Normally, when overriding method_missing, it is a best practice
89
+ # to fall back to super, but this method works differently.
90
+ #
91
+ # method_missing intercepts messages sent to objects of this class
92
+ # and acts as a getter, setter, and deleter. If there are no args,
93
+ # e.g. `path.width`, then this method acts like a getter.
94
+ #
95
+ # Likewise, if the first argument is nil and the method name exists
96
+ # as a key in @options, e.g. `path.param_name = nil`, then this
97
+ # method acts like a deleter and the `param_name` is removed from
98
+ # the list of @options.
99
+ #
100
+ # Finally, in _all_ other cases, the `method` name is used as the
101
+ # `key` and the `*args` are used as the value.
63
102
  def method_missing(method, *args, &block)
64
103
  key = method.to_s.gsub('=', '')
65
- if args.length == 0
104
+
105
+ if args.length == 0 # Get, or
66
106
  return @options[key]
67
- elsif args.first.nil? && @options.has_key?(key)
107
+ elsif args.first.nil? && @options.has_key?(key) # Delete, or
68
108
  @options.delete(key) and return self
69
109
  end
70
110
 
71
- @options[key] = args.join(',')
72
- return self
111
+ @options[key] = args.join(',') # Set the option.
112
+ self
73
113
  end
74
114
 
115
+ # Use ALIASES to define setters for a subset of imgix parameters.
116
+ # E.g. `path.width(100)` would result in `send(:w, [100])`.
75
117
  ALIASES.each do |from, to|
76
118
  define_method from do |*args|
77
119
  self.send(to, *args)
78
120
  end
79
121
 
122
+ # E.g. `path.width = 100` would result in `send(":w=", [100])`.
80
123
  define_method "#{from}=" do |*args|
81
124
  self.send("#{to}=", *args)
82
125
  return self
@@ -85,12 +128,46 @@ module Imgix
85
128
 
86
129
  private
87
130
 
88
- def signature
89
- Digest::MD5.hexdigest(@secure_url_token + path_and_params)
131
+ # Escape and encode any characters in path that are reserved and not utf8 encoded.
132
+ # This includes " +?:#" characters. If a path is being used as a proxy, utf8
133
+ # encode everything. If it is not being used as proxy, leave certain chars, like
134
+ # "/", alone. Method assumes path is not already encoded.
135
+ def sanitize_path(path)
136
+ # remove the leading "/", we'll add it back after encoding
137
+ path = path.slice(1, path.length) if Regexp.new('^/') =~ path
138
+ # if path is being used as a proxy, encode the entire thing
139
+ if /^https?/ =~ path
140
+ return encode_URI_Component(path)
141
+ else
142
+ # otherwise, encode only specific characters
143
+ return encode_URI(path)
144
+ end
90
145
  end
91
146
 
92
- def path_and_params
93
- has_query? ? "#{@path}?#{query}" : @path
147
+ # URL encode the entire path
148
+ def encode_URI_Component(path)
149
+ return "/" + ERB::Util.url_encode(path)
150
+ end
151
+
152
+ # URL encode every character in the path, including
153
+ # " +?:#" characters.
154
+ def encode_URI(path)
155
+ # For each component in the path, URL encode it and add it
156
+ # to the array path component.
157
+ path_components = []
158
+ path.split("/").each do |str|
159
+ path_components << ERB::Util.url_encode(str)
160
+ end
161
+ # Prefix and join the encoded path components.
162
+ "/#{path_components.join('/')}"
163
+ end
164
+
165
+ def signature(rest)
166
+ Digest::MD5.hexdigest(@secure_url_token + rest)
167
+ end
168
+
169
+ def path_and_params(path)
170
+ has_query? ? "#{path}?#{query}" : path
94
171
  end
95
172
 
96
173
  def query
@@ -102,11 +179,86 @@ module Imgix
102
179
  else
103
180
  escaped_key << "=" << ERB::Util.url_encode(val.to_s)
104
181
  end
105
- end.join('&')
182
+ end.join("&")
106
183
  end
107
184
 
108
185
  def has_query?
109
- query.length > 0
186
+ !query.empty?
187
+ end
188
+
189
+ def build_srcset_pairs(options:, params:)
190
+ srcset = ""
191
+
192
+ widths = options[:widths] || []
193
+ width_tolerance = options[:width_tolerance] || DEFAULT_WIDTH_TOLERANCE
194
+ min_width = options[:min_width] || MIN_WIDTH
195
+ max_width = options[:max_width] || MAX_WIDTH
196
+
197
+ if !widths.empty?
198
+ validate_widths!(widths)
199
+ srcset_widths = widths
200
+ elsif width_tolerance != DEFAULT_WIDTH_TOLERANCE || min_width != MIN_WIDTH || max_width != MAX_WIDTH
201
+ validate_range!(min_width, max_width)
202
+ validate_width_tolerance!(width_tolerance)
203
+ srcset_widths = TARGET_WIDTHS.call(width_tolerance, min_width, max_width)
204
+ else
205
+ srcset_widths = DEFAULT_TARGET_WIDTHS
206
+ end
207
+
208
+ srcset_widths.each do |width|
209
+ params[:w] = width
210
+ srcset += "#{to_url(params)} #{width}w,\n"
211
+ end
212
+
213
+ srcset[0..-3]
214
+ end
215
+
216
+ def build_dpr_srcset(options:, params:)
217
+ srcset = ""
218
+
219
+ disable_variable_quality = options[:disable_variable_quality] || false
220
+ validate_variable_qualities!(disable_variable_quality)
221
+
222
+ target_ratios = [1, 2, 3, 4, 5]
223
+ quality = params[:q]
224
+
225
+ target_ratios.each do |ratio|
226
+ params[:dpr] = ratio
227
+
228
+ params[:q] = quality || DPR_QUALITY[ratio] unless disable_variable_quality
229
+
230
+ srcset += "#{to_url(params)} #{ratio}x,\n"
231
+ end
232
+
233
+ srcset[0..-3]
234
+ end
235
+
236
+ def validate_width_tolerance!(width_tolerance)
237
+ width_increment_error = "error: `width_tolerance` must be a positive `Numeric` value"
238
+
239
+ raise ArgumentError, width_increment_error if !width_tolerance.is_a?(Numeric) || width_tolerance <= 0
240
+ end
241
+
242
+ def validate_widths!(widths)
243
+ widths_error = "error: `widths` must be an array of positive `Numeric` values"
244
+ raise ArgumentError, widths_error unless widths.is_a?(Array)
245
+
246
+ all_positive_integers = widths.all? { |i| i.is_a?(Integer) && i > 0 }
247
+ raise ArgumentError, widths_error unless all_positive_integers
248
+ end
249
+
250
+ def validate_range!(min_width, max_width)
251
+ range_numeric_error = "error: `min_width` and `max_width` must be positive `Numeric` values"
252
+ raise ArgumentError, range_numeric_error unless min_width.is_a?(Numeric) && max_width.is_a?(Numeric)
253
+
254
+ raise ArgumentError, range_numeric_error unless min_width > 0 && max_width > 0
255
+ end
256
+
257
+ def validate_variable_qualities!(disable_quality)
258
+ disable_quality_error = "error: `disable_quality` must be a Boolean value"
259
+ unless disable_quality.is_a?(TrueClass) || disable_quality.is_a?(FalseClass)
260
+ raise ArgumentError, disable_quality_error
261
+ end
110
262
  end
111
263
  end
112
264
  end
data/lib/imgix/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Imgix
4
- VERSION = '2.1.0'
4
+ VERSION = "4.0.3"
5
5
  end
data/lib/imgix.rb CHANGED
@@ -1,10 +1,52 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'imgix/version'
4
- require 'imgix/client'
5
- require 'imgix/path'
3
+ require "imgix/version"
4
+ require "imgix/client"
5
+ require "imgix/path"
6
6
 
7
7
  module Imgix
8
- STRATEGIES = [:crc, :cycle]
9
- DOMAIN_REGEX = /^(?:[a-z\d\-_]{1,62}\.){0,125}(?:[a-z\d](?:\-(?=\-*[a-z\d])|[a-z]|\d){0,62}\.)[a-z\d]{1,63}$/i
8
+ # regex pattern used to determine if a domain is valid
9
+ DOMAIN_REGEX = /^(?:[a-z\d\-_]{1,62}\.){0,125}(?:[a-z\d](?:\-(?=\-*[a-z\d])|[a-z]|\d){0,62}\.)[a-z\d]{1,63}$/i.freeze
10
+
11
+ # determines the growth rate when building out srcset pair widths
12
+ DEFAULT_WIDTH_TOLERANCE = 0.08
13
+
14
+ # the default minimum srcset width
15
+ MIN_WIDTH = 100
16
+
17
+ # the default maximum srcset width, also the max width supported by imgix
18
+ MAX_WIDTH = 8192
19
+
20
+ # returns an array of width values used during scrset generation
21
+ TARGET_WIDTHS = lambda { |tolerance, min, max|
22
+ increment_percentage = tolerance || DEFAULT_WIDTH_TOLERANCE
23
+
24
+ unless increment_percentage.is_a?(Numeric) && increment_percentage > 0
25
+ width_increment_error = "error: `width_tolerance` must be a positive `Numeric` value"
26
+ raise ArgumentError, width_increment_error
27
+ end
28
+
29
+ max_size = max || MAX_WIDTH
30
+ resolutions = []
31
+ prev = min || MIN_WIDTH
32
+
33
+ while prev < max_size
34
+ # ensures that each width is even
35
+ resolutions.push(prev.round)
36
+ prev *= 1 + (increment_percentage * 2)
37
+ end
38
+
39
+ resolutions.push(max_size)
40
+ return resolutions
41
+ }
42
+ DEFAULT_TARGET_WIDTHS = TARGET_WIDTHS.call(DEFAULT_WIDTH_TOLERANCE, MIN_WIDTH, MAX_WIDTH).freeze
43
+
44
+ # hash of default quality parameter values mapped by each dpr srcset entry
45
+ DPR_QUALITY = {
46
+ 1 => 75,
47
+ 2 => 50,
48
+ 3 => 35,
49
+ 4 => 23,
50
+ 5 => 20
51
+ }.freeze
10
52
  end
@@ -0,0 +1,11 @@
1
+ $LOAD_PATH << 'lib'
2
+ require 'imgix'
3
+ require 'benchmark/ips'
4
+
5
+ client = Imgix::Client.new(domain: 'domain.com', secure_url_token: 'token')
6
+
7
+ Benchmark.ips do |x|
8
+ x.report('Imgix::Path#initialize') do
9
+ client.path("/img.jpg")
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH << 'lib'
2
+ require 'imgix'
3
+ require 'benchmark/ips'
4
+
5
+ client = Imgix::Client.new(domain: 'domain.com', secure_url_token: 'token')
6
+ path = client.path("/img.jpg")
7
+
8
+ Benchmark.ips do |x|
9
+ x.report('Imgix::Path#to_url') do
10
+ path.to_url({ auto: 'compress,format', fit: 'crop', crop: 'top', w: 590, h: 332 })
11
+ end
12
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: imgix
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 4.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kelly Sutton
@@ -10,39 +10,11 @@ authors:
10
10
  - Antony Denyer
11
11
  - Paul Straw
12
12
  - Sherwin Heydarbeygi
13
- autorequire:
13
+ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
- date: 2019-05-08 00:00:00.000000000 Z
17
- dependencies:
18
- - !ruby/object:Gem::Dependency
19
- name: addressable
20
- requirement: !ruby/object:Gem::Requirement
21
- requirements:
22
- - - ">="
23
- - !ruby/object:Gem::Version
24
- version: '0'
25
- type: :runtime
26
- prerelease: false
27
- version_requirements: !ruby/object:Gem::Requirement
28
- requirements:
29
- - - ">="
30
- - !ruby/object:Gem::Version
31
- version: '0'
32
- - !ruby/object:Gem::Dependency
33
- name: webmock
34
- requirement: !ruby/object:Gem::Requirement
35
- requirements:
36
- - - ">="
37
- - !ruby/object:Gem::Version
38
- version: '0'
39
- type: :development
40
- prerelease: false
41
- version_requirements: !ruby/object:Gem::Requirement
42
- requirements:
43
- - - ">="
44
- - !ruby/object:Gem::Version
45
- version: '0'
16
+ date: 2021-05-05 00:00:00.000000000 Z
17
+ dependencies: []
46
18
  description: Easily create and sign imgix URLs.
47
19
  email:
48
20
  - kelly@imgix.com
@@ -56,7 +28,9 @@ extensions: []
56
28
  extra_rdoc_files: []
57
29
  files:
58
30
  - ".gitignore"
31
+ - ".rubocop.yml"
59
32
  - ".travis.yml"
33
+ - ".vscode/tasks.json"
60
34
  - CHANGELOG.md
61
35
  - Contributing.markdown
62
36
  - Gemfile
@@ -66,19 +40,19 @@ files:
66
40
  - imgix.gemspec
67
41
  - lib/imgix.rb
68
42
  - lib/imgix/client.rb
69
- - lib/imgix/param_helpers.rb
70
43
  - lib/imgix/path.rb
71
44
  - lib/imgix/version.rb
72
- - test/test_helper.rb
73
- - test/units/domains_test.rb
74
- - test/units/path_test.rb
75
- - test/units/purge_test.rb
76
- - test/units/url_test.rb
45
+ - script/bench_path.rb
46
+ - script/bench_to_url.rb
77
47
  homepage: https://github.com/imgix/imgix-rb
78
48
  licenses:
79
49
  - MIT
80
- metadata: {}
81
- post_install_message:
50
+ metadata:
51
+ bug_tracker_uri: https://github.com/imgix/imgix-rb/issues
52
+ changelog_uri: https://github.com/imgix/imgix-rb/blob/main/CHANGELOG.md
53
+ documentation_uri: https://www.rubydoc.info/gems/imgix/4.0.3
54
+ source_code_uri: https://github.com/imgix/imgix-rb/tree/4.0.3
55
+ post_install_message:
82
56
  rdoc_options: []
83
57
  require_paths:
84
58
  - lib
@@ -93,14 +67,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
93
67
  - !ruby/object:Gem::Version
94
68
  version: '0'
95
69
  requirements: []
96
- rubyforge_project:
97
- rubygems_version: 2.6.13
98
- signing_key:
70
+ rubygems_version: 3.1.4
71
+ signing_key:
99
72
  specification_version: 4
100
73
  summary: Official Ruby Gem for easily creating and signing imgix URLs.
101
- test_files:
102
- - test/test_helper.rb
103
- - test/units/domains_test.rb
104
- - test/units/path_test.rb
105
- - test/units/purge_test.rb
106
- - test/units/url_test.rb
74
+ test_files: []
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Imgix
4
- module ParamHelpers
5
- def rect(position)
6
- @options[:rect] = position and return self if position.is_a?(String)
7
-
8
- @options[:rect] = [
9
- position[:x] || position[:left],
10
- position[:y] || position[:top],
11
- position[:width] || (position[:right] - position[:left]),
12
- position[:height] || (position[:bottom] - position[:top])
13
- ].join(',')
14
-
15
- return self
16
- end
17
- end
18
- end