lib/sprockets/processing.rb in sprockets-2.12.5 vs lib/sprockets/processing.rb in sprockets-3.0.0.beta.1
- old
+ new
@@ -1,66 +1,45 @@
require 'sprockets/engines'
+require 'sprockets/lazy_processor'
+require 'sprockets/legacy_proc_processor'
+require 'sprockets/legacy_tilt_processor'
require 'sprockets/mime'
-require 'sprockets/processor'
require 'sprockets/utils'
module Sprockets
# `Processing` is an internal mixin whose public methods are exposed on
- # the `Environment` and `Index` classes.
+ # the `Environment` and `CachedEnvironment` classes.
module Processing
- # Returns an `Array` of format extension `String`s.
- #
- # format_extensions
- # # => ['.js', '.css']
- #
- def format_extensions
- @trail.extensions - @engines.keys
- end
-
- # Deprecated alias for `preprocessors`.
- def processors(*args)
- preprocessors(*args)
- end
-
- # Returns an `Array` of `Processor` classes. If a `mime_type`
- # argument is supplied, the processors registered under that
- # extension will be returned.
- #
# Preprocessors are ran before Postprocessors and Engine
# processors.
+ attr_reader :preprocessors
+
+ # Internal: Find and load preprocessors by mime type.
#
- # All `Processor`s must follow the `Tilt::Template` interface. It is
- # recommended to subclass `Tilt::Template`.
- def preprocessors(mime_type = nil)
- if mime_type
- @preprocessors[mime_type].dup
- else
- deep_copy_hash(@preprocessors)
+ # mime_type - String MIME type.
+ #
+ # Returns Array of Procs.
+ def unwrap_preprocessors(mime_type)
+ preprocessors[mime_type].map do |processor|
+ unwrap_processor(processor)
end
end
- # Returns an `Array` of `Processor` classes. If a `mime_type`
- # argument is supplied, the processors registered under that
- # extension will be returned.
- #
# Postprocessors are ran after Preprocessors and Engine processors.
+ attr_reader :postprocessors
+
+ # Internal: Find and load postprocessors by mime type.
#
- # All `Processor`s must follow the `Tilt::Template` interface. It is
- # recommended to subclass `Tilt::Template`.
- def postprocessors(mime_type = nil)
- if mime_type
- @postprocessors[mime_type].dup
- else
- deep_copy_hash(@postprocessors)
+ # mime_type - String MIME type.
+ #
+ # Returns Array of Procs.
+ def unwrap_postprocessors(mime_type)
+ postprocessors[mime_type].map do |processor|
+ unwrap_processor(processor)
end
end
- # Deprecated alias for `register_preprocessor`.
- def register_processor(*args, &block)
- register_preprocessor(*args, &block)
- end
-
# Registers a new Preprocessor `klass` for `mime_type`.
#
# register_preprocessor 'text/css', Sprockets::DirectiveProcessor
#
# A block can be passed for to create a shorthand processor.
@@ -68,139 +47,251 @@
# register_preprocessor 'text/css', :my_processor do |context, data|
# data.gsub(...)
# end
#
def register_preprocessor(mime_type, klass, &block)
- if block_given?
- name = klass.to_s
- klass = Class.new(Processor) do
- @name = name
- @processor = block
- end
+ mutate_hash_config(:preprocessors, mime_type) do |processors|
+ processors.push(wrap_processor(klass, block))
+ processors
end
-
- @preprocessors[mime_type].push(klass)
end
# Registers a new Postprocessor `klass` for `mime_type`.
#
- # register_postprocessor 'text/css', Sprockets::CharsetNormalizer
+ # register_postprocessor 'application/javascript', Sprockets::DirectiveProcessor
#
# A block can be passed for to create a shorthand processor.
#
- # register_postprocessor 'text/css', :my_processor do |context, data|
+ # register_postprocessor 'application/javascript', :my_processor do |context, data|
# data.gsub(...)
# end
#
- def register_postprocessor(mime_type, klass, &block)
- if block_given?
- name = klass.to_s
- klass = Class.new(Processor) do
- @name = name
- @processor = block
- end
+ def register_postprocessor(mime_type, klass, proc = nil, &block)
+ proc ||= block
+ mutate_hash_config(:postprocessors, mime_type) do |processors|
+ processors.push(wrap_processor(klass, proc))
+ processors
end
-
- @postprocessors[mime_type].push(klass)
end
- # Deprecated alias for `unregister_preprocessor`.
- def unregister_processor(*args)
- unregister_preprocessor(*args)
- end
-
# Remove Preprocessor `klass` for `mime_type`.
#
# unregister_preprocessor 'text/css', Sprockets::DirectiveProcessor
#
def unregister_preprocessor(mime_type, klass)
if klass.is_a?(String) || klass.is_a?(Symbol)
- klass = @preprocessors[mime_type].detect { |cls|
- cls.respond_to?(:name) &&
- cls.name == "Sprockets::Processor (#{klass})"
+ klass = preprocessors[mime_type].detect { |cls|
+ cls.respond_to?(:name) && cls.name == "Sprockets::LegacyProcProcessor (#{klass})"
}
end
- @preprocessors[mime_type].delete(klass)
+ mutate_hash_config(:preprocessors, mime_type) do |processors|
+ processors.delete(klass)
+ processors
+ end
end
# Remove Postprocessor `klass` for `mime_type`.
#
# unregister_postprocessor 'text/css', Sprockets::DirectiveProcessor
#
def unregister_postprocessor(mime_type, klass)
if klass.is_a?(String) || klass.is_a?(Symbol)
- klass = @postprocessors[mime_type].detect { |cls|
- cls.respond_to?(:name) &&
- cls.name == "Sprockets::Processor (#{klass})"
+ klass = postprocessors[mime_type].detect { |cls|
+ cls.respond_to?(:name) && cls.name == "Sprockets::LegacyProcProcessor (#{klass})"
}
end
- @postprocessors[mime_type].delete(klass)
+ mutate_hash_config(:postprocessors, mime_type) do |processors|
+ processors.delete(klass)
+ processors
+ end
end
- # Returns an `Array` of `Processor` classes. If a `mime_type`
- # argument is supplied, the processors registered under that
- # extension will be returned.
- #
# Bundle Processors are ran on concatenated assets rather than
# individual files.
+ attr_reader :bundle_processors
+
+ # Internal: Find and load bundle processors by mime type.
#
- # All `Processor`s must follow the `Tilt::Template` interface. It is
- # recommended to subclass `Tilt::Template`.
- def bundle_processors(mime_type = nil)
- if mime_type
- @bundle_processors[mime_type].dup
- else
- deep_copy_hash(@bundle_processors)
+ # mime_type - String MIME type.
+ #
+ # Returns Array of Procs.
+ def unwrap_bundle_processors(mime_type)
+ bundle_processors[mime_type].map do |processor|
+ unwrap_processor(processor)
end
end
# Registers a new Bundle Processor `klass` for `mime_type`.
#
- # register_bundle_processor 'text/css', Sprockets::CharsetNormalizer
+ # register_bundle_processor 'application/javascript', Sprockets::DirectiveProcessor
#
# A block can be passed for to create a shorthand processor.
#
- # register_bundle_processor 'text/css', :my_processor do |context, data|
+ # register_bundle_processor 'application/javascript', :my_processor do |context, data|
# data.gsub(...)
# end
#
def register_bundle_processor(mime_type, klass, &block)
- if block_given?
- name = klass.to_s
- klass = Class.new(Processor) do
- @name = name
- @processor = block
- end
+ mutate_hash_config(:bundle_processors, mime_type) do |processors|
+ processors.push(wrap_processor(klass, block))
+ processors
end
-
- @bundle_processors[mime_type].push(klass)
end
# Remove Bundle Processor `klass` for `mime_type`.
#
- # unregister_bundle_processor 'text/css', Sprockets::CharsetNormalizer
+ # unregister_bundle_processor 'application/javascript', Sprockets::DirectiveProcessor
#
def unregister_bundle_processor(mime_type, klass)
if klass.is_a?(String) || klass.is_a?(Symbol)
- klass = @bundle_processors[mime_type].detect { |cls|
- cls.respond_to?(:name) &&
- cls.name == "Sprockets::Processor (#{klass})"
+ klass = bundle_processors[mime_type].detect { |cls|
+ cls.respond_to?(:name) && cls.name == "Sprockets::LegacyProcProcessor (#{klass})"
}
end
- @bundle_processors[mime_type].delete(klass)
+ mutate_hash_config(:bundle_processors, mime_type) do |processors|
+ processors.delete(klass)
+ processors
+ end
end
- private
- def add_engine_to_trail(ext, klass)
- @trail.append_extension(ext.to_s)
+ # Internal: Run processors on filename and data.
+ #
+ # Returns Hash.
+ def process(processors, uri, filename, load_path, name, content_type)
+ data, metadata = nil, {}
- if klass.respond_to?(:default_mime_type) && klass.default_mime_type
- if format_ext = extension_for_mime_type(klass.default_mime_type)
- @trail.alias_extension(ext.to_s, format_ext)
+ input = {
+ environment: self,
+ cache: cache,
+ uri: uri,
+ filename: filename,
+ load_path: load_path,
+ name: name,
+ content_type: content_type,
+ metadata: metadata
+ }
+
+ processors.each do |processor|
+ begin
+ result = processor.call(input.merge(data: data, metadata: metadata))
+ case result
+ when NilClass
+ # noop
+ when Hash
+ data = result[:data]
+ metadata = metadata.merge(result)
+ metadata.delete(:data)
+ when String
+ data = result
+ else
+ raise Error, "invalid processor return type: #{result.class}"
end
end
+ end
+
+ {
+ source: data,
+ charset: data.encoding.name.downcase,
+ length: data.bytesize,
+ digest: digest_class.hexdigest(data),
+ metadata: metadata
+ }
+ end
+
+ # Internal: Two dimensional Hash of reducer functions for a given mime type
+ # and asset metadata key.
+ attr_reader :bundle_reducers
+
+ # Public: Register bundle reducer function.
+ #
+ # Examples
+ #
+ # Sprockets.register_bundle_reducer 'application/javascript', :jshint_errors, [], :+
+ #
+ # Sprockets.register_bundle_reducer 'text/css', :selector_count, 0 { |total, count|
+ # total + count
+ # }
+ #
+ # mime_type - String MIME Type. Use '*/*' applies to all types.
+ # key - Symbol metadata key
+ # initial - Initial memo to pass to the reduce funciton (default: nil)
+ # block - Proc accepting the memo accumulator and current value
+ #
+ # Returns nothing.
+ def register_bundle_reducer(mime_type, key, *args, &block)
+ case args.size
+ when 0
+ reducer = block
+ when 1
+ if block_given?
+ initial = args[0]
+ reducer = block
+ else
+ initial = nil
+ reducer = args[0].to_proc
+ end
+ when 2
+ initial = args[0]
+ reducer = args[1].to_proc
+ else
+ raise ArgumentError, "wrong number of arguments (#{args.size} for 0..2)"
+ end
+
+ mutate_hash_config(:bundle_reducers, mime_type) do |reducers|
+ reducers.merge(key => [initial, reducer])
+ end
+ end
+
+ # Internal: Gather all bundle reducer functions for MIME type.
+ #
+ # mime_type - String MIME type
+ #
+ # Returns an Array of [initial, reducer_proc] pairs.
+ def unwrap_bundle_reducers(mime_type)
+ self.bundle_reducers['*/*'].merge(self.bundle_reducers[mime_type])
+ end
+
+ # Internal: Run bundle reducers on set of Assets producing a reduced
+ # metadata Hash.
+ #
+ # assets - Array of Assets
+ # reducers - Array of [initial, reducer_proc] pairs
+ #
+ # Returns reduced asset metadata Hash.
+ def process_bundle_reducers(assets, reducers)
+ initial = {}
+ reducers.each do |k, (v, _)|
+ initial[k] = v if v
+ end
+
+ assets.reduce(initial) do |h, asset|
+ reducers.each do |k, (_, block)|
+ value = k == :data ? asset.source : asset.metadata[k]
+ h[k] = h.key?(k) ? block.call(h[k], value) : value
+ end
+ h
+ end
+ end
+
+ private
+ def wrap_processor(klass, proc)
+ if !proc
+ if klass.class == Sprockets::LazyProcessor || klass.respond_to?(:call)
+ klass
+ else
+ LegacyTiltProcessor.new(klass)
+ end
+ elsif proc.respond_to?(:arity) && proc.arity == 2
+ LegacyProcProcessor.new(klass.to_s, proc)
+ else
+ proc
+ end
+ end
+
+ def unwrap_processor(processor)
+ processor.respond_to?(:unwrap) ? processor.unwrap : processor
end
end
end