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.
@@ -15,6 +15,10 @@ It takes your PNG's, chews them up and spits out sprites!
15
15
 
16
16
  point bin/css-spriter at a directory, and watch it sprite away!
17
17
 
18
+ CSS-Spriter uses Chunky PNG for it's PNG manipulation. Not only is it super fast, but the library is a great example of fast, efficient ruby programming.
19
+
20
+ Chunky PNG is written in pure ruby, this means you can sprite up anything using MRI, JRuby, or Rubinius.
21
+
18
22
  == Installation - standalone
19
23
 
20
24
  sudo gem install css-spriter
@@ -35,7 +39,7 @@ For a full list of options:
35
39
 
36
40
  === Usage - Rails plugin
37
41
 
38
- Spittle assumes all of your sprites are located in the directory public/images/sprites. This directory should contain sub-directories for each sprite you wish to create. The css class names for an image in a sprite will take the form <directory_name>_<image_name>. Here is an example:
42
+ CSS-Spriter assumes all of your sprites are located in the directory public/images/sprites. This directory should contain sub-directories for each sprite you wish to create. The css class names for an image in a sprite will take the form <directory_name>_<image_name>. Here is an example:
39
43
 
40
44
  sprites /
41
45
  cars /
@@ -45,14 +49,10 @@ Spittle assumes all of your sprites are located in the directory public/images/s
45
49
  boeing.png
46
50
  cesna.png
47
51
 
48
- Running sprite:generate does all the work. Each sprite directory (cars, planes) will now contain a sprite.png. Spittle will also generate a sprites.css stylesheet in public/stylesheets/ that you should include in your layout. If you wished to use the ford image from the cars sprite you would give the 'cars_ford' class to the desired element in the view. That's it!
49
-
50
- Check out examples/sprites if you want to see what spriter can do without doing any work.
52
+ Running the sprite:generate task does all the work. Each sprite directory (cars, planes) will now contain a sprite.png. Spittle will also generate a sprites.css stylesheet in public/stylesheets/ that you should include in your layout. If you wished to use the ford image from the cars sprite you would give the 'cars_ford' class to the desired element in the view. That's it!
51
53
 
52
- == Limitations
54
+ Check out examples/sprites if you want to see what CSS-Spriter can do without doing any work.
53
55
 
54
- - does not support color profiles (can cause a slight change in color from the source image)
55
- - does not support reading interlaced PNGs.
56
56
 
57
57
  == Features
58
58
 
@@ -62,12 +62,10 @@ Check out examples/sprites if you want to see what spriter can do without doing
62
62
  - Rails plugin & rake tasks (sprite:generate & sprite:cleanup)
63
63
  - Supports varying dimensions in source images
64
64
  - Does not regenerate sprites that have not changed
65
- - Supports all PNG filter types to improve image compression
66
65
  - supports mixing RGB and RGBA color types
67
66
 
68
67
  == Roadmap - by priority
69
68
 
70
- - Reading interlaced images
71
69
  - allow a global css template override
72
70
  - allow per-sprite and global configuration
73
71
 
data/Rakefile CHANGED
@@ -6,11 +6,12 @@ begin
6
6
  Jeweler::Tasks.new do |gem|
7
7
  gem.name = "css-spriter"
8
8
  gem.summary = %Q{pure ruby PNG spriting library}
9
- gem.description = %Q{Css Spriter is a pure ruby PNG spriting library. It can be used standalone or as a Rails plugin, see the readme for details.}
9
+ gem.description = %Q{CSS-Spriter is a pure ruby PNG spriting library. It can be used standalone or as a Rails plugin, see the readme for details.}
10
10
  gem.email = ["qzzzq1@gmail.com", "tyler.jennings@gmail.com"]
11
11
  gem.homepage = "http://github.com/aberant/css-spriter"
12
12
  gem.authors = ["aberant", "tjennings"]
13
13
  gem.add_development_dependency "rspec" #, ">= 1.2.9"
14
+ gem.add_dependency "chunky_png", "~> 1.1.0"
14
15
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
16
  end
16
17
  Jeweler::GemcutterTasks.new
@@ -18,14 +19,12 @@ rescue LoadError
18
19
  puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
19
20
  end
20
21
 
21
- require 'spec/rake/spectask'
22
- Spec::Rake::SpecTask.new(:spec) do |spec|
23
- spec.libs << 'lib' << 'spec'
24
- spec.spec_files = FileList['spec/**/*_spec.rb']
22
+ require 'rspec/core/rake_task'
23
+ RSpec::Core::RakeTask.new do |task|
24
+ task.pattern = 'spec/**/*_spec.rb'
25
25
  end
26
26
 
27
- Spec::Rake::SpecTask.new(:rcov) do |spec|
28
- spec.libs << 'lib' << 'spec'
27
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
29
28
  spec.pattern = 'spec/**/*_spec.rb'
30
29
  spec.rcov = true
31
30
  end
@@ -39,7 +38,7 @@ Rake::RDocTask.new do |rdoc|
39
38
  version = File.exist?('VERSION') ? File.read('VERSION') : ""
40
39
 
41
40
  rdoc.rdoc_dir = 'rdoc'
42
- rdoc.title = "spittle #{version}"
41
+ rdoc.title = "css-spriter #{version}"
43
42
  rdoc.rdoc_files.include('README*')
44
43
  rdoc.rdoc_files.include('lib/**/*.rb')
45
44
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.2
1
+ 1.0.1
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'optparse'
4
- require File.dirname(__FILE__) + "/../lib/css-spriter.rb"
4
+ require File.dirname(__FILE__) + "/../lib/css-spriter"
5
5
 
6
6
 
7
7
  options = {}
@@ -0,0 +1,106 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{css-spriter}
8
+ s.version = "1.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["aberant", "tjennings"]
12
+ s.date = %q{2011-03-23}
13
+ s.default_executable = %q{css-spriter}
14
+ s.description = %q{CSS-Spriter is a pure ruby PNG spriting library. It can be used standalone or as a Rails plugin, see the readme for details.}
15
+ s.email = ["qzzzq1@gmail.com", "tyler.jennings@gmail.com"]
16
+ s.executables = ["css-spriter"]
17
+ s.extra_rdoc_files = [
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ "MIT-LICENSE",
22
+ "README.rdoc",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "bin/css-spriter",
26
+ "css-spriter.gemspec",
27
+ "examples/sprites/.mtimes",
28
+ "examples/sprites/README",
29
+ "examples/sprites/fragment.css",
30
+ "examples/sprites/index.html",
31
+ "examples/sprites/many_sized_cats/.mtimes",
32
+ "examples/sprites/many_sized_cats/cat-on-keyboard.png",
33
+ "examples/sprites/many_sized_cats/darth_cat.png",
34
+ "examples/sprites/many_sized_cats/fragment.css",
35
+ "examples/sprites/many_sized_cats/music-keyboard-cat.png",
36
+ "examples/sprites/many_sized_cats/sprite.css",
37
+ "examples/sprites/many_sized_cats/sprite.png",
38
+ "examples/sprites/server.rb",
39
+ "examples/sprites/sprite.css",
40
+ "examples/sprites/words/.mtimes",
41
+ "examples/sprites/words/fragment.css",
42
+ "examples/sprites/words/latitude.png",
43
+ "examples/sprites/words/of.png",
44
+ "examples/sprites/words/set.png",
45
+ "examples/sprites/words/specified.png",
46
+ "examples/sprites/words/sprite.css",
47
+ "examples/sprites/words/sprite.png",
48
+ "init.rb",
49
+ "lib/css-spriter.rb",
50
+ "lib/css-spriter/directory_processor.rb",
51
+ "lib/css-spriter/image.rb",
52
+ "lib/css-spriter/mtime_tracker.rb",
53
+ "lib/css-spriter/processor.rb",
54
+ "lib/css-spriter/sprite.rb",
55
+ "lib/css-spriter/stylesheet_builder.rb",
56
+ "spec/builders/image_builder.rb",
57
+ "spec/css_fragments/deep/style/fragment.css",
58
+ "spec/css_fragments/some/fragment.css",
59
+ "spec/expected_output/merge_right_test.png",
60
+ "spec/expected_output/write_test.png",
61
+ "spec/images/lightening.png",
62
+ "spec/integration_spec.rb",
63
+ "spec/lib/css_spriter_image_spec.rb",
64
+ "spec/lib/sprite_spec.rb",
65
+ "spec/mtime_tracking_spec.rb",
66
+ "spec/spec.opts",
67
+ "spec/spec_helper.rb",
68
+ "spec/sprite_dirs/words/latitude.png",
69
+ "spec/sprite_dirs/words/of.png",
70
+ "spec/sprite_dirs/words/set.png",
71
+ "spec/sprite_dirs/words/specified.png",
72
+ "spec/tmp/merge_right_test.png",
73
+ "spec/tmp/write_test.png",
74
+ "tasks/spriter_tasks.rake"
75
+ ]
76
+ s.homepage = %q{http://github.com/aberant/css-spriter}
77
+ s.require_paths = ["lib"]
78
+ s.rubygems_version = %q{1.3.7}
79
+ s.summary = %q{pure ruby PNG spriting library}
80
+ s.test_files = [
81
+ "examples/sprites/server.rb",
82
+ "spec/builders/image_builder.rb",
83
+ "spec/integration_spec.rb",
84
+ "spec/lib/css_spriter_image_spec.rb",
85
+ "spec/lib/sprite_spec.rb",
86
+ "spec/mtime_tracking_spec.rb",
87
+ "spec/spec_helper.rb"
88
+ ]
89
+
90
+ if s.respond_to? :specification_version then
91
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
92
+ s.specification_version = 3
93
+
94
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
95
+ s.add_development_dependency(%q<rspec>, [">= 0"])
96
+ s.add_runtime_dependency(%q<chunky_png>, ["~> 1.1.0"])
97
+ else
98
+ s.add_dependency(%q<rspec>, [">= 0"])
99
+ s.add_dependency(%q<chunky_png>, ["~> 1.1.0"])
100
+ end
101
+ else
102
+ s.add_dependency(%q<rspec>, [">= 0"])
103
+ s.add_dependency(%q<chunky_png>, ["~> 1.1.0"])
104
+ end
105
+ end
106
+
@@ -1,16 +1,7 @@
1
- require 'zlib'
2
-
3
- require 'css-spriter/png/file_header'
4
- require 'css-spriter/png/parser'
5
- require 'css-spriter/png/filters'
6
- require 'css-spriter/png/chunk'
7
- require 'css-spriter/png/ihdr'
8
- require 'css-spriter/png/idat'
9
- require 'css-spriter/png/iend'
10
- require 'css-spriter/png/image'
1
+ require 'chunky_png'
11
2
  require 'css-spriter/sprite'
3
+ require 'css-spriter/image'
12
4
  require 'css-spriter/directory_processor'
13
5
  require 'css-spriter/stylesheet_builder'
14
6
  require 'css-spriter/processor'
15
7
  require 'css-spriter/mtime_tracker'
16
- require 'css-spriter/image_data'
@@ -1,94 +1,98 @@
1
- class DirectoryProcessor
2
-
3
- DEFAULT_TEMPLATE = <<-EOF
4
- .<name>_<image_name> {
5
- background: transparent url(<image_loc>) <offset>px 0px no-repeat;
6
- width:<width>;
7
- height:<height>;
8
- text-indent:-5000px;
9
- }
10
-
11
- EOF
12
-
13
- def initialize(dir, options = {})
14
- @options = options
15
- @dir = dir
16
- @sprite = Sprite.new
17
- @tracker = MtimeTracker.new(@dir,
18
- :exclude => ['sprite.css', 'fragment.css', 'sprite.png'])
19
- end
1
+ module CssSpriter
2
+ class DirectoryProcessor
20
3
 
21
- def images
22
- Dir.glob(@dir + "/*.png").reject{|i| i.match /sprite\.png/}
23
- end
4
+ DEFAULT_TEMPLATE = <<-EOF
5
+ .<name>_<image_name> {
6
+ background: transparent url(<image_loc>) <offset>px 0px no-repeat;
7
+ width:<width>;
8
+ height:<height>;
9
+ text-indent:-5000px;
10
+ }
24
11
 
25
- def write
26
- return unless @tracker.has_changes?
27
- images.each {|f| @sprite.append(PNG::Image.image_data(f))}
28
- @sprite.write(sprite_file)
29
- File.open(css_file, 'w') do |f|
30
- f.write(css)
12
+ EOF
13
+
14
+ def initialize(dir, options = {})
15
+ @options = options
16
+ @dir = dir
17
+ @sprite = Sprite.new
18
+ @tracker = MtimeTracker.new(@dir,
19
+ :exclude => ['sprite.css', 'fragment.css', 'sprite.png'])
31
20
  end
32
- @tracker.update
33
- end
34
21
 
35
- def cleanup
36
- File.delete(sprite_file) rescue nil
37
- File.delete(css_file) rescue nil
38
- @tracker.cleanup
39
- end
22
+ def images
23
+ Dir.glob(@dir + "/*.png").reject{|i| i.match /sprite\.png/}
24
+ end
40
25
 
41
- def sprite_file
42
- @dir + "/sprite.png"
43
- end
26
+ def write
27
+ return unless @tracker.has_changes?
28
+ images.each {|f| @sprite.append_file(f)}
44
29
 
45
- def css_file
46
- @dir + "/fragment.css"
47
- end
30
+ @sprite.write(sprite_file)
48
31
 
49
- def dir_name
50
- @dir.split('/').last
51
- end
32
+ File.open(css_file, 'w') do |f|
33
+ f.write(css)
34
+ end
35
+ @tracker.update
36
+ end
52
37
 
53
- def image_loc
54
- #TODO: Lame!
38
+ def cleanup
39
+ File.delete(sprite_file) rescue nil
40
+ File.delete(css_file) rescue nil
41
+ @tracker.cleanup
42
+ end
55
43
 
56
- dir = truncate_abs_path
57
- base = ("/" + dir + "/sprite.png").gsub(/^\/.\//, "/").gsub("//", "/")
58
- source = @options[:source]
59
- base = base.gsub(source, "") if source && source != "."
60
- base = @options[:path_prefix] + base if @options[:path_prefix]
61
- base
62
- end
44
+ def sprite_file
45
+ @dir + "/sprite.png"
46
+ end
63
47
 
64
- def truncate_abs_path
65
- return @dir unless @options[:source]
66
- path_elements = @options[:source].split('/')
67
- path_elements.pop #we want to remove everything above the root
68
- to_truncate = path_elements.join("/")
69
- @dir.gsub(to_truncate, "")
70
- end
48
+ def css_file
49
+ @dir + "/fragment.css"
50
+ end
71
51
 
72
- def template_file
73
- @dir + "/template.css"
74
- end
52
+ def dir_name
53
+ @dir.split('/').last
54
+ end
55
+
56
+ def image_loc
57
+ #TODO: Lame!
75
58
 
76
- def template
77
- if File.exists?(template_file)
78
- return File.read(template_file)
59
+ dir = truncate_abs_path
60
+ base = ("/" + dir + "/sprite.png").gsub(/^\/.\//, "/").gsub("//", "/")
61
+ source = @options[:source]
62
+ base = base.gsub(source, "") if source && source != "."
63
+ base = @options[:path_prefix] + base if @options[:path_prefix]
64
+ base
65
+ end
66
+
67
+ def truncate_abs_path
68
+ return @dir unless @options[:source]
69
+ path_elements = @options[:source].split('/')
70
+ path_elements.pop #we want to remove everything above the root
71
+ to_truncate = path_elements.join("/")
72
+ @dir.gsub(to_truncate, "")
73
+ end
74
+
75
+ def template_file
76
+ @dir + "/template.css"
77
+ end
78
+
79
+ def template
80
+ if File.exists?(template_file)
81
+ return File.read(template_file)
82
+ end
83
+ return DEFAULT_TEMPLATE
79
84
  end
80
- return DEFAULT_TEMPLATE
81
- end
82
85
 
83
- def css
84
- @sprite.locations.inject("") do |out, image|
85
- image_name, properties = image
86
- out << template.gsub("<name>", dir_name).
87
- gsub("<image_name>", image_name.to_s).
88
- gsub("<width>", properties[:width].to_s).
89
- gsub("<height>", properties[:height].to_s).
90
- gsub("<offset>", properties[:x].to_s).
91
- gsub("<image_loc>", image_loc)
86
+ def css
87
+ @sprite.locations.inject("") do |out, image|
88
+ image_name, properties = image
89
+ out << template.gsub("<name>", dir_name).
90
+ gsub("<image_name>", image_name.to_s).
91
+ gsub("<width>", properties[:width].to_s).
92
+ gsub("<height>", properties[:height].to_s).
93
+ gsub("<offset>", properties[:x].to_s).
94
+ gsub("<image_loc>", image_loc)
95
+ end
92
96
  end
93
97
  end
94
- end
98
+ end
@@ -0,0 +1,13 @@
1
+ module CssSpriter
2
+ class Image < ::ChunkyPNG::Image
3
+ attr_accessor :name
4
+
5
+ def self.from_file( filename )
6
+ name = File.basename( filename, ".png" )
7
+
8
+ image = super
9
+ image.name = name
10
+ image
11
+ end
12
+ end
13
+ end
@@ -1,79 +1,82 @@
1
- class MtimeTracker
2
- def initialize(dir, options = {})
3
- @dir = dir
4
- @options = options
5
- end
1
+ module CssSpriter
2
+ class MtimeTracker
3
+ def initialize(dir, options = {})
4
+ @dir = dir
5
+ @options = options
6
+ end
6
7
 
7
- def cleanup
8
- File.delete(mtime_file) rescue nil
9
- end
8
+ def cleanup
9
+ File.delete(mtime_file) rescue nil
10
+ end
10
11
 
11
- def fresh?
12
- not File.exists?(mtime_file)
13
- end
12
+ def fresh?
13
+ not File.exists?(mtime_file)
14
+ end
14
15
 
15
- def files
16
- return @files if @files
17
- @files = without_exclusions(Dir.glob(@dir + "/**/*"))
18
- end
16
+ def files
17
+ @files = without_exclusions(Dir.glob(@dir + "/**/*"))
18
+ end
19
19
 
20
- def without_exclusions(files)
21
- return files unless @options[:exclude]
22
- exclusions = [@options[:exclude]].flatten
23
- files.select{|f| not exclusions.any?{|e| f.match e}}
24
- end
20
+ def without_exclusions(files)
21
+ return files unless @options[:exclude]
22
+ exclusions = [@options[:exclude]].flatten
23
+ files.select{|f| not exclusions.any?{|e| f.match e}}
24
+ end
25
25
 
26
- def current_mtimes
27
- @current ||= files.inject({}) do |map, f|
28
- map[f] = File.mtime(f).to_i; map
26
+ def current_mtimes
27
+ @current ||= files.inject({}) do |map, f|
28
+ map[f] = File.mtime(f).to_i; map
29
+ end
29
30
  end
30
- end
31
31
 
32
- def file_changed?(file)
33
- mtimes[file] != current_mtimes[file]
34
- end
32
+ def file_changed?(file)
33
+ mtimes[file] != current_mtimes[file]
34
+ end
35
35
 
36
- def mtimes
37
- return @mtimes if @mtimes
38
- return {} unless File.exists?(mtime_file)
39
- @mtimes = read_mtimes
40
- end
36
+ def mtimes
37
+ return @mtimes if @mtimes
38
+ return {} unless File.exists?(mtime_file)
39
+ @mtimes = read_mtimes
40
+ end
41
41
 
42
- def read_mtimes
43
- mtimes = {}
44
- File.open(mtime_file) do |f|
45
- f.each do |line|
46
- name, time = line.split("\t")
47
- mtimes[name] = time.to_i
42
+ def read_mtimes
43
+ mtimes = {}
44
+ File.open(mtime_file) do |f|
45
+ f.each do |line|
46
+ name, time = line.split("\t")
47
+ mtimes[name] = time.to_i
48
+ end
48
49
  end
50
+ mtimes
49
51
  end
50
- mtimes
51
- end
52
52
 
53
- def changeset
54
- files.select{|f| file_changed?(f)}
55
- end
53
+ def changeset
54
+ changed = files.select{|f| file_changed?(f)}
55
+ deleted = without_exclusions(mtimes.keys) - current_mtimes.keys
56
+ changed + deleted
57
+ end
56
58
 
57
- def has_changes?
58
- not changeset.empty?
59
- end
59
+ def has_changes?
60
+ not changeset.empty?
61
+ end
60
62
 
61
- def mtime_file
62
- @dir + "/.mtimes"
63
- end
63
+ def mtime_file
64
+ @dir + "/.mtimes"
65
+ end
64
66
 
65
- def update
66
- File.open(mtime_file, 'w') do |f|
67
- current = current_mtimes
68
- flat = current.map{|k, v| "#{k}\t#{v}\n"}.join
69
- f.write flat
67
+ def update
68
+ File.open(mtime_file, 'w') do |f|
69
+ current = current_mtimes
70
+ flat = current.map{|k, v| "#{k}\t#{v}\n"}.join
71
+ f.write flat
72
+ end
73
+ reset
70
74
  end
71
- reset
72
- end
73
75
 
74
- def reset
75
- @mtimes = nil
76
- @current = nil
77
- @files = nil
76
+ def reset
77
+ @mtimes = nil
78
+ @current = nil
79
+ @files = nil
80
+ end
78
81
  end
79
- end
82
+ end