This repository was archived by the owner on Sep 23, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathtag.rb
119 lines (97 loc) · 3.68 KB
/
tag.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
require "rmagick"
require "digest/sha1"
module Jekyll
class SrcsetTag < Liquid::Tag
include Magick
attr_accessor :markup
def self.optipng?
@optinpng ||= system("which optipng")
end
def initialize(tag_name, markup, _)
@markup = markup
super
end
def render(context)
options = parse_options(markup, context)
return "Bad options to image_tag, syntax is: {% image_tag src=\"image.png\" width=\"100\"}" unless options["src"]
return "Error resizing - can't set both width and height" if options["width"] && options["height"]
site = context.registers[:site]
img_attrs = generate_image(site, options["src"], options)
srcset = []
(1..3).each do |factor|
srcset << {:factor => factor, :img => generate_image(site, options["src"], options.merge("factor" => factor))}
end
img_attrs["srcset"] = srcset.map {|i| "#{i[:img]["src"]} #{i[:factor]}x"}.join(", ")
"<img #{options.merge(img_attrs).map {|k,v| "#{k}=\"#{v}\""}.join(" ")}>"
end
def parse_options(markup, context)
options = {}
markup.scan(/(\w+)=((?:"[^"]+")|(?:'[^']+')|[\w\.\_-]+)/) do |key,value|
if (value[0..0] == "'" && value[-1..-1]) == "'" || (value[0..0] == '"' && value[-1..-1] == '"')
options[key] = value[1..-2]
else
options[key] = context[value]
end
end
options
end
def config(site)
site.config['srcset'] || {}
end
def optimize?(site)
config(site)['optipng']
end
def cache_dir(site)
config(site)['cache']
end
def generate_image(site, src, attrs)
cache = cache_dir(site)
sha = cache && Digest::SHA1.hexdigest(attrs.sort.inspect + File.read(File.join(site.source, src)) + (optimize?(site) ? "optimize" : ""))
if sha
if File.exists?(File.join(cache, sha))
img_attrs = JSON.parse(File.read(File.join(cache,sha,"json")))
filename = img_attrs["src"].sub(/^\//, '')
dest = File.join(site.dest, filename)
FileUtils.mkdir_p(File.dirname(dest))
FileUtils.cp(File.join(cache,sha,"img"), dest)
site.config['keep_files'] << filename unless site.config['keep_files'].include?(filename)
return img_attrs
end
end
img = Image.read(File.join(site.source, src)).first
img_attrs = {}
if attrs["height"]
scale = attrs["height"].to_f * (attrs["factor"] || 1) / img.rows.to_f
elsif attrs["width"]
scale = attrs["width"].to_f * (attrs["factor"] || 1) / img.columns.to_f
else
scale = attrs["factor"] || 1
end
img_attrs["height"] = attrs["height"] if attrs["height"]
img_attrs["width"] = attrs["width"] if attrs["width"]
img_attrs["src"] = src.sub(/(\.\w+)$/, "-#{img.columns}x#{img.rows}" + '\1')
filename = img_attrs["src"].sub(/^\//, '')
dest = File.join(site.dest, filename)
FileUtils.mkdir_p(File.dirname(dest))
unless File.exist?(dest)
img.scale!(scale) if scale <= 1
img.strip!
img.write(dest)
if dest.match(/\.png$/) && optimize?(site) && self.class.optipng?
`optipng #{dest}`
end
end
site.config['keep_files'] << filename unless site.config['keep_files'].include?(filename)
# Keep files around for incremental builds in Jekyll 3
site.regenerator.add(filename) if site.respond_to?(:regenerator)
if sha
FileUtils.mkdir_p(File.join(cache, sha))
FileUtils.cp(dest, File.join(cache, sha, "img"))
File.open(File.join(cache, sha, "json"), "w") do |f|
f.write(JSON.generate(img_attrs))
end
end
img_attrs
end
end
end