cloudinary 1.1.7 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8c21572d5ca0363eb07c0a226e92498d90d9f2b9
4
- data.tar.gz: ab8a7a05057dbf409296897576f69745d9516a8a
3
+ metadata.gz: 9b2454e65f38986500bbd665f0b795bc828c778e
4
+ data.tar.gz: ad45733ff5323991533c2c731539b39dfed1156c
5
5
  SHA512:
6
- metadata.gz: d609e1b2f396d259645df469f7ec94769f31bae9e49571b77530aa73521bbece7dcdff545309db03f8486ff4c566a68179b26f3d3473a7db444554fd1cdddcca
7
- data.tar.gz: 3496b66de2e36abdde1e9b28e30c392807f784295ed4de76f4f0e87e5362fb9be2202e625cd6ffe85c6e8b4c8d01a70127c6c29ff5a4c6b278e8c0999be7412c
6
+ metadata.gz: f0896c0b1aadf9c847c2fd057c9ff8f8d268198b342e6287e9edc595a6459247df5bee21040d581d3f603f24e43cad165dca7be34801d87bf3d1420e1e5584b6
7
+ data.tar.gz: c7170f8a53f59af81e4a7e7ff757f002ab095d409c5c81c93310f5b1632e72fe5f0dd3a3bafb1f1e0a6986184e8b6c8443b0d94a82f600f82400fa4c0e46bc60
@@ -1,4 +1,19 @@
1
1
 
2
+ 1.2.0 / 2016-06-22
3
+ ==================
4
+
5
+ New functionality and features
6
+ ------------------------------
7
+
8
+ * New configuration parameter `:client_hints`
9
+ * Enhanced auto `width` values
10
+ * Enhanced `quality` values
11
+
12
+ Other Changes
13
+ -------------
14
+
15
+ * Remove coffee and map files. Fixes #203
16
+
2
17
  1.1.7 / 2016-06-06
3
18
  ==================
4
19
 
data/Rakefile CHANGED
@@ -16,8 +16,7 @@ namespace :cloudinary do
16
16
  task :fetch_assets do
17
17
  index_files = %w[jquery.ui.widget.js jquery.iframe-transport.js jquery.fileupload.js jquery.cloudinary.js]
18
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
- other_files = %w[jquery.cloudinary.coffee jquery.cloudinary.js.map]
20
- files = index_files + processing_files + other_files
19
+ files = index_files + processing_files
21
20
 
22
21
  release = JSON(RestClient.get("https://api.github.com/repos/cloudinary/cloudinary_js/releases/latest"))
23
22
 
@@ -46,9 +46,11 @@ module CloudinaryHelper
46
46
  source = cloudinary_url_internal(source, tag_options)
47
47
 
48
48
  responsive_placeholder = Cloudinary::Utils.config_option_consume(tag_options, :responsive_placeholder)
49
+ client_hints = Cloudinary::Utils.config_option_consume(tag_options, :client_hints)
50
+
49
51
  hidpi = tag_options.delete(:hidpi)
50
52
  responsive = tag_options.delete(:responsive)
51
- if hidpi || responsive
53
+ if !client_hints && (hidpi || responsive)
52
54
  tag_options["data-src"] = source
53
55
  source = nil
54
56
  extra_class = responsive ? "cld-responsive" : "cld-hidpi"
@@ -184,6 +186,9 @@ module CloudinaryHelper
184
186
  content_tag("script", "$.cloudinary.config(#{params.to_json});".html_safe, :type=>"text/javascript")
185
187
  end
186
188
 
189
+ def cl_client_hints_meta_tag
190
+ tag "meta", "http-equiv" => "Accept-CH", :content => "DPR, Viewport-Width, Width"
191
+ end
187
192
  def cloudinary_url(source, options = {})
188
193
  cloudinary_url_internal(source, options.clone)
189
194
  end
@@ -51,10 +51,10 @@ class Cloudinary::Utils
51
51
  angle = build_array(options.delete(:angle)).join(".")
52
52
 
53
53
  no_html_sizes = has_layer || angle.present? || crop.to_s == "fit" || crop.to_s == "limit" || crop.to_s == "lfill"
54
- options.delete(:width) if width && (width.to_f < 1 || no_html_sizes || width == "auto" || responsive_width)
54
+ options.delete(:width) if width && (width.to_f < 1 || no_html_sizes || width.to_s.start_with?("auto") || responsive_width)
55
55
  options.delete(:height) if height && (height.to_f < 1 || no_html_sizes || responsive_width)
56
56
 
57
- width=height=nil if crop.nil? && !has_layer && width != "auto" && !allow_implicit_crop_mode
57
+ width=height=nil if crop.nil? && !has_layer && !width.to_s.start_with?("auto") && !allow_implicit_crop_mode
58
58
 
59
59
  background = options.delete(:background)
60
60
  background = background.sub(/^#/, 'rgb:') if background
@@ -156,7 +156,7 @@ class Cloudinary::Utils
156
156
  transformations << generate_transformation_string(responsive_width_transformation.clone, allow_implicit_crop_mode)
157
157
  end
158
158
 
159
- if width.to_s == "auto" || responsive_width
159
+ if width.to_s.start_with?( "auto") || responsive_width
160
160
  options[:responsive] = true
161
161
  end
162
162
  if dpr.to_s == "auto"
@@ -1,4 +1,4 @@
1
1
  # Copyright Cloudinary
2
2
  module Cloudinary
3
- VERSION = "1.1.7"
3
+ VERSION = "1.2.0"
4
4
  end
@@ -11,6 +11,9 @@ end
11
11
  RSpec.describe CloudinaryHelper do
12
12
  let(:helper) { helper_class.new }
13
13
  let(:options) { {} }
14
+ before :each do
15
+ Cloudinary.config({})
16
+ end
14
17
  context "#cl_image_upload_tag" do
15
18
  let(:options) {{:multiple => true}}
16
19
  before do
@@ -70,5 +73,58 @@ RSpec.describe CloudinaryHelper do
70
73
  expect(test_tag['data-src']).to eq( "http://res.cloudinary.com/test/image/upload/dpr_auto/sample.jpg")
71
74
  end
72
75
  end
76
+
77
+ context ":client_hints" do
78
+ shared_examples "client_hints" do
79
+ it "should not use data-src or set responsive class" do
80
+ expect(test_tag.name).to match( 'img')
81
+ expect(test_tag['class']).to be_nil
82
+ expect(test_tag['data-src']).to be_nil
83
+ expect(test_tag['src']).to eq( "http://res.cloudinary.com/test/image/upload/dpr_auto,w_auto/sample.jpg")
84
+ end
85
+ it "should override :responsive" do
86
+ Cloudinary.config.responsive = true
87
+ expect(test_tag.name).to match( 'img')
88
+ expect(test_tag['class']).to be_nil
89
+ expect(test_tag['data-src']).to be_nil
90
+ expect(test_tag['src']).to eq( "http://res.cloudinary.com/test/image/upload/dpr_auto,w_auto/sample.jpg")
91
+ end
92
+ end
93
+ context "as option" do
94
+ let(:options) { {:dpr => :auto, :cloud_name => "test", :width => "auto", :client_hints => true} }
95
+ include_examples "client_hints"
96
+ end
97
+ context "as global configuration" do
98
+ before do
99
+ Cloudinary.config.client_hints = true
100
+ end
101
+ let(:options) { {:dpr => :auto, :cloud_name => "test", :width => "auto"} }
102
+ include_examples "client_hints"
103
+ end
104
+
105
+ context "false" do
106
+ let(:options) { {:width => :auto, :cloud_name => "test", :client_hints => false} }
107
+ it "should use normal responsive behaviour" do
108
+ expect(test_tag.name).to match( 'img')
109
+ expect(test_tag['class']).to eq( 'cld-responsive')
110
+ expect(test_tag['data-src']).to eq( "http://res.cloudinary.com/test/image/upload/w_auto/sample.jpg")
111
+ end
112
+ end
113
+ context "width" do
114
+ let(:options) { {:dpr => :auto, :cloud_name => "test", :width => "auto:breakpoints", :client_hints => true}}
115
+ it "supports auto width" do
116
+ expect(test_tag['src']).to eq( "http://res.cloudinary.com/test/image/upload/dpr_auto,w_auto:breakpoints/sample.jpg")
117
+ end
118
+ end
119
+ end
120
+ end
121
+
122
+ context "#cl_client_hints_meta_tag" do
123
+ it "should create a meta tag" do
124
+ tag = TestTag.new( helper.cl_client_hints_meta_tag)
125
+ expect(tag.name).to match('meta')
126
+ expect(tag['content']).to eq('DPR, Viewport-Width, Width')
127
+ expect(tag['http-equiv']).to eq('Accept-CH')
128
+ end
73
129
  end
74
130
  end
@@ -207,6 +207,18 @@ describe Cloudinary::Utils do
207
207
  .to produce_url("#{upload_path}/c_crop,h_10,w_10/test")
208
208
  .and mutate_options_to({ :width => "10", :height => "10" })
209
209
  end
210
+ it "should support auto width" do
211
+ expect(["test", { :width => "auto:20", :crop => :fill }])
212
+ .to produce_url("#{upload_path}/c_fill,w_auto:20/test")
213
+ expect(["test", { :width => "auto:20:350", :crop => :fill }])
214
+ .to produce_url("#{upload_path}/c_fill,w_auto:20:350/test")
215
+ expect(["test", { :width => "auto:breakpoints", :crop => :fill }])
216
+ .to produce_url("#{upload_path}/c_fill,w_auto:breakpoints/test")
217
+ expect(["test", { :width => "auto:breakpoints_100_1900_20_15", :crop => :fill }])
218
+ .to produce_url("#{upload_path}/c_fill,w_auto:breakpoints_100_1900_20_15/test")
219
+ expect(["test", { :width => "auto:breakpoints:json", :crop => :fill }])
220
+ .to produce_url("#{upload_path}/c_fill,w_auto:breakpoints:json/test")
221
+ end
210
222
  end
211
223
 
212
224
  it "should use x, y, radius, prefix, gravity and quality from options" do
@@ -214,7 +226,24 @@ describe Cloudinary::Utils do
214
226
  .to produce_url("#{upload_path}/g_center,p_a,q_0.4,r_3,x_1,y_2/test")
215
227
  .and empty_options
216
228
  end
229
+ context ":quality" do
230
+ it "support a percent value" do
231
+ expect(["test", { :x => 1, :y => 2, :radius => 3, :gravity => :center, :quality => 80, :prefix => "a" }])
232
+ .to produce_url("#{upload_path}/g_center,p_a,q_80,r_3,x_1,y_2/test")
233
+
234
+ expect(["test", { :x => 1, :y => 2, :radius => 3, :gravity => :center, :quality => "80:444", :prefix => "a" }])
235
+ .to produce_url("#{upload_path}/g_center,p_a,q_80:444,r_3,x_1,y_2/test")
236
+ end
237
+ it "should support auto value" do
238
+
239
+ expect(["test", { :x => 1, :y => 2, :radius => 3, :gravity => :center, :quality => "auto", :prefix => "a" }])
240
+ .to produce_url("#{upload_path}/g_center,p_a,q_auto,r_3,x_1,y_2/test")
217
241
 
242
+ expect(["test", { :x => 1, :y => 2, :radius => 3, :gravity => :center, :quality => "auto:good", :prefix => "a" }])
243
+ .to produce_url("#{upload_path}/g_center,p_a,q_auto:good,r_3,x_1,y_2/test")
244
+
245
+ end
246
+ end
218
247
  describe ":transformation" do
219
248
  it "should support named tranformation" do
220
249
  expect(["test", { :transformation => "blip" }])
@@ -1,6 +1,6 @@
1
1
 
2
2
  /**
3
- * Cloudinary's JavaScript library - Version 2.0.9
3
+ * Cloudinary's JavaScript library - Version 2.1.0
4
4
  * Copyright Cloudinary
5
5
  * see https://github.com/cloudinary/cloudinary_js
6
6
  *
@@ -1748,16 +1748,18 @@ var extend = function(child, parent) { for (var key in parent) { if (hasProp.cal
1748
1748
  };
1749
1749
 
1750
1750
  Transformation.prototype.dpr = function(value) {
1751
- return this.param(value, "dpr", "dpr", function(dpr) {
1752
- dpr = dpr.toString();
1753
- if (dpr === "auto") {
1754
- return "1.0";
1755
- } else if (dpr != null ? dpr.match(/^\d+$/) : void 0) {
1756
- return dpr + ".0";
1757
- } else {
1758
- return dpr;
1759
- }
1760
- });
1751
+ return this.param(value, "dpr", "dpr", (function(_this) {
1752
+ return function(dpr) {
1753
+ dpr = dpr.toString();
1754
+ if ((dpr === "auto") && _this.getValue("client_hints") !== true) {
1755
+ return "1.0";
1756
+ } else if (dpr != null ? dpr.match(/^\d+$/) : void 0) {
1757
+ return dpr + ".0";
1758
+ } else {
1759
+ return dpr;
1760
+ }
1761
+ };
1762
+ })(this));
1761
1763
  };
1762
1764
 
1763
1765
  Transformation.prototype.effect = function(value) {
@@ -2389,6 +2391,12 @@ var extend = function(child, parent) { for (var key in parent) { if (hasProp.cal
2389
2391
  return element;
2390
2392
  };
2391
2393
 
2394
+ HtmlTag.isResponsive = function(tag, responsiveClass) {
2395
+ var dataSrc;
2396
+ dataSrc = Util.getData(tag, 'src-cache') || Util.getData(tag, 'src');
2397
+ return Util.hasClass(tag, responsiveClass) && /\bw_auto\b/.exec(dataSrc);
2398
+ };
2399
+
2392
2400
  return HtmlTag;
2393
2401
 
2394
2402
  })();
@@ -2837,9 +2845,9 @@ var extend = function(child, parent) { for (var key in parent) { if (hasProp.cal
2837
2845
 
2838
2846
  })(TextLayer);
2839
2847
  Cloudinary = (function() {
2840
- var AKAMAI_SHARED_CDN, CF_SHARED_CDN, DEFAULT_POSTER_OPTIONS, DEFAULT_VIDEO_SOURCE_TYPES, OLD_AKAMAI_SHARED_CDN, SHARED_CDN, VERSION, absolutize, applyBreakpoints, cdnSubdomainNumber, closestAbove, cloudinaryUrlPrefix, defaultBreakpoints, finalizeResourceType, parentWidth;
2848
+ var AKAMAI_SHARED_CDN, CF_SHARED_CDN, DEFAULT_POSTER_OPTIONS, DEFAULT_VIDEO_SOURCE_TYPES, OLD_AKAMAI_SHARED_CDN, SHARED_CDN, VERSION, absolutize, applyBreakpoints, cdnSubdomainNumber, closestAbove, cloudinaryUrlPrefix, defaultBreakpoints, finalizeResourceType, findContainerWidth, maxWidth, updateDpr;
2841
2849
 
2842
- VERSION = "2.0.9";
2850
+ VERSION = "2.1.0";
2843
2851
 
2844
2852
  CF_SHARED_CDN = "d3jpl91pxevbkh.cloudfront.net";
2845
2853
 
@@ -3137,17 +3145,20 @@ var extend = function(child, parent) { for (var key in parent) { if (hasProp.cal
3137
3145
  */
3138
3146
 
3139
3147
  Cloudinary.prototype.image = function(publicId, options) {
3140
- var img;
3148
+ var client_hints, img, ref, ref1;
3141
3149
  if (options == null) {
3142
3150
  options = {};
3143
3151
  }
3144
3152
  img = this.imageTag(publicId, options);
3145
- if (options.src == null) {
3153
+ client_hints = (ref = (ref1 = options.client_hints) != null ? ref1 : this.config('client_hints')) != null ? ref : false;
3154
+ if (!((options.src != null) || client_hints)) {
3146
3155
  img.setAttr("src", '');
3147
3156
  }
3148
3157
  img = img.toDOM();
3149
- Util.setData(img, 'src-cache', this.url(publicId, options));
3150
- this.cloudinary_update(img, options);
3158
+ if (!client_hints) {
3159
+ Util.setData(img, 'src-cache', this.url(publicId, options));
3160
+ this.cloudinary_update(img, options);
3161
+ }
3151
3162
  return img;
3152
3163
  };
3153
3164
 
@@ -3355,11 +3366,11 @@ var extend = function(child, parent) { for (var key in parent) { if (hasProp.cal
3355
3366
  * @ignore
3356
3367
  */
3357
3368
 
3358
- Cloudinary.prototype.calc_breakpoint = function(element, width) {
3369
+ Cloudinary.prototype.calc_breakpoint = function(element, width, steps) {
3359
3370
  var breakpoints, point;
3360
3371
  breakpoints = Util.getData(element, 'breakpoints') || Util.getData(element, 'stoppoints') || this.config('breakpoints') || this.config('stoppoints') || defaultBreakpoints;
3361
3372
  if (Util.isFunction(breakpoints)) {
3362
- return breakpoints(width);
3373
+ return breakpoints(width, steps);
3363
3374
  } else {
3364
3375
  if (Util.isString(breakpoints)) {
3365
3376
  breakpoints = ((function() {
@@ -3414,8 +3425,11 @@ var extend = function(child, parent) { for (var key in parent) { if (hasProp.cal
3414
3425
  return dprString;
3415
3426
  };
3416
3427
 
3417
- defaultBreakpoints = function(width) {
3418
- return 100 * Math.ceil(width / 100);
3428
+ defaultBreakpoints = function(width, steps) {
3429
+ if (steps == null) {
3430
+ steps = 100;
3431
+ }
3432
+ return steps * Math.ceil(width / steps);
3419
3433
  };
3420
3434
 
3421
3435
  closestAbove = function(list, value) {
@@ -3510,17 +3524,17 @@ var extend = function(child, parent) { for (var key in parent) { if (hasProp.cal
3510
3524
  return this;
3511
3525
  };
3512
3526
 
3513
- applyBreakpoints = function(tag, width, options) {
3527
+ applyBreakpoints = function(tag, width, steps, options) {
3514
3528
  var ref, ref1, ref2, responsive_use_breakpoints;
3515
3529
  responsive_use_breakpoints = (ref = (ref1 = (ref2 = options['responsive_use_breakpoints']) != null ? ref2 : options['responsive_use_stoppoints']) != null ? ref1 : this.config('responsive_use_breakpoints')) != null ? ref : this.config('responsive_use_stoppoints');
3516
3530
  if ((!responsive_use_breakpoints) || (responsive_use_breakpoints === 'resize' && !options.resizing)) {
3517
3531
  return width;
3518
3532
  } else {
3519
- return this.calc_breakpoint(tag, width);
3533
+ return this.calc_breakpoint(tag, width, steps);
3520
3534
  }
3521
3535
  };
3522
3536
 
3523
- parentWidth = function(element) {
3537
+ findContainerWidth = function(element) {
3524
3538
  var containerWidth, style;
3525
3539
  containerWidth = 0;
3526
3540
  while (((element = element != null ? element.parentNode : void 0) instanceof Element) && !containerWidth) {
@@ -3532,6 +3546,20 @@ var extend = function(child, parent) { for (var key in parent) { if (hasProp.cal
3532
3546
  return containerWidth;
3533
3547
  };
3534
3548
 
3549
+ updateDpr = function(dataSrc, roundDpr) {
3550
+ return dataSrc.replace(/\bdpr_(1\.0|auto)\b/g, 'dpr_' + this.device_pixel_ratio(roundDpr));
3551
+ };
3552
+
3553
+ maxWidth = function(requiredWidth, tag) {
3554
+ var imageWidth;
3555
+ imageWidth = Util.getData(tag, 'width') || 0;
3556
+ if (requiredWidth > imageWidth) {
3557
+ imageWidth = requiredWidth;
3558
+ Util.setData(tag, 'width', requiredWidth);
3559
+ }
3560
+ return requiredWidth;
3561
+ };
3562
+
3535
3563
 
3536
3564
  /**
3537
3565
  * Update hidpi (dpr_auto) and responsive (w_auto) fields according to the current container size and the device pixel ratio.
@@ -3549,10 +3577,16 @@ var extend = function(child, parent) { for (var key in parent) { if (hasProp.cal
3549
3577
  */
3550
3578
 
3551
3579
  Cloudinary.prototype.cloudinary_update = function(elements, options) {
3552
- var containerWidth, imageWidth, j, len, ref, ref1, ref2, ref3, requestedWidth, responsiveClass, roundDpr, setUrl, src, tag;
3580
+ var client_hints, containerWidth, dataSrc, j, len, match, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, requiredWidth, responsive, responsiveClass, roundDpr, setUrl, tag;
3553
3581
  if (options == null) {
3554
3582
  options = {};
3555
3583
  }
3584
+ client_hints = (ref = (ref1 = options.client_hints) != null ? ref1 : this.config('client_hints')) != null ? ref : false;
3585
+ client_hints = client_hints || (typeof document !== "undefined" && document !== null ? document.querySelector('meta[http-equiv="Accept-CH"]') : void 0);
3586
+ if (client_hints) {
3587
+ return;
3588
+ }
3589
+ responsive = (ref2 = (ref3 = options.responsive) != null ? ref3 : this.config('responsive')) != null ? ref2 : false;
3556
3590
  elements = (function() {
3557
3591
  switch (false) {
3558
3592
  case !Util.isArray(elements):
@@ -3565,30 +3599,33 @@ var extend = function(child, parent) { for (var key in parent) { if (hasProp.cal
3565
3599
  return [elements];
3566
3600
  }
3567
3601
  })();
3568
- responsiveClass = (ref = (ref1 = this.responsiveConfig['responsive_class']) != null ? ref1 : options['responsive_class']) != null ? ref : this.config('responsive_class');
3569
- roundDpr = (ref2 = options['round_dpr']) != null ? ref2 : this.config('round_dpr');
3602
+ responsiveClass = (ref4 = (ref5 = this.responsiveConfig['responsive_class']) != null ? ref5 : options['responsive_class']) != null ? ref4 : this.config('responsive_class');
3603
+ roundDpr = (ref6 = options['round_dpr']) != null ? ref6 : this.config('round_dpr');
3570
3604
  for (j = 0, len = elements.length; j < len; j++) {
3571
3605
  tag = elements[j];
3572
- if (!((ref3 = tag.tagName) != null ? ref3.match(/img/i) : void 0)) {
3606
+ if (!((ref7 = tag.tagName) != null ? ref7.match(/img/i) : void 0)) {
3573
3607
  continue;
3574
3608
  }
3575
3609
  setUrl = true;
3576
- if (options.responsive) {
3610
+ if (responsive && !client_hints) {
3577
3611
  Util.addClass(tag, responsiveClass);
3578
3612
  }
3579
- src = Util.getData(tag, 'src-cache') || Util.getData(tag, 'src');
3580
- if (!Util.isEmpty(src)) {
3581
- src = src.replace(/\bdpr_(1\.0|auto)\b/g, 'dpr_' + this.device_pixel_ratio(roundDpr));
3582
- if (Util.hasClass(tag, responsiveClass) && /\bw_auto\b/.exec(src)) {
3583
- containerWidth = parentWidth(tag);
3613
+ dataSrc = Util.getData(tag, 'src-cache') || Util.getData(tag, 'src');
3614
+ if (!Util.isEmpty(dataSrc)) {
3615
+ dataSrc = updateDpr.call(this, dataSrc, roundDpr);
3616
+ if (HtmlTag.isResponsive(tag, responsiveClass)) {
3617
+ containerWidth = findContainerWidth(tag);
3584
3618
  if (containerWidth !== 0) {
3585
- requestedWidth = applyBreakpoints.call(this, tag, containerWidth, options);
3586
- imageWidth = Util.getData(tag, 'width') || 0;
3587
- if (requestedWidth > imageWidth) {
3588
- imageWidth = requestedWidth;
3589
- Util.setData(tag, 'width', requestedWidth);
3619
+ switch (false) {
3620
+ case !/w_auto:breakpoints/.test(dataSrc):
3621
+ requiredWidth = maxWidth(containerWidth, tag);
3622
+ dataSrc = dataSrc.replace(/w_auto:breakpoints([_0-9]*)(:[0-9]+)?/, "w_auto:breakpoints$1:" + requiredWidth);
3623
+ break;
3624
+ case !(match = /w_auto(:(\d+))?/.exec(dataSrc)):
3625
+ requiredWidth = applyBreakpoints.call(this, tag, containerWidth, match[2], options);
3626
+ requiredWidth = maxWidth(requiredWidth, tag);
3627
+ dataSrc = dataSrc.replace(/w_auto[^,\/]*/g, "w_" + requiredWidth);
3590
3628
  }
3591
- src = src.replace(/\bw_auto\b/g, 'w_' + imageWidth);
3592
3629
  Util.removeAttribute(tag, 'width');
3593
3630
  if (!options.responsive_preserve_height) {
3594
3631
  Util.removeAttribute(tag, 'height');
@@ -3598,7 +3635,7 @@ var extend = function(child, parent) { for (var key in parent) { if (hasProp.cal
3598
3635
  }
3599
3636
  }
3600
3637
  if (setUrl) {
3601
- Util.setAttribute(tag, 'src', src);
3638
+ Util.setAttribute(tag, 'src', dataSrc);
3602
3639
  }
3603
3640
  }
3604
3641
  }
@@ -3645,16 +3682,20 @@ var extend = function(child, parent) { for (var key in parent) { if (hasProp.cal
3645
3682
  */
3646
3683
 
3647
3684
  CloudinaryJQuery.prototype.image = function(publicId, options) {
3648
- var img, tag_options, url;
3685
+ var client_hints, img, ref, ref1;
3649
3686
  if (options == null) {
3650
3687
  options = {};
3651
3688
  }
3652
- tag_options = Util.merge({
3653
- src: ''
3654
- }, options);
3655
- img = this.imageTag(publicId, tag_options).toHtml();
3656
- url = this.url(publicId, options);
3657
- return jQuery(img).data('src-cache', url).cloudinary_update(options);
3689
+ img = this.imageTag(publicId, options);
3690
+ client_hints = (ref = (ref1 = options.client_hints) != null ? ref1 : this.config('client_hints')) != null ? ref : false;
3691
+ if (!((options.src != null) || client_hints)) {
3692
+ img.setAttr("src", '');
3693
+ }
3694
+ img = jQuery(img.toHtml());
3695
+ if (!client_hints) {
3696
+ img.data('src-cache', this.url(publicId, options)).cloudinary_update(options);
3697
+ }
3698
+ return img;
3658
3699
  };
3659
3700
 
3660
3701
 
@@ -4022,10 +4063,10 @@ var extend = function(child, parent) { for (var key in parent) { if (hasProp.cal
4022
4063
  TextLayer: TextLayer,
4023
4064
  SubtitlesLayer: SubtitlesLayer,
4024
4065
  Cloudinary: Cloudinary,
4025
- VERSION: "2.0.9",
4066
+ VERSION: "2.1.0",
4026
4067
  CloudinaryJQuery: CloudinaryJQuery
4027
4068
  };
4028
4069
  return cloudinary;
4029
4070
  });
4030
4071
 
4031
- //# sourceMappingURL=jquery.cloudinary.js.map
4072
+