sprite_generator 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,33 @@
1
+ = SpriteGenerator
2
+
3
+ Automatically generate Sprite Images and the corresponding CSS using RMagick and Liquid.
4
+
5
+ == Dependencies
6
+
7
+ * RMagick 2.2.2
8
+ * Liquid 1.7.0
9
+
10
+ == LICENSE:
11
+
12
+ (The MIT License)
13
+
14
+ Copyright (c) 2009 Marcel Scherf
15
+
16
+ Permission is hereby granted, free of charge, to any person obtaining
17
+ a copy of this software and associated documentation files (the
18
+ 'Software'), to deal in the Software without restriction, including
19
+ without limitation the rights to use, copy, modify, merge, publish,
20
+ distribute, sublicense, and/or sell copies of the Software, and to
21
+ permit persons to whom the Software is furnished to do so, subject to
22
+ the following conditions:
23
+
24
+ The above copyright notice and this permission notice shall be
25
+ included in all copies or substantial portions of the Software.
26
+
27
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
28
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
30
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
31
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
32
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
33
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,37 @@
1
+ require 'yaml'
2
+ require 'ostruct'
3
+ require 'pathname'
4
+ require File.expand_path(File.dirname(__FILE__) + '/sprite_generator')
5
+
6
+ class SpriteBatchGenerator
7
+ attr_reader :batches
8
+
9
+ def initialize(filename)
10
+ config = YAML.load(File.read(filename))
11
+ @batches = config.inject([]) do |arr, pair|
12
+ if !!defined?(RAILS_ROOT)
13
+ pair.last.merge!(:config_root => RAILS_ROOT)
14
+ elsif pair.last[:root]
15
+ root = File.expand_path(pair.last[:root], file_name)
16
+ pair.last.merge!(:config_root => root)
17
+ end
18
+ arr.push OpenStruct.new(pair.last)
19
+ arr
20
+ end
21
+ end
22
+
23
+
24
+ def generate
25
+ @batches.each do |batch|
26
+ generator = SpriteGenerator.new(batch.files, batch.output, batch.config_root, batch.options || {})
27
+ css = generator.create
28
+ # only write output if css_output is specified
29
+ unless css.nil? || css.empty? || batch.css_output.nil?
30
+ output = batch.css_template.nil? ? css : Liquid::Template.parse(File.open(batch.css_template).read).render('css' => css)
31
+ File.open(batch.css_output, 'w+'){|f| f.puts output }
32
+ end
33
+ end
34
+ end
35
+
36
+
37
+ end
@@ -0,0 +1,264 @@
1
+ require 'rubygems'
2
+ require 'RMagick'
3
+ require 'liquid'
4
+
5
+ class SpriteGenerator
6
+ VERSION = '0.1.10'
7
+
8
+ include Magick
9
+
10
+ # parameters:
11
+ # files_or_path: can be Dir.glob-able paths or an array of filenames
12
+ # ie: ['../images/icons/icon1_out.png', '../images/icons/icon1_over.png'] or '../images/icons/icon*.png'
13
+ # output: filename where the generated sprite will be stored
14
+ # ie: '../images/sprites/icons.png'
15
+ # options: set a variety of options
16
+ # - delimiter: characters by which multiple variations of images will be found
17
+ # ie: '_' for 'icon_hover.png'
18
+ # ie: '-' for 'icon-hover.png'
19
+ # if icon is the basename
20
+ # - align:
21
+ # - sprite_location: will be available as variable in the liquid template, if this is not set, the template will use output as sprite_location
22
+ # - tile: if set to ie. '100x100' it will center every image on a 100 by 100 tile
23
+ # - template: Liquid template for each sprite, use this to build the css for your sprites
24
+ # these variables are available:
25
+ # - top: distance to top border of sprite in pixels
26
+ # - left: distance to left border of sprite in pixels
27
+ # - width: width of current image in pixels
28
+ # - height: height of current image in pixels
29
+ # - basename: filename or basename of variations
30
+ # ie: with variations: icon_out.png, icon_over.png => icon
31
+ # ie: without variations: icon.png => icon.png
32
+ # - file_basename: always the name of the current image without extension
33
+ # ie: icon_over
34
+ # - filename: icon_over.png
35
+ # - full_filename: ../images/icons/icon_over.ong
36
+ # - variations: number of variations as number
37
+ # - variation: the current variation as zero based number
38
+ # - sprite_location: path to sprite
39
+ def initialize(files_or_paths, output, root, options = {})
40
+ @files = find_files(files_or_paths)
41
+ return if @files.nil? || @files.empty?
42
+ @root = root || ''
43
+ @output = output
44
+ @delimiter = options[:delimiter] || '-'
45
+ @analyzed = find_files_for_mode(options[:distribution] || :smart)
46
+ @template = Liquid::Template.parse(options[:template] || '')
47
+ @sprite_location = options[:sprite_location] || @output
48
+ @background = options[:background] || '#FFFFFF00'
49
+ @tile_size = options[:tile]
50
+ @alignment = options[:alignment] ? Magick.const_get("#{camelize(options[:alignment])}Gravity") : Magick::CenterGravity
51
+ end
52
+
53
+
54
+ def create
55
+ raise 'No files found.' if @files.nil? || @files.empty?
56
+ build_tile
57
+ destination = @root.nil? || @root.empty? ? @output : File.join(@root, @output)
58
+ image, css = build_sprite_and_css
59
+ background = @background
60
+ image.write(destination){ self.background_color = background }
61
+ css
62
+ end
63
+
64
+ protected
65
+
66
+ def build_sprite_and_css
67
+ background = @background
68
+ @images = ImageList.new{ self.background_color = background }
69
+ context = { 'sprite_location' => @sprite_location }
70
+ @css = []
71
+
72
+ @analyzed.keys.sort.each do |key|
73
+ value = @analyzed[key]
74
+
75
+ context['top'] = 0
76
+ puts "basename: %s" % key
77
+ context['basename'] = key
78
+ context['overall'] = @images.length
79
+ if value.size > 1
80
+ context = build_image_list(context, value.sort)
81
+ else
82
+ context = build_single_image(context, value.flatten.first)
83
+ end
84
+ @css << build_css(context)
85
+ end
86
+ [@images.append(false), @css.join("\n")]
87
+ end
88
+
89
+
90
+ def build_single_image(context, filename)
91
+ background = @background
92
+ image = Image.read(filename){ self.background_color = background }.flatten.first
93
+
94
+ context.merge!(build_context_for_single_image(image, filename, context['basename']))
95
+ if @tile
96
+ @images.from_blob(@tile.composite(image, @alignment, Magick::OverCompositeOp).to_blob){ self.background_color = background }
97
+ else
98
+ @images.from_blob(image.to_blob){ self.background_color = background }
99
+ end
100
+ context
101
+ end
102
+
103
+
104
+ def build_context_for_single_image(image, filename, basename)
105
+ file_basename = File.basename(filename, '.*')
106
+ {
107
+ 'variations' => 0,
108
+ 'variation_number' => 0,
109
+ 'full_filename' => filename,
110
+ 'file_basename' => file_basename,
111
+ 'variation_name' => file_basename.gsub("#{basename}#{@delimiter}", ''),
112
+ 'width' => @tile ? @tile.columns : image.columns,
113
+ 'height' => @tile ? @tile.rows : image.rows,
114
+ 'type' => :image,
115
+ 'left' => left_value_for_context
116
+ }
117
+ end
118
+
119
+
120
+ def left_value_for_context
121
+ @tile ? (@images.length * @tile.columns) : (@images.any? ? @images.append(false).columns : 0)
122
+ end
123
+
124
+
125
+ def build_image_list(context, image_filenames)
126
+ background = @background
127
+ image_list = ImageList.new(*image_filenames){ self.background_color = background }
128
+ context.merge!(build_context_for_image_list(image_list, image_filenames))
129
+ if @tile
130
+ tiles = ImageList.new{ self.background_color = background }
131
+ image_list.each do |image|
132
+ tiles << @tile.composite(image, @alignment, Magick::OverCompositeOp)
133
+ end
134
+ append_to_sprite(tiles)
135
+ else
136
+ append_to_sprite(image_list)
137
+ end
138
+ context
139
+ end
140
+
141
+
142
+ def append_to_sprite(images)
143
+ background = @background
144
+ @images.from_blob(images.append(true).to_blob){ self.background_color = background }
145
+ end
146
+
147
+
148
+ def build_context_for_image_list(image_list, image_filenames)
149
+ {
150
+ 'variations' => image_list.length,
151
+ 'type' => :list,
152
+ 'images' => image_list,
153
+ 'filenames' => image_filenames,
154
+ 'left' => left_value_for_context
155
+ }
156
+ end
157
+
158
+
159
+ def build_tile
160
+ return if @tile_size.nil?
161
+ background = @background
162
+ size_x, size_y = @tile_size.split('x').first(2).map{|dim| dim.to_i}
163
+ @tile = Magick::Image.new(size_x, size_y){ self.background_color = background }
164
+ @tile.format = "PNG"
165
+ end
166
+
167
+
168
+ def build_css(context = {})
169
+ type = context['type']
170
+ case type
171
+ when :list
172
+ css = build_css_for_list(context)
173
+ when :image
174
+ # render template if there is only one image
175
+ css = @template.render(context)
176
+ end
177
+ css
178
+ end
179
+
180
+
181
+ def build_css_for_list(context)
182
+ new_context = context.dup
183
+ image_list = context.delete('images')
184
+ new_context['type'] = :image
185
+ css = image_list.inject([]) do |css, image|
186
+ new_context['width'] = @tile ? @tile.columns : image.columns
187
+ new_context['height'] = @tile ? @tile.rows : image.rows
188
+ new_context['variation_number'] = css.size
189
+ new_context['full_filename'] = context['filenames'].shift
190
+ new_context['filename'] = File.basename(new_context['full_filename'])
191
+ new_context['file_basename'] = File.basename(new_context['full_filename'], '.*')
192
+ new_context['variation_name'] = new_context['file_basename'].gsub("#{new_context['basename']}#{@delimiter}", '')
193
+ css << build_css(new_context.dup)
194
+
195
+ new_context['top'] += @tile ? @tile.rows : new_context['height']
196
+ css
197
+ end.join("\n")
198
+ end
199
+
200
+
201
+ # gather files that will be used to create the sprite
202
+ def find_files(*args)
203
+ args.inject([]) do |files, arg|
204
+ found_files = Dir.glob(arg)
205
+ if found_files.empty?
206
+ files << arg if File.exists?(arg) rescue raise arg.inspect
207
+ else
208
+ files << found_files.flatten
209
+ end
210
+ files.flatten.compact.uniq
211
+ end
212
+ end
213
+
214
+
215
+ # put filenames in format for each mode
216
+ def find_files_for_mode(mode)
217
+ case mode.to_sym
218
+ when :smart
219
+ smart_distribution
220
+ when :horizontal
221
+ horizontal_distribution
222
+ when :vertical
223
+ vertical_distribution
224
+ end
225
+ end
226
+
227
+
228
+ # gather information about the selected files
229
+ # check for variations by using a delimiter as an indicator
230
+ def smart_distribution
231
+ @files.inject(Hash.new{|hash, key| hash[key] = Array.new;}) do |h, file|
232
+ basename = File.basename(file, '.*')
233
+ without_variation = basename.split(@delimiter)[0..-2].join(@delimiter)
234
+ basename = without_variation.nil? || without_variation == '' ? basename : without_variation
235
+ h[basename] << file
236
+ h
237
+ end
238
+ end
239
+
240
+
241
+ def horizontal_distribution
242
+ @files.inject(Hash.new{|hash, key| hash[key] = Array.new;}) do |h, file|
243
+ basename = File.basename(file)
244
+ h[basename] << file
245
+ h
246
+ end
247
+ end
248
+
249
+
250
+ def vertical_distribution
251
+ @files.inject(Hash.new{|hash, key| hash[key] = Array.new;}) do |h, file|
252
+ basename = File.basename(file)
253
+ h['all'] << file
254
+ h
255
+ end
256
+ end
257
+
258
+
259
+ # simplyfied version of active_support's camelize version
260
+ def camelize(lower_case_and_underscored_word)
261
+ lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
262
+ end
263
+
264
+ end
@@ -0,0 +1,35 @@
1
+ require 'test/unit'
2
+ require File.expand_path(File.dirname(__FILE__) + '/../../lib/sprite_batch_generator')
3
+
4
+ class SpriteBatchGeneratorTest < Test::Unit::TestCase
5
+
6
+ def setup
7
+ @config = 'test/config/batch.yml'
8
+ end
9
+
10
+ def teardown
11
+ # delete test output
12
+ Dir.glob('test/output/*').each{|f| File.delete f }
13
+ end
14
+
15
+ def test_should_read_config_file
16
+ @batch = SpriteBatchGenerator.new(@config)
17
+ assert_not_nil @batch
18
+ assert_equal 2, @batch.batches.size
19
+ end
20
+
21
+ def test_should_create_files_from_config
22
+ @batch = SpriteBatchGenerator.new(@config)
23
+ css = @batch.generate
24
+ assert_not_nil css
25
+ output_files = Dir.glob('test/output/*')
26
+ assert 6, output_files.size
27
+ end
28
+
29
+ protected
30
+
31
+ def this_method
32
+ caller[0] =~ /`([^']*)'/ and $1
33
+ end
34
+
35
+ end
@@ -0,0 +1,219 @@
1
+ require 'rubygems'
2
+ require 'liquid'
3
+ require 'test/unit'
4
+ require File.expand_path(File.dirname(__FILE__) + '/../../lib/sprite_generator')
5
+
6
+ class SpriteGeneratorTest < Test::Unit::TestCase
7
+
8
+ def setup
9
+ @template = '.{{basename}}_{{variation}}{ background:transparent url({{sprite_location}}) -{{left}}px -{{top}}px no-repeat; width:{{width}}px; height:{{height}}px; }'
10
+ @all_images_path = 'test/images/*.png'
11
+ @output = 'test/output/sprite_by_create.png'
12
+ @page_path = 'test/output/test.html'
13
+ end
14
+
15
+
16
+ def teardown
17
+ # delete test output
18
+ Dir.glob('test/output/*').each{|f| File.delete f }
19
+ end
20
+
21
+ def test_should_create_correct_sprite_for_tile_with_vertical_distribution
22
+ options = {
23
+ :distribution => 'vertical',
24
+ :tile => '40x300',
25
+ :alignment => 'north_west',
26
+ :template => "a.{{file_basename}} { padding-left:2em; background: transparent url(#{this_method}.png) -{{left}}px -{{top}}px no-repeat; }"
27
+ }
28
+
29
+ generator = SpriteGenerator.new(@all_images_path, "test/output/#{this_method}.png", nil, options)
30
+ css = generator.create
31
+ assert css.include?('-4500px')
32
+
33
+ page = Liquid::Template.parse(File.open('test/templates/link.html').read).render('css' => css, 'image' => "#{this_method}.png")
34
+ output_file = File.join('test', 'output', "#{this_method}.html")
35
+ File.open(output_file, 'w+'){ |f| f.puts page }
36
+ assert File.exists?(output_file)
37
+ end
38
+
39
+
40
+ def test_should_create_correct_sprite_for_tile_with_vertical_distribution
41
+ options = {
42
+ :distribution => 'vertical',
43
+ :tile => '40x300',
44
+ :alignment => 'north_west',
45
+ :template => "a.{{file_basename}} { padding-left:2em; background: transparent url(#{this_method}.png) -{{left}}px -{{top}}px no-repeat; }"
46
+ }
47
+
48
+ generator = SpriteGenerator.new(@all_images_path, "test/output/#{this_method}.png", nil, options)
49
+ css = generator.create
50
+ assert css.include?('-4500px')
51
+
52
+ page = Liquid::Template.parse(File.open('test/templates/link.html').read).render('css' => css, 'image' => "#{this_method}.png")
53
+ output_file = File.join('test', 'output', "#{this_method}.html")
54
+ File.open(output_file, 'w+'){ |f| f.puts page }
55
+ assert File.exists?(output_file)
56
+ end
57
+
58
+
59
+
60
+ def test_should_create_correct_sprite_for_tile_with_horizontal_distribution
61
+ options = {
62
+ :distribution => 'horizontal',
63
+ :tile => '400x50',
64
+ :alignment => 'north_west',
65
+ :template => "a.{{file_basename}} { padding-left:2em; background: transparent url(#{this_method}.png) -{{left}}px -{{top}}px no-repeat; }"
66
+ }
67
+
68
+ generator = SpriteGenerator.new(@all_images_path, "test/output/#{this_method}.png", nil, options)
69
+ css = generator.create
70
+ assert css.include?('-6000px')
71
+
72
+ page = Liquid::Template.parse(File.open('test/templates/link.html').read).render('css' => css, 'image' => "#{this_method}.png")
73
+ output_file = File.join('test', 'output', "#{this_method}.html")
74
+ File.open(output_file, 'w+'){ |f| f.puts page }
75
+ assert File.exists?(output_file)
76
+ end
77
+
78
+
79
+ def test_should_user_horizontal_distribution
80
+ template = %q{ {{left}} }
81
+ generator = SpriteGenerator.new(@all_images_path, @output, nil, { :template => template, :distribution => 'horizontal' })
82
+ css = generator.create
83
+ assert css.include?('240')
84
+ end
85
+
86
+ def test_should_user_vertical_distribution
87
+ template = %q{ {{top}} }
88
+ generator = SpriteGenerator.new(@all_images_path, @output, nil, { :template => template, :distribution => 'vertical' })
89
+ css = generator.create
90
+ assert css.include?('240')
91
+ end
92
+
93
+ def test_should_set_correct_context_filebasename_for_images_without_variations
94
+ template = %q{ {{file_basename}} }
95
+ generator = SpriteGenerator.new(@all_images_path, @output, nil, { :template => template, :delimiter => '_' })
96
+ css = generator.create
97
+ assert css.include?('emoticon-evilgrin')
98
+ end
99
+
100
+ def test_should_set_correct_context_width_for_images_without_variations
101
+ template = %q{ {{width}} }
102
+ generator = SpriteGenerator.new(@all_images_path, @output, nil, { :template => template, :delimiter => '_' })
103
+ css = generator.create
104
+ assert css.include?('16')
105
+ end
106
+
107
+ def test_should_set_correct_context_top_for_images_without_variations
108
+ template = %q{ {{top}} }
109
+ generator = SpriteGenerator.new(@all_images_path, @output, nil, { :template => template, :delimiter => '_' })
110
+ css = generator.create
111
+ assert !css.include?('-16')
112
+ end
113
+
114
+ def test_should_create_correct_context
115
+ template = %q{
116
+ basename: {{basename}}
117
+ variation: {{variation}}
118
+ sprite_location: {{sprite_location}}
119
+ left: {{left}}
120
+ top: {{top}}
121
+ width: {{width}}
122
+ height: {{height}}
123
+ filename: {{filename}}
124
+ file_basename: {{file_basename}}
125
+ full_filename: {{full_filename}}
126
+ variations: {{variations}}
127
+ variation_number: {{variation_number}}
128
+ variation_name: {{variation_name}}
129
+ }
130
+ generator = SpriteGenerator.new(@all_images_path, @output, nil, {:template => template})
131
+ css = generator.create
132
+ assert css.include?('basename: emoticon-evilgrin')
133
+ assert css.include?('variation_name: evilgrin')
134
+ assert css.include?('file_basename: emoticon-evilgrin')
135
+ end
136
+
137
+ def test_should_use_alignment_option
138
+ assert_nothing_raised do
139
+ SpriteGenerator.new(@all_images_path, @output, nil, {:template => @template, :tile => '100x100', :background => '#FFFFFF', :alignment => 'west'})
140
+ end
141
+ end
142
+
143
+ def test_should_complain_over_unknown_alignment_option
144
+ assert_raise NameError do
145
+ SpriteGenerator.new(@all_images_path, @output, nil, {:template => @template, :tile => '100x100', :background => '#FFFFFF', :alignment => 'somewhere'})
146
+ end
147
+ end
148
+
149
+ def test_should_center_images_on_tiles
150
+ @generator = SpriteGenerator.new(@all_images_path, @output, nil, {:template => @template, :tile => '100x100', :background => '#FFFFFF00'})
151
+ css = @generator.create
152
+ page = Liquid::Template.parse(File.open('test/templates/test.html').read).render('css' => css)
153
+ assert page.include?("{ background:")
154
+ assert page.include?("width:100px")
155
+ assert page.include?("height:100px")
156
+ assert page.include?("-300px")
157
+ assert page.include?("-800px")
158
+ File.open(@page_path, 'w+'){|f| f.puts page }
159
+ assert File.exists?(@page_path)
160
+ end
161
+
162
+
163
+ def test_should_create_correct_css
164
+ @generator = SpriteGenerator.new(@all_images_path, @output, nil, :template => @template)
165
+ css = @generator.create()
166
+ page = Liquid::Template.parse(File.open('test/templates/test.html').read).render('css' => css)
167
+ assert page.include?("{ background:")
168
+ assert page.include?("width:16px")
169
+ assert page.include?("height:16px")
170
+ assert page.include?("-16px")
171
+ assert page.include?("-96px")
172
+ File.open(@page_path, 'w+'){|f| f.puts page }
173
+ assert File.exists?(@page_path)
174
+ end
175
+
176
+
177
+ def test_should_generate_sprite_file
178
+ @generator = SpriteGenerator.new(@all_images_path, @output, nil, :template => @template)
179
+ css = @generator.create
180
+ assert !(css.nil? || css.empty?)
181
+ assert File.exists?(@output)
182
+ end
183
+
184
+ # bad, testing internal state
185
+ def test_should_find_versions_of_emoticons
186
+ files = Dir.glob(@all_images_path)
187
+ @generator = SpriteGenerator.new(files, @output, nil, {})
188
+ analyzed = @generator.instance_variable_get(:@analyzed)
189
+ assert_equal 9, analyzed['emoticon'].size
190
+ end
191
+
192
+ # bad, using internal state
193
+ def test_should_find_files_for_glob_path
194
+ @generator = SpriteGenerator.new(@all_images_path, @output, nil, {})
195
+ files = @generator.instance_variable_get(:@files)
196
+ assert_equal 16, files.size
197
+ end
198
+
199
+ # bad, using internal state
200
+ def test_should_find_files
201
+ @generator = SpriteGenerator.new(['test/images/emoticon-evilgrin.png', 'test/images/emoticon-grin.png'], @output, nil, {})
202
+ files = @generator.instance_variable_get(:@files)
203
+ assert_equal 2, files.size
204
+ end
205
+
206
+ # bad, using internal state
207
+ def test_should_not_find_anything
208
+ @generator = SpriteGenerator.new('test/blalala/*.hurz', @output, nil, {})
209
+ files = @generator.instance_variable_get(:@files)
210
+ assert_equal 0, files.size
211
+ end
212
+
213
+ protected
214
+
215
+ def this_method
216
+ caller[0] =~ /`([^']*)'/ and $1
217
+ end
218
+
219
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sprite_generator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.4
5
+ platform: ruby
6
+ authors:
7
+ - Marcel Scherf
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-12-08 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: liquid
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: rmagick
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description:
36
+ email: marcel.scherf@gmail.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README.txt
43
+ files:
44
+ - lib/sprite_batch_generator.rb
45
+ - lib/sprite_generator.rb
46
+ - README.txt
47
+ has_rdoc: true
48
+ homepage: http://github.com/the-architect/spritegenerator
49
+ licenses: []
50
+
51
+ post_install_message:
52
+ rdoc_options:
53
+ - --charset=UTF-8
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ version:
68
+ requirements: []
69
+
70
+ rubyforge_project:
71
+ rubygems_version: 1.3.5
72
+ signing_key:
73
+ specification_version: 3
74
+ summary: Automatically generate Sprite Images and the corresponding CSS using RMagick and Liquid.
75
+ test_files:
76
+ - test/units/test_sprite_batch_generator.rb
77
+ - test/units/test_sprite_generator.rb