imgix 3.3.1 → 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.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -0
- data/.travis.yml +3 -5
- data/.vscode/tasks.json +29 -0
- data/CHANGELOG.md +30 -0
- data/Gemfile +6 -1
- data/README.md +17 -46
- data/Rakefile +2 -0
- data/imgix.gemspec +19 -22
- data/lib/imgix.rb +5 -4
- data/lib/imgix/client.rb +65 -51
- data/lib/imgix/path.rb +130 -86
- data/lib/imgix/version.rb +1 -1
- data/script/bench_path.rb +11 -0
- data/script/bench_to_url.rb +12 -0
- metadata +14 -58
- data/.github/CODEOWNERS +0 -2
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -28
- data/.github/ISSUE_TEMPLATE/feature_request.md +0 -27
- data/.github/ISSUE_TEMPLATE/question.md +0 -17
- data/.github/pull_request_template.md +0 -73
- data/lib/imgix/param_helpers.rb +0 -19
- data/test/test_helper.rb +0 -13
- data/test/units/domains_test.rb +0 -17
- data/test/units/param_helpers_test.rb +0 -23
- data/test/units/path_test.rb +0 -182
- data/test/units/purge_test.rb +0 -25
- data/test/units/srcset_test.rb +0 -755
- data/test/units/url_test.rb +0 -80
data/lib/imgix/path.rb
CHANGED
@@ -1,55 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
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
|
-
|
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
|
-
}.freeze
|
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
|
-
@target_widths = TARGET_WIDTHS.call(DEFAULT_WIDTH_TOLERANCE, MIN_WIDTH, MAX_WIDTH)
|
43
15
|
end
|
44
16
|
|
45
17
|
def to_url(opts = {})
|
18
|
+
sanitized_path = sanitize_path(@path)
|
46
19
|
prev_options = @options.dup
|
47
20
|
@options.merge!(opts)
|
48
21
|
|
49
|
-
|
22
|
+
current_path_and_params = path_and_params(sanitized_path)
|
23
|
+
url = @prefix + current_path_and_params
|
50
24
|
|
51
25
|
if @secure_url_token
|
52
|
-
url += (has_query? ?
|
26
|
+
url += (has_query? ? "&" : "?") + "s=#{signature(current_path_and_params)}"
|
53
27
|
end
|
54
28
|
|
55
29
|
@options = prev_options
|
@@ -61,61 +35,139 @@ module Imgix
|
|
61
35
|
self
|
62
36
|
end
|
63
37
|
|
38
|
+
def ixlib(lib_version)
|
39
|
+
@options[:ixlib] = lib_version
|
40
|
+
end
|
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.
|
64
102
|
def method_missing(method, *args, &block)
|
65
103
|
key = method.to_s.gsub('=', '')
|
66
|
-
|
104
|
+
|
105
|
+
if args.length == 0 # Get, or
|
67
106
|
return @options[key]
|
68
|
-
elsif args.first.nil? && @options.has_key?(key)
|
107
|
+
elsif args.first.nil? && @options.has_key?(key) # Delete, or
|
69
108
|
@options.delete(key) and return self
|
70
109
|
end
|
71
110
|
|
72
|
-
@options[key] = args.join(',')
|
111
|
+
@options[key] = args.join(',') # Set the option.
|
73
112
|
self
|
74
113
|
end
|
75
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])`.
|
76
117
|
ALIASES.each do |from, to|
|
77
118
|
define_method from do |*args|
|
78
|
-
warn "Warning: `Path.#{from}' has been deprecated and " \
|
79
|
-
"will be removed in the next major version (along " \
|
80
|
-
"with all parameter `ALIASES`).\n"
|
81
119
|
self.send(to, *args)
|
82
120
|
end
|
83
121
|
|
122
|
+
# E.g. `path.width = 100` would result in `send(":w=", [100])`.
|
84
123
|
define_method "#{from}=" do |*args|
|
85
|
-
warn "Warning: `Path.#{from}=' has been deprecated and " \
|
86
|
-
"will be removed in the next major version (along " \
|
87
|
-
"with all parameter `ALIASES`).\n"
|
88
124
|
self.send("#{to}=", *args)
|
89
125
|
return self
|
90
126
|
end
|
91
127
|
end
|
92
128
|
|
93
|
-
|
94
|
-
prev_options = @options.dup
|
95
|
-
@options.merge!(params)
|
96
|
-
|
97
|
-
width = @options[:w]
|
98
|
-
height = @options[:h]
|
99
|
-
aspect_ratio = @options[:ar]
|
129
|
+
private
|
100
130
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
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
|
145
|
+
end
|
106
146
|
|
107
|
-
|
108
|
-
|
147
|
+
# URL encode the entire path
|
148
|
+
def encode_URI_Component(path)
|
149
|
+
return "/" + ERB::Util.url_encode(path)
|
109
150
|
end
|
110
151
|
|
111
|
-
|
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
|
112
164
|
|
113
|
-
def signature
|
114
|
-
Digest::MD5.hexdigest(@secure_url_token +
|
165
|
+
def signature(rest)
|
166
|
+
Digest::MD5.hexdigest(@secure_url_token + rest)
|
115
167
|
end
|
116
168
|
|
117
|
-
def path_and_params
|
118
|
-
has_query? ? "#{
|
169
|
+
def path_and_params(path)
|
170
|
+
has_query? ? "#{path}?#{query}" : path
|
119
171
|
end
|
120
172
|
|
121
173
|
def query
|
@@ -127,15 +179,15 @@ module Imgix
|
|
127
179
|
else
|
128
180
|
escaped_key << "=" << ERB::Util.url_encode(val.to_s)
|
129
181
|
end
|
130
|
-
end.join(
|
182
|
+
end.join("&")
|
131
183
|
end
|
132
184
|
|
133
185
|
def has_query?
|
134
|
-
query.
|
186
|
+
!query.empty?
|
135
187
|
end
|
136
188
|
|
137
189
|
def build_srcset_pairs(options:, params:)
|
138
|
-
srcset =
|
190
|
+
srcset = ""
|
139
191
|
|
140
192
|
widths = options[:widths] || []
|
141
193
|
width_tolerance = options[:width_tolerance] || DEFAULT_WIDTH_TOLERANCE
|
@@ -150,10 +202,10 @@ module Imgix
|
|
150
202
|
validate_width_tolerance!(width_tolerance)
|
151
203
|
srcset_widths = TARGET_WIDTHS.call(width_tolerance, min_width, max_width)
|
152
204
|
else
|
153
|
-
srcset_widths =
|
205
|
+
srcset_widths = DEFAULT_TARGET_WIDTHS
|
154
206
|
end
|
155
207
|
|
156
|
-
|
208
|
+
srcset_widths.each do |width|
|
157
209
|
params[:w] = width
|
158
210
|
srcset += "#{to_url(params)} #{width}w,\n"
|
159
211
|
end
|
@@ -162,7 +214,7 @@ module Imgix
|
|
162
214
|
end
|
163
215
|
|
164
216
|
def build_dpr_srcset(options:, params:)
|
165
|
-
srcset =
|
217
|
+
srcset = ""
|
166
218
|
|
167
219
|
disable_variable_quality = options[:disable_variable_quality] || false
|
168
220
|
validate_variable_qualities!(disable_variable_quality)
|
@@ -170,12 +222,10 @@ module Imgix
|
|
170
222
|
target_ratios = [1, 2, 3, 4, 5]
|
171
223
|
quality = params[:q]
|
172
224
|
|
173
|
-
|
225
|
+
target_ratios.each do |ratio|
|
174
226
|
params[:dpr] = ratio
|
175
227
|
|
176
|
-
unless disable_variable_quality
|
177
|
-
params[:q] = quality || DPR_QUALITY[ratio]
|
178
|
-
end
|
228
|
+
params[:q] = quality || DPR_QUALITY[ratio] unless disable_variable_quality
|
179
229
|
|
180
230
|
srcset += "#{to_url(params)} #{ratio}x,\n"
|
181
231
|
end
|
@@ -184,34 +234,28 @@ module Imgix
|
|
184
234
|
end
|
185
235
|
|
186
236
|
def validate_width_tolerance!(width_tolerance)
|
187
|
-
width_increment_error =
|
237
|
+
width_increment_error = "error: `width_tolerance` must be a positive `Numeric` value"
|
188
238
|
|
189
|
-
if !width_tolerance.is_a?(Numeric) || width_tolerance <= 0
|
190
|
-
raise ArgumentError, width_increment_error
|
191
|
-
end
|
239
|
+
raise ArgumentError, width_increment_error if !width_tolerance.is_a?(Numeric) || width_tolerance <= 0
|
192
240
|
end
|
193
241
|
|
194
242
|
def validate_widths!(widths)
|
195
|
-
widths_error =
|
243
|
+
widths_error = "error: `widths` must be an array of positive `Numeric` values"
|
196
244
|
raise ArgumentError, widths_error unless widths.is_a?(Array)
|
197
245
|
|
198
246
|
all_positive_integers = widths.all? { |i| i.is_a?(Integer) && i > 0 }
|
199
247
|
raise ArgumentError, widths_error unless all_positive_integers
|
200
248
|
end
|
201
249
|
|
202
|
-
def validate_range!(
|
203
|
-
range_numeric_error =
|
204
|
-
unless
|
205
|
-
raise ArgumentError, range_numeric_error
|
206
|
-
end
|
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)
|
207
253
|
|
208
|
-
unless
|
209
|
-
raise ArgumentError, range_numeric_error
|
210
|
-
end
|
254
|
+
raise ArgumentError, range_numeric_error unless min_width > 0 && max_width > 0
|
211
255
|
end
|
212
256
|
|
213
257
|
def validate_variable_qualities!(disable_quality)
|
214
|
-
disable_quality_error =
|
258
|
+
disable_quality_error = "error: `disable_quality` must be a Boolean value"
|
215
259
|
unless disable_quality.is_a?(TrueClass) || disable_quality.is_a?(FalseClass)
|
216
260
|
raise ArgumentError, disable_quality_error
|
217
261
|
end
|
data/lib/imgix/version.rb
CHANGED
@@ -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:
|
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:
|
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
|
@@ -55,13 +27,10 @@ executables: []
|
|
55
27
|
extensions: []
|
56
28
|
extra_rdoc_files: []
|
57
29
|
files:
|
58
|
-
- ".github/CODEOWNERS"
|
59
|
-
- ".github/ISSUE_TEMPLATE/bug_report.md"
|
60
|
-
- ".github/ISSUE_TEMPLATE/feature_request.md"
|
61
|
-
- ".github/ISSUE_TEMPLATE/question.md"
|
62
|
-
- ".github/pull_request_template.md"
|
63
30
|
- ".gitignore"
|
31
|
+
- ".rubocop.yml"
|
64
32
|
- ".travis.yml"
|
33
|
+
- ".vscode/tasks.json"
|
65
34
|
- CHANGELOG.md
|
66
35
|
- Contributing.markdown
|
67
36
|
- Gemfile
|
@@ -71,25 +40,19 @@ files:
|
|
71
40
|
- imgix.gemspec
|
72
41
|
- lib/imgix.rb
|
73
42
|
- lib/imgix/client.rb
|
74
|
-
- lib/imgix/param_helpers.rb
|
75
43
|
- lib/imgix/path.rb
|
76
44
|
- lib/imgix/version.rb
|
77
|
-
-
|
78
|
-
-
|
79
|
-
- test/units/param_helpers_test.rb
|
80
|
-
- test/units/path_test.rb
|
81
|
-
- test/units/purge_test.rb
|
82
|
-
- test/units/srcset_test.rb
|
83
|
-
- test/units/url_test.rb
|
45
|
+
- script/bench_path.rb
|
46
|
+
- script/bench_to_url.rb
|
84
47
|
homepage: https://github.com/imgix/imgix-rb
|
85
48
|
licenses:
|
86
49
|
- MIT
|
87
50
|
metadata:
|
88
51
|
bug_tracker_uri: https://github.com/imgix/imgix-rb/issues
|
89
52
|
changelog_uri: https://github.com/imgix/imgix-rb/blob/main/CHANGELOG.md
|
90
|
-
documentation_uri: https://www.rubydoc.info/gems/imgix/
|
91
|
-
source_code_uri: https://github.com/imgix/imgix-rb/tree/
|
92
|
-
post_install_message:
|
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:
|
93
56
|
rdoc_options: []
|
94
57
|
require_paths:
|
95
58
|
- lib
|
@@ -104,15 +67,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
67
|
- !ruby/object:Gem::Version
|
105
68
|
version: '0'
|
106
69
|
requirements: []
|
107
|
-
rubygems_version: 3.1.
|
108
|
-
signing_key:
|
70
|
+
rubygems_version: 3.1.4
|
71
|
+
signing_key:
|
109
72
|
specification_version: 4
|
110
73
|
summary: Official Ruby Gem for easily creating and signing imgix URLs.
|
111
|
-
test_files:
|
112
|
-
- test/test_helper.rb
|
113
|
-
- test/units/domains_test.rb
|
114
|
-
- test/units/param_helpers_test.rb
|
115
|
-
- test/units/path_test.rb
|
116
|
-
- test/units/purge_test.rb
|
117
|
-
- test/units/srcset_test.rb
|
118
|
-
- test/units/url_test.rb
|
74
|
+
test_files: []
|