jekyll-plugin-gkpicturetag 0.4.0 → 0.5.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 +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
|