spriter 0.6.0

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.
Files changed (5) hide show
  1. data/README +0 -0
  2. data/Rakefile +55 -0
  3. data/lib/rack/spriter.rb +48 -0
  4. data/lib/spriter.rb +80 -0
  5. metadata +68 -0
data/README ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,55 @@
1
+ require "rubygems"
2
+ require "rake/gempackagetask"
3
+ require "rake/rdoctask"
4
+
5
+ require "rake/testtask"
6
+ Rake::TestTask.new do |t|
7
+ t.pattern = 'test/*_test.rb'
8
+ t.verbose = true
9
+ end
10
+
11
+ task :default => ["test"]
12
+
13
+ spec = Gem::Specification.new do |s|
14
+
15
+ # Change these as appropriate
16
+ s.name = "spriter"
17
+ s.version = "0.6.0"
18
+ s.summary = "Managers sprites and your css in a mega way."
19
+ s.author = "Reevoo"
20
+ s.homepage = "http://www.reevoo.com"
21
+
22
+ s.has_rdoc = true
23
+ s.extra_rdoc_files = %w(README)
24
+ s.rdoc_options = %w(--main README)
25
+
26
+ # Add any extra files to include in the gem (like your README)
27
+ s.files = %w(Rakefile) + Dir.glob("{test,lib/**/*}")
28
+ s.require_paths = ["lib"]
29
+
30
+ s.add_development_dependency("shoulda")
31
+ end
32
+
33
+ # This task actually builds the gem. We also regenerate a static
34
+ # .gemspec file, which is useful if something (i.e. GitHub) will
35
+ # be automatically building a gem for this project. If you're not
36
+ # using GitHub, edit as appropriate.
37
+ Rake::GemPackageTask.new(spec) do |pkg|
38
+ pkg.gem_spec = spec
39
+
40
+ # Generate the gemspec file for github.
41
+ file = File.dirname(__FILE__) + "/#{spec.name}.gemspec"
42
+ File.open(file, "w") {|f| f << spec.to_ruby }
43
+ end
44
+
45
+ # Generate documentation
46
+ Rake::RDocTask.new do |rd|
47
+
48
+ rd.rdoc_files.include("lib/**/*.rb")
49
+ rd.rdoc_dir = "rdoc"
50
+ end
51
+
52
+ desc 'Clear out RDoc and generated packages'
53
+ task :clean => [:clobber_rdoc, :clobber_package] do
54
+ rm "#{spec.name}.gemspec"
55
+ end
@@ -0,0 +1,48 @@
1
+ require 'spriter'
2
+
3
+ module Rack
4
+ class Spriter
5
+
6
+ File = ::File
7
+
8
+ def initialize(app, options = {})
9
+ @app = app
10
+ ::Spriter.assets_path = options[:assets_path] || File.join(Rails.root, *%w[ public images sprite_assets ])
11
+ ::Spriter.sprite_image_path = options[:sprite_image_path] || File.join(Rails.root, *%w[ public images sprites.png ])
12
+ ::Spriter.sprite_image_url = options[:sprite_image_url] || '/images/sprites.png'
13
+ end
14
+
15
+ def call(env)
16
+ if css = generate_css(env)
17
+ return [200, {"Content-Type" => "text/css", "Cache-Control" => "private"}, [css]]
18
+ else
19
+ @app.call(env)
20
+ end
21
+ end
22
+
23
+ private
24
+ def generate_css(env)
25
+ if Rack::Request.new(env).path =~ %r{stylesheets\/(.+)\.css$}
26
+ name = $1
27
+ spriter_path = File.join(Rails.root, 'public', 'stylesheets', "#{name}.spriter")
28
+ generated_css($1) if File.exist? spriter_path
29
+ end
30
+ end
31
+
32
+ def generated_css(name)
33
+ paths = Dir.glob(File.join(Rails.root, 'public', 'stylesheets', '*.spriter'))
34
+ paths.sort!
35
+ files = paths.map{ |p| File.new(p, 'r') }
36
+
37
+ if @generated_css.nil? or files.max{ |a,b| a.mtime <=> b.mtime }.mtime > @generated_at
38
+ names = paths.map{ |p| p =~ %r{stylesheets/(.+)\.spriter$}; $1 }
39
+ css = ::Spriter.transform(*files)
40
+ css = [css] unless css.is_a? Array
41
+ @generated_at = Time.now
42
+ @generated_css = Hash[*names.zip(css).flatten]
43
+ end
44
+
45
+ @generated_css[name]
46
+ end
47
+ end
48
+ end
data/lib/spriter.rb ADDED
@@ -0,0 +1,80 @@
1
+ require 'mini_magick'
2
+
3
+ class Spriter
4
+ class << self
5
+ attr_accessor :assets_path
6
+ attr_accessor :sprite_image_path
7
+ attr_accessor :sprite_image_url
8
+
9
+ def transform(*args)
10
+ new(assets_path, sprite_image_path, sprite_image_url).transform(*args)
11
+ end
12
+
13
+ def transform_files(*args)
14
+ new(assets_path, sprite_image_path, sprite_image_url).transform_files(*args)
15
+ end
16
+
17
+ def image_dimensions(path)
18
+ magick_image = MiniMagick::Image.from_file(path)
19
+ return magick_image[:width], magick_image[:height]
20
+ end
21
+ end
22
+
23
+ def initialize(assets_path, sprite_image_path, sprite_image_url)
24
+ @assets_path, @sprite_image_path, @sprite_image_url = assets_path, sprite_image_path, sprite_image_url
25
+ @images = []
26
+ @y_offsets = {}
27
+ @current_offset, @max_width = 0, 0
28
+ end
29
+
30
+ def transform(*inputs)
31
+ image_matcher = /([^a-z])-spriter-background:\s*([^;\}]+)([;\}])/
32
+ new_css = inputs.inject([]) do |new_css, css|
33
+ css = css.read if css.respond_to? :read
34
+ new_css << css.gsub(image_matcher) do |matched|
35
+ indent = $1
36
+ terminator = $3
37
+ image = $2.strip.gsub(/(?:^['"]|['"]$)/, '')
38
+ add_image(image)
39
+ "#{indent}background: url(#{@sprite_image_url}) no-repeat 0 #{-y_offset(image)}#{y_offset(image) == 0 ? '' : 'px'}#{terminator} /* #{image} */"
40
+ end
41
+ end
42
+
43
+ generate_sprite_image
44
+
45
+ if new_css.length == 1
46
+ new_css.first
47
+ else
48
+ new_css
49
+ end
50
+ end
51
+
52
+ def transform_files(*paths)
53
+ files = paths.map{ |p| File.open(p, 'r') }
54
+ generated_css = transform(*files)
55
+ paths.map{ |p| p.sub(/\.spriter$/, '.css') }.each_with_index do |output_path, i|
56
+ File.open(output_path, 'w'){ |f| f << generated_css[i] }
57
+ end
58
+ end
59
+
60
+ def add_image(image)
61
+ return if @images.include? image
62
+
63
+ width, height = self.class.image_dimensions(File.join(@assets_path, image))
64
+
65
+ @images << image
66
+ @y_offsets[image] = @current_offset
67
+ @current_offset += height
68
+ @max_width = [@max_width, width].max
69
+ end
70
+
71
+ def y_offset(image)
72
+ @y_offsets[image] or raise ArgumentError, 'Unknown image'
73
+ end
74
+
75
+ def generate_sprite_image
76
+ return unless @images.any?
77
+ source_paths = @images.map{ |file| File.join(@assets_path, file) }
78
+ system(*['convert', source_paths, '-gravity', 'West', '-background', '#FFFFFF00', '-append', @sprite_image_path].flatten) or raise "Failed to generate sprite"
79
+ end
80
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spriter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.6.0
5
+ platform: ruby
6
+ authors:
7
+ - Reevoo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-26 00:00:00 +00:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: shoulda
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description:
26
+ email:
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README
33
+ files:
34
+ - Rakefile
35
+ - lib/rack/spriter.rb
36
+ - lib/spriter.rb
37
+ - README
38
+ has_rdoc: true
39
+ homepage: http://www.reevoo.com
40
+ licenses: []
41
+
42
+ post_install_message:
43
+ rdoc_options:
44
+ - --main
45
+ - README
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ requirements: []
61
+
62
+ rubyforge_project:
63
+ rubygems_version: 1.3.5
64
+ signing_key:
65
+ specification_version: 3
66
+ summary: Managers sprites and your css in a mega way.
67
+ test_files: []
68
+