require 'erb' require 'compass/sprite_importer/binding' module Compass class SpriteImporter < Sass::Importers::Base VAILD_FILE_NAME = /\A#{Sass::SCSS::RX::IDENT}\Z/ SPRITE_IMPORTER_REGEX = %r{((.+/)?([^\*.]+))/(.+?)\.png} VALID_EXTENSIONS = ['.png'] TEMPLATE_FOLDER = File.join(File.expand_path('../', __FILE__), 'sprite_importer') CONTENT_TEMPLATE_FILE = File.join(TEMPLATE_FOLDER, 'content.erb') CONTENT_TEMPLATE = ERB.new(File.read(CONTENT_TEMPLATE_FILE)) # finds all sprite files def self.find_all_sprite_map_files(path) hex = "[0-9a-f]" glob = "*-s#{hex*10}{#{VALID_EXTENSIONS.join(",")}}" Dir.glob(File.join(path, "**", glob)) end def find(uri, options) if uri =~ SPRITE_IMPORTER_REGEX return self.class.sass_engine(uri, self.class.sprite_name(uri), self, options) end nil end def find_relative(uri, base, options) nil end def to_s self.class.name end def hash self.class.name.hash end def eql?(other) other.class == self.class end def mtime(uri, options) self.class.files(uri).sort.inject(Time.at(0)) do |max_time, file| (t = File.mtime(file)) > max_time ? t : max_time end end def key(uri, options={}) [self.class.name + ":sprite:" + File.dirname(File.expand_path(uri)), File.basename(uri)] end def self.path_and_name(uri) if uri =~ SPRITE_IMPORTER_REGEX [$1, $3] else raise Compass::Error, "invalid sprite path" end end # Name of this spite def self.sprite_name(uri) _, name = path_and_name(uri) name end # The on-disk location of this sprite def self.path(uri) path, _ = path_and_name(uri) path end # Returns the Glob of image files for the uri def self.files(uri) Compass.configuration.sprite_load_path.compact.each do |folder| files = Dir[File.join(folder, uri)].sort next if files.empty? return files end path = Compass.configuration.sprite_load_path.to_a.join(', ') raise Compass::SpriteException, %Q{No files were found in the load path matching "#{uri}". Your current load paths are: #{path}} end # Returns an Array of image names without the file extension def self.sprite_names(uri) files(uri).collect do |file| filename = File.basename(file, '.png') unless VAILD_FILE_NAME =~ filename raise Compass::Error, "Sprite file names must be legal css identifiers. Please rename #{File.basename(file)}" end filename end end # Returns the sass_options for this sprite def self.sass_options(uri, importer, options) options.merge!(:filename => uri.gsub(%r{\*/},"*\\/"), :syntax => :scss, :importer => importer) end # Returns a Sass::Engine for this sprite object def self.sass_engine(uri, name, importer, options) content = content_for_images(uri, name, options[:skip_overrides]) Sass::Engine.new(content, sass_options(uri, importer, options)) end # Generates the Sass for this sprite file def self.content_for_images(uri, name, skip_overrides = false) binder = Compass::Sprites::Binding.new(:name => name, :uri => uri, :skip_overrides => skip_overrides, :sprite_names => sprite_names(uri), :files => files(uri)) CONTENT_TEMPLATE.result(binder.get_binding) end end end