anonymous / image_size.rb
Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

Nanoc filter that computes image dimensions and injects height and width attributes into img tags for much faster and smoother image loading in browsers

View image_size.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
# vim: set ts=2 sw=2 et ai ft=ruby:
 
# Idea from here:
# http://userprimary.net/posts/2011/01/10/optimizing-nanoc-based-websites/
# Also uses code from other filters that are shipped with Nanoc itself.
#
# Implementation enhanced by Pascal Bleser <loki@fosdem.org>,
# 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')
end
 
protected
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)
selectors.map { |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}
end
end
result = doc.send("to_#{type}")
result
end
 
def image_size(path)
require 'image_size'
path = '/' + path unless path[0, 1] == '/'
img = ImageSize.new(IO.read("output#{path}"))
{ :height => img.height, :width => img.width }
end
 
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.