Skip to content

Instantly share code, notes, and snippets.

@joethephish
Created December 9, 2014 12:44
Show Gist options
  • Save joethephish/09d12d80bd0a98c16670 to your computer and use it in GitHub Desktop.
Save joethephish/09d12d80bd0a98c16670 to your computer and use it in GitHub Desktop.
Thumbnail Jekyll plugin
# Generates a thumbnail image and returns its path, given a path to the full image.
# Hacked from various existing plugins, particularly:
# https://github.com/mrdanadams/jekyll-thumbnailer/blob/master/thumbnail.rb
# https://github.com/10io/jekyll-thumbnailify/blob/master/jekyll-thumbnailify.rb
#
# Doesn't require ImageMagick, and instead uses the Apple Developer tool sips, so
# only works when generated on a Mac. Could easily replace sips with ImageMagick again.
#
# Usage:
#
# <img src="{% thumbnail /path/to/local/image.png width 100 < %}" />
#
# or:
#
# <img src="{% thumbnail /path/to/local/image.png height 100 < %}" />
#
# Depending on whether you want to constrain by width or height.
#
require 'fileutils'
# The image static file model understood by Jekyll
# This is a sub class of StaticFile. But instead of managing a unique
# name between the src file and the dest file, we have a src complete
# path, a dest path and a dest file name.
class ImageStaticFile < Jekyll::StaticFile
# Initialize a new StaticFile.
# +image_src+ is the complete path of the src image file. Eg. /foo/bar.png
# +image_dest_dir+ is the destination dir for the dest image file
# +image_dest_name+ is the String filename of the dest image file
#
# Returns <ImageStaticFile>
def initialize(image_src, image_dest_dir, image_dest_name)
@image_src = image_src
@dir = image_dest_dir
@name = image_dest_name
end
# Obtains source file path.
# In this implementation, simply returns image_src
def path
File.join(@image_src)
end
end
class Jekyll::Thumbnail < Liquid::Tag
def initialize(tag_name, markup, tokens)
if /(?<source>[^\s]+)\s+(?<dimension>(width|height))\s+(?<size>\d+)/i =~ markup
@source = source
@isHeight = (dimension == "height")
@size = size
end
super
end
def render(context)
if @source
# parking
source = @source
size = @size
source_path = ".#{source}"
raise "#{source} is not readable" unless File.readable?(source_path)
# Split up path and generate output path
ext = File.extname(source)
desc = "w#{@size}"
if @isHeight
desc = "h#{@size}"
end
thumbname = "#{File.basename(source_path, ext)}_thumb_#{desc}#{ext}"
final_dest = "#{File.dirname(source)}/#{thumbname}"
# Generate thumbs into a temporary directory for caching
# TODO: How to do this properly without this crap temp directory?!
temp_dest = "./.tmp#{final_dest}"
# Only re-generate the thumb if it doesn't already exist in the temporary directory
if !File.exists?(temp_dest) || File.mtime(temp_dest) <= File.mtime(source_path)
# Generate the full directory path within the .tmp folder
FileUtils.mkpath( File.dirname(temp_dest) )
# Run Apple Developer image resizing tool
if @isHeight
`sips --resampleHeight #{size} #{source_path} --out #{temp_dest}`
else
`sips --resampleWidth #{size} #{source_path} --out #{temp_dest}`
end
end
# Generate the static thumb image file and add it to the site
static_file = ImageStaticFile.new(temp_dest, File.dirname(source), thumbname)
site = context.registers[:site]
site.static_files << static_file
# Return the final path to the thumb
final_dest
else
"Could not create thumbnail for #{source}. Usage: thumbnail /path/to/local/image.png 50x50<"
end
end
end
Liquid::Template.register_tag('thumbnail', Jekyll::Thumbnail)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment