rack-sprockets 1.0.4 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/.gitignore +5 -0
  2. data/Gemfile +4 -0
  3. data/Gemfile.lock +47 -0
  4. data/README.rdoc +2 -2
  5. data/Rakefile +5 -60
  6. data/demos/yui_compressed/Gemfile +5 -0
  7. data/demos/yui_compressed/Gemfile.lock +19 -0
  8. data/demos/yui_compressed/REAME.rdoc +13 -0
  9. data/demos/yui_compressed/app.rb +17 -0
  10. data/demos/yui_compressed/app/javascripts/alert_one.js +4 -0
  11. data/demos/yui_compressed/app/javascripts/alert_two.js +4 -0
  12. data/demos/yui_compressed/app/javascripts/app.js +16 -0
  13. data/demos/yui_compressed/public/javascripts/app.js +1 -0
  14. data/demos/yui_compressed/public/javascripts/uncompressed_app.js +12 -0
  15. data/lib/rack/.rb +1 -0
  16. data/lib/rack/sprockets/request.rb +42 -24
  17. data/lib/rack/sprockets/source.rb +27 -27
  18. data/lib/rack/sprockets/version.rb +4 -12
  19. data/rack-sprockets.gemspec +29 -0
  20. data/test/app_helper.rb +25 -0
  21. data/test/config_test.rb +80 -0
  22. data/test/env.rb +9 -0
  23. data/test/fixtures/mock_options.rb +9 -0
  24. data/test/fixtures/sinatra/app.rb +9 -0
  25. data/test/fixtures/sinatra/app/javascripts/alert_one.js +2 -0
  26. data/test/fixtures/sinatra/app/javascripts/alert_two.js +2 -0
  27. data/test/fixtures/sinatra/app/javascripts/app.js +10 -0
  28. data/test/fixtures/sinatra/app/javascripts/app_compiled.js +12 -0
  29. data/test/fixtures/sinatra/app/javascripts/nested/dependency.js +2 -0
  30. data/test/fixtures/sinatra/app/javascripts/nested/thing.js +11 -0
  31. data/test/fixtures/sinatra/app/javascripts/nested/thing_compiled.js +14 -0
  32. data/test/helper.rb +80 -0
  33. data/test/options_test.rb +78 -0
  34. data/test/request_test.rb +141 -0
  35. data/test/response_test.rb +41 -0
  36. data/test/sinatra_test.rb +42 -0
  37. data/test/source_test.rb +163 -0
  38. metadata +103 -40
@@ -0,0 +1,5 @@
1
+ /pkg/
2
+ /doc/
3
+ /coverage/
4
+ *.log
5
+ *.bundle/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in rack-sprockets.gemspec
4
+ gemspec
@@ -0,0 +1,47 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rack-sprockets (1.0.4)
5
+ rack (~> 1.0)
6
+ sprockets (~> 1.0)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ json (1.5.1)
12
+ kelredd-useful (0.4.1)
13
+ json
14
+ leftright (0.9.0)
15
+ nokogiri (1.4.4)
16
+ rack (1.2.2)
17
+ rack-test (0.5.7)
18
+ rack (>= 1.0)
19
+ shoulda (2.11.3)
20
+ sinatra (1.2.1)
21
+ rack (~> 1.1)
22
+ tilt (>= 1.2.2, < 2.0)
23
+ sprockets (1.0.2)
24
+ test-belt (0.2.1)
25
+ kelredd-useful (~> 0.4.0)
26
+ leftright (~> 0.9.0)
27
+ shoulda (~> 2.11)
28
+ tilt (1.2.2)
29
+ webrat (0.7.3)
30
+ nokogiri (>= 1.2.0)
31
+ rack (>= 1.0)
32
+ rack-test (>= 0.5.3)
33
+ yui-compressor (0.9.4)
34
+
35
+ PLATFORMS
36
+ ruby
37
+
38
+ DEPENDENCIES
39
+ bundler (~> 1.0)
40
+ rack (~> 1.0)
41
+ rack-sprockets!
42
+ rack-test (>= 0.5.3)
43
+ sinatra (>= 0.9.4)
44
+ sprockets (~> 1.0)
45
+ test-belt (= 0.2.1)
46
+ webrat (>= 0.6.0)
47
+ yui-compressor (>= 0.9.1)
@@ -60,10 +60,10 @@ These are similar to sprockets options and, where applicable, map directly to a
60
60
  - The path where static files are located. Maps to the `:asset_root` Sprockets option.
61
61
 
62
62
  * :*source* ["app/javascripts"]
63
- - The path where Sprockets source files are located. Notice this does not map to the `:source_files` Sprockets option. It is assumed that any requested resource found in `:source` be treated as a Sprockets source file.
63
+ - The root path where Sprockets source resources are located. Notice this does not map to the `:source_files` Sprockets option. It is assumed that any requested resource found in `:source` be treated as a Sprockets source file.
64
64
 
65
65
  * :*hosted_at* ["/javascripts"]
66
- - The public hosted HTTP path for static javascripts files.
66
+ - The public hosted HTTP path for static javascript files.
67
67
 
68
68
  * :*load_path* [["app/javascripts/", "vendor/javascripts/"]]
69
69
  - An ordered array of directory names to search for dependencies in. Maps to the `:load_path` Sprockets option.
data/Rakefile CHANGED
@@ -1,62 +1,7 @@
1
- require 'rubygems'
2
- require 'rake/gempackagetask'
3
- require 'rake/testtask'
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
4
3
 
5
- require File.expand_path('../lib/rack/sprockets/version', __FILE__)
4
+ require 'test_belt/rake_tasks'
5
+ TestBelt::RakeTasks.for :test
6
6
 
7
- spec = Gem::Specification.new do |s|
8
- s.name = 'rack-sprockets'
9
- s.version = RackSprockets::Version.to_s
10
- s.has_rdoc = true
11
- s.extra_rdoc_files = %w(README.rdoc)
12
- s.rdoc_options = %w(--main README.rdoc)
13
- s.summary = "Sprockets javascript preprocessing for Rack apps."
14
- s.author = 'Kelly Redding'
15
- s.email = 'kelly@kelredd.com'
16
- s.homepage = 'http://github.com/kelredd/rack-sprockets'
17
- s.files = %w(README.rdoc Rakefile) + Dir.glob("{lib}/**/*")
18
- # s.executables = ['rack-sprockets']
19
-
20
- s.add_development_dependency("shoulda", [">= 2.10.0"])
21
- s.add_development_dependency("sinatra", [">= 0.9.4"])
22
- s.add_development_dependency("rack-test", [">= 0.5.3"])
23
- s.add_development_dependency("webrat", [">= 0.6.0"])
24
- s.add_development_dependency("yui-compressor", [">=0.9.1"])
25
-
26
- s.add_dependency("rack", [">= 0.4"])
27
- s.add_dependency("sprockets", [">= 1.0.0"])
28
- end
29
-
30
- Rake::GemPackageTask.new(spec) do |pkg|
31
- pkg.gem_spec = spec
32
- end
33
-
34
- Rake::TestTask.new do |t|
35
- t.libs << 'test'
36
- t.test_files = FileList["test/**/*_test.rb"]
37
- t.verbose = true
38
- end
39
-
40
- begin
41
- require 'rcov/rcovtask'
42
-
43
- Rcov::RcovTask.new(:coverage) do |t|
44
- t.libs = ['test']
45
- t.test_files = FileList["test/**/*_test.rb"]
46
- t.verbose = true
47
- t.rcov_opts = ['--text-report', "-x #{Gem.path}", '-x /Library/Ruby', '-x /usr/lib/ruby']
48
- end
49
-
50
- task :default => :coverage
51
-
52
- rescue LoadError
53
- warn "\n**** Install rcov (sudo gem install relevance-rcov) to get coverage stats ****\n"
54
- task :default => :test
55
- end
56
-
57
- desc 'Generate the gemspec to serve this gem'
58
- task :gemspec do
59
- file = File.dirname(__FILE__) + "/#{spec.name}.gemspec"
60
- File.open(file, 'w') {|f| f << spec.to_ruby }
61
- puts "Created gemspec: #{file}"
62
- end
7
+ task :default => :build
@@ -0,0 +1,5 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'sinatra'
4
+ gem 'rack-sprockets', '~>1.0.4', :require => "rack/sprockets"
5
+ gem 'yui-compressor'
@@ -0,0 +1,19 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ rack (1.2.1)
5
+ rack-sprockets (1.0.4)
6
+ rack (>= 0.4)
7
+ sprockets (>= 1.0.0)
8
+ sinatra (1.0)
9
+ rack (>= 1.0)
10
+ sprockets (1.0.2)
11
+ yui-compressor (0.9.1)
12
+
13
+ PLATFORMS
14
+ ruby
15
+
16
+ DEPENDENCIES
17
+ rack-sprockets (~> 1.0.4)
18
+ sinatra
19
+ yui-compressor
@@ -0,0 +1,13 @@
1
+ == YUI Compressor Rack Sprockets demo
2
+
3
+ This demo will use rack sprockets to define an /javascripts/app.js resource. To run and test this demo, do the following:
4
+
5
+ 1. Pull the latest rack-sprockets repo
6
+ 2. cd demos/yui_compressed
7
+ 3. bundle install
8
+ 4. ruby app.rb #starts up sinatra app on localhost:4567
9
+ 5. Browse to http://localhost:4567/javascripts/app.rb
10
+ 6. see a compressed js resource
11
+ 7. see a new cached file named app.js written to demos/yui-compressed/public/javascripts
12
+
13
+ Hope this helps as a working usage demo. This was written to help resolve issue #2: http://github.com/kelredd/rack-sprockets/issues/#issue/2
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.setup
4
+
5
+ require 'sinatra'
6
+ Bundler.require(:default)
7
+
8
+ # use the rack-sprockets middleware with default options:
9
+ # => http://github.com/kelredd/rack-sprockets --> README --> "Available Options" for details
10
+ use Rack::Sprockets
11
+
12
+ # configure rack-sprockets with custom configuration settings
13
+ # => http://github.com/kelredd/rack-sprockets --> README --> "Available Configurations" for details
14
+ Rack::Sprockets.configure do |config|
15
+ config.cache = true
16
+ config.compress = :yui
17
+ end
@@ -0,0 +1,4 @@
1
+ function one_message() {
2
+ var one_msg = 'alert one';
3
+ alert(one_msg);
4
+ }
@@ -0,0 +1,4 @@
1
+ function two_message() {
2
+ var two_msg = 'alert 2';
3
+ alert(two_msg);
4
+ }
@@ -0,0 +1,16 @@
1
+ //= require <alert_one>
2
+ //= require <alert_two>
3
+
4
+ function app_message() {
5
+ var app_msg = 'full app';
6
+ alert(app_msg);
7
+ }
8
+
9
+ function () {
10
+ var foo = {};
11
+ foo["bar"] = "baz";
12
+ }
13
+
14
+ one_message();
15
+ two_message();
16
+ app_message();
@@ -0,0 +1 @@
1
+ function one_message(){var a="alert one";alert(a)}function two_message(){var a="alert 2";alert(a)}function app_message(){var a="full app";alert(a)}function(){var a={};a.bar="baz"}one_message();two_message();app_message();
@@ -0,0 +1,12 @@
1
+ var one_message = 'alert one';
2
+ alert(one_message);
3
+ var two_message = 'alert 2';
4
+ alert(two_message);
5
+
6
+ var app_message = 'full app';
7
+ alert(app_message);
8
+
9
+ function () {
10
+ var foo = {};
11
+ foo["bar"] = "baz";
12
+ }
@@ -0,0 +1 @@
1
+ # require 'rack_sprockets//...'
@@ -11,7 +11,7 @@ module Rack::Sprockets
11
11
 
12
12
  class Request < Rack::Request
13
13
  include Rack::Sprockets::Options
14
-
14
+
15
15
  JS_PATH_FORMATS = ['.js']
16
16
 
17
17
  # The HTTP request method. This is the standard implementation of this
@@ -21,25 +21,43 @@ module Rack::Sprockets
21
21
  def request_method
22
22
  @env['REQUEST_METHOD']
23
23
  end
24
-
24
+
25
+ def http_accept
26
+ @env['HTTP_ACCEPT']
27
+ end
28
+
25
29
  def path_info
26
30
  @env['PATH_INFO']
27
31
  end
28
-
29
- def http_accept
30
- @env['HTTP_ACCEPT']
32
+
33
+ def hosted_at_option
34
+ # sanitized :hosted_at option
35
+ # remove any trailing '/'
36
+ # ensure single leading '/'
37
+ @hosted_at_option ||= options(:hosted_at).sub(/\/+$/, '').sub(/^\/*/, '/')
31
38
  end
32
-
33
- def path_resource_name
34
- File.basename(path_info, path_resource_format)
39
+
40
+ def path_info_resource
41
+ # sanitized path to the resource being requested
42
+ # ensure single leading '/'
43
+ # remove any resource format
44
+ # ex:
45
+ # '/something.js' => '/something'
46
+ # '/nested/something.js' => '/nested/something'
47
+ # '///something.js' => '/something'
48
+ # '/nested///something.js' => '/nested/something'
49
+ @path_info_resource ||= File.join(
50
+ File.dirname(path_info.gsub(/\/+/, '/')).sub(/^#{hosted_at_option}/, ''),
51
+ File.basename(path_info.gsub(/\/+/, '/'), path_info_format)
52
+ ).sub(/^\/*/, '/')
35
53
  end
36
-
37
- def path_resource_format
38
- File.extname(path_info)
54
+
55
+ def path_info_format
56
+ @path_info_format ||= File.extname(path_info.gsub(/\/+/, '/'))
39
57
  end
40
58
 
41
59
  def cache
42
- File.join(options(:root), options(:public), options(:hosted_at))
60
+ File.join(options(:root), options(:public), hosted_at_option)
43
61
  end
44
62
 
45
63
  # The Rack::Sprockets::Source that the request is for
@@ -55,36 +73,36 @@ module Rack::Sprockets
55
73
  :expand_paths => options(:expand_paths)
56
74
  }
57
75
  }
58
- Source.new(path_resource_name, source_opts)
76
+ Source.new(path_info_resource, source_opts)
59
77
  end
60
78
  end
61
79
 
62
80
  def for_js?
63
81
  (http_accept && http_accept.include?(Rack::Sprockets::MIME_TYPE)) ||
64
82
  (media_type && media_type.include?(Rack::Sprockets::MIME_TYPE )) ||
65
- JS_PATH_FORMATS.include?(path_resource_format)
83
+ JS_PATH_FORMATS.include?(path_info_format)
66
84
  end
67
85
 
68
86
  def hosted_at?
69
- File.basename(File.dirname(path_info)) == File.basename(options(:hosted_at))
87
+ path_info =~ /^#{hosted_at_option}/
70
88
  end
71
-
72
- def exists?
73
- File.exists?(File.join(cache, "#{path_resource_name}#{path_resource_format}"))
89
+
90
+ def cached?
91
+ File.exists?(File.join(cache, "#{path_info_resource}#{path_info_format}"))
74
92
  end
75
93
 
76
- # Determine if the request is for an existing Sprockets source file
94
+ # Determine if the request is for a non-cached existing Sprockets source file
77
95
  # This will be called on every request so speed is an issue
78
96
  # => first check if the request is a GET on a js resource in :hosted_at (fast)
79
- # => don't process if a file already exists in :hosted_at
97
+ # => don't process if a file has already been cached
80
98
  # => otherwise, check for sprockets source files that match the request (slow)
81
99
  def for_sprockets?
82
- get? &&
100
+ get? && # GET on js resource in :hosted_at (fast, check first)
83
101
  for_js? &&
84
102
  hosted_at? &&
85
- !exists? &&
86
- !source.files.empty?
103
+ !cached? && # resource not cached (little slower)
104
+ !source.files.empty? # there is source for the resource (slow, check last)
87
105
  end
88
-
106
+
89
107
  end
90
108
  end
@@ -10,7 +10,7 @@ end
10
10
  module Rack::Sprockets
11
11
 
12
12
  class Source
13
-
13
+
14
14
  PREFERRED_EXTENSIONS = [:js]
15
15
  SECRETARY_DEFAULTS = {
16
16
  :expand_paths => true
@@ -18,18 +18,18 @@ module Rack::Sprockets
18
18
  YUI_OPTS = {
19
19
  :munge => true
20
20
  }
21
-
22
- attr_reader :js_name
23
-
24
- def initialize(js_name, options={})
25
- @js_name = js_name
21
+
22
+ attr_reader :js_resource
23
+
24
+ def initialize(js_resource, options={})
25
+ @js_resource = js_resource.gsub(/^\/+/, '')
26
26
  @compress = options[:compress]
27
27
  @cache = options[:cache]
28
28
 
29
29
  @folder = get_required_path(options, :folder)
30
30
  @secretary = SECRETARY_DEFAULTS.merge(options[:secretary] || {})
31
31
  end
32
-
32
+
33
33
  def compress?
34
34
  !!@compress
35
35
  end
@@ -39,11 +39,11 @@ module Rack::Sprockets
39
39
  def cache
40
40
  @cache
41
41
  end
42
-
42
+
43
43
  def files
44
44
  @files ||= js_sources
45
- end
46
-
45
+ end
46
+
47
47
  def secretary
48
48
  @secretary_obj ||= Sprockets::Secretary.new(@secretary.merge({
49
49
  :source_files => files
@@ -53,7 +53,7 @@ module Rack::Sprockets
53
53
  def compiled
54
54
  @compiled ||= begin
55
55
  compiled_js = secretary.concatenation.to_s
56
-
56
+
57
57
  compiled_js = case @compress
58
58
  when :whitespace, true
59
59
  compiled_js.delete("\n")
@@ -67,52 +67,52 @@ module Rack::Sprockets
67
67
  compiled_js
68
68
  end
69
69
 
70
- if cache? && !File.exists?(cf = File.join(@cache, "#{@js_name}.js"))
71
- FileUtils.mkdir_p(@cache)
70
+ if cache? && !File.exists?(cf = File.join(@cache, "#{@js_resource}.js"))
71
+ FileUtils.mkdir_p(File.dirname(cf))
72
72
  File.open(cf, "w") do |file|
73
73
  file.write(compiled_js)
74
74
  end
75
75
  end
76
-
76
+
77
77
  compiled_js
78
78
  end
79
79
  end
80
80
  alias_method :to_js, :compiled
81
81
  alias_method :js, :compiled
82
-
82
+
83
83
  protected
84
-
84
+
85
85
  # Source files matching the js name
86
86
  def js_sources
87
- @js_sources ||= preferred_sources([*@js_name])
87
+ @js_sources ||= preferred_source_files([*@js_resource])
88
88
  end
89
-
89
+
90
90
  private
91
-
92
- # Given a list of file names, return a list of
93
- # existing source files with the corresponding names
91
+
92
+ # Given a list of file resources, return a list of
93
+ # existing source files with the corresponding resource names
94
94
  # honoring the preferred extension list
95
- def preferred_sources(file_names)
96
- file_names.collect do |name|
95
+ def preferred_source_files(file_resources)
96
+ file_resources.collect do |resource|
97
97
  PREFERRED_EXTENSIONS.inject(nil) do |source_file, extension|
98
98
  source_file || begin
99
- path = File.join(@folder, "#{name}.#{extension}")
99
+ path = File.join(@folder, "#{resource}.#{extension}")
100
100
  File.exists?(path) ? path : nil
101
101
  end
102
102
  end
103
103
  end.compact
104
104
  end
105
-
105
+
106
106
  def get_required_path(options, path_key)
107
107
  unless options.has_key?(path_key)
108
108
  raise(ArgumentError, "no :#{path_key} option specified")
109
109
  end
110
110
  unless File.exists?(options[path_key])
111
- raise(ArgumentError, "the :#{path_key} ('#{options[path_key]}') does not exist")
111
+ raise(ArgumentError, "the :#{path_key} ('#{options[path_key]}') does not exist")
112
112
  end
113
113
  options[path_key]
114
114
  end
115
115
 
116
116
  end
117
-
117
+
118
118
  end