assets_packager 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. data/.gitignore +5 -0
  2. data/Gemfile +3 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +77 -0
  5. data/Rakefile +14 -0
  6. data/assets_packager.gemspec +34 -0
  7. data/bin/jsmin +205 -0
  8. data/lib/assets_packager.rb +30 -0
  9. data/lib/assets_packager/cleaner.rb +26 -0
  10. data/lib/assets_packager/compressors.rb +9 -0
  11. data/lib/assets_packager/compressors/base.rb +21 -0
  12. data/lib/assets_packager/compressors/javascript.rb +25 -0
  13. data/lib/assets_packager/compressors/stylesheet.rb +27 -0
  14. data/lib/assets_packager/configuration.rb +63 -0
  15. data/lib/assets_packager/mergers.rb +9 -0
  16. data/lib/assets_packager/mergers/base.rb +35 -0
  17. data/lib/assets_packager/mergers/javascript.rb +15 -0
  18. data/lib/assets_packager/mergers/stylesheet.rb +15 -0
  19. data/lib/assets_packager/tasks.rb +84 -0
  20. data/lib/assets_packager/version.rb +5 -0
  21. data/lib/tasks/assets_packager.rake +1 -0
  22. data/spec/assets_packager/compressors/javascript_spec.rb +14 -0
  23. data/spec/assets_packager/compressors/stylesheet_spec.rb +14 -0
  24. data/spec/assets_packager/configuration_spec.rb +12 -0
  25. data/spec/assets_packager/mergers/javascript_spec.rb +12 -0
  26. data/spec/assets_packager/mergers/stylesheet_spec.rb +12 -0
  27. data/spec/fixtures/public/javascripts/application.js +11 -0
  28. data/spec/fixtures/public/javascripts/jquery.js +8316 -0
  29. data/spec/fixtures/public/stylesheets/application.css +17 -0
  30. data/spec/fixtures/public/stylesheets/reset.css +102 -0
  31. data/spec/spec_helper.rb +31 -0
  32. data/spec/support/matchers/change_file_lines.rb +24 -0
  33. metadata +124 -0
@@ -0,0 +1,5 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ Gemfile.lock
5
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Luca Guidi
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,77 @@
1
+ # Assets Packager
2
+ ## A bundler for your javascripts and stylesheets.
3
+
4
+ When you deploy your application it could be convenient to package all your
5
+ stylesheets and javascripts in a single file, let say all.css and all.js, in
6
+ order to decrease the HTTP requests against your server.
7
+
8
+ You may also find useful to reduce the size of those files, through a process
9
+ which eliminates all unneeded white spaces and comments.
10
+
11
+ `Assets Packager` helps you to solve these problems.
12
+
13
+ ## Installation
14
+
15
+ # Gemfile
16
+ gem 'assets_packager'
17
+
18
+ # lib/tasks/assets.rake
19
+ require 'assets_packager/tasks'
20
+
21
+ # shell
22
+ $ rake assets:install
23
+
24
+ If you are in a `Rails` context, you don't need to setup anything else,
25
+ otherwise you can specify your paths:
26
+
27
+ AssetsPackager.configure do |config|
28
+ config.root_path = '/path/to/public/folder'
29
+ config.file_path = '/path/to/assets.yml'
30
+ end
31
+
32
+ ## Assets configuration
33
+ Once you use new assets to your application, just add the to the configuration
34
+ file (look at `config/assets.yml`):
35
+
36
+ ---
37
+ css:
38
+ - application
39
+ - jquery-ui
40
+ js:
41
+ - jquery
42
+ - jquery-ui
43
+ - application
44
+
45
+ Make sure to include library first, you may want to add `jquery.js` before of
46
+ `application.js`.
47
+
48
+ ## Usage
49
+ `Assets Packager` has a lot of useful `Rake` tasks (`rake -T assets`), the most
50
+ important is `assets:package`: it merge and compress all your javascripts and
51
+ stylesheets. Use it as `Capistrano` post deploy hook.
52
+
53
+ If you're using `Rails`, in order to take advantage of bundled assets,
54
+ you should use `:cache => true` option:
55
+
56
+ <%= javascript_include_tag 'jquery', 'jquery-ui', 'application', :cache => true %>
57
+ <%= stylesheet_link_tag 'application', 'jquery-ui', :cache => true %>
58
+
59
+ There are some contexts where you can't bundle assets at deploy time (like `Heroku`),
60
+ what you can do is to reference directly to `all.js` or `all.css`:
61
+
62
+ <%= javascript_include_tag 'all' %>
63
+ <%= stylesheet_link_tag 'all' %>
64
+
65
+ In this way you have to bundle assets on your development machine and put them under
66
+ version control.
67
+
68
+ ## Credits
69
+ `Assets Packager` was strongly inspired by the homonym plugin written by
70
+ [Scott Becker](http://synthesis.sbecker.net/).
71
+
72
+ Uladzislau Latynski for his jsmin.rb Ruby porting.
73
+
74
+ Thanks to [Steve Souders](http://stevesouders.com/) for his [High Performance
75
+ Web Sites](http://oreilly.com/catalog/9780596529307) book.
76
+
77
+ Copyright 2011 Luca Guidi - [www.lucaguidi.com](www.lucaguidi.com) - Released under MIT License
@@ -0,0 +1,14 @@
1
+ require 'bundler'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/rdoctask'
5
+ require 'rspec/core/rake_task'
6
+
7
+ task :default => :spec
8
+
9
+ Bundler::GemHelper.install_tasks
10
+
11
+ RSpec::Core::RakeTask.new do |spec|
12
+ spec.pattern = 'spec/**/*_spec.rb'
13
+ spec.rspec_opts = ['-fs --color --backtrace']
14
+ end
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "assets_packager/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "assets_packager"
7
+ s.version = AssetsPackager::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Luca Guidi"]
10
+ s.email = ["guidi.luca@gmail.com"]
11
+ s.homepage = "http://github.com/jodosha/assets_packager"
12
+ s.summary = %q{A packager for your assets}
13
+ s.description = %q{Compress and merge your JavaScript and CSS files}
14
+
15
+ s.rubyforge_project = "assets_packager"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.specification_version = 3
25
+
26
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
27
+ s.add_development_dependency(%q<rspec>, ["~> 2.5.0"])
28
+ else
29
+ s.add_dependency(%q<rspec>, ["~> 2.5.0"])
30
+ end
31
+ else
32
+ s.add_dependency(%q<rspec>, ["~> 2.5.0"])
33
+ end
34
+ end
@@ -0,0 +1,205 @@
1
+ #!/usr/bin/env ruby
2
+ # jsmin.rb 2007-07-20
3
+ # Author: Uladzislau Latynski
4
+ # This work is a translation from C to Ruby of jsmin.c published by
5
+ # Douglas Crockford. Permission is hereby granted to use the Ruby
6
+ # version under the same conditions as the jsmin.c on which it is
7
+ # based.
8
+ #
9
+ # /* jsmin.c
10
+ # 2003-04-21
11
+ #
12
+ # Copyright (c) 2002 Douglas Crockford (www.crockford.com)
13
+ #
14
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
15
+ # this software and associated documentation files (the "Software"), to deal in
16
+ # the Software without restriction, including without limitation the rights to
17
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
18
+ # of the Software, and to permit persons to whom the Software is furnished to do
19
+ # so, subject to the following conditions:
20
+ #
21
+ # The above copyright notice and this permission notice shall be included in all
22
+ # copies or substantial portions of the Software.
23
+ #
24
+ # The Software shall be used for Good, not Evil.
25
+ #
26
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32
+ # SOFTWARE.
33
+
34
+ EOF = -1
35
+ $theA = ""
36
+ $theB = ""
37
+
38
+ # isAlphanum -- return true if the character is a letter, digit, underscore,
39
+ # dollar sign, or non-ASCII character
40
+ def isAlphanum(c)
41
+ return false if !c || c == EOF
42
+ return ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
43
+ (c >= 'A' && c <= 'Z') || c == '_' || c == '$' ||
44
+ c == '\\' || c[0] > 126)
45
+ end
46
+
47
+ # get -- return the next character from stdin. Watch out for lookahead. If
48
+ # the character is a control character, translate it to a space or linefeed.
49
+ def get()
50
+ c = $stdin.getc
51
+ return EOF if(!c)
52
+ c = c.chr
53
+ return c if (c >= " " || c == "\n" || c.unpack("c") == EOF)
54
+ return "\n" if (c == "\r")
55
+ return " "
56
+ end
57
+
58
+ # Get the next character without getting it.
59
+ def peek()
60
+ lookaheadChar = $stdin.getc
61
+ $stdin.ungetc(lookaheadChar)
62
+ return lookaheadChar.chr
63
+ end
64
+
65
+ # mynext -- get the next character, excluding comments.
66
+ # peek() is used to see if a '/' is followed by a '/' or '*'.
67
+ def mynext()
68
+ c = get
69
+ if (c == "/")
70
+ if(peek == "/")
71
+ while(true)
72
+ c = get
73
+ if (c <= "\n")
74
+ return c
75
+ end
76
+ end
77
+ end
78
+ if(peek == "*")
79
+ get
80
+ while(true)
81
+ case get
82
+ when "*"
83
+ if (peek == "/")
84
+ get
85
+ return " "
86
+ end
87
+ when EOF
88
+ raise "Unterminated comment"
89
+ end
90
+ end
91
+ end
92
+ end
93
+ return c
94
+ end
95
+
96
+
97
+ # action -- do something! What you do is determined by the argument: 1
98
+ # Output A. Copy B to A. Get the next B. 2 Copy B to A. Get the next B.
99
+ # (Delete A). 3 Get the next B. (Delete B). action treats a string as a
100
+ # single character. Wow! action recognizes a regular expression if it is
101
+ # preceded by ( or , or =.
102
+ def action(a)
103
+ if(a==1)
104
+ $stdout.write $theA
105
+ end
106
+ if(a==1 || a==2)
107
+ $theA = $theB
108
+ if ($theA == "\'" || $theA == "\"")
109
+ while (true)
110
+ $stdout.write $theA
111
+ $theA = get
112
+ break if ($theA == $theB)
113
+ raise "Unterminated string literal" if ($theA <= "\n")
114
+ if ($theA == "\\")
115
+ $stdout.write $theA
116
+ $theA = get
117
+ end
118
+ end
119
+ end
120
+ end
121
+ if(a==1 || a==2 || a==3)
122
+ $theB = mynext
123
+ if ($theB == "/" && ($theA == "(" || $theA == "," || $theA == "=" ||
124
+ $theA == ":" || $theA == "[" || $theA == "!" ||
125
+ $theA == "&" || $theA == "|" || $theA == "?" ||
126
+ $theA == "{" || $theA == "}" || $theA == ";" ||
127
+ $theA == "\n"))
128
+ $stdout.write $theA
129
+ $stdout.write $theB
130
+ while (true)
131
+ $theA = get
132
+ if ($theA == "/")
133
+ break
134
+ elsif ($theA == "\\")
135
+ $stdout.write $theA
136
+ $theA = get
137
+ elsif ($theA <= "\n")
138
+ raise "Unterminated RegExp Literal"
139
+ end
140
+ $stdout.write $theA
141
+ end
142
+ $theB = mynext
143
+ end
144
+ end
145
+ end
146
+
147
+ # jsmin -- Copy the input to the output, deleting the characters which are
148
+ # insignificant to JavaScript. Comments will be removed. Tabs will be
149
+ # replaced with spaces. Carriage returns will be replaced with linefeeds.
150
+ # Most spaces and linefeeds will be removed.
151
+ def jsmin
152
+ $theA = "\n"
153
+ action(3)
154
+ while ($theA != EOF)
155
+ case $theA
156
+ when " "
157
+ if (isAlphanum($theB))
158
+ action(1)
159
+ else
160
+ action(2)
161
+ end
162
+ when "\n"
163
+ case ($theB)
164
+ when "{","[","(","+","-"
165
+ action(1)
166
+ when " "
167
+ action(3)
168
+ else
169
+ if (isAlphanum($theB))
170
+ action(1)
171
+ else
172
+ action(2)
173
+ end
174
+ end
175
+ else
176
+ case ($theB)
177
+ when " "
178
+ if (isAlphanum($theA))
179
+ action(1)
180
+ else
181
+ action(3)
182
+ end
183
+ when "\n"
184
+ case ($theA)
185
+ when "}","]",")","+","-","\"","\\", "'", '"'
186
+ action(1)
187
+ else
188
+ if (isAlphanum($theA))
189
+ action(1)
190
+ else
191
+ action(3)
192
+ end
193
+ end
194
+ else
195
+ action(1)
196
+ end
197
+ end
198
+ end
199
+ end
200
+
201
+ ARGV.each do |anArg|
202
+ $stdout.write "// #{anArg}\n"
203
+ end
204
+
205
+ jsmin
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module AssetsPackager
4
+ autoload :Configuration, 'assets_packager/configuration'
5
+ autoload :Cleaner, 'assets_packager/cleaner'
6
+ autoload :Mergers, 'assets_packager/mergers'
7
+ autoload :Compressors, 'assets_packager/compressors'
8
+
9
+ # Configure <tt>AssetsPackager</tt>.
10
+ #
11
+ # Example:
12
+ # AssetsPackager.configure do |config|
13
+ # config.root_path = '/path/to/public/folder'
14
+ # end
15
+ #
16
+ # Options:
17
+ # * <tt>root_path</tt>: Specify the directory where your javascript and stylesheet
18
+ # directories are. i.e. <tt>Rails.public_path</tt>. Default: <tt>Dir.pwd</tt>.
19
+ # * <tt>file_path</tt>: Specify the path of the <tt>YAML</tt> configuration file.
20
+ # Default: <tt>root_path + '/assets.yml'</tt>.
21
+ # * <tt>javascripts_path</tt>: Specify where your javascripts are placed.
22
+ # Default: <tt>root_path + '/javascripts'</tt>
23
+ # * <tt>stylesheets_path</tt>: Specify where your stylesheets are placed.
24
+ # Default: <tt>root_path + '/stylesheets'</tt>
25
+ #
26
+ # Notice: If you are in a <tt>Rails</tt> context, everything is already configured.
27
+ def self.configure
28
+ yield AssetsPackager::Configuration
29
+ end
30
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'fileutils'
3
+
4
+ module AssetsPackager
5
+ module Cleaner
6
+ extend self
7
+
8
+ def clear!
9
+ clear_configuration!
10
+ clear_javascripts!
11
+ clear_stylesheets!
12
+ end
13
+
14
+ def clear_configuration!
15
+ FileUtils.rm AssetsPackager::Configuration.file_path rescue nil
16
+ end
17
+
18
+ def clear_javascripts!
19
+ FileUtils.rm AssetsPackager::Mergers::Javascript.file rescue nil
20
+ end
21
+
22
+ def clear_stylesheets!
23
+ FileUtils.rm AssetsPackager::Mergers::Stylesheet.file rescue nil
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,9 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module AssetsPackager
4
+ module Compressors
5
+ autoload :Base, 'assets_packager/compressors/base'
6
+ autoload :Javascript, 'assets_packager/compressors/javascript'
7
+ autoload :Stylesheet, 'assets_packager/compressors/stylesheet'
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module AssetsPackager
4
+ module Compressors
5
+ class Base
6
+ def self.compress!
7
+ content = _compress_and_load!
8
+ ::File.open(file, 'w+') { |file| file.write content }
9
+ end
10
+
11
+ def self.file
12
+ raise "Not implemented"
13
+ end
14
+
15
+ private
16
+ def self._compress_and_load!
17
+ raise "Not implemented"
18
+ end
19
+ end
20
+ end
21
+ end