123456789_123456789_123456789_123456789_123456789_

Module: Sprockets::Transformers

Relationships & Source Files
Namespace Children
Classes:
Extension / Inclusion / Inheritance Descendants
Extended In:
Included In:
Super Chains via Extension / Inclusion / Inheritance
Instance Chain:
Defined in: lib/sprockets/transformers.rb

Constant Summary

Utils - Included

MODULE_INCLUDE_MUTEX, WHITESPACE_ORDINALS

ProcessorUtils - Included

VALID_METADATA_COMPOUND_TYPES, VALID_METADATA_COMPOUND_TYPES_HASH, VALID_METADATA_TYPES, VALID_METADATA_VALUE_TYPES, VALID_METADATA_VALUE_TYPES_HASH

Instance Method Summary

HTTPUtils - Included

#find_best_mime_type_match

Internal: Find the best qvalue match from an Array of available mime type options.

#find_best_q_match

Internal: Find the best qvalue match from an Array of available options.

#find_mime_type_matches

Internal: Find the all qvalue match from an Array of available mime type options.

#find_q_matches

Internal: Find all qvalue matches from an Array of available options.

#match_mime_type?

Public: Test mime type against mime range.

#match_mime_type_keys

Public: Return values from Hash where the key matches the mime type.

#parse_q_values

Internal: Parse Accept header quality values.

ProcessorUtils - Included

#call_processor

Public: Invoke processor.

#call_processors

Public: Invoke list of processors in right to left order.

#compose_processors

Public: Compose processors in right to left order.

#processor_cache_key

Internal: Get processor defined cached key.

#processors_cache_keys

Internal: Get combined cache keys for set of processors.

#validate_processor_result!

Internal: Validate returned result of calling a processor pipeline and raise a friendly user error message.

Utils - Included

#concat_javascript_sources

Internal: Accumulate asset source to buffer and append a trailing semicolon if necessary.

#dfs

Internal: Post-order Depth-First search algorithm.

#dfs_paths

Internal: Post-order Depth-First search algorithm that gathers all paths along the way.

#duplicable?

Internal: Check if object can safely be .dup’d.

#hash_reassoc

Internal: Duplicate and store key/value on new frozen hash.

#hash_reassoc1

Internal: Duplicate and store key/value on new frozen hash.

#module_include

Internal: Inject into target module for the duration of the block.

#string_end_with_semicolon?

Internal: Check if string has a trailing semicolon.

Instance Method Details

#compose_transformer_list(transformers, preprocessors, postprocessors) (private)

[ GitHub ]

  
# File 'lib/sprockets/transformers.rb', line 131

def compose_transformer_list(transformers, preprocessors, postprocessors)
  processors = []

  transformers.each do |processor|
    processors.concat postprocessors[processor.from]
    processors << processor.proc
    processors.concat preprocessors[processor.to]
  end

  if processors.size > 1
    compose_processors(*processors.reverse)
  elsif processors.size == 1
    processors.first
  end
end

#compose_transformers(transformers, types, preprocessors, postprocessors)

Internal: Compose multiple transformer steps into a single processor function.

transformers - Two level Hash of a source mime type to a target mime type types - Array of mime type steps

Returns Processor.

[ GitHub ]

  
# File 'lib/sprockets/transformers.rb', line 115

def compose_transformers(transformers, types, preprocessors, postprocessors)
  if types.length < 2
    raise ArgumentError, "too few transform types: #{types.inspect}"
  end

  processors = types.each_cons(2).map { |src, dst|
    unless processor = transformers[src][dst]
      raise ArgumentError, "missing transformer for type: #{src} to #{dst}"
    end
    processor
  }

  compose_transformer_list processors, preprocessors, postprocessors
end

#compute_transformers!(registered_transformers) (private)

[ GitHub ]

  
# File 'lib/sprockets/transformers.rb', line 147

def compute_transformers!(registered_transformers)
  preprocessors         = self.config[:preprocessors]
  postprocessors        = self.config[:postprocessors]
  transformers          = Hash.new { {} }
  inverted_transformers = Hash.new { Set.new }
  incoming_edges        = registered_transformers.group_by(&:from)

  registered_transformers.each do |t|
    traversals = dfs_paths([t]) { |k| incoming_edges.fetch(k.to, []) }

    traversals.each do |nodes|
      src, dst = nodes.first.from, nodes.last.to
      processor = compose_transformer_list nodes, preprocessors, postprocessors

      transformers[src] = {} unless transformers.key?(src)
      transformers[src][dst] = processor

      inverted_transformers[dst] = Set.new unless inverted_transformers.key?(dst)
      inverted_transformers[dst] << src
    end
  end

  self.config = hash_reassoc(config, :transformers) { transformers }
  self.config = hash_reassoc(config, :inverted_transformers) { inverted_transformers }
end

#expand_transform_accepts(parsed_accepts)

Internal: Expand accept type list to include possible transformed types.

parsed_accepts - Array of accept q values

Examples

expand_transform_accepts([['application/javascript', 1.0]])
# => [['application/javascript', 1.0], ['text/coffeescript', 0.8]]

Returns an expanded Array of q values.

[ GitHub ]

  
# File 'lib/sprockets/transformers.rb', line 97

def expand_transform_accepts(parsed_accepts)
  accepts = []
  parsed_accepts.each do |(type, q)|
    accepts.push([type, q])
    config[:inverted_transformers][type].each do |subtype|
      accepts.push([subtype, q * 0.8])
    end
  end
  accepts
end

#register_transformer(from, to, proc)

Public: Register a transformer from and to a mime type.

from - String mime type to - String mime type proc - Callable block that accepts an input Hash.

Examples

register_transformer 'text/coffeescript', 'application/javascript',
  ConvertCoffeeScriptToJavaScript

register_transformer 'image/svg+xml', 'image/png', ConvertSvgToPng

Returns nothing.

[ GitHub ]

  
# File 'lib/sprockets/transformers.rb', line 38

def register_transformer(from, to, proc)
  self.config = hash_reassoc(config, :registered_transformers) do |transformers|
    transformers << Transformer.new(from, to, proc)
  end
  compute_transformers!(self.config[:registered_transformers])
end

#register_transformer_suffix(types, type_format, extname, processor)

Internal: Register transformer for existing type adding a suffix.

types - Array of existing mime type Strings type_format - String suffix formatting string extname - String extension to append processor - Callable block that accepts an input Hash.

Returns nothing.

[ GitHub ]

  
# File 'lib/sprockets/transformers.rb', line 53

def register_transformer_suffix(types, type_format, extname, processor)
  Array(types).each do |type|
    extensions, charset = mime_types[type].values_at(:extensions, :charset)
    parts = type.split('/')
    suffix_type = type_format.sub('\1', parts[0]).sub('\2', parts[1])
    extensions = extensions.map { |ext| "#{ext}#{extname}" }

    register_mime_type(suffix_type, extensions: extensions, charset: charset)
    register_transformer(suffix_type, type, processor)
  end
end

#resolve_transform_type(type, accept)

Internal: Resolve target mime type that the source type should be transformed to.

type - String from mime type accept - String accept type list (default: ‘/’)

Examples

resolve_transform_type('text/plain', 'text/plain')
# => 'text/plain'

resolve_transform_type('image/svg+xml', 'image/png, image/*')
# => 'image/png'

resolve_transform_type('text/css', 'image/png')
# => nil

Returns String mime type or nil is no type satisfied the accept value.

[ GitHub ]

  
# File 'lib/sprockets/transformers.rb', line 83

def resolve_transform_type(type, accept)
  find_best_mime_type_match(accept || '*/*', [type].compact + config[:transformers][type].keys)
end

#transformers

Public: Two level mapping of a source mime type to a target mime type.

environment.transformers
# => { 'text/coffeescript' => {
         'application/javascript' => ConvertCoffeeScriptToJavaScript
       }
     }
[ GitHub ]

  
# File 'lib/sprockets/transformers.rb', line 18

def transformers
  config[:transformers]
end