jekyll-plugin-gkpicturetag 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/jekyll-plugin-gkpicturetag.gemspec +3 -3
- data/lib/jekyll-plugin-gkpicturetag.rb +314 -24
- data/lib/jekyll-plugin-gkpicturetag/version.rb +2 -2
- metadata +9 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6456d425d3a46b6a0318141fe1dc6a0feb5765c636726b418f75e9af6a14ccbc
|
4
|
+
data.tar.gz: 1be4f0d907512fd5bea95ce947188fd7844e737bcd207e3b091a0875c3d18c6a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 99ba2898d00e080a5047c643ab8305f668a67c83241dca10914685455a1f309cdaa472562cba4d019e21082e3c5bd61b9d8f6525dd4e919983a18d8e793e17c0
|
7
|
+
data.tar.gz: 25c6cfed8bd2747b671dfb568e154df6e36a7d9e4cc7465f7d0b1237a5d261f67018d22905d66aefb748c3a4892852cca66a788b92fb982b81f4a96cbf91081b
|
@@ -5,7 +5,7 @@ require 'jekyll-plugin-gkpicturetag/version'
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "jekyll-plugin-gkpicturetag"
|
8
|
-
spec.version = Jekyll::
|
8
|
+
spec.version = Jekyll::Picture::VERSION
|
9
9
|
spec.authors = ["@glueckkanja"]
|
10
10
|
spec.email = ["info@glueckkanja.com"]
|
11
11
|
|
@@ -17,8 +17,8 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.require_paths = ["lib"]
|
18
18
|
|
19
19
|
spec.add_dependency 'jekyll', '~> 3.7'
|
20
|
-
spec.add_dependency 'fastimage'
|
21
|
-
spec.add_dependency 'mini_magick'
|
20
|
+
spec.add_dependency 'fastimage', '~> 2.1'
|
21
|
+
spec.add_dependency 'mini_magick', '~> 4.8'
|
22
22
|
|
23
23
|
spec.add_development_dependency "bundler", "~> 1.12"
|
24
24
|
spec.add_development_dependency "rake", "~> 10.0"
|
@@ -1,31 +1,321 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
# Title: Jekyll Picture Tag // changed by GK
|
2
|
+
# Downloaded 2018-01-18 last changed btobolaski committed on Oct 30, 2015
|
3
|
+
# Original Authors: Rob Wierzbowski : @robwierzbowski
|
4
|
+
# Justin Reese : @justinxreese
|
5
|
+
# Welch Canavan : @xiwcx
|
6
|
+
#
|
7
|
+
# Description: Easy responsive images for Jekyll.
|
8
|
+
#
|
9
|
+
# Download: https://github.com/robwierzbowski/jekyll-picture-tag
|
10
|
+
# Documentation: https://github.com/robwierzbowski/jekyll-picture-tag/readme.md
|
11
|
+
# Issues: https://github.com/robwierzbowski/jekyll-picture-tag/issues
|
12
|
+
#
|
13
|
+
# Syntax: {% picture [preset] path/to/img.jpg [source_key: path/to/alt-img.jpg] [attr="value"] %}
|
14
|
+
# Example: {% picture poster.jpg alt="The strange case of responsive images" %}
|
15
|
+
# {% picture gallery poster.jpg source_small: poster_closeup.jpg
|
16
|
+
# alt="The strange case of responsive images" class="gal-img" data-selected %}
|
17
|
+
#
|
18
|
+
# See the documentation for full configuration and usage instructions.
|
4
19
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
20
|
+
require 'fileutils'
|
21
|
+
require 'pathname'
|
22
|
+
require 'digest/md5'
|
23
|
+
require 'mini_magick'
|
24
|
+
require 'fastimage'
|
25
|
+
|
26
|
+
module Jekyll
|
9
27
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
@
|
14
|
-
|
15
|
-
# Regex from # http://stackoverflow.com/questions/3452546/javascript-regex-how-to-get-youtube-video-id-from-url/4811367#4811367
|
16
|
-
youtube_url[/^.*((v\/)|(embed\/)|(watch\?))\??v?=?([^\&\?]*).*/]
|
17
|
-
@youtube_id = $5
|
28
|
+
class Picture < Liquid::Tag
|
29
|
+
|
30
|
+
def initialize(tag_name, markup, tokens)
|
31
|
+
@markup = markup
|
32
|
+
super
|
18
33
|
end
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
34
|
+
|
35
|
+
def render(context)
|
36
|
+
|
37
|
+
# Render any liquid variables in tag arguments and unescape template code
|
38
|
+
render_markup = Liquid::Template.parse(@markup).render(context).gsub(/\\\{\\\{|\\\{\\%/, '\{\{' => '{{', '\{\%' => '{%')
|
39
|
+
|
40
|
+
# Gather settings
|
23
41
|
site = context.registers[:site]
|
24
|
-
|
25
|
-
|
26
|
-
|
42
|
+
debug = site.config['debug']
|
43
|
+
settings = site.config['picture']
|
44
|
+
url = site.config['url']
|
45
|
+
markup = /^(?:(?<preset>[^\s.:\/]+)\s+)?(?<image_src>[^\s]+\.[a-zA-Z0-9]{3,4})\s*(?<source_src>(?:(source_[^\s.:\/]+:\s+[^\s]+\.[a-zA-Z0-9]{3,4})\s*)+)?(?<html_attr>[\s\S]+)?$/.match(render_markup)
|
46
|
+
preset = settings['presets'][ markup[:preset] ] || settings['presets']['default']
|
47
|
+
|
48
|
+
raise "Picture Tag can't read this tag. Try {% picture [preset] path/to/img.jpg [source_key: path/to/alt-img.jpg] [attr=\"value\"] %}." unless markup
|
49
|
+
|
50
|
+
# Assign defaults
|
51
|
+
settings['source'] ||= '.'
|
52
|
+
settings['output'] ||= 'generated'
|
53
|
+
settings['markup'] ||= 'picture'
|
54
|
+
|
55
|
+
# Prevent Jekyll from erasing our generated files
|
56
|
+
site.config['keep_files'] << settings['output'] unless site.config['keep_files'].include?(settings['output'])
|
57
|
+
|
58
|
+
# Deep copy preset for single instance manipulation
|
59
|
+
instance = Marshal.load(Marshal.dump(preset))
|
60
|
+
|
61
|
+
# Process alternate source images
|
62
|
+
source_src = if markup[:source_src]
|
63
|
+
Hash[ *markup[:source_src].gsub(/:/, '').split ]
|
64
|
+
else
|
65
|
+
{}
|
66
|
+
end
|
67
|
+
|
68
|
+
# Process html attributes
|
69
|
+
html_attr = if markup[:html_attr]
|
70
|
+
Hash[ *markup[:html_attr].scan(/(?<attr>[^\s="]+)(?:="(?<value>[^"]+)")?\s?/).flatten ]
|
71
|
+
else
|
72
|
+
{}
|
73
|
+
end
|
74
|
+
|
75
|
+
if instance['attr']
|
76
|
+
html_attr = instance.delete('attr').merge(html_attr)
|
77
|
+
end
|
78
|
+
|
79
|
+
html_attr_string = html_attr.inject('') { |string, attrs|
|
80
|
+
if attrs[1]
|
81
|
+
string << "#{attrs[0]}=\"#{attrs[1]}\" "
|
82
|
+
else
|
83
|
+
string << "#{attrs[0]} "
|
84
|
+
end
|
85
|
+
}
|
86
|
+
|
87
|
+
# Prepare ppi variables
|
88
|
+
ppi = if instance['ppi'] then instance.delete('ppi').sort.reverse else nil end
|
89
|
+
# this might work??? ppi = instance.delete('ppi'){ |ppi| [nil] }.sort.reverse
|
90
|
+
ppi_sources = {}
|
91
|
+
|
92
|
+
# Switch width and height keys to the symbols that generate_image() expects
|
93
|
+
begin
|
94
|
+
instance.each { |key, source|
|
95
|
+
# raise "Preset #{key} is missing a width or a height" if !source['width'] and !source['height']
|
96
|
+
instance[key][:width] = instance[key].delete('width') / 2 if source['width']
|
97
|
+
instance[key][:height] = instance[key].delete('height') / 2 if source['height']
|
98
|
+
}
|
99
|
+
rescue
|
100
|
+
# warn "Info (Picture-Tag): ".yellow + "No width and height. Take original size."
|
101
|
+
end
|
102
|
+
|
103
|
+
# Store keys in an array for ordering the instance sources
|
104
|
+
source_keys = instance.keys
|
105
|
+
# used to escape markdown parsing rendering below
|
106
|
+
markdown_escape = "\ "
|
107
|
+
|
108
|
+
# Raise some exceptions before we start expensive processing
|
109
|
+
raise "Picture Tag can't find the \"#{markup[:preset]}\" preset. Check picture: presets in _config.yml for a list of presets." unless preset
|
110
|
+
raise "Picture Tag can't find this preset source. Check picture: presets: #{markup[:preset]} in _config.yml for a list of sources." unless (source_src.keys - source_keys).empty?
|
111
|
+
|
112
|
+
# Process instance
|
113
|
+
# Add image paths for each source
|
114
|
+
instance.each_key { |key|
|
115
|
+
instance[key][:src] = source_src[key] || markup[:image_src]
|
116
|
+
}
|
117
|
+
|
118
|
+
# Construct ppi sources
|
119
|
+
# Generates -webkit-device-ratio and resolution: dpi media value for cross browser support
|
120
|
+
# Reference: http://www.brettjankord.com/2012/11/28/cross-browser-retinahigh-resolution-media-queries/
|
121
|
+
if ppi
|
122
|
+
instance.each { |key, source|
|
123
|
+
ppi.each { |p|
|
124
|
+
if p != 1
|
125
|
+
ppi_key = "#{key}-x#{p}"
|
126
|
+
|
127
|
+
ppi_sources[ppi_key] = {
|
128
|
+
:width => if source[:width] then (source[:width].to_f * p).round else nil end,
|
129
|
+
:height => if source[:height] then (source[:height].to_f * p).round else nil end,
|
130
|
+
'media' => if source['media']
|
131
|
+
"#{source['media']} and (-webkit-min-device-pixel-ratio: #{p}), #{source['media']} and (min-resolution: #{(p * 96).round}dpi)"
|
132
|
+
else
|
133
|
+
"(-webkit-min-device-pixel-ratio: #{p}), (min-resolution: #{(p * 96).to_i}dpi)"
|
134
|
+
end,
|
135
|
+
:src => source[:src]
|
136
|
+
}
|
137
|
+
|
138
|
+
# Add ppi_key to the source keys order
|
139
|
+
source_keys.insert(source_keys.index(key), ppi_key)
|
140
|
+
end
|
141
|
+
}
|
142
|
+
}
|
143
|
+
instance.merge!(ppi_sources)
|
144
|
+
end
|
145
|
+
|
146
|
+
# Generate resized images
|
147
|
+
instance.each { |key, source|
|
148
|
+
instance[key][:generated_src] = generate_image(source, site.source, site.dest, settings['source'], settings['output'], site.config["baseurl"], debug)
|
149
|
+
instance[key][:generated2x_src] = generate_image2x(source, site.source, site.dest, settings['source'], settings['output'], site.config["baseurl"], debug)
|
150
|
+
}
|
151
|
+
|
152
|
+
# Construct and return tag
|
153
|
+
source_tags = ''
|
154
|
+
source_keys.each do |source|
|
155
|
+
warn "Info (Picture-Tag): ".yellow + "" + instance[source][:generated_src].to_s.green + "\n | ".yellow + instance[source][:generated2x_src].to_s.blue if debug
|
156
|
+
media = " media=\"#{instance[source]['media']}\"" unless source == 'source_default'
|
157
|
+
source_tags += "#{markdown_escape * 4}<source srcset=\"#{instance[source][:generated_src]}, #{instance[source][:generated2x_src]} 2x\"#{media}>\n"
|
158
|
+
end
|
159
|
+
|
160
|
+
# Note: we can't indent html output because markdown parsers will turn 4 spaces into code blocks
|
161
|
+
# Note: Added backslash+space escapes to bypass markdown parsing of indented code below -WD
|
162
|
+
picture_tag = "<picture>\n"\
|
163
|
+
"#{source_tags}"\
|
164
|
+
"#{markdown_escape * 4}<img src=\"#{instance['source_default'][:generated_src]}\" #{html_attr_string}>\n"\
|
165
|
+
"#{markdown_escape * 2}</picture>\n"
|
166
|
+
|
167
|
+
# Return the markup!
|
168
|
+
picture_tag
|
169
|
+
end
|
170
|
+
|
171
|
+
# <picture class="img-responsive">
|
172
|
+
# <source srcset="/img/illus/home-future-workplace.jpg, /img/illus/home-future-workplace@2x.jpg 2x">
|
173
|
+
# <img class="img-responsive" src="/img/illus/home-future-workplace.jpg" alt="Future Workplace">
|
174
|
+
# </picture>
|
175
|
+
|
176
|
+
def generate_image(instance, site_source, site_dest, image_source, image_dest, baseurl, debug)
|
177
|
+
begin
|
178
|
+
digest = Digest::MD5.hexdigest(File.read(File.join(site_source, image_source, instance[:src]))).slice!(0..5)
|
179
|
+
rescue Errno::ENOENT
|
180
|
+
warn "Warning:".yellow + " source image #{instance[:src]} is missing."
|
181
|
+
return ""
|
182
|
+
end
|
183
|
+
|
184
|
+
image_dir = File.dirname(instance[:src])
|
185
|
+
ext = File.extname(instance[:src])
|
186
|
+
basename = File.basename(instance[:src], ext)
|
187
|
+
|
188
|
+
size = FastImage.size(File.join(site_source, image_source, instance[:src]))
|
189
|
+
orig_width = size[0]
|
190
|
+
orig_height = size[1]
|
191
|
+
orig_ratio = orig_width*1.0/orig_height
|
192
|
+
|
193
|
+
gen_width = if instance[:width]
|
194
|
+
instance[:width].to_f
|
195
|
+
elsif instance[:height]
|
196
|
+
orig_ratio * instance[:height].to_f
|
197
|
+
else
|
198
|
+
orig_width
|
199
|
+
end
|
200
|
+
gen_height = if instance[:height]
|
201
|
+
instance[:height].to_f
|
202
|
+
elsif instance[:width]
|
203
|
+
instance[:width].to_f / orig_ratio
|
204
|
+
else
|
205
|
+
orig_height
|
206
|
+
end
|
207
|
+
gen_ratio = gen_width/gen_height
|
208
|
+
|
209
|
+
# Don't allow upscaling. If the image is smaller than the requested dimensions, recalculate.
|
210
|
+
if orig_width < gen_width || orig_height < gen_height
|
211
|
+
undersize = true
|
212
|
+
gen_width = if orig_ratio < gen_ratio then orig_width else orig_height * gen_ratio end
|
213
|
+
gen_height = if orig_ratio > gen_ratio then orig_height else orig_width/gen_ratio end
|
214
|
+
end
|
215
|
+
|
216
|
+
gen_width = gen_width / 2
|
217
|
+
gen_height = gen_height / 2
|
218
|
+
|
219
|
+
gen_name = "#{basename}-#{gen_width.round}by#{gen_height.round}-#{digest}#{ext}"
|
220
|
+
gen_dest_dir = File.join(site_dest, image_dest, image_dir)
|
221
|
+
gen_dest_file = File.join(gen_dest_dir, gen_name)
|
222
|
+
|
223
|
+
# Generate resized files
|
224
|
+
unless File.exists?(gen_dest_file)
|
225
|
+
|
226
|
+
warn "Warning:".yellow + " #{instance[:src]} is smaller than the requested output file. It will be resized without upscaling." if undersize
|
227
|
+
|
228
|
+
# If the destination directory doesn't exist, create it
|
229
|
+
FileUtils.mkdir_p(gen_dest_dir) unless File.exist?(gen_dest_dir)
|
230
|
+
|
231
|
+
# Let people know their images are being generated
|
232
|
+
puts "Generating #{gen_name}" if !debug
|
233
|
+
|
234
|
+
image = MiniMagick::Image.open(File.join(site_source, image_source, instance[:src]))
|
235
|
+
# Scale and crop
|
236
|
+
image.combine_options do |i|
|
237
|
+
i.resize "#{gen_width}x#{gen_height}^"
|
238
|
+
i.gravity "center"
|
239
|
+
i.crop "#{gen_width}x#{gen_height}+0+0"
|
240
|
+
end
|
241
|
+
|
242
|
+
image.write gen_dest_file
|
243
|
+
end
|
244
|
+
|
245
|
+
# Return path relative to the site root for html
|
246
|
+
Pathname.new(File.join(baseurl, image_dest, image_dir, gen_name)).cleanpath
|
247
|
+
end
|
248
|
+
|
249
|
+
def generate_image2x(instance, site_source, site_dest, image_source, image_dest, baseurl, debug)
|
250
|
+
begin
|
251
|
+
digest = Digest::MD5.hexdigest(File.read(File.join(site_source, image_source, instance[:src]))).slice!(0..5)
|
252
|
+
rescue Errno::ENOENT
|
253
|
+
warn "Warning:".yellow + " source image #{instance[:src]} is missing."
|
254
|
+
return ""
|
255
|
+
end
|
256
|
+
|
257
|
+
image_dir = File.dirname(instance[:src])
|
258
|
+
ext = File.extname(instance[:src])
|
259
|
+
basename = File.basename(instance[:src], ext)
|
260
|
+
|
261
|
+
size = FastImage.size(File.join(site_source, image_source, instance[:src]))
|
262
|
+
orig_width = size[0]
|
263
|
+
orig_height = size[1]
|
264
|
+
orig_ratio = orig_width*1.0/orig_height
|
265
|
+
|
266
|
+
gen_width = if instance[:width]
|
267
|
+
instance[:width].to_f
|
268
|
+
elsif instance[:height]
|
269
|
+
orig_ratio * instance[:height].to_f
|
270
|
+
else
|
271
|
+
orig_width
|
272
|
+
end
|
273
|
+
gen_height = if instance[:height]
|
274
|
+
instance[:height].to_f
|
275
|
+
elsif instance[:width]
|
276
|
+
instance[:width].to_f / orig_ratio
|
277
|
+
else
|
278
|
+
orig_height
|
279
|
+
end
|
280
|
+
gen_ratio = gen_width/gen_height
|
281
|
+
|
282
|
+
# Don't allow upscaling. If the image is smaller than the requested dimensions, recalculate.
|
283
|
+
if orig_width < gen_width || orig_height < gen_height
|
284
|
+
undersize = true
|
285
|
+
gen_width = if orig_ratio < gen_ratio then orig_width else orig_height * gen_ratio end
|
286
|
+
gen_height = if orig_ratio > gen_ratio then orig_height else orig_width/gen_ratio end
|
287
|
+
end
|
288
|
+
|
289
|
+
gen_name = "#{basename}-#{gen_width.round}by#{gen_height.round}-#{digest}#{ext}"
|
290
|
+
gen_dest_dir = File.join(site_dest, image_dest, image_dir)
|
291
|
+
gen_dest_file = File.join(gen_dest_dir, gen_name)
|
292
|
+
|
293
|
+
# Generate resized files
|
294
|
+
unless File.exists?(gen_dest_file)
|
295
|
+
|
296
|
+
warn "Warning:".yellow + " #{instance[:src]} is smaller than the requested output file. It will be resized without upscaling." if undersize
|
297
|
+
|
298
|
+
# If the destination directory doesn't exist, create it
|
299
|
+
FileUtils.mkdir_p(gen_dest_dir) unless File.exist?(gen_dest_dir)
|
300
|
+
|
301
|
+
# Let people know their images are being generated
|
302
|
+
puts "Generating #{gen_name}" if !debug
|
303
|
+
|
304
|
+
image = MiniMagick::Image.open(File.join(site_source, image_source, instance[:src]))
|
305
|
+
# Scale and crop
|
306
|
+
image.combine_options do |i|
|
307
|
+
i.resize "#{gen_width}x#{gen_height}^"
|
308
|
+
i.gravity "center"
|
309
|
+
i.crop "#{gen_width}x#{gen_height}+0+0"
|
310
|
+
end
|
311
|
+
|
312
|
+
image.write gen_dest_file
|
313
|
+
end
|
314
|
+
|
315
|
+
# Return path relative to the site root for html
|
316
|
+
Pathname.new(File.join(baseurl, image_dest, image_dir, gen_name)).cleanpath
|
27
317
|
end
|
28
318
|
end
|
319
|
+
end
|
29
320
|
|
30
|
-
|
31
|
-
end
|
321
|
+
Liquid::Template.register_tag('picture', Jekyll::Picture)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jekyll-plugin-gkpicturetag
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- "@glueckkanja"
|
@@ -28,30 +28,30 @@ dependencies:
|
|
28
28
|
name: fastimage
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '2.1'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '2.1'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: mini_magick
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '4.8'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '4.8'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: bundler
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|