cloudinary 1.5.2 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- M2E1MWI3ZmRiNDA2YWE2ZTA0OTYzZDUyZmIxMmNjYWJhMjFhNzVmNA==
5
- data.tar.gz: !binary |-
6
- NjUzMWYwOGVkNTU0ZmE3ZDIyZjJjNzM1MGE5YWM4ZWRhYWY2OGQyYg==
2
+ SHA1:
3
+ metadata.gz: 36330c17f742e019c7770d39fe11a5e394d69acc
4
+ data.tar.gz: 511246947d366e91a8d34095f256437bde533f9e
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- NDFjMjgyNTE1MTkxODkxZjcyN2VmOGU3ODZiMWU2NjAyMWNiODc2YjJiMGMz
10
- YzkxOTYyZjRkOTU4MmM2MGMxNThmMDQ3NThiMWUxOTFmZGE0OTBkNjJkYTlk
11
- ZWI1MDdhOGVjMzUyZmE2NzMzMWQ3M2U0MTFmZWY5NmYxNDJjNWY=
12
- data.tar.gz: !binary |-
13
- ZDEzODU4YWJhOGExNmQxZjY2NGI5OTZkMjk1NmFiMGY1YWFiZTdkODcwZWIw
14
- MmM5NGQ5OWIzZGJmNjBhZmE1OGViZmFhZGMzOGJmNTU4M2M2ZTAzM2FkNTlk
15
- ZDMxNDA1MDNmOGE4ODk5M2Y5MDkyZDRhOTI4NTNlOGVhYmRjZWI=
6
+ metadata.gz: 4fcbb47f1760342d5e1b36e0438a605524eb20b9f0fac98521846f71102447ce6dda1ebb3f435e43d6227320bb48a65c85f5ae44da20b0c4fcb1539f7d78232a
7
+ data.tar.gz: 190f0970236cb76615d6537276fdd3633297e4c749815a6c54ae985188bee5e493d778a55c60798ac3ebaf9cb14930eb2b3589f45914c69cc489d378d5b19970
@@ -1,4 +1,20 @@
1
1
 
2
+ 1.6.0 / 2017-03-08
3
+ ==================
4
+
5
+ New functionality and features
6
+ ------------------------------
7
+
8
+ * Support user defined variables
9
+ * Add `to_type` parameter to the rename method (#236)
10
+ * Add `async` parameter to the upload method (#235)
11
+
12
+ Other Changes
13
+ -------------
14
+
15
+ * Switch ow & oh to iw & ih on respective test case
16
+ * test auto gravity transformation in URL build
17
+
2
18
  1.5.2 / 2017-02-22
3
19
  ==================
4
20
 
@@ -18,6 +18,7 @@ class Cloudinary::Uploader
18
18
  params = {
19
19
  :access_mode => options[:access_mode],
20
20
  :allowed_formats => Cloudinary::Utils.build_array(options[:allowed_formats]).join(","),
21
+ :async => Cloudinary::Utils.as_safe_bool(options[:async]),
21
22
  :auto_tagging => options[:auto_tagging] && options[:auto_tagging].to_f,
22
23
  :background_removal => options[:background_removal],
23
24
  :backup => Cloudinary::Utils.as_safe_bool(options[:backup]),
@@ -142,6 +143,7 @@ class Cloudinary::Uploader
142
143
  :overwrite => Cloudinary::Utils.as_safe_bool(options[:overwrite]),
143
144
  :from_public_id => from_public_id,
144
145
  :to_public_id => to_public_id,
146
+ :to_type => options[:to_type],
145
147
  :invalidate => Cloudinary::Utils.as_safe_bool(options[:invalidate])
146
148
  }
147
149
  end
@@ -19,15 +19,26 @@ class Cloudinary::Utils
19
19
  "<=" => 'lte',
20
20
  ">=" => 'gte',
21
21
  "&&" => 'and',
22
- "||" => 'or'
22
+ "||" => 'or',
23
+ "*" => 'mul',
24
+ "/" => 'div',
25
+ "+" => 'add',
26
+ "-" => 'sub'
23
27
  }
24
28
 
25
- CONDITIONAL_PARAMETERS = {
26
- "width" => "w",
27
- "height" => "h",
28
- "aspect_ratio" => "ar",
29
- "page_count" => "pc",
30
- "face_count" => "fc"
29
+ PREDEFINED_VARS = {
30
+ "aspect_ratio" => "ar",
31
+ "current_page" => "cp",
32
+ "face_count" => "fc",
33
+ "height" => "h",
34
+ "initial_aspect_ratio" => "iar",
35
+ "initial_height" => "ih",
36
+ "initial_width" => "iw",
37
+ "page_count" => "pc",
38
+ "page_x" => "px",
39
+ "page_y" => "py",
40
+ "tags" => "tags",
41
+ "width" => "w"
31
42
  }
32
43
  # Warning: options are being destructively updated!
33
44
  def self.generate_transformation_string(options={}, allow_implicit_crop_mode = false)
@@ -96,24 +107,30 @@ class Cloudinary::Utils
96
107
  ifValue = process_if(options.delete(:if))
97
108
 
98
109
  params = {
99
- :a => angle,
110
+ :a => normalize_expression(angle),
111
+ :ar => normalize_expression(options.delete(:aspect_ratio)),
100
112
  :b => background,
101
113
  :bo => border,
102
114
  :c => crop,
103
115
  :co => color,
104
- :dpr => dpr,
105
- :e => effect,
116
+ :dpr => normalize_expression(dpr),
117
+ :e => normalize_expression(effect),
106
118
  :fl => flags,
107
- :h => height,
119
+ :h => normalize_expression(height),
108
120
  :l => overlay,
121
+ :o => normalize_expression(options.delete(:opacity)),
122
+ :q => normalize_expression(options.delete(:quality)),
123
+ :r => normalize_expression(options.delete(:radius)),
109
124
  :t => named_transformation,
110
125
  :u => underlay,
111
- :w => width
126
+ :w => normalize_expression(width),
127
+ :x => normalize_expression(options.delete(:x)),
128
+ :y => normalize_expression(options.delete(:y)),
129
+ :z => normalize_expression(options.delete(:zoom))
112
130
  }
113
131
  {
114
132
  :ac => :audio_codec,
115
133
  :af => :audio_frequency,
116
- :ar => :aspect_ratio,
117
134
  :br => :bit_rate,
118
135
  :cs => :color_space,
119
136
  :d => :default_image,
@@ -124,18 +141,12 @@ class Cloudinary::Utils
124
141
  :f => :fetch_format,
125
142
  :g => :gravity,
126
143
  :ki => :keyframe_interval,
127
- :o => :opacity,
128
144
  :p => :prefix,
129
145
  :pg => :page,
130
- :q => :quality,
131
- :r => :radius,
132
146
  :so => :start_offset,
133
147
  :sp => :streaming_profile,
134
148
  :vc => :video_codec,
135
- :vs => :video_sampling,
136
- :x => :x,
137
- :y => :y,
138
- :z => :zoom
149
+ :vs => :video_sampling
139
150
  }.each do
140
151
  |param, option|
141
152
  params[param] = options.delete(option)
@@ -146,10 +157,25 @@ class Cloudinary::Utils
146
157
  params[range_value] = norm_range_value params[range_value] if params[range_value].present?
147
158
  end
148
159
 
160
+ variables = options.delete(:variables)
161
+ var_params = []
162
+ options.each_pair do |key, value|
163
+ if key =~ /^\$/
164
+ var_params.push "#{key}_#{normalize_expression(value.to_s)}"
165
+ end
166
+ end
167
+ var_params.sort!
168
+ unless variables.nil? || variables.empty?
169
+ for name, value in variables
170
+ var_params.push "#{name}_#{normalize_expression(value.to_s)}"
171
+ end
172
+ end
173
+ variables = var_params.join(',')
174
+
149
175
  raw_transformation = options.delete(:raw_transformation)
150
176
  transformation = params.reject{|_k,v| v.blank?}.map{|k,v| "#{k}_#{v}"}.sort
151
177
  transformation = transformation.join(",")
152
- transformation = [ifValue, transformation, raw_transformation].reject(&:blank?).join(",")
178
+ transformation = [ifValue, variables, transformation, raw_transformation].reject(&:blank?).join(",")
153
179
 
154
180
  transformations = base_transformations << transformation
155
181
  if responsive_width
@@ -173,15 +199,23 @@ class Cloudinary::Utils
173
199
  # @private
174
200
  def self.process_if(ifValue)
175
201
  if ifValue
176
- ifValue = ifValue.gsub(
177
- /(#{CONDITIONAL_PARAMETERS.keys.join("|")}|[=<>&|!]+)/,
178
- CONDITIONAL_PARAMETERS.merge(CONDITIONAL_OPERATORS))
179
- .gsub(/[ _]+/, "_")
202
+ ifValue = normalize_expression(ifValue)
180
203
 
181
204
  ifValue = "if_" + ifValue
182
205
  end
183
206
  end
184
207
 
208
+ def self.normalize_expression(expression)
209
+ if expression =~ /^!.+!$/ # quoted string
210
+ expression
211
+ else
212
+ expression.to_s.gsub(
213
+ Regexp.union(*PREDEFINED_VARS.keys, *CONDITIONAL_OPERATORS.keys.reverse),
214
+ PREDEFINED_VARS.merge(CONDITIONAL_OPERATORS)
215
+ ).gsub(/[ _]+/, "_")
216
+ end
217
+ end
218
+
185
219
  # Parse layer options
186
220
  # @return [string] layer transformation string
187
221
  # @private
@@ -218,8 +252,16 @@ class Cloudinary::Utils
218
252
  unless public_id.blank? ^ text_style.blank?
219
253
  raise(CloudinaryException, "Must supply either style parameters or a public_id when providing text parameter in a text overlay/underlay")
220
254
  end
221
- text = smart_escape smart_escape(text, %r"([,/])")
222
255
 
256
+ result = ""
257
+ # Don't encode interpolation expressions e.g. $(variable)
258
+ while(/\$\([a-zA-Z]\w+\)/.match text) do
259
+ match = Regexp.last_match
260
+ result += smart_escape smart_escape(match.pre_match, %r"([,/])") # append encoded pre-match
261
+ result += match.to_s # append match
262
+ text = match.post_match
263
+ end
264
+ text = result + smart_escape( smart_escape(text, %r"([,/])"))
223
265
  end
224
266
  end
225
267
  components.push(resource_type) if resource_type != "image"
@@ -1,4 +1,4 @@
1
1
  # Copyright Cloudinary
2
2
  module Cloudinary
3
- VERSION = "1.5.2"
3
+ VERSION = "1.6.0"
4
4
  end
@@ -30,10 +30,16 @@ describe Cloudinary::Uploader do
30
30
  expect(result["signature"]).to eq(expected_signature)
31
31
  end
32
32
 
33
+ it "should successfully upload file asynchronously" do
34
+ result = Cloudinary::Uploader.upload(Pathname.new(TEST_IMG), :async => true)
35
+ expect(result["status"]).to eq("pending")
36
+ end
37
+
33
38
  describe '.rename' do
34
39
  before(:all) do
35
40
  @result = Cloudinary::Uploader.upload(TEST_IMG, :tags => [TEST_TAG, TIMESTAMP_TAG])
36
41
  @resource_1_id = @result["public_id"]
42
+ @resource_1_type = @result["type"]
37
43
  result = Cloudinary::Uploader.upload("spec/favicon.ico", :tags => [TEST_TAG, TIMESTAMP_TAG])
38
44
  @resource_2_id = result["public_id"]
39
45
  end
@@ -49,6 +55,14 @@ describe Cloudinary::Uploader do
49
55
  expect { Cloudinary::Uploader.rename(id, @resource_1_id+"2") }.to raise_error(CloudinaryException)
50
56
  @resource_2_id = id
51
57
  end
58
+ it 'should allow changing type of an uploaded resource' do
59
+ id = @resource_2_id
60
+ from_type = @resource_1_type
61
+ to_type = "private"
62
+ Cloudinary::Uploader.rename(id, id, :type => from_type, :to_type => to_type)
63
+ expect(Cloudinary::Api.resource(id, type: to_type)).to_not be_empty
64
+ Cloudinary::Uploader.rename(id, id, :type => to_type, :to_type => from_type)
65
+ end
52
66
  context ':overwrite => true' do
53
67
  it 'should rename to an existing ID' do
54
68
  new_id = Cloudinary::Uploader.upload(TEST_IMG, :tags => [TEST_TAG, TIMESTAMP_TAG])["public_id"]
@@ -230,9 +230,9 @@ describe Cloudinary::Utils do
230
230
  expect(["test", { :width => "auto:breakpoints:json", :crop => :fill }])
231
231
  .to produce_url("#{upload_path}/c_fill,w_auto:breakpoints:json/test")
232
232
  end
233
- it 'should support oh,ow' do
234
- expect(["test", {:width => "ow", :height => "oh", :crop => :crop}])
235
- .to produce_url("#{upload_path}/c_crop,h_oh,w_ow/test")
233
+ it 'should support ih,iw' do
234
+ expect(["test", {:width => "iw", :height => "ih", :crop => :crop}])
235
+ .to produce_url("#{upload_path}/c_crop,h_ih,w_iw/test")
236
236
  end
237
237
  end
238
238
 
@@ -240,8 +240,12 @@ describe Cloudinary::Utils do
240
240
  expect(["test", { :x => 1, :y => 2, :radius => 3, :gravity => :center, :quality => 0.4, :prefix => "a" }])
241
241
  .to produce_url("#{upload_path}/g_center,p_a,q_0.4,r_3,x_1,y_2/test")
242
242
  .and empty_options
243
+
244
+ expect(["test", { :width => 0.5, :crop => :crop, :gravity => :auto }])
245
+ .to produce_url("#{upload_path}/c_crop,g_auto,w_0.5/test")
246
+ .and empty_options
243
247
  end
244
- context ":quality" do
248
+ describe ":quality" do
245
249
  it "support a percent value" do
246
250
  expect(["test", { :x => 1, :y => 2, :radius => 3, :gravity => :center, :quality => 80, :prefix => "a" }])
247
251
  .to produce_url("#{upload_path}/g_center,p_a,q_80,r_3,x_1,y_2/test")
@@ -771,21 +775,51 @@ describe Cloudinary::Utils do
771
775
  end
772
776
  it "should support and translate operators: '=', '!=', '<', '>', '<=', '>=', '&&', '||'" do
773
777
 
774
- allOperators =
775
- 'if_' +
776
- 'w_eq_0_and' +
777
- '_w_ne_0_or' +
778
- '_h_lt_0_and' +
779
- '_ar_gt_0_and' +
780
- '_pc_lte_0_and' +
781
- '_fc_gte_0' +
778
+ all_operators =
779
+ 'if_' +
780
+ 'w_eq_0_and' +
781
+ '_w_ne_0_or' +
782
+ '_h_lt_0_and' +
783
+ '_ar_gt_0_and' +
784
+ '_pc_lte_0_and' +
785
+ '_fc_gte_0' +
782
786
  ',e_grayscale'
783
787
 
784
788
  expect( ["sample",
785
789
  :if =>"width = 0 && w != 0 || height < 0 and aspect_ratio > 0 and page_count <= 0 and face_count >= 0",
786
790
  :effect =>"grayscale"])
787
- .to produce_url("#{upload_path}/#{allOperators}/sample")
791
+ .to produce_url("#{upload_path}/#{all_operators}/sample")
792
+ end
793
+
794
+ end
795
+ end
796
+
797
+ describe "variables" do
798
+ it "array should define a set of variables" do
799
+ options = {
800
+ :if => "face_count > 2",
801
+ :variables => [ ["$z", 5], ["$foo", "$z * 2"] ],
802
+ :crop => "scale", :width => "$foo * 200"
803
+ }
804
+ t = Cloudinary::Utils.generate_transformation_string options
805
+ expect(t).to eq("if_fc_gt_2,$z_5,$foo_$z_mul_2,c_scale,w_$foo_mul_200")
806
+ end
807
+ it "'$key' should define a variable" do
808
+ options = { :transformation => [
809
+ {"$foo" => 10 },
810
+ {:if => "face_count > 2"},
811
+ {:crop => "scale", :width => "$foo * 200 / face_count"},
812
+ {:if => "end"}
813
+ ] }
814
+ t = Cloudinary::Utils.generate_transformation_string options
815
+ expect(t).to eq("$foo_10/if_fc_gt_2/c_scale,w_$foo_mul_200_div_fc/if_end")
816
+ end
817
+ it "should support text values" do
818
+ expect( ["sample", :effect => "$efname:100", "$efname" => "!blur!"]).to produce_url "#{upload_path}/$efname_!blur!,e_$efname:100/sample"
819
+
788
820
  end
821
+ it "should support string interpolation" do
822
+ expect( ["sample", :crop => "scale", :overlay => {:text => "$(start)Hello $(name)$(ext), $(no ) $( no)$(end)", :font_family => "Arial", :font_size => "18"} ]).to produce_url "#{upload_path}/c_scale,l_text:Arial_18:$(start)Hello%20$(name)$(ext)%252C%20%24%28no%20%29%20%24%28%20no%29$(end)/sample"
789
823
 
790
824
  end
791
825
  end
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.5.2
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nadav Soferman
@@ -10,134 +10,106 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2017-02-22 00:00:00.000000000 Z
13
+ date: 2017-03-08 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: aws_cf_signer
17
17
  requirement: !ruby/object:Gem::Requirement
18
18
  requirements:
19
- - - ! '>='
19
+ - - ">="
20
20
  - !ruby/object:Gem::Version
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
- - - ! '>='
26
+ - - ">="
27
27
  - !ruby/object:Gem::Version
28
28
  version: '0'
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: rspec
31
31
  requirement: !ruby/object:Gem::Requirement
32
32
  requirements:
33
- - - ! '>='
33
+ - - ">="
34
34
  - !ruby/object:Gem::Version
35
35
  version: '3.5'
36
36
  type: :development
37
37
  prerelease: false
38
38
  version_requirements: !ruby/object:Gem::Requirement
39
39
  requirements:
40
- - - ! '>='
40
+ - - ">="
41
41
  - !ruby/object:Gem::Version
42
42
  version: '3.5'
43
43
  - !ruby/object:Gem::Dependency
44
44
  name: rspec-rails
45
45
  requirement: !ruby/object:Gem::Requirement
46
46
  requirements:
47
- - - ! '>='
47
+ - - ">="
48
48
  - !ruby/object:Gem::Version
49
49
  version: '0'
50
50
  type: :development
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
53
53
  requirements:
54
- - - ! '>='
54
+ - - ">="
55
55
  - !ruby/object:Gem::Version
56
56
  version: '0'
57
57
  - !ruby/object:Gem::Dependency
58
58
  name: rest-client
59
59
  requirement: !ruby/object:Gem::Requirement
60
60
  requirements:
61
- - - <
61
+ - - ">="
62
62
  - !ruby/object:Gem::Version
63
- version: '2.0'
64
- type: :runtime
65
- prerelease: false
66
- version_requirements: !ruby/object:Gem::Requirement
67
- requirements:
68
- - - <
69
- - !ruby/object:Gem::Version
70
- version: '2.0'
71
- - !ruby/object:Gem::Dependency
72
- name: json
73
- requirement: !ruby/object:Gem::Requirement
74
- requirements:
75
- - - ~>
76
- - !ruby/object:Gem::Version
77
- version: '1.8'
63
+ version: '0'
78
64
  type: :runtime
79
65
  prerelease: false
80
66
  version_requirements: !ruby/object:Gem::Requirement
81
67
  requirements:
82
- - - ~>
68
+ - - ">="
83
69
  - !ruby/object:Gem::Version
84
- version: '1.8'
70
+ version: '0'
85
71
  - !ruby/object:Gem::Dependency
86
72
  name: actionpack
87
73
  requirement: !ruby/object:Gem::Requirement
88
74
  requirements:
89
- - - <
75
+ - - ">="
90
76
  - !ruby/object:Gem::Version
91
- version: '5.0'
77
+ version: '0'
92
78
  type: :development
93
79
  prerelease: false
94
80
  version_requirements: !ruby/object:Gem::Requirement
95
81
  requirements:
96
- - - <
82
+ - - ">="
97
83
  - !ruby/object:Gem::Version
98
- version: '5.0'
84
+ version: '0'
99
85
  - !ruby/object:Gem::Dependency
100
86
  name: simplecov
101
87
  requirement: !ruby/object:Gem::Requirement
102
88
  requirements:
103
- - - ! '>='
89
+ - - ">="
104
90
  - !ruby/object:Gem::Version
105
91
  version: '0'
106
92
  type: :development
107
93
  prerelease: false
108
94
  version_requirements: !ruby/object:Gem::Requirement
109
95
  requirements:
110
- - - ! '>='
96
+ - - ">="
111
97
  - !ruby/object:Gem::Version
112
98
  version: '0'
113
- - !ruby/object:Gem::Dependency
114
- name: nokogiri
115
- requirement: !ruby/object:Gem::Requirement
116
- requirements:
117
- - - <
118
- - !ruby/object:Gem::Version
119
- version: 1.7.0
120
- type: :development
121
- prerelease: false
122
- version_requirements: !ruby/object:Gem::Requirement
123
- requirements:
124
- - - <
125
- - !ruby/object:Gem::Version
126
- version: 1.7.0
127
99
  - !ruby/object:Gem::Dependency
128
100
  name: rubyzip
129
101
  requirement: !ruby/object:Gem::Requirement
130
102
  requirements:
131
- - - <
103
+ - - ">="
132
104
  - !ruby/object:Gem::Version
133
- version: 1.2.1
105
+ version: '0'
134
106
  type: :development
135
107
  prerelease: false
136
108
  version_requirements: !ruby/object:Gem::Requirement
137
109
  requirements:
138
- - - <
110
+ - - ">="
139
111
  - !ruby/object:Gem::Version
140
- version: 1.2.1
112
+ version: '0'
141
113
  description: Client library for easily using the Cloudinary service
142
114
  email:
143
115
  - nadav.soferman@cloudinary.com
@@ -147,9 +119,9 @@ executables: []
147
119
  extensions: []
148
120
  extra_rdoc_files: []
149
121
  files:
150
- - .gitignore
151
- - .rspec
152
- - .travis.yml
122
+ - ".gitignore"
123
+ - ".rspec"
124
+ - ".travis.yml"
153
125
  - CHANGELOG.md
154
126
  - CONTRIBUTING.md
155
127
  - Gemfile
@@ -219,17 +191,17 @@ require_paths:
219
191
  - lib
220
192
  required_ruby_version: !ruby/object:Gem::Requirement
221
193
  requirements:
222
- - - ! '>='
194
+ - - ">="
223
195
  - !ruby/object:Gem::Version
224
196
  version: '0'
225
197
  required_rubygems_version: !ruby/object:Gem::Requirement
226
198
  requirements:
227
- - - ! '>='
199
+ - - ">="
228
200
  - !ruby/object:Gem::Version
229
201
  version: '0'
230
202
  requirements: []
231
203
  rubyforge_project: cloudinary
232
- rubygems_version: 2.4.8
204
+ rubygems_version: 2.4.5.1
233
205
  signing_key:
234
206
  specification_version: 4
235
207
  summary: Client library for easily using the Cloudinary service