123456789_123456789_123456789_123456789_123456789_

Class: Sprockets::DirectiveProcessor

Relationships & Source Files
Inherits: Object
Defined in: lib/sprockets/directive_processor.rb

Overview

The DirectiveProcessor is responsible for parsing and evaluating directive comments in a source file.

A directive comment starts with a comment prefix, followed by an “=”, then the directive name, then any arguments.

// JavaScript
//= require "foo"

# CoffeeScript
#= require "bar"

/* CSS
 *= require "baz"
 */

This makes it possible to disable or modify the processor to do whatever you’d like. You could add your own custom directives or invent your own directive syntax.

Environment#processors includes DirectiveProcessor by default.

To remove the processor entirely:

env.unregister_processor('text/css', Sprockets::DirectiveProcessor)
env.unregister_processor('application/javascript', Sprockets::DirectiveProcessor)

Then inject your own preprocessor:

env.register_processor('text/css', MyProcessor)

Constant Summary

  • DIRECTIVE_PATTERN =

    Directives are denoted by a ‘=` followed by the name, then argument list.

    A few different styles are allowed:

    // =require foo
    //= require foo
    //= require "foo"
    # File 'lib/sprockets/directive_processor.rb', line 47
    /
      ^ \W* = \s* (\w+.*?) (\*\/)? $
    /x

Class Method Summary

Instance Method Summary

Constructor Details

.new(comments: []) ⇒ DirectiveProcessor

[ GitHub ]

  
# File 'lib/sprockets/directive_processor.rb', line 60

def initialize(comments: [])
  @header_pattern = compile_header_pattern(Array(comments))
end

Class Method Details

.call(input)

[ GitHub ]

  
# File 'lib/sprockets/directive_processor.rb', line 56

def self.call(input)
  instance.call(input)
end

.instance

[ GitHub ]

  
# File 'lib/sprockets/directive_processor.rb', line 51

def self.instance
  # Default to C comment styles
  @instance ||= new(comments: ["//", ["/*", "*/"]])
end

Instance Method Details

#_call(input)

[ GitHub ]

  
# File 'lib/sprockets/directive_processor.rb', line 68

def _call(input)
  @environment  = input[:environment]
  @uri          = input[:uri]
  @filename     = input[:filename]
  @dirname      = File.dirname(@filename)
  # If loading a source map file like `application.js.map` resolve
  # dependencies using `.js` instead of `.js.map`
  @content_type = SourceMapProcessor.original_content_type(input[:content_type], error_when_not_found: false)
  @required     = Set.new(input[:][:required])
  @stubbed      = Set.new(input[:][:stubbed])
  @links        = Set.new(input[:][:links])
  @dependencies = Set.new(input[:][:dependencies])
  @to_link      = Set.new
  @to_load      = Set.new

  data, directives = process_source(input[:data])
  process_directives(directives)

  {
    data:         data,
    required:     @required,
    stubbed:      @stubbed,
    links:        @links,
    to_load:      @to_load,
    to_link:      @to_link,
    dependencies: @dependencies
  }
end

#call(input)

[ GitHub ]

  
# File 'lib/sprockets/directive_processor.rb', line 64

def call(input)
  dup._call(input)
end

#expand_accept_shorthand(accept) (private)

[ GitHub ]

  
# File 'lib/sprockets/directive_processor.rb', line 365

def expand_accept_shorthand(accept)
  if accept.nil?
    nil
  elsif accept.include?("/")
    accept
  elsif accept.start_with?(".")
    @environment.mime_exts[accept]
  else
    @environment.mime_exts[".#{accept}"]
  end
end

#expand_relative_dirname(directive, path) (private)

[ GitHub ]

  
# File 'lib/sprockets/directive_processor.rb', line 399

def expand_relative_dirname(directive, path)
  if @environment.relative_path?(path)
    path = File.expand_path(path, @dirname)
    stat = @environment.stat(path)

    if stat && stat.directory?
      path
    else
      raise ArgumentError, "#{directive} argument must be a directory"
    end
  else
    # The path must be relative and start with a `./`.
    raise ArgumentError, "#{directive} argument must be a relative path"
  end
end

#require_paths(paths, deps) (private)

[ GitHub ]

  
# File 'lib/sprockets/directive_processor.rb', line 377

def require_paths(paths, deps)
  resolve_paths(paths, deps, accept: @content_type, pipeline: :self) do |uri|
    @required << uri
  end
end

#resolve(path, **kargs) (private)

[ GitHub ]

  
# File 'lib/sprockets/directive_processor.rb', line 420

def resolve(path, **kargs)
  # Prevent absolute paths in directives
  if @environment.absolute_path?(path)
    raise FileOutsidePaths, "can't require absolute file: #{path}"
  end

  kargs[:base_path] = @dirname
  uri, deps = @environment.resolve!(path, **kargs)
  @dependencies.merge(deps)
  uri
end

#resolve_paths(paths, deps, **kargs) (private)

[ GitHub ]

  
# File 'lib/sprockets/directive_processor.rb', line 389

def resolve_paths(paths, deps, **kargs)
  @dependencies.merge(deps)
  paths.each do |subpath, stat|
    next if subpath == @filename || stat.directory?
    uri, deps = @environment.resolve(subpath, **kargs)
    @dependencies.merge(deps)
    yield uri if uri && block_given?
  end
end

#to_load(uri) (private)

[ GitHub ]

  
# File 'lib/sprockets/directive_processor.rb', line 415

def to_load(uri)
  @to_load << uri
  uri
end