css-spriter 0.9.2 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +7 -9
- data/Rakefile +7 -8
- data/VERSION +1 -1
- data/bin/css-spriter +1 -1
- data/css-spriter.gemspec +106 -0
- data/lib/css-spriter.rb +2 -11
- data/lib/css-spriter/directory_processor.rb +82 -78
- data/lib/css-spriter/image.rb +13 -0
- data/lib/css-spriter/mtime_tracker.rb +64 -61
- data/lib/css-spriter/sprite.rb +39 -31
- data/lib/css-spriter/stylesheet_builder.rb +19 -17
- data/spec/builders/image_builder.rb +3 -8
- data/spec/integration_spec.rb +27 -50
- data/spec/lib/css_spriter_image_spec.rb +8 -0
- data/spec/lib/sprite_spec.rb +4 -6
- data/spec/mtime_tracking_spec.rb +33 -19
- data/spec/spec_helper.rb +5 -5
- metadata +50 -40
- data/.gitignore +0 -12
- data/bin/png_info +0 -61
- data/examples/filter_util.rb +0 -17
- data/lib/css-spriter/image_data.rb +0 -128
- data/lib/css-spriter/png/chunk.rb +0 -12
- data/lib/css-spriter/png/file_header.rb +0 -7
- data/lib/css-spriter/png/filters.rb +0 -80
- data/lib/css-spriter/png/idat.rb +0 -26
- data/lib/css-spriter/png/iend.rb +0 -9
- data/lib/css-spriter/png/ihdr.rb +0 -34
- data/lib/css-spriter/png/image.rb +0 -153
- data/lib/css-spriter/png/parser.rb +0 -54
- data/spec/image_data_spec.rb +0 -63
- data/spec/lib/file_header_spec.rb +0 -10
- data/spec/lib/idat_spec.rb +0 -31
- data/spec/lib/ihdr_spec.rb +0 -43
- data/spec/lib/image_spec.rb +0 -42
- data/spec/lib/parser_spec.rb +0 -12
data/lib/css-spriter/sprite.rb
CHANGED
@@ -1,39 +1,47 @@
|
|
1
|
-
|
2
|
-
class
|
3
|
-
|
1
|
+
module CssSpriter
|
2
|
+
class Sprite
|
3
|
+
attr_reader :images, :max_height
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
def initialize
|
6
|
+
@images = []
|
7
|
+
@locations = {}
|
8
|
+
end
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
raise ImageFormatException.new("Image #{i} not compatible with #{image}")
|
14
|
-
end
|
10
|
+
def append( image )
|
11
|
+
@images << image
|
12
|
+
@max_height = @images.map{ |i| i.height }.max
|
15
13
|
end
|
16
14
|
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
def append_file( filename )
|
16
|
+
append( CssSpriter::Image.from_file( filename ))
|
17
|
+
end
|
20
18
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
19
|
+
def locations
|
20
|
+
@images.inject(0) do |x, image|
|
21
|
+
@locations[image.name.to_sym] = { :x => -(x),
|
22
|
+
:width => image.width,
|
23
|
+
:height => image.height}
|
24
|
+
image.width + x
|
25
|
+
end
|
26
|
+
@locations
|
27
27
|
end
|
28
|
-
@locations
|
29
|
-
end
|
30
28
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
29
|
+
def write( output_filename )
|
30
|
+
return if @images.empty?
|
31
|
+
|
32
|
+
sprite_height = @images.map{ |i| i.height }.max
|
33
|
+
sprite_width = @images.inject(0){|sum, image| sum + image.width }
|
34
|
+
|
35
|
+
sprite = ChunkyPNG::Image.new(sprite_width, sprite_height)
|
36
|
+
|
37
|
+
current_x = 0
|
38
|
+
|
39
|
+
images.each do |image|
|
40
|
+
sprite = sprite.replace(image, current_x, 0)
|
41
|
+
current_x += image.width
|
42
|
+
end
|
43
|
+
|
44
|
+
sprite.save( output_filename, :best_compression )
|
45
|
+
end
|
38
46
|
end
|
39
|
-
end
|
47
|
+
end
|
@@ -1,22 +1,24 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
module CssSpriter
|
2
|
+
class StylesheetBuilder
|
3
|
+
def initialize(dir)
|
4
|
+
@dir = dir
|
5
|
+
@output_file = @dir + "/sprite.css"
|
6
|
+
end
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
def output_file(file)
|
9
|
+
@output_file = file
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
def css
|
13
|
+
@css ||= Dir.glob(@dir + "/**/fragment.css").inject("") {|acc, f| acc + File.read(f)}
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
def write
|
17
|
+
File.open(@output_file, 'w') {|f| f.write(css)}
|
18
|
+
end
|
18
19
|
|
19
|
-
|
20
|
-
|
20
|
+
def cleanup
|
21
|
+
File.delete(@output_file) rescue nil
|
22
|
+
end
|
21
23
|
end
|
22
|
-
end
|
24
|
+
end
|
@@ -8,16 +8,11 @@ class ImageBuilder
|
|
8
8
|
@general_options = default_options.merge general_options
|
9
9
|
end
|
10
10
|
|
11
|
-
def data(width, height)
|
12
|
-
Array.new((width * height * 3) + height).fill(0)
|
13
|
-
end
|
14
|
-
|
15
11
|
def build( specific_options={} )
|
16
12
|
args = @general_options.merge specific_options
|
17
|
-
|
18
|
-
ihdr = PNG::IHDR.new( args[:width], args[:height] )
|
19
|
-
idat = PNG::IDAT.new( args[:data] || data(args[:width], args[:height]) )
|
20
13
|
|
21
|
-
|
14
|
+
image = CssSpriter::Image.new( args[:width], args[:height], ChunkyPNG::Color::TRANSPARENT )
|
15
|
+
image.name = args[:name]
|
16
|
+
image
|
22
17
|
end
|
23
18
|
end
|
data/spec/integration_spec.rb
CHANGED
@@ -1,81 +1,58 @@
|
|
1
|
-
require 'benchmark'
|
2
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
3
2
|
|
4
|
-
describe 'PNG' do
|
5
|
-
before do
|
6
|
-
@img_dir = File.dirname(__FILE__) + '/images'
|
7
|
-
@expected_dir = File.dirname(__FILE__) + '/expected_output'
|
8
|
-
@tmp_dir = File.dirname(__FILE__) + '/tmp'
|
9
|
-
end
|
10
|
-
|
11
|
-
it 'can read and write a PNG' do
|
12
|
-
img = PNG::Image.open("#{@img_dir}/lightening.png")
|
13
|
-
img.write("#{@tmp_dir}/write_test.png", :filter_type => 0)
|
14
|
-
read("#{@expected_dir}/write_test.png").should == read("#{@tmp_dir}/write_test.png")
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'can merge one PNG on the left of another' do
|
18
|
-
one = PNG::Image.image_data("#{@img_dir}/lightening.png", :rgba => false)
|
19
|
-
two = PNG::Image.image_data("#{@img_dir}/lightening.png", :rgba => false)
|
20
|
-
merged = one.merge_left two
|
21
|
-
PNG::Image.write("#{@tmp_dir}/merge_right_test.png", merged, :filter_type => 0)
|
22
|
-
read("#{@expected_dir}/merge_right_test.png").should == read("#{@tmp_dir}/merge_right_test.png")
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
3
|
describe "Dir sprite" do
|
27
4
|
before :all do
|
28
5
|
@dir = File.dirname(__FILE__) + "/sprite_dirs/words"
|
29
|
-
@spriter = DirectoryProcessor.new(@dir)
|
6
|
+
@spriter = CssSpriter::DirectoryProcessor.new(@dir)
|
30
7
|
@sprite_file = @dir + "/sprite.png"
|
31
8
|
@css_file = @dir + "/fragment.css"
|
32
9
|
@spriter.write
|
33
10
|
end
|
34
11
|
|
35
|
-
after :all do
|
12
|
+
after :all do
|
36
13
|
@spriter.cleanup
|
37
14
|
end
|
38
15
|
|
39
|
-
describe "Sprite generation" do
|
40
|
-
it "provides the correct dir name" do
|
16
|
+
describe "Sprite generation" do
|
17
|
+
it "provides the correct dir name" do
|
41
18
|
@spriter.dir_name.should == 'words'
|
42
19
|
end
|
43
20
|
|
44
|
-
it "find all the pngs in a directory" do
|
21
|
+
it "find all the pngs in a directory" do
|
45
22
|
expected = ['latitude.png', 'of.png', 'set.png', 'specified.png']
|
46
23
|
images = @spriter.images
|
47
24
|
images.map{|f| f.split('/').last}.should == expected
|
48
25
|
end
|
49
26
|
|
50
|
-
it "sprites all the images in a directory" do
|
27
|
+
it "sprites all the images in a directory" do
|
51
28
|
File.exists?(@sprite_file).should be_true
|
52
29
|
end
|
53
30
|
end
|
54
31
|
|
55
|
-
describe "CSS fragments" do
|
56
|
-
before :all do
|
32
|
+
describe "CSS fragments" do
|
33
|
+
before :all do
|
57
34
|
@template = @dir + "/template.css"
|
58
35
|
@css = @spriter.css
|
59
36
|
end
|
60
37
|
|
61
|
-
after do
|
38
|
+
after do
|
62
39
|
File.delete(@template) rescue nil
|
63
40
|
end
|
64
41
|
|
65
|
-
it "should compose class names" do
|
42
|
+
it "should compose class names" do
|
66
43
|
@css.should include( ".words_latitude")
|
67
44
|
@css.should include( ".words_of" )
|
68
45
|
end
|
69
46
|
|
70
|
-
it "has the correct image path" do
|
47
|
+
it "has the correct image path" do
|
71
48
|
@css.should include( "/sprite_dirs/words/sprite.png" )
|
72
49
|
end
|
73
50
|
|
74
|
-
it "should write css fragments for a sprite" do
|
51
|
+
it "should write css fragments for a sprite" do
|
75
52
|
File.exists?(@css_file).should be_true
|
76
53
|
end
|
77
54
|
|
78
|
-
it "can be overidden by including a template.css in the sprite directory" do
|
55
|
+
it "can be overidden by including a template.css in the sprite directory" do
|
79
56
|
File.open(@template, 'w'){|f| f.write("override")}
|
80
57
|
@spriter.write
|
81
58
|
@spriter.css.should include("override")
|
@@ -83,63 +60,63 @@ describe "Dir sprite" do
|
|
83
60
|
end
|
84
61
|
end
|
85
62
|
|
86
|
-
describe 'Stylesheet generator' do
|
87
|
-
before :all do
|
63
|
+
describe 'Stylesheet generator' do
|
64
|
+
before :all do
|
88
65
|
@dir = File.dirname(__FILE__) + "/css_fragments"
|
89
66
|
@out = @dir + "/complete.css"
|
90
|
-
@builder = StylesheetBuilder.new(@dir)
|
67
|
+
@builder = CssSpriter::StylesheetBuilder.new(@dir)
|
91
68
|
@builder.output_file(@out)
|
92
69
|
@css = @builder.css
|
93
70
|
end
|
94
71
|
|
95
|
-
after :all do
|
72
|
+
after :all do
|
96
73
|
@builder.cleanup
|
97
74
|
end
|
98
75
|
|
99
|
-
it "takes the css fragments and concatonates them into a single stylesheet" do
|
76
|
+
it "takes the css fragments and concatonates them into a single stylesheet" do
|
100
77
|
@css.should include( ".some_style" )
|
101
78
|
end
|
102
79
|
|
103
|
-
it "can handle nested folder structures" do
|
80
|
+
it "can handle nested folder structures" do
|
104
81
|
@css.should include( ".deep" )
|
105
82
|
end
|
106
83
|
|
107
|
-
it "writes the css file to the specified location" do
|
84
|
+
it "writes the css file to the specified location" do
|
108
85
|
@builder.write
|
109
86
|
File.exists?(@out).should be_true
|
110
87
|
end
|
111
88
|
end
|
112
89
|
|
113
|
-
describe "Complete spriting process" do
|
114
|
-
before :all do
|
90
|
+
describe "Complete spriting process" do
|
91
|
+
before :all do
|
115
92
|
@dir = File.dirname(__FILE__) + "/sprite_dirs"
|
116
93
|
@css_file = @dir + "/sprite.css"
|
117
94
|
@spriter = CssSpriter::Processor.new(:path_prefix => "/images", :source => @dir, :css_file => @css_file)
|
118
95
|
@spriter.write
|
119
96
|
end
|
120
97
|
|
121
|
-
after :all do
|
98
|
+
after :all do
|
122
99
|
@spriter.cleanup
|
123
100
|
#making sure it cleans things up - shitty place for these
|
124
101
|
File.exists?(@css_file).should be_false
|
125
102
|
File.exists?(@dir + "/words/sprite.png").should be_false
|
126
103
|
end
|
127
104
|
|
128
|
-
it "prepends a path prefix to all sprites in the css file" do
|
105
|
+
it "prepends a path prefix to all sprites in the css file" do
|
129
106
|
file = read(@css_file)
|
130
107
|
file.should include("/images/sprite_dirs/words")
|
131
108
|
end
|
132
109
|
|
133
|
-
it "can find all the sprite directories" do
|
110
|
+
it "can find all the sprite directories" do
|
134
111
|
dirs = @spriter.directories.map{|d| d.split('/').last}
|
135
112
|
dirs.should include( "words" )
|
136
113
|
end
|
137
114
|
|
138
|
-
it "generates the css file at the appropriate location" do
|
115
|
+
it "generates the css file at the appropriate location" do
|
139
116
|
File.exists?(@css_file).should be_true
|
140
117
|
end
|
141
118
|
|
142
|
-
it "creates sprites/css for all subfolders" do
|
119
|
+
it "creates sprites/css for all subfolders" do
|
143
120
|
File.exists?(@dir + "/words/sprite.png").should be_true
|
144
121
|
File.exists?(@dir + "/words/fragment.css").should be_true
|
145
122
|
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe CssSpriter::Image do
|
4
|
+
it "sets the name with the filename of the image" do
|
5
|
+
image = CssSpriter::Image.from_file( File.dirname(__FILE__) + '/../images/lightening.png')
|
6
|
+
image.name.should == 'lightening'
|
7
|
+
end
|
8
|
+
end
|
data/spec/lib/sprite_spec.rb
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
2
|
|
3
|
-
describe Sprite do
|
3
|
+
describe CssSpriter::Sprite do
|
4
4
|
before :each do
|
5
|
-
@sprite = Sprite.new
|
5
|
+
@sprite = CssSpriter::Sprite.new
|
6
6
|
@builder = ImageBuilder.new
|
7
7
|
|
8
|
-
|
9
|
-
@
|
10
|
-
@image2 = @builder.build( :width => 50, :height => 50, :name => "image2").to_image
|
8
|
+
@image1 = @builder.build( :width => 50, :height => 50, :name => "image1")
|
9
|
+
@image2 = @builder.build( :width => 50, :height => 50, :name => "image2")
|
11
10
|
end
|
12
11
|
|
13
12
|
it "can merge an image to the right" do
|
@@ -35,5 +34,4 @@ describe Sprite do
|
|
35
34
|
|
36
35
|
@sprite.max_height.should == max_height
|
37
36
|
end
|
38
|
-
|
39
37
|
end
|
data/spec/mtime_tracking_spec.rb
CHANGED
@@ -2,65 +2,79 @@ require 'benchmark'
|
|
2
2
|
require 'fileutils'
|
3
3
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
4
4
|
|
5
|
-
describe MtimeTracker do
|
6
|
-
describe "on a new directory" do
|
7
|
-
before do
|
5
|
+
describe CssSpriter::MtimeTracker do
|
6
|
+
describe "on a new directory" do
|
7
|
+
before do
|
8
8
|
@img_dir = File.dirname(__FILE__) + '/images'
|
9
|
-
@tracker = MtimeTracker.new(@img_dir)
|
9
|
+
@tracker = CssSpriter::MtimeTracker.new(@img_dir)
|
10
10
|
end
|
11
11
|
|
12
12
|
after do
|
13
13
|
File.delete(@img_dir + "/.mtimes") rescue nil
|
14
14
|
end
|
15
15
|
|
16
|
-
it "tells me there are changes" do
|
16
|
+
it "tells me there are changes" do
|
17
17
|
@tracker.has_changes?.should be_true
|
18
18
|
end
|
19
19
|
|
20
|
-
it "tells me things have not changed after I update the tracking" do
|
20
|
+
it "tells me things have not changed after I update the tracking" do
|
21
21
|
@tracker.update
|
22
22
|
@tracker.has_changes?.should be_false
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
describe "on an existing directory" do
|
27
|
-
before do
|
26
|
+
describe "on an existing directory" do
|
27
|
+
before do
|
28
28
|
@img_dir = File.dirname(__FILE__) + '/images'
|
29
|
-
MtimeTracker.new(@img_dir).update
|
30
|
-
@tracker = MtimeTracker.new(@img_dir)
|
29
|
+
CssSpriter::MtimeTracker.new(@img_dir).update
|
30
|
+
@tracker = CssSpriter::MtimeTracker.new(@img_dir)
|
31
31
|
end
|
32
32
|
|
33
33
|
after do
|
34
34
|
File.delete(@img_dir + "/.mtimes") rescue nil
|
35
35
|
end
|
36
36
|
|
37
|
-
it "tells me nothing has changed" do
|
37
|
+
it "tells me nothing has changed" do
|
38
38
|
@tracker.has_changes?.should be_false
|
39
39
|
end
|
40
40
|
|
41
|
-
describe "when a file has changed" do
|
42
|
-
before do
|
41
|
+
describe "when a file has changed" do
|
42
|
+
before do
|
43
43
|
FileUtils.touch(@img_dir + "/lightening.png")
|
44
44
|
@tracker.reset
|
45
45
|
end
|
46
46
|
|
47
|
-
it "returns true from has_changes" do
|
47
|
+
it "returns true from has_changes" do
|
48
48
|
@tracker.has_changes?.should be_true
|
49
49
|
@tracker.changeset.first.should include("/spec/images/lightening.png")
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
describe "file
|
54
|
-
before do
|
53
|
+
describe "when a file is deleted" do
|
54
|
+
before do
|
55
|
+
FileUtils.touch(@img_dir + "/a_test.png")
|
56
|
+
File.exists?(@img_dir + "/a_test.png").should be_true
|
57
|
+
@tracker.update
|
58
|
+
File.delete(@img_dir + "/a_test.png")
|
59
|
+
end
|
60
|
+
|
61
|
+
it "returns true from has_changes" do
|
62
|
+
@tracker.has_changes?.should be_true
|
63
|
+
@tracker.changeset.first.should include("/spec/images/a_test.png")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "file exclustions" do
|
68
|
+
before do
|
55
69
|
@img_dir = File.dirname(__FILE__) + '/images'
|
56
|
-
@tracker = MtimeTracker.new(@img_dir, :exclude => [/lightening/, "tacos"])
|
70
|
+
@tracker = CssSpriter::MtimeTracker.new(@img_dir, :exclude => [/lightening/, "tacos"])
|
57
71
|
end
|
58
72
|
|
59
|
-
after do
|
73
|
+
after do
|
60
74
|
File.delete(@img_dir + "/.mtimes") rescue nil
|
61
75
|
end
|
62
76
|
|
63
|
-
it "does not report excluded files as changed" do
|
77
|
+
it "does not report excluded files as changed" do
|
64
78
|
FileUtils.touch(@img_dir + "/lightening.png")
|
65
79
|
@tracker.has_changes?.should be_false
|
66
80
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'spec'
|
4
|
-
require 'spec/autorun'
|
1
|
+
require 'rspec'
|
2
|
+
require 'rspec/autorun'
|
5
3
|
|
4
|
+
require 'chunky_png'
|
6
5
|
require 'css-spriter'
|
7
6
|
|
7
|
+
|
8
8
|
require 'builders/image_builder'
|
9
9
|
|
10
|
-
|
10
|
+
RSpec.configure do |config|
|
11
11
|
|
12
12
|
end
|
13
13
|
|