imgix 3.0.0 → 3.1.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 +5 -1
- data/README.md +42 -0
- data/lib/imgix.rb +18 -0
- data/lib/imgix/path.rb +37 -0
- data/lib/imgix/version.rb +1 -1
- data/test/units/srcset_test.rb +226 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c260521282fd6b24c05cf774caaf4b140fef9b5a
|
4
|
+
data.tar.gz: d7b53e8cce58a50020eeba7d9c4ad6aa556dfbb5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 33ff8d7ea4e778dcea4ade90283896b034c40b9d6cbd613920ec2712390b925d39041f996b3d44698a76dd279b829ab1d0a55e86e05dd57fbb2a417a03cf3b7b
|
7
|
+
data.tar.gz: 87ab1ed154e7ea3bfa69538a8904d3f8e9145f3cfa9175b3db60dc9855a20ca0f9845663be9a12eadcf340e8bf3cd1e29de630fa6561c092a0e7e9700a493b22
|
data/CHANGELOG.md
CHANGED
@@ -3,9 +3,13 @@
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
4
4
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
5
5
|
|
6
|
+
## [3.1.0](https://github.com/imgix/imgix-rb/compare/2.1.0...3.1.0) - July 28, 2019
|
7
|
+
|
8
|
+
* feat: add srcset generation ([#47](https://github.com/imgix/imgix-rb/pull/47))
|
9
|
+
|
6
10
|
## [3.0.0](https://github.com/imgix/imgix-rb/compare/2.1.0...3.0.0) - June 7, 2019
|
7
11
|
|
8
|
-
*
|
12
|
+
* fix: remove deprecated domain sharding functionality ([#46](https://github.com/imgix/imgix-rb/pull/46))
|
9
13
|
|
10
14
|
## [2.1.0](https://github.com/imgix/imgix-rb/compare/2.0.0...2.1.0) - May 7, 2019
|
11
15
|
|
data/README.md
CHANGED
@@ -46,6 +46,48 @@ path.defaults.width(300).to_url # Resets parameters
|
|
46
46
|
path.rect(x: 0, y: 50, width: 200, height: 300).to_url # Rect helper
|
47
47
|
```
|
48
48
|
|
49
|
+
## Srcset Generation
|
50
|
+
|
51
|
+
The imgix gem allows for generation of custom `srcset` attributes, which can be invoked through `Imgix::Path#to_srcset`. By default, the `srcset` generated will allow for responsive size switching by building a list of image-width mappings.
|
52
|
+
|
53
|
+
```rb
|
54
|
+
client = Imgix::Client.new(host: 'your-subdomain.imgix.net', secure_url_token: 'your-token', include_library_param: false)
|
55
|
+
path = client.path('/images/demo.png')
|
56
|
+
|
57
|
+
srcset = path.to_srcset
|
58
|
+
```
|
59
|
+
|
60
|
+
Will produce the following attribute value, which can then be served to the client:
|
61
|
+
|
62
|
+
```html
|
63
|
+
https://your-subdomain.imgix.net/images/demo.png?w=100&s=efb3e4ae8eaa1884357f40510b11787c 100w,
|
64
|
+
https://your-subdomain.imgix.net/images/demo.png?w=116&s=1417ebeaaaecff39533408cb44893eda 116w,
|
65
|
+
https://your-subdomain.imgix.net/images/demo.png?w=134&s=4e45e67c087df930b9ddc8cf5be869d0 134w,
|
66
|
+
...
|
67
|
+
https://your-subdomain.imgix.net/images/demo.png?w=7400&s=a5dd7dda1dbac613f0475f1ffd90ef79 7400w,
|
68
|
+
https://your-subdomain.imgix.net/images/demo.png?w=8192&s=9fbd257c53e770e345ce3412b64a3452 8192w
|
69
|
+
```
|
70
|
+
|
71
|
+
In cases where enough information is provided about an image's dimensions, `to_srcset` will instead build a `srcset` that will allow for an image to be served at different resolutions. The parameters taken into consideration when determining if an image is fixed-width are `w`, `h`, and `ar`. By invoking `to_srcset` with either a width **or** the height and aspect ratio provided, a different `srcset` will be generated for a fixed-size image instead.
|
72
|
+
|
73
|
+
```rb
|
74
|
+
client = Imgix::Client.new(host: 'your-subdomain.imgix.net', secure_url_token: 'your-token')
|
75
|
+
path = client.path('/images/demo.png')
|
76
|
+
|
77
|
+
srcset = path.to_srcset(h:800, ar:'3:2')
|
78
|
+
```
|
79
|
+
|
80
|
+
Will produce the following attribute value:
|
81
|
+
|
82
|
+
```html
|
83
|
+
https://your-subdomain.imgix.net/images/demo.png?h=800&ar=3%3A2&s=be8c153bb9ed0dd152e846414a8fdc86 1x,
|
84
|
+
https://your-subdomain.imgix.net/images/demo.png?h=800&ar=3%3A2&s=be8c153bb9ed0dd152e846414a8fdc86 2x,
|
85
|
+
https://your-subdomain.imgix.net/images/demo.png?h=800&ar=3%3A2&s=be8c153bb9ed0dd152e846414a8fdc86 3x,
|
86
|
+
https://your-subdomain.imgix.net/images/demo.png?h=800&ar=3%3A2&s=be8c153bb9ed0dd152e846414a8fdc86 4x,
|
87
|
+
https://your-subdomain.imgix.net/images/demo.png?h=800&ar=3%3A2&s=be8c153bb9ed0dd152e846414a8fdc86 5x
|
88
|
+
```
|
89
|
+
|
90
|
+
For more information to better understand `srcset`, we highly recommend [Eric Portis' "Srcset and sizes" article](https://ericportis.com/posts/2014/srcset-sizes/) which goes into depth about the subject.
|
49
91
|
|
50
92
|
## Multiple Parameters
|
51
93
|
|
data/lib/imgix.rb
CHANGED
@@ -5,5 +5,23 @@ require 'imgix/client'
|
|
5
5
|
require 'imgix/path'
|
6
6
|
|
7
7
|
module Imgix
|
8
|
+
# regex pattern used to determine if a domain is valid
|
8
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
|
10
|
+
|
11
|
+
# returns an array of width values used during scrset generation
|
12
|
+
TARGET_WIDTHS = lambda {
|
13
|
+
increment_percentage = 8
|
14
|
+
max_size = 8192
|
15
|
+
resolutions = []
|
16
|
+
prev = 100
|
17
|
+
|
18
|
+
while(prev <= max_size)
|
19
|
+
# ensures that each width is even
|
20
|
+
resolutions.push((2 * (prev / 2).round))
|
21
|
+
prev *= 1 + ((increment_percentage.to_f) / 100) * 2
|
22
|
+
end
|
23
|
+
|
24
|
+
resolutions.push(max_size)
|
25
|
+
return resolutions
|
26
|
+
}
|
9
27
|
end
|
data/lib/imgix/path.rb
CHANGED
@@ -39,6 +39,7 @@ module Imgix
|
|
39
39
|
|
40
40
|
@path = CGI.escape(@path) if /^https?/ =~ @path
|
41
41
|
@path = "/#{@path}" if @path[0] != '/'
|
42
|
+
@target_widths = TARGET_WIDTHS.call
|
42
43
|
end
|
43
44
|
|
44
45
|
def to_url(opts = {})
|
@@ -83,6 +84,19 @@ module Imgix
|
|
83
84
|
end
|
84
85
|
end
|
85
86
|
|
87
|
+
def to_srcset(params = {})
|
88
|
+
@options.merge!(params)
|
89
|
+
width = @options['w'.to_sym]
|
90
|
+
height = @options['h'.to_sym]
|
91
|
+
aspect_ratio = @options['ar'.to_sym]
|
92
|
+
|
93
|
+
if ((width) || (height && aspect_ratio))
|
94
|
+
build_dpr_srcset(@options)
|
95
|
+
else
|
96
|
+
build_srcset_pairs(@options)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
86
100
|
private
|
87
101
|
|
88
102
|
def signature
|
@@ -108,5 +122,28 @@ module Imgix
|
|
108
122
|
def has_query?
|
109
123
|
query.length > 0
|
110
124
|
end
|
125
|
+
|
126
|
+
def build_srcset_pairs(params = {})
|
127
|
+
srcset = ''
|
128
|
+
for width in @target_widths do
|
129
|
+
currentParams = params || {}
|
130
|
+
currentParams['w'] = width
|
131
|
+
srcset += "#{to_url(currentParams)} #{width}w,\n"
|
132
|
+
end
|
133
|
+
|
134
|
+
return srcset[0..-3]
|
135
|
+
end
|
136
|
+
|
137
|
+
def build_dpr_srcset(params = {})
|
138
|
+
srcset = ''
|
139
|
+
target_ratios = [1,2,3,4,5]
|
140
|
+
url = to_url(params)
|
141
|
+
|
142
|
+
for ratio in target_ratios do
|
143
|
+
srcset += "#{url} #{ratio}x,\n"
|
144
|
+
end
|
145
|
+
|
146
|
+
return srcset[0..-3]
|
147
|
+
end
|
111
148
|
end
|
112
149
|
end
|
data/lib/imgix/version.rb
CHANGED
@@ -0,0 +1,226 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module SrcsetTest
|
4
|
+
|
5
|
+
class SrcsetDefault < Imgix::Test
|
6
|
+
def test_no_parameters
|
7
|
+
srcset = path.to_srcset()
|
8
|
+
expected_number_of_pairs = 31
|
9
|
+
assert_equal expected_number_of_pairs, srcset.split(',').length
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def path
|
14
|
+
@client ||= Imgix::Client.new(host: 'testing.imgix.net', secure_url_token: 'MYT0KEN', include_library_param: false).path('image.jpg')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class SrcsetGivenWidth < Imgix::Test
|
19
|
+
def test_srcset_in_dpr_form
|
20
|
+
device_pixel_ratio = 1
|
21
|
+
|
22
|
+
srcset.split(',').map { |src|
|
23
|
+
ratio = src.split(' ')[1]
|
24
|
+
assert_equal ("#{device_pixel_ratio}x"), ratio
|
25
|
+
device_pixel_ratio += 1
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_srcset_signs_urls
|
30
|
+
expected_signature = 'b95cfd915f4a198442bff4ce5befe5b8'
|
31
|
+
|
32
|
+
srcset.split(',').map { |src|
|
33
|
+
url = src.split(' ')[0]
|
34
|
+
assert_includes url, "s="
|
35
|
+
|
36
|
+
generated_signature = url.slice(url.index("s=")+2, url.length)
|
37
|
+
assert_equal expected_signature, generated_signature
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
def srcset
|
43
|
+
@client ||= Imgix::Client.new(host: 'testing.imgix.net', secure_url_token: 'MYT0KEN', include_library_param: false).path('image.jpg').to_srcset(w:100)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class SrcsetGivenHeight < Imgix::Test
|
48
|
+
def test_srcset_generates_width_pairs
|
49
|
+
expected_number_of_pairs = 31
|
50
|
+
assert_equal expected_number_of_pairs, srcset.split(',').length
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_srcset_respects_height_parameter
|
54
|
+
srcset.split(',').map { |src|
|
55
|
+
assert_includes src, 'h='
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_srcset_within_bounds
|
60
|
+
min, *max = srcset.split(',')
|
61
|
+
|
62
|
+
# parse out the width descriptor as an integer
|
63
|
+
min = min.split(' ')[1].to_i
|
64
|
+
max = max[max.length-1].split(' ')[1].to_i
|
65
|
+
|
66
|
+
assert_operator min, :>=, 100
|
67
|
+
assert_operator max, :<=, 8192
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_srcset_iterates_18_percent
|
71
|
+
increment_allowed = 0.18
|
72
|
+
|
73
|
+
# create an array of widths
|
74
|
+
widths = srcset.split(',').map { |src|
|
75
|
+
src.split(' ')[1].to_i
|
76
|
+
}
|
77
|
+
|
78
|
+
prev = widths[0]
|
79
|
+
|
80
|
+
for i in 1..widths.length-1 do
|
81
|
+
element = widths[i]
|
82
|
+
assert_operator (element / prev), :<, (1 + increment_allowed)
|
83
|
+
prev = element
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_srcset_signs_urls
|
88
|
+
srcset.split(',').map { |srcset_split|
|
89
|
+
src = srcset_split.split(' ')[0]
|
90
|
+
assert_includes src, 's='
|
91
|
+
|
92
|
+
# parses out all parameters except for 's=...'
|
93
|
+
params = src.slice(src.index('?'), src.length)
|
94
|
+
params = params.slice(0, params.index('s=')-1)
|
95
|
+
# parses out the 's=...' parameter
|
96
|
+
generated_signature = src.slice(src.index('s=')+2, src.length)
|
97
|
+
|
98
|
+
signature_base = 'MYT0KEN' + '/image.jpg' + params;
|
99
|
+
expected_signature = Digest::MD5.hexdigest(signature_base)
|
100
|
+
|
101
|
+
assert_equal expected_signature, generated_signature
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
def srcset
|
107
|
+
@client ||= Imgix::Client.new(host: 'testing.imgix.net', secure_url_token: 'MYT0KEN', include_library_param: false).path('image.jpg').to_srcset(h:100)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class SrcsetGivenWidthAndHeight < Imgix::Test
|
112
|
+
def test_srcset_in_dpr_form
|
113
|
+
device_pixel_ratio = 1
|
114
|
+
|
115
|
+
srcset.split(',').map { |src|
|
116
|
+
ratio = src.split(' ')[1]
|
117
|
+
assert_equal ("#{device_pixel_ratio}x"), ratio
|
118
|
+
device_pixel_ratio += 1
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_srcset_signs_urls
|
123
|
+
expected_signature = 'fb081a45c449b28f69e012d474943df3'
|
124
|
+
|
125
|
+
srcset.split(',').map { |src|
|
126
|
+
url = src.split(' ')[0]
|
127
|
+
assert_includes url, "s="
|
128
|
+
|
129
|
+
generated_signature = url.slice(url.index("s=")+2, url.length)
|
130
|
+
assert_equal expected_signature, generated_signature
|
131
|
+
}
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
def srcset
|
136
|
+
@client ||= Imgix::Client.new(host: 'testing.imgix.net', secure_url_token: 'MYT0KEN', include_library_param: false).path('image.jpg').to_srcset(w:100,h:100)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class SrcsetGivenAspectRatio < Imgix::Test
|
141
|
+
def test_srcset_generates_width_pairs
|
142
|
+
expected_number_of_pairs = 31
|
143
|
+
assert_equal expected_number_of_pairs, srcset.split(',').length
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_srcset_within_bounds
|
147
|
+
min, *max = srcset.split(',')
|
148
|
+
|
149
|
+
# parse out the width descriptor as an integer
|
150
|
+
min = min.split(' ')[1].to_i
|
151
|
+
max = max[max.length-1].split(' ')[1].to_i
|
152
|
+
|
153
|
+
assert_operator min, :>=, 100
|
154
|
+
assert_operator max, :<=, 8192
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_srcset_iterates_18_percent
|
158
|
+
increment_allowed = 0.18
|
159
|
+
|
160
|
+
# create an array of widths
|
161
|
+
widths = srcset.split(',').map { |src|
|
162
|
+
src.split(' ')[1].to_i
|
163
|
+
}
|
164
|
+
|
165
|
+
prev = widths[0]
|
166
|
+
|
167
|
+
for i in 1..widths.length-1 do
|
168
|
+
element = widths[i]
|
169
|
+
assert_operator (element / prev), :<, (1 + increment_allowed)
|
170
|
+
prev = element
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def test_srcset_signs_urls
|
175
|
+
srcset.split(',').map { |srcset_split|
|
176
|
+
src = srcset_split.split(' ')[0]
|
177
|
+
assert_includes src, 's='
|
178
|
+
|
179
|
+
# parses out all parameters except for 's=...'
|
180
|
+
params = src.slice(src.index('?'), src.length)
|
181
|
+
params = params.slice(0, params.index('s=')-1)
|
182
|
+
# parses out the 's=...' parameter
|
183
|
+
generated_signature = src.slice(src.index('s=')+2, src.length)
|
184
|
+
|
185
|
+
signature_base = 'MYT0KEN' + '/image.jpg' + params;
|
186
|
+
expected_signature = Digest::MD5.hexdigest(signature_base)
|
187
|
+
|
188
|
+
assert_equal expected_signature, generated_signature
|
189
|
+
}
|
190
|
+
end
|
191
|
+
|
192
|
+
private
|
193
|
+
def srcset
|
194
|
+
@client ||= Imgix::Client.new(host: 'testing.imgix.net', secure_url_token: 'MYT0KEN', include_library_param: false).path('image.jpg').to_srcset(ar:'3:2')
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
class SrcsetGivenAspectRatioAndHeight < Imgix::Test
|
199
|
+
def test_srcset_in_dpr_form
|
200
|
+
device_pixel_ratio = 1
|
201
|
+
|
202
|
+
srcset.split(',').map { |src|
|
203
|
+
ratio = src.split(' ')[1]
|
204
|
+
assert_equal ("#{device_pixel_ratio}x"), ratio
|
205
|
+
device_pixel_ratio += 1
|
206
|
+
}
|
207
|
+
end
|
208
|
+
|
209
|
+
def test_srcset_signs_urls
|
210
|
+
expected_signature = '84db8cb226483fc0130b4fb58e1e6ff2'
|
211
|
+
|
212
|
+
srcset.split(',').map { |src|
|
213
|
+
url = src.split(' ')[0]
|
214
|
+
assert_includes url, "s="
|
215
|
+
|
216
|
+
generated_signature = url.slice(url.index("s=")+2, url.length)
|
217
|
+
assert_equal expected_signature, generated_signature
|
218
|
+
}
|
219
|
+
end
|
220
|
+
|
221
|
+
private
|
222
|
+
def srcset
|
223
|
+
@client ||= Imgix::Client.new(host: 'testing.imgix.net', secure_url_token: 'MYT0KEN', include_library_param: false).path('image.jpg').to_srcset({h:100,ar:'3:2'})
|
224
|
+
end
|
225
|
+
end
|
226
|
+
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: 3.
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kelly Sutton
|
@@ -13,7 +13,7 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date: 2019-
|
16
|
+
date: 2019-07-29 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: addressable
|
@@ -73,6 +73,7 @@ files:
|
|
73
73
|
- test/units/domains_test.rb
|
74
74
|
- test/units/path_test.rb
|
75
75
|
- test/units/purge_test.rb
|
76
|
+
- test/units/srcset_test.rb
|
76
77
|
- test/units/url_test.rb
|
77
78
|
homepage: https://github.com/imgix/imgix-rb
|
78
79
|
licenses:
|
@@ -103,4 +104,5 @@ test_files:
|
|
103
104
|
- test/units/domains_test.rb
|
104
105
|
- test/units/path_test.rb
|
105
106
|
- test/units/purge_test.rb
|
107
|
+
- test/units/srcset_test.rb
|
106
108
|
- test/units/url_test.rb
|