Create a gist now

Instantly share code, notes, and snippets.

anonymous /image_size.rb
Created Jun 16, 2012

Nanoc filter that computes image dimensions and injects height and width attributes into img tags for much faster and smoother image loading in browsers
# vim: set ts=2 sw=2 et ai ft=ruby:
# Idea from here:
# Also uses code from other filters that are shipped with Nanoc itself.
# Implementation enhanced by Pascal Bleser <>,
# under either GPL2 (GNU General Public License) or ASL2.1 (Apache Software License)
# or BSD-3-Clause, as you wish (short version: do whatever you want with it ;)).
# Put this file into lib/helpers/ (or lib/filters/, would be better structured)
# and add an invocation of "filter :imagesize" in your Rules, e.g. like this:
# compile '*' do
# filter :imagesize unless item.binary?
# end
class ImageSizeFilter < Nanoc::Filter
type :text
identifier :imagesize
@@SELECTORS = [ 'img' ]
def run(content, params={})
# Set assigns so helper function can be used
@item_rep = assigns[:item_rep] if @item_rep.nil?
selectors = params.fetch(:select) { @@SELECTORS }
namespaces = params[:namespaces] || {}
require 'nokogiri'
klass = ::Nokogiri::HTML
add_image_size(content, selectors, namespaces, klass, 'xhtml')
def add_image_size(content, selectors, namespaces, klass, type)
# Ensure that all prefixes are strings
namespaces = namespaces.inject({}) { |new, (prefix, uri)| new.merge(prefix.to_s => uri) }
doc = content =~ /<html[\s>]/ ? klass.parse(content) : klass.fragment(content) { |sel| "#{sel}" }.each do |selector|
doc.xpath(selector, namespaces)
.select { |node| node.is_a? Nokogiri::XML::Element }
.select { |img| img.has_attribute?('src') }
.each do |img|
path = img['src']
dimensions = image_size(path)
dimensions.each{|k,v| img[k.to_s] = v.to_s}
result = doc.send("to_#{type}")
def image_size(path)
require 'image_size'
path = '/' + path unless path[0, 1] == '/'
img ="output#{path}"))
{ :height => img.height, :width => img.width }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment