sprockets 2.12.5 → 3.7.2

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.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +296 -0
  3. data/LICENSE +2 -2
  4. data/README.md +235 -262
  5. data/bin/sprockets +1 -0
  6. data/lib/rake/sprocketstask.rb +5 -4
  7. data/lib/sprockets/asset.rb +143 -212
  8. data/lib/sprockets/autoload/closure.rb +7 -0
  9. data/lib/sprockets/autoload/coffee_script.rb +7 -0
  10. data/lib/sprockets/autoload/eco.rb +7 -0
  11. data/lib/sprockets/autoload/ejs.rb +7 -0
  12. data/lib/sprockets/autoload/sass.rb +7 -0
  13. data/lib/sprockets/autoload/uglifier.rb +7 -0
  14. data/lib/sprockets/autoload/yui.rb +7 -0
  15. data/lib/sprockets/autoload.rb +11 -0
  16. data/lib/sprockets/base.rb +56 -393
  17. data/lib/sprockets/bower.rb +58 -0
  18. data/lib/sprockets/bundle.rb +69 -0
  19. data/lib/sprockets/cache/file_store.rb +168 -14
  20. data/lib/sprockets/cache/memory_store.rb +66 -0
  21. data/lib/sprockets/cache/null_store.rb +46 -0
  22. data/lib/sprockets/cache.rb +236 -0
  23. data/lib/sprockets/cached_environment.rb +69 -0
  24. data/lib/sprockets/closure_compressor.rb +35 -10
  25. data/lib/sprockets/coffee_script_processor.rb +25 -0
  26. data/lib/sprockets/coffee_script_template.rb +17 -0
  27. data/lib/sprockets/compressing.rb +44 -23
  28. data/lib/sprockets/configuration.rb +83 -0
  29. data/lib/sprockets/context.rb +86 -144
  30. data/lib/sprockets/dependencies.rb +73 -0
  31. data/lib/sprockets/deprecation.rb +90 -0
  32. data/lib/sprockets/digest_utils.rb +180 -0
  33. data/lib/sprockets/directive_processor.rb +207 -211
  34. data/lib/sprockets/eco_processor.rb +32 -0
  35. data/lib/sprockets/eco_template.rb +9 -30
  36. data/lib/sprockets/ejs_processor.rb +31 -0
  37. data/lib/sprockets/ejs_template.rb +9 -29
  38. data/lib/sprockets/encoding_utils.rb +261 -0
  39. data/lib/sprockets/engines.rb +53 -35
  40. data/lib/sprockets/environment.rb +17 -64
  41. data/lib/sprockets/erb_processor.rb +30 -0
  42. data/lib/sprockets/erb_template.rb +11 -0
  43. data/lib/sprockets/errors.rb +4 -13
  44. data/lib/sprockets/file_reader.rb +15 -0
  45. data/lib/sprockets/http_utils.rb +117 -0
  46. data/lib/sprockets/jst_processor.rb +35 -15
  47. data/lib/sprockets/legacy.rb +330 -0
  48. data/lib/sprockets/legacy_proc_processor.rb +35 -0
  49. data/lib/sprockets/legacy_tilt_processor.rb +29 -0
  50. data/lib/sprockets/loader.rb +325 -0
  51. data/lib/sprockets/manifest.rb +202 -127
  52. data/lib/sprockets/manifest_utils.rb +45 -0
  53. data/lib/sprockets/mime.rb +112 -31
  54. data/lib/sprockets/path_dependency_utils.rb +85 -0
  55. data/lib/sprockets/path_digest_utils.rb +47 -0
  56. data/lib/sprockets/path_utils.rb +287 -0
  57. data/lib/sprockets/paths.rb +42 -19
  58. data/lib/sprockets/processing.rb +178 -126
  59. data/lib/sprockets/processor_utils.rb +180 -0
  60. data/lib/sprockets/resolve.rb +211 -0
  61. data/lib/sprockets/sass_cache_store.rb +22 -17
  62. data/lib/sprockets/sass_compressor.rb +39 -15
  63. data/lib/sprockets/sass_functions.rb +2 -70
  64. data/lib/sprockets/sass_importer.rb +2 -30
  65. data/lib/sprockets/sass_processor.rb +292 -0
  66. data/lib/sprockets/sass_template.rb +12 -59
  67. data/lib/sprockets/server.rb +129 -84
  68. data/lib/sprockets/transformers.rb +145 -0
  69. data/lib/sprockets/uglifier_compressor.rb +39 -12
  70. data/lib/sprockets/unloaded_asset.rb +137 -0
  71. data/lib/sprockets/uri_tar.rb +98 -0
  72. data/lib/sprockets/uri_utils.rb +188 -0
  73. data/lib/sprockets/utils/gzip.rb +67 -0
  74. data/lib/sprockets/utils.rb +210 -44
  75. data/lib/sprockets/version.rb +1 -1
  76. data/lib/sprockets/yui_compressor.rb +39 -11
  77. data/lib/sprockets.rb +142 -81
  78. metadata +96 -90
  79. data/lib/sprockets/asset_attributes.rb +0 -137
  80. data/lib/sprockets/bundled_asset.rb +0 -78
  81. data/lib/sprockets/caching.rb +0 -96
  82. data/lib/sprockets/charset_normalizer.rb +0 -41
  83. data/lib/sprockets/index.rb +0 -100
  84. data/lib/sprockets/processed_asset.rb +0 -152
  85. data/lib/sprockets/processor.rb +0 -32
  86. data/lib/sprockets/safety_colons.rb +0 -28
  87. data/lib/sprockets/scss_template.rb +0 -13
  88. data/lib/sprockets/static_asset.rb +0 -60
@@ -0,0 +1,211 @@
1
+ require 'set'
2
+ require 'sprockets/http_utils'
3
+ require 'sprockets/path_dependency_utils'
4
+ require 'sprockets/uri_utils'
5
+
6
+ module Sprockets
7
+ module Resolve
8
+ include HTTPUtils, PathDependencyUtils, URIUtils
9
+
10
+ # Public: Find Asset URI for given a logical path by searching the
11
+ # environment's load paths.
12
+ #
13
+ # resolve("application.js")
14
+ # # => "file:///path/to/app/javascripts/application.js?type=application/javascript"
15
+ #
16
+ # An accept content type can be given if the logical path doesn't have a
17
+ # format extension.
18
+ #
19
+ # resolve("application", accept: "application/javascript")
20
+ # # => "file:///path/to/app/javascripts/application.coffee?type=application/javascript"
21
+ #
22
+ # The String Asset URI is returned or nil if no results are found.
23
+ def resolve(path, options = {})
24
+ path = path.to_s
25
+ paths = options[:load_paths] || config[:paths]
26
+ accept = options[:accept]
27
+
28
+ if valid_asset_uri?(path)
29
+ uri, deps = resolve_asset_uri(path)
30
+ elsif absolute_path?(path)
31
+ filename, type, deps = resolve_absolute_path(paths, path, accept)
32
+ elsif relative_path?(path)
33
+ filename, type, pipeline, deps = resolve_relative_path(paths, path, options[:base_path], accept)
34
+ else
35
+ filename, type, pipeline, deps = resolve_logical_path(paths, path, accept)
36
+ end
37
+
38
+ if filename
39
+ params = {}
40
+ params[:type] = type if type
41
+ params[:pipeline] = pipeline if pipeline
42
+ params[:pipeline] = options[:pipeline] if options[:pipeline]
43
+ uri = build_asset_uri(filename, params)
44
+ end
45
+
46
+ return uri, deps
47
+ end
48
+
49
+ # Public: Same as resolve() but raises a FileNotFound exception instead of
50
+ # nil if no assets are found.
51
+ def resolve!(path, options = {})
52
+ uri, deps = resolve(path, options.merge(compat: false))
53
+
54
+ unless uri
55
+ message = "couldn't find file '#{path}'"
56
+
57
+ if relative_path?(path) && options[:base_path]
58
+ load_path, _ = paths_split(config[:paths], options[:base_path])
59
+ message << " under '#{load_path}'"
60
+ end
61
+
62
+ message << " with type '#{options[:accept]}'" if options[:accept]
63
+ message << "\nChecked in these paths: \n #{ config[:paths].join("\n ") }"
64
+
65
+ raise FileNotFound, message
66
+ end
67
+
68
+ return uri, deps
69
+ end
70
+
71
+ protected
72
+ def resolve_asset_uri(uri)
73
+ filename, _ = parse_asset_uri(uri)
74
+ return uri, Set.new([build_file_digest_uri(filename)])
75
+ end
76
+
77
+ def resolve_absolute_path(paths, filename, accept)
78
+ deps = Set.new
79
+ filename = File.expand_path(filename)
80
+
81
+ # Ensure path is under load paths
82
+ return nil, nil, deps unless paths_split(paths, filename)
83
+
84
+ _, mime_type, _, _ = parse_path_extnames(filename)
85
+ type = resolve_transform_type(mime_type, accept)
86
+ return nil, nil, deps if accept && !type
87
+
88
+ return nil, nil, deps unless file?(filename)
89
+
90
+ deps << build_file_digest_uri(filename)
91
+ return filename, type, deps
92
+ end
93
+
94
+ def resolve_relative_path(paths, path, dirname, accept)
95
+ filename = File.expand_path(path, dirname)
96
+ load_path, _ = paths_split(paths, dirname)
97
+ if load_path && logical_path = split_subpath(load_path, filename)
98
+ resolve_logical_path([load_path], logical_path, accept)
99
+ else
100
+ return nil, nil, Set.new
101
+ end
102
+ end
103
+
104
+ def resolve_logical_path(paths, logical_path, accept)
105
+ logical_name, mime_type, _, pipeline = parse_path_extnames(logical_path)
106
+ parsed_accept = parse_accept_options(mime_type, accept)
107
+ transformed_accepts = expand_transform_accepts(parsed_accept)
108
+ filename, mime_type, deps = resolve_under_paths(paths, logical_name, transformed_accepts)
109
+
110
+ if filename
111
+ deps << build_file_digest_uri(filename)
112
+ type = resolve_transform_type(mime_type, parsed_accept)
113
+ return filename, type, pipeline, deps
114
+ else
115
+ return nil, nil, nil, deps
116
+ end
117
+ end
118
+
119
+ def resolve_under_paths(paths, logical_name, accepts)
120
+ all_deps = Set.new
121
+ return nil, nil, all_deps if accepts.empty?
122
+
123
+ logical_basename = File.basename(logical_name)
124
+ paths.each do |load_path|
125
+ candidates, deps = path_matches(load_path, logical_name, logical_basename)
126
+ all_deps.merge(deps)
127
+ candidate = find_best_q_match(accepts, candidates) do |c, matcher|
128
+ match_mime_type?(c[1] || "application/octet-stream", matcher)
129
+ end
130
+ return candidate + [all_deps] if candidate
131
+ end
132
+
133
+ return nil, nil, all_deps
134
+ end
135
+
136
+ def parse_accept_options(mime_type, types)
137
+ accepts = []
138
+ accepts += parse_q_values(types) if types
139
+
140
+ if mime_type
141
+ if accepts.empty? || accepts.any? { |accept, _| match_mime_type?(mime_type, accept) }
142
+ accepts = [[mime_type, 1.0]]
143
+ else
144
+ return []
145
+ end
146
+ end
147
+
148
+ if accepts.empty?
149
+ accepts << ['*/*', 1.0]
150
+ end
151
+
152
+ accepts
153
+ end
154
+
155
+ def path_matches(load_path, logical_name, logical_basename)
156
+ dirname = File.dirname(File.join(load_path, logical_name))
157
+ candidates = dirname_matches(dirname, logical_basename)
158
+ deps = file_digest_dependency_set(dirname)
159
+
160
+ result = resolve_alternates(load_path, logical_name)
161
+ result[0].each do |fn|
162
+ candidates << [fn, parse_path_extnames(fn)[1]]
163
+ end
164
+ deps.merge(result[1])
165
+
166
+ dirname = File.join(load_path, logical_name)
167
+ if directory? dirname
168
+ result = dirname_matches(dirname, "index")
169
+ candidates.concat(result)
170
+ end
171
+
172
+ deps.merge(file_digest_dependency_set(dirname))
173
+
174
+ return candidates.select { |fn, _| file?(fn) }, deps
175
+ end
176
+
177
+ def dirname_matches(dirname, basename)
178
+ candidates = []
179
+ entries = self.entries(dirname)
180
+ entries.each do |entry|
181
+ next unless File.basename(entry).start_with?(basename)
182
+ name, type, _, _ = parse_path_extnames(entry)
183
+ if basename == name
184
+ candidates << [File.join(dirname, entry), type]
185
+ end
186
+ end
187
+ candidates
188
+ end
189
+
190
+ def resolve_alternates(load_path, logical_name)
191
+ return [], Set.new
192
+ end
193
+
194
+ # Internal: Returns the name, mime type and `Array` of engine extensions.
195
+ #
196
+ # "foo.js.coffee.erb"
197
+ # # => ["foo", "application/javascript", [".coffee", ".erb"]]
198
+ #
199
+ def parse_path_extnames(path)
200
+ engines = []
201
+ extname, value = match_path_extname(path, extname_map)
202
+
203
+ if extname
204
+ path = path.chomp(extname)
205
+ type, engines, pipeline = value.values_at(:type, :engines, :pipeline)
206
+ end
207
+
208
+ return path, type, engines, pipeline
209
+ end
210
+ end
211
+ end
@@ -1,29 +1,34 @@
1
1
  require 'sass'
2
2
 
3
3
  module Sprockets
4
- class SassCacheStore < ::Sass::CacheStores::Base
5
- attr_reader :environment
4
+ class SassProcessor
5
+ # Internal: Cache wrapper for Sprockets cache adapter.
6
+ class CacheStore < ::Sass::CacheStores::Base
7
+ VERSION = '1'
6
8
 
7
- def initialize(environment)
8
- @environment = environment
9
- end
9
+ def initialize(cache, version)
10
+ @cache, @version = cache, "#{VERSION}/#{version}"
11
+ end
10
12
 
11
- def _store(key, version, sha, contents)
12
- environment.cache_set("sass/#{key}", {:version => version, :sha => sha, :contents => contents})
13
- end
13
+ def _store(key, version, sha, contents)
14
+ @cache.set("#{@version}/#{version}/#{key}/#{sha}", contents, true)
15
+ end
14
16
 
15
- def _retrieve(key, version, sha)
16
- if obj = environment.cache_get("sass/#{key}")
17
- return unless obj[:version] == version
18
- return unless obj[:sha] == sha
19
- obj[:contents]
20
- else
21
- nil
17
+ def _retrieve(key, version, sha)
18
+ @cache.get("#{@version}/#{version}/#{key}/#{sha}", true)
19
+ end
20
+
21
+ def path_to(key)
22
+ key
22
23
  end
23
24
  end
25
+ end
24
26
 
25
- def path_to(key)
26
- key
27
+ # Deprecated: Use Sprockets::SassProcessor::CacheStore instead.
28
+ class SassCacheStore < SassProcessor::CacheStore
29
+ def initialize(*args)
30
+ Deprecation.new.warn "SassCacheStore is deprecated please use SassProcessor::CacheStore instead"
31
+ super
27
32
  end
28
33
  end
29
34
  end
@@ -1,27 +1,51 @@
1
- require 'tilt'
1
+ require 'sprockets/autoload'
2
+ require 'sprockets/digest_utils'
2
3
 
3
4
  module Sprockets
4
- class SassCompressor < Tilt::Template
5
- self.default_mime_type = 'text/css'
5
+ # Public: Sass CSS minifier.
6
+ #
7
+ # To accept the default options
8
+ #
9
+ # environment.register_bundle_processor 'text/css',
10
+ # Sprockets::SassCompressor
11
+ #
12
+ # Or to pass options to the Sass::Engine class.
13
+ #
14
+ # environment.register_bundle_processor 'text/css',
15
+ # Sprockets::SassCompressor.new({ ... })
16
+ #
17
+ class SassCompressor
18
+ VERSION = '1'
6
19
 
7
- def self.engine_initialized?
8
- defined?(::Sass::Engine)
20
+ # Public: Return singleton instance with default options.
21
+ #
22
+ # Returns SassCompressor object.
23
+ def self.instance
24
+ @instance ||= new
9
25
  end
10
26
 
11
- def initialize_engine
12
- require_template_library 'sass'
27
+ def self.call(input)
28
+ instance.call(input)
13
29
  end
14
30
 
15
- def prepare
31
+ def self.cache_key
32
+ instance.cache_key
16
33
  end
17
34
 
18
- def evaluate(context, locals, &block)
19
- ::Sass::Engine.new(data, {
20
- :syntax => :scss,
21
- :cache => false,
22
- :read_cache => false,
23
- :style => :compressed
24
- }).render
35
+ attr_reader :cache_key
36
+
37
+ def initialize(options = {})
38
+ @options = {
39
+ syntax: :scss,
40
+ cache: false,
41
+ read_cache: false,
42
+ style: :compressed
43
+ }.merge(options).freeze
44
+ @cache_key = "#{self.class.name}:#{Autoload::Sass::VERSION}:#{VERSION}:#{DigestUtils.digest(options)}".freeze
45
+ end
46
+
47
+ def call(input)
48
+ Autoload::Sass::Engine.new(input[:data], @options).render
25
49
  end
26
50
  end
27
51
  end
@@ -1,70 +1,2 @@
1
- require 'sass'
2
-
3
- module Sprockets
4
- module SassFunctions
5
- def asset_path(path)
6
- ::Sass::Script::String.new(sprockets_context.asset_path(path.value), :string)
7
- end
8
-
9
- def asset_url(path)
10
- ::Sass::Script::String.new("url(" + sprockets_context.asset_path(path.value) + ")")
11
- end
12
-
13
- def image_path(path)
14
- ::Sass::Script::String.new(sprockets_context.image_path(path.value), :string)
15
- end
16
-
17
- def image_url(path)
18
- ::Sass::Script::String.new("url(" + sprockets_context.image_path(path.value) + ")")
19
- end
20
-
21
- def video_path(path)
22
- ::Sass::Script::String.new(sprockets_context.video_path(path.value), :string)
23
- end
24
-
25
- def video_url(path)
26
- ::Sass::Script::String.new("url(" + sprockets_context.video_path(path.value) + ")")
27
- end
28
-
29
- def audio_path(path)
30
- ::Sass::Script::String.new(sprockets_context.audio_path(path.value), :string)
31
- end
32
-
33
- def audio_url(path)
34
- ::Sass::Script::String.new("url(" + sprockets_context.audio_path(path.value) + ")")
35
- end
36
-
37
- def font_path(path)
38
- ::Sass::Script::String.new(sprockets_context.font_path(path.value), :string)
39
- end
40
-
41
- def font_url(path)
42
- ::Sass::Script::String.new("url(" + sprockets_context.font_path(path.value) + ")")
43
- end
44
-
45
- def javascript_path(path)
46
- ::Sass::Script::String.new(sprockets_context.javascript_path(path.value), :string)
47
- end
48
-
49
- def javascript_url(path)
50
- ::Sass::Script::String.new("url(" + sprockets_context.javascript_path(path.value) + ")")
51
- end
52
-
53
- def stylesheet_path(path)
54
- ::Sass::Script::String.new(sprockets_context.stylesheet_path(path.value), :string)
55
- end
56
-
57
- def stylesheet_url(path)
58
- ::Sass::Script::String.new("url(" + sprockets_context.stylesheet_path(path.value) + ")")
59
- end
60
-
61
- protected
62
- def sprockets_context
63
- options[:sprockets][:context]
64
- end
65
-
66
- def sprockets_environment
67
- options[:sprockets][:environment]
68
- end
69
- end
70
- end
1
+ # Deprecated: Require sprockets/sass_processor instead
2
+ require 'sprockets/sass_processor'
@@ -1,30 +1,2 @@
1
- require 'sass'
2
-
3
- module Sprockets
4
- # This custom importer that tracks all imported filenames during
5
- # compile.
6
- class SassImporter < ::Sass::Importers::Filesystem
7
- attr_reader :imported_filenames
8
-
9
- def initialize(*args)
10
- @imported_filenames = []
11
- super
12
- end
13
-
14
- def find_relative(*args)
15
- engine = super
16
- if engine && (filename = engine.options[:filename])
17
- @imported_filenames << filename
18
- end
19
- engine
20
- end
21
-
22
- def find(*args)
23
- engine = super
24
- if engine && (filename = engine.options[:filename])
25
- @imported_filenames << filename
26
- end
27
- engine
28
- end
29
- end
30
- end
1
+ # Deprecated: Require sprockets/sass_processor instead
2
+ require 'sprockets/sass_processor'