css_sprite 1.3.4 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +32 -5
- data/VERSION +1 -1
- data/css_sprite.gemspec +3 -2
- data/lib/css_sprite/sprite.rb +66 -65
- data/spec/css_sprite/sprite_spec.rb +23 -1
- data/spec/public/images/css_sprite/icons/facebook_icon_hover.png +0 -0
- metadata +4 -3
data/README.textile
CHANGED
@@ -4,15 +4,30 @@ automatically css sprite.
|
|
4
4
|
|
5
5
|
*************************************************************************
|
6
6
|
|
7
|
-
h2.
|
7
|
+
h2. What css_sprite does?
|
8
8
|
|
9
|
-
|
9
|
+
css sprite generates css_sprite image and css files automatically for you follow the conventions as follows.
|
10
|
+
|
11
|
+
| images under css_sprite directory | class name in css_sprite css |
|
12
|
+
| twitter_icon.png | .twitter_icon |
|
13
|
+
| facebook_icon.png | .facebook_icon |
|
14
|
+
| hotmail-logo.png | .hotmail-logo |
|
15
|
+
| gmail-logo.png | .gmail-logo |
|
16
|
+
| icons/twitter_icon.png | .icons .twitter_icon |
|
17
|
+
| widget/icons/twitter_icon.png | .widget .icons .twitter_icon |
|
18
|
+
| twitter_icon_hover.png | .twitter_icon:hover |
|
19
|
+
| twitter-icon-hover.png | .twitter-icon:hover |
|
20
|
+
|
21
|
+
css_sprite directory is the directory whose name is "css_sprite" or "css_sprite" suffixed under public/images directory.
|
22
|
+
css_sprite image is the image file automatically generated under public/images directory.
|
23
|
+
css_sprite css is the css file automatically generated under public/stylesheets directory.
|
10
24
|
|
11
25
|
**************************************************************************
|
12
26
|
|
13
27
|
h2. Install
|
14
28
|
|
15
29
|
css_sprite depends on the <code>rmagick</code> gem, please make sure RMagick is successfully installed on your system.
|
30
|
+
css_sprite also depends on the <code>optipng</code> tool as default image optimization, but you can use any other image optimization tool, check the Configuration section. If you use the default optipng tool, please make sure it is successfully installed on your system.
|
16
31
|
|
17
32
|
install css_sprite as a gem:
|
18
33
|
<pre><code>sudo gem install css_sprite</code></pre>
|
@@ -50,9 +65,19 @@ Or you can just do the css sprite manually by <code>rake css_sprite:build</code>
|
|
50
65
|
|
51
66
|
h2. Configuration
|
52
67
|
|
53
|
-
There is no need to create any configuration by default. If you want
|
68
|
+
There is no need to create any configuration by default. If you want some customizations as follows, you need to define <code>config/css_sprite.yml</code> file.
|
69
|
+
|
70
|
+
h3. Sass
|
71
|
+
|
72
|
+
<pre><code>engine:sass</code></pre>
|
73
|
+
|
74
|
+
h3. Image Optimization
|
75
|
+
|
76
|
+
css_sprite use *optipng* with optimization level 2 to optimize the auto generated css_sprite image. You can change it to any image optimization command.
|
77
|
+
|
78
|
+
<pre><code>optimization: optipng -o 7</code></pre>
|
54
79
|
|
55
|
-
h3.
|
80
|
+
h3. Customization styles
|
56
81
|
|
57
82
|
* For css
|
58
83
|
<pre><code>
|
@@ -96,7 +121,9 @@ if your image filename is icon suffixed (e.g. twitter_icon.png), the correspondi
|
|
96
121
|
|
97
122
|
h2. Best Practices
|
98
123
|
|
99
|
-
I have written
|
124
|
+
I have written posts "css sprite best practices" to introduce the idea that the css_sprite gem follows.
|
125
|
+
"english version":http://www.huangzhimin.com/entries/190-css-sprite-best-practices
|
126
|
+
"chinese version":http://www.huangzhimin.com/entries/189-css-sprite-best-practices
|
100
127
|
|
101
128
|
**************************************************************************
|
102
129
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.4.0
|
data/css_sprite.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{css_sprite}
|
8
|
-
s.version = "1.
|
8
|
+
s.version = "1.4.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Richard Huang"]
|
12
|
-
s.date = %q{2010-04-
|
12
|
+
s.date = %q{2010-04-08}
|
13
13
|
s.description = %q{css_sprite is a rails plugin/gem to generate css sprite image automatically.}
|
14
14
|
s.email = %q{flyerhzm@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -30,6 +30,7 @@ Gem::Specification.new do |s|
|
|
30
30
|
"spec/public/images/css_sprite/gmail_logo.png",
|
31
31
|
"spec/public/images/css_sprite/hotmail_logo.png",
|
32
32
|
"spec/public/images/css_sprite/icons/facebook_icon.png",
|
33
|
+
"spec/public/images/css_sprite/icons/facebook_icon_hover.png",
|
33
34
|
"spec/public/images/css_sprite/icons/twitter_icon.png",
|
34
35
|
"spec/public/images/css_sprite/not_image.txt",
|
35
36
|
"spec/spec.opts",
|
data/lib/css_sprite/sprite.rb
CHANGED
@@ -8,7 +8,6 @@ class Sprite
|
|
8
8
|
def initialize(options={})
|
9
9
|
@image_path = File.expand_path(File.join(Rails.root, 'public/images'))
|
10
10
|
@stylesheet_path = File.expand_path(File.join(Rails.root, 'public/stylesheets'))
|
11
|
-
@todo = {}
|
12
11
|
|
13
12
|
if File.exist?(File.join(Rails.root, 'config/css_sprite.yml'))
|
14
13
|
@config = YAML::load_file(File.join(Rails.root, 'config/css_sprite.yml'))
|
@@ -19,18 +18,20 @@ class Sprite
|
|
19
18
|
|
20
19
|
def build
|
21
20
|
directories = css_sprite_directories
|
22
|
-
directories.each { |directory|
|
23
|
-
output_stylesheet
|
21
|
+
directories.each { |directory| execute(directory) }
|
24
22
|
end
|
25
23
|
|
26
24
|
def check
|
27
25
|
directories = css_sprite_directories
|
28
|
-
directories.each
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
directories.each { |directory| execute(directory) if expire?(directory) }
|
27
|
+
end
|
28
|
+
|
29
|
+
def execute(directory)
|
30
|
+
results = output_image(directory)
|
31
|
+
unless results.empty?
|
32
|
+
optimize_image(directory)
|
33
|
+
output_stylesheet(directory, results)
|
32
34
|
end
|
33
|
-
output_stylesheet
|
34
35
|
end
|
35
36
|
|
36
37
|
def expire?(directory)
|
@@ -42,11 +43,11 @@ class Sprite
|
|
42
43
|
!File.exist?(stylesheet_path) or File.new(directory).mtime > File.new(stylesheet_path).mtime
|
43
44
|
end
|
44
45
|
|
45
|
-
def output_stylesheet
|
46
|
+
def output_stylesheet(directory, results)
|
46
47
|
if sass?
|
47
|
-
output_sass
|
48
|
+
output_sass(directory, results)
|
48
49
|
else
|
49
|
-
output_css
|
50
|
+
output_css(directory, results)
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
@@ -76,74 +77,74 @@ class Sprite
|
|
76
77
|
results << image_properties(source_image, directory).merge(:x => x, :y => y)
|
77
78
|
dest_image = composite_images(dest_image, source_image, x, y)
|
78
79
|
end
|
79
|
-
dest_image.image_type = Magick::PaletteMatteType
|
80
80
|
dest_image.write(dest_image_path)
|
81
81
|
end
|
82
|
-
|
82
|
+
results
|
83
|
+
end
|
84
|
+
|
85
|
+
def optimize_image(directory)
|
86
|
+
dest_image_path = dest_image_path(directory)
|
87
|
+
@config['optimization'] ? system("#{@config['optimization']} #{dest_image_path}") : system("optipng -quiet #{dest_image_path}")
|
83
88
|
end
|
84
89
|
|
85
|
-
def output_css
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
f.print "\}\n"
|
100
|
-
end
|
90
|
+
def output_css(directory, results)
|
91
|
+
unless results.empty?
|
92
|
+
dest_image_name = dest_image_name(directory)
|
93
|
+
dest_css_path = dest_css_path(directory)
|
94
|
+
dest_image_time = File.new(dest_image_path(directory)).mtime
|
95
|
+
File.open(dest_css_path, 'w') do |f|
|
96
|
+
if @config['suffix']
|
97
|
+
@config['suffix'].each do |key, value|
|
98
|
+
cns = class_names(results, :suffix => key)
|
99
|
+
unless cns.empty?
|
100
|
+
f.print cns.join(",\n")
|
101
|
+
f.print " \{\n"
|
102
|
+
f.print value.split("\n").collect { |text| " " + text }.join("\n")
|
103
|
+
f.print "\}\n"
|
101
104
|
end
|
102
105
|
end
|
103
|
-
|
104
|
-
f.print class_names(results).join(",\n")
|
105
|
-
f.print " \{\n background: url('/images/#{dest_image_name}?#{dest_image_time.to_i}') no-repeat;\n\}\n"
|
106
|
+
end
|
106
107
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
108
|
+
f.print class_names(results).join(",\n")
|
109
|
+
f.print " \{\n background: url('/images/#{dest_image_name}?#{dest_image_time.to_i}') no-repeat;\n\}\n"
|
110
|
+
|
111
|
+
results.each do |result|
|
112
|
+
f.print "#{class_name(result[:name])} \{"
|
113
|
+
f.print " background-position: #{-result[:x]}px #{-result[:y]}px;"
|
114
|
+
f.print " width: #{result[:width]}px;"
|
115
|
+
f.print " height: #{result[:height]}px;"
|
116
|
+
f.print " \}\n"
|
114
117
|
end
|
115
118
|
end
|
116
119
|
end
|
117
120
|
end
|
118
121
|
|
119
|
-
def output_sass
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
f.print "\n"
|
134
|
-
end
|
122
|
+
def output_sass(directory, results)
|
123
|
+
unless results.empty?
|
124
|
+
dest_image_name = dest_image_name(directory)
|
125
|
+
dest_sass_path = dest_sass_path(directory)
|
126
|
+
dest_image_time = File.new(dest_image_path(directory)).mtime
|
127
|
+
File.open(dest_sass_path, 'w') do |f|
|
128
|
+
if @config['suffix']
|
129
|
+
@config['suffix'].each do |key, value|
|
130
|
+
cns = class_names(results, :suffix => key)
|
131
|
+
unless cns.empty?
|
132
|
+
f.print cns.join(",\n")
|
133
|
+
f.print "\n"
|
134
|
+
f.print value.split("\n").collect { |text| " " + text }.join("\n")
|
135
|
+
f.print "\n"
|
135
136
|
end
|
136
137
|
end
|
137
|
-
|
138
|
-
f.print class_names(results).join(",\n")
|
139
|
-
f.print " \n background: url('/images/#{dest_image_name}?#{dest_image_time.to_i}') no-repeat\n"
|
138
|
+
end
|
140
139
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
140
|
+
f.print class_names(results).join(",\n")
|
141
|
+
f.print " \n background: url('/images/#{dest_image_name}?#{dest_image_time.to_i}') no-repeat\n"
|
142
|
+
|
143
|
+
results.each do |result|
|
144
|
+
f.print "#{class_name(result[:name])}\n"
|
145
|
+
f.print " background-position: #{-result[:x]}px #{-result[:y]}px\n"
|
146
|
+
f.print " width: #{result[:width]}px\n"
|
147
|
+
f.print " height: #{result[:height]}px\n"
|
147
148
|
end
|
148
149
|
end
|
149
150
|
end
|
@@ -160,7 +161,7 @@ class Sprite
|
|
160
161
|
end
|
161
162
|
|
162
163
|
def class_name(name)
|
163
|
-
".#{name.gsub('/', ' .')}"
|
164
|
+
".#{name.gsub('/', ' .').sub(/[_-]hover$/, ':hover')}"
|
164
165
|
end
|
165
166
|
|
166
167
|
def all_images(directory)
|
@@ -12,7 +12,11 @@ describe Sprite do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should build css_sprite image and sass" do
|
15
|
-
Sprite.new(
|
15
|
+
Sprite.new('engine' => 'sass').build
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should build another image optimization" do
|
19
|
+
Sprite.new('optimization' => "optipng -o 1").build
|
16
20
|
end
|
17
21
|
end
|
18
22
|
|
@@ -34,6 +38,7 @@ describe Sprite do
|
|
34
38
|
it "should read all images from a directory" do
|
35
39
|
expected_images = [File.join(IMAGE_PATH, 'css_sprite/icons/twitter_icon.png'),
|
36
40
|
File.join(IMAGE_PATH, 'css_sprite/icons/facebook_icon.png'),
|
41
|
+
File.join(IMAGE_PATH, 'css_sprite/icons/facebook_icon_hover.png'),
|
37
42
|
File.join(IMAGE_PATH, 'css_sprite/hotmail_logo.png'),
|
38
43
|
File.join(IMAGE_PATH, 'css_sprite/gmail_logo.png')]
|
39
44
|
actual_images = @sprite.all_images(File.join(IMAGE_PATH, 'css_sprite'))
|
@@ -63,6 +68,23 @@ describe Sprite do
|
|
63
68
|
end
|
64
69
|
end
|
65
70
|
|
71
|
+
describe "class_name" do
|
72
|
+
it "should get class_name with simple name" do
|
73
|
+
@sprite.class_name("twitter_icon").should == ".twitter_icon"
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should get class_name with parent class" do
|
77
|
+
@sprite.class_name("icons/twitter_icon").should == ".icons .twitter_icon"
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should get class_name with hover class" do
|
81
|
+
@sprite.class_name("icons/twitter_icon_hover").should == ".icons .twitter_icon:hover"
|
82
|
+
@sprite.class_name("icons/twitter-icon-hover").should == ".icons .twitter-icon:hover"
|
83
|
+
@sprite.class_name("twitter_hover_icon").should == ".twitter_hover_icon"
|
84
|
+
@sprite.class_name("twitter_hover_icon_hover").should == ".twitter_hover_icon:hover"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
66
88
|
describe "dest_image_path" do
|
67
89
|
it "should get css_sprite image path for a directory" do
|
68
90
|
@sprite.dest_image_path(File.join(IMAGE_PATH, 'css_sprite')).should == File.join(IMAGE_PATH, 'css_sprite.png')
|
Binary file
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 1
|
7
|
-
- 3
|
8
7
|
- 4
|
9
|
-
|
8
|
+
- 0
|
9
|
+
version: 1.4.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Richard Huang
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-04-
|
17
|
+
date: 2010-04-08 00:00:00 +08:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -52,6 +52,7 @@ files:
|
|
52
52
|
- spec/public/images/css_sprite/gmail_logo.png
|
53
53
|
- spec/public/images/css_sprite/hotmail_logo.png
|
54
54
|
- spec/public/images/css_sprite/icons/facebook_icon.png
|
55
|
+
- spec/public/images/css_sprite/icons/facebook_icon_hover.png
|
55
56
|
- spec/public/images/css_sprite/icons/twitter_icon.png
|
56
57
|
- spec/public/images/css_sprite/not_image.txt
|
57
58
|
- spec/spec.opts
|