jekyll-cloudinary 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a3cc2859c5c4fea6e38e98866189e0bbb97b49c5
4
+ data.tar.gz: 68e5e29e4c1af56b889e300183c749cd899197cd
5
+ SHA512:
6
+ metadata.gz: 1b6e1b313d511dddd19db4cc105649f696abce40a3e7efb25d272d8b33840d38bc1ff2ac2480ffc9ab6cd6fe3000e000f46727bf8b7260111df7ca2bcb898105
7
+ data.tar.gz: 10e9f60d5cbf6862dcd543bc7b24f8fd8f7989bb8484a6fa2ae86ce1c1faac0a175cc9f5712eb96e6214b94b7d9a84d383f566ed25f19f4cb12598e25ef1c616
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in jekyll-post-files.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Nicolas Hoizey
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # jekyll-cloudinary
2
+
3
+ Liquid tag for Jekyll to use Cloudinary for optimized responsive posts images.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
@@ -0,0 +1 @@
1
+ require "jekyll/cloudinary"
@@ -0,0 +1,179 @@
1
+ =begin
2
+ Liquid tag to use Cloudinary for optimized responsive posts images.
3
+ Usage:
4
+ {% cloudinary [preset] path/to/img.jpg [attr="value"] %}
5
+ Examples:
6
+ {% cloudinary image1.jpg alt="alternate" %}
7
+ {% cloudinary onethird image2.jpg alt="other" title="yet another one" %}
8
+
9
+ Configuration
10
+ In _config.yml:
11
+
12
+ cloudinary:
13
+ api_id: …
14
+ auto: true
15
+ verbose: true
16
+ presets:
17
+ default:
18
+ min_size: 320
19
+ max_size: 1600
20
+ steps: 5
21
+ sizes: "(min-width: 50rem) 50rem, 90vw"
22
+ attributes:
23
+ class: onethird
24
+
25
+ =end
26
+ module Jekyll
27
+ module Cloudinary
28
+
29
+ class CloudinaryTag < Liquid::Tag
30
+ # priority :normal
31
+
32
+ require "RMagick"
33
+
34
+ def initialize(tag_name, markup, tokens)
35
+ @markup = markup
36
+ super
37
+ end
38
+
39
+ def render(context)
40
+
41
+ # Default settings
42
+ preset_defaults = {
43
+ "min_width" => 320,
44
+ "max_width" => 1200,
45
+ "steps" => 5,
46
+ "sizes" => "100vw",
47
+ "caption" => "auto",
48
+ "attributes" => { },
49
+ "verbose" => false
50
+ }
51
+
52
+ # Settings
53
+ site = context.registers[:site]
54
+ url = site.config['url']
55
+ settings = site.config['cloudinary']
56
+
57
+ preset_user_defaults = {}
58
+ if settings['presets']
59
+ if settings['presets']['default']
60
+ preset_user_defaults = settings['presets']['default']
61
+ end
62
+ end
63
+
64
+ preset = preset_defaults.merge(preset_user_defaults)
65
+
66
+ # Render any liquid variables in tag arguments and unescape template code
67
+ rendered_markup = Liquid::Template.parse(@markup).render(context).gsub(/\\\{\\\{|\\\{\\%/, '\{\{' => '{{', '\{\%' => '{%')
68
+
69
+ # Extract tag segments
70
+ markup = /^(?:(?<preset>[^\s.:\/]+)\s+)?(?<image_src>[^\s]+\.[a-zA-Z0-9]{3,4})\s*(?<html_attr>[\s\S]+)?$/.match(rendered_markup)
71
+ raise "Cloudinary can't read this tag. Try {% cloudinary [preset] path/to/img.jpg [attr=\"value\"] %}." unless markup
72
+
73
+ image_src = markup[:image_src]
74
+
75
+ # Build source image URL
76
+ is_image_path_absolute = /^\/.*$/.match(image_src)
77
+ if is_image_path_absolute
78
+ image_path = File.join(site.config['destination'], image_src)
79
+ image_url = File.join(url, image_src)
80
+ else
81
+ image_path = File.join(site.config['destination'], File.dirname(context['page'].url), image_src)
82
+ image_url = File.join(url, File.dirname(context['page'].url), image_src)
83
+ end
84
+
85
+ # Get source image natural width
86
+ image = Magick::Image::read(image_path).first
87
+ natural_width = image.columns
88
+
89
+ if markup[:preset]
90
+ if settings['presets'][markup[:preset]]
91
+ preset = preset.merge(settings['presets'][markup[:preset]])
92
+ else
93
+ if settings['verbose']
94
+ puts "\n[Cloudinary] '#{markup[:preset]}' preset for the Cloudinary plugin doesn't exist in _config.yml, using the default one"
95
+ end
96
+ end
97
+ end
98
+
99
+ attributes = preset['attributes']
100
+
101
+ # Deep copy preset for single instance manipulation
102
+ instance = Marshal.load(Marshal.dump(preset))
103
+
104
+ # Process attributes
105
+ html_attr = if markup[:html_attr]
106
+ Hash[ *markup[:html_attr].scan(/(?<attr>[^\s="]+)(?:="(?<value>[^"]+)")?\s?/).flatten ]
107
+ else
108
+ {}
109
+ end
110
+
111
+ if instance['attr']
112
+ html_attr = instance.delete('attr').merge(html_attr)
113
+ end
114
+
115
+ # Classes from the tag should complete, not replace, the ones from the preset
116
+ if html_attr['class'] && attributes['class']
117
+ html_attr['class'] << " #{attributes['class']}"
118
+ end
119
+ html_attr = attributes.merge(html_attr)
120
+
121
+ # Deal with the "caption" attribute as a true <figcaption>
122
+ if html_attr['caption']
123
+ caption = html_attr['caption']
124
+ html_attr.delete('caption')
125
+ end
126
+
127
+ # alt and title attributes should go only to the <img> even when there is a caption
128
+ img_attr = ""
129
+ if html_attr['alt']
130
+ img_attr << " alt=\"#{html_attr['alt']}\""
131
+ html_attr.delete('alt')
132
+ end
133
+ if html_attr['title']
134
+ img_attr << " title=\"#{html_attr['title']}\""
135
+ html_attr.delete('title')
136
+ end
137
+
138
+ attr_string = html_attr.map { |a,v| "#{a}=\"#{v}\"" }.join(' ')
139
+
140
+ srcset = []
141
+ steps = preset['steps'].to_i
142
+ min_width = preset['min_width'].to_i
143
+ max_width = preset['max_width'].to_i
144
+ step_width = (max_width - min_width) / steps
145
+ sizes = preset['sizes']
146
+
147
+ if natural_width < min_width
148
+ if settings['verbose']
149
+ puts "[Cloudinary] Natural width of source image '#{File.basename(image_src)}' (#{natural_width}px) in #{context['page'].path} not enough for creating any srcset version"
150
+ end
151
+ srcset << "http://res.cloudinary.com/#{settings['api_id']}/image/fetch/q_auto,f_auto/#{image_url} #{natural_width}w"
152
+ else
153
+ (0..steps).each do |factor|
154
+ width = min_width + factor * step_width
155
+ if width <= natural_width
156
+ srcset << "http://res.cloudinary.com/#{settings['api_id']}/image/fetch/c_scale,w_#{width},q_auto,f_auto/#{image_url} #{width}w"
157
+ else
158
+ if settings['verbose']
159
+ puts "[Cloudinary] Natural width of source image '#{File.basename(image_src)}' (#{natural_width}px) in #{context['page'].path} not enough for creating #{width}px version"
160
+ end
161
+ end
162
+ end
163
+ end
164
+ srcset_string = srcset.join(",\n")
165
+
166
+ # preset['caption'] can be 'never', 'auto' or 'always'
167
+ if (caption || preset['caption'] == 'always') && preset['caption'] != 'never'
168
+ "\n<figure #{attr_string}>\n<img src=\"#{image_url}\" srcset=\"#{srcset_string}\" sizes=\"#{sizes}\" #{img_attr} />\n<figcaption>#{caption}</figcaption>\n</figure>\n"
169
+ else
170
+ "<img src=\"#{image_url}\" srcset=\"#{srcset_string}\" sizes=\"#{sizes}\" #{attr_string} #{img_attr} />"
171
+ end
172
+ end
173
+ end
174
+
175
+ end
176
+ end
177
+
178
+ Liquid::Template.register_tag('cloudinary', Jekyll::CloudinaryTag)
179
+
@@ -0,0 +1,5 @@
1
+ module Jekyll
2
+ module Cloudinary
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jekyll-cloudinary
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Nicolas Hoizey
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-07-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: jekyll
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ - - "~>"
21
+ - !ruby/object:Gem::Version
22
+ version: '3.1'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '3.0'
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '3.1'
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.12'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.12'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '10.0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '10.0'
61
+ description: " Liquid tag to use Cloudinary for optimized responsive posts images.\n"
62
+ email:
63
+ - nicolas@hoizey.com
64
+ executables: []
65
+ extensions: []
66
+ extra_rdoc_files: []
67
+ files:
68
+ - Gemfile
69
+ - LICENSE
70
+ - README.md
71
+ - Rakefile
72
+ - lib/jekyll-cloudinary.rb
73
+ - lib/jekyll/cloudinary.rb
74
+ - lib/jekyll/cloudinary/version.rb
75
+ homepage: http://github.com/nhoizey/jekyll-cloudinary/
76
+ licenses:
77
+ - MIT
78
+ metadata: {}
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubyforge_project:
95
+ rubygems_version: 2.6.4
96
+ signing_key:
97
+ specification_version: 4
98
+ summary: Liquid tag for Jekyll with Cloudinary
99
+ test_files: []