sprite-factory-custom 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/Gemfile +12 -0
  4. data/LICENSE +20 -0
  5. data/README.md +351 -0
  6. data/RELEASE_NOTES.md +60 -0
  7. data/Rakefile +73 -0
  8. data/bin/sf +57 -0
  9. data/lib/sprite_factory/layout/horizontal.rb +44 -0
  10. data/lib/sprite_factory/layout/packed.rb +118 -0
  11. data/lib/sprite_factory/layout/vertical.rb +44 -0
  12. data/lib/sprite_factory/library/chunky_png.rb +31 -0
  13. data/lib/sprite_factory/library/image_magick.rb +74 -0
  14. data/lib/sprite_factory/library/rmagick.rb +32 -0
  15. data/lib/sprite_factory/runner.rb +287 -0
  16. data/lib/sprite_factory/style.rb +74 -0
  17. data/lib/sprite_factory.rb +85 -0
  18. data/sprite_factory.gemspec +27 -0
  19. data/test/images/custom/custom.css +4 -0
  20. data/test/images/custom/running.png +0 -0
  21. data/test/images/custom/stopped.png +0 -0
  22. data/test/images/empty/readme.txt +1 -0
  23. data/test/images/formats/alice.gif +0 -0
  24. data/test/images/formats/codeincomplete.ico +0 -0
  25. data/test/images/formats/github.ico +0 -0
  26. data/test/images/formats/monkey.gif +0 -0
  27. data/test/images/formats/spies.jpg +0 -0
  28. data/test/images/formats/stackoverflow.ico +0 -0
  29. data/test/images/formats/thief.png +0 -0
  30. data/test/images/hover/div.bar__img.icon--active.png +0 -0
  31. data/test/images/hover/div.bar__img.icon--focus.png +0 -0
  32. data/test/images/hover/div.bar__img.icon--hover.png +0 -0
  33. data/test/images/hover/div.bar__img.icon--link.png +0 -0
  34. data/test/images/hover/div.bar__img.icon--visited.png +0 -0
  35. data/test/images/hover/div.bar__img.icon.png +0 -0
  36. data/test/images/hover/div.foo__img.icon--active.png +0 -0
  37. data/test/images/hover/div.foo__img.icon--focus.png +0 -0
  38. data/test/images/hover/div.foo__img.icon--hover.png +0 -0
  39. data/test/images/hover/div.foo__img.icon--link.png +0 -0
  40. data/test/images/hover/div.foo__img.icon--visited.png +0 -0
  41. data/test/images/hover/div.foo__img.icon.png +0 -0
  42. data/test/images/irregular/irregular1.png +0 -0
  43. data/test/images/irregular/irregular2.png +0 -0
  44. data/test/images/irregular/irregular3.png +0 -0
  45. data/test/images/irregular/irregular4.png +0 -0
  46. data/test/images/irregular/irregular5.png +0 -0
  47. data/test/images/irregular/readme.txt +2 -0
  48. data/test/images/reference/custom.css +22 -0
  49. data/test/images/reference/custom.png +0 -0
  50. data/test/images/reference/formats.css +28 -0
  51. data/test/images/reference/formats.png +0 -0
  52. data/test/images/reference/hover.css +38 -0
  53. data/test/images/reference/hover.png +0 -0
  54. data/test/images/reference/index.html +182 -0
  55. data/test/images/reference/irregular.css +24 -0
  56. data/test/images/reference/irregular.fixed.css +24 -0
  57. data/test/images/reference/irregular.fixed.png +0 -0
  58. data/test/images/reference/irregular.horizontal.css +24 -0
  59. data/test/images/reference/irregular.horizontal.png +0 -0
  60. data/test/images/reference/irregular.margin.css +24 -0
  61. data/test/images/reference/irregular.margin.png +0 -0
  62. data/test/images/reference/irregular.packed.css +24 -0
  63. data/test/images/reference/irregular.packed.png +0 -0
  64. data/test/images/reference/irregular.padded.css +24 -0
  65. data/test/images/reference/irregular.padded.png +0 -0
  66. data/test/images/reference/irregular.png +0 -0
  67. data/test/images/reference/irregular.sassy.css +38 -0
  68. data/test/images/reference/irregular.sassy.png +0 -0
  69. data/test/images/reference/irregular.sassy.sass +40 -0
  70. data/test/images/reference/irregular.vertical.css +24 -0
  71. data/test/images/reference/irregular.vertical.png +0 -0
  72. data/test/images/reference/regular.css +24 -0
  73. data/test/images/reference/regular.custom.css +24 -0
  74. data/test/images/reference/regular.custom.png +0 -0
  75. data/test/images/reference/regular.fixed.css +24 -0
  76. data/test/images/reference/regular.fixed.png +0 -0
  77. data/test/images/reference/regular.horizontal.css +24 -0
  78. data/test/images/reference/regular.horizontal.png +0 -0
  79. data/test/images/reference/regular.margin.css +24 -0
  80. data/test/images/reference/regular.margin.png +0 -0
  81. data/test/images/reference/regular.nocomments.css +5 -0
  82. data/test/images/reference/regular.nocomments.png +0 -0
  83. data/test/images/reference/regular.packed.css +24 -0
  84. data/test/images/reference/regular.packed.png +0 -0
  85. data/test/images/reference/regular.padded.css +24 -0
  86. data/test/images/reference/regular.padded.png +0 -0
  87. data/test/images/reference/regular.png +0 -0
  88. data/test/images/reference/regular.sassy.css +38 -0
  89. data/test/images/reference/regular.sassy.png +0 -0
  90. data/test/images/reference/regular.sassy.sass +40 -0
  91. data/test/images/reference/regular.vertical.css +24 -0
  92. data/test/images/reference/regular.vertical.png +0 -0
  93. data/test/images/reference/s.gif +0 -0
  94. data/test/images/reference/subfolders.css +24 -0
  95. data/test/images/reference/subfolders.png +0 -0
  96. data/test/images/regular/regular1.PNG +0 -0
  97. data/test/images/regular/regular2.PNG +0 -0
  98. data/test/images/regular/regular3.PNG +0 -0
  99. data/test/images/regular/regular4.PNG +0 -0
  100. data/test/images/regular/regular5.PNG +0 -0
  101. data/test/images/subfolders/england/amy.png +0 -0
  102. data/test/images/subfolders/england/bob.png +0 -0
  103. data/test/images/subfolders/france/bob.png +0 -0
  104. data/test/images/subfolders/usa/amy.png +0 -0
  105. data/test/images/subfolders/usa/bob.png +0 -0
  106. data/test/integration_test.rb +167 -0
  107. data/test/layout/horizontal_test.rb +156 -0
  108. data/test/layout/packed_test.rb +283 -0
  109. data/test/layout/test_case.rb +56 -0
  110. data/test/layout/vertical_test.rb +156 -0
  111. data/test/library_test.rb +58 -0
  112. data/test/runner_test.rb +229 -0
  113. data/test/style_test.rb +72 -0
  114. data/test/test_case.rb +138 -0
  115. metadata +286 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8a81c8fe6af96b06771bb7f78ab64aaa536e4e4b
4
+ data.tar.gz: 148fe646cc3d9c81518a5b029b9d2027fb795663
5
+ SHA512:
6
+ metadata.gz: 60177384a302f97fa156797b768342a8897cb7c1e2f47b2745658d496fa46aa70d2c108f9f6038e08d33e0cd9286d103c122ef36a5540b98ce4a37e945a97672
7
+ data.tar.gz: 11daf41fed50c6e336c6ab4ba865d03684b8b9d0c56fce96abe653ec23135e0d033ed700a4d4a4d3d4b71ab2040d3f59888ec6921544617b2c02660a68032654
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ *~
2
+ *.gem
3
+ .bundle
4
+ Gemfile.lock
5
+ pkg/*
6
+ *.swp
7
+ .sass-cache
8
+ test/images/*.png
9
+ test/images/*.css
10
+ test/images/*.sass
11
+ test/images/*.scss
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source "http://rubygems.org"
2
+
3
+ #
4
+ # NOTE: rmagick dependencies include:
5
+ #
6
+ # $ sudo apt-get install imagemagick
7
+ # $ sudo apt-get install libmagickwand-dev
8
+
9
+ group :development do
10
+ gem "chunky_png", "1.3.0"
11
+ gem "rmagick", "2.13.2"
12
+ end
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011, 2012, 2013, 2014 Jake Gordon and contributors
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
20
+
data/README.md ADDED
@@ -0,0 +1,351 @@
1
+ Sprite Factory (v1.6.0)
2
+ =======================
3
+
4
+ The sprite factory is a ruby library that can be used to generate
5
+ [CSS sprites](http://www.alistapart.com/articles/sprites). It combines
6
+ individual image files from a directory into a single unified sprite image
7
+ and creates an appropriate CSS stylesheet for use in your web application.
8
+
9
+ The library provides:
10
+
11
+ * both a ruby API and a command line script
12
+ * many customizable options
13
+ * support for multiple layout algorithms - horizontal, vertical or [packed](http://codeincomplete.com/posts/2011/5/7/bin_packing/)
14
+ * support for any stylesheet syntax, including [CSS](http://www.w3.org/Style/CSS/) and [Sass](http://sass-lang.com/).
15
+ * support for any image library, including [RMagick](http://rmagick.rubyforge.org/) and [ChunkyPNG](https://github.com/wvanbergen/chunky_png).
16
+ * support for any css selector style, including :hover pseudo-class selectors
17
+ * support for pngcrush'n the generated image file
18
+ * compatible with Rails 3.1 asset pipeline
19
+
20
+
21
+ Installation
22
+ ============
23
+
24
+ $ gem install sprite-factory
25
+
26
+ An image library is also required. SpriteFactory comes with built in support for
27
+ [RMagick](http://rmagick.rubyforge.org/) or [ChunkyPng](https://github.com/wvanbergen/chunky_png).
28
+
29
+ RMagick is the most common image libary to use, installation instructions for ubuntu:
30
+
31
+ $ sudo aptitude install imageMagick libMagickWand-dev
32
+ $ sudo gem install rmagick
33
+
34
+ ChunkyPng is lighter weight but only supports .png format:
35
+
36
+ $ gem install chunky_png
37
+
38
+ SpriteFactory can also be easily extended to use the image library of your choice.
39
+
40
+ Usage
41
+ =====
42
+
43
+ Use the `sf` command line script specifying the location of your images.
44
+
45
+ $ sf images/icons
46
+
47
+ This will combine the individual image files within that directory and generate:
48
+
49
+ * images/icons.png
50
+ * images/icons.css
51
+
52
+ You can also use the SpriteFactory class directly from your own code:
53
+
54
+ require 'sprite_factory'
55
+
56
+ SpriteFactory.run!('images/icons')
57
+
58
+ The original image file name is used for the CSS class to show that image in HTML:
59
+
60
+ <img src='s.gif' class='high'> # e.g. original image was high.png
61
+ <img src='s.gif' class='medium'> # e.g. original image was medium.png
62
+ <img src='s.gif' class='low'> # e.g. original image was low.png
63
+
64
+ If original image files are included in sub-folders, the relative path
65
+ name will be used for the CSS class to show that image in HTML:
66
+
67
+ <img src='s.gif' class='other_high'> # e.g. original image was other/high.png
68
+ <img src='s.gif' class='other_medium'> # e.g. original image was other/medium.png
69
+ <img src='s.gif' class='other_low'> # e.g. original image was other/low.png
70
+
71
+ When using a framework such as Rails, you would usually DRY this up with a helper method:
72
+
73
+ def sprite_tag(name)
74
+ image_tag('s.gif', :class => name)
75
+ end
76
+
77
+ >> NOTE: `s.gif` is the traditional name of a 1x1 pixel transparent .gif used as a
78
+ dummy `src` when the true image comes from a css background attribute. Technically,
79
+ for css sprites, you could just use a `div` with a class instead of an `img`, but
80
+ to keep the markup semantic it is common to use an `img` tag with a dummy `src=s.gif`.
81
+
82
+ Customization
83
+ =============
84
+
85
+ Much of the behavior can be customized by overriding the following options:
86
+
87
+ - `:layout` - specify layout algorithm (horizontal, vertical or packed)
88
+ - `:style` - specify stylesheet syntax (css, scss or sass)
89
+ - `:library` - specify image library to use (rmagick or chunkypng)
90
+ - `:selector` - specify custom css selector (see below)
91
+ - `:cssurl` - specify custom css url (see below)
92
+ - `:output_image` - specify output location for generated image (default: &lt;input folder&gt;.png)
93
+ - `:output_style` - specify output location for generated stylesheet (default: &lt;input folder&gt;.&lt;style&gt;)
94
+ - `:pngcrush` - pngcrush the generated output image (if pngcrush is available)
95
+ - `:padding` - add padding to each sprite
96
+ - `:margin` - add margin to each sprite
97
+ - `:width` - fix width of each sprite to a specific size
98
+ - `:height` - fix height of each sprite to a specific size
99
+ - `:nocss` - suppress generation of output stylesheet (`run!` returns css content as a string instead)
100
+ - `:nocomments` - suppress generation of comments in output stylesheet
101
+
102
+ Options can be passed as command line arguments to the `sf` script:
103
+
104
+ $ sf images/icons --style sass --layout packed
105
+
106
+ Options can also be passed as the 2nd argument to the `#run!` method:
107
+
108
+ SpriteFactory.run!('images/icons', :style => :sass, :layout => :packed)
109
+
110
+ You can see the results of many of these options by viewing the sample page that
111
+ comes with the gem in `test/images/reference/index.html`.
112
+
113
+ >> NOTE: only the common options are available via the command line script (to keep it simple). Specifically,
114
+ the advanced `width`, `height`, and `nocss` options are only available via the Ruby interface.
115
+
116
+ >> NOTE: the `width`, `height` and `padding` options are not particularly useful - you would be better off just
117
+ making your source images have the correct dimensions by editing them appropriately in photoshop (or your editor of choice)
118
+
119
+ >> NOTE: the `margin` option is used primarily to buffer each image in the generated sprite with > 1px margin to
120
+ avoid images bleeding into each other when the browser needs to scale them (e.g. when user increases/decreases font size).
121
+
122
+ Layout
123
+ ======
124
+
125
+ The generated image can be laid out in a horizontal or a vertical strip by
126
+ providing a `:layout` option (defaults to horizontal). A **new option in v1.2.0** is
127
+ to use a **:packed** layout which will attempt to generate an optimized packed
128
+ square-ish layout.
129
+
130
+ For more details on the bin-packing algorithm used:
131
+
132
+ * You can find a [description here](http://codeincomplete.com/posts/2011/5/7/bin_packing/)
133
+ * You can find a [demo here](http://codeincomplete.com/posts/2011/5/7/bin_packing/example/)
134
+
135
+ Customizing the CSS Selector
136
+ ============================
137
+
138
+ By default, the CSS generated is fairly simple. It assumes you will be using `<img>`
139
+ elements for your sprites, and that the basename of each individual file is suitable for
140
+ use as a CSS classname. For example, the following files:
141
+
142
+ images/icons/high.png
143
+ images/icons/medium.png
144
+ images/icons/low.png
145
+
146
+ ... when run with:
147
+
148
+ SpriteFactory.run!('images/icons')
149
+
150
+ ... will generate the following css:
151
+
152
+ img.high { width: 16px; height: 16px; background: url(images/icons.png) 0px 0px no-repeat; }
153
+ img.medium { width: 16px; height: 16px; background: url(images/icons.png) -16px 0px no-repeat; }
154
+ img.low { width: 16px; height: 16px; background: url(images/icons.png) -32px 0px no-repeat; }
155
+
156
+ If you want to use different selectors for your rules, you can provide the `:selector` option. For
157
+ example:
158
+
159
+ SpriteFactory.run!('images/icons', :selector => 'span.icon_')
160
+
161
+ ... will generate:
162
+
163
+ span.icon_high { width: 16px; height: 16px; background: url(images/icons.png) 0px 0px no-repeat; }
164
+ span.icon_medium { width: 16px; height: 16px; background: url(images/icons.png) -16px 0px no-repeat; }
165
+ span.icon_low { width: 16px; height: 16px; background: url(images/icons.png) -32px 0px no-repeat; }
166
+
167
+ Customizing the CSS Selector Per Image
168
+ ======================================
169
+
170
+ If you want to specify a custom selector for each individual image, then name the image files
171
+ accordingly - the library will map '\_\_' (double underscore) to a single space ' ' in any source
172
+ image filename. For example:
173
+
174
+ images/icons/div.foo__span.icon_alert.png
175
+ images/icons/div.bar__span.icon_alert.png
176
+
177
+ ... when run with:
178
+
179
+ SpriteFactory.run!('images/icons', :selector => 'div.example ')
180
+
181
+ ... will generate:
182
+
183
+ div.example div.foo span.icon_alert { ... first file ... }
184
+ div.example div.bar span.icon_alert { ... second file ... }
185
+
186
+
187
+ If you want to specify a psuedo class such as `:hover` for some of your images, the library will also
188
+ map '--' (double dash) to a colon ':' in any source image filename. For example:
189
+
190
+ images/icons/alert.png
191
+ images/icons/alert--hover.png
192
+
193
+ ... when run with:
194
+
195
+ SpriteFactory.run!('images/icons', :selector => 'span.icon_')
196
+
197
+ ... will generate:
198
+
199
+ span.icon_alert { ... first file ... }
200
+ span.icon_alert:hover { ... second file ... }
201
+
202
+ Customizing the CSS Image Url
203
+ =============================
204
+
205
+ Within the generated CSS file, it can be tricky to get the correct path to your unified
206
+ sprite image. For example, you might be hosting your images on Amazon S3, or if you are
207
+ building a Ruby on Rails application you might need to generate URL's using the `#image_path`
208
+ helper method to ensure it gets the appropriate cache-busting query parameter.
209
+
210
+ By default, the SpriteFactory generates simple url's that contain the basename of the
211
+ unified sprite image, e.g:
212
+
213
+ SpriteFactory.run('icons')
214
+
215
+ # generates: url(icons.png)
216
+
217
+ ...but you can control the generation of these url's using the `:cssurl` option:
218
+
219
+ For most CDN's, you can prepend a simple string to the image name:
220
+
221
+ SpriteFactory.run('icons',
222
+ :cssurl => "http://s3.amazonaws.com/")
223
+
224
+ # generates: url(http://s3.amazonaws.com/icons.png)
225
+
226
+ For more control, a simple token replacement can be performed using the $IMAGE token. For example, to generate calls
227
+ to custom Sass helper functions, such as those provided by [sass-rails](https://github.com/rails/sass-rails) plugin:
228
+
229
+ SpriteFactory.run('icons',
230
+ :cssurl => "image-url('$IMAGE')")
231
+
232
+ # generates: image-url('icons.png')
233
+
234
+
235
+ For full control, you can provide a lambda function and generate your own values:
236
+
237
+ SpriteFactory.run('icons',
238
+ :cssurl => lambda{|image| "url(#{image_path(image)})" })
239
+
240
+ # generates: url(/path/to/my/images/icons.png?v123456)
241
+
242
+ >> NOTE: the `:cssurl` option replaces `:csspath` from earlier versions. The previous option only let you
243
+ customize the path inside of the generated `url(...)`, while this new option allows you to customize the
244
+ entire value, including the outer `url(...)` itself.
245
+
246
+ Customizing the entire CSS output
247
+ =================================
248
+
249
+ If you want **complete** control over the generated styles, you can pass a block to the `run!` method.
250
+
251
+ The block will be provided with information about each image, including the generated css attributes.
252
+ Whatever content the block returns will be inserted into the generated css file.
253
+
254
+ SpriteFactory.run!('images/timer') do |images|
255
+ rules = []
256
+ rules << "div.running img.button { cursor: pointer; #{images[:running][:style]} }"
257
+ rules << "div.stopped img.button { cursor: pointer; #{images[:stopped][:style]} }"
258
+ rules.join("\n")
259
+ end
260
+
261
+ The `images` argument is a hash, where each key is the basename of an image file, and the
262
+ value is a hash of image metadata that includes the following:
263
+
264
+ * `:style` - the default generated style
265
+ * `:cssx` - the css sprite x position
266
+ * `:cssy` - the css sprite y position
267
+ * `:cssw` - the css sprite width
268
+ * `:cssh` - the css sprite height
269
+ * `:x` - the image x position
270
+ * `:y` - the image y position
271
+ * `:width` - the image width
272
+ * `:height` - the image height
273
+
274
+ >> NOTE: the image coords can differ form the css sprite coords when padding/margin or fixed width/height options are specified)
275
+
276
+ Using sprite-factory with the Rails asset pipeline
277
+ ==================================================
278
+
279
+ The sprite-factory gem plays nice with the Rails asset pipeline with a few simple steps:
280
+
281
+ Add the sprite-factory to your Gemfile, including your chosen image library dependency:
282
+
283
+ group :assets do
284
+ gem 'sprite-factory', '>= 1.5.2'
285
+ gem 'rmagick'
286
+ end
287
+
288
+ Store your images in Rails 3.1 `app/assets/images` sub-folders, e.g
289
+
290
+ app/assets/images/avatars/*.png
291
+ app/assets/images/icons/*.png
292
+ ...
293
+
294
+ Create a Rake task for regenerating your sprites, e.g. in `lib/tasks/assets.rake`
295
+
296
+ require 'sprite_factory'
297
+
298
+ namespace :assets do
299
+ desc 'recreate sprite images and css'
300
+ task :resprite => :environment do
301
+ SpriteFactory.cssurl = "image-url('$IMAGE')" # use a sass-rails helper method to be evaluated by the rails asset pipeline
302
+ SpriteFactory.run!('app/assets/images/avatars', :output_style => 'app/assets/stylesheets/avatars.css.erb')
303
+ SpriteFactory.run!('app/assets/images/icons', :output_style => 'app/assets/stylesheets/icons.css.erb')
304
+ # ... etc ...
305
+ end
306
+ end
307
+
308
+ Run the rake task
309
+
310
+ bundle exec rake assets:resprite
311
+
312
+ Generates
313
+
314
+ * sprite images in `app/assets/images`
315
+ * sprite styles in `app/assets/stylesheets` - automatically picked up by the asset pipeline and included in your generated application.css
316
+
317
+ You can find out more here:
318
+
319
+ * [Sprite Factory and the Rails Asset Pipeline](http://codeincomplete.com/posts/2011/8/6/sprite_factory_1_4_1/)
320
+
321
+ Extending the Library
322
+ =====================
323
+
324
+ The sprite factory library can be extended in a number of other ways.
325
+
326
+ * provide a custom layout algorithm in the `SpriteFactory::Layout` module.
327
+ * provide a custom style generator in the `SpriteFactory::Style` module.
328
+ * provide a custom image library in the `SpriteFactory::Library` module.
329
+
330
+ _(see existing code for examples of each)._
331
+
332
+ License
333
+ =======
334
+
335
+ See [LICENSE](https://github.com/jakesgordon/sprite-factory/blob/master/LICENSE) file.
336
+
337
+ Credits
338
+ =======
339
+
340
+ Thanks to my employer, [LiquidPlanner](http://liquidplanner.com) for allowing me to take this idea from our
341
+ online project management web application and release it into the wild.
342
+
343
+ Contact
344
+ =======
345
+
346
+ If you have any ideas, feedback, requests or bug reports, you can reach me at
347
+ [jake@codeincomplete.com](mailto:jake@codeincomplete.com), or via
348
+ my website: [Code inComplete](http://codeincomplete.com).
349
+
350
+
351
+
data/RELEASE_NOTES.md ADDED
@@ -0,0 +1,60 @@
1
+ March 16th 2014 - v1.6.0
2
+ ------------------------
3
+
4
+ * Added raw ImageMagick driver can be used without RMagick gem (courtesy of @willglynn - Cheers!)
5
+ * Exposed `padding` and `margin` support to the cli interface (courtesy of @miguelgonz - Cheers!)
6
+
7
+
8
+ February 21st 2013 - v1.5.3
9
+ ---------------------------
10
+ * bugfix: added back `:selector` when providing attributes for custom style generators (it was accidentally removed in v1.5.2)
11
+
12
+ January 13th 2013 - v1.5.2
13
+ --------------------------
14
+ * replaced `:csspath` option with `:cssurl` [issue #21](https://github.com/jakesgordon/sprite-factory/issues/21)
15
+ * ordered css rules by pseudoclass importance [issue #20](https://github.com/jakesgordon/sprite-factory/pull/20)
16
+ * added support for .ico files when using rmagick [issue #18](https://github.com/jakesgordon/sprite-factory/pull/18)
17
+
18
+ June 11th 2012 - v1.5.1
19
+ -----------------------
20
+ * added a new `:return => :images` option for callers that want access to the detailed `images` hash instead of the generated css content
21
+
22
+ May 10th 2012 - v1.5.0
23
+ ----------------------
24
+ * @halida added a new `margin` option to (optionally) separate images in generated spritesheet to avoid 'bleeding' when browser scales the sprite (e.g. when user increases text size)
25
+ * added `padding` support for `packed` layout
26
+ * added `margin` support for `packed` layout
27
+ * added support for using source image filename as automatic css selector [issue #12](https://github.com/jakesgordon/sprite-factory/issues/12)
28
+ * added support for `:hover` (and other pseudo-class) selectors [issue #14](https://github.com/jakesgordon/sprite-factory/issues/14)
29
+
30
+ February 29th 2012 - v1.4.2
31
+ ---------------------------
32
+ * added support for `:nocomments => true` to suppress comments in generated output stylesheet
33
+ * added support for images in subfolders - fixes [github issue #11](https://github.com/jakesgordon/sprite-factory/issues/11)
34
+
35
+ August 5th 2011 - v1.4.1
36
+ ------------------------
37
+ * added support for `:style => :scss` to generate .scss file (even though content will be almost exactly same as .css style)
38
+ * deprecated `:output` option and replaced it with 2 new explicit `:output_image` and `:output_style` options
39
+ * updated RELEASE NOTES to include setup for use with Rails 3.1 asset pipeline
40
+
41
+ Auguest 5th 2011 - v1.4.0
42
+ -------------------------
43
+ * (not available)
44
+
45
+ July 9th 2011 - v1.3.0
46
+ ----------------------
47
+
48
+ * source image file extensions now treated in case INsensitive manner (e.g. we detect both .PNG, .png and .Png)
49
+ * added `:nocss => true` option to suppress generation of output css file (caller should use `run!` return value instead - it contains the generated css content as a string)
50
+
51
+ May 8th 2011 - v1.2.0
52
+ ---------------------
53
+
54
+ * added new `:layout => :packed` option to use bin-packing algorithm for generating rectangular sprite sheet
55
+ * added pngcrush support
56
+
57
+ April 29th 2011 - v1.0.0
58
+ ------------------------
59
+
60
+ * original version
data/Rakefile ADDED
@@ -0,0 +1,73 @@
1
+ require 'rake/testtask'
2
+
3
+ #------------------------------------------------------------------------------
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.test_files = FileList['test/**/*_test.rb']
7
+ t.verbose = true
8
+ end
9
+
10
+ #------------------------------------------------------------------------------
11
+
12
+ desc "run a console with SpriteFactory loaded"
13
+ task :console do
14
+ system "irb -r #{File.expand_path('lib/sprite_factory', File.dirname(__FILE__))}"
15
+ end
16
+
17
+ #------------------------------------------------------------------------------
18
+
19
+ desc "regenerate test reference images"
20
+ task :reference do
21
+
22
+ require File.expand_path('lib/sprite_factory', File.dirname(__FILE__))
23
+
24
+ regenerate = lambda do |input, options = {}, &block|
25
+ output = options[:output] || input
26
+ SpriteFactory.run!(input, {:report => true}.merge(options), &block)
27
+ FileUtils.mv(output + "." + ( :png).to_s, 'test/images/reference')
28
+ FileUtils.mv(output + "." + (options[:style] || :css).to_s, 'test/images/reference')
29
+ end
30
+
31
+ regenerate.call('test/images/regular')
32
+ regenerate.call('test/images/regular', :output => 'test/images/regular.horizontal', :selector => 'img.horizontal_', :layout => :horizontal)
33
+ regenerate.call('test/images/regular', :output => 'test/images/regular.vertical', :selector => 'img.vertical_', :layout => :vertical)
34
+ regenerate.call('test/images/regular', :output => 'test/images/regular.packed', :selector => 'img.packed_', :layout => :packed, :padding => 10, :margin => 10)
35
+ regenerate.call('test/images/regular', :output => 'test/images/regular.padded', :selector => 'img.padded_', :padding => 10)
36
+ regenerate.call('test/images/regular', :output => 'test/images/regular.margin', :selector => 'img.margin_', :margin => 10)
37
+ regenerate.call('test/images/regular', :output => 'test/images/regular.fixed', :selector => 'img.fixed_', :width => 100, :height => 100)
38
+ regenerate.call('test/images/regular', :output => 'test/images/regular.sassy', :selector => 'img.sassy_', :style => :sass)
39
+
40
+ regenerate.call('test/images/irregular')
41
+ regenerate.call('test/images/irregular', :output => 'test/images/irregular.horizontal', :selector => 'img.horizontal_', :layout => :horizontal)
42
+ regenerate.call('test/images/irregular', :output => 'test/images/irregular.vertical', :selector => 'img.vertical_', :layout => :vertical)
43
+ regenerate.call('test/images/irregular', :output => 'test/images/irregular.packed', :selector => 'img.packed_', :layout => :packed, :padding => 10, :margin => 10)
44
+ regenerate.call('test/images/irregular', :output => 'test/images/irregular.padded', :selector => 'img.padded_', :padding => 10)
45
+ regenerate.call('test/images/irregular', :output => 'test/images/irregular.margin', :selector => 'img.margin_', :margin => 10)
46
+ regenerate.call('test/images/irregular', :output => 'test/images/irregular.fixed', :selector => 'img.fixed_', :width => 100, :height => 100)
47
+ regenerate.call('test/images/irregular', :output => 'test/images/irregular.sassy', :selector => 'img.sassy_', :style => :sass)
48
+
49
+ regenerate.call('test/images/hover', :output => 'test/images/hover', :selector => 'div.hover ', :style => :css)
50
+
51
+ regenerate.call('test/images/custom', :output => 'test/images/custom') do |images|
52
+ rules = []
53
+ rules << "div.running img.button { cursor: pointer; #{images[:running][:style]} }"
54
+ rules << "div.stopped img.button { cursor: pointer; #{images[:stopped][:style]} }"
55
+ rules.join("\n")
56
+ end
57
+
58
+ regenerate.call('test/images/formats', :library => :rmagick)
59
+
60
+ end
61
+
62
+ #------------------------------------------------------------------------------
63
+
64
+ desc "convert reference test sass files to css"
65
+ task :sass do
66
+
67
+ `sass 'test/images/reference/regular.sassy.sass' 'test/images/reference/regular.sassy.css'`
68
+ `sass 'test/images/reference/irregular.sassy.sass' 'test/images/reference/irregular.sassy.css'`
69
+
70
+ end
71
+
72
+ #------------------------------------------------------------------------------
73
+
data/bin/sf ADDED
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.push File.expand_path("../lib", File.dirname(__FILE__)) # add sprite factory library to load path
4
+
5
+ require 'sprite_factory'
6
+ require 'optparse'
7
+
8
+ options = { :report => true }
9
+ op = OptionParser.new
10
+ op.banner = "#{SpriteFactory::DESCRIPTION}\nUsage: sprite <dir> [options]"
11
+
12
+ op.on("-h", "--help") do
13
+ puts op.to_s
14
+ exit
15
+ end
16
+
17
+ op.on("-v", "--version") do
18
+ puts SpriteFactory::VERSION
19
+ exit
20
+ end
21
+
22
+ layout_help = "specify layout orientation ( horizontal, vertical, packed )"
23
+ style_help = "specify stylesheet syntax ( css, scss, sass )"
24
+ library_help = "specify image library to use ( rmagic, chunkypng )"
25
+ selector_help = "specify custom selector to use for each css rule ( default: 'img.' )"
26
+ cssurl_help = "specify custom string to use for css image urls ( default: 'url(output image basename)' )"
27
+ output_image_help = "specify output location for generated image ( default: <input folder>.png )"
28
+ output_style_help = "specify output location for generated stylesheet ( default: <input folder>.<style>)"
29
+ pngcrush_help = "use pngcrush to optimize generated image"
30
+ padding_help = "add padding to each sprite"
31
+ margin_help = "add margin to each sprite"
32
+ nocomments_help = "suppress comments in generated stylesheet"
33
+ custom_styles_help = "Add custom styles for each sprites (E.g.: --custom-styles='display: inline-block;'"
34
+
35
+ op.on("--layout [ORIENTATION]", layout_help) {|value| options[:layout] = value }
36
+ op.on("--style [STYLE]", style_help) {|value| options[:style] = value }
37
+ op.on("--library [LIBRARY]", library_help) {|value| options[:library] = value }
38
+ op.on("--selector [SELECTOR]", selector_help) {|value| options[:selector] = value }
39
+ op.on("--cssurl [CSSURL]", cssurl_help) {|value| options[:cssurl] = value }
40
+ op.on("--output-image [PATH]", output_image_help) {|value| options[:output_image] = value }
41
+ op.on("--output-style [PATH]", output_style_help) {|value| options[:output_style] = value }
42
+ op.on("--custom-styles [STYLES]", custom_styles_help) {|value| options[:custom_style] = value }
43
+ op.on("--pngcrush", pngcrush_help) {|value| options[:pngcrush] = value }
44
+ op.on("--padding [PIXELS]", padding_help) {|value| options[:padding] = value.to_i }
45
+ op.on("--margin [PIXELS]", margin_help) {|value| options[:margin] = value.to_i }
46
+ op.on("--nocomments", nocomments_help) {|value| options[:nocomments] = true }
47
+
48
+ begin
49
+ op.parse!(ARGV)
50
+ raise "a single argument must be specified containing images to be sprited" if ARGV.empty?
51
+ SpriteFactory.run!(ARGV[0], options)
52
+ rescue Exception => ex
53
+ puts ex.message
54
+ exit
55
+ end
56
+
57
+
@@ -0,0 +1,44 @@
1
+ module SpriteFactory
2
+ module Layout
3
+ module Horizontal
4
+
5
+ def self.layout(images, options = {})
6
+ width = options[:width]
7
+ height = options[:height]
8
+ hpadding = options[:hpadding] || 0
9
+ vpadding = options[:vpadding] || 0
10
+ hmargin = options[:hmargin] || 0
11
+ vmargin = options[:vmargin] || 0
12
+ max_height = height || (2 *(vpadding + vmargin) + images.map{|i| i[:height]}.max)
13
+ x = 0
14
+ images.each do |i|
15
+
16
+ if width
17
+ i[:cssw] = width
18
+ i[:cssx] = x
19
+ i[:x] = x + (width - i[:width]) / 2
20
+ else
21
+ i[:cssw] = i[:width] + (2 * hpadding) # image width plus padding
22
+ i[:cssx] = x + hmargin # anchored at x
23
+ i[:x] = i[:cssx] + hpadding # image drawn offset to account for padding
24
+ end
25
+
26
+ if height
27
+ i[:cssh] = height
28
+ i[:cssy] = 0
29
+ i[:y] = 0 + (height - i[:height]) / 2
30
+ else
31
+ i[:cssh] = i[:height] + (2 * vpadding) # image height plus padding
32
+ i[:cssy] = (max_height - i[:cssh]) / 2 # centered vertically
33
+ i[:y] = i[:cssy] + vpadding # image drawn offset to account for padding
34
+ end
35
+
36
+ x += i[:cssw] + 2 * hmargin
37
+
38
+ end
39
+ { :width => x, :height => max_height }
40
+ end
41
+
42
+ end
43
+ end
44
+ end