smurf 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ MIT License
2
+ --------------------------------------------------------------------------------
3
+ Copyright (c) 2008 Justin Knowlden
4
+
5
+ Permission is hereby granted, free of charge, to any person
6
+ obtaining a copy of this software and associated documentation
7
+ files (the "Software"), to deal in the Software without
8
+ restriction, including without limitation the rights to use,
9
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the
11
+ Software is furnished to do so, subject to the following
12
+ conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
+ OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,67 @@
1
+ # Smurf
2
+
3
+ Smurf is a Rails plugin that does Javascript and CSS minification the way you would expect. See, with Rails `2.x` we got this cool new `:cache` option on `javascript_include_tag` and `stylesheet_link_tag`, but no option for minifying the cached file(s).
4
+
5
+ Smurf ends that. Smurf - if installed and when caching is enabled for the environment - will nab the concatenated file content from Rails just before it saves it and minifies the content using either JSmin or a custom CSS compressor.
6
+
7
+ Some cool things about Smurf, which also allude to the reasons I wrote it:
8
+
9
+ * Smurf will only run when Rails needs to cache new files
10
+ * It will never run on its own
11
+ * It requires absolutely no configuration
12
+ * Other than installing it, you don't need to do anything
13
+ * It just gets out of your way
14
+
15
+ Smurf will work with any version of Rails `2.x`; including Rails `2.2.2`.
16
+
17
+ ### JSmin
18
+
19
+ It's really an adaptation of Uladzislau Latynski's [jsmin.rb](http://javascript.crockford.com/jsmin.rb) port of Douglas Crockford's [jsmin.c](http://javascript.crockford.com/jsmin.c) library.
20
+
21
+ ### Smurf CSS Compressor
22
+
23
+ The following are the rules I applied, gathered from various perusals around the Internet*s*
24
+
25
+ 1. Replace consecutive whitespace characters with a single space
26
+ 2. Remove whitespace around opening brackets
27
+ 3. Remove whitespace in front of closing brackets
28
+ 4. Remove the semi-colon just before the closing bracket
29
+ 5. Remove comments between `/* ... */` - this could be a problem (esp. for CSS hacks)
30
+ 6. Remove spaces around `;`, `:`, and `,` characters
31
+ 7. Ensure whitespace between closing brackets and periods
32
+
33
+ ## Installation
34
+
35
+ ./script/plugin install git://github.com/thumblemonks/smurf.git
36
+
37
+ Then, wherever you define `javascript_include_tag` or `stylesheet_link_tag`, make sure to add the standard `:cache => true` or `:cache => 'some_bundle'` options.
38
+
39
+ Also make sure to at least have this setting in your production.rb:
40
+
41
+ config.action_controller.perform_caching = true
42
+
43
+ ### Small suggestion
44
+
45
+ [bcarpenter](http://github.com/bcarpenter) reminded all of us that Rails will generate real files if you set `config.action_controller.perform_caching` to `true`. If you happen to do this while developing your fantastic Rails app you may also accidentally commit them to your development repository. This is not what you want as it can send you and your awesome developer friends down the wrong rabbit hole ... and then when you figure out the problem you may be understandably and misguidedly pissed at Smurf :)
46
+
47
+ [bcarpenter](http://github.com/bcarpenter) didn't seem too mad since he reached out to me (whew!) and suggested I add a little comment about making sure to ignore the generated cache files/directories in your SCM of choice. If you happen to be using git, be sure to do something to the effect of the following in your `.gitignore` file:
48
+
49
+ public/*/cache/*
50
+
51
+ ## Testing
52
+
53
+ If you want to test Smurf and you don't want to test with the latest version of Rails, then do something like the following (using 2.2.2 as an example):
54
+
55
+ rake RAILS_GEM_VERSION=2.2.2
56
+
57
+ This is the mechanism I used for testing that Smurf works for all versions:
58
+
59
+ rake && rake RAILS_GEM_VERSION=2.2.2
60
+
61
+ ## Meta
62
+
63
+ Author: Justin Knowlden <gus@thumblemonks.com>
64
+
65
+ Contributions from: Lance Ivy, Scott White, Daniel Schierbeck
66
+
67
+ See MIT-LICENSE for licensing information
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the load_model plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.pattern = 'test/**/*_test.rb'
12
+ t.verbose = true
13
+ end
14
+
15
+ desc 'Generate documentation for the smurf plugin.'
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'Smurf'
19
+ rdoc.options << '--line-numbers' << '--inline-source'
20
+ rdoc.rdoc_files.include('README')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'smurf'
data/install.rb ADDED
File without changes
data/lib/smurf.rb ADDED
@@ -0,0 +1,38 @@
1
+ require 'smurf/javascript'
2
+ require 'smurf/stylesheet'
3
+
4
+ if Rails.version =~ /^2\.2\./
5
+ # Support for Rails >= 2.2.x
6
+ module Smurf
7
+
8
+ module JavaScriptSources
9
+ private
10
+ def joined_contents; Smurf::Javascript.new(super).minified; end
11
+ end # JavaScriptSources
12
+
13
+ module StylesheetSources
14
+ private
15
+ def joined_contents; Smurf::Stylesheet.new(super).minified; end
16
+ end # StylesheetSources
17
+
18
+ end # ActionView::Helpers::AssetTagHelper::AssetTag
19
+ ActionView::Helpers::AssetTagHelper::JavaScriptSources.send(
20
+ :include, Smurf::JavaScriptSources)
21
+ ActionView::Helpers::AssetTagHelper::StylesheetSources.send(
22
+ :include, Smurf::StylesheetSources)
23
+ else
24
+ # Support for Rails <= 2.1.x
25
+ module ActionView::Helpers::AssetTagHelper
26
+ private
27
+ def join_asset_file_contents_with_minification(files)
28
+ content = join_asset_file_contents_without_minification(files)
29
+ if !files.grep(%r[/javascripts]).empty?
30
+ content = Smurf::Javascript.new(content).minified
31
+ elsif !files.grep(%r[/stylesheets]).empty?
32
+ content = Smurf::Stylesheet.new(content).minified
33
+ end
34
+ content
35
+ end
36
+ alias_method_chain :join_asset_file_contents, :minification
37
+ end # ActionView::Helpers::AssetTagHelper
38
+ end
@@ -0,0 +1,225 @@
1
+ # Author: Justin Knowlden
2
+ # Adaption of jsmin.rb published by Uladzislau Latynski
3
+ #
4
+ # -------------------
5
+ # jsmin.rb 2007-07-20
6
+ # Author: Uladzislau Latynski
7
+ # This work is a translation from C to Ruby of jsmin.c published by
8
+ # Douglas Crockford. Permission is hereby granted to use the Ruby
9
+ # version under the same conditions as the jsmin.c on which it is
10
+ # based.
11
+ #
12
+ # /* jsmin.c
13
+ # 2003-04-21
14
+ #
15
+ # Copyright (c) 2002 Douglas Crockford (www.crockford.com)
16
+ #
17
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
18
+ # this software and associated documentation files (the "Software"), to deal in
19
+ # the Software without restriction, including without limitation the rights to
20
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
21
+ # of the Software, and to permit persons to whom the Software is furnished to do
22
+ # so, subject to the following conditions:
23
+ #
24
+ # The above copyright notice and this permission notice shall be included in all
25
+ # copies or substantial portions of the Software.
26
+ #
27
+ # The Software shall be used for Good, not Evil.
28
+ #
29
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35
+ # SOFTWARE.
36
+
37
+ require 'stringio'
38
+
39
+ module Smurf
40
+ class Javascript
41
+ EOF = -1
42
+
43
+ @theA = ""
44
+ @theB = ""
45
+
46
+ def initialize(content)
47
+ @input = StringIO.new(content)
48
+ @output = StringIO.new
49
+ jsmin
50
+ end
51
+
52
+ def minified
53
+ @output.rewind
54
+ @output.read
55
+ end
56
+
57
+ # isAlphanum -- return true if the character is a letter, digit,
58
+ # underscore, # dollar sign, or non-ASCII character
59
+ def isAlphanum(c)
60
+ return false if !c || c == EOF
61
+ return ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
62
+ (c >= 'A' && c <= 'Z') || c == '_' || c == '$' ||
63
+ c == '\\' || Array(c[0].bytes).first > 126)
64
+ end
65
+
66
+ # get -- return the next character from stdin. Watch out for lookahead. If
67
+ # the character is a control character, translate it to a space or linefeed.
68
+ def get()
69
+ c = @input.getc
70
+ return EOF if(!c)
71
+ c = c.chr
72
+ return c if (c >= " " || c == "\n" || c.unpack("c") == EOF)
73
+ return "\n" if (c == "\r")
74
+ return " "
75
+ end
76
+
77
+ # Get the next character without getting it.
78
+ def peek()
79
+ lookaheadChar = @input.getc
80
+ @input.ungetc(lookaheadChar)
81
+ return lookaheadChar.chr
82
+ end
83
+
84
+ # mynext -- get the next character, excluding comments.
85
+ # peek() is used to see if a '/' is followed by a '/' or '*'.
86
+ def mynext()
87
+ c = get
88
+ if (c == "/")
89
+ if(peek == "/")
90
+ while(true)
91
+ c = get
92
+ if (c <= "\n")
93
+ return c
94
+ end
95
+ end
96
+ end
97
+ if(peek == "*")
98
+ get
99
+ while(true)
100
+ case get
101
+ when "*"
102
+ if (peek == "/")
103
+ get
104
+ return " "
105
+ end
106
+ when EOF
107
+ raise "Unterminated comment"
108
+ end
109
+ end
110
+ end
111
+ end
112
+ return c
113
+ end
114
+
115
+ # action -- do something! What you do is determined by the argument: 1
116
+ # Output A. Copy B to A. Get the next B. 2 Copy B to A. Get the next B.
117
+ # (Delete A). 3 Get the next B. (Delete B). action treats a string as a
118
+ # single character. Wow! action recognizes a regular expression if it is
119
+ # preceded by ( or , or =.
120
+ def action(a)
121
+ if(a==1)
122
+ @output.write @theA
123
+ end
124
+ if(a==1 || a==2)
125
+ @theA = @theB
126
+ if (@theA == "\'" || @theA == "\"")
127
+ while (true)
128
+ @output.write @theA
129
+ @theA = get
130
+ break if (@theA == @theB)
131
+ raise "Unterminated string literal" if (@theA <= "\n")
132
+ if (@theA == "\\")
133
+ # allow multi-line strings if each line is terminated by \\n (or \\r\n)
134
+ if ["\r", "\n"].include? peek
135
+ get # throw away the line ending
136
+ get if ["\r", "\n"].include? peek
137
+ else
138
+ @output.write @theA
139
+ end
140
+ @theA = get
141
+ end
142
+ end
143
+ end
144
+ end
145
+ if(a==1 || a==2 || a==3)
146
+ @theB = mynext
147
+ if (@theB == "/" && (@theA == "(" || @theA == "," || @theA == "=" ||
148
+ @theA == ":" || @theA == "[" || @theA == "!" ||
149
+ @theA == "&" || @theA == "|" || @theA == "?" ||
150
+ @theA == "{" || @theA == "}" || @theA == ";" ||
151
+ @theA == "\n"))
152
+ @output.write @theA
153
+ @output.write @theB
154
+ while (true)
155
+ @theA = get
156
+ if (@theA == "/")
157
+ break
158
+ elsif (@theA == "\\")
159
+ @output.write @theA
160
+ @theA = get
161
+ elsif (@theA <= "\n")
162
+ raise "Unterminated RegExp Literal"
163
+ end
164
+ @output.write @theA
165
+ end
166
+ @theB = mynext
167
+ end
168
+ end
169
+ end
170
+
171
+ # jsmin -- Copy the input to the output, deleting the characters which are
172
+ # insignificant to JavaScript. Comments will be removed. Tabs will be
173
+ # replaced with spaces. Carriage returns will be replaced with linefeeds.
174
+ # Most spaces and linefeeds will be removed.
175
+ def jsmin
176
+ @theA = "\n"
177
+ action(3)
178
+ while (@theA != EOF)
179
+ case @theA
180
+ when " "
181
+ if (isAlphanum(@theB))
182
+ action(1)
183
+ else
184
+ action(2)
185
+ end
186
+ when "\n"
187
+ case (@theB)
188
+ when "{","[","(","+","-"
189
+ action(1)
190
+ when " "
191
+ action(3)
192
+ else
193
+ if (isAlphanum(@theB))
194
+ action(1)
195
+ else
196
+ action(2)
197
+ end
198
+ end
199
+ else
200
+ case (@theB)
201
+ when " "
202
+ if (isAlphanum(@theA))
203
+ action(1)
204
+ else
205
+ action(3)
206
+ end
207
+ when "\n"
208
+ case (@theA)
209
+ when "}","]",")","+","-","\"","\\", "'", '"'
210
+ action(1)
211
+ else
212
+ if (isAlphanum(@theA))
213
+ action(1)
214
+ else
215
+ action(3)
216
+ end
217
+ end
218
+ else
219
+ action(1)
220
+ end
221
+ end
222
+ end
223
+ end
224
+ end # Javascript
225
+ end # Smurf
@@ -0,0 +1,34 @@
1
+ module Smurf
2
+ class Stylesheet
3
+ def initialize(content)
4
+ @content = content.nil? ? nil : minify(content)
5
+ end
6
+
7
+ def minified; @content; end
8
+
9
+ # TODO: deal with string values better (urls, content blocks, etc.)
10
+ def minify(content)
11
+ class << content; include Minifier; end
12
+ content.compress_whitespace.remove_comments.remove_spaces_outside_block.
13
+ remove_spaces_inside_block.trim_last_semicolon.strip
14
+ end
15
+
16
+ module Minifier
17
+ # .*? is a non-greedy match on anything
18
+ def compress_whitespace; compress!(/\s+/, ' '); end
19
+ def remove_comments; compress!(/\/\*.*?\*\/\s?/, ''); end
20
+ def remove_spaces_outside_block
21
+ compress!(/(\A|\})(.*?)\{/) { |m| m.gsub(/\s?([}{,])\s?/, '\1') }
22
+ end
23
+ def remove_spaces_inside_block
24
+ compress!(/\{(.*?)(?=\})/) do |m|
25
+ # remove spaces in the labels/attributes
26
+ m.gsub(/(?:\A|\s*;)(.*?)(?::\s*|\z)/) { |n| n.gsub(/\s/, '') }.strip
27
+ end
28
+ end
29
+ def trim_last_semicolon; compress!(/;(?=\})/, ''); end
30
+ private
31
+ def compress!(*args, &block) gsub!(*args, &block) || self; end
32
+ end
33
+ end # Stylesheet
34
+ end # Smurf
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'smurf'
data/smurf.gemspec ADDED
@@ -0,0 +1,42 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "smurf"
3
+ s.summary = "Rails plugin to automatically minify JS and CSS when their bundles get cached"
4
+ s.description = "Rails plugin to automatically minify JS and CSS when their bundles get cached. Send in those patches!"
5
+ s.version = "1.0.0"
6
+ s.authors = ["Justin Knowlden"]
7
+ s.email = %w[gus@thumblemonks.com]
8
+ s.homepage = "http://github.com/thumblemonks/smurf"
9
+ s.has_rdoc = true
10
+ s.rdoc_options = ["--inline-source", "--charset=UTF-8"]
11
+ s.post_install_message = %q{Choosy Gargamels choose Thumble Monks.}
12
+
13
+ s.files = %w[
14
+ MIT-LICENSE
15
+ README.markdown
16
+ Rakefile
17
+ init.rb
18
+ install.rb
19
+ lib/smurf.rb
20
+ lib/smurf/javascript.rb
21
+ lib/smurf/stylesheet.rb
22
+ rails/init.rb
23
+ smurf.gemspec
24
+ uninstall.rb
25
+ ]
26
+
27
+ s.test_files = %w[
28
+ test/rails/app/controllers/application.rb
29
+ test/rails/config/boot.rb
30
+ test/rails/config/database.yml
31
+ test/rails/config/environment.rb
32
+ test/rails/config/environments/test.rb
33
+ test/rails/config/routes.rb
34
+ test/rails/public/javascripts/cache/expected.js
35
+ test/rails/public/javascripts/testing.js
36
+ test/rails/public/stylesheets/bar.css
37
+ test/rails/public/stylesheets/cache/expected.css
38
+ test/rails/public/stylesheets/foo.css
39
+ test/smurf_test.rb
40
+ test/test_helper.rb
41
+ ]
42
+ end
@@ -0,0 +1,2 @@
1
+ class ApplicationController < ActionController::Base
2
+ end
@@ -0,0 +1,109 @@
1
+ # Don't change this file!
2
+ # Configure your app in config/environment.rb and config/environments/*.rb
3
+
4
+ RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
5
+
6
+ module Rails
7
+ class << self
8
+ def boot!
9
+ unless booted?
10
+ preinitialize
11
+ pick_boot.run
12
+ end
13
+ end
14
+
15
+ def booted?
16
+ defined? Rails::Initializer
17
+ end
18
+
19
+ def pick_boot
20
+ (vendor_rails? ? VendorBoot : GemBoot).new
21
+ end
22
+
23
+ def vendor_rails?
24
+ File.exist?("#{RAILS_ROOT}/vendor/rails")
25
+ end
26
+
27
+ def preinitialize
28
+ load(preinitializer_path) if File.exist?(preinitializer_path)
29
+ end
30
+
31
+ def preinitializer_path
32
+ "#{RAILS_ROOT}/config/preinitializer.rb"
33
+ end
34
+ end
35
+
36
+ class Boot
37
+ def run
38
+ load_initializer
39
+ Rails::Initializer.run(:set_load_path)
40
+ end
41
+ end
42
+
43
+ class VendorBoot < Boot
44
+ def load_initializer
45
+ require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
46
+ Rails::Initializer.run(:install_gem_spec_stubs)
47
+ end
48
+ end
49
+
50
+ class GemBoot < Boot
51
+ def load_initializer
52
+ self.class.load_rubygems
53
+ load_rails_gem
54
+ require 'initializer'
55
+ end
56
+
57
+ def load_rails_gem
58
+ if version = self.class.gem_version
59
+ gem 'rails', version
60
+ else
61
+ gem 'rails'
62
+ end
63
+ rescue Gem::LoadError => load_error
64
+ $stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
65
+ exit 1
66
+ end
67
+
68
+ class << self
69
+ def rubygems_version
70
+ Gem::RubyGemsVersion if defined? Gem::RubyGemsVersion
71
+ end
72
+
73
+ def gem_version
74
+ if defined? RAILS_GEM_VERSION
75
+ RAILS_GEM_VERSION
76
+ elsif ENV.include?('RAILS_GEM_VERSION')
77
+ ENV['RAILS_GEM_VERSION']
78
+ else
79
+ parse_gem_version(read_environment_rb)
80
+ end
81
+ end
82
+
83
+ def load_rubygems
84
+ require 'rubygems'
85
+ min_version = '1.1.1'
86
+ unless rubygems_version >= min_version
87
+ $stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)
88
+ exit 1
89
+ end
90
+
91
+ rescue LoadError
92
+ $stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org)
93
+ exit 1
94
+ end
95
+
96
+ def parse_gem_version(text)
97
+ $1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/
98
+ end
99
+
100
+ private
101
+ def read_environment_rb
102
+ File.read("#{RAILS_ROOT}/config/environment.rb")
103
+ end
104
+ end
105
+ end
106
+ end
107
+
108
+ # All that for this:
109
+ Rails.boot!
@@ -0,0 +1,3 @@
1
+ test:
2
+ adapter: sqlite3
3
+ dbfile: ":memory:" # db/test.db
@@ -0,0 +1,24 @@
1
+ # Be sure to restart your server when you modify this file
2
+
3
+ # Uncomment below to force Rails into production mode when
4
+ # you don't control web/app server and can't set it the proper way
5
+ # ENV['RAILS_ENV'] ||= 'production'
6
+
7
+ # Specifies gem version of Rails to use when vendor/rails is not present
8
+ unless defined? RAILS_GEM_VERSION
9
+ RAILS_GEM_VERSION = (ENV['RAILS_GEM_VERSION'] || '2.3.2')
10
+ end
11
+
12
+ # Bootstrap the Rails environment, frameworks, and default configuration
13
+ require File.join(File.dirname(__FILE__), 'boot')
14
+
15
+ Rails::Initializer.run do |config|
16
+ config.gem 'thoughtbot-shoulda', :lib => 'shoulda/rails',
17
+ :source => 'http://gems.github.com'
18
+ config.gem 'sqlite3-ruby', :lib => 'sqlite3'
19
+
20
+ config.action_controller.session = {
21
+ :session_key => '_smurf_session',
22
+ :secret => '731d6426b731d6426b731d6426b731d6426b731d6426b731d6426b731d6426b'
23
+ }
24
+ end
@@ -0,0 +1,19 @@
1
+ # Settings specified here will take precedence over those in config/environment.rb
2
+
3
+ # The test environment is used exclusively to run your application's
4
+ # test suite. You never need to work with it otherwise. Remember that
5
+ # your test database is "scratch space" for the test suite and is wiped
6
+ # and recreated between test runs. Don't rely on the data there!
7
+ config.cache_classes = true
8
+
9
+ # Log error messages when you accidentally call methods on nil.
10
+ config.whiny_nils = true
11
+
12
+ # Show full error reports and disable caching
13
+ config.action_controller.consider_all_requests_local = true
14
+ config.action_controller.perform_caching = false
15
+
16
+ # Tell ActionMailer not to deliver emails to the real world.
17
+ # The :test delivery method accumulates sent emails in the
18
+ # ActionMailer::Base.deliveries array.
19
+ config.action_mailer.delivery_method = :test
@@ -0,0 +1,5 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+ map.connect ':controller/service.wsdl', :action => 'wsdl'
3
+ map.connect ':controller/:action/:id.:format'
4
+ map.connect ':controller/:action/:id'
5
+ end
@@ -0,0 +1,2 @@
1
+
2
+ function foo(){puts"Hello, world"}
@@ -0,0 +1,3 @@
1
+ function foo() {
2
+ puts "Hello, world"
3
+ }
@@ -0,0 +1,44 @@
1
+ abbr, acronym {
2
+ border: 0;
3
+ font-variant: normal;
4
+ }
5
+
6
+ sup {
7
+ vertical-align: text-top;
8
+ }
9
+ /*
10
+ hello, my name is sam
11
+ */
12
+ sub {
13
+ vertical-align: text-bottom;
14
+ }
15
+
16
+ input, textarea, select{
17
+ font-family: inherit;
18
+ font-size: inherit;
19
+ font-weight: inherit;
20
+ }
21
+
22
+ input, textarea, select {
23
+ *font-size: 100%;
24
+ }
25
+
26
+ legend { color:#000; }
27
+
28
+ del, ins {
29
+ text-decoration:none;
30
+ }
31
+
32
+ smurf {
33
+ content: "pa pa";
34
+ }
35
+
36
+ .smurf :link li {
37
+ color:blue;
38
+ }
39
+
40
+ smurf #smurf , :smurf .smurf {
41
+ color : black;
42
+ }
43
+
44
+ smurfdom { papa: smurf }
@@ -0,0 +1 @@
1
+ html{color:#000;background:#FFF}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0}table{border-collapse:collapse;border-spacing:0}fieldset,img{border:0}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal}li{list-style:none}caption,th{text-align:left}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}q:before,q:after{content:''}abbr,acronym{border:0;font-variant:normal}sup{vertical-align:text-top}sub{vertical-align:text-bottom}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit}input,textarea,select{*font-size:100%}legend{color:#000}del,ins{text-decoration:none}smurf{content:"pa pa"}.smurf :link li{color:blue}smurf #smurf,:smurf .smurf{color:black}smurfdom{papa:smurf}
@@ -0,0 +1,48 @@
1
+ /*
2
+ Copyright (c) 2008, Yahoo! Inc. All rights reserved.
3
+ Code licensed under the BSD License:
4
+ http://developer.yahoo.net/yui/license.txt
5
+ version: 2.6.0
6
+ */
7
+
8
+ html {
9
+ color: #000;
10
+ background: #FFF;
11
+ }
12
+
13
+ body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, textarea, p, blockquote, th, td {
14
+ margin: 0;
15
+ padding: 0;
16
+ }
17
+
18
+ table {
19
+ border-collapse: collapse;
20
+ border-spacing: 0;
21
+ }
22
+
23
+ fieldset, img {
24
+ border: 0;
25
+ }
26
+
27
+ address, caption, cite, code, dfn, em, strong, th, var {
28
+ font-style: normal;
29
+ font-weight: normal;
30
+ }
31
+
32
+ li {
33
+ list-style: none;
34
+ }
35
+
36
+ caption, th {
37
+ text-align: left;
38
+ }
39
+
40
+ h1, h2, h3, h4, h5, h6 {
41
+ font-size: 100%;
42
+ font-weight: normal;
43
+ }
44
+
45
+ q:before, q:after {
46
+ content: '';
47
+ }
48
+
@@ -0,0 +1,82 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ class SmurfTest < Test::Unit::TestCase
4
+ include ActionView::Helpers::TagHelper
5
+ include ActionView::Helpers::AssetTagHelper
6
+
7
+ # Javascript
8
+
9
+ context "when caching on for javascript" do
10
+ setup do
11
+ ActionController::Base.stubs(:perform_caching).returns(true)
12
+ javascript_include_tag('testing.js', :cache => 'cache/actual')
13
+ end
14
+
15
+ should_have_same_contents('javascripts/cache/expected.js',
16
+ 'javascripts/cache/actual.js')
17
+ end # when caching on for javascript
18
+
19
+ context "minifying multi-line strings in javascript" do
20
+ setup do
21
+ input = StringIO.new()
22
+ input.puts("var foo='bar \\")
23
+ input.puts(" bar \\")
24
+ input.puts(" baz';")
25
+ input.rewind
26
+ @content = input.read
27
+ end
28
+
29
+ should "not affect the string" do
30
+ expected = "\n" + @content.gsub(/\\?\r?\n/, '')
31
+ assert_equal expected, Smurf::Javascript.new(@content).minified
32
+ end
33
+ end
34
+
35
+ # Stylesheet
36
+
37
+ context "when caching on for stylesheets" do
38
+ setup do
39
+ ActionController::Base.stubs(:perform_caching).returns(true)
40
+ stylesheet_link_tag('foo', 'bar', :cache => 'cache/actual')
41
+ end
42
+
43
+ should_have_same_contents('stylesheets/cache/expected.css',
44
+ 'stylesheets/cache/actual.css')
45
+ end # when caching on for stylesheets
46
+
47
+ context "minifying a non-existent pattern in a stylesheet" do
48
+ setup {@himom = "hi{mom:super-awesome}"}
49
+
50
+ # Thanks to someone named Niko for finding this
51
+ should "succeed for removing comments" do
52
+ actual = "hi { mom: super-awesome; } "
53
+ assert_equal @himom, Smurf::Stylesheet.new(actual).minified
54
+ end
55
+
56
+ should "succeed when no spaces to compress" do
57
+ actual = @himom
58
+ assert_equal @himom, Smurf::Stylesheet.new(actual).minified
59
+ end
60
+
61
+ should "succeed when no outside or inside blocks" do
62
+ # nothing outside, means nothing inside. they are complementary
63
+ actual = "how-did: this-happen; typo: maybe;}"
64
+ expected = "how-did: this-happen; typo: maybe}"
65
+ assert_equal expected, Smurf::Stylesheet.new(actual).minified
66
+ end
67
+
68
+ should "succeed when no last semi-colon in block" do
69
+ actual = "hi { mom: super-awesome } "
70
+ assert_equal @himom, Smurf::Stylesheet.new(actual).minified
71
+ end
72
+
73
+ should "succeed across all parsers when no content provided" do
74
+ actual = ""
75
+ assert_equal "", Smurf::Stylesheet.new(actual).minified
76
+ end
77
+
78
+ should "succeed if nil provided" do
79
+ assert_nil Smurf::Stylesheet.new(nil).minified
80
+ end
81
+ end # minifying a non-existent pattern
82
+ end
@@ -0,0 +1,32 @@
1
+ ENV["RAILS_ENV"] = "test"
2
+ ENV["RAILS_ROOT"] = File.expand_path(File.join(File.dirname(__FILE__), 'rails'))
3
+ require File.expand_path(File.join(ENV["RAILS_ROOT"], 'config', 'environment'))
4
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'init'))
5
+
6
+ require 'test_help'
7
+ require 'ruby-debug'
8
+
9
+ class Test::Unit::TestCase
10
+
11
+ def teardown
12
+ artifacts = Dir.glob(File.join(asset_path, '**', 'cache', 'actual.*'))
13
+ FileUtils.rm(artifacts)
14
+ end
15
+
16
+ def self.should_have_same_contents(expected_path, actual_path)
17
+ should "have the same file contents as #{expected_path}" do
18
+ expected = read_asset_file(expected_path)
19
+ actual = read_asset_file(actual_path)
20
+ assert_equal expected, actual
21
+ end
22
+ end
23
+
24
+ private
25
+ def asset_path
26
+ File.join(File.join(ENV["RAILS_ROOT"], 'public'))
27
+ end
28
+
29
+ def read_asset_file(relative_path)
30
+ File.read(File.join(asset_path, relative_path))
31
+ end
32
+ end
data/uninstall.rb ADDED
File without changes
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: smurf
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Justin Knowlden
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-02 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Rails plugin to automatically minify JS and CSS when their bundles get cached. Send in those patches!
17
+ email:
18
+ - gus@thumblemonks.com
19
+ executables: []
20
+
21
+ extensions: []
22
+
23
+ extra_rdoc_files: []
24
+
25
+ files:
26
+ - MIT-LICENSE
27
+ - README.markdown
28
+ - Rakefile
29
+ - init.rb
30
+ - install.rb
31
+ - lib/smurf.rb
32
+ - lib/smurf/javascript.rb
33
+ - lib/smurf/stylesheet.rb
34
+ - rails/init.rb
35
+ - smurf.gemspec
36
+ - uninstall.rb
37
+ has_rdoc: true
38
+ homepage: http://github.com/thumblemonks/smurf
39
+ licenses: []
40
+
41
+ post_install_message: Choosy Gargamels choose Thumble Monks.
42
+ rdoc_options:
43
+ - --inline-source
44
+ - --charset=UTF-8
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ requirements: []
60
+
61
+ rubyforge_project:
62
+ rubygems_version: 1.3.5
63
+ signing_key:
64
+ specification_version: 3
65
+ summary: Rails plugin to automatically minify JS and CSS when their bundles get cached
66
+ test_files:
67
+ - test/rails/app/controllers/application.rb
68
+ - test/rails/config/boot.rb
69
+ - test/rails/config/database.yml
70
+ - test/rails/config/environment.rb
71
+ - test/rails/config/environments/test.rb
72
+ - test/rails/config/routes.rb
73
+ - test/rails/public/javascripts/cache/expected.js
74
+ - test/rails/public/javascripts/testing.js
75
+ - test/rails/public/stylesheets/bar.css
76
+ - test/rails/public/stylesheets/cache/expected.css
77
+ - test/rails/public/stylesheets/foo.css
78
+ - test/smurf_test.rb
79
+ - test/test_helper.rb