asset-pocket 0.1 → 0.2
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.
- 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'
|