css_image_embedder 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +10 -0
- data/Manifest +14 -15
- data/README.md +8 -38
- data/Rakefile +2 -2
- data/css_image_embedder.gemspec +14 -17
- data/lib/css_image_embedder.rb +1 -3
- data/lib/css_image_embedder/compressor.rb +10 -8
- data/lib/css_image_embedder/engine.rb +34 -64
- data/lib/css_image_embedder/image.rb +57 -0
- data/spec/{files → app/assets/images}/bg.png +0 -0
- data/spec/{files → app/assets/images}/bg_base64.png +0 -0
- data/spec/{files → app/assets/images}/too_big.jpg +0 -0
- data/spec/{files → app/assets/stylesheets}/big_converted.css +0 -0
- data/spec/{files → app/assets/stylesheets}/file_sources_invalid.css +0 -0
- data/spec/{files → app/assets/stylesheets}/oneliner.css +0 -0
- data/spec/{files → app/assets/stylesheets}/oneliner_converted.css +0 -0
- data/spec/app/assets/stylesheets/std.css +6 -0
- data/spec/{files → app/assets/stylesheets}/std_converted.css +0 -0
- data/spec/app/assets/stylesheets/too_big.css +6 -0
- data/spec/compressor_spec.rb +26 -0
- data/spec/engine_spec.rb +33 -0
- data/spec/image_spec.rb +54 -0
- data/spec/spec_helper.rb +27 -1
- metadata +29 -32
- data/lib/css_image_embedder/converter.rb +0 -65
- data/lib/css_image_embedder/exception.rb +0 -9
- data/lib/css_image_embedder/helper.rb +0 -46
- data/spec/css_image_embedder_spec.rb +0 -168
- data/spec/files/std.css +0 -6
- data/spec/files/too_big.css +0 -6
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
= Version 0.3.0
|
2
|
+
* Removed Rails 2.3 compatibility
|
3
|
+
* Removed Rails 3.0 compatibility
|
4
|
+
* Removed Rails 3.1 compatibility
|
5
|
+
* Removed Ruby 1.8 compatibility
|
6
|
+
* Removed non-rails app support
|
7
|
+
* Huge refactoring
|
8
|
+
* Docs are now in yard
|
9
|
+
* Easier asset pipeline integration
|
10
|
+
|
1
11
|
= Version 0.1.1
|
2
12
|
* Fixed compressed (one line) embeds
|
3
13
|
|
data/Manifest
CHANGED
@@ -3,24 +3,23 @@ Gemfile
|
|
3
3
|
LICENCE
|
4
4
|
README.md
|
5
5
|
Rakefile
|
6
|
-
css_image_embedder.gemspec
|
7
6
|
init.rb
|
8
7
|
lib/css_image_embedder.rb
|
9
8
|
lib/css_image_embedder/compressor.rb
|
10
|
-
lib/css_image_embedder/converter.rb
|
11
9
|
lib/css_image_embedder/engine.rb
|
12
|
-
lib/css_image_embedder/
|
13
|
-
|
14
|
-
spec/
|
15
|
-
spec/
|
16
|
-
spec/
|
17
|
-
spec/
|
18
|
-
spec/
|
19
|
-
spec/
|
20
|
-
spec/
|
21
|
-
spec/
|
22
|
-
spec/
|
23
|
-
spec/
|
24
|
-
spec/
|
10
|
+
lib/css_image_embedder/image.rb
|
11
|
+
spec/app/assets/images/bg.png
|
12
|
+
spec/app/assets/images/bg_base64.png
|
13
|
+
spec/app/assets/images/too_big.jpg
|
14
|
+
spec/app/assets/stylesheets/big_converted.css
|
15
|
+
spec/app/assets/stylesheets/file_sources_invalid.css
|
16
|
+
spec/app/assets/stylesheets/oneliner.css
|
17
|
+
spec/app/assets/stylesheets/oneliner_converted.css
|
18
|
+
spec/app/assets/stylesheets/std.css
|
19
|
+
spec/app/assets/stylesheets/std_converted.css
|
20
|
+
spec/app/assets/stylesheets/too_big.css
|
21
|
+
spec/compressor_spec.rb
|
22
|
+
spec/engine_spec.rb
|
23
|
+
spec/image_spec.rb
|
25
24
|
spec/spec_helper.rb
|
26
25
|
Manifest
|
data/README.md
CHANGED
@@ -8,55 +8,25 @@ Css Image Embedder puts your background files directly into corresponding CSS fi
|
|
8
8
|
|
9
9
|
# USAGE
|
10
10
|
|
11
|
-
## Rails 3.
|
12
|
-
|
13
|
-
Add gem to your gemfile:
|
14
|
-
|
15
|
-
gem 'css_image_embedder'
|
16
|
-
|
17
|
-
and then you will gain a helper method called `image_embed_stylesheet_link_tag`. Use it instead of `stylesheet_link_tag` (params are the same). This helper method will not destroy (or modify) your original CSS files. It only changes cached CSS file, so if you do not use:
|
18
|
-
|
19
|
-
:cache => "/path/cached_stylesheets.css"
|
20
|
-
|
21
|
-
method will act the same way as `stylesheet_link_tag`. Also - you will not see any effect in development environment (except when you turn caching on).
|
22
|
-
|
23
|
-
## Rails 3.1
|
11
|
+
## Ruby on Rails 3.1 and 3.2
|
24
12
|
|
25
13
|
In environments/production.rb:
|
26
14
|
|
27
|
-
config.assets.css_compressor = CssImageEmbedder::Compressor.new
|
15
|
+
config.assets.css_compressor = CssImageEmbedder::Compressor.new
|
28
16
|
|
29
17
|
## Disadvantages
|
30
18
|
|
31
19
|
Css Image Embedder has one major disadvantage. Files converted into base64 are approximately 30% bigger then normal, so when you embed them into CSS file, the total size of CSS with backgrounds will not be equal to sum of CSS file and backgrounds files. However, if you use gzip compression on your server - it will compress CSS file and the total size will be approximately equal. So just turn gzip compression on :)
|
32
|
-
## Example
|
33
|
-
|
34
|
-
### Rails 3.0 (and probably 2.3.7 ;) )
|
35
20
|
|
36
|
-
|
37
|
-
|
38
|
-
The background declarations will be normal. You don't need to do anything special in your CSS files. So lets take `first.css`:
|
39
|
-
|
40
|
-
#first { background: #fff url(/images/bg1.png) no-repeat;}
|
41
|
-
|
42
|
-
and second stylesheet:
|
43
|
-
|
44
|
-
#second { background: #fff url(/images/bg2.png) no-repeat;}
|
45
|
-
|
46
|
-
Now lets just use them in our layout:
|
21
|
+
## Example
|
47
22
|
|
48
|
-
|
49
|
-
"first", "second",
|
50
|
-
:cache => "cached_stylesheet"
|
51
|
-
)
|
52
|
-
|
53
|
-
This will produce nice `cached_stylesheet` with both background images embedded directly into cached CSS file.
|
23
|
+
We set up CssImageEmbedder::Compressor as a css compressor and... thats all :)
|
54
24
|
|
55
|
-
|
25
|
+
config.assets.css_compressor = CssImageEmbedder::Compressor.new
|
56
26
|
|
57
|
-
|
27
|
+
## Tests
|
58
28
|
|
59
|
-
|
29
|
+
bundle exec rspec spec/
|
60
30
|
|
61
31
|
## Note on Patches/Pull Requests
|
62
32
|
|
@@ -69,4 +39,4 @@ We set up CssImageEmbedder::Compressor as a css compressor and... thats all :)
|
|
69
39
|
|
70
40
|
## Copyright
|
71
41
|
|
72
|
-
Copyright (c)
|
42
|
+
Copyright (c) 2013 Maciej Mensfeld. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -3,12 +3,12 @@ require 'rubygems'
|
|
3
3
|
require 'rake'
|
4
4
|
require 'echoe'
|
5
5
|
|
6
|
-
Echoe.new('css_image_embedder', '0.
|
6
|
+
Echoe.new('css_image_embedder', '0.3.0') do |p|
|
7
7
|
p.description = "Css Image Embedder puts your background files directly into corresponding CSS file. Thanks to that - your server needs to handle fewer requests and the page layout renders smoothly (whole stylesheet at once)."
|
8
8
|
p.url = "https://github.com/mensfeld/Css-Image-Embedder"
|
9
9
|
p.author = "Maciej Mensfeld"
|
10
10
|
p.email = "maciej@mensfeld.pl"
|
11
11
|
p.ignore_pattern = ["tmp/*", "script/*"]
|
12
|
-
p.development_dependencies = ["rspec >=2.0.0"
|
12
|
+
p.development_dependencies = ["rspec >=2.0.0"]
|
13
13
|
p.dependencies = ["sass"]
|
14
14
|
end
|
data/css_image_embedder.gemspec
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
|
-
s.name =
|
5
|
-
s.version = "0.
|
4
|
+
s.name = "css_image_embedder"
|
5
|
+
s.version = "0.3.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
-
s.authors = [
|
9
|
-
s.date =
|
10
|
-
s.description =
|
11
|
-
s.email =
|
12
|
-
s.extra_rdoc_files = [
|
13
|
-
s.files = [
|
14
|
-
s.homepage =
|
15
|
-
s.rdoc_options = [
|
16
|
-
s.require_paths = [
|
17
|
-
s.rubyforge_project =
|
18
|
-
s.rubygems_version =
|
19
|
-
s.summary =
|
8
|
+
s.authors = ["Maciej Mensfeld"]
|
9
|
+
s.date = "2013-05-25"
|
10
|
+
s.description = "Css Image Embedder puts your background files directly into corresponding CSS file. Thanks to that - your server needs to handle fewer requests and the page layout renders smoothly (whole stylesheet at once)."
|
11
|
+
s.email = "maciej@mensfeld.pl"
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG.rdoc", "README.md", "lib/css_image_embedder.rb", "lib/css_image_embedder/compressor.rb", "lib/css_image_embedder/engine.rb", "lib/css_image_embedder/image.rb"]
|
13
|
+
s.files = ["CHANGELOG.rdoc", "Gemfile", "LICENCE", "README.md", "Rakefile", "init.rb", "lib/css_image_embedder.rb", "lib/css_image_embedder/compressor.rb", "lib/css_image_embedder/engine.rb", "lib/css_image_embedder/image.rb", "spec/app/assets/images/bg.png", "spec/app/assets/images/bg_base64.png", "spec/app/assets/images/too_big.jpg", "spec/app/assets/stylesheets/big_converted.css", "spec/app/assets/stylesheets/file_sources_invalid.css", "spec/app/assets/stylesheets/oneliner.css", "spec/app/assets/stylesheets/oneliner_converted.css", "spec/app/assets/stylesheets/std.css", "spec/app/assets/stylesheets/std_converted.css", "spec/app/assets/stylesheets/too_big.css", "spec/compressor_spec.rb", "spec/engine_spec.rb", "spec/image_spec.rb", "spec/spec_helper.rb", "Manifest", "css_image_embedder.gemspec"]
|
14
|
+
s.homepage = "https://github.com/mensfeld/Css-Image-Embedder"
|
15
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Css_image_embedder", "--main", "README.md"]
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
s.rubyforge_project = "css_image_embedder"
|
18
|
+
s.rubygems_version = "1.8.24"
|
19
|
+
s.summary = "Css Image Embedder puts your background files directly into corresponding CSS file. Thanks to that - your server needs to handle fewer requests and the page layout renders smoothly (whole stylesheet at once)."
|
20
20
|
|
21
21
|
if s.respond_to? :specification_version then
|
22
22
|
s.specification_version = 3
|
@@ -24,15 +24,12 @@ Gem::Specification.new do |s|
|
|
24
24
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
25
25
|
s.add_runtime_dependency(%q<sass>, [">= 0"])
|
26
26
|
s.add_development_dependency(%q<rspec>, [">= 2.0.0"])
|
27
|
-
s.add_development_dependency(%q<rails>, [">= 0"])
|
28
27
|
else
|
29
28
|
s.add_dependency(%q<sass>, [">= 0"])
|
30
29
|
s.add_dependency(%q<rspec>, [">= 2.0.0"])
|
31
|
-
s.add_dependency(%q<rails>, [">= 0"])
|
32
30
|
end
|
33
31
|
else
|
34
32
|
s.add_dependency(%q<sass>, [">= 0"])
|
35
33
|
s.add_dependency(%q<rspec>, [">= 2.0.0"])
|
36
|
-
s.add_dependency(%q<rails>, [">= 0"])
|
37
34
|
end
|
38
35
|
end
|
data/lib/css_image_embedder.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
path = File.expand_path(File.dirname(__FILE__))
|
2
2
|
|
3
|
-
require "#{path}/css_image_embedder/
|
4
|
-
require "#{path}/css_image_embedder/helper"
|
3
|
+
require "#{path}/css_image_embedder/image"
|
5
4
|
require "#{path}/css_image_embedder/engine"
|
6
|
-
require "#{path}/css_image_embedder/converter"
|
7
5
|
require "#{path}/css_image_embedder/compressor"
|
@@ -6,16 +6,18 @@ require 'sass'
|
|
6
6
|
module CssImageEmbedder
|
7
7
|
class Compressor
|
8
8
|
|
9
|
-
#
|
10
|
-
#
|
11
|
-
def initialize(
|
12
|
-
@
|
13
|
-
@img_max_size = img_max_size
|
9
|
+
# @param [Integer] max image size that will be embedded (in KB)
|
10
|
+
# @return [CssImageEmbedder::Compressor] compressor instance
|
11
|
+
def initialize(img_max_size = 32)
|
12
|
+
@engine = CssImageEmbedder::Engine.new(img_max_size)
|
14
13
|
end
|
15
14
|
|
15
|
+
# Compress given CSS/SCSS file and embed into it images
|
16
|
+
# @params [String] CSS/SCSS input
|
17
|
+
# @return [String] CSS file content with embedded images
|
16
18
|
def compress(string)
|
17
|
-
|
18
|
-
|
19
|
+
sass = Sass::Engine.new(string, syntax: :scss, style: :compressed)
|
20
|
+
@engine.compress(sass.render)
|
19
21
|
end
|
20
22
|
end
|
21
|
-
end
|
23
|
+
end
|
@@ -1,78 +1,48 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
# Css image embedder engine - used to embed images into CSS
|
1
|
+
# Css image embedder engine - used to embed images into CSS files
|
4
2
|
module CssImageEmbedder
|
5
3
|
class Engine
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
5
|
+
EXTRACT_REGEXP = /url\(.+?\)/i
|
6
|
+
|
7
|
+
# @param [String] root of imgs position - this needs to be an absolute
|
8
|
+
# path, so we need to join it with Rails.root if we use Rails
|
9
|
+
# @param [Integer] maximum file size (in kb) - bigger will not be embedded
|
10
|
+
# @return [CssImageEmbedder::Engine] instance
|
11
|
+
# @example
|
12
|
+
# CssImageEmbedder::Engine.new(ASSET_IMAGE_LIMIT)
|
13
|
+
# CssImageEmbedder::Engine.new
|
14
|
+
def initialize(img_max_size = 32)
|
15
|
+
@image_root = File.join(Rails.root, 'app')
|
16
|
+
@image_max_size = img_max_size*1024
|
12
17
|
end
|
13
18
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
next
|
26
|
-
end
|
19
|
+
# @param [String] content of a CSS file in which we want to embed pictures
|
20
|
+
# @return [String] content of a CSS file with embedded pictures
|
21
|
+
# @example
|
22
|
+
# engine.compress(@css_content)
|
23
|
+
def compress(css)
|
24
|
+
images(css).each do |image|
|
25
|
+
begin
|
26
|
+
next if File.size?(image.file_path) > @image_max_size
|
27
|
+
css.gsub!(image.css_url, "url(data:image/#{image.ext};base64,#{image.to_base64})")
|
28
|
+
rescue
|
29
|
+
next
|
27
30
|
end
|
28
|
-
@result = source
|
29
|
-
else
|
30
|
-
@result = string
|
31
31
|
end
|
32
|
+
css
|
32
33
|
end
|
33
34
|
|
34
|
-
# Convert to base64 without new lines
|
35
|
-
def self.file_to_base64(path)
|
36
|
-
str = File.open(path, 'r') { |file| file.read }
|
37
|
-
Base64.encode64(str).gsub("\n", '')
|
38
|
-
end
|
39
|
-
|
40
|
-
|
41
35
|
private
|
42
|
-
|
43
|
-
# Pulls out files paths from url(smthng)
|
44
|
-
# Returns an array containing:
|
45
|
-
# - original path (./images/smthng.png)
|
46
|
-
# - converted path (/images/smthng.png)
|
47
|
-
# - original url (url(./images/smthng.png))
|
48
|
-
def pull(css)
|
49
|
-
# Whole urls including stuff around (url('/images/smthng.png') )
|
50
|
-
whole_urls = css.scan(/url\(.+?\)/i)
|
51
|
-
return nil if whole_urls.count == 0
|
52
36
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
img = "/#{img}" if img[0] != '/'
|
62
|
-
img
|
63
|
-
end
|
64
|
-
|
65
|
-
result = []
|
66
|
-
img_bg_paths.each_with_index do |el, i|
|
67
|
-
result <<
|
68
|
-
{:original_path =>img_bg_paths_original[i],
|
69
|
-
:converted_path => el,
|
70
|
-
:original_url => whole_urls[i]
|
71
|
-
}
|
72
|
-
end
|
73
|
-
result.uniq!
|
74
|
-
result
|
37
|
+
# Extracts all the images paths from input CSS string. It extracts
|
38
|
+
# CSS urls with a regular expression
|
39
|
+
#
|
40
|
+
# @param [String] CSS input content (css file content)
|
41
|
+
# @return [Array<CssImageEmbedder::Image>] returns all the images that
|
42
|
+
# were used in given css file.
|
43
|
+
def images(css)
|
44
|
+
css.scan(EXTRACT_REGEXP).collect { |img| Image.new(img, @image_root) }
|
75
45
|
end
|
76
46
|
|
77
47
|
end
|
78
|
-
end
|
48
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
3
|
+
# Image model that represents single image that we want to embed
|
4
|
+
module CssImageEmbedder
|
5
|
+
class Image
|
6
|
+
|
7
|
+
# Regular expression used to extract only the url itself
|
8
|
+
URL_REGEXP = /url\(\s*["']?([^"']+)["']?\s*\)/i
|
9
|
+
|
10
|
+
# @param [String] original css url ("url('./something/etc')")
|
11
|
+
# @param [String] file root
|
12
|
+
# @return [CssImageEmbedder::Image] image instance
|
13
|
+
def initialize(css_url, root)
|
14
|
+
@css_url = css_url
|
15
|
+
@root = root
|
16
|
+
@url = css_url.scan(URL_REGEXP)[0][0]
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [String] original CSS url string
|
20
|
+
def css_url
|
21
|
+
@css_url
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [String] pure url (without CSS stuff)
|
25
|
+
# @example
|
26
|
+
# image.url #=> './something/picture.png'
|
27
|
+
def url
|
28
|
+
@url
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [String] absolute path to a given picture
|
32
|
+
# @example
|
33
|
+
# image.file_path #=> '/var/www/app/assets/images/picture.jpg'
|
34
|
+
def file_path
|
35
|
+
path = url.gsub('./', '/')
|
36
|
+
path = "/#{path}" if path[0] != '/'
|
37
|
+
File.join(@root, path.gsub('assets/', 'assets/images/'))
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [String] downcased file extension
|
41
|
+
# @example
|
42
|
+
# image.ext #=> 'jpg'
|
43
|
+
def ext
|
44
|
+
splitted = file_path.split('.')
|
45
|
+
splitted.length > 1 ? splitted.last.downcase : ''
|
46
|
+
end
|
47
|
+
|
48
|
+
# @return [String] bse64 converted picture
|
49
|
+
# @example
|
50
|
+
# image.to_base64 #=> base64 content
|
51
|
+
def to_base64
|
52
|
+
str = File.open(file_path, 'r') { |file| file.read }
|
53
|
+
Base64.encode64(str).gsub("\n", '')
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CssImageEmbedder::Compressor do
|
4
|
+
|
5
|
+
subject { CssImageEmbedder::Compressor.new }
|
6
|
+
|
7
|
+
context "when we have a CSS file withount anything special" do
|
8
|
+
context "and it is in multiply lines" do
|
9
|
+
it "should compress it" do
|
10
|
+
css = '
|
11
|
+
#test { background: #ffffff; }
|
12
|
+
#test2 { background: #000000; }
|
13
|
+
'
|
14
|
+
subject.compress(css).should == "#test{background:#ffffff}#test2{background:#000000}\n"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when we have CSS file without any strange stuff" do
|
20
|
+
it "should convert std css file and embed pictures into it" do
|
21
|
+
sass = Sass::Engine.new(css_content("std_converted"), syntax: :scss, style: :compressed)
|
22
|
+
subject.compress(css_content("std")).should == sass.render
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
data/spec/engine_spec.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CssImageEmbedder::Engine do
|
4
|
+
|
5
|
+
subject { CssImageEmbedder::Engine.new }
|
6
|
+
|
7
|
+
context "when we have CSS file without any strange stuff" do
|
8
|
+
it "should convert std css file and embed pictures into it" do
|
9
|
+
subject.compress(css_content('std')).should === css_content("std_converted")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context "when we provide too big background" do
|
14
|
+
it "should not embed it by default" do
|
15
|
+
subject.compress(css_content('too_big')).should === css_content("too_big")
|
16
|
+
end
|
17
|
+
|
18
|
+
context "but when limit is bigger" do
|
19
|
+
subject { CssImageEmbedder::Engine.new(100*1024) }
|
20
|
+
|
21
|
+
it "should embed it" do
|
22
|
+
subject.compress(css_content('too_big')).should === css_content("big_converted")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when we provide css file where paths don't point to valid files" do
|
28
|
+
it "should leave original css file structure" do
|
29
|
+
subject.compress(css_content('file_sources_invalid')).should === css_content("file_sources_invalid")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
data/spec/image_spec.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CssImageEmbedder::Image do
|
4
|
+
|
5
|
+
let(:url){ '/assets/dir/bg.png' }
|
6
|
+
let(:css_url){ "url('#{url}')" }
|
7
|
+
|
8
|
+
subject { CssImageEmbedder::Image.new(css_url, Rails.root) }
|
9
|
+
|
10
|
+
describe '#css_url' do
|
11
|
+
it 'should be the same as base css url' do
|
12
|
+
subject.css_url.should == css_url
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#url' do
|
17
|
+
it 'should extract only the url' do
|
18
|
+
subject.url.should == url
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#ext' do
|
23
|
+
context 'when there is an extension' do
|
24
|
+
it 'should return it' do
|
25
|
+
subject.ext.should == 'png'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'when there is no extension' do
|
30
|
+
before { subject.instance_variable_set('@url', '') }
|
31
|
+
|
32
|
+
it 'should return empty string' do
|
33
|
+
subject.ext.should == ''
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#file_path' do
|
39
|
+
context 'when this is an http absolute path' do
|
40
|
+
it 'should return valid file path' do
|
41
|
+
subject.file_path.should == "#{Rails.root}/assets/images/dir/bg.png"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'when this is an http local path' do
|
46
|
+
before { subject.instance_variable_set('@url', ".#{subject.url}") }
|
47
|
+
|
48
|
+
it 'should return valid file path' do
|
49
|
+
subject.file_path.should == "#{Rails.root}/assets/images/dir/bg.png"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,8 +2,34 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
2
2
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
3
|
|
4
4
|
require 'rubygems'
|
5
|
-
require 'rails'
|
6
5
|
require 'fileutils'
|
7
6
|
require 'action_view'
|
8
7
|
|
8
|
+
class Rails
|
9
|
+
def self.root
|
10
|
+
File.expand_path(File.dirname(__FILE__))
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.app
|
14
|
+
File.join(root, 'app')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def file_content(f)
|
19
|
+
file = File.new("#{f}", "r")
|
20
|
+
content = ''
|
21
|
+
while (line = file.gets)
|
22
|
+
content+=line
|
23
|
+
end
|
24
|
+
content
|
25
|
+
end
|
26
|
+
|
27
|
+
def css_content(name)
|
28
|
+
file_content("#{Rails.app}/assets/stylesheets/#{name}.css")
|
29
|
+
end
|
30
|
+
|
31
|
+
def files_equal?(f1, f2)
|
32
|
+
file_content(f1) == file_content(f2)
|
33
|
+
end
|
34
|
+
|
9
35
|
require 'css_image_embedder'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: css_image_embedder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-05-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sass
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,15 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: rspec
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ! '>='
|
@@ -32,18 +37,12 @@ dependencies:
|
|
32
37
|
version: 2.0.0
|
33
38
|
type: :development
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
36
|
-
- !ruby/object:Gem::Dependency
|
37
|
-
name: rails
|
38
|
-
requirement: &23529740 !ruby/object:Gem::Requirement
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
41
|
none: false
|
40
42
|
requirements:
|
41
43
|
- - ! '>='
|
42
44
|
- !ruby/object:Gem::Version
|
43
|
-
version:
|
44
|
-
type: :development
|
45
|
-
prerelease: false
|
46
|
-
version_requirements: *23529740
|
45
|
+
version: 2.0.0
|
47
46
|
description: Css Image Embedder puts your background files directly into corresponding
|
48
47
|
CSS file. Thanks to that - your server needs to handle fewer requests and the page
|
49
48
|
layout renders smoothly (whole stylesheet at once).
|
@@ -55,37 +54,35 @@ extra_rdoc_files:
|
|
55
54
|
- README.md
|
56
55
|
- lib/css_image_embedder.rb
|
57
56
|
- lib/css_image_embedder/compressor.rb
|
58
|
-
- lib/css_image_embedder/converter.rb
|
59
57
|
- lib/css_image_embedder/engine.rb
|
60
|
-
- lib/css_image_embedder/
|
61
|
-
- lib/css_image_embedder/helper.rb
|
58
|
+
- lib/css_image_embedder/image.rb
|
62
59
|
files:
|
63
60
|
- CHANGELOG.rdoc
|
64
61
|
- Gemfile
|
65
62
|
- LICENCE
|
66
63
|
- README.md
|
67
64
|
- Rakefile
|
68
|
-
- css_image_embedder.gemspec
|
69
65
|
- init.rb
|
70
66
|
- lib/css_image_embedder.rb
|
71
67
|
- lib/css_image_embedder/compressor.rb
|
72
|
-
- lib/css_image_embedder/converter.rb
|
73
68
|
- lib/css_image_embedder/engine.rb
|
74
|
-
- lib/css_image_embedder/
|
75
|
-
-
|
76
|
-
- spec/
|
77
|
-
- spec/
|
78
|
-
- spec/
|
79
|
-
- spec/
|
80
|
-
- spec/
|
81
|
-
- spec/
|
82
|
-
- spec/
|
83
|
-
- spec/
|
84
|
-
- spec/
|
85
|
-
- spec/
|
86
|
-
- spec/
|
69
|
+
- lib/css_image_embedder/image.rb
|
70
|
+
- spec/app/assets/images/bg.png
|
71
|
+
- spec/app/assets/images/bg_base64.png
|
72
|
+
- spec/app/assets/images/too_big.jpg
|
73
|
+
- spec/app/assets/stylesheets/big_converted.css
|
74
|
+
- spec/app/assets/stylesheets/file_sources_invalid.css
|
75
|
+
- spec/app/assets/stylesheets/oneliner.css
|
76
|
+
- spec/app/assets/stylesheets/oneliner_converted.css
|
77
|
+
- spec/app/assets/stylesheets/std.css
|
78
|
+
- spec/app/assets/stylesheets/std_converted.css
|
79
|
+
- spec/app/assets/stylesheets/too_big.css
|
80
|
+
- spec/compressor_spec.rb
|
81
|
+
- spec/engine_spec.rb
|
82
|
+
- spec/image_spec.rb
|
87
83
|
- spec/spec_helper.rb
|
88
84
|
- Manifest
|
85
|
+
- css_image_embedder.gemspec
|
89
86
|
homepage: https://github.com/mensfeld/Css-Image-Embedder
|
90
87
|
licenses: []
|
91
88
|
post_install_message:
|
@@ -112,7 +109,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
112
109
|
version: '1.2'
|
113
110
|
requirements: []
|
114
111
|
rubyforge_project: css_image_embedder
|
115
|
-
rubygems_version: 1.8.
|
112
|
+
rubygems_version: 1.8.24
|
116
113
|
signing_key:
|
117
114
|
specification_version: 3
|
118
115
|
summary: Css Image Embedder puts your background files directly into corresponding
|
@@ -1,65 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
# Converts CSS files - it will embed any img file attached as background
|
4
|
-
# background: url(...)... --> (base64) --> url(data:image/png;base64,...)
|
5
|
-
# By default will embed only images smaller then 32kb
|
6
|
-
|
7
|
-
module CssImageEmbedder
|
8
|
-
|
9
|
-
class Converter
|
10
|
-
# IE does not accept embed files bigger then 32kb
|
11
|
-
DEFAULT_MAX_IMG_SIZE = 32
|
12
|
-
|
13
|
-
attr_reader :result
|
14
|
-
|
15
|
-
def initialize(*sources)
|
16
|
-
options = sources.extract_options!.stringify_keys
|
17
|
-
source = options.delete("source")
|
18
|
-
@file_path = options.delete("path")
|
19
|
-
@root_path = options.delete("root")
|
20
|
-
@overwrite = options.delete("overwrite") || false
|
21
|
-
@result = nil
|
22
|
-
|
23
|
-
@img_max_size = options.delete("img_max_size") || DEFAULT_MAX_IMG_SIZE
|
24
|
-
|
25
|
-
if @file_path
|
26
|
-
raise CssNotFound unless File.exists?(@file_path)
|
27
|
-
@source = File.open(@file_path, 'r') { |file| file.read }
|
28
|
-
else
|
29
|
-
raise CssStringNotProvided unless source
|
30
|
-
@source = source
|
31
|
-
@overwrite = false
|
32
|
-
end
|
33
|
-
|
34
|
-
raise RootPathNotProvided unless @root_path
|
35
|
-
end
|
36
|
-
|
37
|
-
# Performe converting
|
38
|
-
def convert
|
39
|
-
@result = CssImageEmbedder::Engine.new(@root_path, @img_max_size).compress(@source)
|
40
|
-
end
|
41
|
-
|
42
|
-
# Saves converted result to file
|
43
|
-
def save(filename = nil)
|
44
|
-
if @file_path && @overwrite && filename.nil?
|
45
|
-
p = @file_path
|
46
|
-
else
|
47
|
-
p = filename
|
48
|
-
end
|
49
|
-
f = File.new(p, "w")
|
50
|
-
f.write(@result)
|
51
|
-
f.close
|
52
|
-
end
|
53
|
-
|
54
|
-
# Force overwrite
|
55
|
-
def save!(filename = nil)
|
56
|
-
@overwrite = true
|
57
|
-
save(filename)
|
58
|
-
end
|
59
|
-
|
60
|
-
def self.file_to_base64(file)
|
61
|
-
CssImageEmbedder::Engine.file_to_base64(file)
|
62
|
-
end
|
63
|
-
|
64
|
-
end
|
65
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
# Helper methods for ActionView::Base in Rails
|
2
|
-
module CssImageEmbedder
|
3
|
-
|
4
|
-
module Helper
|
5
|
-
|
6
|
-
if Rails.version.to_s.include?('3.0')
|
7
|
-
# Basicly it's just stylesheet_link_tag with one small difference ;)
|
8
|
-
# Will not test it - Rails guys already did it
|
9
|
-
def image_embed_stylesheet_link_tag(*sources)
|
10
|
-
options = sources.extract_options!.stringify_keys
|
11
|
-
concat = options.delete("concat")
|
12
|
-
cache = concat || options.delete("cache")
|
13
|
-
recursive = options.delete("recursive")
|
14
|
-
root = options.delete("root") || File.join(Rails.root, 'public')
|
15
|
-
env = options.delete("env") || Rails.env
|
16
|
-
|
17
|
-
if concat || (config.perform_caching && cache)
|
18
|
-
joined_stylesheet_name = (cache == true ? "all" : cache) + ".css"
|
19
|
-
joined_stylesheet_path = File.join(joined_stylesheet_name[/^#{File::SEPARATOR}/] ? config.assets_dir : config.stylesheets_dir, joined_stylesheet_name)
|
20
|
-
|
21
|
-
unless config.perform_caching && File.exists?(joined_stylesheet_path)
|
22
|
-
write_asset_file_contents(joined_stylesheet_path, compute_stylesheet_paths(sources, recursive))
|
23
|
-
# here's the magic ;)
|
24
|
-
css = CssImageEmbedder::Converter.new(
|
25
|
-
:path => joined_stylesheet_path,
|
26
|
-
:overwrite => true,
|
27
|
-
:root => root)
|
28
|
-
css.convert
|
29
|
-
css.save!
|
30
|
-
end
|
31
|
-
stylesheet_tag(joined_stylesheet_name, options)
|
32
|
-
else
|
33
|
-
sources = expand_stylesheet_sources(sources, recursive)
|
34
|
-
# When we use SASS and test env - will not work - and will raise
|
35
|
-
# exception - that css files does not exist. We make a workaround
|
36
|
-
# by not checking sources in test env
|
37
|
-
ensure_stylesheet_sources!(sources) if cache && env != 'test'
|
38
|
-
sources.collect { |source| stylesheet_tag(source, options) }.join("\n").html_safe
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end # Helper
|
43
|
-
|
44
|
-
end # Base64CssEmbedder
|
45
|
-
|
46
|
-
ActionView::Base.send :include, CssImageEmbedder::Helper
|
@@ -1,168 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
ROOT = File.expand_path(File.dirname(__FILE__))
|
4
|
-
FILES_ROOT = File.join(ROOT, 'files')
|
5
|
-
|
6
|
-
def file_content(f)
|
7
|
-
file = File.new("#{f}", "r")
|
8
|
-
content = ''
|
9
|
-
while (line = file.gets)
|
10
|
-
content+=line
|
11
|
-
end
|
12
|
-
content
|
13
|
-
end
|
14
|
-
|
15
|
-
def files_equal?(f1, f2)
|
16
|
-
file_content(f1) == file_content(f2)
|
17
|
-
end
|
18
|
-
|
19
|
-
describe CssImageEmbedder::Converter do
|
20
|
-
|
21
|
-
subject { CssImageEmbedder::Converter }
|
22
|
-
|
23
|
-
# Should clear all css files created in test
|
24
|
-
after(:all) do
|
25
|
-
FileUtils.rm("#{ROOT}/std.css")
|
26
|
-
end
|
27
|
-
|
28
|
-
context "when we have CSS file without any strange stuff" do
|
29
|
-
it "should convert std css file and embed pictures into it" do
|
30
|
-
converter = subject.new(
|
31
|
-
:path => "#{FILES_ROOT}/std.css",
|
32
|
-
:overwrite => true,
|
33
|
-
:root => ROOT
|
34
|
-
)
|
35
|
-
converter.convert
|
36
|
-
converter.result.should === file_content("#{FILES_ROOT}/std_converted.css")
|
37
|
-
end
|
38
|
-
|
39
|
-
context "and allow to overwrite" do
|
40
|
-
it "should embed backgrounds and overwrite source file" do
|
41
|
-
# Copy std.css to check if it will be overwritten
|
42
|
-
FileUtils.cp("#{FILES_ROOT}/std.css", "#{ROOT}/std.css")
|
43
|
-
converter = subject.new(
|
44
|
-
:path => "#{ROOT}/std.css",
|
45
|
-
:overwrite => true,
|
46
|
-
:root => ROOT
|
47
|
-
)
|
48
|
-
converter.convert
|
49
|
-
converter.save
|
50
|
-
converter.result.should == file_content("#{ROOT}/std.css")
|
51
|
-
converter.result.should == file_content("#{FILES_ROOT}/std_converted.css")
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
56
|
-
|
57
|
-
context "when we provide too big background" do
|
58
|
-
it "should not embed it by default" do
|
59
|
-
converter = subject.new(
|
60
|
-
:path => "#{FILES_ROOT}/too_big.css",
|
61
|
-
:overwrite => true,
|
62
|
-
:root => ROOT
|
63
|
-
)
|
64
|
-
converter.convert
|
65
|
-
converter.result.should === file_content("#{FILES_ROOT}/too_big.css")
|
66
|
-
end
|
67
|
-
|
68
|
-
context "but limit is bigger" do
|
69
|
-
it "should embed it" do
|
70
|
-
converter = subject.new(
|
71
|
-
:path => "#{FILES_ROOT}/too_big.css",
|
72
|
-
:overwrite => true,
|
73
|
-
:root => ROOT,
|
74
|
-
:img_max_size => 100*1024
|
75
|
-
)
|
76
|
-
converter.convert
|
77
|
-
converter.result.should === file_content("#{FILES_ROOT}/big_converted.css")
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
context "when we provide css file where paths don't point to valid files" do
|
83
|
-
it "should leave original css file structure" do
|
84
|
-
converter = subject.new(
|
85
|
-
:path => "#{FILES_ROOT}/file_sources_invalid.css",
|
86
|
-
:root => ROOT
|
87
|
-
)
|
88
|
-
converter.convert
|
89
|
-
converter.result.should == file_content("#{FILES_ROOT}/file_sources_invalid.css")
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
context "when we don't provide root path" do
|
94
|
-
it "should raise RootPathNotProvided" do
|
95
|
-
lambda {
|
96
|
-
subject.new(
|
97
|
-
:path => "#{FILES_ROOT}/std_converted.css"
|
98
|
-
)
|
99
|
-
}.should raise_exception(RootPathNotProvided)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
context "when we provide invalid source css file" do
|
104
|
-
it "should raise Exceptions::CssNotFound" do
|
105
|
-
lambda {
|
106
|
-
subject.new(
|
107
|
-
:path => "#{FILES_ROOT}no_file.css"
|
108
|
-
)
|
109
|
-
}.should raise_exception(CssNotFound)
|
110
|
-
end
|
111
|
-
|
112
|
-
context "but we provide string containing css" do
|
113
|
-
it "should convert it from string" do
|
114
|
-
converter = subject.new(
|
115
|
-
:source => file_content("#{FILES_ROOT}/std.css"),
|
116
|
-
:root => ROOT
|
117
|
-
)
|
118
|
-
converter.convert
|
119
|
-
converter.result.should == file_content("#{FILES_ROOT}/std_converted.css")
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
context "when we try to convert file to base64" do
|
124
|
-
it "should convert it" do
|
125
|
-
subject.file_to_base64("#{FILES_ROOT}/bg.png").should == file_content("#{FILES_ROOT}/bg_base64.png").gsub("\n", '')
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
context "when we provide huge one liner" do
|
130
|
-
it "should convert it without hesitation" do
|
131
|
-
converter = subject.new(
|
132
|
-
:path => "#{FILES_ROOT}/oneliner.css",
|
133
|
-
:root => ROOT
|
134
|
-
)
|
135
|
-
converter.convert
|
136
|
-
converter.result.should == file_content("#{FILES_ROOT}/oneliner_converted.css")
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
end
|
142
|
-
|
143
|
-
describe CssImageEmbedder::Compressor do
|
144
|
-
|
145
|
-
subject { CssImageEmbedder::Compressor }
|
146
|
-
|
147
|
-
context "when we have a CSS file withount anything special" do
|
148
|
-
context "and it is in multiply lines" do
|
149
|
-
it "should compress it" do
|
150
|
-
s = subject.new(ROOT)
|
151
|
-
css = '
|
152
|
-
#test { background: #ffffff; }
|
153
|
-
#test2 { background: #000000; }
|
154
|
-
'
|
155
|
-
s.compress(css).should == "#test{background:#ffffff}#test2{background:#000000}\n"
|
156
|
-
end
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
context "when we have CSS file without any strange stuff" do
|
161
|
-
it "should convert std css file and embed pictures into it" do
|
162
|
-
s = subject.new(ROOT)
|
163
|
-
sass = Sass::Engine.new(file_content("#{FILES_ROOT}/std_converted.css"), :syntax => :scss, :style => :compressed)
|
164
|
-
s.compress(file_content("#{FILES_ROOT}/std.css")).should=== sass.render
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
end
|
data/spec/files/std.css
DELETED
data/spec/files/too_big.css
DELETED