Generated sprite filename is now unique based on inputs.

This commit is contained in:
Chris Eppstein 2010-12-05 17:50:25 -08:00
parent b131fe23da
commit a89d61ce21
4 changed files with 61 additions and 36 deletions

View File

@ -34,7 +34,7 @@ And you'll get the following CSS output:
.icon-delete, .icon-delete,
.icon-edit, .icon-edit,
.icon-new, .icon-new,
.icon-save { background: url('/images/icon.png?1291584143') no-repeat; } .icon-save { background: url('/images/icon-34fe0604ab.png') no-repeat; }
.icon-delete { background-position: 0 0; } .icon-delete { background-position: 0 0; }
.icon-edit { background-position: 0 -32px; } .icon-edit { background-position: 0 -32px; }
@ -73,7 +73,7 @@ And your stylesheet will compile to:
.actions .new, .actions .new,
.actions .edit, .actions .edit,
.actions .save, .actions .save,
.actions .delete { background: url('/images/icon.png?1291584143') no-repeat; } .actions .delete { background: url('/images/icon-34fe0604ab.png') no-repeat; }
.actions .new { background-position: 0 -64px; } .actions .new { background-position: 0 -64px; }
.actions .edit { background-position: 0 -32px; } .actions .edit { background-position: 0 -32px; }

View File

@ -1,3 +1,4 @@
require 'md5'
module Compass::SassExtensions::Functions::Sprites module Compass::SassExtensions::Functions::Sprites
ZERO = Sass::Script::Number::new(0) ZERO = Sass::Script::Number::new(0)
@ -12,6 +13,10 @@ module Compass::SassExtensions::Functions::Sprites
class SpriteMap < Sass::Script::Literal class SpriteMap < Sass::Script::Literal
# Changing this string will invalidate all previously generated sprite images.
# We should do so only when the packing algorithm changes
SPRITE_VERSION = "1"
attr_accessor :image_names, :path, :name, :options attr_accessor :image_names, :path, :name, :options
attr_accessor :images, :width, :height attr_accessor :images, :width, :height
@ -63,7 +68,8 @@ module Compass::SassExtensions::Functions::Sprites
:width => width, :width => width,
:repeat => repeat_for(sprite_name), :repeat => repeat_for(sprite_name),
:spacing => spacing_for(sprite_name), :spacing => spacing_for(sprite_name),
:position => position_for(sprite_name) :position => position_for(sprite_name),
:digest => MD5.file(file).hexdigest
} }
end end
@images.each_with_index do |image, index| @images.each_with_index do |image, index|
@ -151,7 +157,21 @@ module Compass::SassExtensions::Functions::Sprites
# The on-the-disk filename of the sprite # The on-the-disk filename of the sprite
def filename def filename
File.join(Compass.configuration.images_path, "#{path}.png") File.join(Compass.configuration.images_path, "#{path}-#{uniqueness_hash}.png")
end
def uniqueness_hash
@uniqueness_hash ||= begin
sum = MD5.md5(SPRITE_VERSION)
sum << path
images.each do |image|
[:relative_file, :height, :width, :repeat, :spacing, :position, :digest].each do |attr|
sum << image[attr].to_s
end
end
sum.hexdigest[0...10]
end
@uniqueness_hash
end end
# saves the sprite for later retrieval # saves the sprite for later retrieval
@ -268,7 +288,7 @@ module Compass::SassExtensions::Functions::Sprites
missing_sprite!("sprite-url") missing_sprite!("sprite-url")
end end
map.generate map.generate
image_url(Sass::Script::String.new("#{map.path}.png")) image_url(Sass::Script::String.new("#{map.path}-#{map.uniqueness_hash}.png"))
end end
Sass::Script::Functions.declare :sprite_url, [:map] Sass::Script::Functions.declare :sprite_url, [:map]

View File

@ -16,13 +16,17 @@ describe Compass::Sprites do
FileUtils.rm_r @images_tmp_path FileUtils.rm_r @images_tmp_path
end end
def map_location(file)
Dir.glob(File.join(@images_tmp_path, file)).first
end
def image_size(file) def image_size(file)
IO.read(File.join(@images_tmp_path, file))[0x10..0x18].unpack('NN') IO.read(map_location(file))[0x10..0x18].unpack('NN')
end end
def image_md5(file) def image_md5(file)
md5 = Digest::MD5.new md5 = Digest::MD5.new
md5.update IO.read(File.join(@images_tmp_path, file)) md5.update IO.read(map_location(file))
md5.hexdigest md5.hexdigest
end end
@ -46,7 +50,7 @@ describe Compass::Sprites do
SCSS SCSS
css.should == <<-CSS css.should == <<-CSS
.squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty {
background: url('/squares.png') no-repeat; background: url('/squares-161c60ad78.png') no-repeat;
} }
.squares-ten-by-ten { .squares-ten-by-ten {
@ -57,8 +61,8 @@ describe Compass::Sprites do
background-position: 0 -10px; background-position: 0 -10px;
} }
CSS CSS
image_size('squares.png').should == [20, 30] image_size('squares-*.png').should == [20, 30]
image_md5('squares.png').should == 'e8cd71d546aae6951ea44cb01af35820' image_md5('squares-*.png').should == 'e8cd71d546aae6951ea44cb01af35820'
end end
it "should generate sprite classes with dimensions" do it "should generate sprite classes with dimensions" do
@ -69,7 +73,7 @@ describe Compass::Sprites do
SCSS SCSS
css.should == <<-CSS css.should == <<-CSS
.squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty {
background: url('/squares.png') no-repeat; background: url('/squares-161c60ad78.png') no-repeat;
} }
.squares-ten-by-ten { .squares-ten-by-ten {
@ -84,7 +88,7 @@ describe Compass::Sprites do
width: 20px; width: 20px;
} }
CSS CSS
image_size('squares.png').should == [20, 30] image_size('squares-*.png').should == [20, 30]
end end
it "should provide sprite mixin" do it "should provide sprite mixin" do
@ -101,7 +105,7 @@ describe Compass::Sprites do
SCSS SCSS
css.should == <<-CSS css.should == <<-CSS
.squares-sprite, .cubicle, .large-cube { .squares-sprite, .cubicle, .large-cube {
background: url('/squares.png') no-repeat; background: url('/squares-161c60ad78.png') no-repeat;
} }
.cubicle { .cubicle {
@ -114,7 +118,7 @@ describe Compass::Sprites do
width: 20px; width: 20px;
} }
CSS CSS
image_size('squares.png').should == [20, 30] image_size('squares-*.png').should == [20, 30]
end end
# CUSTOMIZATIONS: # CUSTOMIZATIONS:
@ -126,10 +130,10 @@ describe Compass::Sprites do
SCSS SCSS
css.should == <<-CSS css.should == <<-CSS
.circles { .circles {
background: url('/squares.png') no-repeat; background: url('/squares-161c60ad78.png') no-repeat;
} }
CSS CSS
image_size('squares.png').should == [20, 30] image_size('squares-*.png').should == [20, 30]
end end
it "should calculate the spacing between images but not before first image" do it "should calculate the spacing between images but not before first image" do
@ -140,7 +144,7 @@ describe Compass::Sprites do
SCSS SCSS
css.should == <<-CSS css.should == <<-CSS
.squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty {
background: url('/squares.png') no-repeat; background: url('/squares-89450808af.png') no-repeat;
} }
.squares-ten-by-ten { .squares-ten-by-ten {
@ -151,7 +155,7 @@ describe Compass::Sprites do
background-position: 0 -43px; background-position: 0 -43px;
} }
CSS CSS
image_size('squares.png').should == [20, 63] image_size('squares-*.png').should == [20, 63]
end end
it "should calculate the spacing between images" do it "should calculate the spacing between images" do
@ -162,7 +166,7 @@ describe Compass::Sprites do
SCSS SCSS
css.should == <<-CSS css.should == <<-CSS
.squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty {
background: url('/squares.png') no-repeat; background: url('/squares-673837183a.png') no-repeat;
} }
.squares-ten-by-ten { .squares-ten-by-ten {
@ -173,7 +177,7 @@ describe Compass::Sprites do
background-position: 0 -43px; background-position: 0 -43px;
} }
CSS CSS
image_size('squares.png').should == [20, 63] image_size('squares-*.png').should == [20, 63]
end end
it "should calculate the maximum spacing between images" do it "should calculate the maximum spacing between images" do
@ -185,7 +189,7 @@ describe Compass::Sprites do
SCSS SCSS
css.should == <<-CSS css.should == <<-CSS
.squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty {
background: url('/squares.png') no-repeat; background: url('/squares-1cd84c9068.png') no-repeat;
} }
.squares-ten-by-ten { .squares-ten-by-ten {
@ -196,7 +200,7 @@ describe Compass::Sprites do
background-position: 0 -54px; background-position: 0 -54px;
} }
CSS CSS
image_size('squares.png').should == [20, 74] image_size('squares-*.png').should == [20, 74]
end end
it "should calculate the maximum spacing between images in reversed order" do it "should calculate the maximum spacing between images in reversed order" do
@ -208,7 +212,7 @@ describe Compass::Sprites do
SCSS SCSS
css.should == <<-CSS css.should == <<-CSS
.squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty {
background: url('/squares.png') no-repeat; background: url('/squares-f25b7090ca.png') no-repeat;
} }
.squares-ten-by-ten { .squares-ten-by-ten {
@ -219,7 +223,7 @@ describe Compass::Sprites do
background-position: 0 -54px; background-position: 0 -54px;
} }
CSS CSS
image_size('squares.png').should == [20, 74] image_size('squares-*.png').should == [20, 74]
end end
it "should calculate the default spacing between images" do it "should calculate the default spacing between images" do
@ -230,7 +234,7 @@ describe Compass::Sprites do
SCSS SCSS
css.should == <<-CSS css.should == <<-CSS
.squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty {
background: url('/squares.png') no-repeat; background: url('/squares-d66bf24bab.png') no-repeat;
} }
.squares-ten-by-ten { .squares-ten-by-ten {
@ -241,7 +245,7 @@ describe Compass::Sprites do
background-position: 0 -32px; background-position: 0 -32px;
} }
CSS CSS
image_size('squares.png').should == [20, 52] image_size('squares-*.png').should == [20, 52]
end end
it "should use position adjustments in functions" do it "should use position adjustments in functions" do
@ -265,7 +269,7 @@ describe Compass::Sprites do
SCSS SCSS
css.should == <<-CSS css.should == <<-CSS
.squares-sprite { .squares-sprite {
background: url('/squares.png') no-repeat; background: url('/squares-8e490168dd.png') no-repeat;
} }
.adjusted-percentage { .adjusted-percentage {
@ -280,8 +284,8 @@ describe Compass::Sprites do
background-position: -3px -8px; background-position: -3px -8px;
} }
CSS CSS
image_size('squares.png').should == [20, 30] image_size('squares-*.png').should == [20, 30]
image_md5('squares.png').should == 'b61700e6d402d9df5f3820b73479f371' image_md5('squares-*.png').should == 'b61700e6d402d9df5f3820b73479f371'
end end
it "should use position adjustments in mixins" do it "should use position adjustments in mixins" do
@ -303,7 +307,7 @@ describe Compass::Sprites do
SCSS SCSS
css.should == <<-CSS css.should == <<-CSS
.squares-sprite, .adjusted-percentage, .adjusted-px-1, .adjusted-px-2 { .squares-sprite, .adjusted-percentage, .adjusted-px-1, .adjusted-px-2 {
background: url('/squares.png') no-repeat; background: url('/squares-8e490168dd.png') no-repeat;
} }
.adjusted-percentage { .adjusted-percentage {
@ -318,8 +322,8 @@ describe Compass::Sprites do
background-position: -3px -8px; background-position: -3px -8px;
} }
CSS CSS
image_size('squares.png').should == [20, 30] image_size('squares-*.png').should == [20, 30]
image_md5('squares.png').should == 'b61700e6d402d9df5f3820b73479f371' image_md5('squares-*.png').should == 'b61700e6d402d9df5f3820b73479f371'
end end
it "should repeat the image" do it "should repeat the image" do
@ -330,7 +334,7 @@ describe Compass::Sprites do
SCSS SCSS
css.should == <<-CSS css.should == <<-CSS
.squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty {
background: url('/squares.png') no-repeat; background: url('/squares-a5550fd132.png') no-repeat;
} }
.squares-ten-by-ten { .squares-ten-by-ten {
@ -341,8 +345,8 @@ describe Compass::Sprites do
background-position: 0 -10px; background-position: 0 -10px;
} }
CSS CSS
image_size('squares.png').should == [20, 30] image_size('squares-*.png').should == [20, 30]
image_md5('squares.png').should == '0187306f3858136feee87d3017e7f307' image_md5('squares-*.png').should == '0187306f3858136feee87d3017e7f307'
end end
it "should provide a nice errors for lemonade's old users" do it "should provide a nice errors for lemonade's old users" do
@ -382,7 +386,7 @@ describe Compass::Sprites do
SCSS SCSS
actual_css.should == <<-CSS actual_css.should == <<-CSS
.squares { .squares {
background: url('/squares.png') 0 -10px no-repeat; background: url('/squares-145869726f.png') 0 -10px no-repeat;
} }
CSS CSS
end end

View File

@ -1,3 +1,4 @@
@charset "UTF-8";
.pie-element, .bordered, .gradient { .pie-element, .bordered, .gradient {
behavior: url('/tmp/PIE.htc'); behavior: url('/tmp/PIE.htc');
position: relative; } position: relative; }