carrierwave-cloudflare 0.1.1 → 0.3.1

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: 542a858721ea0a09a74b3aa0bec87cc0a43cee7377fafef29dc99bee23a22cdc
4
+ data.tar.gz: 73110195e913127f4d496637a69611fb3c183613a0d2154584280b6b9613b82c
5
5
  SHA512:
6
- metadata.gz: a35397c051afa4e66920e22ce10a3717e789b8f5bf1b41ac970c16814c24f8b5a380a587cb886af919628eaf8aeff60d5dfbab1105d1ba61835eaf2aeeccf0fc
7
- data.tar.gz: d28e1eef9d280247abb591258478dec7a0b7e9bc66b3f6354a0037aea37c9f584b32465cb9b04dcc287bde94b65b96808270185e9bec2096447b481cf5a2c34c
6
+ metadata.gz: d10ba26a72aa5d3c1e7c9e52720920c54918f1cfc5611dc8e9ead91a2d94337cdfd209d0057b7604db4848a4ab902528a38d20190a150c2606ccfc72a113a9e1
7
+ data.tar.gz: 053fd7d9086726ad54110efdfc5989c820e5a02f109e9af78795d59c613bb4c76522e79be8a65539770e0848a859c61d1f4558ad40f85e658cdec24ab45af521
data/.gitignore CHANGED
@@ -9,3 +9,5 @@
9
9
 
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
+
13
+ Gemfile.lock
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/README.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # Carrierwave::Cloudflare
2
2
 
3
- This gem provides a simple wrapper for transformation images via Cloudflare
3
+ [![Tests](https://github.com/resume-io/carrierwave-cloudflare/actions/workflows/run-specs.yml/badge.svg?branch=master)](https://github.com/resume-io/carrierwave-cloudflare/actions/workflows/run-specs.yml)
4
+ [![Gem Version](https://badge.fury.io/rb/carrierwave-cloudflare.svg)](https://badge.fury.io/rb/carrierwave-cloudflare)
5
+
6
+ This gem integrates CarrierWave with [Cloudflare Image Resizing](https://developers.cloudflare.com/images/)
7
+
4
8
 
5
9
  ## Installation
6
10
 
@@ -28,8 +32,8 @@ class BaseUploader < CarrierWave::Uploader::Base
28
32
  end
29
33
  ```
30
34
 
35
+ 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
36
 
32
- Define `virtual` version in some uploader:
33
37
  ```ruby
34
38
  class AvatarUploader < BaseUploader
35
39
  version(:medium) do
@@ -37,14 +41,13 @@ class AvatarUploader < BaseUploader
37
41
  end
38
42
  end
39
43
 
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
44
+ user = User.find(some_id)
45
+ user.avatar.medium # CarrierWave::Uploader
46
+ user.avatar.url # "https://s3.your-website.com/users/avatar/1.jpg"
47
+ user.avatar.medium_url # "https://s3.your-website.com/cdn-cgi/width=100,height=100,dpr=2/users/avatar/1.jpg"
48
+ user.avatar.url(:medium) # "https://s3.your-website.com/cdn-cgi/width=100,height=100,dpr=2/users/avatar/1.jpg"
49
+ user.avatar.medium.url(dpr: 1) # "https://s3.your-website.com/cdn-cgi/width=100,height=100,dpr=1/users/avatar/1.jpg"
50
+ 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
51
  ```
49
52
 
50
53
  ### Options
@@ -53,7 +56,7 @@ Supported options:
53
56
 
54
57
  `width`, `height`, `dpr`, `fit`, `gravity`, `quality`, `format`, `onerror`, `metadata`
55
58
 
56
- See details in Cloudflare [documentation](https://developers.cloudflare.com/images/about)
59
+ See details in Cloudflare [documentation](https://developers.cloudflare.com/images/url-format)
57
60
 
58
61
  Also, you can define default options (supports all options described above)
59
62
 
@@ -63,21 +66,71 @@ class BaseUploader < CarrierWave::Uploader::Base
63
66
  end
64
67
  ```
65
68
 
66
- ## Development
69
+ ### In development env
67
70
 
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.
71
+ 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
72
 
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).
73
+ ``` ruby
74
+ CarrierWave::Cloudflare.configure do |config|
75
+ config.cloudflare_transform(false)
76
+ end
77
+ ```
78
+
79
+ `cloudflare_transform: false` disables links generation and put all Cloudflare's arguments into query string (for easy debugging)
71
80
 
72
- ## Contributing
81
+ e.g:
82
+
83
+ ```
84
+ /1.jpg?cdn-cgi=width-11.height-300.fit-pad
85
+ ```
86
+
87
+ ## Rails views helpers
88
+
89
+ ### cdn_transformed(url, **options)
90
+ Returns an image URL with CDN transformations applied. Can process already transformed URLs, in that case the options will be merged together.
91
+
92
+ ```ruby
93
+ cdn_transformed('/img.jpg', width: 400)
94
+ # => '/cdn-cgi/image/width=400/img.jpg'
95
+
96
+ cdn_transformed('/cdn-cgi/image/width=100,fit=pad/img.jpg', width: 333)
97
+ # => '/cdn-cgi/image/width=333,fit=pad/img.jpg'
98
+ ```
73
99
 
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
100
 
101
+ ### hidpi_image_tag(url, dprs: nil, **options)
76
102
 
77
- ## License
103
+ Returns an image tag with with scaled variations (via `srcset`) attribute for devices with different DPR values.
78
104
 
79
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
80
105
 
81
- ## Code of Conduct
106
+ The transformation of the original image should be specified via options.
82
107
 
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).
108
+ ```ruby
109
+ hidpi_image_tag('/bird.jpg', width: 400, drps: [1, 2])
110
+ # => <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" />
111
+ ```
112
+
113
+
114
+ ### responsive_image_tag(url, width:, sizes: nil, dprs: [1, 2], **options)
115
+
116
+ Returns a reponsive image tag with variations.
117
+
118
+ ```ruby
119
+ responsive_image_tag('/bird.jpg', width: 1200, sizes: { phone: 600, tablet: 800 })
120
+
121
+ # => <img srcset="/cdn-cgi/image/width=1200,dpr=0.5/bird.jpg 600w,
122
+ # /cdn-cgi/image/width=1200,dpr=1.0/bird.jpg 1200w,
123
+ # /cdn-cgi/image/width=1200,dpr=0.67/bird.jpg 800w,
124
+ # /cdn-cgi/image/width=1200,dpr=1.33/bird.jpg 1600w,
125
+ # /cdn-cgi/image/width=1200,dpr=2.0/bird.jpg 2400w"
126
+ # sizes="(max-width: 767px) 600px, (max-width: 1023px) 800px, 1200px"
127
+ # src="/cdn-cgi/image/width=1200/bird.jpg" />
128
+
129
+ ```
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 tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
@@ -1,36 +1,36 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'lib/carrierwave/cloudflare/version'
3
+ require_relative "lib/carrierwave/cloudflare/version"
4
4
 
5
5
  Gem::Specification.new do |spec|
6
- spec.name = 'carrierwave-cloudflare'
7
- spec.version = Carrierwave::Cloudflare::VERSION
8
- spec.authors = ['Mark Frost', 'Alexey Taktarov']
9
- spec.email = ['cheerful.mf@gmail.com']
6
+ spec.name = "carrierwave-cloudflare"
7
+ spec.version = CarrierWave::Cloudflare::VERSION
8
+ spec.authors = ["Mark Frost", "Alexey Taktarov"]
9
+ spec.email = ["cheerful.mf@gmail.com"]
10
10
 
11
- spec.summary = 'Wrapper for cloudflare transforming images'
12
- spec.homepage = 'https://github.com/resume-io/carrierwave-cloudflare'
13
- spec.license = 'MIT'
14
- spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
11
+ spec.summary = "Wrapper for cloudflare transforming images"
12
+ spec.homepage = "https://github.com/resume-io/carrierwave-cloudflare"
13
+ spec.license = "MIT"
14
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
15
15
 
16
- spec.metadata['homepage_uri'] = spec.homepage
17
- spec.metadata['source_code_uri'] = 'https://github.com/resume-io/carrierwave-cloudflare'
18
- spec.metadata['changelog_uri'] = 'https://github.com/resume-io/carrierwave-cloudflare/blob/master/CHANGELOG.md'
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+ spec.metadata["source_code_uri"] = "https://github.com/resume-io/carrierwave-cloudflare"
18
+ spec.metadata["changelog_uri"] = "https://github.com/resume-io/carrierwave-cloudflare/blob/master/CHANGELOG.md"
19
19
 
20
20
  # Specify which files should be added to the gem when it is released.
21
21
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
22
22
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
23
23
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
24
24
  end
25
- spec.bindir = 'exe'
25
+ spec.bindir = "exe"
26
26
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
- spec.require_paths = ['lib']
27
+ spec.require_paths = ["lib"]
28
28
 
29
- spec.add_development_dependency 'activesupport', '~> 5.2'
30
- spec.add_development_dependency 'pry'
31
- spec.add_development_dependency 'rack', '~> 2.0'
32
- spec.add_development_dependency 'rake'
33
- spec.add_development_dependency 'rspec'
34
-
35
- spec.add_dependency 'carrierwave', '~> 1.3'
29
+ spec.add_development_dependency "actionview", "~> 5.2"
30
+ spec.add_development_dependency "activesupport", "~> 5.2"
31
+ spec.add_development_dependency "carrierwave", "~> 1.3"
32
+ spec.add_development_dependency "pry"
33
+ spec.add_development_dependency "rack", "~> 2.0"
34
+ spec.add_development_dependency "rake"
35
+ spec.add_development_dependency "rspec"
36
36
  end
@@ -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,7 @@
1
- module Carrierwave
1
+ # frozen_string_literal: true
2
+
3
+ module CarrierWave
2
4
  module Cloudflare
3
- VERSION = "0.1.1"
5
+ VERSION = "0.3.1"
4
6
  end
5
7
  end
metadata CHANGED
@@ -1,16 +1,30 @@
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.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Frost
8
8
  - Alexey Taktarov
9
- autorequire:
9
+ autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2021-07-22 00:00:00.000000000 Z
12
+ date: 2021-08-02 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: actionview
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '5.2'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '5.2'
14
28
  - !ruby/object:Gem::Dependency
15
29
  name: activesupport
16
30
  requirement: !ruby/object:Gem::Requirement
@@ -25,6 +39,20 @@ dependencies:
25
39
  - - "~>"
26
40
  - !ruby/object:Gem::Version
27
41
  version: '5.2'
42
+ - !ruby/object:Gem::Dependency
43
+ name: carrierwave
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '1.3'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '1.3'
28
56
  - !ruby/object:Gem::Dependency
29
57
  name: pry
30
58
  requirement: !ruby/object:Gem::Requirement
@@ -81,36 +109,20 @@ dependencies:
81
109
  - - ">="
82
110
  - !ruby/object:Gem::Version
83
111
  version: '0'
84
- - !ruby/object:Gem::Dependency
85
- name: carrierwave
86
- requirement: !ruby/object:Gem::Requirement
87
- requirements:
88
- - - "~>"
89
- - !ruby/object:Gem::Version
90
- version: '1.3'
91
- type: :runtime
92
- prerelease: false
93
- version_requirements: !ruby/object:Gem::Requirement
94
- requirements:
95
- - - "~>"
96
- - !ruby/object:Gem::Version
97
- version: '1.3'
98
- description:
112
+ description:
99
113
  email:
100
114
  - cheerful.mf@gmail.com
101
115
  executables: []
102
116
  extensions: []
103
117
  extra_rdoc_files: []
104
118
  files:
105
- - ".github/workflows/publish-gem.yml"
106
119
  - ".github/workflows/run-specs.yml"
107
120
  - ".gitignore"
108
121
  - ".rspec"
122
+ - ".rubocop.yml"
109
123
  - ".travis.yml"
110
124
  - CHANGELOG.md
111
- - CODE_OF_CONDUCT.md
112
125
  - Gemfile
113
- - Gemfile.lock
114
126
  - LICENSE.txt
115
127
  - README.md
116
128
  - Rakefile
@@ -118,6 +130,8 @@ files:
118
130
  - bin/setup
119
131
  - carrierwave-cloudflare.gemspec
120
132
  - lib/carrierwave/cloudflare.rb
133
+ - lib/carrierwave/cloudflare/action_view/responsive_images_helper.rb
134
+ - lib/carrierwave/cloudflare/railtie.rb
121
135
  - lib/carrierwave/cloudflare/url.rb
122
136
  - lib/carrierwave/cloudflare/url/query_string.rb
123
137
  - lib/carrierwave/cloudflare/version.rb
@@ -128,7 +142,7 @@ metadata:
128
142
  homepage_uri: https://github.com/resume-io/carrierwave-cloudflare
129
143
  source_code_uri: https://github.com/resume-io/carrierwave-cloudflare
130
144
  changelog_uri: https://github.com/resume-io/carrierwave-cloudflare/blob/master/CHANGELOG.md
131
- post_install_message:
145
+ post_install_message:
132
146
  rdoc_options: []
133
147
  require_paths:
134
148
  - lib
@@ -143,8 +157,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
143
157
  - !ruby/object:Gem::Version
144
158
  version: '0'
145
159
  requirements: []
146
- rubygems_version: 3.0.3.1
147
- signing_key:
160
+ rubygems_version: 3.0.3
161
+ signing_key:
148
162
  specification_version: 4
149
163
  summary: Wrapper for cloudflare transforming images
150
164
  test_files: []
@@ -1,49 +0,0 @@
1
- name: Publish Gem
2
-
3
- on:
4
- # Manually publish
5
- workflow_dispatch:
6
- # Alternatively, publish whenever changes are merged to the `main` branch.
7
- push:
8
- branches: "*"
9
- pull_request:
10
- branches: "*"
11
-
12
- jobs:
13
- build:
14
- name: Build + Publish
15
- runs-on: ubuntu-latest
16
- permissions:
17
- packages: write
18
- contents: read
19
-
20
- steps:
21
- - uses: actions/checkout@v2
22
- - name: Set up Ruby 2.6
23
- uses: ruby/setup-ruby@477b21f02be01bcb8030d50f37cfec92bfa615b6
24
- with:
25
- ruby-version: 2.6
26
- - run: bundle install
27
-
28
- # - name: Publish to GPR
29
- # run: |
30
- # mkdir -p $HOME/.gem
31
- # touch $HOME/.gem/credentials
32
- # chmod 0600 $HOME/.gem/credentials
33
- # printf -- "---\n:github: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
34
- # gem build *.gemspec
35
- # gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} *.gem
36
- # env:
37
- # GEM_HOST_API_KEY: "Bearer ${{secrets.GITHUB_TOKEN}}"
38
- # OWNER: ${{ github.repository_owner }}
39
-
40
- - name: Publish to RubyGems
41
- run: |
42
- mkdir -p $HOME/.gem
43
- touch $HOME/.gem/credentials
44
- chmod 0600 $HOME/.gem/credentials
45
- printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
46
- gem build *.gemspec
47
- gem push *.gem
48
- env:
49
- GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
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/
data/Gemfile.lock DELETED
@@ -1,67 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- carrierwave-cloudflare (0.1.1)
5
- carrierwave (~> 1.3)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- activemodel (5.2.3)
11
- activesupport (= 5.2.3)
12
- activesupport (5.2.3)
13
- concurrent-ruby (~> 1.0, >= 1.0.2)
14
- i18n (>= 0.7, < 2)
15
- minitest (~> 5.1)
16
- tzinfo (~> 1.1)
17
- carrierwave (1.3.2)
18
- activemodel (>= 4.0.0)
19
- activesupport (>= 4.0.0)
20
- mime-types (>= 1.16)
21
- ssrf_filter (~> 1.0)
22
- coderay (1.1.2)
23
- concurrent-ruby (1.1.6)
24
- diff-lcs (1.4.4)
25
- i18n (1.8.5)
26
- concurrent-ruby (~> 1.0)
27
- method_source (1.0.0)
28
- mime-types (3.3.1)
29
- mime-types-data (~> 3.2015)
30
- mime-types-data (3.2020.1104)
31
- minitest (5.14.1)
32
- pry (0.13.1)
33
- coderay (~> 1.1)
34
- method_source (~> 1.0)
35
- rack (2.2.3)
36
- rake (13.0.3)
37
- rspec (3.10.0)
38
- rspec-core (~> 3.10.0)
39
- rspec-expectations (~> 3.10.0)
40
- rspec-mocks (~> 3.10.0)
41
- rspec-core (3.10.1)
42
- rspec-support (~> 3.10.0)
43
- rspec-expectations (3.10.1)
44
- diff-lcs (>= 1.2.0, < 2.0)
45
- rspec-support (~> 3.10.0)
46
- rspec-mocks (3.10.1)
47
- diff-lcs (>= 1.2.0, < 2.0)
48
- rspec-support (~> 3.10.0)
49
- rspec-support (3.10.1)
50
- ssrf_filter (1.0.7)
51
- thread_safe (0.3.6)
52
- tzinfo (1.2.7)
53
- thread_safe (~> 0.1)
54
-
55
- PLATFORMS
56
- ruby
57
-
58
- DEPENDENCIES
59
- activesupport (~> 5.2)
60
- carrierwave-cloudflare!
61
- pry
62
- rack (~> 2.0)
63
- rake
64
- rspec
65
-
66
- BUNDLED WITH
67
- 2.1.4