cloudinary 1.9.1 → 1.10.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 +15 -5
- data/.gitignore +1 -0
- data/CHANGELOG.md +32 -0
- data/cloudinary.gemspec +2 -1
- data/lib/cloudinary/api.rb +28 -13
- data/lib/cloudinary/cache.rb +38 -0
- data/lib/cloudinary/cache/breakpoints_cache.rb +31 -0
- data/lib/cloudinary/cache/key_value_cache_adapter.rb +25 -0
- data/lib/cloudinary/cache/rails_cache_adapter.rb +34 -0
- data/lib/cloudinary/cache/storage/rails_cache_storage.rb +5 -0
- data/lib/cloudinary/helper.rb +47 -4
- data/lib/cloudinary/responsive.rb +111 -0
- data/lib/cloudinary/uploader.rb +22 -4
- data/lib/cloudinary/utils.rb +122 -5
- data/lib/cloudinary/version.rb +1 -1
- data/spec/access_control_spec.rb +3 -0
- data/spec/api_spec.rb +19 -13
- data/spec/auth_token_spec.rb +8 -10
- data/spec/cache_spec.rb +109 -0
- data/spec/cloudinary_helper_spec.rb +147 -12
- data/spec/image_spec.rb +107 -0
- data/spec/spec_helper.rb +38 -17
- data/spec/uploader_spec.rb +23 -8
- data/spec/utils_spec.rb +46 -3
- data/spec/video_tag_spec.rb +7 -5
- data/spec/video_url_spec.rb +4 -2
- data/tools/update_version +202 -0
- metadata +83 -30
checksums.yaml
CHANGED
@@ -1,7 +1,17 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
2
|
+
!binary "U0hBMjU2":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ODI0YWQ0Mjg5NGRkYjkxYjRkZTNkOTZhMTgzNzA5YmMyY2E2ZGVhMmZmN2Fj
|
5
|
+
NDRkYTNkNjI3ZDM5YjEwZDFkYg==
|
6
|
+
data.tar.gz: !binary |-
|
7
|
+
MGMyNDU5NTIxY2Q3M2UyMWM2ZjFmYWVkZjUwNGZmYWFmNmE0MWY0MWY2MTgz
|
8
|
+
ZTgyNzIyMjA0YjU1NjZhMWM3Yg==
|
5
9
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
|
10
|
+
metadata.gz: !binary |-
|
11
|
+
YWViMTg1MzFiOWI1ODkzYWYzNWQxMzUyZWUyMTUyNWIwODRiMDI5NWFjNmYy
|
12
|
+
YjVlNjc3NjUzN2E3ODgzNWRiNTEwZDVlZWFlYWQ2ODg5NTc3ZTcxNzIyOThl
|
13
|
+
YWY3MjlkYzkwNjk0MDY1YjI3ODJjM2RjY2FiMWYyOTMyODU4NzU=
|
14
|
+
data.tar.gz: !binary |-
|
15
|
+
MTQzOWE0OGZjZTg3MmI1YTJiOWQ2NzI1MmE4ZDQ2YWQxN2NhMThmMjMzNjJk
|
16
|
+
ZjUwZjNmYTc4MDA4ODBlM2Y0Y2FjOWNiOTc2NjI1YTg1M2EyOTg1MTNkMjg1
|
17
|
+
NTE2ZmQ2ZGEyMjk2YTE1MDM0NWM3ZGIyZDcxZDFjM2ZlNDJhNTk=
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,36 @@
|
|
1
1
|
|
2
|
+
1.10.0 / 2018-11-08
|
3
|
+
===================
|
4
|
+
|
5
|
+
New functionality and features
|
6
|
+
------------------------------
|
7
|
+
|
8
|
+
* Add the `custom_function` transformation parameter
|
9
|
+
* Add Picture and source tags
|
10
|
+
* Add `srcset` attribute to image tag
|
11
|
+
* Add support for overlays of type fetch
|
12
|
+
* Add breakpoints cache
|
13
|
+
|
14
|
+
Other Changes
|
15
|
+
-------------
|
16
|
+
|
17
|
+
* Add `update_version` script
|
18
|
+
* Fix transformations test
|
19
|
+
* Replace ruby list notation to support older ruby versions
|
20
|
+
* Refactor tests
|
21
|
+
* Replace REXML with Nokogiri
|
22
|
+
* Un-ignore the lib folder
|
23
|
+
* Ignore empty transformations when processing an array of transformations
|
24
|
+
* Restore configuration after each test
|
25
|
+
* Limit Rack version to fix compatibility issues with ruby 1.9.3
|
26
|
+
* Fix context escaping in call_context_api
|
27
|
+
* Fix uploadLarge to use X-Unique-Upload-Id
|
28
|
+
* Add test cases of OCR for upload and URL generation
|
29
|
+
* Add test case of conditional tags
|
30
|
+
* Fix expected result in cname with cdn_subdomain test
|
31
|
+
* Fix raw conversion test
|
32
|
+
* Raise exception when api-secret is missing in signed-url flow
|
33
|
+
|
2
34
|
1.9.1 / 2018-03-06
|
3
35
|
==================
|
4
36
|
|
data/cloudinary.gemspec
CHANGED
@@ -33,10 +33,11 @@ Gem::Specification.new do |s|
|
|
33
33
|
elsif RUBY_VERSION >= "1.9"
|
34
34
|
s.add_dependency "rest-client", '< 2.0'
|
35
35
|
s.add_dependency 'json', '~> 1.8'
|
36
|
-
s.add_development_dependency "actionpack", '<
|
36
|
+
s.add_development_dependency "actionpack", '<5.0'
|
37
37
|
s.add_development_dependency "simplecov"
|
38
38
|
s.add_development_dependency "nokogiri", "<1.7.0"
|
39
39
|
s.add_development_dependency "rubyzip", '<1.2.1'
|
40
|
+
s.add_development_dependency "rack", '<1.6.5'
|
40
41
|
else
|
41
42
|
s.add_dependency "i18n", "<0.7.0"
|
42
43
|
s.add_dependency "rest-client", "<=1.6.8"
|
data/lib/cloudinary/api.rb
CHANGED
@@ -19,9 +19,9 @@ class Cloudinary::Api
|
|
19
19
|
# This sets the instantiated self as the response Hash
|
20
20
|
update Cloudinary::Api.parse_json_response response
|
21
21
|
|
22
|
-
@rate_limit_allowed = response.headers[:x_featureratelimit_limit].to_i
|
23
|
-
@rate_limit_reset_at = Time.parse(response.headers[:x_featureratelimit_reset])
|
24
|
-
@rate_limit_remaining = response.headers[:x_featureratelimit_remaining].to_i
|
22
|
+
@rate_limit_allowed = response.headers[:x_featureratelimit_limit].to_i if response.headers[:x_featureratelimit_limit]
|
23
|
+
@rate_limit_reset_at = Time.parse(response.headers[:x_featureratelimit_reset]) if response.headers[:x_featureratelimit_reset]
|
24
|
+
@rate_limit_remaining = response.headers[:x_featureratelimit_remaining].to_i if response.headers[:x_featureratelimit_remaining]
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -311,6 +311,18 @@ class Cloudinary::Api
|
|
311
311
|
update_resources_access_mode(access_mode, :public_ids, public_ids, options)
|
312
312
|
end
|
313
313
|
|
314
|
+
def self.get_breakpoints(public_id, options)
|
315
|
+
local_options = options.clone
|
316
|
+
base_transformation = Cloudinary::Utils.generate_transformation_string(local_options)
|
317
|
+
srcset = local_options[:srcset]
|
318
|
+
breakpoints = [:min_width, :max_width, :bytes_step, :max_images].map {|k| srcset[k]}.join('_')
|
319
|
+
|
320
|
+
|
321
|
+
local_options[:transformation] = [base_transformation, width: "auto:breakpoints_#{breakpoints}:json"]
|
322
|
+
json_url = Cloudinary::Utils.cloudinary_url public_id, local_options
|
323
|
+
call_json_api('GET', json_url, {}, 60, {})
|
324
|
+
end
|
325
|
+
|
314
326
|
protected
|
315
327
|
|
316
328
|
def self.call_api(method, uri, params, options)
|
@@ -330,24 +342,27 @@ class Cloudinary::Api
|
|
330
342
|
else
|
331
343
|
payload = params.reject { |k, v| v.nil? || v=="" }
|
332
344
|
end
|
345
|
+
call_json_api(method, api_url, payload, timeout, headers)
|
346
|
+
end
|
347
|
+
|
348
|
+
def self.call_json_api(method, api_url, payload, timeout, headers)
|
333
349
|
RestClient::Request.execute(:method => method, :url => api_url, :payload => payload, :timeout => timeout, :headers => headers) do
|
334
350
|
|response, request, tmpresult|
|
335
351
|
return Response.new(response) if response.code == 200
|
336
352
|
exception_class = case response.code
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
353
|
+
when 400 then BadRequest
|
354
|
+
when 401 then AuthorizationRequired
|
355
|
+
when 403 then NotAllowed
|
356
|
+
when 404 then NotFound
|
357
|
+
when 409 then AlreadyExists
|
358
|
+
when 420 then RateLimited
|
359
|
+
when 500 then GeneralError
|
360
|
+
else raise GeneralError.new("Server returned unexpected status code - #{response.code} - #{response.body}")
|
361
|
+
end
|
346
362
|
json = parse_json_response(response)
|
347
363
|
raise exception_class.new(json["error"]["message"])
|
348
364
|
end
|
349
365
|
end
|
350
|
-
|
351
366
|
def self.parse_json_response(response)
|
352
367
|
return Cloudinary::Utils.json_decode(response.body)
|
353
368
|
rescue => e
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'digest'
|
2
|
+
|
3
|
+
module Cloudinary
|
4
|
+
module Cache
|
5
|
+
|
6
|
+
class << self
|
7
|
+
attr_accessor :storage
|
8
|
+
|
9
|
+
def get(public_id, options)
|
10
|
+
if block_given?
|
11
|
+
storage.read(generate_cache_key(public_id, options)) {yield}
|
12
|
+
else
|
13
|
+
storage.read(generate_cache_key(public_id, options))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def set(public_id, options, value)
|
18
|
+
storage.write(generate_cache_key(public_id, options), value)
|
19
|
+
end
|
20
|
+
|
21
|
+
alias_method :fetch, :get
|
22
|
+
|
23
|
+
def flush_all
|
24
|
+
storage.clear
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def generate_cache_key(public_id, options)
|
30
|
+
type = options[:type] || "upload"
|
31
|
+
resource_type = options[:resource_type] || "image"
|
32
|
+
transformation = Cloudinary::Utils.generate_transformation_string options.clone
|
33
|
+
format = options[:format]
|
34
|
+
Digest::SHA1.hexdigest [public_id, type, resource_type, transformation, format].reject(&:blank?).join('/')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Cloudinary::Cache
|
2
|
+
class BreakpointsCache
|
3
|
+
attr_accessor :adapter
|
4
|
+
|
5
|
+
def set(public_id, options, value)
|
6
|
+
upload_type, resource_type, transformation, format = options_to_parameters(options)
|
7
|
+
@adapter.set(public_id, upload_type, resource_type, transformation, format, value)
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
def fetch(public_id, options)
|
12
|
+
upload_type, resource_type, transformation, format = options_to_parameters(options)
|
13
|
+
@adapter.set(public_id, upload_type, resource_type, transformation, format, &Proc.new)
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
def get(public_id, options)
|
18
|
+
upload_type, resource_type, transformation, format = options_to_parameters(options)
|
19
|
+
@adapter.get(public_id, upload_type, resource_type, transformation, format)
|
20
|
+
end
|
21
|
+
|
22
|
+
def options_to_parameters(options)
|
23
|
+
options = Cloudinary::Utils.symbolize_keys options
|
24
|
+
transformation = Cloudinary::Utils.generate_transformation_string(options)
|
25
|
+
upload_type = options[:type] || 'upload'
|
26
|
+
resource_type = options[:resource_type] || 'image'
|
27
|
+
format = options[:format] || ""
|
28
|
+
[upload_type, resource_type, transformation, format]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'digest'
|
2
|
+
module Cloudinary::Cache
|
3
|
+
class KeyValueCacheAdapter < CacheAdapter
|
4
|
+
def get(public_id, type, resource_type, transformation, format)
|
5
|
+
key = generate_cache_key(public_id, type, resource_type, transformation, format)
|
6
|
+
@storage.get(key)
|
7
|
+
end
|
8
|
+
|
9
|
+
def set(public_id, type, resource_type, transformation, format, value)
|
10
|
+
key = generate_cache_key(public_id, type, resource_type, transformation, format)
|
11
|
+
@storage.set(key, value)
|
12
|
+
end
|
13
|
+
|
14
|
+
def flush_all()
|
15
|
+
@storage.flush_all()
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def generate_cache_key(public_id, type, resource_type, transformation, format)
|
21
|
+
Digest::SHA1.hexdigest [public_id, type, resource_type, transformation, format].reject(&:blank?)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Cloudinary::Cache
|
2
|
+
class RailsCacheAdapter < CacheAdapter
|
3
|
+
|
4
|
+
def flush_all
|
5
|
+
end
|
6
|
+
|
7
|
+
def get(public_id, type, resource_type, transformation, format)
|
8
|
+
key = generate_cache_key(public_id, type, resource_type, transformation, format)
|
9
|
+
Rails.cache.read(key)
|
10
|
+
end
|
11
|
+
|
12
|
+
def init
|
13
|
+
unless defined? Rails
|
14
|
+
raise CloudinaryException.new "Rails is required in order to use RailsCacheAdapter"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def set(public_id, type, resource_type, transformation, format, value)
|
19
|
+
key = generate_cache_key(public_id, type, resource_type, transformation, format)
|
20
|
+
Rails.cache.write(key, value)
|
21
|
+
end
|
22
|
+
|
23
|
+
def fetch(public_id, type, resource_type, transformation, format)
|
24
|
+
key = generate_cache_key(public_id, type, resource_type, transformation, format)
|
25
|
+
Rails.cache.fetch(key, &Proc.new)
|
26
|
+
end
|
27
|
+
private
|
28
|
+
|
29
|
+
def generate_cache_key(public_id, type, resource_type, transformation, format)
|
30
|
+
Digest::SHA1.hexdigest [public_id, type, resource_type, transformation, format].reject(&:blank?)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
data/lib/cloudinary/helper.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
require 'digest/md5'
|
2
2
|
require 'cloudinary/video_helper'
|
3
|
+
require 'cloudinary/responsive'
|
3
4
|
|
4
5
|
module CloudinaryHelper
|
6
|
+
include ActionView::Helpers::CaptureHelper
|
7
|
+
include Responsive
|
8
|
+
|
5
9
|
CL_BLANK = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
|
6
10
|
|
7
11
|
# Stand-in for Rails image_tag helper that accepts various options for transformations.
|
@@ -37,13 +41,45 @@ module CloudinaryHelper
|
|
37
41
|
|
38
42
|
end
|
39
43
|
|
44
|
+
|
45
|
+
def cl_picture_tag(source, options = {}, sources =[])
|
46
|
+
|
47
|
+
options = options.clone
|
48
|
+
content_tag 'picture' do
|
49
|
+
sources.map do |source_def|
|
50
|
+
source_options = options.clone
|
51
|
+
source_options = Cloudinary::Utils.chain_transformation(source_options, source_def[:transformation])
|
52
|
+
source_options[:media] = source_def
|
53
|
+
cl_source_tag(source, source_options)
|
54
|
+
end.push(cl_image_tag(source, options))
|
55
|
+
.join('')
|
56
|
+
.html_safe
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def cl_source_tag(source, options)
|
61
|
+
srcset_param = options.fetch(:srcset, {}).merge(Cloudinary.config.srcset || {})
|
62
|
+
attributes = options.fetch(:attributes, {}).clone
|
63
|
+
responsive_attributes = generate_image_responsive_attributes(source, attributes, srcset_param, options)
|
64
|
+
attributes = attributes.merge(responsive_attributes)
|
65
|
+
unless attributes.has_key? :srcset
|
66
|
+
attributes[:srcset] = Cloudinary::Utils.cloudinary_url(source, options)
|
67
|
+
end
|
68
|
+
media_attr = generate_media_attribute(options[:media])
|
69
|
+
attributes[:media] = media_attr unless media_attr.empty?
|
70
|
+
tag "source", attributes, true
|
71
|
+
end
|
72
|
+
|
73
|
+
|
40
74
|
def cloudinary_tag(source, options = {})
|
41
75
|
tag_options = options.clone
|
42
76
|
tag_options[:width] = tag_options.delete(:html_width) if tag_options.include?(:html_width)
|
43
77
|
tag_options[:height] = tag_options.delete(:html_height) if tag_options.include?(:html_height)
|
44
78
|
tag_options[:size] = tag_options.delete(:html_size) if tag_options.include?(:html_size)
|
45
79
|
tag_options[:border] = tag_options.delete(:html_border) if tag_options.include?(:html_border)
|
46
|
-
|
80
|
+
srcset_param = Cloudinary::Utils.config_option_consume(tag_options, :srcset, {})
|
81
|
+
src = cloudinary_url_internal(source, tag_options)
|
82
|
+
attributes = tag_options.delete(:attributes) || {}
|
47
83
|
|
48
84
|
responsive_placeholder = Cloudinary::Utils.config_option_consume(tag_options, :responsive_placeholder)
|
49
85
|
client_hints = Cloudinary::Utils.config_option_consume(tag_options, :client_hints)
|
@@ -51,15 +87,21 @@ module CloudinaryHelper
|
|
51
87
|
hidpi = tag_options.delete(:hidpi)
|
52
88
|
responsive = tag_options.delete(:responsive)
|
53
89
|
if !client_hints && (hidpi || responsive)
|
54
|
-
tag_options["data-src"] =
|
55
|
-
|
90
|
+
tag_options["data-src"] = src
|
91
|
+
src = nil
|
56
92
|
extra_class = responsive ? "cld-responsive" : "cld-hidpi"
|
57
93
|
tag_options[:class] = [tag_options[:class], extra_class].compact.join(" ")
|
58
94
|
responsive_placeholder = CL_BLANK if responsive_placeholder == "blank"
|
59
95
|
tag_options[:src] = responsive_placeholder
|
60
96
|
end
|
97
|
+
responsive_attrs = generate_image_responsive_attributes(source, attributes, srcset_param, options)
|
98
|
+
unless responsive_attrs.empty?
|
99
|
+
tag_options.delete(:width)
|
100
|
+
tag_options.delete(:height)
|
101
|
+
tag_options.merge! responsive_attrs
|
102
|
+
end
|
61
103
|
if block_given?
|
62
|
-
yield(
|
104
|
+
yield(src,tag_options)
|
63
105
|
else
|
64
106
|
tag('div', tag_options)
|
65
107
|
end
|
@@ -281,6 +323,7 @@ module CloudinaryHelper
|
|
281
323
|
end
|
282
324
|
|
283
325
|
private
|
326
|
+
|
284
327
|
def cloudinary_url_internal(source, options = {})
|
285
328
|
options[:ssl_detected] = request.ssl? if defined?(request) && request && request.respond_to?(:ssl?)
|
286
329
|
if defined?(CarrierWave::Uploader::Base) && source.is_a?(CarrierWave::Uploader::Base)
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module Responsive
|
2
|
+
# Calculate breakpoints for the given configuration
|
3
|
+
# @private
|
4
|
+
def generate_breakpoints(srcset)
|
5
|
+
return srcset[:breakpoints] if srcset[:breakpoints].is_a? Array
|
6
|
+
min_width, max_width, max_images = [:min_width, :max_width, :max_images].map {|k| srcset[k]}
|
7
|
+
unless [min_width, max_width, max_images].all? {|a| a.is_a? Numeric}
|
8
|
+
throw 'Either (min_width, max_width, max_images) or breakpoints must be provided to the image srcset attribute'
|
9
|
+
end
|
10
|
+
if min_width > max_width
|
11
|
+
throw 'min_width must be less than max_width'
|
12
|
+
end
|
13
|
+
|
14
|
+
if max_images <= 0
|
15
|
+
throw 'max_images must be a positive integer'
|
16
|
+
elsif max_images === 1
|
17
|
+
min_width = max_width
|
18
|
+
end
|
19
|
+
step_size = ((max_width - min_width).to_f / [max_images - 1, 1].max).ceil
|
20
|
+
current = min_width
|
21
|
+
breakpoints = []
|
22
|
+
while current < max_width do
|
23
|
+
breakpoints.push(current)
|
24
|
+
current += step_size
|
25
|
+
end
|
26
|
+
breakpoints.push(max_width)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Generate the srcset and sizes attributes
|
30
|
+
# @private
|
31
|
+
def generate_image_responsive_attributes(public_id, attributes = {}, srcset_data = {}, options = {})
|
32
|
+
# Create both srcset and sizes here to avoid fetching breakpoints twice
|
33
|
+
|
34
|
+
responsive_attributes = {}
|
35
|
+
generate_srcset = !attributes[:srcset]
|
36
|
+
|
37
|
+
if srcset_data.empty?
|
38
|
+
return responsive_attributes
|
39
|
+
elsif srcset_data.is_a? String
|
40
|
+
responsive_attributes[:srcset] = srcset_data
|
41
|
+
return responsive_attributes
|
42
|
+
end
|
43
|
+
|
44
|
+
generate_sizes = !attributes[:sizes] && srcset_data[:sizes]
|
45
|
+
|
46
|
+
if generate_srcset || generate_sizes
|
47
|
+
breakpoints = get_or_generate_breakpoints(public_id, srcset_data, options)
|
48
|
+
|
49
|
+
if generate_srcset
|
50
|
+
transformation = srcset_data[:transformation]
|
51
|
+
srcset_attr = generate_srcset_attribute(public_id, breakpoints, transformation, options)
|
52
|
+
responsive_attributes[:srcset] = srcset_attr unless srcset_attr.empty?
|
53
|
+
end
|
54
|
+
|
55
|
+
if generate_sizes
|
56
|
+
sizes_attr = generate_sizes_attribute(breakpoints)
|
57
|
+
responsive_attributes[:sizes] = sizes_attr unless sizes_attr.empty?
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
responsive_attributes
|
62
|
+
end
|
63
|
+
|
64
|
+
# If cache is enabled, get the breakpoints from the cache. If the values were not found in the cache,
|
65
|
+
# or cache is not enabled, generate the values.
|
66
|
+
# @private
|
67
|
+
def get_or_generate_breakpoints(public_id, srcset, options)
|
68
|
+
if srcset[:use_cache]
|
69
|
+
Cloudinary::Cache.get(public_id, options) || []
|
70
|
+
else
|
71
|
+
generate_breakpoints(srcset)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Generate a resource URL scaled to the given width
|
76
|
+
# @private
|
77
|
+
def generate_scaled_url(public_id, width, transformation={}, options={})
|
78
|
+
config_params = Cloudinary::Utils.extract_config_params(options)
|
79
|
+
transformation ||= options
|
80
|
+
config_params[:raw_transformation] = Cloudinary::Utils.generate_transformation_string(
|
81
|
+
[transformation.clone, {:crop => 'scale', :width => width}].reject(&:blank?))
|
82
|
+
config_params.delete :width
|
83
|
+
config_params.delete :height
|
84
|
+
Cloudinary::Utils.cloudinary_url public_id, config_params
|
85
|
+
end
|
86
|
+
|
87
|
+
# Generate srcset attribute value of the HTML img tag
|
88
|
+
# @private
|
89
|
+
def generate_srcset_attribute(public_id, breakpoints, transformation={}, options={})
|
90
|
+
options = options.clone
|
91
|
+
Cloudinary::Utils.patch_fetch_format(options)
|
92
|
+
breakpoints.map{|width| "#{generate_scaled_url(public_id, width, transformation, options)} #{width}w"}.join(', ').html_safe
|
93
|
+
end
|
94
|
+
|
95
|
+
# Generate media attribute value of the HTML img tag
|
96
|
+
# @private
|
97
|
+
def generate_media_attribute(options)
|
98
|
+
options ||= {}
|
99
|
+
[:min_width, :max_width]
|
100
|
+
.select {|name| options[name]}
|
101
|
+
.map {|name| "(#{name.to_s.tr('_', '-')}: #{options[name]}px)"}
|
102
|
+
.join(' and ').html_safe
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
# Generate the sizes attribute
|
107
|
+
# @private
|
108
|
+
def generate_sizes_attribute(breakpoints)
|
109
|
+
breakpoints.map{|width| "(max-width: #{width}px) #{width}px"}.join(', ')
|
110
|
+
end
|
111
|
+
end
|