spriteful 0.0.5 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 73d334005f825ad6112c391af3a52fc0f798b438
4
- data.tar.gz: 96c043607fc238a36029ca89877f5607b534d6c7
3
+ metadata.gz: 2b498ca0bbb52dc394d82e7f70a97da8cc396e95
4
+ data.tar.gz: 12de0e904606ee2d3db4906ced8e4bf0aa83eae2
5
5
  SHA512:
6
- metadata.gz: 3d1064cdcf852ac57d17a5ca6bed3105a9211563a03886855f24e1af4b9cfc2e1ce7a5cac790c8e96820299f3e65d50629ef7f6b06d6b153d81fd403049d677f
7
- data.tar.gz: d62e19d7926ab8e76dbe5bdee58600a86fca3cb871a5946c845bba25447f9f51d8b9da82fb3071f1e969ebf9706a7fe47568aff5688b03aaad4f4def731bf358
6
+ metadata.gz: e750c5e844f876add52a6a778d7958014afb925d56df0cb444f59f7eb30d9020bd935366d1a698b64fa4f0a5e69f81ebaf83d346d24ef47c1dfba0ae14b10056
7
+ data.tar.gz: cc43b5640091d6985dcf178068521ae140041658668a9f0b3aa8d3976f8deaac4ff7c4db2703401787b870aa8e47058789612fd9c13e977c869bf031b7c9c4dc
data/README.md CHANGED
@@ -55,7 +55,7 @@ spriteful images/icons -f scss
55
55
  }
56
56
  ```
57
57
 
58
- You can also choose to genete the code using
58
+ You can also choose to generate the code using
59
59
  [Mixin Directives](http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#mixins).
60
60
 
61
61
  ```bash
@@ -71,6 +71,17 @@ spriteful images/icons -f scss --mixin
71
71
  }
72
72
  ```
73
73
 
74
+ When using SCSS, the generated stylesheet will have a variable with a list of all images
75
+ inside the generated sprite, so you can hack own your own on top of that.
76
+
77
+ ```scss
78
+ @each $image in $icons-sprite-names {
79
+ .my-class-for-#{$image} {
80
+ @extend %icons-sprite-#{$image};
81
+ }
82
+ }
83
+ ```
84
+
74
85
  ### Multiple sprites
75
86
 
76
87
  You can deal with multiple sprites in a single run. If `images/icons` has a set of images for one
@@ -110,6 +121,29 @@ images under `icons` will generate the `icons.png` and `icons.css` files. This c
110
121
  enforces previsibility over generated files and helps when regenating existing sprites whenever
111
122
  you need to add a new source to an existing sprite.
112
123
 
124
+ ## SVG Support
125
+
126
+ Spriteful has a basic support for dealing with SVG images (and not only PNGs). SVG images
127
+ will be combined along the rest of your images and will be embedded directly on the final
128
+ Stylesheet in the data URI format. Using the `svg` root class (based on Modernizr), the
129
+ data URI will be used for browsers that support SVG images and the composed PNG will work
130
+ as a fallback for legacy browsers.
131
+
132
+ ```css
133
+ .images.update-icon {
134
+ background-position: 0px -10px;
135
+ }
136
+
137
+ .svg .images.update-icon {
138
+ background-image: url('data:image/svg+xml;utf8, SVG XML goes here :)');
139
+ background-position: 0 0;
140
+ }
141
+
142
+ ```
143
+
144
+ Future versions of Spriteful could have support for generating composed images as SVG files
145
+ (and not only PNG), so feel free to send a contribution improving the feature.
146
+
113
147
  ## Available options
114
148
 
115
149
  * `--stylesheets` (`-s`) - Directory to save the generated stylesheet(s), instead of copying them to the clipboard.
@@ -1,3 +1,5 @@
1
+ require 'svg_optimizer'
2
+
1
3
  module Spriteful
2
4
  # Internal: Data structure to represent the images that are part
3
5
  # of a sprite.
@@ -20,24 +22,38 @@ module Spriteful
20
22
  # Public: Gets/sets the left position of the image in a sprite.
21
23
  attr_accessor :left
22
24
 
23
- # Public: Gets the source 'ChunkyPNG::Image'.
25
+ # Public: Gets the source 'Magick::Image'.
24
26
  attr_reader :source
25
27
 
26
28
  # Public: Initializes an Image, extracting the image
27
- # metadata such as width and path supplied by an 'ChunkyPNG::Image'
29
+ # metadata such as width and path supplied by an 'Magick::Image'
28
30
  # object that was initialized from the real image blob.
29
31
  #
30
- # chunky_image - an 'ChunkyPNG::Image' object.
31
- # path - the path where the image is present.
32
- def initialize(chunky_image, path)
33
- @source = chunky_image
34
- @path = path
32
+ # magick_image - an 'Magick::Image' object.
33
+ def initialize(magick_image)
34
+ @source = magick_image
35
+ @path = magick_image.filename
35
36
  @name = File.basename(@path)
36
- @width = chunky_image.width
37
- @height = chunky_image.height
37
+ @width = magick_image.columns
38
+ @height = magick_image.rows
38
39
 
39
40
  @top = 0
40
41
  @left = 0
41
42
  end
43
+
44
+ # Public: Gets the source image contents.
45
+ #
46
+ # Returns a String.
47
+ def blob
48
+ @blob ||= SvgOptimizer.optimize(File.read(path))
49
+ end
50
+
51
+ # Public: detects if the source is a SVG image
52
+ # based on its path.
53
+ #
54
+ # Returns true or false.
55
+ def svg?
56
+ File.extname(@path) == '.svg'
57
+ end
42
58
  end
43
59
  end
@@ -1,4 +1,4 @@
1
- require 'chunky_png'
1
+ require 'RMagick'
2
2
 
3
3
  module Spriteful
4
4
  # Public: the 'Sprite' class is responsible for combining a directory
@@ -40,7 +40,7 @@ module Spriteful
40
40
  # :spacing - spacing in pixels that should be placed between
41
41
  # the images in the sprite. Defaults to 0.
42
42
  def initialize(source_dir, destination, options = {})
43
- source_pattern = File.join(source_dir, '*.png')
43
+ source_pattern = File.join(source_dir, '*{.png,.svg}')
44
44
  sources = Dir[source_pattern].sort
45
45
 
46
46
  if sources.size == 0
@@ -53,8 +53,8 @@ module Spriteful
53
53
  @name = File.basename(source_dir)
54
54
  @filename = "#{name}.png"
55
55
  @path = File.expand_path(File.join(destination, @filename))
56
- sources = sources.map { |source| [source, ChunkyPNG::Image.from_file(source)] }
57
- @images = initialize_images(Hash[sources])
56
+ @list = Magick::ImageList.new(*sources)
57
+ @images = initialize_images(@list)
58
58
 
59
59
  @height, @width = detect_dimensions
60
60
  end
@@ -64,11 +64,12 @@ module Spriteful
64
64
  #
65
65
  # Returns nothing.
66
66
  def combine!
67
- combined = ChunkyPNG::Image.new(width, height, ChunkyPNG::Color::TRANSPARENT)
67
+ combined = Magick::Image.new(width, height)
68
+ combined.opacity = Magick::MaxRGB
68
69
  @images.each do |image|
69
- combined.compose!(image.source, image.left.abs, image.top.abs)
70
+ combined.composite!(image.source, image.left.abs, image.top.abs, Magick::SrcOverCompositeOp)
70
71
  end
71
- @blob = combined.to_blob(:best_compression)
72
+ @blob = combined.to_blob { self.format = 'png' }
72
73
  end
73
74
 
74
75
  # Public: exposes the source images found in the 'source'
@@ -110,14 +111,14 @@ module Spriteful
110
111
  # 'left' coordinates that the image will be placed
111
112
  # in the sprite.
112
113
  #
113
- # sources - a Hash of source paths and image objects.
114
- #
115
- # Returns an Array.
116
- def initialize_images(sources)
114
+ # list - a 'RMagick::ImageList' of sources.
115
+ # Returns an Array
116
+ def initialize_images(list)
117
117
  sprite_position = 0
118
118
  images = []
119
- sources.each_with_index do |(path, chunky_image), index|
120
- image = Image.new(chunky_image, path)
119
+
120
+ list.to_a.each_with_index do |magick_image, index|
121
+ image = Image.new(magick_image)
121
122
 
122
123
  if vertical?
123
124
  image.top = sprite_position
@@ -1,5 +1,5 @@
1
- require 'pathname'
2
1
  require 'erb'
2
+ require 'pathname'
3
3
 
4
4
  module Spriteful
5
5
  # Public: class responsible for putting together the CSS code
@@ -122,5 +122,15 @@ module Spriteful
122
122
  path.relative_path_from(@destination)
123
123
  end
124
124
  end
125
+
126
+ # Internal: Gets an embeddable Data URI of the image if it
127
+ # is a SVG image.
128
+ #
129
+ # Returns a String.
130
+ def data_uri(image)
131
+ if image.svg?
132
+ %['data:image/svg+xml;utf8,#{image.blob.gsub(/\r?\n/, "")}']
133
+ end
134
+ end
125
135
  end
126
136
  end
@@ -21,4 +21,10 @@
21
21
  .<%= class_name_for(sprite) %>.<%= class_name_for(image) %> {
22
22
  background-position: <%= image.left %>px <%= image.top %>px;
23
23
  }
24
+ <% if image.svg? %>
25
+ .svg .<%= class_name_for(sprite) %>.<%= class_name_for(image) %> {
26
+ background-image: url(<%= data_uri(image) %>);
27
+ background-position: 0 0;
28
+ }
29
+ <% end -%>
24
30
  <% end %>
@@ -16,6 +16,9 @@
16
16
  // <%= extension_strategy %><%= class_name_for(sprite) %>-sprite-<%= class_name_for(sprite.images.first) %>;
17
17
  // // Your styles here.
18
18
  // }
19
+ //
20
+ // There also will be available a variable named '$<%= class_name_for(sprite) %>-sprite-names'
21
+ // with all the images inside this sprite.
19
22
 
20
23
  <%= extension_prefix %><%= class_name_for(sprite) %>-sprite {
21
24
  <%- if rails? -%>
@@ -29,5 +32,13 @@
29
32
  <%= extension_prefix %><%= class_name_for(sprite) %>-sprite-<%= class_name_for(image) %> {
30
33
  <%= extension_strategy %><%= class_name_for(sprite) %>-sprite;
31
34
  background-position: <%= image.left %>px <%= image.top %>px;
35
+ <%- if image.svg? %>
36
+ .svg & {
37
+ background-image: url(<%= data_uri(image) %>);
38
+ background-position: 0 0;
39
+ }
40
+ <%- end -%>
32
41
  }
33
42
  <% end %>
43
+
44
+ $<%= class_name_for(sprite) %>-sprite-names: <%= sprite.images.map { |i| class_name_for(i) }.join(' ') %>;
@@ -1,3 +1,3 @@
1
1
  module Spriteful
2
- VERSION = '0.0.5'
2
+ VERSION = '0.1.0'
3
3
  end
@@ -0,0 +1,37 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
+ <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
5
+ width="10px" height="10px" viewBox="0 0 10 10" enable-background="new 0 0 10 10" xml:space="preserve">
6
+ <rect fill="#39B54A" width="10" height="10"/>
7
+ <g>
8
+ </g>
9
+ <g>
10
+ </g>
11
+ <g>
12
+ </g>
13
+ <g>
14
+ </g>
15
+ <g>
16
+ </g>
17
+ <g>
18
+ </g>
19
+ <g>
20
+ </g>
21
+ <g>
22
+ </g>
23
+ <g>
24
+ </g>
25
+ <g>
26
+ </g>
27
+ <g>
28
+ </g>
29
+ <g>
30
+ </g>
31
+ <g>
32
+ </g>
33
+ <g>
34
+ </g>
35
+ <g>
36
+ </g>
37
+ </svg>
Binary file
@@ -1,13 +1,26 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Spriteful::Image do
4
- let(:path) { 'path/to/image.png' }
5
- let(:chunky_image) { double('ChunkyPNG Image', width: 10, height: 5) }
6
- subject(:image) { Spriteful::Image.new(chunky_image, path) }
4
+ let(:source_image) { double('Magick Image', filename: 'path/to/image.png', columns: 10, rows: 5) }
5
+ subject(:image) { Spriteful::Image.new(source_image) }
7
6
 
8
7
  it { expect(image.name).to eq('image.png') }
9
8
  it { expect(image.path).to eq('path/to/image.png') }
10
9
  it { expect(image.width).to eq(10) }
11
10
  it { expect(image.height).to eq(5) }
12
- it { expect(image.source).to eq(chunky_image) }
11
+ it { expect(image.source).to eq(source_image) }
12
+ it { expect(image).to_not be_svg }
13
+
14
+ context 'SVG images' do
15
+ before do
16
+ source_image.stub(filename: 'spec/fixtures/svg/green.svg')
17
+ end
18
+
19
+ it { expect(image).to be_svg }
20
+
21
+ it 'returns the SVG XML as the #blob' do
22
+ xml = SvgOptimizer.optimize(File.read(source_image.filename))
23
+ expect(image.blob).to eq(xml)
24
+ end
25
+ end
13
26
  end
@@ -64,17 +64,17 @@ describe Spriteful::Sprite do
64
64
  it 'combine images vertically by default' do
65
65
  sprite = Spriteful::Sprite.new(source, destination)
66
66
  sprite.combine!
67
- image = ChunkyPNG::Image.from_blob(sprite.blob)
68
- expect(image.width).to be(10)
69
- expect(image.height).to be(20)
67
+ image = Magick::Image.from_blob(sprite.blob).first
68
+ expect(image.columns).to be(10)
69
+ expect(image.rows).to be(20)
70
70
  end
71
71
 
72
72
  it 'can combine images horizontally' do
73
73
  sprite = Spriteful::Sprite.new(source, destination, horizontal: true)
74
74
  sprite.combine!
75
- image = ChunkyPNG::Image.from_blob(sprite.blob)
76
- expect(image.width).to be(20)
77
- expect(image.height).to be(10)
75
+ image = Magick::Image.from_blob(sprite.blob).first
76
+ expect(image.columns).to be(20)
77
+ expect(image.rows).to be(10)
78
78
  end
79
79
  end
80
80
 
@@ -36,6 +36,14 @@ describe Spriteful::Stylesheet do
36
36
  expect(output).to match(/@mixin simple-sprite-red \{/)
37
37
  end
38
38
 
39
+ it 'renders a SCSS variable with the all the images in the sprite' do
40
+ sprite = Spriteful::Sprite.new(source, destination)
41
+ stylesheet = Spriteful::Stylesheet.new(sprite, destination, format: 'scss', mixin: true)
42
+ output = stylesheet.render
43
+
44
+ expect(output).to match(/\$simple-sprite-names\: blue red/)
45
+ end
46
+
39
47
  it 'documents the Spriteful options used to generate the stylesheet' do
40
48
  Spriteful.options = %w(one two three)
41
49
  sprite = Spriteful::Sprite.new(source, destination)
@@ -44,5 +52,24 @@ describe Spriteful::Stylesheet do
44
52
 
45
53
  expect(output).to match(/'spriteful one two three'/)
46
54
  end
55
+
56
+ describe 'SVG support' do
57
+ let(:source) { File.expand_path('spec/fixtures/svg') }
58
+
59
+ it 'exposes an alternative class for browsers that support SVG' do
60
+ stylesheet = Spriteful::Stylesheet.new(sprite, destination, format: 'css')
61
+ output = stylesheet.render
62
+
63
+ expect(output).to match(/^.svg.green \{/)
64
+ expect(output).to match(/^.svg .svg.green \{/)
65
+ end
66
+
67
+ it 'extends the placeholder selectors for browsers that support SVG' do
68
+ stylesheet = Spriteful::Stylesheet.new(sprite, destination, format: 'scss')
69
+ output = stylesheet.render
70
+
71
+ expect(output).to match(/^ .svg & \{/)
72
+ end
73
+ end
47
74
  end
48
75
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spriteful
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lucas Mazza
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-18 00:00:00.000000000 Z
11
+ date: 2013-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -31,19 +31,33 @@ dependencies:
31
31
  - !ruby/object:Gem::Version
32
32
  version: '2.0'
33
33
  - !ruby/object:Gem::Dependency
34
- name: chunky_png
34
+ name: rmagick
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - ~>
38
38
  - !ruby/object:Gem::Version
39
- version: 1.2.8
39
+ version: 2.13.2
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - ~>
45
45
  - !ruby/object:Gem::Version
46
- version: 1.2.8
46
+ version: 2.13.2
47
+ - !ruby/object:Gem::Dependency
48
+ name: svg_optimizer
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
47
61
  - !ruby/object:Gem::Dependency
48
62
  name: rspec
49
63
  requirement: !ruby/object:Gem::Requirement
@@ -106,6 +120,8 @@ files:
106
120
  - lib/spriteful.rb
107
121
  - spec/fixtures/simple/blue.png
108
122
  - spec/fixtures/simple/red.png
123
+ - spec/fixtures/svg/green.svg
124
+ - spec/fixtures/svg/red.png
109
125
  - spec/image_spec.rb
110
126
  - spec/spec_helper.rb
111
127
  - spec/sprite_spec.rb
@@ -131,13 +147,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
131
147
  version: '0'
132
148
  requirements: []
133
149
  rubyforge_project:
134
- rubygems_version: 2.0.6
150
+ rubygems_version: 2.0.3
135
151
  signing_key:
136
152
  specification_version: 4
137
153
  summary: ''
138
154
  test_files:
139
155
  - spec/fixtures/simple/blue.png
140
156
  - spec/fixtures/simple/red.png
157
+ - spec/fixtures/svg/green.svg
158
+ - spec/fixtures/svg/red.png
141
159
  - spec/image_spec.rb
142
160
  - spec/spec_helper.rb
143
161
  - spec/sprite_spec.rb