class Jekyll::Image

Constants

VERSION

Public Class Methods

new(tag_name, markup, tokens) click to toggle source
Calls superclass method
# File lib/jekyll-plugin-gkimagetag.rb, line 28
def initialize(tag_name, markup, tokens)
  @markup = markup
  super
end

Public Instance Methods

generate_image(instance, site_source, site_dest, image_source, image_dest, debug) click to toggle source
# File lib/jekyll-plugin-gkimagetag.rb, line 115
def generate_image(instance, site_source, site_dest, image_source, image_dest, debug)

  MiniMagick.configure do |config|
    config.whiny = false
  end
  image_source_path = File.join(site_source, image_source, instance[:src])
  unless File.exists?image_source_path
    puts "Missing: #{image_source_path}"
    return false
  end

  image = MiniMagick::Image.open(image_source_path)
  digest = Digest::MD5.hexdigest(image.to_blob).slice!(0..5)

  image_dir = File.dirname(instance[:src])
  ext = File.extname(instance[:src])
  basename = File.basename(instance[:src], ext)

  orig_width = image[:width].to_f
  orig_height = image[:height].to_f
  orig_ratio = orig_width/orig_height

  gen_width = if instance[:width]
    instance[:width].to_f * 2
  elsif instance[:height]
    orig_ratio * instance[:height].to_f * 2
  else
    orig_width
  end
  gen_height = if instance[:height]
    instance[:height].to_f * 2
  elsif instance[:width]
    instance[:width].to_f / orig_ratio * 2
  else
    orig_height
  end
  gen_ratio = gen_width/gen_height

  # Don't allow upscaling. If the image is smaller than the requested dimensions, recalculate.
  if orig_width < gen_width || orig_height < gen_height
    undersize = true
    gen_width = if orig_ratio < gen_ratio then orig_width else orig_height * gen_ratio end
    gen_height = if orig_ratio > gen_ratio then orig_height else orig_width/gen_ratio end
  end

  #2x
  gen_name = "#{basename}-#{gen_width.round}x#{gen_height.round}-#{digest}@2x#{ext}"
  gen_dest_dir = File.join(site_dest, image_dest, image_dir)
  gen_dest_file = File.join(gen_dest_dir, gen_name)

  # Generate resized files
  unless File.exists?(gen_dest_file)

    warn "Warning:".yellow + " #{instance[:src]} is smaller than the requested output file. It will be resized without upscaling." if undersize

    #  If the destination directory doesn't exist, create it
    FileUtils.mkdir_p(gen_dest_dir) unless File.exist?(gen_dest_dir)

    # Let people know their images are being generated
    puts "Generating #{gen_name}" if !debug

    # Scale and crop
    image.combine_options do |i|
      i.resize "#{gen_width}x#{gen_height}^"
      i.gravity "center"
      i.crop "#{gen_width}x#{gen_height}+0+0"
      #i.layers "Optimize"
    end

    image.write gen_dest_file
  end

  #1x
  gen_name = "#{basename}-#{gen_width.round}x#{gen_height.round}-#{digest}#{ext}"
  gen_dest_dir = File.join(site_dest, image_dest, image_dir)
  gen_dest_file = File.join(gen_dest_dir, gen_name)

  gen_width = gen_width / 2
  gen_height = gen_height / 2

  # Generate resized files
  unless File.exists?(gen_dest_file)

    warn "Warning:".yellow + " #{instance[:src]} is smaller than the requested output file. It will be resized without upscaling." if undersize

    #  If the destination directory doesn't exist, create it
    FileUtils.mkdir_p(gen_dest_dir) unless File.exist?(gen_dest_dir)

    # Let people know their images are being generated
    puts "Generating #{gen_name}" if !debug

    # Scale and crop
    image.combine_options do |i|
      i.resize "#{gen_width}x#{gen_height}^"
      i.gravity "center"
      i.crop "#{gen_width}x#{gen_height}+0+0"
      #i.layers "Optimize"
    end

    image.write gen_dest_file
  end

  # Return path relative to the site root for html
  Pathname.new(File.join('/', image_dest, image_dir, gen_name)).cleanpath
end
render(context) click to toggle source
# File lib/jekyll-plugin-gkimagetag.rb, line 33
def render(context)

  # Render any liquid variables in tag arguments and unescape template code
  render_markup = Liquid::Template.parse(@markup).render(context).gsub(/\\\{\\\{|\\\{\\%/, '\{\{' => '{{', '\{\%' => '{%')

  warn "Info (Image-Tag): ".yellow + "" + render_markup.to_s

  # Gather settings
  site = context.registers[:site]
  debug = site.config['debug']
  settings = site.config['image']
  markup = /^(?:(?<preset>[^\s.:\/]+)\s+)?(?<image_src>[^\s]+\.[a-zA-Z0-9]{3,4})\s*(?<html_attr>[\s\S]+)?$/.match(render_markup)
  preset = settings['presets'][ markup[:preset] ]

  raise "Image Tag can't read this tag. Try {% image [preset or WxH] path/to/img.jpg [attr=\"value\"] %}." unless markup

  # Assign defaults
  settings['source'] ||= '.'
  settings['output'] ||= 'generated'

  # Prevent Jekyll from erasing our generated files
  site.config['keep_files'] << settings['output'] unless site.config['keep_files'].include?(settings['output'])

  # Process instance
  instance = if preset
    {
      :width => preset['width'],
      :height => preset['height'],
      :src => markup[:image_src]
    }
  elsif dim = /^(?:(?<width>\d+)|auto)(?:x)(?:(?<height>\d+)|auto)$/i.match(markup[:preset])
    {
      :width => dim['width'],
      :height => dim['height'],
      :src => markup[:image_src]
    }
  else
    { :src => markup[:image_src] }
  end

  # Process html attributes
  html_attr = if markup[:html_attr]
    Hash[ *markup[:html_attr].scan(/(?<attr>[^\s="]+)(?:="(?<value>[^"]+)")?\s?/).flatten ]
  else
    {}
  end

  if preset && preset['attr']
    html_attr = preset['attr'].merge(html_attr)
  end

  html_attr_string = html_attr.inject('') { |string, attrs|
    if attrs[1]
      string << "#{attrs[0]}=\"#{attrs[1]}\" "
    else
      string << "#{attrs[0]} "
    end
  }

  # Raise some exceptions before we start expensive processing
  raise "Image Tag can't find the \"#{markup[:preset]}\" preset. Check image: presets in _config.yml for a list of presets." unless preset || dim ||  markup[:preset].nil?

  # Generate resized images
  generated_src = generate_image(instance, site.source, site.dest, settings['source'], settings['output'], debug)
  unless generated_src
    return
  end
  # Generate resized images 2x
  generated2x_src = File.join(generated_src.dirname.to_s + "/" + File.basename(generated_src, ".*") + "@2x" + generated_src.extname)

  warn "Info (Image-Tag): ".yellow + "" + generated_src.to_s.green + "\n                 | ".yellow + generated2x_src.to_s.blue if debug

  generated_src = File.join(site.baseurl, generated_src) unless site.baseurl.empty?
  generated2x_src = File.join(site.baseurl, generated2x_src) unless site.baseurl.empty?
  
  markup_width = if instance[:width]
    "width=\"#{instance[:width]}\""
  end
  # Return the markup!
  "<img src=\"#{generated_src}\" srcset=\"#{generated_src} 1x, #{generated2x_src} 2x\" #{markup_width} #{html_attr_string}>"
end