spriteful 0.0.5 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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