carrierwave-cloudflare 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bfcbaec70caed8b3460a42e0bc1b39d1232fd43e16a5085d13e9f22f4dee3e2c
4
- data.tar.gz: 95a8e0999e8b2e95ce197705166488a207e869c58a6cb971de451c0c024794ee
3
+ metadata.gz: 964e322fe551ff9f8361aed8ca8f4c7b5db9ec45721223c116f05651692d872c
4
+ data.tar.gz: 84cbd3caf7864e50afe1d28391ad3244522f93cf9f89dd9093cd1ead131f6c44
5
5
  SHA512:
6
- metadata.gz: a35397c051afa4e66920e22ce10a3717e789b8f5bf1b41ac970c16814c24f8b5a380a587cb886af919628eaf8aeff60d5dfbab1105d1ba61835eaf2aeeccf0fc
7
- data.tar.gz: d28e1eef9d280247abb591258478dec7a0b7e9bc66b3f6354a0037aea37c9f584b32465cb9b04dcc287bde94b65b96808270185e9bec2096447b481cf5a2c34c
6
+ metadata.gz: 640b189cffc176b43bd72b5e019d097b08f313a9c4c69c530b31ca9cbffc2b0e9d919c3525f5df42bec4ca75f8dae8ec47476647c20e8605875da463a9aea18e
7
+ data.tar.gz: d388d2fef0a9f7d3e23e98539563abaaf4a31c97d61dcf4c92b0ad53b1723125a13fd0bd02f3075883e7514d212fc9a46c86bed1c549c7f2938992c51e276672
@@ -5,9 +5,7 @@ on:
5
5
  workflow_dispatch:
6
6
  # Alternatively, publish whenever changes are merged to the `main` branch.
7
7
  push:
8
- branches: "*"
9
- pull_request:
10
- branches: "*"
8
+ branches: [master]
11
9
 
12
10
  jobs:
13
11
  build:
data/.rubocop.yml ADDED
@@ -0,0 +1,264 @@
1
+ Style/CollectionMethods:
2
+ Description: Preferred collection methods.
3
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#map-find-select-reduce-size
4
+ Enabled: true
5
+ PreferredMethods:
6
+ collect: map
7
+ collect!: map!
8
+ find: detect
9
+ find_all: select
10
+ reduce: inject
11
+
12
+ Layout/DotPosition:
13
+ Description: Checks the position of the dot in multi-line method calls.
14
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#consistent-multi-line-chains
15
+ Enabled: true
16
+ EnforcedStyle: trailing
17
+ SupportedStyles:
18
+ - leading
19
+ - trailing
20
+
21
+ Naming/PredicateName:
22
+ Description: Check the names of predicate methods.
23
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#bool-methods-qmark
24
+ Enabled: true
25
+ NamePrefix:
26
+ - is_
27
+ - has_
28
+ - have_
29
+ ForbiddenPrefixes:
30
+ - is_
31
+ Exclude:
32
+ - spec/**/*
33
+
34
+ Style/SingleLineMethods:
35
+ Description: Avoid single-line methods.
36
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-single-line-methods
37
+ Enabled: true
38
+ AllowIfMethodIsEmpty: true
39
+
40
+ Style/StringLiterals:
41
+ Description: Checks if uses of quotes match the configured preference.
42
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#consistent-string-literals
43
+ Enabled: true
44
+ EnforcedStyle: double_quotes
45
+ SupportedStyles:
46
+ - single_quotes
47
+ - double_quotes
48
+
49
+ Style/StringLiteralsInInterpolation:
50
+ Description: Checks if uses of quotes inside expressions in interpolated strings
51
+ match the configured preference.
52
+ Enabled: true
53
+ EnforcedStyle: single_quotes
54
+ SupportedStyles:
55
+ - single_quotes
56
+ - double_quotes
57
+
58
+ Metrics/AbcSize:
59
+ Description: A calculated magnitude based on number of assignments, branches, and
60
+ conditions.
61
+ Enabled: false
62
+ Max: 15
63
+
64
+ Metrics/ClassLength:
65
+ Description: Avoid classes longer than 100 lines of code.
66
+ Enabled: false
67
+ CountComments: false
68
+ Max: 100
69
+
70
+ Metrics/ModuleLength:
71
+ CountComments: false
72
+ Max: 100
73
+ Description: Avoid modules longer than 100 lines of code.
74
+ Enabled: false
75
+
76
+ Metrics/CyclomaticComplexity:
77
+ Description: A complexity metric that is strongly correlated to the number of test
78
+ cases needed to validate a method.
79
+ Enabled: false
80
+ Max: 6
81
+
82
+ Metrics/MethodLength:
83
+ Description: Avoid methods longer than 10 lines of code.
84
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#short-methods
85
+ Enabled: false
86
+ CountComments: false
87
+ Max: 10
88
+
89
+ Metrics/ParameterLists:
90
+ Description: Avoid parameter lists longer than three or four parameters.
91
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#too-many-params
92
+ Enabled: false
93
+ Max: 5
94
+ CountKeywordArgs: true
95
+
96
+ Metrics/PerceivedComplexity:
97
+ Description: A complexity metric geared towards measuring complexity for a human
98
+ reader.
99
+ Enabled: false
100
+ Max: 7
101
+
102
+ Lint/AssignmentInCondition:
103
+ Description: Don't use assignment in conditions.
104
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#safe-assignment-in-condition
105
+ Enabled: false
106
+ AllowSafeAssignment: true
107
+
108
+ Lint/EachWithObjectArgument:
109
+ Description: Check for immutable argument given to each_with_object.
110
+ Enabled: true
111
+
112
+ Lint/SuppressedException:
113
+ Description: Don't suppress exception.
114
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#dont-hide-exceptions
115
+ Enabled: false
116
+
117
+ Lint/LiteralAsCondition:
118
+ Description: Checks of literals used in conditions.
119
+ Enabled: false
120
+
121
+ Lint/LiteralInInterpolation:
122
+ Description: Checks for literals used in interpolation.
123
+ Enabled: false
124
+
125
+ Style/InlineComment:
126
+ Description: Avoid inline comments.
127
+ Enabled: false
128
+
129
+ Naming/AccessorMethodName:
130
+ Description: Check the naming of accessor methods for get_/set_.
131
+ Enabled: false
132
+
133
+ Style/Alias:
134
+ Description: Use alias_method instead of alias.
135
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#alias-method
136
+ Enabled: false
137
+
138
+ Style/Documentation:
139
+ Description: Document classes and non-namespace modules.
140
+ Enabled: false
141
+
142
+ Style/DoubleNegation:
143
+ Description: Checks for uses of double negation (!!).
144
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-bang-bang
145
+ Enabled: false
146
+
147
+ Style/EachWithObject:
148
+ Description: Prefer `each_with_object` over `inject` or `reduce`.
149
+ Enabled: false
150
+
151
+ Style/EmptyLiteral:
152
+ Description: Prefer literals to Array.new/Hash.new/String.new.
153
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#literal-array-hash
154
+ Enabled: false
155
+
156
+ Style/ModuleFunction:
157
+ Description: Checks for usage of `extend self` in modules.
158
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#module-function
159
+ Enabled: false
160
+
161
+ Style/OneLineConditional:
162
+ Description: Favor the ternary operator(?:) over if/then/else/end constructs.
163
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#ternary-operator
164
+ Enabled: false
165
+
166
+ Style/PerlBackrefs:
167
+ Description: Avoid Perl-style regex back references.
168
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-perl-regexp-last-matchers
169
+ Enabled: false
170
+
171
+ Style/Send:
172
+ Description: Prefer `Object#__send__` or `Object#public_send` to `send`, as `send`
173
+ may overlap with existing methods.
174
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#prefer-public-send
175
+ Enabled: false
176
+
177
+ Style/SpecialGlobalVars:
178
+ Description: Avoid Perl-style global variables.
179
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-cryptic-perlisms
180
+ Enabled: false
181
+
182
+ Style/VariableInterpolation:
183
+ Description: Don't interpolate global, instance and class variables directly in
184
+ strings.
185
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#curlies-interpolate
186
+ Enabled: false
187
+
188
+ Style/WhenThen:
189
+ Description: Use when x then ... for one-line cases.
190
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#one-line-cases
191
+ Enabled: false
192
+
193
+ Style/RaiseArgs:
194
+ Description: Checks the arguments passed to raise/fail.
195
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#exception-class-messages
196
+ Enabled: false
197
+ EnforcedStyle: exploded
198
+ SupportedStyles:
199
+ - compact
200
+ - exploded
201
+
202
+ Style/SignalException:
203
+ Description: Checks for proper usage of fail and raise.
204
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#fail-method
205
+ Enabled: false
206
+ EnforcedStyle: semantic
207
+ SupportedStyles:
208
+ - only_raise
209
+ - only_fail
210
+ - semantic
211
+
212
+ Style/SingleLineBlockParams:
213
+ Description: Enforces the names of some block params.
214
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#reduce-blocks
215
+ Enabled: false
216
+ Methods:
217
+ - reduce:
218
+ - a
219
+ - e
220
+ - inject:
221
+ - a
222
+ - e
223
+
224
+ Style/GuardClause:
225
+ Description: Check for conditionals that can be replaced with guard clauses
226
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals
227
+ Enabled: false
228
+ MinBodyLength: 1
229
+
230
+ Style/IfUnlessModifier:
231
+ Description: Favor modifier if/unless usage when you have a single-line body.
232
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#if-as-a-modifier
233
+ Enabled: false
234
+
235
+ Style/OptionHash:
236
+ Description: Don't use option hashes when you can use keyword arguments.
237
+ Enabled: false
238
+
239
+ Style/PercentLiteralDelimiters:
240
+ Description: Use `%`-literal delimiters consistently
241
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#percent-literal-braces
242
+ Enabled: false
243
+ PreferredDelimiters:
244
+ "%": "()"
245
+ "%i": "()"
246
+ "%q": "()"
247
+ "%Q": "()"
248
+ "%r": "{}"
249
+ "%s": "()"
250
+ "%w": "()"
251
+ "%W": "()"
252
+ "%x": "()"
253
+
254
+ Style/TrailingCommaInArguments:
255
+ Description: Checks for trailing comma in parameter lists and literals.
256
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas
257
+ Enabled: false
258
+ EnforcedStyleForMultiline: no_comma
259
+
260
+ Metrics/BlockLength:
261
+ Description: Check if the length of a block exceeds some maximum value.
262
+ Enabled: true
263
+ Exclude:
264
+ - spec/**/*
data/Gemfile.lock CHANGED
@@ -1,12 +1,18 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- carrierwave-cloudflare (0.1.1)
4
+ carrierwave-cloudflare (0.2.0)
5
5
  carrierwave (~> 1.3)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
+ actionview (5.2.3)
11
+ activesupport (= 5.2.3)
12
+ builder (~> 3.1)
13
+ erubi (~> 1.4)
14
+ rails-dom-testing (~> 2.0)
15
+ rails-html-sanitizer (~> 1.0, >= 1.0.3)
10
16
  activemodel (5.2.3)
11
17
  activesupport (= 5.2.3)
12
18
  activesupport (5.2.3)
@@ -14,6 +20,7 @@ GEM
14
20
  i18n (>= 0.7, < 2)
15
21
  minitest (~> 5.1)
16
22
  tzinfo (~> 1.1)
23
+ builder (3.2.4)
17
24
  carrierwave (1.3.2)
18
25
  activemodel (>= 4.0.0)
19
26
  activesupport (>= 4.0.0)
@@ -21,18 +28,33 @@ GEM
21
28
  ssrf_filter (~> 1.0)
22
29
  coderay (1.1.2)
23
30
  concurrent-ruby (1.1.6)
31
+ crass (1.0.6)
24
32
  diff-lcs (1.4.4)
33
+ erubi (1.10.0)
25
34
  i18n (1.8.5)
26
35
  concurrent-ruby (~> 1.0)
36
+ loofah (2.11.0)
37
+ crass (~> 1.0.2)
38
+ nokogiri (>= 1.5.9)
27
39
  method_source (1.0.0)
28
40
  mime-types (3.3.1)
29
41
  mime-types-data (~> 3.2015)
30
42
  mime-types-data (3.2020.1104)
43
+ mini_portile2 (2.5.3)
31
44
  minitest (5.14.1)
45
+ nokogiri (1.11.7)
46
+ mini_portile2 (~> 2.5.0)
47
+ racc (~> 1.4)
32
48
  pry (0.13.1)
33
49
  coderay (~> 1.1)
34
50
  method_source (~> 1.0)
51
+ racc (1.5.2)
35
52
  rack (2.2.3)
53
+ rails-dom-testing (2.0.3)
54
+ activesupport (>= 4.2.0)
55
+ nokogiri (>= 1.6)
56
+ rails-html-sanitizer (1.3.0)
57
+ loofah (~> 2.3)
36
58
  rake (13.0.3)
37
59
  rspec (3.10.0)
38
60
  rspec-core (~> 3.10.0)
@@ -56,6 +78,7 @@ PLATFORMS
56
78
  ruby
57
79
 
58
80
  DEPENDENCIES
81
+ actionview (~> 5.2)
59
82
  activesupport (~> 5.2)
60
83
  carrierwave-cloudflare!
61
84
  pry
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  This gem provides a simple wrapper for transformation images via Cloudflare
4
4
 
5
+
6
+
5
7
  ## Installation
6
8
 
7
9
  Add this line to your application's Gemfile:
@@ -28,8 +30,8 @@ class BaseUploader < CarrierWave::Uploader::Base
28
30
  end
29
31
  ```
30
32
 
33
+ Use `cdn_transform` for define Cloudflare's version (this means that now the file will not be stored on the, but will be transformed on the cloudflare side)
31
34
 
32
- Define `virtual` version in some uploader:
33
35
  ```ruby
34
36
  class AvatarUploader < BaseUploader
35
37
  version(:medium) do
@@ -37,14 +39,13 @@ class AvatarUploader < BaseUploader
37
39
  end
38
40
  end
39
41
 
40
-
41
- User.avatar.medium # CarrierWave::Uploader
42
- User.avatar.url # "https://s3.resume.io/users/avatar/1.jpg"
43
- User.avatar.medium_url # "https://s3.resume.io/cdn-cgi/.../users/avatar/1.jpg"
44
- User.avatar.medium.url # "https://s3.resume.io/cdn-cgi/.../users/avatar/1.jpg"
45
- User.avatar.url(:medium) # "https://s3.resume.io/cdn-cgi/.../users/avatar/1.jpg"
46
- User.avatar.medium.url(dpr: 1)
47
- User.avatar.resize(width: 1200, fit: :cover).url
42
+ user = User.find(some_id)
43
+ user.avatar.medium # CarrierWave::Uploader
44
+ user.avatar.url # "https://s3.your-website.com/users/avatar/1.jpg"
45
+ user.avatar.medium_url # "https://s3.your-website.com/cdn-cgi/width=100,height=100,dpr=2/users/avatar/1.jpg"
46
+ user.avatar.url(:medium) # "https://s3.your-website.com/cdn-cgi/width=100,height=100,dpr=2/users/avatar/1.jpg"
47
+ user.avatar.medium.url(dpr: 1) # "https://s3.your-website.com/cdn-cgi/width=100,height=100,dpr=1/users/avatar/1.jpg"
48
+ user.avatar.resize(width: 1200, fit: :cover).url # "https://s3.your-website.com/cdn-cgi/width=1200,height=100,dpr=2,fit=cover/users/avatar/1.jpg"
48
49
  ```
49
50
 
50
51
  ### Options
@@ -63,21 +64,71 @@ class BaseUploader < CarrierWave::Uploader::Base
63
64
  end
64
65
  ```
65
66
 
66
- ## Development
67
+ ### In development env
67
68
 
68
- 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.
69
+ In development, you don't need to generate URLs for Cloudflare, because they will not work and therefore you need to disable the Cloudflare transform
69
70
 
70
- 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 tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
71
+ ``` ruby
72
+ CarrierWave::Cloudflare.configure do |config|
73
+ config.cloudflare_transform(false)
74
+ end
75
+ ```
76
+
77
+ `cloudflare_transform: false` disables links generation and put all Cloudflare's arguments into query string (for easy debugging)
71
78
 
72
- ## Contributing
79
+ e.g:
80
+
81
+ ```
82
+ /1.jpg?cdn-cgi=width-11.height-300.fit-pad
83
+ ```
84
+
85
+ ## Rails views helpers
86
+
87
+ ### cdn_transformed(url, **options)
88
+ Returns an image URL with CDN transformations applied. Can process already transformed URLs, in that case the options will be merged together.
89
+
90
+ ```ruby
91
+ cdn_transformed('/img.jpg', width: 400)
92
+ # => '/cdn-cgi/image/width=400/img.jpg'
93
+
94
+ cdn_transformed('/cdn-cgi/image/width=100,fit=pad/img.jpg', width: 333)
95
+ # => '/cdn-cgi/image/width=333,fit=pad/img.jpg'
96
+ ```
73
97
 
74
- Bug reports and pull requests are welcome on GitHub at https://github.com/resume-io/carrierwave-cloudflare. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/resume-io/carrierwave-cloudflare/blob/master/CODE_OF_CONDUCT.md).
75
98
 
99
+ ### hidpi_image_tag(url, dprs: nil, **options)
76
100
 
77
- ## License
101
+ Returns an image tag with with scaled variations (via `srcset`) attribute for devices with different DPR values.
78
102
 
79
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
80
103
 
81
- ## Code of Conduct
104
+ The transformation of the original image should be specified via options.
82
105
 
83
- Everyone interacting in the Carrierwave::Cloudflare project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/resume-io/carrierwave-cloudflare/blob/master/CODE_OF_CONDUCT.md).
106
+ ```ruby
107
+ hidpi_image_tag('/bird.jpg', width: 400, drps: [1, 2])
108
+ # => <img srcset="/cdn-cgi/image/width=400,dpr=1/img.jpg 1x, /cdn-cgi/image/width=400,dpr=2/img.jpg 2x" src="/cdn-cgi/image/width=400/img.jpg" />
109
+ ```
110
+
111
+
112
+ ### responsive_image_tag(url, width:, sizes: nil, dprs: [1, 2], **options)
113
+
114
+ Returns a reponsive image tag with variations.
115
+
116
+ ```ruby
117
+ responsive_image_tag('/bird.jpg', width: 1200, sizes: { phone: 600, tablet: 800 })
118
+
119
+ # => <img srcset="/cdn-cgi/image/width=1200,dpr=0.5/bird.jpg 600w,
120
+ # /cdn-cgi/image/width=1200,dpr=1.0/bird.jpg 1200w,
121
+ # /cdn-cgi/image/width=1200,dpr=0.67/bird.jpg 800w,
122
+ # /cdn-cgi/image/width=1200,dpr=1.33/bird.jpg 1600w,
123
+ # /cdn-cgi/image/width=1200,dpr=2.0/bird.jpg 2400w"
124
+ # sizes="(max-width: 767px) 600px, (max-width: 1023px) 800px, 1200px"
125
+ # src="/cdn-cgi/image/width=1200/bird.jpg" />
126
+
127
+ ```
128
+
129
+
130
+ ## Development
131
+
132
+ 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.
133
+
134
+ 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 tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
@@ -27,6 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.require_paths = ['lib']
28
28
 
29
29
  spec.add_development_dependency 'activesupport', '~> 5.2'
30
+ spec.add_development_dependency 'actionview', '~> 5.2'
30
31
  spec.add_development_dependency 'pry'
31
32
  spec.add_development_dependency 'rack', '~> 2.0'
32
33
  spec.add_development_dependency 'rake'
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support'
3
+ require "active_support"
4
4
 
5
- require 'carrierwave/cloudflare/version'
5
+ require "carrierwave/cloudflare/version"
6
6
 
7
7
  module CarrierWave
8
8
  module Cloudflare
@@ -72,7 +72,7 @@ module CarrierWave
72
72
  def resize(**options)
73
73
  # build temporary uploader
74
74
  uploader = self.class.dup
75
- self.class.const_set("Uploader#{uploader.object_id}".tr('-', '_'), uploader)
75
+ self.class.const_set("Uploader#{uploader.object_id}".tr("-", "_"), uploader)
76
76
  uploader.version_options = { cdn_transform: options }
77
77
 
78
78
  # init the instance uploader and set parent_version
@@ -102,4 +102,4 @@ module CarrierWave
102
102
  end
103
103
  end
104
104
 
105
- require_relative 'cloudflare/url'
105
+ require "carrierwave/cloudflare/url"
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CarrierWave
4
+ module Cloudflare
5
+ module ActionView
6
+ module ResponsiveImagesHelper
7
+ CDN_TRANSFORM_KEYS = CarrierWave::Cloudflare::URL::ALLOWED_OPTIONS.map(&:to_sym)
8
+
9
+ # Returns an image URL with CDN transformations applied.
10
+ # Can process already transformed URLs, in that case the
11
+ # options will be merged together.
12
+ #
13
+ # ==== Examples
14
+ #
15
+ # cdn_transformed('/img.jpg', width: 400)
16
+ # # => '/cdn-cgi/image/width=400/img.jpg'
17
+ #
18
+ # cdn_transformed('/cdn-cgi/image/width=100,fit=pad/img.jpg', width: 333)
19
+ # # => '/cdn-cgi/image/width=333,fit=pad/img.jpg'
20
+ #
21
+ def cdn_transformed(url, **options)
22
+ base_options = BaseUploader.default_cdn_options
23
+
24
+ CarrierWave::Cloudflare::URL.transform(
25
+ url,
26
+ **base_options,
27
+ **options
28
+ )
29
+ end
30
+
31
+ # Returns an image tag with with scaled variations (via `srcset`)
32
+ # attribute for devices with different DPR values.
33
+ #
34
+ # The transformation of the original image should be specified via
35
+ # options.
36
+ #
37
+ # ==== Examples
38
+ #
39
+ # hidpi_image_tag('/bird.jpg', width: 400, height: 100, alt: 'A bird')
40
+ #
41
+ # hidpi_image_tag('/bird.jpg', width: 400, drps: [1, 2])
42
+ #
43
+ def hidpi_image_tag(url, dprs: nil, **options)
44
+ url = url.url if url.is_a?(CarrierWave::Uploader)
45
+ transform, rest = split_cdn_transform_options(options)
46
+
47
+ image_tag(
48
+ cdn_transformed(url, **transform),
49
+ srcset: hidpi_image_srcset(url, dprs: dprs, **transform),
50
+ **rest
51
+ )
52
+ end
53
+
54
+ # Like #hidpi_image_tag, but returns an scrset attribute value.
55
+ def hidpi_image_srcset(url, dprs: nil, **options)
56
+ return nil unless url.present?
57
+
58
+ url = url.url if url.is_a?(CarrierWave::Uploader)
59
+
60
+ (dprs || [1, 2]).map do |dpr|
61
+ [cdn_transformed(url, dpr: dpr, **options), "#{dpr}x"].join(" ")
62
+ end.join(", ")
63
+ end
64
+
65
+ # Returns a reponsive image tag with variations.
66
+ #
67
+ # ==== Examples
68
+ #
69
+ # responsive_image_tag('/bird.jpg', width: 1200, sizes:
70
+ # { phone: 600, tablet: 800 })
71
+ #
72
+ def responsive_image_tag(url, width:, sizes: nil, dprs: [1, 2], **options)
73
+ url = url.url if url.is_a?(CarrierWave::Uploader)
74
+
75
+ if sizes.nil?
76
+ return hidpi_image_tag(url, **options)
77
+ end
78
+
79
+ sizes[:default] = width
80
+
81
+ breakpoints = {
82
+ phone: "(max-width: 767px)",
83
+ mobile: "(max-width: 767px)", # an alias for :phone
84
+ tablet: "(max-width: 1023px)",
85
+ laptop: "(max-width: 1279px)",
86
+ desktop: "(min-width: 1280px)",
87
+ default: nil
88
+ }
89
+
90
+ sizes_attr = breakpoints.map do |device, media|
91
+ next nil unless sizes[device]
92
+
93
+ [media, "#{sizes[device]}px"].compact.join(" ")
94
+ end.compact.join(", ")
95
+
96
+ transform, rest = split_cdn_transform_options(options)
97
+ base_version = cdn_transformed(url, width: width, **transform)
98
+
99
+ # construct the array of available variation sizes in `srcset`
100
+ variations = scrset_variations_from_breakpoints(sizes, dprs: dprs)
101
+
102
+ srcset = variations.map do |size|
103
+ scale = (size.to_f / width).round(2)
104
+ [cdn_transformed(url, width: width, **transform, dpr: scale), "#{size}w"]
105
+ end
106
+
107
+ image_tag(
108
+ base_version,
109
+ srcset: srcset,
110
+ sizes: sizes_attr,
111
+ **rest
112
+ )
113
+ end
114
+
115
+ def scrset_variations_from_breakpoints(breakpoints, dprs:, granularity: 180)
116
+ # [300, 900] => [300, 600, 900, 1800]
117
+ doubled = breakpoints.values.product(dprs).map { |s, d| (s * d).round }
118
+
119
+ # [100, 101, 150, 250, 320] => [100, 250, 320]
120
+ doubled.uniq { |s| s / granularity }
121
+ end
122
+
123
+ # returns a pair of transformation options and other options
124
+ def split_cdn_transform_options(options)
125
+ [
126
+ options.slice(*CDN_TRANSFORM_KEYS),
127
+ options.except(*CDN_TRANSFORM_KEYS)
128
+ ]
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,15 @@
1
+ require "rails/railtie"
2
+
3
+ module CarrierWave
4
+ module Cloudflare
5
+ class Railtie < ::Rails::Railtie
6
+ initializer "carrierwave-cloudflare.action_view" do |_app|
7
+ ActiveSupport.on_load :action_view do
8
+ require "carrierwave/cloudflare/action_view/responsive_images_helper"
9
+
10
+ include CarrierWave::Cloudflare::ActionView::ResponsiveImagesHelper
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,86 +1,90 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'url/query_string'
3
+ require "carrierwave/cloudflare/url/query_string"
4
4
 
5
- module CarrierWave::Cloudflare
6
- module URL
7
- ALLOWED_OPTIONS = %w[width height dpr fit gravity quality format onerror metadata].freeze
5
+ module CarrierWave
6
+ module Cloudflare
7
+ module URL
8
+ ALLOWED_OPTIONS = %w[width height dpr fit gravity quality format onerror metadata].freeze
8
9
 
9
- module_function
10
+ module_function
10
11
 
11
- def should_modify_path?
12
- ::CarrierWave::Cloudflare.cloudflare_transform
13
- end
12
+ def should_modify_path?
13
+ ::CarrierWave::Cloudflare.cloudflare_transform
14
+ end
14
15
 
15
- def extract(url)
16
- uri = URI.parse(url)
17
- options = {}
16
+ def extract(url)
17
+ uri = URI.parse(url)
18
+ options = {}
18
19
 
19
- if should_modify_path?
20
- if %r{/cdn-cgi/image/([^/]+)(/.*)} =~ uri.path
21
- formatted = $LAST_MATCH_INFO[1]
22
- original_path = $LAST_MATCH_INFO[2]
20
+ if should_modify_path?
21
+ if %r{/cdn-cgi/image/([^/]+)(/.*)} =~ uri.path
22
+ formatted = $LAST_MATCH_INFO[1]
23
+ original_path = $LAST_MATCH_INFO[2]
23
24
 
24
- options = parse_options(formatted)
25
- uri.path = original_path
26
- end
27
- else
28
- query = QueryString.new(uri.query)
25
+ options = parse_options(formatted)
26
+ uri.path = original_path
27
+ end
28
+ else
29
+ query = QueryString.new(uri.query)
29
30
 
30
- if query.key?('cdn-cgi')
31
- options = parse_options(query['cdn-cgi'], separator: '.', assigner: '-')
31
+ if query.key?("cdn-cgi")
32
+ options = parse_options(query["cdn-cgi"], separator: ".", assigner: "-")
33
+ end
32
34
  end
33
- end
34
35
 
35
- [uri, options]
36
- end
36
+ [uri, options]
37
+ end
37
38
 
38
- def transform(url, **options)
39
- uri, existing_opts = extract(url)
40
- options = existing_opts.merge(options.transform_keys(&:to_s))
39
+ def transform(url, **options)
40
+ uri, existing_opts = extract(url)
41
+ options = existing_opts.merge(options.transform_keys(&:to_s))
41
42
 
42
- pairs = sanitized_options(options)
43
+ pairs = sanitized_options(options)
43
44
 
44
- if pairs.empty?
45
- url
46
- else
47
- append_options!(uri, pairs)
48
- uri.to_s
45
+ if pairs.empty?
46
+ url
47
+ else
48
+ append_options!(uri, pairs)
49
+ uri.to_s
50
+ end
49
51
  end
50
- end
51
52
 
52
- def append_options!(uri, options)
53
- if should_modify_path?
54
- segment = '/cdn-cgi/image/' + options.map { |k, v| "#{k}=#{v}" }.join(',')
55
- uri.path = segment + uri.path
56
- else
57
- uri.query = QueryString.new(uri.query).tap do |params|
58
- # the format is "width-500.height.200", only safe symbols are used
59
- param_with_options = options.map { |k, v| "#{k}-#{v}" }.join('.')
60
-
61
- params['cdn-cgi'] = param_with_options
62
- end.to_query
63
- end
64
- end
53
+ def append_options!(uri, options)
54
+ if should_modify_path?
55
+ query = options.map { |k, v| "#{k}=#{v}" }.join(",")
56
+
57
+ segment = "/cdn-cgi/image/#{query}"
58
+ uri.path = segment + uri.path
59
+ else
60
+ uri.query = QueryString.new(uri.query).tap do |params|
61
+ # the format is "width-500.height.200", only safe symbols are used
62
+ param_with_options = options.map { |k, v| "#{k}-#{v}" }.join(".")
65
63
 
66
- def sanitized_options(options)
67
- ordered = options.map do |k, v|
68
- idx = ALLOWED_OPTIONS.index(k)
69
- [idx, [k, v]]
64
+ params["cdn-cgi"] = param_with_options
65
+ end.to_query
66
+ end
70
67
  end
71
68
 
72
- filtered = ordered.select { |i,| i }.sort
69
+ def sanitized_options(options)
70
+ ordered = options.map do |k, v|
71
+ idx = ALLOWED_OPTIONS.index(k)
72
+ [idx, [k, v]]
73
+ end
74
+
75
+ filtered = ordered.select { |i,| i }.sort
73
76
 
74
- filtered.map do |_, (k, v)|
75
- v = v.join('x') if v.is_a?(Array)
76
- [k, v]
77
+ filtered.map do |_, (k, v)|
78
+ v = v.join("x") if v.is_a?(Array)
79
+ [k, v]
80
+ end
77
81
  end
78
- end
79
82
 
80
- # converts strings "w=foo,h=bar" into hashes
81
- def parse_options(str, separator: ',', assigner: '=')
82
- kv = str.split(separator).map { |s| s.strip.split(assigner) }
83
- Hash[kv]
83
+ # converts strings "w=foo,h=bar" into hashes
84
+ def parse_options(str, separator: ",", assigner: "=")
85
+ kv = str.split(separator).map { |s| s.strip.split(assigner) }
86
+ Hash[kv]
87
+ end
84
88
  end
85
89
  end
86
90
  end
@@ -1,26 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rack/utils'
3
+ require "rack/utils"
4
4
 
5
- module CarrierWave::Cloudflare::URL
6
- class QueryString < Hash
7
- Parser = Object.new.tap do |obj|
8
- obj.extend(Rack::Utils)
5
+ module CarrierWave
6
+ module Cloudflare
7
+ module URL
8
+ class QueryString < Hash
9
+ Parser = Object.new.tap do |obj|
10
+ obj.extend(Rack::Utils)
9
11
 
10
- # these methods are private in Rack::Utils
11
- obj.singleton_class.instance_eval { public :build_query, :parse_query }
12
- end
12
+ # these methods are private in Rack::Utils
13
+ obj.singleton_class.instance_eval { public :build_query, :parse_query }
14
+ end
13
15
 
14
- def initialize(query = '')
15
- super()
16
- merge!(Parser.parse_query(query))
17
- end
16
+ def initialize(query = "")
17
+ super()
18
+ merge!(Parser.parse_query(query))
19
+ end
18
20
 
19
- def to_query
20
- result = Parser.build_query(self)
21
- result unless result.empty?
22
- end
21
+ def to_query
22
+ result = Parser.build_query(self)
23
+ result unless result.empty?
24
+ end
23
25
 
24
- alias to_s to_query
26
+ alias to_s to_query
27
+ end
28
+ end
25
29
  end
26
30
  end
@@ -1,5 +1,5 @@
1
1
  module Carrierwave
2
2
  module Cloudflare
3
- VERSION = "0.1.1"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: carrierwave-cloudflare
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Frost
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2021-07-22 00:00:00.000000000 Z
12
+ date: 2021-08-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -25,6 +25,20 @@ dependencies:
25
25
  - - "~>"
26
26
  - !ruby/object:Gem::Version
27
27
  version: '5.2'
28
+ - !ruby/object:Gem::Dependency
29
+ name: actionview
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '5.2'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '5.2'
28
42
  - !ruby/object:Gem::Dependency
29
43
  name: pry
30
44
  requirement: !ruby/object:Gem::Requirement
@@ -106,9 +120,9 @@ files:
106
120
  - ".github/workflows/run-specs.yml"
107
121
  - ".gitignore"
108
122
  - ".rspec"
123
+ - ".rubocop.yml"
109
124
  - ".travis.yml"
110
125
  - CHANGELOG.md
111
- - CODE_OF_CONDUCT.md
112
126
  - Gemfile
113
127
  - Gemfile.lock
114
128
  - LICENSE.txt
@@ -118,6 +132,8 @@ files:
118
132
  - bin/setup
119
133
  - carrierwave-cloudflare.gemspec
120
134
  - lib/carrierwave/cloudflare.rb
135
+ - lib/carrierwave/cloudflare/action_view/responsive_images_helper.rb
136
+ - lib/carrierwave/cloudflare/railtie.rb
121
137
  - lib/carrierwave/cloudflare/url.rb
122
138
  - lib/carrierwave/cloudflare/url/query_string.rb
123
139
  - lib/carrierwave/cloudflare/version.rb
data/CODE_OF_CONDUCT.md DELETED
@@ -1,74 +0,0 @@
1
- # Contributor Covenant Code of Conduct
2
-
3
- ## Our Pledge
4
-
5
- In the interest of fostering an open and welcoming environment, we as
6
- contributors and maintainers pledge to making participation in our project and
7
- our community a harassment-free experience for everyone, regardless of age, body
8
- size, disability, ethnicity, gender identity and expression, level of experience,
9
- nationality, personal appearance, race, religion, or sexual identity and
10
- orientation.
11
-
12
- ## Our Standards
13
-
14
- Examples of behavior that contributes to creating a positive environment
15
- include:
16
-
17
- * Using welcoming and inclusive language
18
- * Being respectful of differing viewpoints and experiences
19
- * Gracefully accepting constructive criticism
20
- * Focusing on what is best for the community
21
- * Showing empathy towards other community members
22
-
23
- Examples of unacceptable behavior by participants include:
24
-
25
- * The use of sexualized language or imagery and unwelcome sexual attention or
26
- advances
27
- * Trolling, insulting/derogatory comments, and personal or political attacks
28
- * Public or private harassment
29
- * Publishing others' private information, such as a physical or electronic
30
- address, without explicit permission
31
- * Other conduct which could reasonably be considered inappropriate in a
32
- professional setting
33
-
34
- ## Our Responsibilities
35
-
36
- Project maintainers are responsible for clarifying the standards of acceptable
37
- behavior and are expected to take appropriate and fair corrective action in
38
- response to any instances of unacceptable behavior.
39
-
40
- Project maintainers have the right and responsibility to remove, edit, or
41
- reject comments, commits, code, wiki edits, issues, and other contributions
42
- that are not aligned to this Code of Conduct, or to ban temporarily or
43
- permanently any contributor for other behaviors that they deem inappropriate,
44
- threatening, offensive, or harmful.
45
-
46
- ## Scope
47
-
48
- This Code of Conduct applies both within project spaces and in public spaces
49
- when an individual is representing the project or its community. Examples of
50
- representing a project or community include using an official project e-mail
51
- address, posting via an official social media account, or acting as an appointed
52
- representative at an online or offline event. Representation of a project may be
53
- further defined and clarified by project maintainers.
54
-
55
- ## Enforcement
56
-
57
- Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
- reported by contacting the project team at cheerful.mf@gmail.com. All
59
- complaints will be reviewed and investigated and will result in a response that
60
- is deemed necessary and appropriate to the circumstances. The project team is
61
- obligated to maintain confidentiality with regard to the reporter of an incident.
62
- Further details of specific enforcement policies may be posted separately.
63
-
64
- Project maintainers who do not follow or enforce the Code of Conduct in good
65
- faith may face temporary or permanent repercussions as determined by other
66
- members of the project's leadership.
67
-
68
- ## Attribution
69
-
70
- This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
- available at [https://contributor-covenant.org/version/1/4][version]
72
-
73
- [homepage]: https://contributor-covenant.org
74
- [version]: https://contributor-covenant.org/version/1/4/