sprockets 2.2.3 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +68 -0
  3. data/README.md +482 -255
  4. data/bin/sprockets +20 -7
  5. data/lib/rake/sprocketstask.rb +28 -15
  6. data/lib/sprockets/add_source_map_comment_to_asset_processor.rb +60 -0
  7. data/lib/sprockets/asset.rb +142 -207
  8. data/lib/sprockets/autoload/babel.rb +8 -0
  9. data/lib/sprockets/autoload/closure.rb +8 -0
  10. data/lib/sprockets/autoload/coffee_script.rb +8 -0
  11. data/lib/sprockets/autoload/eco.rb +8 -0
  12. data/lib/sprockets/autoload/ejs.rb +8 -0
  13. data/lib/sprockets/autoload/jsminc.rb +8 -0
  14. data/lib/sprockets/autoload/sass.rb +8 -0
  15. data/lib/sprockets/autoload/sassc.rb +8 -0
  16. data/lib/sprockets/autoload/uglifier.rb +8 -0
  17. data/lib/sprockets/autoload/yui.rb +8 -0
  18. data/lib/sprockets/autoload/zopfli.rb +7 -0
  19. data/lib/sprockets/autoload.rb +16 -0
  20. data/lib/sprockets/babel_processor.rb +66 -0
  21. data/lib/sprockets/base.rb +89 -249
  22. data/lib/sprockets/bower.rb +61 -0
  23. data/lib/sprockets/bundle.rb +105 -0
  24. data/lib/sprockets/cache/file_store.rb +190 -14
  25. data/lib/sprockets/cache/memory_store.rb +75 -0
  26. data/lib/sprockets/cache/null_store.rb +54 -0
  27. data/lib/sprockets/cache.rb +271 -0
  28. data/lib/sprockets/cached_environment.rb +64 -0
  29. data/lib/sprockets/closure_compressor.rb +48 -0
  30. data/lib/sprockets/coffee_script_processor.rb +39 -0
  31. data/lib/sprockets/compressing.rb +134 -0
  32. data/lib/sprockets/configuration.rb +79 -0
  33. data/lib/sprockets/context.rb +204 -135
  34. data/lib/sprockets/dependencies.rb +74 -0
  35. data/lib/sprockets/digest_utils.rb +200 -0
  36. data/lib/sprockets/directive_processor.rb +224 -216
  37. data/lib/sprockets/eco_processor.rb +33 -0
  38. data/lib/sprockets/ejs_processor.rb +32 -0
  39. data/lib/sprockets/encoding_utils.rb +262 -0
  40. data/lib/sprockets/environment.rb +23 -68
  41. data/lib/sprockets/erb_processor.rb +37 -0
  42. data/lib/sprockets/errors.rb +6 -13
  43. data/lib/sprockets/exporters/base.rb +72 -0
  44. data/lib/sprockets/exporters/file_exporter.rb +24 -0
  45. data/lib/sprockets/exporters/zlib_exporter.rb +33 -0
  46. data/lib/sprockets/exporters/zopfli_exporter.rb +14 -0
  47. data/lib/sprockets/exporting.rb +73 -0
  48. data/lib/sprockets/file_reader.rb +16 -0
  49. data/lib/sprockets/http_utils.rb +135 -0
  50. data/lib/sprockets/jsminc_compressor.rb +32 -0
  51. data/lib/sprockets/jst_processor.rb +36 -19
  52. data/lib/sprockets/loader.rb +343 -0
  53. data/lib/sprockets/manifest.rb +231 -96
  54. data/lib/sprockets/manifest_utils.rb +48 -0
  55. data/lib/sprockets/mime.rb +80 -32
  56. data/lib/sprockets/npm.rb +52 -0
  57. data/lib/sprockets/path_dependency_utils.rb +77 -0
  58. data/lib/sprockets/path_digest_utils.rb +48 -0
  59. data/lib/sprockets/path_utils.rb +367 -0
  60. data/lib/sprockets/paths.rb +82 -0
  61. data/lib/sprockets/preprocessors/default_source_map.rb +49 -0
  62. data/lib/sprockets/processing.rb +140 -192
  63. data/lib/sprockets/processor_utils.rb +169 -0
  64. data/lib/sprockets/resolve.rb +295 -0
  65. data/lib/sprockets/sass_cache_store.rb +30 -0
  66. data/lib/sprockets/sass_compressor.rb +63 -0
  67. data/lib/sprockets/sass_functions.rb +3 -0
  68. data/lib/sprockets/sass_importer.rb +3 -0
  69. data/lib/sprockets/sass_processor.rb +313 -0
  70. data/lib/sprockets/sassc_compressor.rb +56 -0
  71. data/lib/sprockets/sassc_processor.rb +297 -0
  72. data/lib/sprockets/server.rb +138 -90
  73. data/lib/sprockets/source_map_processor.rb +66 -0
  74. data/lib/sprockets/source_map_utils.rb +483 -0
  75. data/lib/sprockets/transformers.rb +173 -0
  76. data/lib/sprockets/uglifier_compressor.rb +66 -0
  77. data/lib/sprockets/unloaded_asset.rb +139 -0
  78. data/lib/sprockets/uri_tar.rb +99 -0
  79. data/lib/sprockets/uri_utils.rb +191 -0
  80. data/lib/sprockets/utils/gzip.rb +99 -0
  81. data/lib/sprockets/utils.rb +186 -53
  82. data/lib/sprockets/version.rb +2 -1
  83. data/lib/sprockets/yui_compressor.rb +56 -0
  84. data/lib/sprockets.rb +217 -52
  85. metadata +250 -59
  86. data/LICENSE +0 -21
  87. data/lib/sprockets/asset_attributes.rb +0 -126
  88. data/lib/sprockets/bundled_asset.rb +0 -79
  89. data/lib/sprockets/caching.rb +0 -96
  90. data/lib/sprockets/charset_normalizer.rb +0 -41
  91. data/lib/sprockets/eco_template.rb +0 -38
  92. data/lib/sprockets/ejs_template.rb +0 -37
  93. data/lib/sprockets/engines.rb +0 -74
  94. data/lib/sprockets/index.rb +0 -99
  95. data/lib/sprockets/processed_asset.rb +0 -152
  96. data/lib/sprockets/processor.rb +0 -32
  97. data/lib/sprockets/safety_colons.rb +0 -28
  98. data/lib/sprockets/static_asset.rb +0 -57
  99. data/lib/sprockets/trail.rb +0 -90
@@ -1,96 +0,0 @@
1
- module Sprockets
2
- # `Caching` is an internal mixin whose public methods are exposed on
3
- # the `Environment` and `Index` classes.
4
- module Caching
5
- protected
6
- # Cache helper method. Takes a `path` argument which maybe a
7
- # logical path or fully expanded path. The `&block` is passed
8
- # for finding and building the asset if its not in cache.
9
- def cache_asset(path)
10
- # If `cache` is not set, return fast
11
- if cache.nil?
12
- yield
13
-
14
- # Check cache for `path`
15
- elsif (asset = Asset.from_hash(self, cache_get_hash(path.to_s))) && asset.fresh?(self)
16
- asset
17
-
18
- # Otherwise yield block that slowly finds and builds the asset
19
- elsif asset = yield
20
- hash = {}
21
- asset.encode_with(hash)
22
-
23
- # Save the asset to its path
24
- cache_set_hash(path.to_s, hash)
25
-
26
- # Since path maybe a logical or full pathname, save the
27
- # asset its its full path too
28
- if path.to_s != asset.pathname.to_s
29
- cache_set_hash(asset.pathname.to_s, hash)
30
- end
31
-
32
- asset
33
- end
34
- end
35
-
36
- private
37
- # Strips `Environment#root` from key to make the key work
38
- # consisently across different servers. The key is also hashed
39
- # so it does not exceed 250 characters.
40
- def expand_cache_key(key)
41
- File.join('sprockets', digest_class.hexdigest(key.sub(root, '')))
42
- end
43
-
44
- def cache_get_hash(key)
45
- hash = cache_get(expand_cache_key(key))
46
- if hash.is_a?(Hash) && digest.hexdigest == hash['_version']
47
- hash
48
- end
49
- end
50
-
51
- def cache_set_hash(key, hash)
52
- hash['_version'] = digest.hexdigest
53
- cache_set(expand_cache_key(key), hash)
54
- hash
55
- end
56
-
57
- # Low level cache getter for `key`. Checks a number of supported
58
- # cache interfaces.
59
- def cache_get(key)
60
- # `Cache#get(key)` for Memcache
61
- if cache.respond_to?(:get)
62
- cache.get(key)
63
-
64
- # `Cache#[key]` so `Hash` can be used
65
- elsif cache.respond_to?(:[])
66
- cache[key]
67
-
68
- # `Cache#read(key)` for `ActiveSupport::Cache` support
69
- elsif cache.respond_to?(:read)
70
- cache.read(key)
71
-
72
- else
73
- nil
74
- end
75
- end
76
-
77
- # Low level cache setter for `key`. Checks a number of supported
78
- # cache interfaces.
79
- def cache_set(key, value)
80
- # `Cache#set(key, value)` for Memcache
81
- if cache.respond_to?(:set)
82
- cache.set(key, value)
83
-
84
- # `Cache#[key]=value` so `Hash` can be used
85
- elsif cache.respond_to?(:[]=)
86
- cache[key] = value
87
-
88
- # `Cache#write(key, value)` for `ActiveSupport::Cache` support
89
- elsif cache.respond_to?(:write)
90
- cache.write(key, value)
91
- end
92
-
93
- value
94
- end
95
- end
96
- end
@@ -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,38 +0,0 @@
1
- require 'tilt'
2
-
3
- module Sprockets
4
- # Tilt engine class for the Eco compiler. Depends on the `eco` gem.
5
- #
6
- # For more infomation see:
7
- #
8
- # https://github.com/sstephenson/ruby-eco
9
- # https://github.com/sstephenson/eco
10
- #
11
- class EcoTemplate < Tilt::Template
12
- # Check to see if Eco is loaded
13
- def self.engine_initialized?
14
- defined? ::Eco
15
- end
16
-
17
- # Autoload eco library. If the library isn't loaded, Tilt will produce
18
- # a thread safetly warning. If you intend to use `.eco` files, you
19
- # should explicitly require it.
20
- def initialize_engine
21
- require_template_library 'eco'
22
- end
23
-
24
- def prepare
25
- end
26
-
27
- # Compile template data with Eco compiler.
28
- #
29
- # Returns a JS function definition String. The result should be
30
- # assigned to a JS variable.
31
- #
32
- # # => "function(...) {...}"
33
- #
34
- def evaluate(scope, locals, &block)
35
- Eco.compile(data)
36
- end
37
- end
38
- end
@@ -1,37 +0,0 @@
1
- require 'tilt'
2
-
3
- module Sprockets
4
- # Tilt engine class for the EJS compiler. Depends on the `ejs` gem.
5
- #
6
- # For more infomation see:
7
- #
8
- # https://github.com/sstephenson/ruby-ejs
9
- #
10
- class EjsTemplate < Tilt::Template
11
- # Check to see if EJS is loaded
12
- def self.engine_initialized?
13
- defined? ::EJS
14
- end
15
-
16
- # Autoload ejs library. If the library isn't loaded, Tilt will produce
17
- # a thread safetly warning. If you intend to use `.ejs` files, you
18
- # should explicitly require it.
19
- def initialize_engine
20
- require_template_library 'ejs'
21
- end
22
-
23
- def prepare
24
- end
25
-
26
- # Compile template data with EJS compiler.
27
- #
28
- # Returns a JS function definition String. The result should be
29
- # assigned to a JS variable.
30
- #
31
- # # => "function(obj){...}"
32
- #
33
- def evaluate(scope, locals, &block)
34
- EJS.compile(data)
35
- end
36
- end
37
- end
@@ -1,74 +0,0 @@
1
- require 'sprockets/eco_template'
2
- require 'sprockets/ejs_template'
3
- require 'sprockets/jst_processor'
4
- require 'sprockets/utils'
5
- require 'tilt'
6
-
7
- module Sprockets
8
- # `Engines` provides a global and `Environment` instance registry.
9
- #
10
- # An engine is a type of processor that is bound to an filename
11
- # extension. `application.js.coffee` indicates that the
12
- # `CoffeeScriptTemplate` engine will be ran on the file.
13
- #
14
- # Extensions can be stacked and will be evaulated from right to
15
- # left. `application.js.coffee.erb` will first run `ERBTemplate`
16
- # then `CoffeeScriptTemplate`.
17
- #
18
- # All `Engine`s must follow the `Tilt::Template` interface. It is
19
- # recommended to subclass `Tilt::Template`.
20
- #
21
- # Its recommended that you register engine changes on your local
22
- # `Environment` instance.
23
- #
24
- # environment.register_engine '.foo', FooProcessor
25
- #
26
- # The global registry is exposed for plugins to register themselves.
27
- #
28
- # Sprockets.register_engine '.sass', SassTemplate
29
- #
30
- module Engines
31
- # Returns an `Array` of `Engine`s registered on the
32
- # `Environment`. If an `ext` argument is supplied, the `Engine`
33
- # register under that extension will be returned.
34
- #
35
- # environment.engines
36
- # # => [CoffeeScriptTemplate, SassTemplate, ...]
37
- #
38
- # environment.engines('.coffee')
39
- # # => CoffeeScriptTemplate
40
- #
41
- def engines(ext = nil)
42
- if ext
43
- ext = Sprockets::Utils.normalize_extension(ext)
44
- @engines[ext]
45
- else
46
- @engines.dup
47
- end
48
- end
49
-
50
- # Returns an `Array` of engine extension `String`s.
51
- #
52
- # environment.engine_extensions
53
- # # => ['.coffee', '.sass', ...]
54
- def engine_extensions
55
- @engines.keys
56
- end
57
-
58
- # Registers a new Engine `klass` for `ext`. If the `ext` already
59
- # has an engine registered, it will be overridden.
60
- #
61
- # environment.register_engine '.coffee', CoffeeScriptTemplate
62
- #
63
- def register_engine(ext, klass)
64
- ext = Sprockets::Utils.normalize_extension(ext)
65
- @engines[ext] = klass
66
- end
67
-
68
- private
69
- def deep_copy_hash(hash)
70
- initial = Hash.new { |h, k| h[k] = [] }
71
- hash.inject(initial) { |h, (k, a)| h[k] = a.dup; h }
72
- end
73
- end
74
- end
@@ -1,99 +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
-
35
- # Initialize caches
36
- @assets = {}
37
- @digests = {}
38
- end
39
-
40
- # No-op return self as index
41
- def index
42
- self
43
- end
44
-
45
- # Cache calls to `file_digest`
46
- def file_digest(pathname)
47
- key = pathname.to_s
48
- if @digests.key?(key)
49
- @digests[key]
50
- else
51
- @digests[key] = super
52
- end
53
- end
54
-
55
- # Cache `find_asset` calls
56
- def find_asset(path, options = {})
57
- options[:bundle] = true unless options.key?(:bundle)
58
- if asset = @assets[cache_key_for(path, options)]
59
- asset
60
- elsif asset = super
61
- logical_path_cache_key = cache_key_for(path, options)
62
- full_path_cache_key = cache_key_for(asset.pathname, options)
63
-
64
- # Cache on Index
65
- @assets[logical_path_cache_key] = @assets[full_path_cache_key] = asset
66
-
67
- # Push cache upstream to Environment
68
- @environment.instance_eval do
69
- @assets[logical_path_cache_key] = @assets[full_path_cache_key] = asset
70
- end
71
-
72
- asset
73
- end
74
- end
75
-
76
- protected
77
- # Index is immutable, any methods that try to clear the cache
78
- # should bomb.
79
- def expire_index!
80
- raise TypeError, "can't modify immutable index"
81
- end
82
-
83
- # Cache asset building in memory and in persisted cache.
84
- def build_asset(path, pathname, options)
85
- # Memory cache
86
- key = cache_key_for(pathname, options)
87
- if @assets.key?(key)
88
- @assets[key]
89
- else
90
- @assets[key] = begin
91
- # Persisted cache
92
- cache_asset(key) do
93
- super
94
- end
95
- end
96
- end
97
- end
98
- end
99
- 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.info "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 :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,57 +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
- options[:compress] ||= File.extname(filename) == '.gz'
25
-
26
- FileUtils.mkdir_p File.dirname(filename)
27
-
28
- if options[:compress]
29
- # Open file and run it through `Zlib`
30
- pathname.open('rb') do |rd|
31
- File.open("#{filename}+", 'wb') do |wr|
32
- gz = Zlib::GzipWriter.new(wr, Zlib::BEST_COMPRESSION)
33
- buf = ""
34
- while rd.read(16384, buf)
35
- gz.write(buf)
36
- end
37
- gz.close
38
- end
39
- end
40
- else
41
- # If no compression needs to be done, we can just copy it into place.
42
- FileUtils.cp(pathname, "#{filename}+")
43
- end
44
-
45
- # Atomic write
46
- FileUtils.mv("#{filename}+", filename)
47
-
48
- # Set mtime correctly
49
- File.utime(mtime, mtime, filename)
50
-
51
- nil
52
- ensure
53
- # Ensure tmp file gets cleaned up
54
- FileUtils.rm("#{filename}+") if File.exist?("#{filename}+")
55
- end
56
- end
57
- end