Skip to content

Instantly share code, notes, and snippets.

@rosenfeld
Last active November 15, 2018 09:48
Show Gist options
  • Save rosenfeld/e756423e6eeba481888b to your computer and use it in GitHub Desktop.
Save rosenfeld/e756423e6eeba481888b to your computer and use it in GitHub Desktop.
Sprite generator to replace compass (only Ruby and ImageMagick are required)
This was created to replace compass in a Rails project.
The generator supports multiple themes and the sprite dimensions are available in a dimensions.sass file as variables.
There are no other dependencies than Ruby and ImageMagick binaries (or compatible commands with convert and identify).
The image name contains an MD5 hash of all images content and is stored directly into public/assets
so that the resulting CSS doesn't depend on sprockets.
It took about 0.2s to generate two theme sprites for me with about 30 images each.
#!/usr/bin/env ruby
require_relative 'sprite_generator'
['default', 'fancy'].each{|theme| SpriteGenerator.generate theme }
require 'fileutils'
class SpriteGenerator
def self.generate(theme)
new(theme).generate
end
def initialize(theme)
@theme = theme
end
def generate
create_sprite
compute_size_and_offset
FileUtils.rm_rf css_output_path
FileUtils.mkdir_p css_output_path
generate_css
generate_dimensions_sass_vars
end
private
def create_sprite
FileUtils.rm_rf output_path
FileUtils.mkdir_p output_path
`convert -append #{theme_path}/*.png #{output_path}/#{sprite_filename}`
end
def theme_path
@theme_path ||= "images/#{@theme}/theme"
end
def output_path
@output_path ||= "public/assets/#{@theme}"
end
def sprite_filename
@sprite_filename ||= "theme-#{checksum}.png"
end
def checksum
@checksum ||= `cat #{theme_path}/*.png|md5sum`.match(/(.*?)\s/)[1]
end
def compute_size_and_offset
dimensions = `identify -format "%wx%h,%t\\n" #{theme_path}/*.png`
@image_props = []
offset = 0
dimensions.split("\n").each do |d|
m = d.match /(\d+)x(\d+),(.*)/
w, h, name = m[1..-1]
@image_props << [w.to_i, h = h.to_i, name, offset]
offset += h
end
end
def css_output_path
@css_output_path ||= "app/assets/stylesheets/themes/#{@theme}"
end
def generate_css
common_rules = [
@image_props.map{|(w, h, name, offset)| ".#{name}"}.join(', '),
'{',
" background-image: url(/assets/#{@theme}/#{sprite_filename});",
' background-repeat: no-repeat;',
' display: inline-block;',
' border: 0;',
' background-color: transparent;',
'}',
].join "\n"
content = @image_props.map do |(w, h, name, offset)|
[
".theme-#{name} {",
" height: #{h}px;",
" width: #{w}px;",
" background-position: 0 -#{offset}px;",
"}",
].join "\n"
end.join("\n")
File.write "#{css_output_path}/theme.css", "#{common_rules}\n\n#{content}"
end
def generate_dimensions_sass_vars
content = @image_props.map do |(w, h, name, offset)|
"$theme-#{name}-width: #{w}px;\n$theme-#{name}-height: #{h}px;\n"
end.join("\n")
File.write "#{css_output_path}/dimensions.sass", content
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment