rack-sprockets 0.1.0
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/README.rdoc +116 -0
- data/Rakefile +61 -0
- data/lib/rack/sprockets.rb +51 -0
- data/lib/rack/sprockets/base.rb +67 -0
- data/lib/rack/sprockets/config.rb +40 -0
- data/lib/rack/sprockets/options.rb +131 -0
- data/lib/rack/sprockets/request.rb +78 -0
- data/lib/rack/sprockets/response.rb +45 -0
- data/lib/rack/sprockets/source.rb +118 -0
- data/lib/rack/sprockets/version.rb +13 -0
- metadata +124 -0
data/README.rdoc
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
= Rack::Sprockets
|
2
|
+
|
3
|
+
== Description
|
4
|
+
|
5
|
+
Sprockets javascript preprocessing for Rack apps.
|
6
|
+
|
7
|
+
== Installation
|
8
|
+
|
9
|
+
gem install rack-sprockets
|
10
|
+
|
11
|
+
# optional, for compression
|
12
|
+
gem install yui-compressor
|
13
|
+
|
14
|
+
== Basic Usage
|
15
|
+
|
16
|
+
Rack::Sprockets is implemented as a piece of Rack middleware and can be used with
|
17
|
+
any Rack-based application. If your application includes a rackup (`.ru`) file
|
18
|
+
or uses Rack::Builder to construct the application pipeline, simply require
|
19
|
+
and use as follows:
|
20
|
+
|
21
|
+
require 'rack/sprockets'
|
22
|
+
|
23
|
+
# optional - use as necessary
|
24
|
+
Rack::Sprockets.configure do |config|
|
25
|
+
config.compress = true
|
26
|
+
# other configs ...
|
27
|
+
end
|
28
|
+
|
29
|
+
use Rack::Sprockets,
|
30
|
+
:load_path => 'app/scripts',
|
31
|
+
:hosted_at => '/'
|
32
|
+
# additional options ...
|
33
|
+
|
34
|
+
run app
|
35
|
+
|
36
|
+
== Using with Rails
|
37
|
+
|
38
|
+
Add this to your `config/environment.rb`:
|
39
|
+
|
40
|
+
config.middleware.use "Rack::Sprockets"
|
41
|
+
|
42
|
+
Add any configs in an initializer (optional - use as necessary):
|
43
|
+
|
44
|
+
Rack::Sprockets.configure do |config|
|
45
|
+
config.cache = true
|
46
|
+
# additional configs ...
|
47
|
+
end
|
48
|
+
|
49
|
+
You should now see `Rack::Sprockets` listed in the middleware pipeline:
|
50
|
+
|
51
|
+
rake middleware
|
52
|
+
|
53
|
+
== Available Options
|
54
|
+
These are similar to sprockets options and, where applicable, map directly to a corresponding Sprockets option.
|
55
|
+
|
56
|
+
* :*root* ['.']
|
57
|
+
- The app root. The reference point for the source and public options. Maps to the `:root` Sprockets option.
|
58
|
+
|
59
|
+
* :*public* ['public']
|
60
|
+
- The path where static files are located. Maps to the `:asset_root` Sprockets option.
|
61
|
+
|
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.
|
64
|
+
|
65
|
+
* :*hosted_at* ["/javascripts"]
|
66
|
+
- The public hosted HTTP path for static javascripts files.
|
67
|
+
|
68
|
+
* :*load_path* [["app/javascripts/", "vendor/javascripts/"]]
|
69
|
+
- An ordered array of directory names to search for dependencies in. Maps to the `:load_path` Sprockets option.
|
70
|
+
|
71
|
+
* :*expand_paths* [true]
|
72
|
+
- Whether or not to expand filenames according to shell glob rules. Maps to the `:expand_paths` Sprockets option.
|
73
|
+
|
74
|
+
== Available Configurations
|
75
|
+
* .*cache* [false]
|
76
|
+
- Whether or not to cache the concatenation output to a corresponding static file.
|
77
|
+
|
78
|
+
* .*compress* [false]
|
79
|
+
- Whether or not to apply compression to the concatenation output - uses YUI Compressor if available or will remove extraneous whitespace if not.
|
80
|
+
|
81
|
+
== Links
|
82
|
+
|
83
|
+
* *GitHub*
|
84
|
+
- http://github.com/kelredd/rack-sprockets
|
85
|
+
|
86
|
+
* *Sprockets*
|
87
|
+
- http://getsprockets.org
|
88
|
+
|
89
|
+
* *Yui* *Compressor*
|
90
|
+
- http://github.com/sstephenson/ruby-yui-compressor
|
91
|
+
- http://developer.yahoo.com/yui/compressor
|
92
|
+
|
93
|
+
== License
|
94
|
+
|
95
|
+
Copyright (c) 2010 Kelly Redding (mailto:kelly@kelredd.com)
|
96
|
+
|
97
|
+
Permission is hereby granted, free of charge, to any person
|
98
|
+
obtaining a copy of this software and associated documentation
|
99
|
+
files (the "Software"), to deal in the Software without
|
100
|
+
restriction, including without limitation the rights to use,
|
101
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
102
|
+
copies of the Software, and to permit persons to whom the
|
103
|
+
Software is furnished to do so, subject to the following
|
104
|
+
conditions:
|
105
|
+
|
106
|
+
The above copyright notice and this permission notice shall be
|
107
|
+
included in all copies or substantial portions of the Software.
|
108
|
+
|
109
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
110
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
111
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
112
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
113
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
114
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
115
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
116
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
require 'lib/rack/sprockets/version'
|
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
|
+
|
25
|
+
s.add_dependency("rack", [">= 0.4"])
|
26
|
+
s.add_dependency("sprockets", [">= 1.0.0"])
|
27
|
+
end
|
28
|
+
|
29
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
30
|
+
pkg.gem_spec = spec
|
31
|
+
end
|
32
|
+
|
33
|
+
Rake::TestTask.new do |t|
|
34
|
+
t.libs << 'test'
|
35
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
36
|
+
t.verbose = true
|
37
|
+
end
|
38
|
+
|
39
|
+
begin
|
40
|
+
require 'rcov/rcovtask'
|
41
|
+
|
42
|
+
Rcov::RcovTask.new(:coverage) do |t|
|
43
|
+
t.libs = ['test']
|
44
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
45
|
+
t.verbose = true
|
46
|
+
t.rcov_opts = ['--text-report', "-x #{Gem.path}", '-x /Library/Ruby', '-x /usr/lib/ruby']
|
47
|
+
end
|
48
|
+
|
49
|
+
task :default => :coverage
|
50
|
+
|
51
|
+
rescue LoadError
|
52
|
+
warn "\n**** Install rcov (sudo gem install relevance-rcov) to get coverage stats ****\n"
|
53
|
+
task :default => :test
|
54
|
+
end
|
55
|
+
|
56
|
+
desc 'Generate the gemspec to serve this gem'
|
57
|
+
task :gemspec do
|
58
|
+
file = File.dirname(__FILE__) + "/#{spec.name}.gemspec"
|
59
|
+
File.open(file, 'w') {|f| f << spec.to_ruby }
|
60
|
+
puts "Created gemspec: #{file}"
|
61
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'rack'
|
2
|
+
require 'rack/sprockets/config'
|
3
|
+
require 'rack/sprockets/options'
|
4
|
+
require 'rack/sprockets/source'
|
5
|
+
require 'rack/sprockets/base'
|
6
|
+
require 'rack/sprockets/request'
|
7
|
+
require 'rack/sprockets/response'
|
8
|
+
|
9
|
+
# === Usage
|
10
|
+
#
|
11
|
+
# Create with default configs:
|
12
|
+
# require 'rack/sprockets'
|
13
|
+
# Rack::Sprockets.new(app, :compress => true)
|
14
|
+
#
|
15
|
+
# Within a rackup file (or with Rack::Builder):
|
16
|
+
# require 'rack/sprockets'
|
17
|
+
#
|
18
|
+
# use Rack::Sprockets,
|
19
|
+
# :source => 'app/scripts'
|
20
|
+
# :compress => true
|
21
|
+
#
|
22
|
+
# run app
|
23
|
+
|
24
|
+
module Rack::Sprockets
|
25
|
+
MIME_TYPE = "text/javascript"
|
26
|
+
@@config = Config.new
|
27
|
+
|
28
|
+
class << self
|
29
|
+
|
30
|
+
# Configuration accessors for Rack::Sprockets
|
31
|
+
# (see config.rb for details)
|
32
|
+
def configure
|
33
|
+
yield @@config if block_given?
|
34
|
+
end
|
35
|
+
def config
|
36
|
+
@@config
|
37
|
+
end
|
38
|
+
def config=(value)
|
39
|
+
@@config = value
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
# Create a new Rack::Sprockets middleware component
|
45
|
+
# => the +options+ Hash can be used to specify default option values
|
46
|
+
# => (see Rack::Sprockets::Options for possible key/values)
|
47
|
+
def self.new(app, options={}, &block)
|
48
|
+
Base.new(app, options, &block)
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'rack/sprockets/options'
|
2
|
+
require 'rack/sprockets/request'
|
3
|
+
require 'rack/sprockets/response'
|
4
|
+
|
5
|
+
module Rack::Sprockets
|
6
|
+
class Base
|
7
|
+
include Rack::Sprockets::Options
|
8
|
+
|
9
|
+
def initialize(app, options={})
|
10
|
+
@app = app
|
11
|
+
initialize_options options
|
12
|
+
yield self if block_given?
|
13
|
+
validate_options
|
14
|
+
end
|
15
|
+
|
16
|
+
# The Rack call interface. The receiver acts as a prototype and runs
|
17
|
+
# each request in a clone object unless the +rack.run_once+ variable is
|
18
|
+
# set in the environment.
|
19
|
+
def call(env)
|
20
|
+
if env['rack.run_once']
|
21
|
+
call! env
|
22
|
+
else
|
23
|
+
clone.call! env
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# The real Rack call interface.
|
28
|
+
# if Sprockets JS is being requested, this is an endpoint:
|
29
|
+
# => generate the compiled javascripts
|
30
|
+
# => respond appropriately
|
31
|
+
# Otherwise, call on up to the app as normal
|
32
|
+
def call!(env)
|
33
|
+
@default_options.each { |k,v| env[k] ||= v }
|
34
|
+
@env = env
|
35
|
+
|
36
|
+
if (@request = Request.new(@env.dup.freeze)).for_sprockets?
|
37
|
+
Response.new(@env.dup.freeze, @request.source.to_js).to_rack
|
38
|
+
else
|
39
|
+
@app.call(env)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def validate_options
|
46
|
+
# ensure a root path is specified and does exists
|
47
|
+
unless options.has_key?(option_name(:root)) and !options(:root).nil?
|
48
|
+
raise(ArgumentError, "no :root option set")
|
49
|
+
end
|
50
|
+
unless File.exists?(options(:root))
|
51
|
+
raise(ArgumentError, "the :root path ('#{options(:root)}') does not exist")
|
52
|
+
end
|
53
|
+
|
54
|
+
set :root, File.expand_path(options(:root))
|
55
|
+
|
56
|
+
# ensure a source path is specified and does exists
|
57
|
+
unless options.has_key?(option_name(:source)) and !options(:source).nil?
|
58
|
+
raise(ArgumentError, "no :source option set")
|
59
|
+
end
|
60
|
+
source_path = File.join(options(:root), options(:source))
|
61
|
+
unless File.exists?(source_path)
|
62
|
+
raise(ArgumentError, "the :source path ('#{source_path}') does not exist")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Rack::Sprockets
|
2
|
+
|
3
|
+
# Handles configuration for Rack::Sprockets
|
4
|
+
# Available config settings:
|
5
|
+
# :cache
|
6
|
+
# whether to cache the compilation output to
|
7
|
+
# a corresponding static file. Also determines
|
8
|
+
# what value config#combinations(:key) returns
|
9
|
+
# :compress
|
10
|
+
# Whether or not to apply compression to the
|
11
|
+
# concatenation output - uses YUI Compressor
|
12
|
+
# if available or will remove extraneous
|
13
|
+
# whitespace if not.
|
14
|
+
|
15
|
+
class Config
|
16
|
+
|
17
|
+
ATTRIBUTES = [:cache, :compress]
|
18
|
+
attr_accessor *ATTRIBUTES
|
19
|
+
|
20
|
+
DEFAULTS = {
|
21
|
+
:cache => false,
|
22
|
+
:compress => false
|
23
|
+
}
|
24
|
+
|
25
|
+
def initialize(settings={})
|
26
|
+
ATTRIBUTES.each do |a|
|
27
|
+
instance_variable_set("@#{a}", settings[a] || DEFAULTS[a])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def cache?
|
32
|
+
!!@cache
|
33
|
+
end
|
34
|
+
|
35
|
+
def compress?
|
36
|
+
!!@compress
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module Rack::Sprockets
|
2
|
+
module Options
|
3
|
+
|
4
|
+
# Handles options for Rack::Sprockets
|
5
|
+
# Available options:
|
6
|
+
# => root
|
7
|
+
# The app root. The reference point for
|
8
|
+
# the source and public options. Maps to
|
9
|
+
# the `:root` Sprockets option.
|
10
|
+
# => public
|
11
|
+
# The path where static files are located.
|
12
|
+
# Maps to the `:asset_root` Sprockets option.
|
13
|
+
# => source
|
14
|
+
# The path where Sprockets source files are
|
15
|
+
# located. Notice this does not map to the
|
16
|
+
# `:source_files` Sprockets option. It is
|
17
|
+
# assumed that any requested resource found
|
18
|
+
# in `:source` be treated as a Sprockets
|
19
|
+
# source file.
|
20
|
+
# => hosted_at
|
21
|
+
# The public hosted HTTP path for static
|
22
|
+
# javascripts files.
|
23
|
+
# => load_path
|
24
|
+
# An ordered array of directory names to
|
25
|
+
# search for dependencies in. Maps to the
|
26
|
+
# `:load_path` Sprockets option.
|
27
|
+
# => expand_paths
|
28
|
+
# Whether or not to expand filenames according
|
29
|
+
# to shell glob rules. Maps to the
|
30
|
+
# `:expand_paths` Sprockets option.
|
31
|
+
|
32
|
+
RACK_ENV_NS = "rack-sprockets"
|
33
|
+
COLLECTION_OPTS = ["#{RACK_ENV_NS}.load_path"]
|
34
|
+
|
35
|
+
module ClassMethods
|
36
|
+
|
37
|
+
def defaults
|
38
|
+
{
|
39
|
+
option_name(:root) => ".",
|
40
|
+
option_name(:public) => 'public',
|
41
|
+
option_name(:source) => 'app/javascripts',
|
42
|
+
option_name(:hosted_at) => '/javascripts',
|
43
|
+
option_name(:load_path) => [
|
44
|
+
"app/javascripts/",
|
45
|
+
"vendor/javascripts/"
|
46
|
+
],
|
47
|
+
option_name(:expand_paths) => true
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
# Rack::Sprockets uses the Rack Environment to store option values. All options
|
52
|
+
# are stored in the Rack Environment as "<RACK_ENV_PREFIX>.<option>", where
|
53
|
+
# <option> is the option name.
|
54
|
+
def option_name(key)
|
55
|
+
case key
|
56
|
+
when Symbol ; "#{RACK_ENV_NS}.#{key}"
|
57
|
+
when String ; key
|
58
|
+
else raise ArgumentError
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
module InstanceMethods
|
65
|
+
|
66
|
+
# Rack::Sprockets uses the Rack Environment to store option values. All options
|
67
|
+
# are stored in the Rack Environment as "<RACK_ENV_PREFIX>.<option>", where
|
68
|
+
# <option> is the option name.
|
69
|
+
def option_name(key)
|
70
|
+
self.class.option_name(key)
|
71
|
+
end
|
72
|
+
|
73
|
+
# The underlying options Hash. During initialization (or outside of a
|
74
|
+
# request), this is a default values Hash. During a request, this is the
|
75
|
+
# Rack environment Hash. The default values Hash is merged in underneath
|
76
|
+
# the Rack environment before each request is processed.
|
77
|
+
# => if a key is passed, the option value for the key is returned
|
78
|
+
def options(key=nil)
|
79
|
+
if key
|
80
|
+
(@env || @default_options)[option_name(key)]
|
81
|
+
else
|
82
|
+
@env || @default_options
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Set multiple options at once.
|
87
|
+
def options=(hash={})
|
88
|
+
hash.each { |key,value| write_option(key, value) }
|
89
|
+
end
|
90
|
+
|
91
|
+
# Set an option. When +option+ is a Symbol, it is set in the Rack
|
92
|
+
# Environment as "rack-cache.option". When +option+ is a String, it
|
93
|
+
# exactly as specified. The +option+ argument may also be a Hash in
|
94
|
+
# which case each key/value pair is merged into the environment as if
|
95
|
+
# the #set method were called on each.
|
96
|
+
def set(option, value=nil)
|
97
|
+
if value.nil?
|
98
|
+
self.options = option.to_hash
|
99
|
+
else
|
100
|
+
write_option option, value
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
def initialize_options(options={})
|
107
|
+
@default_options = self.class.defaults
|
108
|
+
self.options = options
|
109
|
+
end
|
110
|
+
|
111
|
+
def read_option(key)
|
112
|
+
options[option_name(key)]
|
113
|
+
end
|
114
|
+
|
115
|
+
def write_option(key, value)
|
116
|
+
if COLLECTION_OPTS.include?(opt_name = option_name(key))
|
117
|
+
options[opt_name] = [*value]
|
118
|
+
else
|
119
|
+
options[opt_name] = value
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.included(receiver)
|
126
|
+
receiver.extend ClassMethods
|
127
|
+
receiver.send :include, InstanceMethods
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'rack/request'
|
2
|
+
require 'rack/sprockets'
|
3
|
+
require 'rack/sprockets/options'
|
4
|
+
require 'rack/sprockets/source'
|
5
|
+
|
6
|
+
module Rack::Sprockets
|
7
|
+
|
8
|
+
# Provides access to the HTTP request.
|
9
|
+
# Request objects respond to everything defined by Rack::Request
|
10
|
+
# as well as some additional convenience methods defined here
|
11
|
+
|
12
|
+
class Request < Rack::Request
|
13
|
+
include Rack::Sprockets::Options
|
14
|
+
|
15
|
+
JS_PATH_FORMATS = ['.js']
|
16
|
+
|
17
|
+
# The HTTP request method. This is the standard implementation of this
|
18
|
+
# method but is respecified here due to libraries that attempt to modify
|
19
|
+
# the behavior to respect POST tunnel method specifiers. We always want
|
20
|
+
# the real request method.
|
21
|
+
def request_method
|
22
|
+
@env['REQUEST_METHOD']
|
23
|
+
end
|
24
|
+
|
25
|
+
def path_info
|
26
|
+
@env['PATH_INFO']
|
27
|
+
end
|
28
|
+
|
29
|
+
def http_accept
|
30
|
+
@env['HTTP_ACCEPT']
|
31
|
+
end
|
32
|
+
|
33
|
+
def path_resource_name
|
34
|
+
File.basename(path_info, path_resource_format)
|
35
|
+
end
|
36
|
+
|
37
|
+
def path_resource_format
|
38
|
+
File.extname(path_info)
|
39
|
+
end
|
40
|
+
|
41
|
+
# The Rack::Sprockets::Source that the request is for
|
42
|
+
def source
|
43
|
+
@source ||= begin
|
44
|
+
cache = if Rack::Sprockets.config.cache?
|
45
|
+
File.join(options(:root), options(:public), options(:hosted_at))
|
46
|
+
else
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
source_opts = {
|
50
|
+
:folder => File.join(options(:root), options(:source)),
|
51
|
+
:cache => cache,
|
52
|
+
:compress => Rack::Sprockets.config.compress,
|
53
|
+
:secretary => {
|
54
|
+
:root => options(:root),
|
55
|
+
:load_path => options(:load_path),
|
56
|
+
:expand_paths => options(:expand_paths)
|
57
|
+
}
|
58
|
+
}
|
59
|
+
Source.new(path_resource_name, source_opts)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def for_js?
|
64
|
+
(http_accept && http_accept.include?(Rack::Sprockets::MIME_TYPE)) ||
|
65
|
+
(media_type && media_type.include?(Rack::Sprockets::MIME_TYPE )) ||
|
66
|
+
JS_PATH_FORMATS.include?(path_resource_format)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Determine if the request is for an existing Sprockets source file
|
70
|
+
# This will be called on every request so speed is an issue
|
71
|
+
# => first check if the request is a GET on a js resource (fast)
|
72
|
+
# => then check for sprockets source files that match the request (slow)
|
73
|
+
def for_sprockets?
|
74
|
+
get? && for_js? && !source.files.empty?
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'rack/response'
|
2
|
+
require 'rack/utils'
|
3
|
+
|
4
|
+
module Rack::Sprockets
|
5
|
+
|
6
|
+
# Given some generated js, mimicks a Rack::Response
|
7
|
+
# => call to_rack to build standard rack response parameters
|
8
|
+
class Response
|
9
|
+
include Rack::Sprockets::Options
|
10
|
+
include Rack::Response::Helpers
|
11
|
+
|
12
|
+
# Rack response tuple accessors.
|
13
|
+
attr_accessor :status, :headers, :body
|
14
|
+
|
15
|
+
class << self
|
16
|
+
|
17
|
+
# Calculate appropriate content_length
|
18
|
+
def content_length(body)
|
19
|
+
if body.respond_to?(:bytesize)
|
20
|
+
body.bytesize
|
21
|
+
else
|
22
|
+
body.size
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
# Create a Response instance given the env
|
29
|
+
# and some generated js.
|
30
|
+
def initialize(env, js)
|
31
|
+
@env = env
|
32
|
+
@body = js
|
33
|
+
@status = 200 # OK
|
34
|
+
@headers = Rack::Utils::HeaderHash.new
|
35
|
+
|
36
|
+
headers["Content-Type"] = Rack::Sprockets::MIME_TYPE
|
37
|
+
headers["Content-Length"] = self.class.content_length(body).to_s
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_rack
|
41
|
+
[status, headers.to_hash, body]
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'sprockets'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require "yui/compressor"
|
5
|
+
rescue LoadError
|
6
|
+
# only error about missing yui compressor if
|
7
|
+
# :yui compression is requested
|
8
|
+
end
|
9
|
+
|
10
|
+
module Rack::Sprockets
|
11
|
+
|
12
|
+
class Source
|
13
|
+
|
14
|
+
PREFERRED_EXTENSIONS = [:js]
|
15
|
+
SECRETARY_DEFAULTS = {
|
16
|
+
:expand_paths => true
|
17
|
+
}
|
18
|
+
YUI_OPTS = {
|
19
|
+
:munge => true
|
20
|
+
}
|
21
|
+
|
22
|
+
attr_reader :js_name
|
23
|
+
|
24
|
+
def initialize(js_name, options={})
|
25
|
+
@js_name = js_name
|
26
|
+
@compress = options[:compress]
|
27
|
+
@cache = options[:cache]
|
28
|
+
|
29
|
+
@folder = get_required_path(options, :folder)
|
30
|
+
@secretary = SECRETARY_DEFAULTS.merge(options[:secretary] || {})
|
31
|
+
end
|
32
|
+
|
33
|
+
def compress?
|
34
|
+
!!@compress
|
35
|
+
end
|
36
|
+
def cache?
|
37
|
+
!@cache.nil?
|
38
|
+
end
|
39
|
+
def cache
|
40
|
+
@cache
|
41
|
+
end
|
42
|
+
|
43
|
+
def files
|
44
|
+
@files ||= js_sources
|
45
|
+
end
|
46
|
+
|
47
|
+
def secretary
|
48
|
+
@secretary_obj ||= Sprockets::Secretary.new(@secretary.merge({
|
49
|
+
:source_files => files
|
50
|
+
}))
|
51
|
+
end
|
52
|
+
|
53
|
+
def compiled
|
54
|
+
@compiled ||= begin
|
55
|
+
compiled_js = secretary.concatenation.to_s
|
56
|
+
|
57
|
+
compiled_js = case @compress
|
58
|
+
when :whitespace
|
59
|
+
compiled_js.delete("\n")
|
60
|
+
when :yui
|
61
|
+
if defined?(YUI::JavaScriptCompressor)
|
62
|
+
YUI::JavaScriptCompressor.new(YUI_OPTS).compress(compiled_js)
|
63
|
+
else
|
64
|
+
raise LoadError, "YUI::JavaScriptCompressor is not available. Install it with: gem install yui-compressor"
|
65
|
+
end
|
66
|
+
else
|
67
|
+
compiled_js
|
68
|
+
end
|
69
|
+
|
70
|
+
if cache? && !File.exists?(cf = File.join(@cache, "#{@js_name}.js"))
|
71
|
+
FileUtils.mkdir_p(@cache)
|
72
|
+
File.open(cf, "w") do |file|
|
73
|
+
file.write(compiled_js)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
compiled_js
|
78
|
+
end
|
79
|
+
end
|
80
|
+
alias_method :to_js, :compiled
|
81
|
+
alias_method :js, :compiled
|
82
|
+
|
83
|
+
protected
|
84
|
+
|
85
|
+
# Source files matching the js name
|
86
|
+
def js_sources
|
87
|
+
@js_sources ||= preferred_sources([*@js_name])
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
# Given a list of file names, return a list of
|
93
|
+
# existing source files with the corresponding names
|
94
|
+
# honoring the preferred extension list
|
95
|
+
def preferred_sources(file_names)
|
96
|
+
file_names.collect do |name|
|
97
|
+
PREFERRED_EXTENSIONS.inject(nil) do |source_file, extension|
|
98
|
+
source_file || begin
|
99
|
+
path = File.join(@folder, "#{name}.#{extension}")
|
100
|
+
File.exists?(path) ? path : nil
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end.compact
|
104
|
+
end
|
105
|
+
|
106
|
+
def get_required_path(options, path_key)
|
107
|
+
unless options.has_key?(path_key)
|
108
|
+
raise(ArgumentError, "no :#{path_key} option specified")
|
109
|
+
end
|
110
|
+
unless File.exists?(options[path_key])
|
111
|
+
raise(ArgumentError, "the :#{path_key} ('#{options[path_key]}') does not exist")
|
112
|
+
end
|
113
|
+
options[path_key]
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
metadata
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack-sprockets
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kelly Redding
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-02-14 00:00:00 -06:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: shoulda
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 2.10.0
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: sinatra
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.9.4
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rack-test
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.5.3
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: webrat
|
47
|
+
type: :development
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.6.0
|
54
|
+
version:
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rack
|
57
|
+
type: :runtime
|
58
|
+
version_requirement:
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: "0.4"
|
64
|
+
version:
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
name: sprockets
|
67
|
+
type: :runtime
|
68
|
+
version_requirement:
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: 1.0.0
|
74
|
+
version:
|
75
|
+
description:
|
76
|
+
email: kelly@kelredd.com
|
77
|
+
executables: []
|
78
|
+
|
79
|
+
extensions: []
|
80
|
+
|
81
|
+
extra_rdoc_files:
|
82
|
+
- README.rdoc
|
83
|
+
files:
|
84
|
+
- README.rdoc
|
85
|
+
- Rakefile
|
86
|
+
- lib/rack/sprockets/base.rb
|
87
|
+
- lib/rack/sprockets/config.rb
|
88
|
+
- lib/rack/sprockets/options.rb
|
89
|
+
- lib/rack/sprockets/request.rb
|
90
|
+
- lib/rack/sprockets/response.rb
|
91
|
+
- lib/rack/sprockets/source.rb
|
92
|
+
- lib/rack/sprockets/version.rb
|
93
|
+
- lib/rack/sprockets.rb
|
94
|
+
has_rdoc: true
|
95
|
+
homepage: http://github.com/kelredd/rack-sprockets
|
96
|
+
licenses: []
|
97
|
+
|
98
|
+
post_install_message:
|
99
|
+
rdoc_options:
|
100
|
+
- --main
|
101
|
+
- README.rdoc
|
102
|
+
require_paths:
|
103
|
+
- lib
|
104
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: "0"
|
109
|
+
version:
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: "0"
|
115
|
+
version:
|
116
|
+
requirements: []
|
117
|
+
|
118
|
+
rubyforge_project:
|
119
|
+
rubygems_version: 1.3.5
|
120
|
+
signing_key:
|
121
|
+
specification_version: 3
|
122
|
+
summary: Sprockets javascript preprocessing for Rack apps.
|
123
|
+
test_files: []
|
124
|
+
|