sprite_generator 0.2.4

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.
@@ -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