asset-pocket 0.1 → 0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/features/rails.feature +0 -34
- data/lib/asset_pocket/pocket.rb +0 -37
- metadata +10 -11
- data/features/sprites.feature +0 -94
- data/features/step_definitions/sprites.rb +0 -76
- data/lib/asset_pocket.rb +0 -4
- data/lib/asset_pocket/css_sprites.rb +0 -141
- data/lib/asset_pocket/rails.rb +0 -15
- data/rails/init.rb +0 -1
data/features/rails.feature
CHANGED
@@ -1,9 +1,5 @@
|
|
1
1
|
|
2
2
|
Feature: Rails integration
|
3
|
-
Rails views have a helper method sprite_tag to create a HTML tag which will
|
4
|
-
show the image.
|
5
|
-
|
6
|
-
The rake task pocket:update will generate the pocket.
|
7
3
|
|
8
4
|
@rails
|
9
5
|
Scenario: create a new application and define a pocket with some files
|
@@ -20,33 +16,3 @@ Feature: Rails integration
|
|
20
16
|
When update the pocket
|
21
17
|
Then a file named "public/stylesheets/application.css" contains "1\n2"
|
22
18
|
|
23
|
-
@rails
|
24
|
-
Scenario: create a CSS sprite in a rails application
|
25
|
-
Given a rails application in a temporary directory
|
26
|
-
And a file named "app/views/images/first.png" with a random image of 10x20
|
27
|
-
And a file named "app/views/images/second.png" with a random image of 10x30
|
28
|
-
And the application has a pocket with:
|
29
|
-
"""
|
30
|
-
css "public/stylesheets/sprites.css" do
|
31
|
-
sprite "icons" do
|
32
|
-
layout :vertical
|
33
|
-
use "app/views/images/*"
|
34
|
-
end
|
35
|
-
end
|
36
|
-
"""
|
37
|
-
And the controller "foo" has a view "index" with:
|
38
|
-
"""
|
39
|
-
<%= sprite_tag "icons/first" %>
|
40
|
-
generated HTML from rails
|
41
|
-
<%= sprite_tag "icons/second" %>
|
42
|
-
"""
|
43
|
-
When update the pocket
|
44
|
-
Then the sprite "icons" is generated in "public/stylesheets/sprites.css"
|
45
|
-
And this sprite has 2 images
|
46
|
-
And this sprite is 10x50
|
47
|
-
And this sprite format is PNG
|
48
|
-
And this sprite has the image "first"
|
49
|
-
And this sprite has the image "second"
|
50
|
-
Then the page at "/foo/index" include "generated HTML from rails"
|
51
|
-
And this page has a tag matched with ".sprite-icons--first"
|
52
|
-
And this page has a tag matched with ".sprite-icons--second"
|
data/lib/asset_pocket/pocket.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
|
2
2
|
require 'asset_pocket/compressor'
|
3
|
-
require 'asset_pocket/css_sprites'
|
4
3
|
|
5
4
|
module AssetPocket
|
6
5
|
class Pocket
|
@@ -94,42 +93,6 @@ module AssetPocket
|
|
94
93
|
end
|
95
94
|
|
96
95
|
class CSSDefinitions < Definitions
|
97
|
-
|
98
|
-
def sprite(name, &block)
|
99
|
-
@current_sprite = SpriteDefition.new(name, self)
|
100
|
-
block.call
|
101
|
-
@current_sprite.generate!
|
102
|
-
ensure
|
103
|
-
@current_sprite = nil
|
104
|
-
end
|
105
|
-
|
106
|
-
def layout(value)
|
107
|
-
ensure_sprite!
|
108
|
-
@current_sprite.layout = value
|
109
|
-
end
|
110
|
-
|
111
|
-
def images_location(value)
|
112
|
-
ensure_sprite!
|
113
|
-
@current_sprite.images_location = value
|
114
|
-
end
|
115
|
-
|
116
|
-
def quality(value)
|
117
|
-
ensure_sprite!
|
118
|
-
@current_sprite.quality = value
|
119
|
-
end
|
120
|
-
|
121
|
-
def use(pattern)
|
122
|
-
if @current_sprite
|
123
|
-
@current_sprite.use pattern
|
124
|
-
else
|
125
|
-
super
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
private
|
130
|
-
def ensure_sprite!
|
131
|
-
raise NameError, "this macro has to be used in a sprite block" if @current_sprite.nil?
|
132
|
-
end
|
133
96
|
end
|
134
97
|
|
135
98
|
class JSDefinitions < Definitions
|
metadata
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: asset-pocket
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 15
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 0
|
7
|
-
-
|
8
|
-
version: "0.
|
8
|
+
- 2
|
9
|
+
version: "0.2"
|
9
10
|
platform: ruby
|
10
11
|
authors:
|
11
12
|
- Ayose Cazorla
|
@@ -13,7 +14,7 @@ autorequire:
|
|
13
14
|
bindir: bin
|
14
15
|
cert_chain: []
|
15
16
|
|
16
|
-
date: 2010-
|
17
|
+
date: 2010-10-14 00:00:00 +01:00
|
17
18
|
default_executable:
|
18
19
|
dependencies: []
|
19
20
|
|
@@ -30,22 +31,16 @@ files:
|
|
30
31
|
- features/support/env.rb
|
31
32
|
- features/step_definitions/files.rb
|
32
33
|
- features/step_definitions/rails.rb
|
33
|
-
- features/step_definitions/sprites.rb
|
34
34
|
- features/rails.feature
|
35
35
|
- features/images.feature
|
36
36
|
- features/sass.feature
|
37
37
|
- features/javascripts.feature
|
38
|
-
- features/sprites.feature
|
39
38
|
- lib/asset_pocket/pocket.rb
|
40
|
-
- lib/asset_pocket/css_sprites.rb
|
41
39
|
- lib/asset_pocket/source_filter.rb
|
42
40
|
- lib/asset_pocket/compressor.rb
|
43
41
|
- lib/asset_pocket/generator.rb
|
44
|
-
- lib/asset_pocket/rails.rb
|
45
|
-
- lib/asset_pocket.rb
|
46
42
|
- lib/tasks/pocket.rake
|
47
|
-
|
48
|
-
has_rdoc: true
|
43
|
+
has_rdoc: false
|
49
44
|
homepage: http://github.com/setepo/asset_pocket
|
50
45
|
licenses: []
|
51
46
|
|
@@ -55,23 +50,27 @@ rdoc_options: []
|
|
55
50
|
require_paths:
|
56
51
|
- lib
|
57
52
|
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
58
54
|
requirements:
|
59
55
|
- - ">="
|
60
56
|
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
61
58
|
segments:
|
62
59
|
- 0
|
63
60
|
version: "0"
|
64
61
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
65
63
|
requirements:
|
66
64
|
- - ">="
|
67
65
|
- !ruby/object:Gem::Version
|
66
|
+
hash: 3
|
68
67
|
segments:
|
69
68
|
- 0
|
70
69
|
version: "0"
|
71
70
|
requirements: []
|
72
71
|
|
73
72
|
rubyforge_project:
|
74
|
-
rubygems_version: 1.3.
|
73
|
+
rubygems_version: 1.3.7
|
75
74
|
signing_key:
|
76
75
|
specification_version: 3
|
77
76
|
summary: Manages assets in a versatile way
|
data/features/sprites.feature
DELETED
@@ -1,94 +0,0 @@
|
|
1
|
-
|
2
|
-
Feature: generate CSS sprites from the pocket
|
3
|
-
|
4
|
-
@sprites
|
5
|
-
Scenario: create a simple sprite with different images
|
6
|
-
Given a file named "images/a.png" with a random image of 10x10
|
7
|
-
And a file named "images/b.png" with a random image of 10x20
|
8
|
-
And a file named "images/c.png" with a random image of 20x20
|
9
|
-
When generate a pocket with:
|
10
|
-
"""
|
11
|
-
css "sprites/css/first.css" do
|
12
|
-
sprite "all" do
|
13
|
-
layout :vertical
|
14
|
-
use "images/*"
|
15
|
-
end
|
16
|
-
end
|
17
|
-
"""
|
18
|
-
Then the sprite "all" is generated in "sprites/css/first.css"
|
19
|
-
And this sprite has 3 images
|
20
|
-
And this sprite is 20x50
|
21
|
-
And this sprite format is PNG
|
22
|
-
|
23
|
-
@sprites
|
24
|
-
Scenario Outline: sprites can be generated with different layoutes
|
25
|
-
Given 20 random images at "images/<case>/firstNN.png" with a random image of 10x30
|
26
|
-
When generate a pocket with:
|
27
|
-
"""
|
28
|
-
css "sprites/css/<case>.css" do
|
29
|
-
sprite "all-<case>" do
|
30
|
-
layout <layout>
|
31
|
-
use "images/<case>/*"
|
32
|
-
end
|
33
|
-
end
|
34
|
-
"""
|
35
|
-
Then the sprite "all-<case>" is generated in "sprites/css/<case>.css"
|
36
|
-
And this sprite has 20 images
|
37
|
-
And this sprite is <size>
|
38
|
-
And this sprite format is PNG
|
39
|
-
|
40
|
-
Scenarios:
|
41
|
-
| case | layout | size |
|
42
|
-
| vertical | :vertical | 10x600 |
|
43
|
-
| horizontal | :horizontal | 200x30 |
|
44
|
-
| table | :columns => 5 | 50x120 |
|
45
|
-
|
46
|
-
@sprites
|
47
|
-
Scenario: different formats create different sprites
|
48
|
-
Given a file named "images/a.png" with a random image of 10x10
|
49
|
-
And a file named "images/b.png" with a random image of 10x20
|
50
|
-
And a file named "images/c.gif" with a random image of 20x20
|
51
|
-
And 10 random images at "images/firstNN.jpeg" with a random image of 10x30
|
52
|
-
When generate a pocket with:
|
53
|
-
"""
|
54
|
-
css "sprites/css/multiformat.css" do
|
55
|
-
sprite "multiformat" do
|
56
|
-
layout :vertical
|
57
|
-
use "images/*"
|
58
|
-
end
|
59
|
-
end
|
60
|
-
"""
|
61
|
-
Then the sprite "multiformat" encoded in PNG is generated in "sprites/css/multiformat.css"
|
62
|
-
And this sprite has 2 images
|
63
|
-
And this sprite is 10x30
|
64
|
-
And the sprite "multiformat" encoded in GIF is generated in "sprites/css/multiformat.css"
|
65
|
-
And this sprite has 1 image
|
66
|
-
And this sprite is 20x20
|
67
|
-
And the sprite "multiformat" encoded in JPEG is generated in "sprites/css/multiformat.css"
|
68
|
-
And this sprite has 10 images
|
69
|
-
And this sprite is 10x300
|
70
|
-
|
71
|
-
@sprites
|
72
|
-
Scenario: the sprites can be generated using different quality values
|
73
|
-
Given a file named "images/a.jpeg" with a random image of 10x10
|
74
|
-
And a file named "images/b.jpeg" with a random image of 10x20
|
75
|
-
And a file named "images/c.jpeg" with a random image of 20x20
|
76
|
-
When generate a pocket with:
|
77
|
-
"""
|
78
|
-
css "sprites/css/everything.css" do
|
79
|
-
sprite "best" do
|
80
|
-
layout :vertical
|
81
|
-
quality 100
|
82
|
-
use "images/*"
|
83
|
-
end
|
84
|
-
|
85
|
-
sprite "worst" do
|
86
|
-
layout :vertical
|
87
|
-
quality 1
|
88
|
-
use "images/*"
|
89
|
-
end
|
90
|
-
end
|
91
|
-
"""
|
92
|
-
Then the sprite "worst" is generated in "sprites/css/everything.css"
|
93
|
-
And the sprite "best" is generated in "sprites/css/everything.css"
|
94
|
-
And the size of the sprite "worst" is smaller than the size of the sprite "best"
|
@@ -1,76 +0,0 @@
|
|
1
|
-
|
2
|
-
def random_image(filename, width, height)
|
3
|
-
img = Magick::Image.new(width, height)
|
4
|
-
img.import_pixels 0, 0, width, height, "RGB", File.read("/dev/urandom", width*height*3)
|
5
|
-
|
6
|
-
filename = @temp_dir.join(filename)
|
7
|
-
filename.dirname.mkpath
|
8
|
-
img.write filename.to_s
|
9
|
-
|
10
|
-
@created_files.unshift filename if @created_files
|
11
|
-
end
|
12
|
-
|
13
|
-
Given /^(\d+) random images at "([^"]*)" with a random image of (\d+)x(\d+)$/ do |count, pattern, width, height|
|
14
|
-
width = width.to_i
|
15
|
-
height = height.to_i
|
16
|
-
count.to_i.times do |iter|
|
17
|
-
random_image pattern.sub("NN", iter.to_s), width, height
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
Given /^a file named "([^"]*)" with a random image of (\d+)x(\d+)$/ do |filename, width, height|
|
22
|
-
random_image filename, width.to_i, height.to_i
|
23
|
-
end
|
24
|
-
|
25
|
-
|
26
|
-
def just_parse_css(content)
|
27
|
-
content.scan(/(\S+)\s*\{(.*?)\}/m).inject({}) do |hash, item|
|
28
|
-
rule, attributes = item
|
29
|
-
hash[rule] = attributes.split(";").map {|attribute| attribute.strip }
|
30
|
-
hash
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
Then /^the sprite "([^"]*)" is generated in "([^"]*)"$/ do |sprite, css_file|
|
35
|
-
Then %|the sprite "#{sprite}" encoded in \\w+ is generated in "#{css_file}"|
|
36
|
-
end
|
37
|
-
|
38
|
-
Then /^the sprite "([^"]*)" encoded in (\S+) is generated in "([^"]*)"$/ do |sprite, format, css_file|
|
39
|
-
|
40
|
-
@found_sprites ||= {}
|
41
|
-
|
42
|
-
@sprite_name = sprite
|
43
|
-
|
44
|
-
css_file = @temp_dir.join(css_file)
|
45
|
-
@css_loaded = just_parse_css(css_file.read)
|
46
|
-
@css_loaded.should include_key(/\.sprite-#{sprite}--/)
|
47
|
-
|
48
|
-
@sprite = @css_loaded.reject {|key, value| key !~ /\.sprite-#{sprite}--/ or value.join !~ /url\([^)]+\.#{format}\)/i }
|
49
|
-
@image_sprite = Magick::Image.read(css_file.dirname.join(@sprite.values.to_s.first =~ /url\((.*?\.#{format})\)/i && $1).to_s).first
|
50
|
-
|
51
|
-
@found_sprites[sprite] = @image_sprite
|
52
|
-
end
|
53
|
-
|
54
|
-
Then /^this sprite has (\d+) images?$/ do |count|
|
55
|
-
@sprite.size.should eql(count.to_i)
|
56
|
-
end
|
57
|
-
|
58
|
-
Then /^this sprite is (\d+)x(\d+)$/ do |width, height|
|
59
|
-
@image_sprite.columns.should eql(width.to_i)
|
60
|
-
@image_sprite.rows.should eql(height.to_i)
|
61
|
-
end
|
62
|
-
|
63
|
-
Then /^this sprite format is (\S+)$/ do |format|
|
64
|
-
@image_sprite.format.downcase.should eql(format.downcase)
|
65
|
-
end
|
66
|
-
|
67
|
-
Then /^this sprite has the image "([^"]*)"$/ do |image_name|
|
68
|
-
@css_loaded.should include_key(/\.sprite-#{@sprite_name}--#{image_name}\b/)
|
69
|
-
end
|
70
|
-
|
71
|
-
Then /^the size of the sprite "([^"]*)" is smaller than the size of the sprite "([^"]*)"$/ do |big_sprite, small_sprite|
|
72
|
-
@found_sprites[big_sprite].should_not be_nil
|
73
|
-
@found_sprites[small_sprite].should_not be_nil
|
74
|
-
(@found_sprites[big_sprite].to_blob > @found_sprites[small_sprite].to_blob).should be_true
|
75
|
-
end
|
76
|
-
|
data/lib/asset_pocket.rb
DELETED
@@ -1,141 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'RMagick'
|
3
|
-
require 'md5'
|
4
|
-
|
5
|
-
module AssetPocket
|
6
|
-
class Pocket
|
7
|
-
class SpriteDefition
|
8
|
-
attr_accessor :layout, :quality
|
9
|
-
attr_reader :name, :css_block, :images_location
|
10
|
-
|
11
|
-
def initialize(name, css_block)
|
12
|
-
@name = name
|
13
|
-
@css_block = css_block
|
14
|
-
@files = {}
|
15
|
-
@layout = :vertical
|
16
|
-
|
17
|
-
self.images_location = "../images/"
|
18
|
-
end
|
19
|
-
|
20
|
-
def images_location=(location)
|
21
|
-
@images_location = css_block.pocket.generator.root_path.join(css_block.filename).dirname.join(location)
|
22
|
-
end
|
23
|
-
|
24
|
-
def generate!
|
25
|
-
@images_location.mkpath
|
26
|
-
|
27
|
-
@files.each_pair do |format, images|
|
28
|
-
|
29
|
-
sprite_name = @images_location.join("sprite-#{name}.#{format.downcase}")
|
30
|
-
url_css_sprite = sprite_name.relative_path_from(css_block.full_filename.dirname)
|
31
|
-
|
32
|
-
# Compute the canvas size
|
33
|
-
width = 0
|
34
|
-
height = 0
|
35
|
-
|
36
|
-
distribute_images images do |image, cx, cy|
|
37
|
-
cx = cx + image.columns
|
38
|
-
cy = cy + image.rows
|
39
|
-
|
40
|
-
height = cy if cy > height
|
41
|
-
width = cx if cx > width
|
42
|
-
end
|
43
|
-
|
44
|
-
canvas = Magick::Image.new(width, height)
|
45
|
-
canvas.format = format
|
46
|
-
|
47
|
-
distribute_images images do |image, cx, cy|
|
48
|
-
canvas.composite! image, cx, cy, Magick::OverCompositeOp
|
49
|
-
|
50
|
-
css = ".sprite.sprite-#{name}--#{File.basename(image.filename).gsub(/\.\w+$/, "")} {"
|
51
|
-
css << "background: url(#{url_css_sprite}) -#{cx}px -#{cy}px;"
|
52
|
-
css << "width: #{image.columns}px;"
|
53
|
-
css << "height: #{image.rows}px;"
|
54
|
-
css << "} \n"
|
55
|
-
css_block.content << [ :string, css]
|
56
|
-
end
|
57
|
-
|
58
|
-
images.clear
|
59
|
-
quality = quality() # Force variable creation. Block passed to canvas.write losses instance reference (called with instance_eval?)
|
60
|
-
canvas.write(sprite_name.to_s) do |info|
|
61
|
-
info.quality = quality if quality
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def use(pattern)
|
67
|
-
@files ||= []
|
68
|
-
Dir[css_block.pocket.generator.root_path.join(pattern)].each do |image_file|
|
69
|
-
begin
|
70
|
-
image = Magick::Image.read(image_file)
|
71
|
-
if image.size != 1
|
72
|
-
# Animated images can not be sprited
|
73
|
-
# TODO log the action
|
74
|
-
next
|
75
|
-
end
|
76
|
-
|
77
|
-
image = image.first
|
78
|
-
|
79
|
-
rescue Magick::ImageMagickError
|
80
|
-
# TODO log the error
|
81
|
-
next
|
82
|
-
end
|
83
|
-
|
84
|
-
@files[image.format] ||= []
|
85
|
-
@files[image.format] << image
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
private
|
90
|
-
def distribute_images(images, &block)
|
91
|
-
cx = cy = 0
|
92
|
-
valid_layout = true
|
93
|
-
|
94
|
-
case layout
|
95
|
-
when :vertical
|
96
|
-
images.each do |image|
|
97
|
-
block.call image, cx, cy
|
98
|
-
cy += image.rows
|
99
|
-
end
|
100
|
-
|
101
|
-
when :horizontal
|
102
|
-
images.each do |image|
|
103
|
-
block.call image, cx, cy
|
104
|
-
cx += image.columns
|
105
|
-
end
|
106
|
-
|
107
|
-
when Hash
|
108
|
-
if layout[:columns]
|
109
|
-
column = 0
|
110
|
-
row_height = 0
|
111
|
-
columns_per_row = layout[:columns]
|
112
|
-
|
113
|
-
images.each do |image|
|
114
|
-
column += 1
|
115
|
-
if column > columns_per_row
|
116
|
-
column = 1
|
117
|
-
cx = 0
|
118
|
-
cy += row_height
|
119
|
-
row_height = 0
|
120
|
-
end
|
121
|
-
|
122
|
-
block.call image, cx, cy
|
123
|
-
cx += image.columns
|
124
|
-
row_height = image.rows if image.rows > row_height
|
125
|
-
end
|
126
|
-
|
127
|
-
else
|
128
|
-
valid_layout = false
|
129
|
-
end
|
130
|
-
|
131
|
-
else
|
132
|
-
valid_layout = false
|
133
|
-
end
|
134
|
-
|
135
|
-
unless valid_layout
|
136
|
-
raise ArgumentError, "Unknown layout: #{layout} in sprite #{name}"
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
data/lib/asset_pocket/rails.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
|
2
|
-
module AssetPocket
|
3
|
-
module ViewHelperMethods
|
4
|
-
def sprite_tag(name, options = {})
|
5
|
-
# TODO options: tag_name, :class, :style, something like that
|
6
|
-
# TODO Generate the CSS class name inside AssetPocket, and not hardcoded
|
7
|
-
group, image = name.split("/")
|
8
|
-
%[<span class="sprite-#{group}--#{image}"> </span>].html_safe
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
ActionView::Base.class_eval do
|
14
|
-
include AssetPocket::ViewHelperMethods
|
15
|
-
end
|
data/rails/init.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'asset_pocket/rails'
|