next_gen_images 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
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
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in next_gen_images.gemspec
6
+ gemspec
7
+
8
+ gem 'rake', '~> 13.0'
9
+ gem 'rspec', '~> 3.0'
10
+ gem 'rubocop', '~> 1.21'
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,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require 'rubocop/rake_task'
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
@@ -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,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/engine'
4
+
5
+ module NextGenImages
6
+ module Rails
7
+ class Engine < ::Rails::Engine
8
+ end
9
+ end
10
+ 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,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NextGenImages
4
+ VERSION = '0.1.0'
5
+ 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'
@@ -0,0 +1,4 @@
1
+ module NextGenImages
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
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: []