Class: Jekyll::SrcsetTag

Inherits:
Liquid::Tag
  • Object
show all
Includes:
Magick
Defined in:
lib/jekyll/srcset/tag.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(tag_name, markup, _) ⇒ SrcsetTag

Returns a new instance of SrcsetTag.



13
14
15
16
# File 'lib/jekyll/srcset/tag.rb', line 13

def initialize(tag_name, markup, _)
  @markup = markup
  super
end

Instance Attribute Details

#markupObject

Returns the value of attribute markup.



7
8
9
# File 'lib/jekyll/srcset/tag.rb', line 7

def markup
  @markup
end

Class Method Details

.optipng?Boolean

Returns:

  • (Boolean)


9
10
11
# File 'lib/jekyll/srcset/tag.rb', line 9

def self.optipng?
  @optinpng ||= system("which optipng")
end

Instance Method Details

#cache_dir(site) ⇒ Object



56
57
58
# File 'lib/jekyll/srcset/tag.rb', line 56

def cache_dir(site)
  config(site)['cache']
end

#config(site) ⇒ Object



48
49
50
# File 'lib/jekyll/srcset/tag.rb', line 48

def config(site)
  site.config['srcset'] || {}
end

#generate_image(site, src, attrs) ⇒ Object



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
# File 'lib/jekyll/srcset/tag.rb', line 60

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

#optimize?(site) ⇒ Boolean

Returns:

  • (Boolean)


52
53
54
# File 'lib/jekyll/srcset/tag.rb', line 52

def optimize?(site)
  config(site)['optipng']
end

#parse_options(markup, context) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
# File 'lib/jekyll/srcset/tag.rb', line 36

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

#render(context) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/jekyll/srcset/tag.rb', line 18

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