next_gen_images 0.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 +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +46 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +223 -0
- data/LICENSE.txt +21 -0
- data/README.md +144 -0
- data/Rakefile +12 -0
- data/lib/next_gen_images/carrierwave_helpers.rb +25 -0
- data/lib/next_gen_images/engine.rb +10 -0
- data/lib/next_gen_images/railtie.rb +17 -0
- data/lib/next_gen_images/tasks/assets/webp.rake +39 -0
- data/lib/next_gen_images/version.rb +5 -0
- data/lib/next_gen_images/view_helpers.rb +87 -0
- data/lib/next_gen_images.rb +7 -0
- data/sig/next_gen_images.rbs +4 -0
- metadata +148 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: d036a649a224dfa3fd151e5e245f5810e1e25d99f98777ae9b3db696d3022392
|
|
4
|
+
data.tar.gz: aae969d7879faa41ea7e47f1107866d204ad0937ec07236e28ebbf45a86ede8b
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 51a469c51f54459115a8358665bae628e11a0a8fc97b781484a7197e21636768d0fce2310f3ae101145d3a6607eeaf24c51c8b915ba6d740f77188cd45c2a16c
|
|
7
|
+
data.tar.gz: dab440a1384baa2a02512e1922b8450e400d0489ccc1c27683574e74f25227ec9af1121b7bab56a04678f0d5591dc772c4e9fb2cf71e6ac6154d0d4dcdefbd55
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
require:
|
|
2
|
+
- rubocop-rspec
|
|
3
|
+
|
|
4
|
+
AllCops:
|
|
5
|
+
TargetRubyVersion: 2.6
|
|
6
|
+
NewCops: 'enable'
|
|
7
|
+
Exclude:
|
|
8
|
+
- 'bin/*'
|
|
9
|
+
- 'vendor/bundle/**/*'
|
|
10
|
+
|
|
11
|
+
Style/StringLiterals:
|
|
12
|
+
Enabled: true
|
|
13
|
+
EnforcedStyle: single_quotes
|
|
14
|
+
|
|
15
|
+
Style/StringLiteralsInInterpolation:
|
|
16
|
+
Enabled: true
|
|
17
|
+
EnforcedStyle: double_quotes
|
|
18
|
+
|
|
19
|
+
Style/Documentation:
|
|
20
|
+
Enabled: false
|
|
21
|
+
|
|
22
|
+
Layout/LineLength:
|
|
23
|
+
Max: 120
|
|
24
|
+
AllowURI: true
|
|
25
|
+
URISchemes:
|
|
26
|
+
- http
|
|
27
|
+
- https
|
|
28
|
+
|
|
29
|
+
Metrics/BlockLength:
|
|
30
|
+
CountComments: false
|
|
31
|
+
Max: 25
|
|
32
|
+
|
|
33
|
+
Metrics/AbcSize:
|
|
34
|
+
# The ABC size is a calculated magnitude, so this number can be an Integer or
|
|
35
|
+
# a Float.
|
|
36
|
+
Max: 18
|
|
37
|
+
|
|
38
|
+
Metrics/MethodLength:
|
|
39
|
+
CountComments: false
|
|
40
|
+
Max: 24
|
|
41
|
+
|
|
42
|
+
RSpec/MultipleExpectations:
|
|
43
|
+
Max: 2
|
|
44
|
+
|
|
45
|
+
RSpec/NestedGroups:
|
|
46
|
+
Max: 4
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
next_gen_images (0.1.0)
|
|
5
|
+
rails (>= 3.1)
|
|
6
|
+
webp-ffi (~> 0.3.1)
|
|
7
|
+
|
|
8
|
+
GEM
|
|
9
|
+
remote: https://rubygems.org/
|
|
10
|
+
specs:
|
|
11
|
+
actioncable (7.0.4)
|
|
12
|
+
actionpack (= 7.0.4)
|
|
13
|
+
activesupport (= 7.0.4)
|
|
14
|
+
nio4r (~> 2.0)
|
|
15
|
+
websocket-driver (>= 0.6.1)
|
|
16
|
+
actionmailbox (7.0.4)
|
|
17
|
+
actionpack (= 7.0.4)
|
|
18
|
+
activejob (= 7.0.4)
|
|
19
|
+
activerecord (= 7.0.4)
|
|
20
|
+
activestorage (= 7.0.4)
|
|
21
|
+
activesupport (= 7.0.4)
|
|
22
|
+
mail (>= 2.7.1)
|
|
23
|
+
net-imap
|
|
24
|
+
net-pop
|
|
25
|
+
net-smtp
|
|
26
|
+
actionmailer (7.0.4)
|
|
27
|
+
actionpack (= 7.0.4)
|
|
28
|
+
actionview (= 7.0.4)
|
|
29
|
+
activejob (= 7.0.4)
|
|
30
|
+
activesupport (= 7.0.4)
|
|
31
|
+
mail (~> 2.5, >= 2.5.4)
|
|
32
|
+
net-imap
|
|
33
|
+
net-pop
|
|
34
|
+
net-smtp
|
|
35
|
+
rails-dom-testing (~> 2.0)
|
|
36
|
+
actionpack (7.0.4)
|
|
37
|
+
actionview (= 7.0.4)
|
|
38
|
+
activesupport (= 7.0.4)
|
|
39
|
+
rack (~> 2.0, >= 2.2.0)
|
|
40
|
+
rack-test (>= 0.6.3)
|
|
41
|
+
rails-dom-testing (~> 2.0)
|
|
42
|
+
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
|
43
|
+
actiontext (7.0.4)
|
|
44
|
+
actionpack (= 7.0.4)
|
|
45
|
+
activerecord (= 7.0.4)
|
|
46
|
+
activestorage (= 7.0.4)
|
|
47
|
+
activesupport (= 7.0.4)
|
|
48
|
+
globalid (>= 0.6.0)
|
|
49
|
+
nokogiri (>= 1.8.5)
|
|
50
|
+
actionview (7.0.4)
|
|
51
|
+
activesupport (= 7.0.4)
|
|
52
|
+
builder (~> 3.1)
|
|
53
|
+
erubi (~> 1.4)
|
|
54
|
+
rails-dom-testing (~> 2.0)
|
|
55
|
+
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
|
56
|
+
activejob (7.0.4)
|
|
57
|
+
activesupport (= 7.0.4)
|
|
58
|
+
globalid (>= 0.3.6)
|
|
59
|
+
activemodel (7.0.4)
|
|
60
|
+
activesupport (= 7.0.4)
|
|
61
|
+
activerecord (7.0.4)
|
|
62
|
+
activemodel (= 7.0.4)
|
|
63
|
+
activesupport (= 7.0.4)
|
|
64
|
+
activestorage (7.0.4)
|
|
65
|
+
actionpack (= 7.0.4)
|
|
66
|
+
activejob (= 7.0.4)
|
|
67
|
+
activerecord (= 7.0.4)
|
|
68
|
+
activesupport (= 7.0.4)
|
|
69
|
+
marcel (~> 1.0)
|
|
70
|
+
mini_mime (>= 1.1.0)
|
|
71
|
+
activesupport (7.0.4)
|
|
72
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
73
|
+
i18n (>= 1.6, < 2)
|
|
74
|
+
minitest (>= 5.1)
|
|
75
|
+
tzinfo (~> 2.0)
|
|
76
|
+
addressable (2.8.4)
|
|
77
|
+
public_suffix (>= 2.0.2, < 6.0)
|
|
78
|
+
ast (2.4.2)
|
|
79
|
+
builder (3.2.4)
|
|
80
|
+
carrierwave (2.2.3)
|
|
81
|
+
activemodel (>= 5.0.0)
|
|
82
|
+
activesupport (>= 5.0.0)
|
|
83
|
+
addressable (~> 2.6)
|
|
84
|
+
image_processing (~> 1.1)
|
|
85
|
+
marcel (~> 1.0.0)
|
|
86
|
+
mini_mime (>= 0.1.3)
|
|
87
|
+
ssrf_filter (~> 1.0)
|
|
88
|
+
concurrent-ruby (1.1.10)
|
|
89
|
+
crass (1.0.6)
|
|
90
|
+
diff-lcs (1.5.0)
|
|
91
|
+
erubi (1.11.0)
|
|
92
|
+
ffi (1.15.5)
|
|
93
|
+
ffi-compiler (1.0.1)
|
|
94
|
+
ffi (>= 1.0.0)
|
|
95
|
+
rake
|
|
96
|
+
globalid (1.0.0)
|
|
97
|
+
activesupport (>= 5.0)
|
|
98
|
+
i18n (1.12.0)
|
|
99
|
+
concurrent-ruby (~> 1.0)
|
|
100
|
+
image_processing (1.12.2)
|
|
101
|
+
mini_magick (>= 4.9.5, < 5)
|
|
102
|
+
ruby-vips (>= 2.0.17, < 3)
|
|
103
|
+
json (2.6.2)
|
|
104
|
+
loofah (2.19.0)
|
|
105
|
+
crass (~> 1.0.2)
|
|
106
|
+
nokogiri (>= 1.5.9)
|
|
107
|
+
mail (2.7.1)
|
|
108
|
+
mini_mime (>= 0.1.1)
|
|
109
|
+
marcel (1.0.2)
|
|
110
|
+
method_source (1.0.0)
|
|
111
|
+
mini_magick (4.12.0)
|
|
112
|
+
mini_mime (1.1.2)
|
|
113
|
+
minitest (5.16.3)
|
|
114
|
+
net-imap (0.3.1)
|
|
115
|
+
net-protocol
|
|
116
|
+
net-pop (0.1.2)
|
|
117
|
+
net-protocol
|
|
118
|
+
net-protocol (0.1.3)
|
|
119
|
+
timeout
|
|
120
|
+
net-smtp (0.3.2)
|
|
121
|
+
net-protocol
|
|
122
|
+
nio4r (2.5.8)
|
|
123
|
+
nokogiri (1.13.8-arm64-darwin)
|
|
124
|
+
racc (~> 1.4)
|
|
125
|
+
nokogiri (1.13.8-x86_64-linux)
|
|
126
|
+
racc (~> 1.4)
|
|
127
|
+
parallel (1.22.1)
|
|
128
|
+
parser (3.1.2.1)
|
|
129
|
+
ast (~> 2.4.1)
|
|
130
|
+
public_suffix (5.0.1)
|
|
131
|
+
racc (1.6.0)
|
|
132
|
+
rack (2.2.4)
|
|
133
|
+
rack-test (2.0.2)
|
|
134
|
+
rack (>= 1.3)
|
|
135
|
+
rails (7.0.4)
|
|
136
|
+
actioncable (= 7.0.4)
|
|
137
|
+
actionmailbox (= 7.0.4)
|
|
138
|
+
actionmailer (= 7.0.4)
|
|
139
|
+
actionpack (= 7.0.4)
|
|
140
|
+
actiontext (= 7.0.4)
|
|
141
|
+
actionview (= 7.0.4)
|
|
142
|
+
activejob (= 7.0.4)
|
|
143
|
+
activemodel (= 7.0.4)
|
|
144
|
+
activerecord (= 7.0.4)
|
|
145
|
+
activestorage (= 7.0.4)
|
|
146
|
+
activesupport (= 7.0.4)
|
|
147
|
+
bundler (>= 1.15.0)
|
|
148
|
+
railties (= 7.0.4)
|
|
149
|
+
rails-dom-testing (2.0.3)
|
|
150
|
+
activesupport (>= 4.2.0)
|
|
151
|
+
nokogiri (>= 1.6)
|
|
152
|
+
rails-html-sanitizer (1.4.3)
|
|
153
|
+
loofah (~> 2.3)
|
|
154
|
+
railties (7.0.4)
|
|
155
|
+
actionpack (= 7.0.4)
|
|
156
|
+
activesupport (= 7.0.4)
|
|
157
|
+
method_source
|
|
158
|
+
rake (>= 12.2)
|
|
159
|
+
thor (~> 1.0)
|
|
160
|
+
zeitwerk (~> 2.5)
|
|
161
|
+
rainbow (3.1.1)
|
|
162
|
+
rake (13.0.6)
|
|
163
|
+
regexp_parser (2.6.0)
|
|
164
|
+
rexml (3.2.5)
|
|
165
|
+
rspec (3.12.0)
|
|
166
|
+
rspec-core (~> 3.12.0)
|
|
167
|
+
rspec-expectations (~> 3.12.0)
|
|
168
|
+
rspec-mocks (~> 3.12.0)
|
|
169
|
+
rspec-core (3.12.0)
|
|
170
|
+
rspec-support (~> 3.12.0)
|
|
171
|
+
rspec-expectations (3.12.0)
|
|
172
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
173
|
+
rspec-support (~> 3.12.0)
|
|
174
|
+
rspec-mocks (3.12.0)
|
|
175
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
176
|
+
rspec-support (~> 3.12.0)
|
|
177
|
+
rspec-support (3.12.0)
|
|
178
|
+
rubocop (1.38.0)
|
|
179
|
+
json (~> 2.3)
|
|
180
|
+
parallel (~> 1.10)
|
|
181
|
+
parser (>= 3.1.2.1)
|
|
182
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
183
|
+
regexp_parser (>= 1.8, < 3.0)
|
|
184
|
+
rexml (>= 3.2.5, < 4.0)
|
|
185
|
+
rubocop-ast (>= 1.23.0, < 2.0)
|
|
186
|
+
ruby-progressbar (~> 1.7)
|
|
187
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
|
188
|
+
rubocop-ast (1.23.0)
|
|
189
|
+
parser (>= 3.1.1.0)
|
|
190
|
+
rubocop-rspec (2.17.1)
|
|
191
|
+
rubocop (~> 1.33)
|
|
192
|
+
ruby-progressbar (1.11.0)
|
|
193
|
+
ruby-vips (2.1.4)
|
|
194
|
+
ffi (~> 1.12)
|
|
195
|
+
ssrf_filter (1.1.1)
|
|
196
|
+
thor (1.2.1)
|
|
197
|
+
timeout (0.3.0)
|
|
198
|
+
tzinfo (2.0.5)
|
|
199
|
+
concurrent-ruby (~> 1.0)
|
|
200
|
+
unicode-display_width (2.3.0)
|
|
201
|
+
webp-ffi (0.3.1)
|
|
202
|
+
ffi (>= 1.9.0)
|
|
203
|
+
ffi-compiler (>= 0.1.2)
|
|
204
|
+
websocket-driver (0.7.5)
|
|
205
|
+
websocket-extensions (>= 0.1.0)
|
|
206
|
+
websocket-extensions (0.1.5)
|
|
207
|
+
zeitwerk (2.6.1)
|
|
208
|
+
|
|
209
|
+
PLATFORMS
|
|
210
|
+
arm64-darwin-21
|
|
211
|
+
x86_64-linux
|
|
212
|
+
|
|
213
|
+
DEPENDENCIES
|
|
214
|
+
bundler
|
|
215
|
+
carrierwave (>= 2.0)
|
|
216
|
+
next_gen_images!
|
|
217
|
+
rake (~> 13.0)
|
|
218
|
+
rspec (~> 3.0)
|
|
219
|
+
rubocop (~> 1.21)
|
|
220
|
+
rubocop-rspec (~> 2.17.1)
|
|
221
|
+
|
|
222
|
+
BUNDLED WITH
|
|
223
|
+
2.3.25
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 JP Balarini
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Next Gen Images
|
|
2
|
+
|
|
3
|
+
## Motivation
|
|
4
|
+
|
|
5
|
+
Currently Rails does not provide a `picture` HTML tag helper. An HTML `picture` tag provides [several advantages](https://blog.bitsrc.io/why-you-should-use-picture-tag-instead-of-img-tag-b9841e86bf8b) over an image tag, like fallback image support, resolution switching and art direction.
|
|
6
|
+
Also, most of a website assets are still JPEG or PNG images, and we don't want to convert our assets manually to WebP, we want this to happen automatically if it's needed.
|
|
7
|
+
|
|
8
|
+
This gem brings next gen image formats to Ruby on Rails. A `picture_tag` view helper is provided along several utilities to automatically convert them. Currently, it supports `WebP` images. A Carrierwave module with some utility methods is provided.
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
IMPORTANT:
|
|
14
|
+
Since this gem adds the ability to convert all your project images to WebP and depends on `webp-ffi`, you will need to install the WebP converter before. You can check specific instructions for your operating system [here](https://github.com/le0pard/webp-ffi#installation)
|
|
15
|
+
|
|
16
|
+
Once you are ready with, install the gem and add to the application's Gemfile by executing:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
$ bundle add next_gen_images
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Or add it to your application's Gemfile
|
|
23
|
+
```ruby
|
|
24
|
+
gem 'next_gen_images'
|
|
25
|
+
```
|
|
26
|
+
and then run
|
|
27
|
+
```bash
|
|
28
|
+
bundle install
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
### View Helpers
|
|
34
|
+
|
|
35
|
+
This gem adds support for a `picture_tag` helper. Syntax is the following:
|
|
36
|
+
```
|
|
37
|
+
picture_tag SOURCE, PICTURE_TAG_OPTIONS, image: IMAGE_TAG_OPTIONS
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
This will output something like this:
|
|
41
|
+
```html
|
|
42
|
+
<picture PICTURE_TAG_OPTIONS>
|
|
43
|
+
<source srcset=SOURCE ...>
|
|
44
|
+
...
|
|
45
|
+
<img IMAGE_TAG_OPTIONS>
|
|
46
|
+
</picture>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Depending on your needs, you can use the `picture_tag` in 3 different ways:
|
|
50
|
+
|
|
51
|
+
1. You can pass your existing image as the source, and add the `add_webp: true` option to automatically infer the `webp` image from the PNG/JPEG and add fallback image support.
|
|
52
|
+
```ruby
|
|
53
|
+
picture_tag 'satellite.png', image: { alt: 'satellite image', class: 'mt-0' }, add_webp: true
|
|
54
|
+
```
|
|
55
|
+
This will create the following HTML:
|
|
56
|
+
```html
|
|
57
|
+
<picture>
|
|
58
|
+
<source srcset="/assets/satellite.png.web" type="image/webp">
|
|
59
|
+
<source srcset="/assets/satellite.png" type="image/png">
|
|
60
|
+
<img alt="satellite image" class="mt-0" src="/assets/satellite.png.webp">
|
|
61
|
+
</picture>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
2. If you want to manually specify your sources, you can pass an array of images to the `picture_tag`. This is extremely useful for dynamically generated images (that a user uploaded for example).
|
|
65
|
+
```ruby
|
|
66
|
+
picture_tag [post.cover_image.webp.medium.url, post.cover_image.medium.url], image: { alt: 'post image', class: 'rounded' }
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
This will create the following HTML:
|
|
70
|
+
```html
|
|
71
|
+
<picture>
|
|
72
|
+
<source srcset="/uploads/posts/1/cover-image.png.webp" type="image/webp">
|
|
73
|
+
<source srcset="/uploads/posts/1/cover-image.png" type="image/png">
|
|
74
|
+
<img alt="post image" class="rounded" src="/uploads/posts/1/cover-image.png.webp">
|
|
75
|
+
</picture>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
3. The last option is to provide a block that will be inserted directly into the picture tag. This can be extremely useful for art direction.
|
|
79
|
+
|
|
80
|
+
```ruby
|
|
81
|
+
= picture_tag 'city.png', image: { alt: 'city image' } do
|
|
82
|
+
= source_tag srcset: "#{image_path('city_small.png')}.webp", type: 'image/webp', media: '(max-width: 1728px)'
|
|
83
|
+
= source_tag srcset: "#{image_path('city_big.png')}.webp", type: 'image/webp'
|
|
84
|
+
= source_tag srcset: image_path('city_small.png'), type: 'image/png', media: '(max-width: 1728px)'
|
|
85
|
+
= source_tag srcset: image_path('city_big.png'), type: 'image/png'
|
|
86
|
+
```
|
|
87
|
+
Which will create the following HTML:
|
|
88
|
+
```html
|
|
89
|
+
<picture>
|
|
90
|
+
<source srcset="/assets/city_small.png.webp" type="image/webp" media="(max-width: 1728px)">
|
|
91
|
+
<source srcset="/assets/city_small.png.webp" type="image/webp">
|
|
92
|
+
<source srcset="/assets/city_small.png" type="image/png" media="(max-width: 1728px)">
|
|
93
|
+
<source srcset="/assets/city_big.png" type="image/png">
|
|
94
|
+
<img alt="city image" src="/assets/city_small.png.webp">
|
|
95
|
+
</picture>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Asset conversion
|
|
99
|
+
|
|
100
|
+
A rake task called `assets:webp` that converts all of your images to WebP is provided. When you run the `assets:precompile` task, the `assets:webp` task will also run (via an `enhance` to the `assets:precompile` task) and automatically convert your images to WebP.
|
|
101
|
+
If you want to manually convert your images, you can run:
|
|
102
|
+
```bash
|
|
103
|
+
rake assets:webp
|
|
104
|
+
```
|
|
105
|
+
Assets will be compiled to `public/assets/` or the path that you specifed in `Rails.application.config.assets.prefix`.
|
|
106
|
+
The file names of the generated image assets will be in the format:`OLD_IMAGE.OLD_EXTENSION.webp`
|
|
107
|
+
|
|
108
|
+
### Carrierwave integration
|
|
109
|
+
|
|
110
|
+
A `convert_to_webp` method that converts images to WebP is provided. You can send any encoding option available to [webp-ffi](https://github.com/le0pard/webp-ffi#encode-webp-image).
|
|
111
|
+
We also provide a helper method called `build_webp_full_filename` that allows you to generate the WebP filename from the original filename and version.
|
|
112
|
+
|
|
113
|
+
Example Uploader class:
|
|
114
|
+
```ruby
|
|
115
|
+
class ImageUploader < CarrierWave::Uploader::Base
|
|
116
|
+
include NextGenImages::CarrierwaveHelpers
|
|
117
|
+
|
|
118
|
+
version :small, from_version: :medium do
|
|
119
|
+
process resize_to_fit: [400, 400]
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
version :webp do
|
|
123
|
+
process convert_to_webp: [{ quality: 80, method: 5 }]
|
|
124
|
+
|
|
125
|
+
def full_filename(file)
|
|
126
|
+
build_webp_full_filename(file, version_name)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Development
|
|
133
|
+
|
|
134
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
135
|
+
|
|
136
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
137
|
+
|
|
138
|
+
## Contributing
|
|
139
|
+
|
|
140
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/eagerworks/next_gen_images.
|
|
141
|
+
|
|
142
|
+
## License
|
|
143
|
+
|
|
144
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module NextGenImages
|
|
4
|
+
module CarrierwaveHelpers
|
|
5
|
+
def convert_to_webp(options = {})
|
|
6
|
+
webp_path = "#{path}.webp"
|
|
7
|
+
|
|
8
|
+
WebP.encode(path, webp_path, options)
|
|
9
|
+
|
|
10
|
+
@filename = webp_path.split('/').pop
|
|
11
|
+
|
|
12
|
+
@file = CarrierWave::SanitizedFile.new(
|
|
13
|
+
tempfile: webp_path,
|
|
14
|
+
filename: webp_path,
|
|
15
|
+
content_type: 'image/webp'
|
|
16
|
+
)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def build_webp_full_filename(filename, version_name)
|
|
20
|
+
return "#{version_name}_#{filename}" if filename.split('.').last == 'webp'
|
|
21
|
+
|
|
22
|
+
"#{version_name}_#{filename}.webp"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'next_gen_images/view_helpers'
|
|
4
|
+
|
|
5
|
+
module NextGenImages
|
|
6
|
+
# Load everything we need into rails
|
|
7
|
+
class Railtie < Rails::Railtie
|
|
8
|
+
initializer 'next_gen_images.view_helpers' do
|
|
9
|
+
ActionView::Base.include ViewHelpers
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
rake_tasks do
|
|
13
|
+
path = File.expand_path(__dir__)
|
|
14
|
+
Dir.glob("#{path}/tasks/**/*.rake").each { |f| load f }
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'webp-ffi'
|
|
4
|
+
|
|
5
|
+
namespace :assets do
|
|
6
|
+
desc 'Create .webp versions of assets'
|
|
7
|
+
task webp: :environment do
|
|
8
|
+
image_types = /\.(?:png|jpe?g)$/
|
|
9
|
+
|
|
10
|
+
public_assets = File.join(
|
|
11
|
+
Rails.root,
|
|
12
|
+
'public',
|
|
13
|
+
Rails.application.config.assets.prefix
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
Dir["#{public_assets}/**/*"].each do |filename|
|
|
17
|
+
next unless filename =~ image_types
|
|
18
|
+
|
|
19
|
+
mtime = File.mtime(filename)
|
|
20
|
+
webp_file = "#{filename}.webp"
|
|
21
|
+
next if File.exist?(webp_file) && File.mtime(webp_file) >= mtime
|
|
22
|
+
|
|
23
|
+
begin
|
|
24
|
+
# encode with lossy encoding and slowest method (best quality)
|
|
25
|
+
WebP.encode(filename, webp_file, lossless: 0, quality: 80, method: 6)
|
|
26
|
+
File.utime(mtime, mtime, webp_file)
|
|
27
|
+
$stdout.puts "Converted image to Webp: #{webp_file}"
|
|
28
|
+
rescue StandardError => e
|
|
29
|
+
$stdout.puts "Webp conversion error on image #{webp_file}. Error info: #{e.message}"
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Hook into existing assets:precompile task
|
|
35
|
+
Rake::Task['assets:precompile'].enhance do
|
|
36
|
+
# TODO: if defined?(NextGenImages) && NextGenImages.config.run_on_precompile
|
|
37
|
+
Rake::Task['assets:webp'].invoke
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'action_view'
|
|
4
|
+
|
|
5
|
+
module NextGenImages
|
|
6
|
+
module ViewHelpers
|
|
7
|
+
def self.included(klass)
|
|
8
|
+
klass.class_eval do
|
|
9
|
+
include ActionView::Context
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def picture_tag(source, options = {}, &block)
|
|
14
|
+
picture_options = options.except(:image)
|
|
15
|
+
|
|
16
|
+
content_tag :picture, picture_options do
|
|
17
|
+
build_picture_content(source, options, block)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def source_tag(options = {})
|
|
22
|
+
tag :source, options
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def build_picture_content(source, options, block)
|
|
28
|
+
image_options = options.fetch(:image, {})
|
|
29
|
+
image_options[:src] = build_img_src(source)
|
|
30
|
+
add_webp = options.fetch(:add_webp, false)
|
|
31
|
+
|
|
32
|
+
content = ''.html_safe
|
|
33
|
+
if block.present?
|
|
34
|
+
content += capture(&block).html_safe
|
|
35
|
+
else
|
|
36
|
+
[source].flatten.each do |img_src|
|
|
37
|
+
content += build_source_from_img(image_path(img_src), add_webp)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
content += tag('img', image_options)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def build_img_src(source)
|
|
44
|
+
case source
|
|
45
|
+
when String
|
|
46
|
+
image_path(source)
|
|
47
|
+
when Array
|
|
48
|
+
image_path(source.last)
|
|
49
|
+
else
|
|
50
|
+
''
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def build_source_from_img(img_path, add_webp)
|
|
55
|
+
source_tags = ''.html_safe
|
|
56
|
+
webp_path = "#{img_path}.webp"
|
|
57
|
+
# order of source tags matters
|
|
58
|
+
if add_webp && file_exist_in_public_path?(webp_path)
|
|
59
|
+
source_tags += source_tag(srcset: webp_path, type: 'image/webp')
|
|
60
|
+
end
|
|
61
|
+
source_tags + source_tag(
|
|
62
|
+
srcset: img_path,
|
|
63
|
+
type: image_type(img_path)
|
|
64
|
+
)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def image_type(image_path)
|
|
68
|
+
extension = File.extname(image_path)
|
|
69
|
+
Rack::Mime::MIME_TYPES.merge!({
|
|
70
|
+
'.webp' => 'image/webp'
|
|
71
|
+
})
|
|
72
|
+
Rack::Mime.mime_type(extension).to_s
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def file_exist_in_public_path?(path)
|
|
76
|
+
# for performance reasons, we assume production contains the asset
|
|
77
|
+
return true if ::Rails.env.production?
|
|
78
|
+
|
|
79
|
+
public_path = File.join(
|
|
80
|
+
::Rails.root,
|
|
81
|
+
'public',
|
|
82
|
+
path
|
|
83
|
+
)
|
|
84
|
+
File.exist?(public_path)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'next_gen_images/version'
|
|
4
|
+
require_relative 'next_gen_images/railtie' if defined?(Rails)
|
|
5
|
+
require_relative 'next_gen_images/engine'
|
|
6
|
+
require_relative 'next_gen_images/view_helpers'
|
|
7
|
+
require_relative 'next_gen_images/carrierwave_helpers'
|
metadata
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: next_gen_images
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- JP Balarini
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2023-04-19 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: rails
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '3.1'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '3.1'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: webp-ffi
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: 0.3.1
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: 0.3.1
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: bundler
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: carrierwave
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '2.0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '2.0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: rspec
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: 3.12.0
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: 3.12.0
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: rubocop-rspec
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - "~>"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: 2.17.1
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - "~>"
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: 2.17.1
|
|
97
|
+
description: Adds support for a picture_tag and several utilities to automatically
|
|
98
|
+
convert images to WebP
|
|
99
|
+
email:
|
|
100
|
+
- jp@eagerworks.com
|
|
101
|
+
executables: []
|
|
102
|
+
extensions: []
|
|
103
|
+
extra_rdoc_files: []
|
|
104
|
+
files:
|
|
105
|
+
- ".rspec"
|
|
106
|
+
- ".rubocop.yml"
|
|
107
|
+
- Gemfile
|
|
108
|
+
- Gemfile.lock
|
|
109
|
+
- LICENSE.txt
|
|
110
|
+
- README.md
|
|
111
|
+
- Rakefile
|
|
112
|
+
- lib/next_gen_images.rb
|
|
113
|
+
- lib/next_gen_images/carrierwave_helpers.rb
|
|
114
|
+
- lib/next_gen_images/engine.rb
|
|
115
|
+
- lib/next_gen_images/railtie.rb
|
|
116
|
+
- lib/next_gen_images/tasks/assets/webp.rake
|
|
117
|
+
- lib/next_gen_images/version.rb
|
|
118
|
+
- lib/next_gen_images/view_helpers.rb
|
|
119
|
+
- sig/next_gen_images.rbs
|
|
120
|
+
homepage: https://eagerworks.com
|
|
121
|
+
licenses:
|
|
122
|
+
- MIT
|
|
123
|
+
metadata:
|
|
124
|
+
allowed_push_host: https://rubygems.org
|
|
125
|
+
homepage_uri: https://eagerworks.com
|
|
126
|
+
source_code_uri: https://github.com/eagerworks/next_gen_images
|
|
127
|
+
rubygems_mfa_required: 'true'
|
|
128
|
+
post_install_message:
|
|
129
|
+
rdoc_options: []
|
|
130
|
+
require_paths:
|
|
131
|
+
- lib
|
|
132
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
133
|
+
requirements:
|
|
134
|
+
- - ">="
|
|
135
|
+
- !ruby/object:Gem::Version
|
|
136
|
+
version: 2.6.0
|
|
137
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
138
|
+
requirements:
|
|
139
|
+
- - ">="
|
|
140
|
+
- !ruby/object:Gem::Version
|
|
141
|
+
version: '0'
|
|
142
|
+
requirements: []
|
|
143
|
+
rubygems_version: 3.2.3
|
|
144
|
+
signing_key:
|
|
145
|
+
specification_version: 4
|
|
146
|
+
summary: Handle next-gen image formats in your Ruby on Rails project. WebP is currently
|
|
147
|
+
supported
|
|
148
|
+
test_files: []
|