amikula-sprite 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.md +193 -0
- data/Rakefile +38 -0
- data/VERSION +1 -0
- data/bin/sprite +8 -0
- data/lib/sprite.rb +28 -0
- data/lib/sprite/builder.rb +185 -0
- data/lib/sprite/config.rb +48 -0
- data/lib/sprite/image_combiner.rb +35 -0
- data/lib/sprite/image_config.rb +40 -0
- data/lib/sprite/image_reader.rb +10 -0
- data/lib/sprite/image_resizer.rb +19 -0
- data/lib/sprite/image_writer.rb +27 -0
- data/lib/sprite/runner.rb +32 -0
- data/lib/sprite/sass_extensions.rb +81 -0
- data/lib/sprite/styles.rb +22 -0
- data/lib/sprite/styles/css_generator.rb +36 -0
- data/lib/sprite/styles/sass_generator.rb +43 -0
- data/lib/sprite/styles/sass_mixin_generator.rb +46 -0
- data/lib/sprite/styles/sass_yml_generator.rb +53 -0
- data/lib/sprite/styles/templated_css_generator.rb +41 -0
- data/rails/init.rb +2 -0
- data/tasks/sprite_tasks.rake +13 -0
- metadata +78 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 [Richard Huang (flyerhzm@gmail.com)]
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
# sprite #
|
2
|
+
|
3
|
+
`sprite` is a gem that helps generate css sprite images automagically. It's aim is to support all web frameworks (Merb/Rails/Sinatra), and have extensible output generator. By default, it supports CSS and SASS output (via mixins).
|
4
|
+
|
5
|
+
## INSTALL ##
|
6
|
+
|
7
|
+
### Install the `rmagick` gem ###
|
8
|
+
|
9
|
+
`sprite` currently requires the rmagick gem. to install it, use
|
10
|
+
|
11
|
+
gem install rmagick
|
12
|
+
|
13
|
+
if you have any problems with the rmagick gem, install imagemagick via macports first:
|
14
|
+
|
15
|
+
sudo port install libxml2
|
16
|
+
sudo port install ImageMagick
|
17
|
+
|
18
|
+
or via installer: http://github.com/maddox/magick-installer/tree/master
|
19
|
+
|
20
|
+
### Install the `sprite` gem ###
|
21
|
+
|
22
|
+
Install the `sprite` gem from gemcutter
|
23
|
+
|
24
|
+
gem sources -a http://gemcutter.org
|
25
|
+
gem install sprite
|
26
|
+
|
27
|
+
## USAGE ##
|
28
|
+
|
29
|
+
if installed as a gem, at your root project folder you can just run
|
30
|
+
|
31
|
+
sprite
|
32
|
+
|
33
|
+
### Intelligent Defaults ###
|
34
|
+
|
35
|
+
Without having to configure anything, `sprite` will allow you to easily generate sprites based on a couple default folder settings we give you right off the bat.
|
36
|
+
|
37
|
+
For example, given you have the following setup:
|
38
|
+
|
39
|
+
public/
|
40
|
+
images/
|
41
|
+
sprites/
|
42
|
+
black-icons/
|
43
|
+
stop.png
|
44
|
+
go.png
|
45
|
+
back.png
|
46
|
+
forward.png
|
47
|
+
|
48
|
+
weather/
|
49
|
+
sunny.gif
|
50
|
+
rainy.gif
|
51
|
+
cloudy.gif
|
52
|
+
|
53
|
+
Running `sprite` with no configuration file will generate the following new files:
|
54
|
+
|
55
|
+
public/
|
56
|
+
stylesheets/
|
57
|
+
sprites.css
|
58
|
+
images/
|
59
|
+
sprites/
|
60
|
+
black-icons.png
|
61
|
+
weather.png
|
62
|
+
|
63
|
+
Any folders within `public/images/sprites/` will get compressed into a merged image file at the same
|
64
|
+
location. Then `sprites.css` will get generated in the stylesheets folder with all the class definitions for
|
65
|
+
these files. Just add a link to `sprites.css` into your html <head> and you're ready to go!
|
66
|
+
|
67
|
+
|
68
|
+
## CONFIGURATION ##
|
69
|
+
|
70
|
+
Configuration of `sprite` is done via `config/sprite.yml`. It allows you to set sprite configuration options, and fine tune exactly which sprites get generated where.
|
71
|
+
|
72
|
+
* `config:` section defines all the global properties for sprite generation. Such as how it generates the styles, where it looks for images, where it writes it output file to, and what image file format it uses by default
|
73
|
+
- `style:` defines how the style rules are outputted. built in options are `css`, `sass`, and `sass_mixin`. (defaults to `css`)
|
74
|
+
- `style_output_path:` defines the file path where your style settings get written (defaults to `stylesheets/sprites`). the file extension not needed as it will be set based on the `style:` setting
|
75
|
+
- `image_output_path:` defines the folder path where the combined sprite images files are written (defaults to `images/sprites/`)
|
76
|
+
- `css_image_path:` defines the path used in css to find sprite image files (defaults to `/images/sprites/`)
|
77
|
+
- `image_source_path:` defines the folder where source image files are read from (defaults to `images/`)
|
78
|
+
- `public_path:` defines the root folder where static assets live (defaults to `public/`)
|
79
|
+
- `sprites_class:` defines the class name that gets added to all sprite stylesheet rules (defaults to `sprites`)
|
80
|
+
- `default_format:` defines the default file image format of the generated files. (defaults to `png`)
|
81
|
+
- `default_spacing:` defines the default pixel spacing between sprites (defaults to 0)
|
82
|
+
- `resize_to:` width and height (in the format "120x60") to resize all source images to before composition. (defaults to no nil, or no resizing)
|
83
|
+
- `class_separator:` used to generated the class name by separating the image name and sprite name (defaults to `-`)
|
84
|
+
- `add_datestamps`: whether or not to add datestamps to the generated background image urls. this will allow proper cache versioning (defaults to `true`)
|
85
|
+
|
86
|
+
* `images:` section provides an array of configurations which define which image files are built, and where they get their sprites from. each image setup provides the following config options:
|
87
|
+
- `name:` name of image (required)
|
88
|
+
- `sources:` defines a list of source image filenames to build the target image from (required). They are parsed by <code>Dir.glob</code>
|
89
|
+
- `align:` defines the composite gravity type, horizontal or vertical. (defaults to `vertical`)
|
90
|
+
- `spaced_by:` spacing (in pixels) between the combined images. (defaults to `0`)
|
91
|
+
- `resize_to:` width and height (in the format "120x60") to resize all source images to before composition. (defaults to no nil, or no resizing)
|
92
|
+
- `format:` define what image file format gets created (optional, uses `default_format` setting if not set)
|
93
|
+
|
94
|
+
All image and style paths should be set relative to the public folder (which is configurable via public_path setting).
|
95
|
+
|
96
|
+
### Sample Configuration `config/sprite.yml` ###
|
97
|
+
|
98
|
+
# defines the base configuration options (file paths, etc, default style, etc)
|
99
|
+
|
100
|
+
config:
|
101
|
+
style: css
|
102
|
+
style_output_path: stylesheets/sprites
|
103
|
+
image_output_path: images/sprites/
|
104
|
+
image_source_path: images/
|
105
|
+
public_path: public/
|
106
|
+
sprites_class: 'sprites'
|
107
|
+
class_separator: '-'
|
108
|
+
default_format: png
|
109
|
+
default_spacing: 50
|
110
|
+
|
111
|
+
# defines what sprite collections get created
|
112
|
+
images:
|
113
|
+
|
114
|
+
# creates a public/images/sprites/blue_stars.png image with 4 sprites in it
|
115
|
+
- name: blue_stars
|
116
|
+
format: png
|
117
|
+
align: horizontal
|
118
|
+
spaced_by: 50
|
119
|
+
sources:
|
120
|
+
- icons/blue-stars/small.png
|
121
|
+
- icons/blue-stars/medium.png
|
122
|
+
- icons/blue-stars/large.png
|
123
|
+
- icons/blue-stars/xlarge.png
|
124
|
+
|
125
|
+
# creates a public/images/sprites/green-stars.jpg image with
|
126
|
+
# all the gif files contained within /images/icons/green-stars/
|
127
|
+
- name: green_stars
|
128
|
+
format: png
|
129
|
+
align: vertical
|
130
|
+
spaced_by: 50
|
131
|
+
sources:
|
132
|
+
- icons/green-stars/*.gif
|
133
|
+
|
134
|
+
### Style Settings ###
|
135
|
+
|
136
|
+
By default, it will use with `style: css` and generate the file at `public/stylesheets/sprites.css`
|
137
|
+
|
138
|
+
.sprites.blue-stars-small {
|
139
|
+
background: url('/images/icons/blue-stars/small.png') no-repeat 0px 0px;
|
140
|
+
width: 12px;
|
141
|
+
height: 6px;
|
142
|
+
}
|
143
|
+
.sprites.blue-stars-medium {
|
144
|
+
background: url('/images/icons/blue-stars/medium.png') no-repeat 0px 6px;
|
145
|
+
width: 30px;
|
146
|
+
height: 15px;
|
147
|
+
}
|
148
|
+
.sprites.blue-stars-large {
|
149
|
+
background: url('/images/icons/blue-stars/large.png') no-repeat 0px 21px;
|
150
|
+
width: 60px;
|
151
|
+
height: 30px;
|
152
|
+
}
|
153
|
+
.sprites.blue-stars-xlarge {
|
154
|
+
background: url('/images/icons/blue-stars/xlarge.png') no-repeat 0px 96px;
|
155
|
+
width: 100px;
|
156
|
+
height: 75px;
|
157
|
+
}
|
158
|
+
|
159
|
+
We also support mixin syntax via `style: sass_mixin`. If set, it will generate a SASS mixin which you can use in order to mix in these sprites anywhere within your SASS stylesheets. For this option, set `style_output_path:` to `stylesheets/sass/_sprites` in order to generate the sass mixin file at `stylesheets/sass/_sprites.sass`
|
160
|
+
|
161
|
+
@import "sass/mixins/sprites.sass"
|
162
|
+
|
163
|
+
// you can then use your sprite like this
|
164
|
+
.largebluestar
|
165
|
+
+sprite("blue-stars", "large")
|
166
|
+
|
167
|
+
.mysmallbluestar
|
168
|
+
+sprite("blue-stars", "small")
|
169
|
+
|
170
|
+
Additional style generators are very easy to add. We have one for `style: sass` and `style: sass_ext`. The `sass_ext` style is a work in progress, as it's attempting to write the sprite data to yml and use a dynamic sass extension to provide the mixin. Eventually, if it works, this will be the default for `sass_mixin`
|
171
|
+
|
172
|
+
## Framework Integration?? ##
|
173
|
+
|
174
|
+
`sprite` is provided as a command line helper. Deep web framework integration is not implemented at this time, however it shouldn't be needed. Just generate your sprites on your dev machine by running the command line, check in the resulting sprite images and stylesheets to your source control, and deploy!
|
175
|
+
|
176
|
+
You can also easily script it out via capistrano. You could also run `sprite` on application start, or just about anywhere. Let me know what limitations you run into.
|
177
|
+
|
178
|
+
## ABOUT `sprite` ##
|
179
|
+
|
180
|
+
`sprite` was originally based off of Richard Huang's excellent Rails plugin: [css_sprite](http://github.com/flyerhzm/css_sprite)
|
181
|
+
|
182
|
+
Since then it's been rebuilt (with some reuse of the image generation code) to be a general purpose ruby executable, with hooks for merb/rails/sinatra
|
183
|
+
|
184
|
+
|
185
|
+
## LICENSE ##
|
186
|
+
|
187
|
+
Released under the MIT License
|
188
|
+
|
189
|
+
## COPYRIGHT ##
|
190
|
+
|
191
|
+
Copyright (c) 2009 Gist
|
192
|
+
|
193
|
+
Original Codebase Copyright (c) 2009 [Richard Huang]
|
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'spec/rake/spectask'
|
3
|
+
require 'jeweler'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :spec
|
7
|
+
|
8
|
+
desc "Run all specs in spec directory"
|
9
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
10
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
11
|
+
end
|
12
|
+
|
13
|
+
namespace :spec do
|
14
|
+
desc "Run all specs in spec directory with RCov"
|
15
|
+
Spec::Rake::SpecTask.new(:rcov) do |t|
|
16
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
17
|
+
t.rcov = true
|
18
|
+
t.rcov_opts = ["--exclude spec/*,gems/*,lib/tasks/*,app/analytics/application_metrics.rb"]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
Jeweler::Tasks.new do |gemspec|
|
25
|
+
gemspec.name = "amikula-sprite"
|
26
|
+
gemspec.summary = "generate your css sprites automagically"
|
27
|
+
gemspec.description = "sprite is a rails/merb plugin that generates sprites for css, sass"
|
28
|
+
gemspec.email = "amikula@gmail.com"
|
29
|
+
gemspec.homepage = "http://github.com/amikula/sprite"
|
30
|
+
gemspec.authors = ["Jacques Crocker", "Alf Mikula"]
|
31
|
+
gemspec.files.exclude '.gitignore'
|
32
|
+
|
33
|
+
# removing test files and specs from the gem to save space
|
34
|
+
gemspec.files -= Dir.glob("spec/**/*")
|
35
|
+
gemspec.test_files = []
|
36
|
+
end
|
37
|
+
Jeweler::GemcutterTasks.new
|
38
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.8
|
data/bin/sprite
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# The compass command line utility
|
3
|
+
|
4
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'sprite'))
|
5
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'sprite', 'runner'))
|
6
|
+
|
7
|
+
command = Sprite::Runner.new(ARGV)
|
8
|
+
exit command.run!
|
data/lib/sprite.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Sprite
|
2
|
+
|
3
|
+
# provides the root directory to use when reading and writing files
|
4
|
+
def self.root
|
5
|
+
@root ||= nil
|
6
|
+
|
7
|
+
# set the root to the framework setting (if not already set)
|
8
|
+
@root ||= begin
|
9
|
+
if defined?(Rails)
|
10
|
+
Rails.root
|
11
|
+
elsif defined?(Merb)
|
12
|
+
Merb.root
|
13
|
+
else
|
14
|
+
"."
|
15
|
+
end
|
16
|
+
end
|
17
|
+
@root
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'sprite/builder'
|
22
|
+
require 'sprite/config'
|
23
|
+
require 'sprite/image_combiner'
|
24
|
+
require 'sprite/image_config'
|
25
|
+
require 'sprite/image_reader'
|
26
|
+
require 'sprite/image_resizer'
|
27
|
+
require 'sprite/image_writer'
|
28
|
+
require 'sprite/styles'
|
@@ -0,0 +1,185 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
module Sprite
|
3
|
+
class Builder
|
4
|
+
attr_reader :config
|
5
|
+
attr_reader :images
|
6
|
+
|
7
|
+
def self.from_config(path = nil)
|
8
|
+
results = Config.read_config(path)
|
9
|
+
new(results["config"], results["images"])
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(config = nil, images = nil)
|
13
|
+
@config = config || {}
|
14
|
+
set_config_defaults
|
15
|
+
|
16
|
+
@images = images || []
|
17
|
+
if @images.empty?
|
18
|
+
@images = default_images
|
19
|
+
end
|
20
|
+
expand_image_paths
|
21
|
+
|
22
|
+
# initialize datestamp
|
23
|
+
@datestamp_query = "?#{Time.now.to_i}" if @config["add_datestamps"]
|
24
|
+
|
25
|
+
# initialize sprite files
|
26
|
+
@sprite_files = {}
|
27
|
+
end
|
28
|
+
|
29
|
+
def build
|
30
|
+
@sprite_files = {}
|
31
|
+
|
32
|
+
if images.size > 0
|
33
|
+
# create images
|
34
|
+
images.each do |image|
|
35
|
+
write_image(image)
|
36
|
+
end
|
37
|
+
|
38
|
+
if @sprite_files.values.length > 0
|
39
|
+
# write css
|
40
|
+
write_styles
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# get the disk path for the style output file
|
46
|
+
def style_output_path(relative = false)
|
47
|
+
style = Styles.get(config["style"]).new(self)
|
48
|
+
|
49
|
+
path = config['style_output_path']
|
50
|
+
unless path.include?(".#{style.extension}")
|
51
|
+
path = "#{path}.#{style.extension}"
|
52
|
+
end
|
53
|
+
Config.new(config).public_path(path, relative)
|
54
|
+
end
|
55
|
+
|
56
|
+
def image_path(group)
|
57
|
+
image_info = images.detect{|image| image['name'] == group}
|
58
|
+
image_config = ImageConfig.new(image_info, config)
|
59
|
+
sprite_file = "#{image_config.name}.#{image_config.format}"
|
60
|
+
"#{config['css_image_path']}#{sprite_file}"
|
61
|
+
end
|
62
|
+
|
63
|
+
protected
|
64
|
+
def write_image(image_info)
|
65
|
+
results = []
|
66
|
+
image_config = ImageConfig.new(image_info, config)
|
67
|
+
sources = image_config.sources
|
68
|
+
return unless sources.length > 0
|
69
|
+
|
70
|
+
name = image_config.name
|
71
|
+
resizer = ImageResizer.new(image_config.resize_to)
|
72
|
+
combiner = ImageCombiner.new(image_config)
|
73
|
+
|
74
|
+
# Let's get the sprite started with the first image
|
75
|
+
first_image = ImageReader.read(sources.shift)
|
76
|
+
resizer.resize(first_image)
|
77
|
+
|
78
|
+
dest_image = first_image
|
79
|
+
results << combiner.image_properties(dest_image).merge(:x => 0, :y => 0, :group => name)
|
80
|
+
|
81
|
+
# Now let's add the rest of the images in turn
|
82
|
+
sources.each do |source|
|
83
|
+
source_image = ImageReader.read(source)
|
84
|
+
resizer.resize(source_image)
|
85
|
+
if image_config.horizontal_layout?
|
86
|
+
x = dest_image.columns + image_config.spaced_by
|
87
|
+
y = 0
|
88
|
+
align = "horizontal"
|
89
|
+
else
|
90
|
+
x = 0
|
91
|
+
y = dest_image.rows + image_config.spaced_by
|
92
|
+
align = "vertical"
|
93
|
+
end
|
94
|
+
results << combiner.image_properties(source_image).merge(:x => -x, :y => -y, :group => name, :align => align)
|
95
|
+
dest_image = combiner.composite_images(dest_image, source_image, x, y)
|
96
|
+
end
|
97
|
+
|
98
|
+
ImageWriter.new(config).write(dest_image, name, image_config.format, image_config.quality, image_config.background_color)
|
99
|
+
|
100
|
+
@sprite_files["#{name}.#{image_config.format}#{@datestamp_query}"] = results
|
101
|
+
end
|
102
|
+
|
103
|
+
def write_styles
|
104
|
+
# use the absolute style output path to make sure we have the directory set up
|
105
|
+
path = style_output_path
|
106
|
+
FileUtils.mkdir_p(File.dirname(path))
|
107
|
+
|
108
|
+
# send the style the relative path
|
109
|
+
style.write(style_output_path(true), @sprite_files)
|
110
|
+
end
|
111
|
+
|
112
|
+
def style
|
113
|
+
@style ||= Styles.get(config["style"]).new(self)
|
114
|
+
end
|
115
|
+
|
116
|
+
# sets all the default values on the config
|
117
|
+
def set_config_defaults
|
118
|
+
@config['style'] ||= 'css'
|
119
|
+
@config['style_output_path'] ||= 'stylesheets/sprites'
|
120
|
+
@config['image_output_path'] ||= 'images/sprites/'
|
121
|
+
@config['css_image_path'] ||= "/#{@config['image_output_path']}"
|
122
|
+
@config['image_source_path'] ||= 'images/'
|
123
|
+
@config['public_path'] ||= 'public/'
|
124
|
+
@config['default_format'] ||= 'png'
|
125
|
+
@config['class_separator'] ||= '-'
|
126
|
+
@config["sprites_class"] ||= 'sprites'
|
127
|
+
@config["default_spacing"] ||= 0
|
128
|
+
|
129
|
+
unless @config.has_key?("add_datestamps")
|
130
|
+
@config["add_datestamps"] = true
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# if no image configs are detected, set some intelligent defaults
|
135
|
+
def default_images
|
136
|
+
sprites_path = image_source_path("sprites")
|
137
|
+
collection = []
|
138
|
+
|
139
|
+
if File.exists?(sprites_path)
|
140
|
+
Dir.glob(File.join(sprites_path, "*")) do |dir|
|
141
|
+
next unless File.directory?(dir)
|
142
|
+
source_name = File.basename(dir)
|
143
|
+
|
144
|
+
# default to finding all png, gif, jpg, and jpegs within the directory
|
145
|
+
collection << {
|
146
|
+
"name" => source_name,
|
147
|
+
"sources" => [
|
148
|
+
File.join("sprites", source_name, "*.png"),
|
149
|
+
File.join("sprites", source_name, "*.gif"),
|
150
|
+
File.join("sprites", source_name, "*.jpg"),
|
151
|
+
File.join("sprites", source_name, "*.jpeg"),
|
152
|
+
]
|
153
|
+
}
|
154
|
+
end
|
155
|
+
end
|
156
|
+
collection
|
157
|
+
end
|
158
|
+
|
159
|
+
# expands out sources, taking the Glob paths and turning them into separate entries in the array
|
160
|
+
def expand_image_paths
|
161
|
+
# cycle through image sources and expand out globs
|
162
|
+
@images.each do |image|
|
163
|
+
# expand out all the globs
|
164
|
+
image['sources'] = image['sources'].to_a.map{ |source|
|
165
|
+
Dir.glob(image_source_path(source))
|
166
|
+
}.flatten.compact
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
# get the disk path for an image source file
|
171
|
+
def image_source_path(location, relative = false)
|
172
|
+
path_parts = []
|
173
|
+
path_parts << Config.chop_trailing_slash(config["image_source_path"]) if Config.path_present?(config['image_source_path'])
|
174
|
+
path_parts << location
|
175
|
+
Config.new(config).public_path(File.join(*path_parts), relative)
|
176
|
+
end
|
177
|
+
|
178
|
+
def style_template_source_path(image, relative = false)
|
179
|
+
location = image["style_output_template"]
|
180
|
+
path_parts = []
|
181
|
+
path_parts << location
|
182
|
+
Config.new(config).public_path(File.join(*path_parts), relative)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Sprite
|
2
|
+
class Config
|
3
|
+
DEFAULT_CONFIG_PATH = 'config/sprite.yml'
|
4
|
+
|
5
|
+
def self.read_config(path = nil)
|
6
|
+
config_path = File.join(Sprite.root, path || DEFAULT_CONFIG_PATH)
|
7
|
+
|
8
|
+
# read configuration
|
9
|
+
if File.exists?(config_path)
|
10
|
+
begin
|
11
|
+
File.open(config_path) {|f| YAML::load(f)} || {}
|
12
|
+
rescue => e
|
13
|
+
puts "Error reading sprite config: #{config_path}"
|
14
|
+
puts e.to_s
|
15
|
+
{}
|
16
|
+
end
|
17
|
+
else
|
18
|
+
{}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# chop off the trailing slash on a directory path (if it exists)
|
23
|
+
def self.chop_trailing_slash(path)
|
24
|
+
path = path[0...-1] if path[-1] == File::SEPARATOR
|
25
|
+
path
|
26
|
+
end
|
27
|
+
|
28
|
+
# check if the path is set
|
29
|
+
def self.path_present?(path)
|
30
|
+
path.to_s.strip != ""
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(settings_hash)
|
34
|
+
@settings = settings_hash
|
35
|
+
end
|
36
|
+
|
37
|
+
# get the disk path for a location within the public folder (if set)
|
38
|
+
def public_path(location, relative = false)
|
39
|
+
path_parts = []
|
40
|
+
path_parts << Sprite.root unless relative
|
41
|
+
path_parts << Config.chop_trailing_slash(@settings['public_path']) if Config.path_present?(@settings['public_path'])
|
42
|
+
path_parts << location
|
43
|
+
|
44
|
+
File.join(*path_parts)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Sprite
|
2
|
+
class ImageCombiner
|
3
|
+
def initialize(image_config)
|
4
|
+
# avoid loading rmagick till the last possible moment
|
5
|
+
require 'rmagick'
|
6
|
+
@image_config = image_config
|
7
|
+
end
|
8
|
+
|
9
|
+
def composite_images(dest_image, src_image, x, y)
|
10
|
+
width = [src_image.columns + x, dest_image.columns].max
|
11
|
+
height = [src_image.rows + y, dest_image.rows].max
|
12
|
+
image = Magick::Image.new(width, height)
|
13
|
+
if @image_config.background_color
|
14
|
+
image.opacity = 0
|
15
|
+
else
|
16
|
+
image.opacity = Magick::MaxRGB
|
17
|
+
end
|
18
|
+
|
19
|
+
image.composite!(dest_image, 0, 0, Magick::OverCompositeOp)
|
20
|
+
image.composite!(src_image, x, y, Magick::OverCompositeOp)
|
21
|
+
image
|
22
|
+
end
|
23
|
+
|
24
|
+
# Image Utility Methods
|
25
|
+
|
26
|
+
def image_properties(image)
|
27
|
+
{:name => File.basename(image.filename).split('.')[0], :width => image.columns, :height => image.rows}
|
28
|
+
end
|
29
|
+
|
30
|
+
# REMOVE RMAGICK AND USE IMAGEMAGICK FROM THE COMMAND LINE
|
31
|
+
# identify => find properties for an image
|
32
|
+
# composite => combine 2 images
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Sprite
|
2
|
+
class ImageConfig
|
3
|
+
def initialize(image_info, global_config_info)
|
4
|
+
@image_info = image_info
|
5
|
+
@global_config_info = global_config_info
|
6
|
+
end
|
7
|
+
|
8
|
+
def sources
|
9
|
+
@image_info['sources'].to_a
|
10
|
+
end
|
11
|
+
|
12
|
+
def name
|
13
|
+
@image_info['name']
|
14
|
+
end
|
15
|
+
|
16
|
+
def format
|
17
|
+
@image_info['format'] || @global_config_info["default_format"]
|
18
|
+
end
|
19
|
+
|
20
|
+
def quality
|
21
|
+
@image_info['quality'] || @global_config_info["default_quality"]
|
22
|
+
end
|
23
|
+
|
24
|
+
def background_color
|
25
|
+
@image_info['background_color'] || @global_config_info["default_background_color"]
|
26
|
+
end
|
27
|
+
|
28
|
+
def spaced_by
|
29
|
+
@image_info['spaced_by'] || @global_config_info["default_spacing"] || 0
|
30
|
+
end
|
31
|
+
|
32
|
+
def resize_to
|
33
|
+
@image_info['resize_to'] || @global_config_info['resize_to']
|
34
|
+
end
|
35
|
+
|
36
|
+
def horizontal_layout?
|
37
|
+
@image_info['align'].to_s == 'horizontal'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Sprite
|
2
|
+
class ImageResizer
|
3
|
+
def initialize(resize_to)
|
4
|
+
if resize_to
|
5
|
+
@resizing = true
|
6
|
+
@target_width, @target_height = *(resize_to.split('x').map(&:to_i))
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def resize(image)
|
11
|
+
if @resizing
|
12
|
+
needs_resizing = image.columns != @target_width || image.rows != @target_height
|
13
|
+
if needs_resizing
|
14
|
+
image.scale!(@target_width, @target_height)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Sprite
|
2
|
+
class ImageWriter
|
3
|
+
def initialize(config)
|
4
|
+
@config = config
|
5
|
+
end
|
6
|
+
|
7
|
+
def write(image, name, format, quality = nil, background_color = nil)
|
8
|
+
# set up path
|
9
|
+
path = image_output_path(name, format)
|
10
|
+
FileUtils.mkdir_p(File.dirname(path))
|
11
|
+
|
12
|
+
# write sprite image file to disk
|
13
|
+
image.write(path) {
|
14
|
+
self.quality = quality unless quality.nil?
|
15
|
+
self.background_color = background_color unless background_color.nil?
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
# get the disk path for a location within the image output folder
|
20
|
+
def image_output_path(name, format, relative = false)
|
21
|
+
path_parts = []
|
22
|
+
path_parts << Config.chop_trailing_slash(@config['image_output_path']) if Config.path_present?(@config['image_output_path'])
|
23
|
+
path_parts << "#{name}.#{format}"
|
24
|
+
Config.new(@config).public_path(File.join(*path_parts), relative)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Sprite
|
2
|
+
class Runner
|
3
|
+
|
4
|
+
attr_accessor :options
|
5
|
+
def initialize(args)
|
6
|
+
self.options = set_options(args)
|
7
|
+
end
|
8
|
+
|
9
|
+
def set_options(args)
|
10
|
+
opts = {}
|
11
|
+
# TODO
|
12
|
+
# edit options with passed in args
|
13
|
+
opts[:path] = args.first if args.any?
|
14
|
+
|
15
|
+
opts
|
16
|
+
end
|
17
|
+
|
18
|
+
# run sprite creator
|
19
|
+
def run!
|
20
|
+
begin
|
21
|
+
Sprite::Builder.from_config(options[:path]).build
|
22
|
+
# rescue Exception => e
|
23
|
+
# # catch errors
|
24
|
+
# puts "ERROR"
|
25
|
+
# puts e
|
26
|
+
# return 1
|
27
|
+
end
|
28
|
+
0
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Sprite
|
2
|
+
module Sass
|
3
|
+
module Extensions
|
4
|
+
def sprite_background(group, image)
|
5
|
+
sprite = sprite_data(group, image)
|
6
|
+
if sprite
|
7
|
+
sprite_path = sprite_builder.image_path(group.value)
|
8
|
+
"url('#{sprite_path}') no-repeat #{sprite[:x]}px #{sprite[:y]}px"
|
9
|
+
else
|
10
|
+
""
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def sprite_width(*args)
|
15
|
+
sprite_attr(:width, *args)
|
16
|
+
end
|
17
|
+
|
18
|
+
def sprite_height(*args)
|
19
|
+
sprite_attr(:height, *args)
|
20
|
+
end
|
21
|
+
|
22
|
+
def sprite_x_offset(*args)
|
23
|
+
sprite_attr(:x, *args)
|
24
|
+
end
|
25
|
+
|
26
|
+
def sprite_y_offset(*args)
|
27
|
+
sprite_attr(:y, *args)
|
28
|
+
end
|
29
|
+
|
30
|
+
def sprite_image(group)
|
31
|
+
sprite_builder.image_path(group.value)
|
32
|
+
end
|
33
|
+
|
34
|
+
def sprite_url(group)
|
35
|
+
"url('#{sprite_image(group)}')"
|
36
|
+
end
|
37
|
+
|
38
|
+
def sprite_offset(group, image, x=nil, y=nil)
|
39
|
+
x ||= sprite_x_offset(group, image)
|
40
|
+
y ||= sprite_y_offset(group, image)
|
41
|
+
"#{x} #{y}"
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
def sprite_attr(attr, group, image)
|
46
|
+
sprite = sprite_data(group, image)
|
47
|
+
if sprite
|
48
|
+
"#{sprite[attr]}px"
|
49
|
+
else
|
50
|
+
""
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def sprite_builder
|
55
|
+
@__sprite_builder ||= Builder.from_config
|
56
|
+
end
|
57
|
+
|
58
|
+
def sprite_data(group, image)
|
59
|
+
unless @__sprite_data
|
60
|
+
sprite_data_path = sprite_builder.style_output_path
|
61
|
+
|
62
|
+
# read sprite data from yml
|
63
|
+
@__sprite_data = File.open(sprite_data_path) { |yf| YAML::load( yf ) }
|
64
|
+
end
|
65
|
+
|
66
|
+
group_data = @__sprite_data[group.to_s]
|
67
|
+
if group_data
|
68
|
+
return group_data[image.to_s]
|
69
|
+
else
|
70
|
+
nil
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
if defined?(Sass)
|
78
|
+
module Sass::Script::Functions
|
79
|
+
include Sprite::Sass::Extensions
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'sprite/styles/sass_generator'
|
2
|
+
require 'sprite/styles/css_generator'
|
3
|
+
require 'sprite/styles/sass_yml_generator'
|
4
|
+
require 'sprite/styles/sass_mixin_generator'
|
5
|
+
require 'sprite/styles/templated_css_generator'
|
6
|
+
|
7
|
+
module Sprite::Styles
|
8
|
+
GENERATORS = {
|
9
|
+
"css" => "CssGenerator",
|
10
|
+
"templated_css" => "TemplatedCssGenerator",
|
11
|
+
"sass" => "SassGenerator",
|
12
|
+
"sass_mixin" => "SassMixinGenerator",
|
13
|
+
"sass_yml" => "SassYmlGenerator"
|
14
|
+
}
|
15
|
+
|
16
|
+
def self.get(config)
|
17
|
+
const_get(GENERATORS[config])
|
18
|
+
rescue
|
19
|
+
CssGenerator
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Sprite
|
2
|
+
module Styles
|
3
|
+
# renders standard css style rules
|
4
|
+
class CssGenerator
|
5
|
+
def initialize(builder)
|
6
|
+
@builder = builder
|
7
|
+
end
|
8
|
+
|
9
|
+
def write(path, sprite_files)
|
10
|
+
# write styles to disk
|
11
|
+
File.open(File.join(Sprite.root, path), 'w') do |f|
|
12
|
+
write_standard_css(f, sprite_files)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def write_standard_css(f, sprite_files)
|
17
|
+
# set up class_name to append to each rule
|
18
|
+
sprites_class = @builder.config['sprites_class'] ? ".#{@builder.config['sprites_class']}" : ""
|
19
|
+
|
20
|
+
sprite_files.each do |sprite_file, sprites|
|
21
|
+
sprites.each do |sprite|
|
22
|
+
f.puts "#{sprites_class}.#{sprite[:group]}#{@builder.config['class_separator']}#{sprite[:name]} {"
|
23
|
+
f.puts " background: url('/#{@builder.config['image_output_path']}#{sprite_file}') no-repeat #{sprite[:x]}px #{sprite[:y]}px;"
|
24
|
+
f.puts " width: #{sprite[:width]}px;"
|
25
|
+
f.puts " height: #{sprite[:height]}px;"
|
26
|
+
f.puts "}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def extension
|
32
|
+
"css"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Sprite
|
2
|
+
module Styles
|
3
|
+
|
4
|
+
# renders standard sass rules
|
5
|
+
class SassGenerator
|
6
|
+
def initialize(builder)
|
7
|
+
@builder = builder
|
8
|
+
end
|
9
|
+
|
10
|
+
def write(path, sprite_files)
|
11
|
+
@level = 0
|
12
|
+
|
13
|
+
File.open(File.join(Sprite.root, path), 'w') do |f|
|
14
|
+
if @builder.config['sprites_class']
|
15
|
+
f.puts ".#{@builder.config['sprites_class']}"
|
16
|
+
@level += 1
|
17
|
+
end
|
18
|
+
|
19
|
+
sprite_files.each do |sprite_file, sprites|
|
20
|
+
sprites.each do |sprite|
|
21
|
+
f.puts sass_line("&.#{sprite[:group]}#{@builder.config['class_separator']}#{sprite[:name]}")
|
22
|
+
@level += 1
|
23
|
+
f.puts sass_line("background: url('/#{@builder.config['image_output_path']}#{sprite_file}') no-repeat #{sprite[:x]}px #{sprite[:y]}px")
|
24
|
+
f.puts sass_line("width: #{sprite[:width]}px")
|
25
|
+
f.puts sass_line("height: #{sprite[:height]}px")
|
26
|
+
f.puts sass_line("")
|
27
|
+
@level -= 1
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# write sass output with correct tab spaces prepended
|
34
|
+
def sass_line(sass)
|
35
|
+
"#{' '*@level}#{sass}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def extension
|
39
|
+
"sass"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Sprite
|
2
|
+
module Styles
|
3
|
+
# renders a yml file that is later parsed by a sass extension when generating the mixins
|
4
|
+
class SassMixinGenerator
|
5
|
+
def initialize(builder)
|
6
|
+
@builder = builder
|
7
|
+
end
|
8
|
+
|
9
|
+
def write(path, sprite_files)
|
10
|
+
# write the sass mixins to disk
|
11
|
+
File.open(File.join(Sprite.root, path), 'w') do |f|
|
12
|
+
add_else = false
|
13
|
+
|
14
|
+
f.puts "= sprite(!group_name, !image_name, !offset=0)"
|
15
|
+
sprite_files.each do |sprite_file, sprites|
|
16
|
+
sprites.each do |sprite|
|
17
|
+
|
18
|
+
f << " @"
|
19
|
+
if add_else
|
20
|
+
f << "else "
|
21
|
+
end
|
22
|
+
add_else = true
|
23
|
+
#{sprite[:x]}px #{sprite[:y]}px
|
24
|
+
|
25
|
+
if sprite[:align] == 'horizontal'
|
26
|
+
background_offset = "\#{#{sprite[:x]}+!offset}px #{sprite[:y]}px"
|
27
|
+
else
|
28
|
+
background_offset = "#{sprite[:x]}px \#{#{sprite[:y]}+!offset}px"
|
29
|
+
end
|
30
|
+
|
31
|
+
f.puts %{if !group_name == "#{sprite[:group]}" and !image_name == "#{sprite[:name]}"}
|
32
|
+
f.puts " background: url('/#{@builder.config['image_output_path']}#{sprite_file}') no-repeat #{background_offset}"
|
33
|
+
f.puts " width: #{sprite[:width]}px"
|
34
|
+
f.puts " height: #{sprite[:height]}px"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def extension
|
41
|
+
"sass"
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
module Sprite
|
3
|
+
module Styles
|
4
|
+
# renders a yml file that is later parsed by a sass extension when generating the mixins
|
5
|
+
class SassYmlGenerator
|
6
|
+
def initialize(builder)
|
7
|
+
@builder = builder
|
8
|
+
end
|
9
|
+
|
10
|
+
def write(path, sprite_files)
|
11
|
+
# build the yml file
|
12
|
+
write_config(path, sprite_files)
|
13
|
+
|
14
|
+
# Where to put the sass mixin file
|
15
|
+
sass_path = path.gsub(".yml", ".sass")
|
16
|
+
|
17
|
+
# write the sass mixins to disk
|
18
|
+
File.open(File.join(Sprite.root, sass_path), 'w') do |f|
|
19
|
+
f.puts "!sprite_data = '#{path}'"
|
20
|
+
f.puts ""
|
21
|
+
f.puts "= sprite(!group_name, !image_name)"
|
22
|
+
f.puts " background= sprite_background(!group_name, !image_name)"
|
23
|
+
f.puts " width= sprite_width(!group_name, !image_name)"
|
24
|
+
f.puts " height= sprite_height(!group_name, !image_name)"
|
25
|
+
f.puts ""
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# write the sprite configuration file (used by the yml extension)
|
30
|
+
def write_config(path, sprite_files)
|
31
|
+
# build a grouped hash with all the sprites in it
|
32
|
+
result = {}
|
33
|
+
sprite_files.each do |sprite_file, sprites|
|
34
|
+
sprites.each do |sprite|
|
35
|
+
if sprite[:group]
|
36
|
+
result[sprite[:group]] ||= {}
|
37
|
+
result[sprite[:group]][sprite[:name]] = sprite
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# write the config yml to disk
|
43
|
+
File.open(File.join(Sprite.root, path), 'w') do |f|
|
44
|
+
YAML.dump(result, f)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def extension
|
49
|
+
"yml"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module Sprite
|
4
|
+
module Styles
|
5
|
+
# renders css rules from template
|
6
|
+
class TemplatedCssGenerator
|
7
|
+
def initialize(builder)
|
8
|
+
@builder = builder
|
9
|
+
end
|
10
|
+
|
11
|
+
def write(path, sprite_files)
|
12
|
+
# write styles to disk
|
13
|
+
File.open(File.join(Sprite.root, path), 'w') do |f|
|
14
|
+
f.puts "/* Generated by the sprite gem */"
|
15
|
+
sprite_files.each do |sprite_file|
|
16
|
+
@builder.images.each do |image|
|
17
|
+
if "#{image['name']}.#{image['format']}" == sprite_file[0]
|
18
|
+
erb_path = @builder.send :style_template_source_path, image
|
19
|
+
erb_template = ERB.new(File.read(erb_path))
|
20
|
+
sprites = sprite_file[1]
|
21
|
+
sprites.each do |sprite|
|
22
|
+
name = sprite[:name]
|
23
|
+
width = sprite[:width]
|
24
|
+
height = sprite[:height]
|
25
|
+
left = sprite[:x]
|
26
|
+
top = sprite[:y]
|
27
|
+
image_path = ImageWriter.new(@builder.config).image_output_path(image['name'], image['format'])
|
28
|
+
f.puts erb_template.result(binding)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def extension
|
37
|
+
"css"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/rails/init.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../lib/sprite/sprite.rb')
|
2
|
+
|
3
|
+
namespace :sprite do
|
4
|
+
desc "build sprite images based on config/sprite.yml"
|
5
|
+
task :build do
|
6
|
+
Sprite.new.build
|
7
|
+
end
|
8
|
+
|
9
|
+
task :list => [:build] do
|
10
|
+
# TODO
|
11
|
+
# list all the currently configured sprites
|
12
|
+
end
|
13
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: amikula-sprite
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.8
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jacques Crocker
|
8
|
+
- Alf Mikula
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2010-03-14 00:00:00 -08:00
|
14
|
+
default_executable: sprite
|
15
|
+
dependencies: []
|
16
|
+
|
17
|
+
description: sprite is a rails/merb plugin that generates sprites for css, sass
|
18
|
+
email: amikula@gmail.com
|
19
|
+
executables:
|
20
|
+
- sprite
|
21
|
+
extensions: []
|
22
|
+
|
23
|
+
extra_rdoc_files:
|
24
|
+
- README.md
|
25
|
+
files:
|
26
|
+
- MIT-LICENSE
|
27
|
+
- README.md
|
28
|
+
- Rakefile
|
29
|
+
- VERSION
|
30
|
+
- bin/sprite
|
31
|
+
- lib/sprite.rb
|
32
|
+
- lib/sprite/builder.rb
|
33
|
+
- lib/sprite/config.rb
|
34
|
+
- lib/sprite/image_combiner.rb
|
35
|
+
- lib/sprite/image_config.rb
|
36
|
+
- lib/sprite/image_reader.rb
|
37
|
+
- lib/sprite/image_resizer.rb
|
38
|
+
- lib/sprite/image_writer.rb
|
39
|
+
- lib/sprite/runner.rb
|
40
|
+
- lib/sprite/sass_extensions.rb
|
41
|
+
- lib/sprite/styles.rb
|
42
|
+
- lib/sprite/styles/css_generator.rb
|
43
|
+
- lib/sprite/styles/sass_generator.rb
|
44
|
+
- lib/sprite/styles/sass_mixin_generator.rb
|
45
|
+
- lib/sprite/styles/sass_yml_generator.rb
|
46
|
+
- lib/sprite/styles/templated_css_generator.rb
|
47
|
+
- rails/init.rb
|
48
|
+
- tasks/sprite_tasks.rake
|
49
|
+
has_rdoc: true
|
50
|
+
homepage: http://github.com/amikula/sprite
|
51
|
+
licenses: []
|
52
|
+
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options:
|
55
|
+
- --charset=UTF-8
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: "0"
|
63
|
+
version:
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: "0"
|
69
|
+
version:
|
70
|
+
requirements: []
|
71
|
+
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 1.3.5
|
74
|
+
signing_key:
|
75
|
+
specification_version: 3
|
76
|
+
summary: generate your css sprites automagically
|
77
|
+
test_files: []
|
78
|
+
|