cloudinary 1.13.1 → 1.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +42 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +21 -0
- data/CHANGELOG.md +59 -0
- data/Rakefile +3 -45
- data/cloudinary.gemspec +16 -2
- data/lib/active_storage/service/cloudinary_service.rb +44 -9
- data/lib/cloudinary.rb +22 -18
- data/lib/cloudinary/api.rb +3 -2
- data/lib/cloudinary/carrier_wave.rb +1 -0
- data/lib/cloudinary/carrier_wave/remote.rb +2 -2
- data/lib/cloudinary/carrier_wave/storage.rb +2 -1
- data/lib/cloudinary/cloudinary_controller.rb +2 -4
- data/lib/cloudinary/railtie.rb +7 -3
- data/lib/cloudinary/uploader.rb +6 -2
- data/lib/cloudinary/utils.rb +13 -10
- data/lib/cloudinary/version.rb +1 -1
- data/lib/tasks/cloudinary/fetch_assets.rake +48 -0
- data/lib/tasks/{cloudinary.rake → cloudinary/sync_static.rake} +0 -0
- data/vendor/assets/javascripts/cloudinary/jquery.cloudinary.js +17 -13
- metadata +12 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eeda4318322d6304cf37a68c621387dc7d4382cd45d6665eddea154ce30adac3
|
4
|
+
data.tar.gz: ef675318a0c25a7e729d91ad014a8b36bad2756cafb73c20f69693b230747537
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c1ad5eee4b1b5eca7467e134cba0fc9516c0fe5af018637c1c0dbabc0a707a30e1cb115892de48f2acd2f8d339159842599edb7e0a1be15ea4ef391cbe569b78
|
7
|
+
data.tar.gz: 19235e8274a35ed46c302a57056c45ff885b1a59a8ad852b057bce384729b108105b9b6d53638adefc2b317cccbc3fae48f4dbae962937e3e682da962f817b86
|
@@ -0,0 +1,42 @@
|
|
1
|
+
---
|
2
|
+
name: Bug report
|
3
|
+
about: Bug report for Cloudinary Ruby SDK
|
4
|
+
title: ''
|
5
|
+
labels: ''
|
6
|
+
assignees: const-cloudinary
|
7
|
+
|
8
|
+
---
|
9
|
+
|
10
|
+
## Bug report for Cloudinary Ruby SDK
|
11
|
+
Before proceeding, please update to latest version and test if the issue persists
|
12
|
+
|
13
|
+
## Describe the bug in a sentence or two.
|
14
|
+
…
|
15
|
+
|
16
|
+
## Issue Type (Can be multiple)
|
17
|
+
[ ] Build - Can’t install or import the SDK
|
18
|
+
[ ] Performance - Performance issues
|
19
|
+
[ ] Behaviour - Functions aren’t working as expected (Such as generate URL)
|
20
|
+
[ ] Documentation - Inconsistency between the docs and behaviour
|
21
|
+
[ ] Other (Specify)
|
22
|
+
|
23
|
+
## Steps to reproduce
|
24
|
+
… if applicable
|
25
|
+
|
26
|
+
## Error screenshots or Stack Trace (if applicable)
|
27
|
+
…
|
28
|
+
|
29
|
+
## Operating System
|
30
|
+
[ ] Linux
|
31
|
+
[ ] Windows
|
32
|
+
[ ] OSX
|
33
|
+
[ ] All
|
34
|
+
|
35
|
+
## Environment and Libraries (fill in the version numbers)
|
36
|
+
Cloudinary Ruby SDK version - 0.0.0
|
37
|
+
Ruby Version - 0.0.0
|
38
|
+
Rails Version - 0.0.0
|
39
|
+
Other Libraries (Carrierwave, ActiveStorage, etc) - 0.0.0
|
40
|
+
|
41
|
+
## Repository
|
42
|
+
If possible, please provide a link to a reproducible repository that showcases the problem
|
@@ -0,0 +1,21 @@
|
|
1
|
+
---
|
2
|
+
name: Feature request
|
3
|
+
about: Feature request for Cloudinary Ruby SDK
|
4
|
+
title: ''
|
5
|
+
labels: ''
|
6
|
+
assignees: const-cloudinary
|
7
|
+
|
8
|
+
---
|
9
|
+
|
10
|
+
## Feature request for Cloudinary Ruby SDK
|
11
|
+
…(If your feature is for other SDKs, please request them there)
|
12
|
+
|
13
|
+
|
14
|
+
## Explain your use case
|
15
|
+
… (A high level explanation of why you need this feature)
|
16
|
+
|
17
|
+
## Describe the problem you’re trying to solve
|
18
|
+
… (A more technical view of what you’d like to accomplish, and how this feature will help you achieve it)
|
19
|
+
|
20
|
+
## Do you have a proposed solution?
|
21
|
+
… (yes, no? Please elaborate if needed)
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,63 @@
|
|
1
1
|
|
2
|
+
1.16.1 / 2020-07-06
|
3
|
+
===================
|
4
|
+
|
5
|
+
* Detect data URLs with suffix in mime type
|
6
|
+
* Fix `Invalid regular expression` error in Safari
|
7
|
+
|
8
|
+
1.16.0 / 2020-06-29
|
9
|
+
===================
|
10
|
+
|
11
|
+
New functionality and features
|
12
|
+
------------------------------
|
13
|
+
|
14
|
+
* Add support for uploading `StringIO`
|
15
|
+
|
16
|
+
Other Changes
|
17
|
+
-------------
|
18
|
+
|
19
|
+
* Set default cache storage to `file` in `CarrierWave`
|
20
|
+
* Fix `normalize_expression` to ignore predefined variables
|
21
|
+
* Fix sample projects
|
22
|
+
|
23
|
+
1.15.0 / 2020-06-11
|
24
|
+
===================
|
25
|
+
|
26
|
+
New functionality and features
|
27
|
+
------------------------------
|
28
|
+
|
29
|
+
* Add support for `accessibility_analysis` parameter
|
30
|
+
|
31
|
+
Other Changes
|
32
|
+
-------------
|
33
|
+
* Fix `download` function in `Cloudinary::CarrierWave`
|
34
|
+
* Fix handling of empty value in `if` parameter
|
35
|
+
* Fix consumption of configuration from environment variables
|
36
|
+
|
37
|
+
1.14.0 / 2020-05-06
|
38
|
+
===================
|
39
|
+
|
40
|
+
New functionality and features
|
41
|
+
------------------------------
|
42
|
+
|
43
|
+
* Add support of global folder in ActiveStorage
|
44
|
+
* Add duration to conditions in video
|
45
|
+
|
46
|
+
Other Changes
|
47
|
+
-------------
|
48
|
+
|
49
|
+
* Fix `URI.unescape is obsolete` warning
|
50
|
+
* Fix lingering Rails 6 autoload warnings
|
51
|
+
* Fix Ruby 1.9 CI build
|
52
|
+
* Allow setting uploader timeout to `nil`
|
53
|
+
* Update link to CarrierWave integration
|
54
|
+
* Update issue templates
|
55
|
+
|
56
|
+
1.13.2 / 2020-01-19
|
57
|
+
===================
|
58
|
+
|
59
|
+
* Fix asset extension detection in active storage service `url` method
|
60
|
+
|
2
61
|
1.13.1 / 2019-11-24
|
3
62
|
===================
|
4
63
|
|
data/Rakefile
CHANGED
@@ -1,55 +1,13 @@
|
|
1
1
|
require 'bundler'
|
2
2
|
require 'fileutils'
|
3
|
-
require 'tmpdir'
|
4
|
-
require 'rest_client'
|
5
|
-
require 'json'
|
6
|
-
require 'rubygems/package'
|
7
|
-
|
8
3
|
require 'rspec/core/rake_task'
|
4
|
+
|
9
5
|
RSpec::Core::RakeTask.new(:spec)
|
10
6
|
task :default => :spec
|
11
7
|
|
12
8
|
Bundler::GemHelper.install_tasks
|
13
9
|
|
14
|
-
|
15
|
-
|
16
|
-
task :fetch_assets do
|
17
|
-
index_files = %w[jquery.ui.widget.js jquery.iframe-transport.js jquery.fileupload.js jquery.cloudinary.js]
|
18
|
-
processing_files = %w[canvas-to-blob.min.js load-image.all.min.js jquery.fileupload-process.js jquery.fileupload-image.js jquery.fileupload-validate.js]
|
19
|
-
files = index_files + processing_files
|
20
|
-
|
21
|
-
release = JSON(RestClient.get("https://api.github.com/repos/cloudinary/cloudinary_js/releases/latest"))
|
22
|
-
|
23
|
-
FileUtils.rm_rf 'vendor/assets'
|
24
|
-
html_folder = 'vendor/assets/html'
|
25
|
-
FileUtils.mkdir_p html_folder
|
26
|
-
js_folder = 'vendor/assets/javascripts/cloudinary'
|
27
|
-
FileUtils.mkdir_p js_folder
|
28
|
-
|
29
|
-
puts "Fetching cloudinary_js version #{release["tag_name"]}\n\n"
|
30
|
-
sio = StringIO.new(RestClient.get(release["tarball_url"]).body)
|
31
|
-
file =Zlib::GzipReader.new(sio)
|
32
|
-
tar = Gem::Package::TarReader.new(file)
|
33
|
-
tar.each_entry do |entry|
|
34
|
-
name = File.basename(entry.full_name)
|
35
|
-
if files.include? name
|
36
|
-
js_full_name = File.join(js_folder, name)
|
37
|
-
puts "Adding #{js_full_name}"
|
38
|
-
File.write js_full_name, entry.read
|
39
|
-
elsif name == 'cloudinary_cors.html'
|
40
|
-
html_full_name = File.join(html_folder, name)
|
41
|
-
puts "Adding #{html_full_name}"
|
42
|
-
File.write html_full_name, entry.read
|
43
|
-
end
|
44
|
-
end
|
45
|
-
puts "Creating 'index.js' and 'processing.js' files"
|
46
|
-
File.open("vendor/assets/javascripts/cloudinary/index.js", "w") do |f|
|
47
|
-
index_files.each { |name| f.puts "//= require ./#{name}" }
|
48
|
-
end
|
49
|
-
File.open("vendor/assets/javascripts/cloudinary/processing.js", "w") do |f|
|
50
|
-
processing_files.each { |name| f.puts "//= require ./#{name}" }
|
51
|
-
end
|
52
|
-
end
|
10
|
+
path = File.expand_path(__dir__)
|
11
|
+
Dir.glob("#{path}/lib/tasks/**/*.rake").each { |f| import f }
|
53
12
|
|
54
|
-
end
|
55
13
|
task :build => "cloudinary:fetch_assets"
|
data/cloudinary.gemspec
CHANGED
@@ -24,11 +24,25 @@ Gem::Specification.new do |s|
|
|
24
24
|
|
25
25
|
s.add_development_dependency "actionpack"
|
26
26
|
s.add_development_dependency "nokogiri"
|
27
|
-
|
27
|
+
|
28
|
+
if RUBY_VERSION >= "2.2.0"
|
29
|
+
s.add_development_dependency "rake", ">= 13.0.1"
|
30
|
+
else
|
31
|
+
s.add_development_dependency "rake", "<= 12.2.1"
|
32
|
+
end
|
33
|
+
|
28
34
|
s.add_development_dependency "sqlite3"
|
29
35
|
s.add_development_dependency "rspec", '>=3.5'
|
30
36
|
s.add_development_dependency "rails", "~>5.2" if RUBY_VERSION >= "2.2.2"
|
37
|
+
|
38
|
+
s.add_development_dependency "railties", "<= 4.2.7" if RUBY_VERSION <= "1.9.3"
|
31
39
|
s.add_development_dependency "rspec-rails"
|
40
|
+
|
32
41
|
s.add_development_dependency "rubyzip", "<=1.2.0" # support testing Ruby 1.9
|
33
|
-
|
42
|
+
|
43
|
+
if RUBY_VERSION <= "2.4.0"
|
44
|
+
s.add_development_dependency "simplecov", "<= 0.17.1" # support testing Ruby 1.9
|
45
|
+
else
|
46
|
+
s.add_development_dependency "simplecov", "> 0.18.0"
|
47
|
+
end
|
34
48
|
end
|
@@ -12,6 +12,15 @@ unless ActiveStorage::Blob.method_defined? :original_key
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
+
module CloudinaryHelper
|
16
|
+
alias cloudinary_url_internal_original cloudinary_url_internal
|
17
|
+
|
18
|
+
def cloudinary_url_internal(source, options = {})
|
19
|
+
source = ActiveStorage::Blob.service.public_id(source) if defined? ActiveStorage::Blob.service.public_id
|
20
|
+
cloudinary_url_internal_original(source, options)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
15
24
|
module ActiveStorage
|
16
25
|
class Service::CloudinaryService < Service
|
17
26
|
module Headers
|
@@ -31,7 +40,7 @@ module ActiveStorage
|
|
31
40
|
options = @options.merge(options)
|
32
41
|
Cloudinary::Uploader.upload(
|
33
42
|
io,
|
34
|
-
public_id:
|
43
|
+
public_id: public_id_internal(key),
|
35
44
|
resource_type: resource_type(io, key),
|
36
45
|
context: {active_storage_key: key, checksum: checksum},
|
37
46
|
extra_headers: extra_headers,
|
@@ -48,9 +57,10 @@ module ActiveStorage
|
|
48
57
|
url = Cloudinary::Utils.cloudinary_url(
|
49
58
|
public_id(key),
|
50
59
|
resource_type: resource_type(nil, key),
|
51
|
-
format:
|
60
|
+
format: ext_for_file(filename, content_type),
|
52
61
|
**@options.merge(options.symbolize_keys)
|
53
62
|
)
|
63
|
+
|
54
64
|
payload[:url] = url
|
55
65
|
|
56
66
|
url
|
@@ -60,7 +70,7 @@ module ActiveStorage
|
|
60
70
|
def url_for_direct_upload(key, **options)
|
61
71
|
instrument :url, key: key do |payload|
|
62
72
|
options = {:resource_type => resource_type(nil, key)}.merge(@options.merge(options.symbolize_keys))
|
63
|
-
options[:public_id] =
|
73
|
+
options[:public_id] = public_id_internal(key)
|
64
74
|
options[:context] = {active_storage_key: key}
|
65
75
|
options.delete(:file)
|
66
76
|
payload[:url] = api_uri("upload", options)
|
@@ -136,20 +146,41 @@ module ActiveStorage
|
|
136
146
|
|
137
147
|
end
|
138
148
|
|
149
|
+
def public_id(key)
|
150
|
+
return key unless @options[:folder]
|
151
|
+
|
152
|
+
File.join(@options.fetch(:folder), public_id_internal(key))
|
153
|
+
end
|
154
|
+
|
139
155
|
private
|
140
156
|
|
141
157
|
def api_uri(action, options)
|
142
158
|
base_url = Cloudinary::Utils.cloudinary_api_url(action, options)
|
143
159
|
upload_params = Cloudinary::Uploader.build_upload_params(options)
|
144
160
|
|
145
|
-
upload_params.reject! {|k, v| Cloudinary::Utils.safe_blank?(v)}
|
161
|
+
upload_params.reject! { |k, v| Cloudinary::Utils.safe_blank?(v) }
|
146
162
|
unless options[:unsigned]
|
147
163
|
upload_params = Cloudinary::Utils.sign_request(upload_params, options)
|
148
164
|
end
|
149
165
|
"#{base_url}?#{upload_params.to_query}"
|
150
166
|
end
|
151
167
|
|
152
|
-
|
168
|
+
# Helper method for getting the filename extension.
|
169
|
+
#
|
170
|
+
# It does the best effort when original filename does not include extension, but we know the mime-type.
|
171
|
+
#
|
172
|
+
# @param [ActiveStorage::Filename] filename The original filename.
|
173
|
+
# @param [string] content_type The content type of the file.
|
174
|
+
#
|
175
|
+
# @return [string] The extension of the filename.
|
176
|
+
def ext_for_file(filename, content_type)
|
177
|
+
ext = filename.respond_to?(:extension_without_delimiter) ? filename.extension_without_delimiter : nil
|
178
|
+
return ext unless ext.blank?
|
179
|
+
|
180
|
+
# Raw files are not convertible, no extension guessing for them
|
181
|
+
return nil if content_type_to_resource_type(content_type).eql?('raw')
|
182
|
+
|
183
|
+
# Fallback when there is no extension.
|
153
184
|
@formats ||= Hash.new do |h, key|
|
154
185
|
ext = Rack::Mime::MIME_TYPES.invert[key]
|
155
186
|
h[key] = ext.slice(1..-1) unless ext.nil?
|
@@ -157,14 +188,12 @@ module ActiveStorage
|
|
157
188
|
@formats[content_type]
|
158
189
|
end
|
159
190
|
|
160
|
-
def
|
191
|
+
def public_id_internal(key)
|
161
192
|
# TODO: Allow custom manipulation of key to obscure how we store in Cloudinary
|
162
193
|
key
|
163
194
|
end
|
164
195
|
|
165
|
-
def
|
166
|
-
options = key.respond_to?(:attributes) ? key.attributes : {}
|
167
|
-
content_type = options[:content_type] || (io.nil? ? '' : Marcel::MimeType.for(io))
|
196
|
+
def content_type_to_resource_type(content_type)
|
168
197
|
type, subtype = content_type.split('/')
|
169
198
|
case type
|
170
199
|
when 'video', 'audio'
|
@@ -184,5 +213,11 @@ module ActiveStorage
|
|
184
213
|
'image'
|
185
214
|
end
|
186
215
|
end
|
216
|
+
|
217
|
+
def resource_type(io, key = "")
|
218
|
+
options = key.respond_to?(:attributes) ? key.attributes : {}
|
219
|
+
content_type = options[:content_type] || (io.nil? ? '' : Marcel::MimeType.for(io))
|
220
|
+
content_type_to_resource_type(content_type)
|
221
|
+
end
|
187
222
|
end
|
188
223
|
end
|
data/lib/cloudinary.rb
CHANGED
@@ -64,19 +64,7 @@ module Cloudinary
|
|
64
64
|
first_time = @@config.nil?
|
65
65
|
@@config ||= OpenStruct.new((YAML.load(ERB.new(IO.read(config_dir.join("cloudinary.yml"))).result)[config_env] rescue {}))
|
66
66
|
|
67
|
-
|
68
|
-
if first_time && ENV["CLOUDINARY_CLOUD_NAME"]
|
69
|
-
set_config(
|
70
|
-
"cloud_name" => ENV["CLOUDINARY_CLOUD_NAME"],
|
71
|
-
"api_key" => ENV["CLOUDINARY_API_KEY"],
|
72
|
-
"api_secret" => ENV["CLOUDINARY_API_SECRET"],
|
73
|
-
"secure_distribution" => ENV["CLOUDINARY_SECURE_DISTRIBUTION"],
|
74
|
-
"private_cdn" => ENV["CLOUDINARY_PRIVATE_CDN"].to_s == 'true',
|
75
|
-
"secure" => ENV["CLOUDINARY_SECURE"].to_s == 'true'
|
76
|
-
)
|
77
|
-
elsif first_time && ENV["CLOUDINARY_URL"]
|
78
|
-
config_from_url(ENV["CLOUDINARY_URL"])
|
79
|
-
end
|
67
|
+
config_from_env if first_time
|
80
68
|
|
81
69
|
set_config(new_config) if new_config
|
82
70
|
yield(@@config) if block_given?
|
@@ -105,7 +93,7 @@ module Cloudinary
|
|
105
93
|
if isNestedKey? key
|
106
94
|
putNestedKey key, value
|
107
95
|
else
|
108
|
-
set_config(key =>
|
96
|
+
set_config(key => Utils.smart_unescape(value))
|
109
97
|
end
|
110
98
|
end
|
111
99
|
end
|
@@ -140,18 +128,34 @@ module Cloudinary
|
|
140
128
|
end
|
141
129
|
|
142
130
|
private
|
143
|
-
|
131
|
+
|
132
|
+
def self.config_from_env
|
133
|
+
# Heroku support
|
134
|
+
if ENV["CLOUDINARY_CLOUD_NAME"]
|
135
|
+
config_keys = ENV.keys.select! { |key| key.start_with? "CLOUDINARY_" }
|
136
|
+
config_keys -= ["CLOUDINARY_URL"] # ignore it when explicit options are passed
|
137
|
+
config_keys.each do |full_key|
|
138
|
+
conf_key = full_key["CLOUDINARY_".length..-1].downcase # convert "CLOUDINARY_CONFIG_NAME" to "config_name"
|
139
|
+
conf_val = ENV[full_key]
|
140
|
+
conf_val = conf_val == 'true' if %w[true false].include?(conf_val) # cast relevant boolean values
|
141
|
+
set_config(conf_key => conf_val)
|
142
|
+
end
|
143
|
+
elsif ENV["CLOUDINARY_URL"]
|
144
|
+
config_from_url(ENV["CLOUDINARY_URL"])
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
144
148
|
def self.config_env
|
145
149
|
return ENV["CLOUDINARY_ENV"] if ENV["CLOUDINARY_ENV"]
|
146
150
|
return Rails.env if defined? Rails::env
|
147
151
|
nil
|
148
152
|
end
|
149
|
-
|
153
|
+
|
150
154
|
def self.config_dir
|
151
|
-
return Pathname.new(ENV["CLOUDINARY_CONFIG_DIR"]) if ENV["CLOUDINARY_CONFIG_DIR"]
|
155
|
+
return Pathname.new(ENV["CLOUDINARY_CONFIG_DIR"]) if ENV["CLOUDINARY_CONFIG_DIR"]
|
152
156
|
self.app_root.join("config")
|
153
157
|
end
|
154
|
-
|
158
|
+
|
155
159
|
def self.set_config(new_config)
|
156
160
|
new_config.each{|k,v| @@config.send(:"#{k}=", v) if !v.nil?}
|
157
161
|
end
|
data/lib/cloudinary/api.rb
CHANGED
@@ -78,7 +78,7 @@ class Cloudinary::Api
|
|
78
78
|
resource_type = options[:resource_type] || "image"
|
79
79
|
type = options[:type] || "upload"
|
80
80
|
uri = "resources/#{resource_type}/#{type}/#{public_id}"
|
81
|
-
call_api(:get, uri,
|
81
|
+
call_api(:get, uri,
|
82
82
|
only(options,
|
83
83
|
:cinemagraph_analysis,
|
84
84
|
:colors,
|
@@ -90,7 +90,8 @@ class Cloudinary::Api
|
|
90
90
|
:pages,
|
91
91
|
:phash,
|
92
92
|
:quality_analysis,
|
93
|
-
:derived_next_cursor
|
93
|
+
:derived_next_cursor,
|
94
|
+
:accessibility_analysis
|
94
95
|
), options)
|
95
96
|
end
|
96
97
|
|
@@ -9,6 +9,7 @@ module Cloudinary::CarrierWave
|
|
9
9
|
|
10
10
|
def self.included(base)
|
11
11
|
base.storage Cloudinary::CarrierWave::Storage
|
12
|
+
base.cache_storage = :file if base.cache_storage.blank?
|
12
13
|
base.extend ClassMethods
|
13
14
|
base.class_attribute :metadata
|
14
15
|
base.class_attribute :storage_type, instance_reader: false
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module Cloudinary::CarrierWave
|
2
2
|
def download!(uri, *args)
|
3
|
-
return super
|
3
|
+
return super unless self.cloudinary_should_handle_remote?
|
4
4
|
if respond_to?(:process_uri)
|
5
5
|
uri = process_uri(uri)
|
6
6
|
else # Backward compatibility with old CarrierWave
|
7
|
-
uri = URI.parse(
|
7
|
+
uri = URI.parse(Cloudinary::Utils.smart_escape(Cloudinary::Utils.smart_unescape(uri)))
|
8
8
|
end
|
9
9
|
return if uri.to_s.blank?
|
10
10
|
self.original_filename = @cache_id = @filename = File.basename(uri.path).gsub(/[^a-zA-Z0-9\.\-\+_]/, '')
|
@@ -1,7 +1,8 @@
|
|
1
1
|
class Cloudinary::CarrierWave::Storage < ::CarrierWave::Storage::Abstract
|
2
2
|
|
3
3
|
def store!(file)
|
4
|
-
return
|
4
|
+
return unless uploader.enable_processing
|
5
|
+
|
5
6
|
if uploader.is_main_uploader?
|
6
7
|
case file
|
7
8
|
when Cloudinary::CarrierWave::PreloadedCloudinaryFile
|
@@ -1,13 +1,11 @@
|
|
1
1
|
module Cloudinary::CloudinaryController
|
2
2
|
protected
|
3
|
-
|
3
|
+
|
4
4
|
def valid_cloudinary_response?
|
5
5
|
received_signature = request.query_parameters[:signature]
|
6
6
|
calculated_signature = Cloudinary::Utils.api_sign_request(
|
7
7
|
request.query_parameters.select{|key, value| [:public_id, :version].include?(key.to_sym)},
|
8
8
|
Cloudinary.config.api_secret)
|
9
9
|
return received_signature == calculated_signature
|
10
|
-
end
|
10
|
+
end
|
11
11
|
end
|
12
|
-
|
13
|
-
ActionController::Base.send :include, Cloudinary::CloudinaryController
|
data/lib/cloudinary/railtie.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
class Cloudinary::Railtie < Rails::Railtie
|
2
2
|
rake_tasks do
|
3
|
-
Dir[File.join(File.dirname(__FILE__),'../tasks
|
4
|
-
end
|
3
|
+
Dir[File.join(File.dirname(__FILE__),'../tasks/**/*.rake')].each { |f| load f }
|
4
|
+
end
|
5
5
|
config.after_initialize do |app|
|
6
6
|
ActionView::Base.send :include, CloudinaryHelper
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
|
+
ActiveSupport.on_load(:action_controller_base) do
|
10
|
+
ActionController::Base.send :include, Cloudinary::CloudinaryController
|
11
|
+
end
|
12
|
+
end
|
data/lib/cloudinary/uploader.rb
CHANGED
@@ -64,6 +64,7 @@ class Cloudinary::Uploader
|
|
64
64
|
:unique_filename => Cloudinary::Utils.as_safe_bool(options[:unique_filename]),
|
65
65
|
:upload_preset => options[:upload_preset],
|
66
66
|
:use_filename => Cloudinary::Utils.as_safe_bool(options[:use_filename]),
|
67
|
+
:accessibility_analysis => Cloudinary::Utils.as_safe_bool(options[:accessibility_analysis])
|
67
68
|
}
|
68
69
|
params
|
69
70
|
end
|
@@ -77,6 +78,9 @@ class Cloudinary::Uploader
|
|
77
78
|
params = build_upload_params(options)
|
78
79
|
if file.is_a?(Pathname)
|
79
80
|
params[:file] = File.open(file, "rb")
|
81
|
+
elsif file.is_a?(StringIO)
|
82
|
+
file.rewind
|
83
|
+
params[:file] = Cloudinary::Blob.new(file.read, options)
|
80
84
|
elsif file.respond_to?(:read) || Cloudinary::Utils.is_remote?(file)
|
81
85
|
params[:file] = file
|
82
86
|
else
|
@@ -248,7 +252,7 @@ class Cloudinary::Uploader
|
|
248
252
|
end
|
249
253
|
end
|
250
254
|
|
251
|
-
# options may include 'exclusive' (boolean) which causes clearing this tag from all other resources
|
255
|
+
# options may include 'exclusive' (boolean) which causes clearing this tag from all other resources
|
252
256
|
def self.add_tag(tag, public_ids = [], options = {})
|
253
257
|
exclusive = options.delete(:exclusive)
|
254
258
|
command = exclusive ? "set_exclusive" : "add"
|
@@ -317,7 +321,7 @@ class Cloudinary::Uploader
|
|
317
321
|
params[:signature] = Cloudinary::Utils.api_sign_request(params.reject { |k, v| non_signable.include?(k) }, api_secret)
|
318
322
|
params[:api_key] = api_key
|
319
323
|
end
|
320
|
-
timeout = options
|
324
|
+
timeout = options.fetch(:timeout) { Cloudinary.config.to_h.fetch(:timeout, 60) }
|
321
325
|
|
322
326
|
result = nil
|
323
327
|
|
data/lib/cloudinary/utils.rb
CHANGED
@@ -42,6 +42,8 @@ class Cloudinary::Utils
|
|
42
42
|
"page_x" => "px",
|
43
43
|
"page_y" => "py",
|
44
44
|
"tags" => "tags",
|
45
|
+
"initial_duration" => "idu",
|
46
|
+
"duration" => "du",
|
45
47
|
"width" => "w"
|
46
48
|
}
|
47
49
|
|
@@ -137,7 +139,7 @@ class Cloudinary::Utils
|
|
137
139
|
zoom
|
138
140
|
].map(&:to_sym)
|
139
141
|
|
140
|
-
REMOTE_URL_REGEX = %r(^ftp:|^https?:|^s3:|^gs:|^data:([\w-]+\/[\w-]+)?(;[\w-]+=[\w-]+)*;base64,([a-zA-Z0-9\/+\n=]+)$)
|
142
|
+
REMOTE_URL_REGEX = %r(^ftp:|^https?:|^s3:|^gs:|^data:([\w-]+\/[\w-]+(\+[\w-]+)?)?(;[\w-]+=[\w-]+)*;base64,([a-zA-Z0-9\/+\n=]+)$)
|
141
143
|
|
142
144
|
def self.extract_config_params(options)
|
143
145
|
options.select{|k,v| URL_KEYS.include?(k)}
|
@@ -300,15 +302,11 @@ class Cloudinary::Utils
|
|
300
302
|
# Translates the condition if provided.
|
301
303
|
# @return [string] "if_" + ifValue
|
302
304
|
# @private
|
303
|
-
def self.process_if(
|
304
|
-
|
305
|
-
ifValue = normalize_expression(ifValue)
|
306
|
-
|
307
|
-
ifValue = "if_" + ifValue
|
308
|
-
end
|
305
|
+
def self.process_if(if_value)
|
306
|
+
"if_" + normalize_expression(if_value) unless if_value.to_s.empty?
|
309
307
|
end
|
310
308
|
|
311
|
-
EXP_REGEXP = Regexp.new(PREDEFINED_VARS.keys.join("|")+'|('+CONDITIONAL_OPERATORS.keys.reverse.map { |k| Regexp.escape(k) }.join('|')+')(?=[ _])')
|
309
|
+
EXP_REGEXP = Regexp.new('(?<!\$)('+PREDEFINED_VARS.keys.join("|")+')'+'|('+CONDITIONAL_OPERATORS.keys.reverse.map { |k| Regexp.escape(k) }.join('|')+')(?=[ _])')
|
312
310
|
EXP_REPLACEMENT = PREDEFINED_VARS.merge(CONDITIONAL_OPERATORS)
|
313
311
|
|
314
312
|
def self.normalize_expression(expression)
|
@@ -563,7 +561,7 @@ class Cloudinary::Utils
|
|
563
561
|
source = smart_escape(source)
|
564
562
|
source_to_sign = source
|
565
563
|
else
|
566
|
-
source = smart_escape(
|
564
|
+
source = smart_escape(smart_unescape(source))
|
567
565
|
source_to_sign = source
|
568
566
|
unless url_suffix.blank?
|
569
567
|
raise(CloudinaryException, "url_suffix should not include . or /") if url_suffix.match(%r([\./]))
|
@@ -767,13 +765,18 @@ class Cloudinary::Utils
|
|
767
765
|
"#{public_id}#{ext}"
|
768
766
|
end
|
769
767
|
|
770
|
-
# Based on CGI::
|
768
|
+
# Based on CGI::escape. In addition does not escape / :
|
771
769
|
def self.smart_escape(string, unsafe = /([^a-zA-Z0-9_.\-\/:]+)/)
|
772
770
|
string.gsub(unsafe) do |m|
|
773
771
|
'%' + m.unpack('H2' * m.bytesize).join('%').upcase
|
774
772
|
end
|
775
773
|
end
|
776
774
|
|
775
|
+
# Based on CGI::unescape. In addition keeps '+' character as is
|
776
|
+
def self.smart_unescape(string)
|
777
|
+
CGI.unescape(string.sub('+', '%2B'))
|
778
|
+
end
|
779
|
+
|
777
780
|
def self.random_public_id
|
778
781
|
sr = defined?(ActiveSupport::SecureRandom) ? ActiveSupport::SecureRandom : SecureRandom
|
779
782
|
sr.base64(20).downcase.gsub(/[^a-z0-9]/, "").sub(/^[0-9]+/, '')[0,20]
|
data/lib/cloudinary/version.rb
CHANGED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
require 'rest_client'
|
3
|
+
require 'json'
|
4
|
+
require 'rubygems/package'
|
5
|
+
|
6
|
+
unless Rake::Task.task_defined?('cloudinary:fetch_assets') # prevent double-loading/execution
|
7
|
+
namespace :cloudinary do
|
8
|
+
desc "Fetch the latest JavaScript library files and create the JavaScript index files"
|
9
|
+
task :fetch_assets do
|
10
|
+
index_files = %w[jquery.ui.widget.js jquery.iframe-transport.js jquery.fileupload.js jquery.cloudinary.js]
|
11
|
+
processing_files = %w[canvas-to-blob.min.js load-image.all.min.js jquery.fileupload-process.js jquery.fileupload-image.js jquery.fileupload-validate.js]
|
12
|
+
files = index_files + processing_files
|
13
|
+
|
14
|
+
release = JSON(RestClient.get("https://api.github.com/repos/cloudinary/cloudinary_js/releases/latest"))
|
15
|
+
|
16
|
+
FileUtils.rm_rf 'vendor/assets'
|
17
|
+
html_folder = 'vendor/assets/html'
|
18
|
+
FileUtils.mkdir_p html_folder
|
19
|
+
js_folder = 'vendor/assets/javascripts/cloudinary'
|
20
|
+
FileUtils.mkdir_p js_folder
|
21
|
+
|
22
|
+
puts "Fetching cloudinary_js version #{release["tag_name"]}\n\n"
|
23
|
+
sio = StringIO.new(RestClient.get(release["tarball_url"]).body)
|
24
|
+
file = Zlib::GzipReader.new(sio)
|
25
|
+
tar = Gem::Package::TarReader.new(file)
|
26
|
+
tar.each_entry do |entry|
|
27
|
+
name = File.basename(entry.full_name)
|
28
|
+
if files.include? name
|
29
|
+
js_full_name = File.join(js_folder, name)
|
30
|
+
puts "Adding #{js_full_name}"
|
31
|
+
File.write js_full_name, entry.read
|
32
|
+
elsif name == 'cloudinary_cors.html'
|
33
|
+
html_full_name = File.join(html_folder, name)
|
34
|
+
puts "Adding #{html_full_name}"
|
35
|
+
File.write html_full_name, entry.read
|
36
|
+
end
|
37
|
+
end
|
38
|
+
puts "Creating 'index.js' and 'processing.js' files"
|
39
|
+
File.open("vendor/assets/javascripts/cloudinary/index.js", "w") do |f|
|
40
|
+
index_files.each { |name| f.puts "//= require ./#{name}" }
|
41
|
+
end
|
42
|
+
File.open("vendor/assets/javascripts/cloudinary/processing.js", "w") do |f|
|
43
|
+
processing_files.each { |name| f.puts "//= require ./#{name}" }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
File without changes
|
@@ -164,7 +164,7 @@ var slice = [].slice,
|
|
164
164
|
* @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
|
165
165
|
* @example
|
166
166
|
*
|
167
|
-
* function Foo(){};
|
167
|
+
* function Foo(){};
|
168
168
|
* isFunction(Foo);
|
169
169
|
* // => true
|
170
170
|
*
|
@@ -1403,7 +1403,8 @@ var slice = [].slice,
|
|
1403
1403
|
"*": "mul",
|
1404
1404
|
"/": "div",
|
1405
1405
|
"+": "add",
|
1406
|
-
"-": "sub"
|
1406
|
+
"-": "sub",
|
1407
|
+
"^": "pow",
|
1407
1408
|
};
|
1408
1409
|
|
1409
1410
|
|
@@ -1472,30 +1473,33 @@ var slice = [].slice,
|
|
1472
1473
|
return new this(expressionStr);
|
1473
1474
|
};
|
1474
1475
|
|
1475
|
-
|
1476
1476
|
/**
|
1477
1477
|
* Normalize a string expression
|
1478
1478
|
* @function Cloudinary#normalize
|
1479
1479
|
* @param {string} expression a expression, e.g. "w gt 100", "width_gt_100", "width > 100"
|
1480
1480
|
* @return {string} the normalized form of the value expression, e.g. "w_gt_100"
|
1481
1481
|
*/
|
1482
|
-
|
1483
1482
|
Expression.normalize = function(expression) {
|
1484
|
-
var operators,
|
1483
|
+
var operators, operatorsPattern, operatorsReplaceRE, predefinedVarsPattern, predefinedVarsReplaceRE;
|
1485
1484
|
if (expression == null) {
|
1486
1485
|
return expression;
|
1487
1486
|
}
|
1488
1487
|
expression = String(expression);
|
1489
|
-
operators = "
|
1490
|
-
|
1491
|
-
|
1492
|
-
|
1493
|
-
|
1494
|
-
|
1488
|
+
operators = "\\|\\||>=|<=|&&|!=|>|=|<|/|-|\\+|\\*|\\^";
|
1489
|
+
|
1490
|
+
// operators
|
1491
|
+
operatorsPattern = "((" + operators + ")(?=[ _]))";
|
1492
|
+
operatorsReplaceRE = new RegExp(operatorsPattern, "g");
|
1493
|
+
expression = expression.replace(operatorsReplaceRE, match => Expression.OPERATORS[match]);
|
1494
|
+
|
1495
|
+
// predefined variables
|
1496
|
+
predefinedVarsPattern = "(" + Object.keys(Expression.PREDEFINED_VARS).join("|") + ")";
|
1497
|
+
predefinedVarsReplaceRE = new RegExp(predefinedVarsPattern, "g");
|
1498
|
+
expression = expression.replace(predefinedVarsReplaceRE, (match, p1, offset) => (expression[offset - 1] === '$' ? match : Expression.PREDEFINED_VARS[match]));
|
1499
|
+
|
1495
1500
|
return expression.replace(/[ _]+/g, '_');
|
1496
1501
|
};
|
1497
1502
|
|
1498
|
-
|
1499
1503
|
/**
|
1500
1504
|
* Serialize the expression
|
1501
1505
|
* @return {string} the expression as a string
|
@@ -3070,7 +3074,7 @@ var slice = [].slice,
|
|
3070
3074
|
* @protected
|
3071
3075
|
* @param {string} key - attribute name
|
3072
3076
|
* @param {*|boolean} value - the value of the attribute. If the value is boolean `true`, return the key only.
|
3073
|
-
* @returns {string} the attribute
|
3077
|
+
* @returns {string} the attribute
|
3074
3078
|
*
|
3075
3079
|
*/
|
3076
3080
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloudinary
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.16.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nadav Soferman
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2020-07-06 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: aws_cf_signer
|
@@ -74,14 +74,14 @@ dependencies:
|
|
74
74
|
requirements:
|
75
75
|
- - ">="
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version:
|
77
|
+
version: 13.0.1
|
78
78
|
type: :development
|
79
79
|
prerelease: false
|
80
80
|
version_requirements: !ruby/object:Gem::Requirement
|
81
81
|
requirements:
|
82
82
|
- - ">="
|
83
83
|
- !ruby/object:Gem::Version
|
84
|
-
version:
|
84
|
+
version: 13.0.1
|
85
85
|
- !ruby/object:Gem::Dependency
|
86
86
|
name: sqlite3
|
87
87
|
requirement: !ruby/object:Gem::Requirement
|
@@ -156,16 +156,16 @@ dependencies:
|
|
156
156
|
name: simplecov
|
157
157
|
requirement: !ruby/object:Gem::Requirement
|
158
158
|
requirements:
|
159
|
-
- - "
|
159
|
+
- - ">"
|
160
160
|
- !ruby/object:Gem::Version
|
161
|
-
version:
|
161
|
+
version: 0.18.0
|
162
162
|
type: :development
|
163
163
|
prerelease: false
|
164
164
|
version_requirements: !ruby/object:Gem::Requirement
|
165
165
|
requirements:
|
166
|
-
- - "
|
166
|
+
- - ">"
|
167
167
|
- !ruby/object:Gem::Version
|
168
|
-
version:
|
168
|
+
version: 0.18.0
|
169
169
|
description: Client library for easily using the Cloudinary service
|
170
170
|
email:
|
171
171
|
- nadav.soferman@cloudinary.com
|
@@ -175,6 +175,8 @@ executables: []
|
|
175
175
|
extensions: []
|
176
176
|
extra_rdoc_files: []
|
177
177
|
files:
|
178
|
+
- ".github/ISSUE_TEMPLATE/bug_report.md"
|
179
|
+
- ".github/ISSUE_TEMPLATE/feature_request.md"
|
178
180
|
- ".gitignore"
|
179
181
|
- ".rspec"
|
180
182
|
- ".travis.yml"
|
@@ -218,7 +220,8 @@ files:
|
|
218
220
|
- lib/cloudinary/utils.rb
|
219
221
|
- lib/cloudinary/version.rb
|
220
222
|
- lib/cloudinary/video_helper.rb
|
221
|
-
- lib/tasks/cloudinary.rake
|
223
|
+
- lib/tasks/cloudinary/fetch_assets.rake
|
224
|
+
- lib/tasks/cloudinary/sync_static.rake
|
222
225
|
- tools/update_version
|
223
226
|
- vendor/assets/html/cloudinary_cors.html
|
224
227
|
- vendor/assets/javascripts/cloudinary/canvas-to-blob.min.js
|