sinatra-assetpack 0.0.9 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/HISTORY.md CHANGED
@@ -1,3 +1,17 @@
1
+ v0.0.10 - Sep 18, 2011
2
+ ----------------------
3
+
4
+ ### Added:
5
+ * Support for 'prebuild' to build on startup.
6
+ * Add UglifyJS support via `js_compression :uglify`. (#18)
7
+ * Ignore '.*' and '_*' files. (#17)
8
+ * Allow specifying of files to be ignored. (#17)
9
+
10
+ ### Changed:
11
+ * Built files from 'rake assetpack:build' now match the mtimes of their
12
+ sources. (#12)
13
+ * Refactor Compressor into separate engine classes.
14
+
1
15
  v0.0.9 - Sep 18, 2011
2
16
  ---------------------
3
17
 
@@ -6,8 +20,8 @@ v0.0.9 - Sep 18, 2011
6
20
  * Fix the Rake task when the main App class is in a module. (#11)
7
21
 
8
22
  ### Changed:
9
- * Use Sinatra's `template_cache`. This makes AssetPack honor Sinatra's
10
- `reload_templates` setting. (#15)
23
+ * Use Sinatra's `template_cache`. This makes AssetPack honor Sinatra's
24
+ `reload_templates` setting. (#15)
11
25
 
12
26
  ### Added:
13
27
  * Added .htc (IE behavior files) to the list of file formats to be served.
@@ -17,16 +31,16 @@ v0.0.8 - Sep 06, 2011
17
31
  ---------------------
18
32
 
19
33
  ### Fixed:
20
- * Fixed the CSS preprocessing bug that gives invalid 'url()' properties to
21
- non-existing images. Closes #1.
34
+ * Fixed the CSS preprocessing bug that gives invalid 'url()' properties to
35
+ non-existing images. (#1)
22
36
 
23
37
  ### Added:
24
- * Allow adding CSS/JS files that don't exist. Closes #8.
25
- * Support any Tilt-compatible CSS or JS engine. Related to #5.
38
+ * Allow adding CSS/JS files that don't exist. (#8)
39
+ * Support any Tilt-compatible CSS or JS engine. (#5)
26
40
 
27
41
  ### Changed:
28
- * Default to '/assets/x.js' then using assets.css without a path. Inspiration
29
- from Jammit.
42
+ * Default to '/assets/x.js' then using assets.css without a path. Inspiration
43
+ from Jammit.
30
44
  * Ask browsers to cache assets for 1 month.
31
45
 
32
46
  ### Misc:
data/README.md CHANGED
@@ -136,7 +136,7 @@ compressors in the `assets` block:
136
136
 
137
137
  ``` ruby
138
138
  assets {
139
- js_compression :jsmin # :jsmin | :yui | :closure
139
+ js_compression :jsmin # :jsmin | :yui | :closure | :uglify
140
140
  css_compression :simple # :simple | :sass | :yui | :sqwish
141
141
  }
142
142
  ```
@@ -155,10 +155,19 @@ assets {
155
155
  }
156
156
  ```
157
157
 
158
+ __Note:__ This depends on the `yui-compressor` gem. You will need to install it.
159
+ (`gem install yui-compressor`) If you use Bundler, you will need to add it to
160
+ your Gemfile as well.
161
+
162
+ ``` ruby
163
+ # Gemfile
164
+ gem 'yui-compressor', :require => 'yui/compressor'
165
+ ```
166
+
158
167
  ### SASS compression
159
168
 
160
169
  For SASS compression, you need the Sass gem (`gem install sass`). This treats
161
- the CSS files as Scss files and uses Sass's `output: :compressed`.
170
+ the CSS files as Scss files and uses Sass's `:output => :compressed`.
162
171
 
163
172
  ``` ruby
164
173
  assets {
@@ -166,6 +175,15 @@ assets {
166
175
  }
167
176
  ```
168
177
 
178
+ __Note:__ This depends on the `sass` gem. You will need to install it (`gem
179
+ install sass`). If you use Bundler, you will need to add it to your Gemfile as
180
+ well.
181
+
182
+ ``` ruby
183
+ # Gemfile
184
+ gem 'sass'
185
+ ```
186
+
169
187
  ### Sqwish CSS compression
170
188
 
171
189
  [Sqwish](http://github.com/ded/sqwish) is a NodeJS-based CSS compressor. To use
@@ -196,6 +214,35 @@ assets {
196
214
  }
197
215
  ```
198
216
 
217
+ ### UglifyJS compression
218
+
219
+ This uses the [UglifyJS](https://github.com/mishoo/UglifyJS) compressor to
220
+ compress your JavaScript. You will need to install the
221
+ [uglifier](http://rubygems.org/gems/uglifier) gem.
222
+
223
+ For options, refer to the [Uglifier
224
+ documentation](https://github.com/lautis/uglifier).
225
+
226
+ ``` ruby
227
+ assets {
228
+ js_compression :uglify
229
+ js_compression :uglify, [options]
230
+ }
231
+ ```
232
+
233
+ __Note:__ This depends on the `uglifier` gem. In your Gemfile, you will need to
234
+ add it. For Heroku support, you will need to add the `therubyracer-heroku` gem
235
+ as well.
236
+
237
+ ``` ruby
238
+ # Gemfile
239
+ gem 'uglifier'
240
+
241
+ # If you're on Heroku:
242
+ gem "therubyracer-heroku", "0.8.1.pre3", :require => false
243
+ ```
244
+
245
+
199
246
  Images
200
247
  ------
201
248
 
@@ -378,8 +425,8 @@ from `./app/javascripts/vendor/jquery*.js`.
378
425
 
379
426
  ``` ruby
380
427
  class App < Sinatra::Base
381
- serve '/js', from: '/app/javascripts'
382
428
  assets {
429
+ serve '/js', from: '/app/javascripts'
383
430
  js :application, [
384
431
  '/js/vendor/jquery.*.js',
385
432
  '/js/vendor/jquery.js'
@@ -390,6 +437,96 @@ end
390
437
  # In views: <%= js :application %>
391
438
  ```
392
439
 
440
+ ### assets.ignore
441
+ Excludes any URL paths that match the given spec.
442
+
443
+ These files will not show up in packages, and they will not be accessible.
444
+
445
+ By default, `.*` and `_*` are ignored. The former protects folders such as
446
+ `.svn` from being accessed, and the latter protects Sass partial files from
447
+ being accessed directly.
448
+
449
+ Note that this matches against URL paths, not local file paths. This means
450
+ something like `*.scss` will not work, as all stylesheet files will be compiled
451
+ to `.css`.
452
+
453
+ ``` ruby
454
+ # Usage:
455
+ assets {
456
+ ignore FILESPEC
457
+ }
458
+ ```
459
+
460
+ #### Example
461
+ Here's an example.
462
+
463
+ ``` ruby
464
+ class App < Sinatra::Base
465
+ assets {
466
+ # Ignores all files matching *.private.js in any folder.
467
+ ignore '*.private.js'
468
+
469
+ # Ignores all files in `/app/js/foo/**/*`
470
+ ignore '/js/foo'
471
+ }
472
+ end
473
+ ```
474
+
475
+ #### Advanced usage
476
+ By default, `.*` and `_*` are ignored. To disable this behavior, you can use
477
+ `clear_ignores!` before your `ignore` lines.
478
+
479
+ ``` ruby
480
+ assets {
481
+ clear_ignores!
482
+ ignore '*.private.js'
483
+ }
484
+ ```
485
+
486
+ To check if a certain file is ignored, use `assets.ignore?`
487
+
488
+ ``` ruby
489
+ assets.ignored?("/css/_chrome.css") #=> true
490
+ ```
491
+
492
+
493
+ ### assets.prebuild
494
+ Caches the built packages on application startup.
495
+
496
+ If this is not used, the packages will be minified when they are first
497
+ requested. This only has an effect in the production environment (or when
498
+ Sinatra's `reload_templates` is otherwise set to false).
499
+
500
+ ``` ruby
501
+ # Usage:
502
+ prebuild {true|false}
503
+ ```
504
+
505
+ #### Example
506
+ In this example, the package for `:application` will be built when the
507
+ application is started in the production environment.
508
+
509
+ ``` ruby
510
+ class App < Sinatra::Base
511
+ assets {
512
+ js_compression :closure
513
+
514
+ js :application, [
515
+ '/js/vendor/jquery.*.js',
516
+ '/js/vendor/jquery.js'
517
+ ]
518
+ prebuild true
519
+ }
520
+ end
521
+
522
+ # $ RACK_ENV=production ruby app.rb
523
+ # ** Building /assets/application.js...
524
+ # == Sinatra/1.2.6 has taken the stage on 4567 for production
525
+ # >> Thin web server (v1.2.11 codename Bat-Shit Crazy)
526
+ # >> Maximum connections set to 1024
527
+ # >> Listening on 0.0.0.0:4567, CTRL+C to stop
528
+ ```
529
+
393
530
  API reference: helpers
394
531
  ----------------------
395
532
 
@@ -500,19 +637,6 @@ class Main
500
637
  end
501
638
  ```
502
639
 
503
- To do
504
- -----
505
-
506
- AssetPack will eventually have:
507
-
508
- * Nested packages
509
- * Ignored files (to ignore included sass files and such)
510
- * `rake assetpack:build` should be able to output to another folder
511
- * Cache folder support (best if your app has many workers)
512
- * Refactor *Compressor* module
513
- * CDN (Cloudfront, S3) support
514
- * Better support for Compass sprites
515
-
516
640
  Acknowledgements
517
641
  ----------------
518
642
 
@@ -1,3 +1,4 @@
1
1
  ("App.js goes here.");
2
+ console.log("Hello");
2
3
 
3
4
 
@@ -1,4 +1,4 @@
1
- $:.unshift File.expand_path('../../lib', __FILE__)
1
+ $:.unshift File.expand_path('../../../lib', __FILE__)
2
2
 
3
3
  require 'sinatra/base'
4
4
  require 'sinatra/assetpack'
@@ -8,6 +8,9 @@ class App < Sinatra::Base
8
8
  register Sinatra::AssetPack
9
9
 
10
10
  assets do
11
+ #js_compression :closure
12
+ js_compression :uglify
13
+
11
14
  js :main, '/js/main.js', [
12
15
  '/js/vendor/*.js',
13
16
  '/js/app.js'
@@ -22,6 +25,8 @@ class App < Sinatra::Base
22
25
  css :more, '/css/more.css', [
23
26
  '/css/more/*.css'
24
27
  ]
28
+
29
+ prebuild true
25
30
  end
26
31
 
27
32
  get '/' do
@@ -1,4 +1,4 @@
1
- $:.unshift File.expand_path('../../lib', __FILE__)
1
+ $:.unshift File.expand_path('../../../lib', __FILE__)
2
2
 
3
3
  require 'sinatra/base'
4
4
  require 'sinatra/assetpack'
@@ -13,6 +13,11 @@ module Sinatra
13
13
  def assets_initialize!
14
14
  add_compressed_routes!
15
15
  add_individual_routes!
16
+
17
+ # Cache the built files.
18
+ if assets.prebuild && !reload_templates
19
+ assets.cache! { |file| $stderr.write "** Building #{file}...\n" }
20
+ end
16
21
  end
17
22
 
18
23
  # Add routes for the compressed versions
@@ -40,6 +45,8 @@ module Sinatra
40
45
  pass unless AssetPack.supported_formats.include?(fmt)
41
46
  fn = asset_path_for(file, from) or pass
42
47
 
48
+ pass if settings.assets.ignored?("#{path}/#{file}")
49
+
43
50
  # Send headers
44
51
  content_type fmt.to_sym
45
52
  last_modified File.mtime(fn).to_i
@@ -8,102 +8,47 @@ module Sinatra
8
8
  # compress File.read('x.js'), :js, :jsmin
9
9
  #
10
10
  def compress(str, type, engine=nil, options={})
11
- engine ||= 'jsmin' if type == :js
12
- engine ||= 'simple' if type == :css
11
+ # Use defaults if no engine is given.
12
+ return fallback(str, type, options) if engine.nil?
13
13
 
14
- key = :"#{type}/#{engine}"
15
- meth = compressors[key]
16
- return str unless meth
14
+ # Ensure that the engine exists.
15
+ klass = compressors[[type, engine]]
16
+ raise Error, "Engine #{engine} (#{type}) doesn't exist." unless klass
17
17
 
18
- meth[str, options]
19
- end
20
-
21
- def compressors
22
- @compressors ||= {
23
- :'js/jsmin' => method(:jsmin),
24
- :'js/yui' => method(:yui_js),
25
- :'js/closure' => method(:closure_js),
26
- :'css/sass' => method(:sass),
27
- :'css/yui' => method(:yui_css),
28
- :'css/simple' => method(:simple_css),
29
- :'css/sqwish' => method(:sqwish_css)
30
- }
31
- end
32
-
33
- # =====================================================================
34
- # Compressors
35
-
36
- def jsmin(str, options={})
37
- require 'jsmin'
38
- JSMin.minify str
39
- end
40
-
41
- def sass(str, options={})
42
- Tilt.new("scss", {:style => :compressed}) { str }.render
43
- rescue LoadError
44
- simple_css str
45
- end
18
+ # Ensure that the engine can support that type.
19
+ engine = klass.new
20
+ raise Error, "#{klass} does not support #{type.upcase} compression." unless engine.respond_to?(type)
46
21
 
47
- def yui_css(str, options={})
48
- require 'yui/compressor'
49
- YUI::CssCompressor.new.compress(str)
50
- rescue Errno::ENOENT
51
- sass str
22
+ # Build it using the engine, and fallback to defaults if it fails.
23
+ output = engine.send type, str, options
24
+ output ||= fallback(str, type, options) unless options[:no_fallback]
25
+ output
52
26
  end
53
27
 
54
- def yui_js(str, options={})
55
- require 'yui/compressor'
56
- YUI::JavaScriptCompressor.new(options).compress(str)
57
- rescue LoadError
58
- jsmin str
28
+ # Compresses a given string using the default engines.
29
+ def fallback(str, type, options)
30
+ if type == :js
31
+ compress str, :js, :jsmin, :no_fallback => true
32
+ elsif type == :css
33
+ compress str, :css, :simple, :no_fallback => true
34
+ end
59
35
  end
60
36
 
61
- def simple_css(str, options={})
62
- str.gsub! /[ \r\n\t]+/m, ' '
63
- str.gsub! %r{ *([;\{\},:]) *}, '\1'
64
- end
65
-
66
- def sqwish_css(str, options={})
67
- cmd = "#{sqwish_bin} %f "
68
- cmd += "--strict" if options[:strict]
69
-
70
- _, input = sys :css, str, cmd
71
- output = input.gsub(/\.css/, '.min.css')
72
-
73
- File.read(output)
74
- rescue => e
75
- simple_css str
76
- end
77
-
78
- def sqwish_bin
79
- ENV['SQWISH_PATH'] || "sqwish"
80
- end
81
-
82
- def closure_js(str, options={})
83
- require 'net/http'
84
- require 'uri'
85
-
86
- response = Net::HTTP.post_form(URI.parse('http://closure-compiler.appspot.com/compile'), {
87
- 'js_code' => str,
88
- 'compilation_level' => options[:level] || "ADVANCED_OPTIMIZATIONS",
89
- 'output_format' => 'text',
90
- 'output_info' => 'compiled_code'
91
- })
92
-
93
- response.body
37
+ def compressors
38
+ @compressors ||= Hash.new
94
39
  end
95
40
 
96
- # For others
97
- def sys(type, str, cmd)
98
- t = Tempfile.new ['', ".#{type}"]
99
- t.write(str)
100
- t.close
101
-
102
- output = `#{cmd.gsub('%f', t.path)}`
103
- FileUtils.rm t
104
-
105
- [output, t.path]
41
+ def register(type, engine, meth)
42
+ compressors[[type, engine]] = meth
106
43
  end
107
44
  end
45
+
46
+ require "#{AssetPack::PREFIX}/assetpack/engines/simple"
47
+ require "#{AssetPack::PREFIX}/assetpack/engines/jsmin"
48
+ require "#{AssetPack::PREFIX}/assetpack/engines/yui"
49
+ require "#{AssetPack::PREFIX}/assetpack/engines/sass"
50
+ require "#{AssetPack::PREFIX}/assetpack/engines/sqwish"
51
+ require "#{AssetPack::PREFIX}/assetpack/engines/closure"
52
+ require "#{AssetPack::PREFIX}/assetpack/engines/uglify"
108
53
  end
109
54
  end
@@ -0,0 +1,20 @@
1
+ module Sinatra
2
+ module AssetPack
3
+ # The base class for all CSS/JS compression engines.
4
+ class Engine
5
+ # Helper for system files.
6
+ # Usage: sys('css', string, "sqwish %f")
7
+ # Returns stdout.
8
+ def sys(type, str, cmd)
9
+ t = Tempfile.new ['', ".#{type}"]
10
+ t.write(str)
11
+ t.close
12
+
13
+ output = `#{cmd.gsub('%f', t.path)}`
14
+ FileUtils.rm t
15
+
16
+ [output, t.path]
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ module Sinatra::AssetPack
2
+ class ClosureEngine < Engine
3
+ def js(str, options={})
4
+ require 'net/http'
5
+ require 'uri'
6
+
7
+ response = Net::HTTP.post_form(URI.parse('http://closure-compiler.appspot.com/compile'), {
8
+ 'js_code' => str,
9
+ 'compilation_level' => options[:level] || "ADVANCED_OPTIMIZATIONS",
10
+ 'output_format' => 'text',
11
+ 'output_info' => 'compiled_code'
12
+ })
13
+
14
+ response.body
15
+ end
16
+ end
17
+
18
+ Compressor.register :js, :closure, ClosureEngine
19
+ end
@@ -0,0 +1,10 @@
1
+ module Sinatra::AssetPack
2
+ class JsminEngine < Engine
3
+ def js(str, options={})
4
+ require 'jsmin'
5
+ JSMin.minify str
6
+ end
7
+ end
8
+
9
+ Compressor.register :js, :jsmin, JsminEngine
10
+ end
@@ -0,0 +1,11 @@
1
+ module Sinatra::AssetPack
2
+ class SassEngine < Engine
3
+ def css(str, options={})
4
+ Tilt.new("scss", {:style => :compressed}) { str }.render
5
+ rescue LoadError
6
+ nil
7
+ end
8
+ end
9
+
10
+ Compressor.register :css, :sass, SassEngine
11
+ end
@@ -0,0 +1,11 @@
1
+ module Sinatra::AssetPack
2
+ class SimpleEngine < Engine
3
+ def css(str, options={})
4
+ str.gsub! /[ \r\n\t]+/m, ' '
5
+ str.gsub! %r{ *([;\{\},:]) *}, '\1'
6
+ str
7
+ end
8
+ end
9
+
10
+ Compressor.register :css, :simple, SimpleEngine
11
+ end
@@ -0,0 +1,21 @@
1
+ module Sinatra::AssetPack
2
+ class SqwishEngine < Engine
3
+ def css(str, options={})
4
+ cmd = "#{sqwish_bin} %f "
5
+ cmd += "--strict" if options[:strict]
6
+
7
+ _, input = sys :css, str, cmd
8
+ output = input.gsub(/\.css/, '.min.css')
9
+
10
+ File.read(output)
11
+ rescue => e
12
+ nil
13
+ end
14
+
15
+ def sqwish_bin
16
+ ENV['SQWISH_PATH'] || "sqwish"
17
+ end
18
+ end
19
+
20
+ Compressor.register :css, :sqwish, SqwishEngine
21
+ end
@@ -0,0 +1,12 @@
1
+ module Sinatra::AssetPack
2
+ class UglifyEngine < Engine
3
+ def js(str, options={})
4
+ require 'uglifier'
5
+ Uglifier.compile str, options
6
+ rescue => e
7
+ nil
8
+ end
9
+ end
10
+
11
+ Compressor.register :js, :uglify, UglifyEngine
12
+ end
@@ -0,0 +1,22 @@
1
+ module Sinatra::AssetPack
2
+ class YuiEngine < Engine
3
+ def initialize
4
+ require 'yui/compressor'
5
+ end
6
+
7
+ def js(str, options={})
8
+ YUI::JavaScriptCompressor.new(options).compress(str)
9
+ rescue LoadError
10
+ nil
11
+ end
12
+
13
+ def css(str, options={})
14
+ YUI::CssCompressor.new.compress(str)
15
+ rescue Errno::ENOENT
16
+ nil
17
+ end
18
+ end
19
+
20
+ Compressor.register :js, :yui, YuiEngine
21
+ Compressor.register :css, :yui, YuiEngine
22
+ end
@@ -38,20 +38,6 @@ module Sinatra
38
38
  new arr.each_slice(2).map { |(k, v)| Hash[k, v] }
39
39
  end
40
40
 
41
- # Works like Hash#each.
42
- #
43
- # By extension, methods that rely on #each (like #inject) will work
44
- # as intended.
45
- #
46
- def each(&block)
47
- super { |hash| yield hash.to_a.flatten }
48
- end
49
-
50
- # Works like Hash#map.
51
- def map(&block)
52
- super { |hash| yield hash.to_a.flatten }
53
- end
54
-
55
41
  # Works like Hash#values.
56
42
  def values
57
43
  inject([]) { |a, (k, v)| a << v; a }
@@ -65,6 +51,16 @@ module Sinatra
65
51
  def keys
66
52
  inject([]) { |a, (k, v)| a << k; a }
67
53
  end
54
+
55
+ [:each, :map, :map!, :reject, :reject!, :select, :select!].each do |meth|
56
+ send(:define_method, meth) { |*a, &block|
57
+ if block.respond_to?(:call)
58
+ super(*a) { |hash| block.call *hash.to_a }
59
+ else
60
+ super(*a)
61
+ end
62
+ }
63
+ end
68
64
  end
69
65
  end
70
66
  end
@@ -49,6 +49,8 @@ module Sinatra
49
49
  @js_compression_options = Hash.new
50
50
  @css_compression_options = Hash.new
51
51
 
52
+ @ignored = Array.new
53
+
52
54
  reset!
53
55
 
54
56
  # Defaults!
@@ -56,6 +58,9 @@ module Sinatra
56
58
  serve '/js', :from => 'app/js'
57
59
  serve '/images', :from => 'app/images'
58
60
 
61
+ ignore '.*'
62
+ ignore '_*'
63
+
59
64
  blk.arity <= 0 ? instance_eval(&blk) : yield(self) if block_given?
60
65
  end
61
66
 
@@ -75,6 +80,27 @@ module Sinatra
75
80
  @packages = Hash.new
76
81
  end
77
82
 
83
+ # Ignores a given path spec.
84
+ def ignore(spec)
85
+ if spec[0] == '/'
86
+ @ignored << "#{spec}"
87
+ @ignored << "#{spec}/**"
88
+ else
89
+ @ignored << "**/#{spec}"
90
+ @ignored << "**/#{spec}/**"
91
+ end
92
+ end
93
+
94
+ # Makes nothing ignored. Use this if you don't want to ignore dotfiles and underscore files.
95
+ def clear_ignores!
96
+ @ignored = Array.new
97
+ end
98
+
99
+ # Checks if a given path is ignored.
100
+ def ignored?(fn)
101
+ @ignored.any? { |spec| File.fnmatch spec, fn }
102
+ end
103
+
78
104
  # Adds some JS packages.
79
105
  #
80
106
  # js :foo, [ '/js/vendor/jquery.*.js', ... ]
@@ -122,6 +148,8 @@ module Sinatra
122
148
  attrib :js_compression_options # Hash
123
149
  attrib :css_compression_options # Hash
124
150
 
151
+ attrib :prebuild # Bool
152
+
125
153
  def js_compression(name=nil, options=nil)
126
154
  @js_compression = name unless name.nil?
127
155
  @js_compression_options = options if options.is_a?(Hash)
@@ -142,18 +170,40 @@ module Sinatra
142
170
  def build!(&blk)
143
171
  session = Rack::Test::Session.new app
144
172
 
173
+ get = lambda { |path|
174
+ response = session.get(path)
175
+ out = response.body
176
+ mtime = Time.parse(response.headers['Last-Modified']) if response.headers['Last-Modified']
177
+
178
+ [ out, mtime ]
179
+ }
180
+
145
181
  packages.each { |_, pack|
146
- out = session.get(pack.path).body
182
+ out, mtime = get[pack.path]
147
183
 
148
- write pack.path, out, &blk
149
- write pack.production_path, out, &blk
184
+ write pack.path, out, mtime, &blk
185
+ write pack.production_path, out, mtime, &blk
150
186
  }
151
187
 
152
188
  files.each { |path, local|
153
- out = session.get(path).body
154
- write path, out, &blk
155
- write BusterHelpers.add_cache_buster(path, local), out, &blk
189
+ out, mtime = get[path]
190
+
191
+ write path, out, mtime, &blk
192
+ write BusterHelpers.add_cache_buster(path, local), out, mtime, &blk
193
+ }
194
+ end
195
+
196
+ # Caches the packages.
197
+ def cache!(&blk)
198
+ return false if app.reload_templates
199
+
200
+ session = Rack::Test::Session.new app
201
+ packages.each { |_, pack|
202
+ yield pack.path if block_given?
203
+ session.get(pack.path)
156
204
  }
205
+
206
+ true
157
207
  end
158
208
 
159
209
  def served?(path)
@@ -189,7 +239,7 @@ module Sinatra
189
239
  end
190
240
 
191
241
  # Writes `public/#{path}` based on contents of `output`.
192
- def write(path, output)
242
+ def write(path, output, mtime=nil)
193
243
  require 'fileutils'
194
244
 
195
245
  path = File.join(@output_path, path)
@@ -197,6 +247,10 @@ module Sinatra
197
247
 
198
248
  FileUtils.mkdir_p File.dirname(path)
199
249
  File.open(path, 'w') { |f| f.write output }
250
+
251
+ if mtime
252
+ File.utime mtime, mtime, path
253
+ end
200
254
  end
201
255
 
202
256
  # Returns the files as a hash.
@@ -37,7 +37,9 @@ module Sinatra
37
37
 
38
38
  # Returns a list of URIs
39
39
  def paths_and_files
40
- @assets.glob @filespecs, :preserve => true
40
+ list = @assets.glob(@filespecs, :preserve => true)
41
+ list.reject! { |path, file| @assets.ignored?(path) }
42
+ list
41
43
  end
42
44
 
43
45
  def files
@@ -1,7 +1,7 @@
1
1
  module Sinatra
2
2
  module AssetPack
3
3
  def self.version
4
- "0.0.9"
4
+ "0.0.10"
5
5
  end
6
6
  end
7
7
  end
@@ -46,6 +46,7 @@ module Sinatra
46
46
  autoload :Helpers, "#{PREFIX}/assetpack/helpers"
47
47
  autoload :HtmlHelpers, "#{PREFIX}/assetpack/html_helpers"
48
48
  autoload :BusterHelpers, "#{PREFIX}/assetpack/buster_helpers"
49
+ autoload :Engine, "#{PREFIX}/assetpack/engine"
49
50
  autoload :Package, "#{PREFIX}/assetpack/package"
50
51
  autoload :Compressor, "#{PREFIX}/assetpack/compressor"
51
52
  autoload :Image, "#{PREFIX}/assetpack/image"
@@ -22,4 +22,5 @@ Gem::Specification.new do |s|
22
22
  s.add_development_dependency "contest"
23
23
  s.add_development_dependency "mocha"
24
24
  s.add_development_dependency "stylus"
25
+ s.add_development_dependency "uglifier"
25
26
  end
@@ -0,0 +1 @@
1
+ alert("HELLO I SHOULD BE IGNORED. BUMBLEBEE.");
@@ -0,0 +1,7 @@
1
+ (function() {
2
+ var kitsch = 1;
3
+ var noodle = 2;
4
+ var banana = 3;
5
+ console.log(noodle, banana);
6
+ })();
7
+
data/test/arity_test.rb CHANGED
@@ -1,8 +1,7 @@
1
1
  require File.expand_path('../test_helper', __FILE__)
2
2
 
3
3
  class ArityTest < UnitTest
4
- class App < Sinatra::Base
5
- set :root, File.expand_path('../app', __FILE__)
4
+ class App < UnitTest::App
6
5
  register Sinatra::AssetPack
7
6
 
8
7
  assets do |a|
data/test/build_test.rb CHANGED
@@ -11,11 +11,21 @@ class BuildTest < UnitTest
11
11
  app.assets.build!
12
12
 
13
13
  assert File.file? File.join(app.root, 'public/js/app.js')
14
+ assert File.mtime(File.join(app.root, 'public/js/app.js')).to_i == app.assets.packages['app.js'].mtime.to_i
15
+
14
16
  assert Dir[File.join(app.root, 'public/js/app.*.js')].first
15
17
 
16
18
  assert File.read(File.join(app.root, 'public/js/app.js')).include?('function(){alert("Hello");')
17
19
 
18
20
  assert Dir["#{app.root}/public/images/background.*.jpg"].first
19
21
  assert Dir["#{app.root}/public/images/email.*.png"].first
22
+
23
+ assert \
24
+ File.mtime(Dir["#{app.root}/public/images/background.*.jpg"].first).to_i ==
25
+ File.mtime(Dir["#{app.root}/public/images/background.jpg"].first).to_i
26
+
27
+ assert \
28
+ File.mtime(Dir["#{app.root}/public/images/background.*.jpg"].first).to_i ==
29
+ File.mtime(Dir["#{app.root}/app/images/background.jpg"].first).to_i
20
30
  end
21
31
  end
data/test/cache_test.rb CHANGED
@@ -3,7 +3,7 @@ require File.expand_path('../test_helper', __FILE__)
3
3
  class CacheTest < UnitTest
4
4
  test "Compressed js caching" do
5
5
  app.set :reload_templates, false
6
- JSMin.expects(:minify).times(1)
6
+ JSMin.expects(:minify).times(1).returns ""
7
7
  3.times { get '/js/app.js' }
8
8
  end
9
9
  end
@@ -0,0 +1,30 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ class IgnoreTest < UnitTest
4
+ class App < UnitTest::App
5
+ register Sinatra::AssetPack
6
+
7
+ assets do
8
+ js :main, '/main.js', %w[/js/*.js]
9
+ end
10
+ end
11
+
12
+ def app
13
+ App
14
+ end
15
+
16
+ test "ignore as individual file" do
17
+ get '/js/_ignoreme.js'
18
+ assert last_response.status == 404
19
+ end
20
+
21
+ test "ignore in package" do
22
+ get '/main.js'
23
+ assert body.size > 0
24
+ assert !body.include?("BUMBLEBEE")
25
+ end
26
+
27
+ test "package files" do
28
+ assert !app.assets.packages['main.js'].files.any? { |s| s.include? '_ignoreme.js' }
29
+ end
30
+ end
data/test/sqwish_test.rb CHANGED
@@ -20,9 +20,8 @@ class SqwishTest < UnitTest
20
20
 
21
21
  if sqwish?
22
22
  test "build" do
23
- Sinatra::AssetPack::Compressor.expects(:`).with() { |cmd|
24
- cmd.match /^sqwish .*? --strict$/
25
- }
23
+ Sinatra::AssetPack::Compressor
24
+ Sinatra::AssetPack::SqwishEngine.any_instance.expects(:css)
26
25
 
27
26
  get '/css/sq.css'
28
27
  end
@@ -0,0 +1,23 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ class UglifyTest < UnitTest
4
+ class App < UnitTest::App
5
+ register Sinatra::AssetPack
6
+
7
+ assets do
8
+ js_compression :uglify, :mangle => true
9
+ js :main, '/main.js', [
10
+ '/js/ugly.js'
11
+ ]
12
+ end
13
+ end
14
+
15
+ def app
16
+ App
17
+ end
18
+
19
+ test "build" do
20
+ get '/main.js'
21
+ assert !body.include?("noodle")
22
+ end
23
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sinatra-assetpack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.10
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2011-09-17 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: tilt
16
- requirement: &2156684180 !ruby/object:Gem::Requirement
16
+ requirement: &2153561760 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 1.3.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2156684180
24
+ version_requirements: *2153561760
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: sinatra
27
- requirement: &2156683760 !ruby/object:Gem::Requirement
27
+ requirement: &2153561340 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *2156683760
35
+ version_requirements: *2153561340
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: jsmin
38
- requirement: &2156683300 !ruby/object:Gem::Requirement
38
+ requirement: &2153560880 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *2156683300
46
+ version_requirements: *2153560880
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rack-test
49
- requirement: &2156682880 !ruby/object:Gem::Requirement
49
+ requirement: &2153560460 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *2156682880
57
+ version_requirements: *2153560460
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: yui-compressor
60
- requirement: &2156682460 !ruby/object:Gem::Requirement
60
+ requirement: &2153560040 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *2156682460
68
+ version_requirements: *2153560040
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: sass
71
- requirement: &2156682040 !ruby/object:Gem::Requirement
71
+ requirement: &2153559620 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *2156682040
79
+ version_requirements: *2153559620
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: haml
82
- requirement: &2156681620 !ruby/object:Gem::Requirement
82
+ requirement: &2153559200 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *2156681620
90
+ version_requirements: *2153559200
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: coffee-script
93
- requirement: &2156681200 !ruby/object:Gem::Requirement
93
+ requirement: &2153558780 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *2156681200
101
+ version_requirements: *2153558780
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: contest
104
- requirement: &2156680780 !ruby/object:Gem::Requirement
104
+ requirement: &2153558360 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ! '>='
@@ -109,10 +109,10 @@ dependencies:
109
109
  version: '0'
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *2156680780
112
+ version_requirements: *2153558360
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: mocha
115
- requirement: &2156680360 !ruby/object:Gem::Requirement
115
+ requirement: &2153557940 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - ! '>='
@@ -120,10 +120,10 @@ dependencies:
120
120
  version: '0'
121
121
  type: :development
122
122
  prerelease: false
123
- version_requirements: *2156680360
123
+ version_requirements: *2153557940
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: stylus
126
- requirement: &2156679940 !ruby/object:Gem::Requirement
126
+ requirement: &2153557520 !ruby/object:Gem::Requirement
127
127
  none: false
128
128
  requirements:
129
129
  - - ! '>='
@@ -131,7 +131,18 @@ dependencies:
131
131
  version: '0'
132
132
  type: :development
133
133
  prerelease: false
134
- version_requirements: *2156679940
134
+ version_requirements: *2153557520
135
+ - !ruby/object:Gem::Dependency
136
+ name: uglifier
137
+ requirement: &2153557100 !ruby/object:Gem::Requirement
138
+ none: false
139
+ requirements:
140
+ - - ! '>='
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ type: :development
144
+ prerelease: false
145
+ version_requirements: *2153557100
135
146
  description: Package your assets for Sinatra.
136
147
  email:
137
148
  - rico@sinefunc.com
@@ -176,6 +187,14 @@ files:
176
187
  - lib/sinatra/assetpack/compressor.rb
177
188
  - lib/sinatra/assetpack/configurator.rb
178
189
  - lib/sinatra/assetpack/css.rb
190
+ - lib/sinatra/assetpack/engine.rb
191
+ - lib/sinatra/assetpack/engines/closure.rb
192
+ - lib/sinatra/assetpack/engines/jsmin.rb
193
+ - lib/sinatra/assetpack/engines/sass.rb
194
+ - lib/sinatra/assetpack/engines/simple.rb
195
+ - lib/sinatra/assetpack/engines/sqwish.rb
196
+ - lib/sinatra/assetpack/engines/uglify.rb
197
+ - lib/sinatra/assetpack/engines/yui.rb
179
198
  - lib/sinatra/assetpack/hasharray.rb
180
199
  - lib/sinatra/assetpack/helpers.rb
181
200
  - lib/sinatra/assetpack/html_helpers.rb
@@ -197,8 +216,10 @@ files:
197
216
  - test/app/app/css_stylus/stylus.styl
198
217
  - test/app/app/images/background.jpg
199
218
  - test/app/app/images/email.png
219
+ - test/app/app/js/_ignoreme.js
200
220
  - test/app/app/js/hello.js
201
221
  - test/app/app/js/hi.coffee
222
+ - test/app/app/js/ugly.js
202
223
  - test/app/app/js_glob/a/b/c1/hello.js
203
224
  - test/app/app/js_glob/a/b/c2/hi.js
204
225
  - test/app/app/js_glob/a/b/c2/hola.js
@@ -209,6 +230,7 @@ files:
209
230
  - test/compressed_test.rb
210
231
  - test/glob_test.rb
211
232
  - test/helpers_test.rb
233
+ - test/ignore_test.rb
212
234
  - test/img_test.rb
213
235
  - test/local_file_test.rb
214
236
  - test/mime_type_test.rb
@@ -223,6 +245,7 @@ files:
223
245
  - test/template_cache_test.rb
224
246
  - test/test_helper.rb
225
247
  - test/tilt_test.rb
248
+ - test/uglifier_test.rb
226
249
  - test/unit_test.rb
227
250
  - test/yui_test.rb
228
251
  homepage: http://github.com/rstacruz/sinatra-assetpack