sprockets 3.0.0.beta.6 → 3.0.0.beta.7
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.
- checksums.yaml +4 -4
- data/README.md +171 -100
- data/lib/rake/sprocketstask.rb +2 -2
- data/lib/sprockets.rb +69 -63
- data/lib/sprockets/asset.rb +2 -61
- data/lib/sprockets/autoload_processor.rb +48 -0
- data/lib/sprockets/base.rb +4 -6
- data/lib/sprockets/bower.rb +8 -5
- data/lib/sprockets/bundle.rb +9 -13
- data/lib/sprockets/cache.rb +19 -14
- data/lib/sprockets/cache/file_store.rb +2 -1
- data/lib/sprockets/cached_environment.rb +15 -68
- data/lib/sprockets/closure_compressor.rb +17 -4
- data/lib/sprockets/coffee_script_processor.rb +26 -0
- data/lib/sprockets/coffee_script_template.rb +3 -20
- data/lib/sprockets/compressing.rb +10 -4
- data/lib/sprockets/configuration.rb +21 -37
- data/lib/sprockets/context.rb +37 -67
- data/lib/sprockets/dependencies.rb +73 -0
- data/lib/sprockets/digest_utils.rb +8 -2
- data/lib/sprockets/directive_processor.rb +122 -165
- data/lib/sprockets/eco_processor.rb +32 -0
- data/lib/sprockets/eco_template.rb +3 -26
- data/lib/sprockets/ejs_processor.rb +31 -0
- data/lib/sprockets/ejs_template.rb +3 -25
- data/lib/sprockets/encoding_utils.rb +9 -21
- data/lib/sprockets/engines.rb +25 -27
- data/lib/sprockets/environment.rb +9 -1
- data/lib/sprockets/erb_processor.rb +30 -0
- data/lib/sprockets/erb_template.rb +3 -20
- data/lib/sprockets/file_reader.rb +15 -0
- data/lib/sprockets/http_utils.rb +2 -0
- data/lib/sprockets/jst_processor.rb +9 -2
- data/lib/sprockets/legacy.rb +212 -3
- data/lib/sprockets/legacy_tilt_processor.rb +1 -1
- data/lib/sprockets/loader.rb +95 -89
- data/lib/sprockets/manifest.rb +23 -59
- data/lib/sprockets/mime.rb +28 -41
- data/lib/sprockets/path_dependency_utils.rb +76 -0
- data/lib/sprockets/path_utils.rb +21 -1
- data/lib/sprockets/paths.rb +23 -8
- data/lib/sprockets/processing.rb +102 -91
- data/lib/sprockets/processor_utils.rb +97 -0
- data/lib/sprockets/resolve.rb +110 -97
- data/lib/sprockets/sass_cache_store.rb +2 -2
- data/lib/sprockets/sass_compressor.rb +17 -4
- data/lib/sprockets/sass_functions.rb +2 -2
- data/lib/sprockets/sass_importer.rb +2 -2
- data/lib/sprockets/sass_processor.rb +305 -0
- data/lib/sprockets/sass_template.rb +4 -286
- data/lib/sprockets/server.rb +1 -13
- data/lib/sprockets/transformers.rb +62 -25
- data/lib/sprockets/uglifier_compressor.rb +17 -4
- data/lib/sprockets/uri_utils.rb +190 -0
- data/lib/sprockets/utils.rb +87 -6
- data/lib/sprockets/version.rb +1 -1
- data/lib/sprockets/yui_compressor.rb +17 -4
- metadata +14 -5
- data/lib/sprockets/asset_uri.rb +0 -80
- data/lib/sprockets/lazy_processor.rb +0 -15
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'sprockets/autoload_processor'
|
2
|
+
|
3
|
+
module Sprockets
|
4
|
+
# Functional utilities for dealing with Processor functions.
|
5
|
+
#
|
6
|
+
# A Processor is a general function that my modify or transform an asset as
|
7
|
+
# part of the pipeline. CoffeeScript to JavaScript conversion, Minification
|
8
|
+
# or Concatenation are all implemented as seperate Processor steps.
|
9
|
+
#
|
10
|
+
# Processors maybe any object that responds to call. So procs or a class that
|
11
|
+
# defines a self.call method.
|
12
|
+
#
|
13
|
+
# For ergonomics, processors may return a number of shorthand values.
|
14
|
+
# Unfortunately, this means that processors can not compose via ordinary
|
15
|
+
# function composition. The composition helpers here can help.
|
16
|
+
module ProcessorUtils
|
17
|
+
extend self
|
18
|
+
|
19
|
+
# Internal: Setup autoload and wrapper for lazy loaded processor.
|
20
|
+
#
|
21
|
+
# Sprockets.autoload_processor :CoffeeScriptProcessor, 'sprockets/coffee_script_processor'
|
22
|
+
#
|
23
|
+
# mod - Symbol name of processor class/module
|
24
|
+
# filename - String require path for module
|
25
|
+
#
|
26
|
+
# Returns AutoloadProcessor.
|
27
|
+
def autoload_processor(mod, filename)
|
28
|
+
autoload(mod, filename)
|
29
|
+
AutoloadProcessor.new(self, mod)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Public: Compose processors in right to left order.
|
33
|
+
#
|
34
|
+
# processors - Array of processors callables
|
35
|
+
#
|
36
|
+
# Returns a composed Proc.
|
37
|
+
def compose_processors(*processors)
|
38
|
+
context = self
|
39
|
+
obj = method(:call_processors).to_proc.curry[processors]
|
40
|
+
metaclass = (class << obj; self; end)
|
41
|
+
metaclass.send(:define_method, :cache_key) do
|
42
|
+
context.processors_cache_keys(processors)
|
43
|
+
end
|
44
|
+
obj
|
45
|
+
end
|
46
|
+
|
47
|
+
# Public: Invoke list of processors in right to left order.
|
48
|
+
#
|
49
|
+
# The right to left order processing mirrors standard function composition.
|
50
|
+
# Think about:
|
51
|
+
#
|
52
|
+
# bundle.call(uglify.call(coffee.call(input)))
|
53
|
+
#
|
54
|
+
# processors - Array of processor callables
|
55
|
+
# input - Hash of input data to pass to each processor
|
56
|
+
#
|
57
|
+
# Returns a Hash with :data and other processor metadata key/values.
|
58
|
+
def call_processors(processors, input)
|
59
|
+
data = input[:data] || ""
|
60
|
+
metadata = input[:metadata] || {}
|
61
|
+
|
62
|
+
processors.reverse_each do |processor|
|
63
|
+
result = processor.call(input.merge(data: data, metadata: metadata))
|
64
|
+
case result
|
65
|
+
when NilClass
|
66
|
+
when Hash
|
67
|
+
data = result.delete(:data) if result.key?(:data)
|
68
|
+
metadata.merge!(result)
|
69
|
+
when String
|
70
|
+
data = result
|
71
|
+
else
|
72
|
+
raise TypeError, "invalid processor return type: #{result.class}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
metadata.merge(data: data)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Internal: Get processor defined cached key.
|
80
|
+
#
|
81
|
+
# processor - Processor function
|
82
|
+
#
|
83
|
+
# Returns JSON serializable key or nil.
|
84
|
+
def processor_cache_key(processor)
|
85
|
+
processor.cache_key if processor.respond_to?(:cache_key)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Internal: Get combined cache keys for set of processors.
|
89
|
+
#
|
90
|
+
# processors - Array of processor functions
|
91
|
+
#
|
92
|
+
# Returns Array of JSON serializable keys.
|
93
|
+
def processors_cache_keys(processors)
|
94
|
+
processors.map { |processor| processor_cache_key(processor) }
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
data/lib/sprockets/resolve.rb
CHANGED
@@ -1,110 +1,121 @@
|
|
1
|
-
require '
|
1
|
+
require 'set'
|
2
|
+
require 'sprockets/http_utils'
|
3
|
+
require 'sprockets/path_dependency_utils'
|
4
|
+
require 'sprockets/uri_utils'
|
2
5
|
|
3
6
|
module Sprockets
|
4
7
|
module Resolve
|
5
|
-
|
8
|
+
include HTTPUtils, PathDependencyUtils, URIUtils
|
9
|
+
|
10
|
+
# Public: Find Asset URI for given a logical path by searching the
|
6
11
|
# environment's load paths.
|
7
12
|
#
|
8
13
|
# resolve("application.js")
|
9
|
-
# # => "
|
14
|
+
# # => "file:///path/to/app/javascripts/application.js?type=application/javascript"
|
10
15
|
#
|
11
16
|
# An accept content type can be given if the logical path doesn't have a
|
12
17
|
# format extension.
|
13
18
|
#
|
14
19
|
# resolve("application", accept: "application/javascript")
|
15
|
-
# # => "
|
20
|
+
# # => "file:///path/to/app/javascripts/application.coffee?type=application/javascript"
|
16
21
|
#
|
17
|
-
# The String
|
22
|
+
# The String Asset URI is returned or nil if no results are found.
|
18
23
|
def resolve(path, options = {})
|
19
|
-
|
20
|
-
|
24
|
+
path = path.to_s
|
21
25
|
paths = options[:load_paths] || self.paths
|
26
|
+
accept = options[:accept]
|
27
|
+
skip_bundle = options.key?(:bundle) ? !options[:bundle] : false
|
22
28
|
|
23
|
-
if
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
30
|
-
else
|
31
|
-
path
|
32
|
-
end
|
33
|
-
end
|
29
|
+
if valid_asset_uri?(path)
|
30
|
+
resolve_asset_uri(path)
|
31
|
+
elsif absolute_path?(path)
|
32
|
+
resolve_absolute_path(paths, path, accept, skip_bundle)
|
33
|
+
elsif relative_path?(path)
|
34
|
+
resolve_relative_path(paths, path, options[:base_path], accept, skip_bundle)
|
34
35
|
else
|
35
|
-
|
36
|
-
filename, _ = resolve_under_paths(paths, logical_name, mime_type, accepts)
|
37
|
-
filename
|
36
|
+
resolve_logical_path(paths, path, accept, skip_bundle)
|
38
37
|
end
|
39
38
|
end
|
40
39
|
|
41
|
-
# Public:
|
42
|
-
#
|
43
|
-
|
44
|
-
|
45
|
-
# # => "file:///path/to/app/javascripts/application.js?content_type=application/javascript"
|
46
|
-
#
|
47
|
-
# An accept content type can be given if the logical path doesn't have a
|
48
|
-
# format extension.
|
49
|
-
#
|
50
|
-
# locate("application", accept: "application/javascript")
|
51
|
-
# # => "file:///path/to/app/javascripts/application.coffee?content_type=application/javascript"
|
52
|
-
#
|
53
|
-
# The String Asset URI is returned or nil if no results are found.
|
54
|
-
def locate(path, options = {})
|
55
|
-
path = path.to_s
|
56
|
-
accept = options[:accept]
|
57
|
-
skip_bundle = options.key?(:bundle) ? !options[:bundle] : false
|
40
|
+
# Public: Same as resolve() but raises a FileNotFound exception instead of
|
41
|
+
# nil if no assets are found.
|
42
|
+
def resolve!(path, options = {})
|
43
|
+
uri, deps = resolve(path, options.merge(compat: false))
|
58
44
|
|
59
|
-
|
60
|
-
|
45
|
+
unless uri
|
46
|
+
message = "couldn't find file '#{path}'"
|
47
|
+
message << " with type '#{options[:accept]}'" if options[:accept]
|
48
|
+
raise FileNotFound, message
|
49
|
+
end
|
61
50
|
|
62
|
-
|
51
|
+
return uri, deps
|
52
|
+
end
|
63
53
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
else
|
77
|
-
logical_name, mime_type, _ = parse_path_extnames(path)
|
78
|
-
parsed_accept = parse_accept_options(mime_type, accept)
|
54
|
+
protected
|
55
|
+
def resolve_asset_uri(uri)
|
56
|
+
filename, _ = parse_asset_uri(uri)
|
57
|
+
return uri, Set.new([build_file_digest_uri(filename)])
|
58
|
+
end
|
59
|
+
|
60
|
+
def resolve_absolute_path(paths, filename, accept, skip_bundle)
|
61
|
+
deps = Set.new
|
62
|
+
filename = File.expand_path(filename)
|
63
|
+
|
64
|
+
# Ensure path is under load paths
|
65
|
+
return nil, deps unless paths_split(paths, filename)
|
79
66
|
|
80
|
-
|
81
|
-
|
67
|
+
mime_type = parse_path_extnames(filename)[1]
|
68
|
+
type = resolve_transform_type(mime_type, accept)
|
69
|
+
return nil, deps if accept && !type
|
70
|
+
|
71
|
+
return nil, deps unless file?(filename)
|
72
|
+
|
73
|
+
uri = build_asset_uri(filename, type: type, skip_bundle: skip_bundle)
|
74
|
+
deps << build_file_digest_uri(filename)
|
75
|
+
return uri, deps
|
76
|
+
end
|
77
|
+
|
78
|
+
def resolve_relative_path(paths, path, dirname, accept, skip_bundle)
|
79
|
+
filename = File.expand_path(path, dirname)
|
80
|
+
load_path, _ = paths_split(paths, dirname)
|
81
|
+
if load_path && logical_path = split_subpath(load_path, filename)
|
82
|
+
resolve_logical_path([load_path], logical_path, accept, skip_bundle)
|
83
|
+
else
|
84
|
+
[nil, Set.new]
|
82
85
|
end
|
86
|
+
end
|
83
87
|
|
88
|
+
def resolve_logical_path(paths, logical_path, accept, skip_bundle)
|
89
|
+
logical_name, mime_type, _ = parse_path_extnames(logical_path)
|
90
|
+
parsed_accept = parse_accept_options(mime_type, accept)
|
84
91
|
transformed_accepts = expand_transform_accepts(parsed_accept)
|
85
|
-
filename, mime_type = resolve_under_paths(paths, logical_name,
|
86
|
-
|
92
|
+
filename, mime_type, deps = resolve_under_paths(paths, logical_name, transformed_accepts)
|
93
|
+
|
94
|
+
if filename
|
95
|
+
deps << build_file_digest_uri(filename)
|
96
|
+
type = resolve_transform_type(mime_type, parsed_accept)
|
97
|
+
uri = build_asset_uri(filename, type: type, skip_bundle: skip_bundle)
|
98
|
+
return uri, deps
|
99
|
+
else
|
100
|
+
return nil, deps
|
101
|
+
end
|
87
102
|
end
|
88
103
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
end
|
93
|
-
end
|
104
|
+
def resolve_under_paths(paths, logical_name, accepts)
|
105
|
+
all_deps = Set.new
|
106
|
+
return nil, nil, all_deps if accepts.empty?
|
94
107
|
|
95
|
-
protected
|
96
|
-
def resolve_under_paths(paths, logical_name, mime_type, accepts)
|
97
108
|
logical_basename = File.basename(logical_name)
|
98
|
-
|
99
109
|
paths.each do |load_path|
|
100
|
-
candidates = path_matches(load_path, logical_name, logical_basename)
|
110
|
+
candidates, deps = path_matches(load_path, logical_name, logical_basename)
|
111
|
+
all_deps.merge(deps)
|
101
112
|
candidate = find_best_q_match(accepts, candidates) do |c, matcher|
|
102
113
|
match_mime_type?(c[1] || "application/octet-stream", matcher)
|
103
114
|
end
|
104
|
-
return candidate if candidate
|
115
|
+
return candidate + [all_deps] if candidate
|
105
116
|
end
|
106
117
|
|
107
|
-
nil
|
118
|
+
return nil, nil, all_deps
|
108
119
|
end
|
109
120
|
|
110
121
|
def parse_accept_options(mime_type, types)
|
@@ -133,24 +144,40 @@ module Sprockets
|
|
133
144
|
end
|
134
145
|
|
135
146
|
def path_matches(load_path, logical_name, logical_basename)
|
136
|
-
candidates = []
|
147
|
+
candidates, deps = [], Set.new
|
137
148
|
dirname = File.dirname(File.join(load_path, logical_name))
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
149
|
+
|
150
|
+
result = dirname_matches(dirname, logical_basename)
|
151
|
+
candidates.concat(result[0])
|
152
|
+
deps.merge(result[1])
|
153
|
+
|
154
|
+
result = resolve_alternates(load_path, logical_name)
|
155
|
+
result[0].each do |fn|
|
156
|
+
candidates << [fn, parse_path_extnames(fn)[1]]
|
157
|
+
end
|
158
|
+
deps.merge(result[1])
|
159
|
+
|
160
|
+
result = dirname_matches(File.join(load_path, logical_name), "index")
|
161
|
+
candidates.concat(result[0])
|
162
|
+
deps.merge(result[1])
|
163
|
+
|
164
|
+
return candidates.select { |fn, _| file?(fn) }, deps
|
142
165
|
end
|
143
166
|
|
144
167
|
def dirname_matches(dirname, basename)
|
145
|
-
|
168
|
+
candidates = []
|
169
|
+
entries, deps = self.entries_with_dependencies(dirname)
|
170
|
+
entries.each do |entry|
|
146
171
|
name, type, _ = parse_path_extnames(entry)
|
147
172
|
if basename == name
|
148
|
-
|
173
|
+
candidates << [File.join(dirname, entry), type]
|
149
174
|
end
|
150
175
|
end
|
176
|
+
return candidates, deps
|
151
177
|
end
|
152
178
|
|
153
179
|
def resolve_alternates(load_path, logical_name)
|
180
|
+
return [], Set.new
|
154
181
|
end
|
155
182
|
|
156
183
|
# Internal: Returns the name, mime type and `Array` of engine extensions.
|
@@ -159,26 +186,12 @@ module Sprockets
|
|
159
186
|
# # => ["foo", "application/javascript", [".coffee", ".erb"]]
|
160
187
|
#
|
161
188
|
def parse_path_extnames(path)
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
if engines.key?(extname)
|
168
|
-
mime_type = engine_mime_types[extname]
|
169
|
-
engine_extnames.unshift(extname)
|
170
|
-
len -= extname.length
|
171
|
-
elsif mime_exts.key?(extname)
|
172
|
-
mime_type = mime_exts[extname]
|
173
|
-
len -= extname.length
|
174
|
-
break
|
175
|
-
else
|
176
|
-
break
|
177
|
-
end
|
189
|
+
extname, value = match_path_extname(path, config[:_extnames])
|
190
|
+
if extname
|
191
|
+
return path.chomp(extname), value[:type], value[:engines]
|
192
|
+
else
|
193
|
+
return path, nil, []
|
178
194
|
end
|
179
|
-
|
180
|
-
name = path[0, len]
|
181
|
-
return [name, mime_type, engine_extnames]
|
182
195
|
end
|
183
196
|
end
|
184
197
|
end
|
@@ -1,2 +1,2 @@
|
|
1
|
-
# Deprecated: Require sprockets/
|
2
|
-
require 'sprockets/
|
1
|
+
# Deprecated: Require sprockets/sass_processor instead
|
2
|
+
require 'sprockets/sass_processor'
|
@@ -16,18 +16,31 @@ module Sprockets
|
|
16
16
|
class SassCompressor
|
17
17
|
VERSION = '1'
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
# Public: Return singleton instance with default options.
|
20
|
+
#
|
21
|
+
# Returns SassCompressor object.
|
22
|
+
def self.instance
|
23
|
+
@instance ||= new
|
21
24
|
end
|
22
25
|
|
26
|
+
def self.call(input)
|
27
|
+
instance.call(input)
|
28
|
+
end
|
29
|
+
|
30
|
+
def cache_key
|
31
|
+
instance.cache_key
|
32
|
+
end
|
33
|
+
|
34
|
+
attr_reader :cache_key
|
35
|
+
|
23
36
|
def initialize(options = {})
|
24
37
|
@options = options
|
25
38
|
@cache_key = [
|
26
|
-
|
39
|
+
self.class.name,
|
27
40
|
::Sass::VERSION,
|
28
41
|
VERSION,
|
29
42
|
options
|
30
|
-
]
|
43
|
+
].freeze
|
31
44
|
end
|
32
45
|
|
33
46
|
def call(input)
|
@@ -1,2 +1,2 @@
|
|
1
|
-
# Deprecated: Require sprockets/
|
2
|
-
require 'sprockets/
|
1
|
+
# Deprecated: Require sprockets/sass_processor instead
|
2
|
+
require 'sprockets/sass_processor'
|
@@ -1,2 +1,2 @@
|
|
1
|
-
# Deprecated: Require sprockets/
|
2
|
-
require 'sprockets/
|
1
|
+
# Deprecated: Require sprockets/sass_processor instead
|
2
|
+
require 'sprockets/sass_processor'
|
@@ -0,0 +1,305 @@
|
|
1
|
+
require 'rack/utils'
|
2
|
+
require 'sass'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module Sprockets
|
6
|
+
# Processor engine class for the SASS/SCSS compiler. Depends on the `sass` gem.
|
7
|
+
#
|
8
|
+
# For more infomation see:
|
9
|
+
#
|
10
|
+
# https://github.com/sass/sass
|
11
|
+
# https://github.com/rails/sass-rails
|
12
|
+
#
|
13
|
+
class SassProcessor
|
14
|
+
# Internal: Defines default sass syntax to use. Exposed so the ScssProcessor
|
15
|
+
# may override it.
|
16
|
+
def self.syntax
|
17
|
+
:sass
|
18
|
+
end
|
19
|
+
|
20
|
+
# Public: Return singleton instance with default options.
|
21
|
+
#
|
22
|
+
# Returns SassProcessor object.
|
23
|
+
def self.instance
|
24
|
+
@instance ||= new
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.call(input)
|
28
|
+
instance.call(input)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.cache_key
|
32
|
+
instance.cache_key
|
33
|
+
end
|
34
|
+
|
35
|
+
attr_reader :cache_key
|
36
|
+
|
37
|
+
# Public: Initialize template with custom options.
|
38
|
+
#
|
39
|
+
# options - Hash
|
40
|
+
# cache_version - String custom cache version. Used to force a cache
|
41
|
+
# change after code changes are made to Sass Functions.
|
42
|
+
#
|
43
|
+
def initialize(options = {}, &block)
|
44
|
+
@cache_version = options[:cache_version]
|
45
|
+
@cache_key = [
|
46
|
+
self.class.name,
|
47
|
+
VERSION,
|
48
|
+
Sass::VERSION,
|
49
|
+
@cache_version
|
50
|
+
].freeze
|
51
|
+
|
52
|
+
@functions = Module.new do
|
53
|
+
include Functions
|
54
|
+
include options[:functions] if options[:functions]
|
55
|
+
class_eval(&block) if block_given?
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def call(input)
|
60
|
+
context = input[:environment].context_class.new(input)
|
61
|
+
|
62
|
+
options = {
|
63
|
+
filename: input[:filename],
|
64
|
+
syntax: self.class.syntax,
|
65
|
+
cache_store: CacheStore.new(input[:cache], @cache_version),
|
66
|
+
load_paths: input[:environment].paths,
|
67
|
+
sprockets: {
|
68
|
+
context: context,
|
69
|
+
environment: input[:environment],
|
70
|
+
dependencies: context.metadata[:dependencies]
|
71
|
+
}
|
72
|
+
}
|
73
|
+
|
74
|
+
engine = ::Sass::Engine.new(input[:data], options)
|
75
|
+
|
76
|
+
css = Utils.module_include(::Sass::Script::Functions, @functions) do
|
77
|
+
engine.render
|
78
|
+
end
|
79
|
+
|
80
|
+
# Track all imported files
|
81
|
+
engine.dependencies.map do |dependency|
|
82
|
+
context.metadata[:dependencies] << URIUtils.build_file_digest_uri(dependency.options[:filename])
|
83
|
+
end
|
84
|
+
|
85
|
+
context.metadata.merge(data: css)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Public: Functions injected into Sass context during Sprockets evaluation.
|
89
|
+
#
|
90
|
+
# This module may be extended to add global functionality to all Sprockets
|
91
|
+
# Sass environments. Though, scoping your functions to just your environment
|
92
|
+
# is preferred.
|
93
|
+
#
|
94
|
+
# module Sprockets::SassProcessor::Functions
|
95
|
+
# def asset_path(path, options = {})
|
96
|
+
# end
|
97
|
+
# end
|
98
|
+
#
|
99
|
+
module Functions
|
100
|
+
# Public: Generate a url for asset path.
|
101
|
+
#
|
102
|
+
# Default implementation is deprecated. Currently defaults to
|
103
|
+
# Context#asset_path.
|
104
|
+
#
|
105
|
+
# Will raise NotImplementedError in the future. Users should provide their
|
106
|
+
# own base implementation.
|
107
|
+
#
|
108
|
+
# Returns a Sass::Script::String.
|
109
|
+
def asset_path(path, options = {})
|
110
|
+
path = path.value
|
111
|
+
|
112
|
+
path, _, query, fragment = URI.split(path)[5..8]
|
113
|
+
path = sprockets_context.asset_path(path, options)
|
114
|
+
query = "?#{query}" if query
|
115
|
+
fragment = "##{fragment}" if fragment
|
116
|
+
|
117
|
+
::Sass::Script::String.new("#{path}#{query}#{fragment}", :string)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Public: Generate a asset url() link.
|
121
|
+
#
|
122
|
+
# path - Sass::Script::String URL path
|
123
|
+
#
|
124
|
+
# Returns a Sass::Script::String.
|
125
|
+
def asset_url(path, options = {})
|
126
|
+
::Sass::Script::String.new("url(#{asset_path(path, options).value})")
|
127
|
+
end
|
128
|
+
|
129
|
+
# Public: Generate url for image path.
|
130
|
+
#
|
131
|
+
# path - Sass::Script::String URL path
|
132
|
+
#
|
133
|
+
# Returns a Sass::Script::String.
|
134
|
+
def image_path(path)
|
135
|
+
asset_path(path, type: :image)
|
136
|
+
end
|
137
|
+
|
138
|
+
# Public: Generate a image url() link.
|
139
|
+
#
|
140
|
+
# path - Sass::Script::String URL path
|
141
|
+
#
|
142
|
+
# Returns a Sass::Script::String.
|
143
|
+
def image_url(path)
|
144
|
+
asset_url(path, type: :image)
|
145
|
+
end
|
146
|
+
|
147
|
+
# Public: Generate url for video path.
|
148
|
+
#
|
149
|
+
# path - Sass::Script::String URL path
|
150
|
+
#
|
151
|
+
# Returns a Sass::Script::String.
|
152
|
+
def video_path(path)
|
153
|
+
asset_path(path, type: :video)
|
154
|
+
end
|
155
|
+
|
156
|
+
# Public: Generate a video url() link.
|
157
|
+
#
|
158
|
+
# path - Sass::Script::String URL path
|
159
|
+
#
|
160
|
+
# Returns a Sass::Script::String.
|
161
|
+
def video_url(path)
|
162
|
+
asset_url(path, type: :video)
|
163
|
+
end
|
164
|
+
|
165
|
+
# Public: Generate url for audio path.
|
166
|
+
#
|
167
|
+
# path - Sass::Script::String URL path
|
168
|
+
#
|
169
|
+
# Returns a Sass::Script::String.
|
170
|
+
def audio_path(path)
|
171
|
+
asset_path(path, type: :audio)
|
172
|
+
end
|
173
|
+
|
174
|
+
# Public: Generate a audio url() link.
|
175
|
+
#
|
176
|
+
# path - Sass::Script::String URL path
|
177
|
+
#
|
178
|
+
# Returns a Sass::Script::String.
|
179
|
+
def audio_url(path)
|
180
|
+
asset_url(path, type: :audio)
|
181
|
+
end
|
182
|
+
|
183
|
+
# Public: Generate url for font path.
|
184
|
+
#
|
185
|
+
# path - Sass::Script::String URL path
|
186
|
+
#
|
187
|
+
# Returns a Sass::Script::String.
|
188
|
+
def font_path(path)
|
189
|
+
asset_path(path, type: :font)
|
190
|
+
end
|
191
|
+
|
192
|
+
# Public: Generate a font url() link.
|
193
|
+
#
|
194
|
+
# path - Sass::Script::String URL path
|
195
|
+
#
|
196
|
+
# Returns a Sass::Script::String.
|
197
|
+
def font_url(path)
|
198
|
+
asset_url(path, type: :font)
|
199
|
+
end
|
200
|
+
|
201
|
+
# Public: Generate url for javascript path.
|
202
|
+
#
|
203
|
+
# path - Sass::Script::String URL path
|
204
|
+
#
|
205
|
+
# Returns a Sass::Script::String.
|
206
|
+
def javascript_path(path)
|
207
|
+
asset_path(path, type: :javascript)
|
208
|
+
end
|
209
|
+
|
210
|
+
# Public: Generate a javascript url() link.
|
211
|
+
#
|
212
|
+
# path - Sass::Script::String URL path
|
213
|
+
#
|
214
|
+
# Returns a Sass::Script::String.
|
215
|
+
def javascript_url(path)
|
216
|
+
asset_url(path, type: :javascript)
|
217
|
+
end
|
218
|
+
|
219
|
+
# Public: Generate url for stylesheet path.
|
220
|
+
#
|
221
|
+
# path - Sass::Script::String URL path
|
222
|
+
#
|
223
|
+
# Returns a Sass::Script::String.
|
224
|
+
def stylesheet_path(path)
|
225
|
+
asset_path(path, type: :stylesheet)
|
226
|
+
end
|
227
|
+
|
228
|
+
# Public: Generate a stylesheet url() link.
|
229
|
+
#
|
230
|
+
# path - Sass::Script::String URL path
|
231
|
+
#
|
232
|
+
# Returns a Sass::Script::String.
|
233
|
+
def stylesheet_url(path)
|
234
|
+
asset_url(path, type: :stylesheet)
|
235
|
+
end
|
236
|
+
|
237
|
+
# Public: Generate a data URI for asset path.
|
238
|
+
#
|
239
|
+
# path - Sass::Script::String logical asset path
|
240
|
+
#
|
241
|
+
# Returns a Sass::Script::String.
|
242
|
+
def asset_data_url(path)
|
243
|
+
url = sprockets_context.asset_data_uri(path.value)
|
244
|
+
::Sass::Script::String.new("url(" + url + ")")
|
245
|
+
end
|
246
|
+
|
247
|
+
protected
|
248
|
+
# Public: The Environment.
|
249
|
+
#
|
250
|
+
# Returns Sprockets::Environment.
|
251
|
+
def sprockets_environment
|
252
|
+
options[:sprockets][:environment]
|
253
|
+
end
|
254
|
+
|
255
|
+
# Public: Mutatable set of dependencies.
|
256
|
+
#
|
257
|
+
# Returns a Set.
|
258
|
+
def sprockets_dependencies
|
259
|
+
options[:sprockets][:dependencies]
|
260
|
+
end
|
261
|
+
|
262
|
+
# Deprecated: Get the Context instance. Use APIs on
|
263
|
+
# sprockets_environment or sprockets_dependencies directly.
|
264
|
+
#
|
265
|
+
# Returns a Context instance.
|
266
|
+
def sprockets_context
|
267
|
+
options[:sprockets][:context]
|
268
|
+
end
|
269
|
+
|
270
|
+
end
|
271
|
+
|
272
|
+
# Internal: Cache wrapper for Sprockets cache adapter.
|
273
|
+
class CacheStore < ::Sass::CacheStores::Base
|
274
|
+
VERSION = '1'
|
275
|
+
|
276
|
+
def initialize(cache, version)
|
277
|
+
@cache, @version = cache, "#{VERSION}/#{version}"
|
278
|
+
end
|
279
|
+
|
280
|
+
def _store(key, version, sha, contents)
|
281
|
+
@cache.set("#{@version}/#{version}/#{key}/#{sha}", contents)
|
282
|
+
end
|
283
|
+
|
284
|
+
def _retrieve(key, version, sha)
|
285
|
+
@cache.get("#{@version}/#{version}/#{key}/#{sha}")
|
286
|
+
end
|
287
|
+
|
288
|
+
def path_to(key)
|
289
|
+
key
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
class ScssProcessor < SassProcessor
|
295
|
+
def self.syntax
|
296
|
+
:scss
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
# Deprecated: Use Sprockets::SassProcessor::Functions instead.
|
301
|
+
SassFunctions = SassProcessor::Functions
|
302
|
+
|
303
|
+
# Deprecated: Use Sprockets::SassProcessor::CacheStore instead.
|
304
|
+
SassCacheStore = SassProcessor::CacheStore
|
305
|
+
end
|