sinatra-sprockets-ext 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +47 -0
- data/Rakefile +2 -0
- data/lib/sinatra/sprockets/asset_paths.rb +134 -0
- data/lib/sinatra/sprockets/configuration.rb +28 -0
- data/lib/sinatra/sprockets/helpers.rb +78 -0
- data/lib/sinatra/sprockets/static_compiler.rb +61 -0
- data/lib/sinatra/sprockets/version.rb +5 -0
- data/lib/sinatra/sprockets.rb +41 -0
- data/sinatra-sprockets.gemspec +19 -0
- metadata +74 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Andrew Marshall
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# Sinatra::Sprockets
|
2
|
+
|
3
|
+
Sinatra extension for Sprockets integration.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'sinatra-sprockets-ext', :require => 'sinatra/sprockets'
|
10
|
+
|
11
|
+
Currently requires 1.9 (1.8 is near end-of-life anyway).
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
Register the plugin in your `app.rb`:
|
16
|
+
|
17
|
+
register Sinatra::Sprockets
|
18
|
+
|
19
|
+
In your `config.ru`, add a mapping for Sprockets:
|
20
|
+
|
21
|
+
map "/#{Sinatra::Sprockets.config.prefix}" do
|
22
|
+
run Sinatra::Sprockets.environment
|
23
|
+
end
|
24
|
+
|
25
|
+
Optionally configure as needed. Configuration is similar to Rails's Asset Pipeline.
|
26
|
+
Below is an example configuration with some options showing the default values:
|
27
|
+
|
28
|
+
Sinatra::Sprockets.configure do |config|
|
29
|
+
config.compile = false # On-the-fly compilation
|
30
|
+
config.compress = false # Compress assets
|
31
|
+
config.digest = false # Append a digest to URLs
|
32
|
+
config.css_compressor = false # CSS compressor instance
|
33
|
+
config.js_compressor = false # JS compressor instance
|
34
|
+
end
|
35
|
+
|
36
|
+
All options and their defaults are shown in `lib/sinatra-sprockets/configuration.rb`.
|
37
|
+
|
38
|
+
You'll also get helper functions that will be familiar to those who use Rails:
|
39
|
+
|
40
|
+
- `javascript_include_tag :asset_name`
|
41
|
+
- `stylesheet_link_tag :asset_name`
|
42
|
+
- `asset_path :asset_name`
|
43
|
+
|
44
|
+
## Credits & License
|
45
|
+
|
46
|
+
Copyright ©2012 J. Andrew Marshall. All rights reserved.
|
47
|
+
License is available in the LICENSE file.
|
data/Rakefile
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
module Sinatra::Sprockets
|
2
|
+
module Helpers
|
3
|
+
class AssetPaths
|
4
|
+
class AssetNotPrecompiledError < StandardError; end
|
5
|
+
|
6
|
+
def initialize config
|
7
|
+
@config = config
|
8
|
+
end
|
9
|
+
|
10
|
+
def asset_for(source, ext)
|
11
|
+
source = source.to_s
|
12
|
+
return nil if is_uri?(source)
|
13
|
+
source = rewrite_extension(source, nil, ext)
|
14
|
+
asset_environment[source]
|
15
|
+
rescue Sprockets::FileOutsidePaths
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def digest_for(logical_path)
|
20
|
+
if @config.digest && @config.digests && (digest = @config.digests[logical_path])
|
21
|
+
return digest
|
22
|
+
end
|
23
|
+
|
24
|
+
if @config.compile
|
25
|
+
if @config.digest && asset = asset_environment[logical_path]
|
26
|
+
return asset.digest_path
|
27
|
+
end
|
28
|
+
return logical_path
|
29
|
+
else
|
30
|
+
raise AssetNotPrecompiledError.new("#{logical_path} isn't precompiled")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def rewrite_asset_path(source, dir, options = {})
|
35
|
+
if source[0] == ?/
|
36
|
+
source
|
37
|
+
else
|
38
|
+
source = digest_for(source) unless options[:digest] == false
|
39
|
+
source = File.join(dir, source)
|
40
|
+
source = "/#{source}" unless source =~ /^\//
|
41
|
+
source
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def rewrite_extension(source, dir, ext)
|
46
|
+
if ext && File.extname(source) != ".#{ext}"
|
47
|
+
"#{source}.#{ext}"
|
48
|
+
else
|
49
|
+
source
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def compute_public_path(source, dir, options = {})
|
54
|
+
source = source.to_s
|
55
|
+
unless is_uri?(source)
|
56
|
+
source = rewrite_extension(source, dir, options[:ext]) if options[:ext]
|
57
|
+
source = rewrite_asset_path(source, dir, options)
|
58
|
+
source = rewrite_relative_url_root(source, @config.relative_url_root)
|
59
|
+
source = rewrite_host_and_protocol(source, options[:protocol])
|
60
|
+
end
|
61
|
+
source
|
62
|
+
end
|
63
|
+
|
64
|
+
def is_uri?(path)
|
65
|
+
path =~ %r{^[-a-z]+://|^cid:|^//}
|
66
|
+
end
|
67
|
+
|
68
|
+
def rewrite_host_and_protocol(source, protocol = nil)
|
69
|
+
host = compute_asset_host(source)
|
70
|
+
if host && !is_uri?(host)
|
71
|
+
if (protocol || default_protocol) == :request && !has_request?
|
72
|
+
host = nil
|
73
|
+
else
|
74
|
+
host = "#{compute_protocol(protocol)}#{host}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
host ? "#{host}#{source}" : source
|
78
|
+
end
|
79
|
+
|
80
|
+
def rewrite_relative_url_root(source, relative_url_root)
|
81
|
+
relative_url_root && !source.starts_with?("#{relative_url_root}/") ? "#{relative_url_root}#{source}" : source
|
82
|
+
end
|
83
|
+
|
84
|
+
def compute_asset_host(source)
|
85
|
+
if host = @config.host
|
86
|
+
if host.respond_to?(:call)
|
87
|
+
args = [source]
|
88
|
+
arity = arity_of(host)
|
89
|
+
if arity > 1 && request.nil?
|
90
|
+
invalid_asset_host!("Remove the second argument to your asset_host Proc if you do not need the request.")
|
91
|
+
end
|
92
|
+
args << current_request if (arity > 1 || arity < 0) && has_request?
|
93
|
+
host.call(*args)
|
94
|
+
else
|
95
|
+
(host =~ /%d/) ? host % (Zlib.crc32(source) % 4) : host
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def default_protocol
|
101
|
+
@config.default_protocol || (request.nil?? :relative : :request)
|
102
|
+
end
|
103
|
+
|
104
|
+
def compute_protocol(protocol)
|
105
|
+
protocol ||= default_protocol
|
106
|
+
case protocol
|
107
|
+
when :request
|
108
|
+
if request.nil?
|
109
|
+
invalid_asset_host!("The protocol requested was :request. Consider using :relative instead.")
|
110
|
+
end
|
111
|
+
request.protocol
|
112
|
+
when :relative
|
113
|
+
"//"
|
114
|
+
else
|
115
|
+
"#{protocol}://"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def arity_of(callable)
|
120
|
+
callable.respond_to?(:arity) ? callable.arity : callable.method(:call).arity
|
121
|
+
end
|
122
|
+
|
123
|
+
def invalid_asset_host!(help_message)
|
124
|
+
raise ActionController::RoutingError, "This asset host cannot be computed without a request in scope. #{help_message}"
|
125
|
+
end
|
126
|
+
|
127
|
+
private
|
128
|
+
|
129
|
+
def asset_environment
|
130
|
+
Sinatra::Sprockets.environment
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Sinatra::Sprockets
|
2
|
+
DEFAULT_OPTIONS = {
|
3
|
+
app: nil,
|
4
|
+
debug: false,
|
5
|
+
digest: false,
|
6
|
+
compile: false,
|
7
|
+
compress: false,
|
8
|
+
host: nil,
|
9
|
+
manifest_path: 'public/assets',
|
10
|
+
paths: %w[images javascripts stylesheets],
|
11
|
+
precompile: [ /\w+\.(?!js|css).+/, /application.(css|js)$/ ],
|
12
|
+
prefix: 'assets',
|
13
|
+
relative_url_root: ENV['RACK_RELATIVE_URL_ROOT'],
|
14
|
+
css_compressor: false,
|
15
|
+
js_compressor: false
|
16
|
+
}
|
17
|
+
|
18
|
+
class Configuration < Struct.new(*DEFAULT_OPTIONS.keys)
|
19
|
+
attr_accessor *DEFAULT_OPTIONS.keys, :digests
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
DEFAULT_OPTIONS.each do |key, value|
|
23
|
+
send "#{key}=".to_sym, value
|
24
|
+
end
|
25
|
+
@digests = {}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Sinatra::Sprockets
|
2
|
+
module Helpers
|
3
|
+
def asset_path source, options = {}
|
4
|
+
source = source.logical_path if source.respond_to?(:logical_path)
|
5
|
+
path = asset_paths.compute_public_path(source, config.prefix, options.merge(:body => true))
|
6
|
+
options[:body] ? "#{path}?body=1" : path
|
7
|
+
end
|
8
|
+
|
9
|
+
def image_path source, options = {}
|
10
|
+
asset_path source, { dir: 'images' }.merge(options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def javascript_path source, options = {}
|
14
|
+
asset_path source, { dir: 'javascripts', ext: 'js' }.merge(options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def stylesheet_path source, options = {}
|
18
|
+
asset_path source, { dir: 'stylesheets', ext: 'css' }.merge(options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def javascript_include_tag(*sources)
|
22
|
+
debug = config.debug
|
23
|
+
body = false
|
24
|
+
digest = config.digest
|
25
|
+
|
26
|
+
sources.collect do |source|
|
27
|
+
if debug && asset = asset_paths.asset_for(source, 'js')
|
28
|
+
asset.to_a.map do |dep|
|
29
|
+
src = asset_path(dep, :ext => 'js', :body => true, :digest => digest)
|
30
|
+
"<script src=#{src} type='application/javascript'></script>"
|
31
|
+
end
|
32
|
+
else
|
33
|
+
src = asset_path(source, :ext => 'js', :body => body, :digest => digest)
|
34
|
+
"<script src=#{src} type='application/javascript'></script>"
|
35
|
+
end
|
36
|
+
end.join("\n")
|
37
|
+
end
|
38
|
+
|
39
|
+
def stylesheet_link_tag(*sources)
|
40
|
+
options = {}
|
41
|
+
debug = config.debug
|
42
|
+
body = false
|
43
|
+
digest = config.digest
|
44
|
+
|
45
|
+
sources.collect do |source|
|
46
|
+
if debug && asset = asset_paths.asset_for(source, 'css')
|
47
|
+
asset.to_a.map do |dep|
|
48
|
+
href = asset_path(dep, :ext => 'css', :body => true, :protocol => :request, :digest => digest)
|
49
|
+
"<link href='#{href}' media='screen' rel='stylesheet', type='text/css' />"
|
50
|
+
end
|
51
|
+
else
|
52
|
+
href = asset_path(source, :ext => 'css', :body => body, :protocol => :request, :digest => digest)
|
53
|
+
"<link href='#{href}' media='screen' rel='stylesheet', type='text/css' />"
|
54
|
+
end
|
55
|
+
end.join("\n")
|
56
|
+
end
|
57
|
+
|
58
|
+
def asset_path(source, options={})
|
59
|
+
source = source.logical_path if source.respond_to?(:logical_path)
|
60
|
+
path = asset_paths.compute_public_path(source, config.prefix, options.merge(:body => true))
|
61
|
+
options[:body] ? "#{path}?body=1" : path
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def assets_environment
|
67
|
+
Sinatra::Sprockets.environment
|
68
|
+
end
|
69
|
+
|
70
|
+
def asset_paths
|
71
|
+
@asset_paths ||= AssetPaths.new Sinatra::Sprockets.config
|
72
|
+
end
|
73
|
+
|
74
|
+
def config
|
75
|
+
Sinatra::Sprockets.config
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Sinatra::Sprockets
|
4
|
+
class StaticCompiler
|
5
|
+
attr_accessor :env, :target, :paths
|
6
|
+
|
7
|
+
def initialize(env, target, paths, options = {})
|
8
|
+
@env = env
|
9
|
+
@target = target
|
10
|
+
@paths = paths
|
11
|
+
@digest = options.key?(:digest) ? options.delete(:digest) : true
|
12
|
+
@manifest = options.key?(:manifest) ? options.delete(:manifest) : true
|
13
|
+
@manifest_path = options.delete(:manifest_path) || target
|
14
|
+
end
|
15
|
+
|
16
|
+
def compile
|
17
|
+
manifest = {}
|
18
|
+
env.each_logical_path do |logical_path|
|
19
|
+
next unless compile_path?(logical_path)
|
20
|
+
if asset = env.find_asset(logical_path)
|
21
|
+
manifest[logical_path] = write_asset(asset)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
write_manifest(manifest) if @manifest
|
25
|
+
end
|
26
|
+
|
27
|
+
def write_manifest(manifest)
|
28
|
+
FileUtils.mkdir_p(@manifest_path)
|
29
|
+
File.open("#{@manifest_path}/manifest.yml", 'wb') do |f|
|
30
|
+
YAML.dump(manifest, f)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def write_asset(asset)
|
35
|
+
path_for(asset).tap do |path|
|
36
|
+
filename = File.join(target, path)
|
37
|
+
FileUtils.mkdir_p File.dirname(filename)
|
38
|
+
asset.write_to(filename)
|
39
|
+
asset.write_to("#{filename}.gz") if filename.to_s =~ /\.(css|js)$/
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def compile_path?(logical_path)
|
44
|
+
paths.each do |path|
|
45
|
+
case path
|
46
|
+
when Regexp
|
47
|
+
return true if path.match(logical_path)
|
48
|
+
when Proc
|
49
|
+
return true if path.call(logical_path)
|
50
|
+
else
|
51
|
+
return true if File.fnmatch(path.to_s, logical_path)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
false
|
55
|
+
end
|
56
|
+
|
57
|
+
def path_for(asset)
|
58
|
+
@digest ? asset.digest_path : asset.logical_path
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "sinatra/sprockets/version"
|
2
|
+
require "sinatra/sprockets/asset_paths"
|
3
|
+
require "sinatra/sprockets/configuration"
|
4
|
+
require "sinatra/sprockets/helpers"
|
5
|
+
|
6
|
+
module Sinatra
|
7
|
+
module Sprockets
|
8
|
+
def self.configure
|
9
|
+
yield config
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.config
|
13
|
+
@config ||= Configuration.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.environment
|
17
|
+
@environment
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.registered app
|
21
|
+
config.app = app
|
22
|
+
|
23
|
+
@environment = ::Sprockets::Environment.new app.root
|
24
|
+
|
25
|
+
config.paths.each do |path|
|
26
|
+
environment.append_path File.join(config.app.root, config.prefix, path)
|
27
|
+
environment.append_path File.join(config.app.root, 'lib', config.prefix, path)
|
28
|
+
end
|
29
|
+
|
30
|
+
if config.compress
|
31
|
+
environment.css_compressor = config.css_compressor
|
32
|
+
environment.js_compressor = config.js_compressor
|
33
|
+
end
|
34
|
+
|
35
|
+
app.helpers Helpers
|
36
|
+
environment.context_class.instance_eval do
|
37
|
+
include Helpers
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/sinatra/sprockets/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Andrew Marshall"]
|
6
|
+
gem.email = ["andrew@johnandrewmarshall.com"]
|
7
|
+
gem.description = %q{Sinatra plugin for Sprockets integration}
|
8
|
+
gem.summary = %q{Sinatra plugin for Sprockets integration}
|
9
|
+
gem.homepage = "http://johnandrewmarshall.com/projects/sinatra-sprockets"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "sinatra-sprockets-ext"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Sinatra::Sprockets::VERSION
|
17
|
+
|
18
|
+
gem.add_dependency "sprockets"
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sinatra-sprockets-ext
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Andrew Marshall
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-03 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: sprockets
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description: Sinatra plugin for Sprockets integration
|
31
|
+
email:
|
32
|
+
- andrew@johnandrewmarshall.com
|
33
|
+
executables: []
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- .gitignore
|
38
|
+
- Gemfile
|
39
|
+
- LICENSE
|
40
|
+
- README.md
|
41
|
+
- Rakefile
|
42
|
+
- lib/sinatra/sprockets.rb
|
43
|
+
- lib/sinatra/sprockets/asset_paths.rb
|
44
|
+
- lib/sinatra/sprockets/configuration.rb
|
45
|
+
- lib/sinatra/sprockets/helpers.rb
|
46
|
+
- lib/sinatra/sprockets/static_compiler.rb
|
47
|
+
- lib/sinatra/sprockets/version.rb
|
48
|
+
- sinatra-sprockets.gemspec
|
49
|
+
homepage: http://johnandrewmarshall.com/projects/sinatra-sprockets
|
50
|
+
licenses: []
|
51
|
+
post_install_message:
|
52
|
+
rdoc_options: []
|
53
|
+
require_paths:
|
54
|
+
- lib
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ! '>='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
requirements: []
|
68
|
+
rubyforge_project:
|
69
|
+
rubygems_version: 1.8.23
|
70
|
+
signing_key:
|
71
|
+
specification_version: 3
|
72
|
+
summary: Sinatra plugin for Sprockets integration
|
73
|
+
test_files: []
|
74
|
+
has_rdoc:
|