petebrowne / sprockets-sass

Better Sass integration with Sprockets 2.x
MIT License
90 stars 29 forks source link

Allow the use of custom SASS importers #32

Closed alem0lars closed 9 years ago

alem0lars commented 9 years ago

By default SASS allows the definition of custom importers. Using this gem, you won't have that ability anymore because the importer choice is wired. This pull request allows the use of a custom importer (inheriting Sprockets::Sass::Importer) instead of the default one, if specified in the sass :importer configuration.

petebrowne commented 9 years ago

Thanks for this - can you add a test and I'll merge it in? I'm curious though, what's the use case? Wouldn't a custom importer defeat the purpose of using Sprockets::Sass?

alem0lars commented 9 years ago

The custom importer specified should be a Sprockets::Sass::Importer so it will have the basic features of the base importer and the custom behaviour..

There are many use cases for an importer, a common one is to interpret the path specified in @import, e.g.:

module SmartFS
  module Sass

    ##
    # Importer allowing smart files finding.
    #
    # Usage example in Middleman:
    #
    # - Edit the `config.rb` file:
    #
    #   set :sass, {:importer => SmartFS::Sass::Importer.new}
    #
    class Importer < Sprockets::Sass::Importer

      SMARTFS_REG = /@(?<what>[^:]+):(?<name>[^:]+)(?::(?<entry_point>[^:]+))?/

      def find_relative(uri, base, options, *args)
        middleman_app = options[:custom][:sprockets_context].app
        md = SMARTFS_REG.match(uri)
        unless md.nil? || md[:what].nil? || md[:name].nil?
          if md[:entry_point].nil?
            uri = middleman_app.c_css_path(md[:what], md[:name])
          else
            uri = middleman_app.c_css_path(md[:what], md[:name], md[:entry_point])
          end
        end
        super(uri, base, options, *args)
      end

      # Override because `super()` implementation is bad
      # (raises exception for `context` not found).
      def to_s
        self.class.name
      end

    end

  end
end

That importer (the one that I uses in my projects) will allow to make decisions about the physical path from the specified logical path.. For example one could use:

@import "@component:foobar"

to import the foobar component. In fact it underlies into c_css_path which will build the path using Middleman configuration variables.

Of course, this is just one opinionated use case. You can also define more sophisticated DSL-like syntaxes for importing stuff...

BTW, if you want to play with that importer this is the c_css_path definition: https://gist.github.com/alem0lars/d1cbf3bfa2ec52f83653

Sorry if I went OFT..


Coming back to our pull-request :smile:, to use that you need to configure SASS accordingly.. One example in Middleman would be:

set :sass, {:importer => SmartFS::Sass::Importer.new}

inside the config.rb file.

Of course the way to select the importer is not Middleman-specific: the code above just sets the Sass engine options, which is the standard way to configure Sass.

petebrowne commented 9 years ago

Ahh I see - that's a cool idea

alem0lars commented 9 years ago

I've added the test that ensures that the custom importer is used instead of the default one when specifying it in the SASS options.

BTW, you can selectively run that spec:

$ rspec -P spec/custom_importer_spec.rb
petebrowne commented 9 years ago

Thanks!

alem0lars commented 9 years ago

Could you maybe create a new gem so we can start using right now?

Thanks :smiley:

petebrowne commented 9 years ago

Release: http://rubygems.org/gems/sprockets-sass