Skip to content
This repository
file 105 lines (88 sloc) 2.972 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
require 'sprockets/sass_importer'

module Sprockets
  class SassImporter < Sass::Importers::Filesystem
    GLOB = /\*|\[.+\]/

    attr_reader :context
    private :context

    def extensions
      {
        'css' => :scss,
        'css.scss' => :scss,
        'css.sass' => :sass,
        'css.erb' => :scss,
        'scss.erb' => :scss,
        'sass.erb' => :sass,
        'css.scss.erb' => :scss,
        'css.sass.erb' => :sass
      }.merge!(super)
    end

    def find_relative(name, base, options)
      if name =~ GLOB
        glob_imports(name, Pathname.new(base), options)
      else
        engine_from_path(name, File.dirname(base), options)
      end
    end

    def find(name, options)
      if name =~ GLOB
        nil # globs must be relative
      else
        engine_from_path(name, root, options)
      end
    end

    def each_globbed_file(glob, base_pathname, options)
      Dir["#{base_pathname}/#{glob}"].sort.each do |filename|
        next if filename == options[:filename]
        yield filename if File.directory?(filename) || context.asset_requirable?(filename)
      end
    end

    def glob_imports(glob, base_pathname, options)
      contents = ""
      each_globbed_file(glob, base_pathname.dirname, options) do |filename|
        if File.directory?(filename)
          depend_on(filename)
        elsif context.asset_requirable?(filename)
          depend_on(filename)
          contents << "@import #{Pathname.new(filename).relative_path_from(base_pathname.dirname).to_s.inspect};\n"
        end
      end
      return nil if contents.empty?
      Sass::Engine.new(contents, options.merge(
        :filename => base_pathname.to_s,
        :importer => self,
        :syntax => :scss
      ))
    end

    private

      def depend_on(filename)
        context.depend_on(filename)
        context.depend_on(globbed_file_parent(filename))
      end

      def globbed_file_parent(filename)
        if File.directory?(filename)
          File.expand_path('..', filename)
        else
          File.dirname(filename)
        end
      end

      def engine_from_path(name, dir, options)
        full_filename, syntax = Sass::Util.destructure(find_real_file(dir, name, options))
        return unless full_filename && File.readable?(full_filename)

        engine = Sass::Engine.new(evaluate(full_filename), options.merge(
          syntax: syntax,
          filename: full_filename,
          importer: self
        ))

        if engine && (filename = engine.options[:filename])
          @context.depend_on(filename)
        end

        engine
      end

      def evaluate(filename)
        attributes = context.environment.attributes_for(filename)
        processors = context.environment.preprocessors(attributes.content_type) +
          attributes.engines.reverse - [Sprockets::ScssTemplate, Sprockets::SassTemplate]

        context.evaluate(filename, processors: processors)
      end
  end
end
Something went wrong with that request. Please try again.