sprockets 2.12.5 → 3.7.2

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -1,41 +0,0 @@
1
- require 'tilt'
2
-
3
- module Sprockets
4
- # Some browsers have issues with stylesheets that contain multiple
5
- # `@charset` definitions. The issue surfaces while using Sass since
6
- # it inserts a `@charset` at the top of each file. Then Sprockets
7
- # concatenates them together.
8
- #
9
- # The `CharsetNormalizer` processor strips out multiple `@charset`
10
- # definitions.
11
- #
12
- # The current implementation is naive. It picks the first `@charset`
13
- # it sees and strips the others. This works for most people because
14
- # the other definitions are usually `UTF-8`. A more sophisticated
15
- # approach would be to re-encode stylesheets with mixed encodings.
16
- #
17
- # This behavior can be disabled with:
18
- #
19
- # environment.unregister_bundle_processor 'text/css', Sprockets::CharsetNormalizer
20
- #
21
- class CharsetNormalizer < Tilt::Template
22
- def prepare
23
- end
24
-
25
- def evaluate(context, locals, &block)
26
- charset = nil
27
-
28
- # Find and strip out any `@charset` definitions
29
- filtered_data = data.gsub(/^@charset "([^"]+)";$/) {
30
- charset ||= $1; ""
31
- }
32
-
33
- if charset
34
- # If there was a charset, move it to the top
35
- "@charset \"#{charset}\";#{filtered_data}"
36
- else
37
- data
38
- end
39
- end
40
- end
41
- end
@@ -1,100 +0,0 @@
1
- require 'sprockets/base'
2
-
3
- module Sprockets
4
- # `Index` is a special cached version of `Environment`.
5
- #
6
- # The expection is that all of its file system methods are cached
7
- # for the instances lifetime. This makes `Index` much faster. This
8
- # behavior is ideal in production environments where the file system
9
- # is immutable.
10
- #
11
- # `Index` should not be initialized directly. Instead use
12
- # `Environment#index`.
13
- class Index < Base
14
- def initialize(environment)
15
- @environment = environment
16
-
17
- if environment.respond_to?(:default_external_encoding)
18
- @default_external_encoding = environment.default_external_encoding
19
- end
20
-
21
- # Copy environment attributes
22
- @logger = environment.logger
23
- @context_class = environment.context_class
24
- @cache = environment.cache
25
- @trail = environment.trail.index
26
- @digest = environment.digest
27
- @digest_class = environment.digest_class
28
- @version = environment.version
29
- @mime_types = environment.mime_types
30
- @engines = environment.engines
31
- @preprocessors = environment.preprocessors
32
- @postprocessors = environment.postprocessors
33
- @bundle_processors = environment.bundle_processors
34
- @compressors = environment.compressors
35
-
36
- # Initialize caches
37
- @assets = {}
38
- @digests = {}
39
- end
40
-
41
- # No-op return self as index
42
- def index
43
- self
44
- end
45
-
46
- # Cache calls to `file_digest`
47
- def file_digest(pathname)
48
- key = pathname.to_s
49
- if @digests.key?(key)
50
- @digests[key]
51
- else
52
- @digests[key] = super
53
- end
54
- end
55
-
56
- # Cache `find_asset` calls
57
- def find_asset(path, options = {})
58
- options[:bundle] = true unless options.key?(:bundle)
59
- if asset = @assets[cache_key_for(path, options)]
60
- asset
61
- elsif asset = super
62
- logical_path_cache_key = cache_key_for(path, options)
63
- full_path_cache_key = cache_key_for(asset.pathname, options)
64
-
65
- # Cache on Index
66
- @assets[logical_path_cache_key] = @assets[full_path_cache_key] = asset
67
-
68
- # Push cache upstream to Environment
69
- @environment.instance_eval do
70
- @assets[logical_path_cache_key] = @assets[full_path_cache_key] = asset
71
- end
72
-
73
- asset
74
- end
75
- end
76
-
77
- protected
78
- # Index is immutable, any methods that try to clear the cache
79
- # should bomb.
80
- def expire_index!
81
- raise TypeError, "can't modify immutable index"
82
- end
83
-
84
- # Cache asset building in memory and in persisted cache.
85
- def build_asset(path, pathname, options)
86
- # Memory cache
87
- key = cache_key_for(pathname, options)
88
- if @assets.key?(key)
89
- @assets[key]
90
- else
91
- @assets[key] = begin
92
- # Persisted cache
93
- cache_asset(key) do
94
- super
95
- end
96
- end
97
- end
98
- end
99
- end
100
- end
@@ -1,152 +0,0 @@
1
- require 'sprockets/asset'
2
- require 'sprockets/utils'
3
-
4
- module Sprockets
5
- class ProcessedAsset < Asset
6
- def initialize(environment, logical_path, pathname)
7
- super
8
-
9
- start_time = Time.now.to_f
10
-
11
- context = environment.context_class.new(environment, logical_path, pathname)
12
- @source = context.evaluate(pathname)
13
- @length = Rack::Utils.bytesize(source)
14
- @digest = environment.digest.update(source).hexdigest
15
-
16
- build_required_assets(environment, context)
17
- build_dependency_paths(environment, context)
18
-
19
- @dependency_digest = compute_dependency_digest(environment)
20
-
21
- elapsed_time = ((Time.now.to_f - start_time) * 1000).to_i
22
- environment.logger.debug "Compiled #{logical_path} (#{elapsed_time}ms) (pid #{Process.pid})"
23
- end
24
-
25
- # Interal: Used to check equality
26
- attr_reader :dependency_digest
27
-
28
- attr_reader :source
29
-
30
- # Initialize `BundledAsset` from serialized `Hash`.
31
- def init_with(environment, coder)
32
- super
33
-
34
- @source = coder['source']
35
- @dependency_digest = coder['dependency_digest']
36
-
37
- @required_assets = coder['required_paths'].map { |p|
38
- p = expand_root_path(p)
39
-
40
- unless environment.paths.detect { |path| p[path] }
41
- raise UnserializeError, "#{p} isn't in paths"
42
- end
43
-
44
- p == pathname.to_s ? self : environment.find_asset(p, :bundle => false)
45
- }
46
- @dependency_paths = coder['dependency_paths'].map { |h|
47
- DependencyFile.new(expand_root_path(h['path']), h['mtime'], h['digest'])
48
- }
49
- end
50
-
51
- # Serialize custom attributes in `BundledAsset`.
52
- def encode_with(coder)
53
- super
54
-
55
- coder['source'] = source
56
- coder['dependency_digest'] = dependency_digest
57
-
58
- coder['required_paths'] = required_assets.map { |a|
59
- relativize_root_path(a.pathname).to_s
60
- }
61
- coder['dependency_paths'] = dependency_paths.map { |d|
62
- { 'path' => relativize_root_path(d.pathname).to_s,
63
- 'mtime' => d.mtime.iso8601,
64
- 'digest' => d.digest }
65
- }
66
- end
67
-
68
- # Checks if Asset is stale by comparing the actual mtime and
69
- # digest to the inmemory model.
70
- def fresh?(environment)
71
- # Check freshness of all declared dependencies
72
- @dependency_paths.all? { |dep| dependency_fresh?(environment, dep) }
73
- end
74
-
75
- protected
76
- class DependencyFile < Struct.new(:pathname, :mtime, :digest)
77
- def initialize(pathname, mtime, digest)
78
- pathname = Pathname.new(pathname) unless pathname.is_a?(Pathname)
79
- mtime = Time.parse(mtime) if mtime.is_a?(String)
80
- super
81
- end
82
-
83
- def eql?(other)
84
- other.is_a?(DependencyFile) &&
85
- pathname.eql?(other.pathname) &&
86
- mtime.eql?(other.mtime) &&
87
- digest.eql?(other.digest)
88
- end
89
-
90
- def hash
91
- pathname.to_s.hash
92
- end
93
- end
94
-
95
- private
96
- def build_required_assets(environment, context)
97
- @required_assets = resolve_dependencies(environment, context._required_paths + [pathname.to_s]) -
98
- resolve_dependencies(environment, context._stubbed_assets.to_a)
99
- end
100
-
101
- def resolve_dependencies(environment, paths)
102
- assets = []
103
- cache = {}
104
-
105
- paths.each do |path|
106
- if path == self.pathname.to_s
107
- unless cache[self]
108
- cache[self] = true
109
- assets << self
110
- end
111
- elsif asset = environment.find_asset(path, :bundle => false)
112
- asset.required_assets.each do |asset_dependency|
113
- unless cache[asset_dependency]
114
- cache[asset_dependency] = true
115
- assets << asset_dependency
116
- end
117
- end
118
- end
119
- end
120
-
121
- assets
122
- end
123
-
124
- def build_dependency_paths(environment, context)
125
- dependency_paths = {}
126
-
127
- context._dependency_paths.each do |path|
128
- dep = DependencyFile.new(path, environment.stat(path).mtime, environment.file_digest(path).hexdigest)
129
- dependency_paths[dep] = true
130
- end
131
-
132
- context._dependency_assets.each do |path|
133
- if path == self.pathname.to_s
134
- dep = DependencyFile.new(pathname, environment.stat(path).mtime, environment.file_digest(path).hexdigest)
135
- dependency_paths[dep] = true
136
- elsif asset = environment.find_asset(path, :bundle => false)
137
- asset.dependency_paths.each do |d|
138
- dependency_paths[d] = true
139
- end
140
- end
141
- end
142
-
143
- @dependency_paths = dependency_paths.keys
144
- end
145
-
146
- def compute_dependency_digest(environment)
147
- required_assets.inject(environment.digest) { |digest, asset|
148
- digest.update asset.digest
149
- }.hexdigest
150
- end
151
- end
152
- end
@@ -1,32 +0,0 @@
1
- require 'tilt'
2
-
3
- module Sprockets
4
- # `Processor` creates an anonymous processor class from a block.
5
- #
6
- # register_preprocessor 'text/css', :my_processor do |context, data|
7
- # # ...
8
- # end
9
- #
10
- class Processor < Tilt::Template
11
- # `processor` is a lambda or block
12
- def self.processor
13
- @processor
14
- end
15
-
16
- def self.name
17
- "Sprockets::Processor (#{@name})"
18
- end
19
-
20
- def self.to_s
21
- name
22
- end
23
-
24
- def prepare
25
- end
26
-
27
- # Call processor block with `context` and `data`.
28
- def evaluate(context, locals)
29
- self.class.processor.call(context, data)
30
- end
31
- end
32
- end
@@ -1,28 +0,0 @@
1
- require 'tilt'
2
-
3
- module Sprockets
4
- # For JS developers who are colonfobic, concatenating JS files using
5
- # the module pattern usually leads to syntax errors.
6
- #
7
- # The `SafetyColons` processor will insert missing semicolons to the
8
- # end of the file.
9
- #
10
- # This behavior can be disabled with:
11
- #
12
- # environment.unregister_postprocessor 'application/javascript', Sprockets::SafetyColons
13
- #
14
- class SafetyColons < Tilt::Template
15
- def prepare
16
- end
17
-
18
- def evaluate(context, locals, &block)
19
- # If the file is blank or ends in a semicolon, leave it as is
20
- if data =~ /\A\s*\Z/m || data =~ /;\s*\Z/m
21
- data
22
- else
23
- # Otherwise, append a semicolon and newline
24
- "#{data};\n"
25
- end
26
- end
27
- end
28
- end
@@ -1,13 +0,0 @@
1
- require 'sprockets/sass_template'
2
-
3
- module Sprockets
4
- # Scss handler to replace Tilt's builtin one. See `SassTemplate` and
5
- # `SassImporter` for more infomation.
6
- class ScssTemplate < SassTemplate
7
- self.default_mime_type = 'text/css'
8
-
9
- def syntax
10
- :scss
11
- end
12
- end
13
- end
@@ -1,60 +0,0 @@
1
- require 'sprockets/asset'
2
- require 'fileutils'
3
- require 'zlib'
4
-
5
- module Sprockets
6
- # `StaticAsset`s are used for files that are served verbatim without
7
- # any processing or concatenation. These are typical images and
8
- # other binary files.
9
- class StaticAsset < Asset
10
- # Returns file contents as its `source`.
11
- def source
12
- # File is read everytime to avoid memory bloat of large binary files
13
- pathname.open('rb') { |f| f.read }
14
- end
15
-
16
- # Implemented for Rack SendFile support.
17
- def to_path
18
- pathname.to_s
19
- end
20
-
21
- # Save asset to disk.
22
- def write_to(filename, options = {})
23
- # Gzip contents if filename has '.gz'
24
- unless options.key?(:compress)
25
- options[:compress] = File.extname(filename) == '.gz' && File.extname(logical_path) != '.gz'
26
- end
27
-
28
- FileUtils.mkdir_p File.dirname(filename)
29
-
30
- if options[:compress]
31
- # Open file and run it through `Zlib`
32
- pathname.open('rb') do |rd|
33
- File.open("#{filename}+", 'wb') do |wr|
34
- gz = Zlib::GzipWriter.new(wr, Zlib::BEST_COMPRESSION)
35
- gz.mtime = mtime.to_i
36
- buf = ""
37
- while rd.read(16384, buf)
38
- gz.write(buf)
39
- end
40
- gz.close
41
- end
42
- end
43
- else
44
- # If no compression needs to be done, we can just copy it into place.
45
- FileUtils.cp(pathname, "#{filename}+")
46
- end
47
-
48
- # Atomic write
49
- FileUtils.mv("#{filename}+", filename)
50
-
51
- # Set mtime correctly
52
- File.utime(mtime, mtime, filename)
53
-
54
- nil
55
- ensure
56
- # Ensure tmp file gets cleaned up
57
- FileUtils.rm("#{filename}+") if File.exist?("#{filename}+")
58
- end
59
- end
60
- end