imgix-rails 1.1.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +49 -43
- data/lib/imgix/rails/image_tag.rb +13 -0
- data/lib/imgix/rails/picture_tag.rb +28 -0
- data/lib/imgix/rails/tag.rb +162 -0
- data/lib/imgix/rails/version.rb +1 -1
- data/lib/imgix/rails/view_helper.rb +6 -43
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 62c3df395875ff9ec0422abe8b6b5ab60ddc8a0c
|
4
|
+
data.tar.gz: 285cbe4283c1caad13a3266dfe150e1726a6977f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c3ecb91c1f1452f5a026bf77590d56987ab2946d7875276a95784ab9dec52c89d245ae3b73a002199513addca758848ac4fcb588570440106b076519a32154da
|
7
|
+
data.tar.gz: 26927455ee9b481d06a6427176876d2f2ee5c45c28c5f96af2cada5c35eeae582de03da29ecb8649787785a855db001b7bf6387132d06c7ba65afaddb9759674
|
data/README.md
CHANGED
@@ -12,12 +12,11 @@ We recommend using something like [Paperclip](https://github.com/thoughtbot/pape
|
|
12
12
|
* [Usage](#usage)
|
13
13
|
* [Configuration](#configuration)
|
14
14
|
* [ix_image_tag](#ix_image_tag)
|
15
|
-
* [ix_responsive_image_tag](#ix_responsive_image_tag)
|
16
15
|
* [ix_picture_tag](#ix_picture_tag)
|
17
16
|
* [ix_image_url](#ix_image_url)
|
18
17
|
* [Hostname Removal](#hostname-removal)
|
19
18
|
* [Using With Image Uploading Libraries](#using-with-image-uploading-libraries)
|
20
|
-
* [Paperclip](#paperclip)
|
19
|
+
* [Paperclip and CarrierWave](#paperclip-and-carrierwave)
|
21
20
|
* [Refile](#refile)
|
22
21
|
* [Development](#development)
|
23
22
|
* [Contributing](#contributing)
|
@@ -65,16 +64,28 @@ The following configuration flags will be respected:
|
|
65
64
|
<a name="ix_image_tag"></a>
|
66
65
|
### ix_image_tag
|
67
66
|
|
68
|
-
The
|
67
|
+
The `ix_image_tag` helper method makes it easy to pass parameters to imgix to handle resizing, cropping, etc. It also simplifies adding responsive imagery to your Rails app by automatically generating a `srcset` based on the parameters you pass. We talk a bit about using the `srcset` attribute in an application in the following blog post: [“Responsive Images with `srcset` and imgix.”](http://blog.imgix.com/post/127012184664/responsive-images-with-srcset-imgix).
|
68
|
+
|
69
|
+
`ix_image_tag` generates `<img>` tags with a filled-out `srcset` attribute that leans on imgix to do the hard work. If you already know the minimum or maximum number of physical pixels that this image will need to be displayed at, you can pass the `min_width` and/or `max_width` options. This will result in a smaller, more tailored `srcset`.
|
69
70
|
|
70
71
|
```erb
|
71
|
-
<%= ix_image_tag('/
|
72
|
+
<%= ix_image_tag('/unsplash/hotairballoon.jpg', { w: 300, h: 500, fit: 'crop', crop: 'right', alt: 'A hot air balloon on a sunny day' }) %>
|
72
73
|
```
|
73
74
|
|
74
75
|
Will render out HTML like the following:
|
75
76
|
|
76
77
|
```html
|
77
|
-
<img
|
78
|
+
<img
|
79
|
+
alt="A hot air balloon on a sunny day"
|
80
|
+
sizes="100vw"
|
81
|
+
srcset="
|
82
|
+
https://assets.imgix.net/unsplash/hotairballoon.jpg?w=100&h=167&fit=crop&crop=right 100w,
|
83
|
+
https://assets.imgix.net/unsplash/hotairballoon.jpg?w=200&h=333&fit=crop&crop=right 200w,
|
84
|
+
…
|
85
|
+
https://assets.imgix.net/unsplash/hotairballoon.jpg?w=2560&h=4267&fit=crop&crop=right 2560w
|
86
|
+
"
|
87
|
+
src="https://assets.imgix.net/unsplash/hotairballoon.jpg?w=300&h=500&fit=crop&crop=right"
|
88
|
+
>
|
78
89
|
```
|
79
90
|
|
80
91
|
We recommend leveraging this to generate powerful helpers within your application like the following:
|
@@ -91,51 +102,46 @@ Then rendering the portrait in your application is very easy:
|
|
91
102
|
<%= profile_image_tag(@user) %>
|
92
103
|
```
|
93
104
|
|
94
|
-
<a name="ix_responsive_image_tag"></a>
|
95
|
-
### ix_responsive_image_tag
|
96
|
-
|
97
|
-
The `ix_responsive_image_tag` helper method makes it easy to bring responsive imagery to your Rails app. We talk a bit about using the `srcset` attribute in an application in the following blog post: [“Responsive Images with `srcset` and imgix.”](http://blog.imgix.com/post/127012184664/responsive-images-with-srcset-imgix)
|
98
|
-
|
99
|
-
The `ix_responsive_image_tag` will generate an `<img>` element with a filled-out `srcset` attribute that leans on imgix to do the hard work.
|
100
|
-
|
101
|
-
It will use the configured device-pixel-ratios in the `config.imgix[:responsive_resolutions]` value. It will default to `[1, 2]`.
|
102
|
-
|
103
|
-
```erb
|
104
|
-
<%= ix_responsive_image_tag('/users/1/avatar.png', { w: 400, h: 300 }) %>
|
105
|
-
```
|
106
|
-
|
107
|
-
This will generate the following HTML:
|
108
|
-
|
109
|
-
```html
|
110
|
-
<img
|
111
|
-
srcset="https://assets.imgix.net/users/1/avatar.png?w=400&h=300 1x,
|
112
|
-
https://assets.imgix.net/users/1/avatar.png?w=400&h=300&dpr=2 2x"
|
113
|
-
src="https://assets.imgix.net/users/1/avatar.png?w=400&h=300"
|
114
|
-
/>
|
115
|
-
```
|
116
105
|
|
117
106
|
<a name="ix_picture_tag"></a>
|
118
107
|
### ix_picture_tag
|
119
108
|
|
120
|
-
The `ix_picture_tag` helper method makes it easy to generate
|
109
|
+
The `ix_picture_tag` helper method makes it easy to generate `picture` elements in your Rails app. `picture` elements are useful when an images needs to be art directed differently at different screen sizes.
|
121
110
|
|
122
|
-
|
111
|
+
`ix_picture_tag` takes four arguments:
|
123
112
|
|
124
|
-
|
113
|
+
* `source`: The path or URL of the image to display.
|
114
|
+
* `picture_tag_options`: Any options to apply to the parent `picture` element. This is useful for adding class names, etc.
|
115
|
+
* `imgix_default_options`: Default imgix options. These will be used to generate a fallback `img` tag for older browsers, and used in each `source` unless overridden by `breakpoints`.
|
116
|
+
* `breakpoints`: A hash describing the variants. Each key must be a media query (e.g. `(max-width: 880px)`), and each value must be a hash of param overrides for that media query. A `source` element will be generated for each breakpoint specified.
|
125
117
|
|
126
118
|
```erb
|
127
|
-
<%= ix_picture_tag('
|
119
|
+
<%= ix_picture_tag('bertandernie.jpg',
|
120
|
+
picture_tag_options: {
|
121
|
+
class: 'a-picture-tag'
|
122
|
+
},
|
123
|
+
imgix_default_options: {
|
124
|
+
w: 300,
|
125
|
+
h: 300,
|
126
|
+
fit: 'crop',
|
127
|
+
},
|
128
|
+
breakpoints: {
|
129
|
+
'(max-width: 640px)' => {
|
130
|
+
h: 100,
|
131
|
+
sizes: 'calc(100vw - 20px)'
|
132
|
+
},
|
133
|
+
'(max-width: 880px)' => {
|
134
|
+
crop: 'right',
|
135
|
+
sizes: 'calc(100vw - 20px - 50%)'
|
136
|
+
},
|
137
|
+
'(min-width: 881px)' => {
|
138
|
+
crop: 'left',
|
139
|
+
sizes: '430px'
|
140
|
+
}
|
141
|
+
}
|
142
|
+
) %>
|
128
143
|
```
|
129
144
|
|
130
|
-
Will generate the following HTML:
|
131
|
-
|
132
|
-
```html
|
133
|
-
<picture>
|
134
|
-
<source srcset="https://assets.imgix.net/users/1/avatar.png?w=400&h=300 1x,
|
135
|
-
https://assets.imgix.net/users/1/avatar.png?w=400&h=300&dpr=2 2x" />
|
136
|
-
<img src="https://assets.imgix.net/users/1/avatar.png?w=400&h=300" />
|
137
|
-
</picture>
|
138
|
-
```
|
139
145
|
|
140
146
|
<a name="ix_image_url"></a>
|
141
147
|
### ix_image_url
|
@@ -201,10 +207,10 @@ Renders:
|
|
201
207
|
imgix-rails plays well with image uploading libraries, because it just requires a URL and optional parameters as arguments. A good way to handle this interaction is by creating helpers that bridge between your uploading library of choice and imgix-rails. Below are examples of how this can work with some common libraries. Please submit an issue if you'd like to see specific examples for another!
|
202
208
|
|
203
209
|
|
204
|
-
<a name="paperclip"></a>
|
205
|
-
### Paperclip
|
210
|
+
<a name="paperclip-and-carrierwave"></a>
|
211
|
+
### Paperclip and CarrierWave
|
206
212
|
|
207
|
-
Paperclip can directly provide paths to uploaded images, so we can use
|
213
|
+
Paperclip and CarrierWave can directly provide paths to uploaded images, so we can use them with imgix-rails without a bridge.
|
208
214
|
|
209
215
|
``` html
|
210
216
|
<%= ix_image_tag(@user.avatar.path, { auto: 'format', fit: 'crop', w: 500}) %>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "imgix/rails/tag"
|
2
|
+
|
3
|
+
class Imgix::Rails::ImageTag < Imgix::Rails::Tag
|
4
|
+
def render
|
5
|
+
@options[:srcset] = srcset
|
6
|
+
@options[:sizes] ||= '100vw'
|
7
|
+
|
8
|
+
@source = replace_hostname(@source)
|
9
|
+
normal_opts = @options.slice!(*self.class.available_parameters)
|
10
|
+
|
11
|
+
image_tag(ix_image_url(@source, @options), normal_opts)
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "imgix/rails/tag"
|
2
|
+
require "imgix/rails/image_tag"
|
3
|
+
|
4
|
+
class Imgix::Rails::PictureTag < Imgix::Rails::Tag
|
5
|
+
include ActionView::Context
|
6
|
+
|
7
|
+
def initialize(source, options, default_options, breakpoints)
|
8
|
+
@source = source
|
9
|
+
@options = options
|
10
|
+
@default_options = default_options
|
11
|
+
@breakpoints = breakpoints
|
12
|
+
end
|
13
|
+
|
14
|
+
def render
|
15
|
+
content_tag(:picture, @options) do
|
16
|
+
@breakpoints.each do |media, opts|
|
17
|
+
html_opts = opts.except(*self.class.available_parameters)
|
18
|
+
html_opts[:media] ||= media
|
19
|
+
html_opts[:srcset] ||= srcset(@default_options.clone.merge(opts))
|
20
|
+
|
21
|
+
|
22
|
+
concat(content_tag(:source, nil, html_opts))
|
23
|
+
end
|
24
|
+
|
25
|
+
concat Imgix::Rails::ImageTag.new(@source, @default_options).render
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require "imgix/rails/url_helper"
|
2
|
+
|
3
|
+
class Imgix::Rails::Tag
|
4
|
+
include Imgix::Rails::UrlHelper
|
5
|
+
include ActionView::Helpers
|
6
|
+
|
7
|
+
@@parameters = nil
|
8
|
+
|
9
|
+
# Store our parameter information on the class instance so that
|
10
|
+
# each instance of any this class or our subclasses doesn't have to
|
11
|
+
# go back to disk to get this configuration information
|
12
|
+
def self.available_parameters
|
13
|
+
@@available_parameters ||= parameters.keys
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.parameters
|
17
|
+
return @@parameters if @@parameters
|
18
|
+
|
19
|
+
path = File.expand_path("../../../../vendor/parameters.json", __FILE__)
|
20
|
+
@@parameters ||= JSON.parse(File.read(path), symbolize_names: true)[:parameters]
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(source, options={})
|
24
|
+
@source = source
|
25
|
+
@options = options
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
def srcset(opts=@options)
|
31
|
+
@source = replace_hostname(@source)
|
32
|
+
target_widths.map do |target_width|
|
33
|
+
srcset_options = opts.slice(*self.class.available_parameters)
|
34
|
+
srcset_options[:w] = target_width
|
35
|
+
|
36
|
+
if opts[:w].present? && opts[:h].present?
|
37
|
+
srcset_options[:h] = (target_width * (opts[:h].to_f / opts[:w])).round
|
38
|
+
end
|
39
|
+
|
40
|
+
"#{ix_image_url(@source, srcset_options)} #{target_width}w"
|
41
|
+
end.join(', ')
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
MAXIMUM_SCREEN_WIDTH = 2560 * 2 # Physical resolution of 27" iMac (2016)
|
47
|
+
SCREEN_STEP = 100
|
48
|
+
|
49
|
+
# Taken from http://mydevice.io/devices/
|
50
|
+
|
51
|
+
# Phones
|
52
|
+
IPHONE = { css_width: 320, dpr: 1 }
|
53
|
+
IPHONE_4 = { css_width: 320, dpr: 2 }
|
54
|
+
IPHONE_6 = { css_width: 375, dpr: 2 }
|
55
|
+
LG_G3 = { css_width: 360, dpr: 4 }
|
56
|
+
|
57
|
+
# Phablets
|
58
|
+
IPHONE_6_PLUS = { css_width: 414, dpr: 3 }
|
59
|
+
IPHONE_6_PLUS_LANDSCAPE = { css_width: 736, dpr: 3 }
|
60
|
+
MOTO_NEXUS_6 = { css_width: 412, dpr: 3.5 }
|
61
|
+
MOTO_NEXUS_6_LANDSCAPE = { css_width: 690, dpr: 3.5 }
|
62
|
+
LUMIA_1520 = { css_width: 432, dpr: 2.5 }
|
63
|
+
LUMIA_1520_LANDSCAPE = { css_width: 768, dpr: 2.5 }
|
64
|
+
GALAXY_NOTE_3 = { css_width: 360, dpr: 3 }
|
65
|
+
GALAXY_NOTE_3_LANDSCAPE = { css_width: 640, dpr: 3 }
|
66
|
+
GALAXY_NOTE_4 = { css_width: 360, dpr: 4 }
|
67
|
+
GALAXY_NOTE_4_LANDSCAPE = { css_width: 640, dpr: 4 }
|
68
|
+
|
69
|
+
# Tablets
|
70
|
+
IPAD = { css_width: 768, dpr: 1 };
|
71
|
+
IPAD_LANDSCAPE = { css_width: 1024, dpr: 1 };
|
72
|
+
IPAD_3 = { css_width: 768, dpr: 2 };
|
73
|
+
IPAD_3_LANDSCAPE = { css_width: 1024, dpr: 2 };
|
74
|
+
IPAD_PRO = { css_width: 1024, dpr: 2 };
|
75
|
+
IPAD_PRO_LANDSCAPE = { css_width: 1366, dpr: 2 };
|
76
|
+
|
77
|
+
BOOTSTRAP_SM = { css_width: 576, dpr: 1 }
|
78
|
+
BOOTSTRAP_MD = { css_width: 720, dpr: 1 }
|
79
|
+
BOOTSTRAP_LG = { css_width: 940, dpr: 1 }
|
80
|
+
BOOTSTRAP_XL = { css_width: 1140, dpr: 1 }
|
81
|
+
|
82
|
+
def devices
|
83
|
+
phones + phablets + tablets + bootstrap_breaks
|
84
|
+
end
|
85
|
+
|
86
|
+
def bootstrap_breaks
|
87
|
+
breaks = [
|
88
|
+
BOOTSTRAP_SM,
|
89
|
+
BOOTSTRAP_MD,
|
90
|
+
BOOTSTRAP_LG,
|
91
|
+
BOOTSTRAP_XL
|
92
|
+
]
|
93
|
+
|
94
|
+
breaks + breaks.map { |b| b[:dpr] = 2; b }
|
95
|
+
end
|
96
|
+
|
97
|
+
def phones
|
98
|
+
[
|
99
|
+
IPHONE,
|
100
|
+
IPHONE_4,
|
101
|
+
IPHONE_6,
|
102
|
+
LG_G3
|
103
|
+
]
|
104
|
+
end
|
105
|
+
|
106
|
+
def phablets
|
107
|
+
[
|
108
|
+
IPHONE_6_PLUS,
|
109
|
+
IPHONE_6_PLUS_LANDSCAPE,
|
110
|
+
MOTO_NEXUS_6,
|
111
|
+
MOTO_NEXUS_6_LANDSCAPE,
|
112
|
+
LUMIA_1520,
|
113
|
+
LUMIA_1520_LANDSCAPE,
|
114
|
+
GALAXY_NOTE_3,
|
115
|
+
GALAXY_NOTE_3_LANDSCAPE,
|
116
|
+
GALAXY_NOTE_4,
|
117
|
+
GALAXY_NOTE_4_LANDSCAPE
|
118
|
+
]
|
119
|
+
end
|
120
|
+
|
121
|
+
def tablets
|
122
|
+
[
|
123
|
+
IPAD,
|
124
|
+
IPAD_LANDSCAPE,
|
125
|
+
IPAD_3,
|
126
|
+
IPAD_3_LANDSCAPE,
|
127
|
+
IPAD_PRO,
|
128
|
+
IPAD_PRO_LANDSCAPE
|
129
|
+
]
|
130
|
+
end
|
131
|
+
|
132
|
+
# Return the widths to generate given the input `sizes`
|
133
|
+
# attribute.
|
134
|
+
#
|
135
|
+
# @return {Array} An array of {Fixnum} instances representing the unique `srcset` URLs to generate.
|
136
|
+
def target_widths
|
137
|
+
min_screen_width_required = @options[:min_width] || SCREEN_STEP
|
138
|
+
max_screen_width_required = @options[:max_width] || MAXIMUM_SCREEN_WIDTH
|
139
|
+
|
140
|
+
(device_widths + screen_widths).select do |w|
|
141
|
+
w <= max_screen_width_required && w >= min_screen_width_required
|
142
|
+
end.compact.uniq.sort
|
143
|
+
end
|
144
|
+
|
145
|
+
def device_widths
|
146
|
+
devices.map do |device|
|
147
|
+
(device[:css_width] * device[:dpr]).round
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# Generates an array of physical screen widths to represent
|
152
|
+
# the different potential viewport sizes.
|
153
|
+
#
|
154
|
+
# We step by `SCREEN_STEP` to give some sanity to the amount
|
155
|
+
# of widths we output.
|
156
|
+
#
|
157
|
+
# The upper bound is the widest known screen on the planet.
|
158
|
+
# @return {Array} An array of {Fixnum} instances
|
159
|
+
def screen_widths
|
160
|
+
(0..MAXIMUM_SCREEN_WIDTH).step(SCREEN_STEP).to_a + [MAXIMUM_SCREEN_WIDTH]
|
161
|
+
end
|
162
|
+
end
|
data/lib/imgix/rails/version.rb
CHANGED
@@ -1,55 +1,18 @@
|
|
1
1
|
require "imgix"
|
2
|
-
require "imgix/rails/
|
2
|
+
require "imgix/rails/image_tag"
|
3
|
+
require "imgix/rails/picture_tag"
|
3
4
|
|
4
5
|
module Imgix
|
5
6
|
module Rails
|
6
|
-
|
7
|
+
module ViewHelper
|
7
8
|
include UrlHelper
|
8
9
|
|
9
10
|
def ix_image_tag(source, options={})
|
10
|
-
source
|
11
|
-
normal_opts = options.slice!(*available_parameters)
|
12
|
-
|
13
|
-
image_tag(ix_image_url(source, options), normal_opts)
|
14
|
-
end
|
15
|
-
|
16
|
-
def ix_responsive_image_tag(source, options={})
|
17
|
-
options.merge!({
|
18
|
-
srcset: srcset_for(source, options)
|
19
|
-
})
|
20
|
-
|
21
|
-
ix_image_tag(source, options)
|
22
|
-
end
|
23
|
-
|
24
|
-
def ix_picture_tag(source, options={})
|
25
|
-
content_tag(:picture) do
|
26
|
-
concat(tag(:source, srcset: srcset_for(source, options)))
|
27
|
-
concat(ix_image_tag(source, options))
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
def available_parameters
|
34
|
-
@available_parameters ||= parameters.keys
|
35
|
-
end
|
36
|
-
|
37
|
-
def parameters
|
38
|
-
path = File.expand_path("../../../../vendor/parameters.json", __FILE__)
|
39
|
-
@parameters ||= JSON.parse(File.read(path), symbolize_names: true)[:parameters]
|
40
|
-
end
|
41
|
-
|
42
|
-
def srcset_for(source, options={})
|
43
|
-
source = replace_hostname(source)
|
44
|
-
configured_resolutions.map do |resolution|
|
45
|
-
srcset_options = options.slice(*available_parameters)
|
46
|
-
srcset_options[:dpr] = resolution unless resolution == 1
|
47
|
-
"#{ix_image_url(source, srcset_options)} #{resolution}x"
|
48
|
-
end.join(', ')
|
11
|
+
Imgix::Rails::ImageTag.new(source, options).render
|
49
12
|
end
|
50
13
|
|
51
|
-
def
|
52
|
-
|
14
|
+
def ix_picture_tag(source, picture_tag_options:, imgix_default_options:, breakpoints:)
|
15
|
+
Imgix::Rails::PictureTag.new(source, picture_tag_options, imgix_default_options, breakpoints).render
|
53
16
|
end
|
54
17
|
end
|
55
18
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: imgix-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kelly Sutton
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-05-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: imgix
|
@@ -107,6 +107,9 @@ files:
|
|
107
107
|
- bin/setup
|
108
108
|
- imgix-rails.gemspec
|
109
109
|
- lib/imgix/rails.rb
|
110
|
+
- lib/imgix/rails/image_tag.rb
|
111
|
+
- lib/imgix/rails/picture_tag.rb
|
112
|
+
- lib/imgix/rails/tag.rb
|
110
113
|
- lib/imgix/rails/url_helper.rb
|
111
114
|
- lib/imgix/rails/version.rb
|
112
115
|
- lib/imgix/rails/view_helper.rb
|