sinatra-sprockets-ext 0.0.1
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/.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:
|