Skip to content

Instantly share code, notes, and snippets.

@svallory
Last active December 18, 2015 21:58
Show Gist options
  • Save svallory/5850711 to your computer and use it in GitHub Desktop.
Save svallory/5850711 to your computer and use it in GitHub Desktop.
Sass custom importer which only imports the same file once. Requires colorize to make it easy to debug. You can remove it safely (but make sure to remove all the .red, .blue etc. calls also)
require 'colorize'
module Liftr
module Importers
class ImportOnce < ::Sass::Importers::FilesystemFilesystem
attr_accessor :root, :debug_level, :staleness_check, :imported, :original_filename
# Creates a new filesystem importer that imports files relative to a given path.
#
# @param root [String] The root path.
# This importer will import files relative to this path.
def initialize(root)
@debug_level = 2
@imported = []
super(root)
end
def debug?
return true
end
def debug(text, level = 1)
if debug? && debug_level >= level
puts "__ DEBUG: " + text.to_s
end
end
def dir(obj)
obj.each {|k,v|
puts k.inspect + " = " + (v ? v.inspect : "") + "\n"
}
end
def update_imported_list(options)
@original_filename ||= options[:original_filename]
if @original_filename != options[:original_filename]
@imported = []
@original_filename = options[:original_filename]
end
end
def staleness_check?(options)
# as per sass/importers/filesystem.rb : 135, 148
# quote: "If options[:_line] exists, we're here due to an actual import in an import_node
# Otherwise, we're here via StalenessChecker."
# But it's only true for the first file, all subsequent imports will
# have a :_line, so, unfortunately, for now, will have to check the stack
Kernel.caller.each {|call|
return true if call.include? "staleness_checker"
}
return false
# We can try using this:
# return !options[:_from_import_node]
end
# @see Base#find_relative
def find_relative(name, base, options)
update_imported_list options
debug " finding relative ".yellow + name.blue
just_checking = staleness_check? options
# get the real file
real_file, syntax = Sass::Util.destructure(find_real_file(File.dirname(base), name, options))
if !real_file
debug " Could not find a RELATIVE file for #{name}".red, 2
return nil
end
unless just_checking
if @imported.include? real_file
debug " already included".red
debug @imported.join(", ").yellow, 3
return empty(options)
end
else
debug " Just checking", 2
end
f = _find(File.dirname(base), name, options)
if f
debug " imported: ".yellow + real_file.green
@imported << real_file unless just_checking
end
return f
end
# @see Base#find
def find(name, options)
update_imported_list options
debug "finding absolute " + name.blue
just_checking = staleness_check? options
# get the real file
real_file, syntax = Sass::Util.destructure(find_real_file(@root, name, options))
if !real_file
debug "Could not find the file for #{name}".red, 2
return nil
end
unless just_checking
if @imported.include? real_file
debug "already included".red
debug @imported.join(", ").yellow, 3
return empty(options)
end
else
debug "Just checking", 2
end
f = _find(@root, name, options)
if f
debug " imported: " + real_file.green
@imported << real_file unless just_checking
else
debug "NOT FOUND!".red
end
return f
end
protected
def possible_files(name)
if(name == 'liftr')
return [['liftr/{_,}liftr.sass', :sass], ['liftr/{_,}liftr.scss', :scss]] + super
end
files = []
if name.start_with? "liftr"
files += split_filename(name.sub('liftr', 'liftr/components') + '/lift')
files += split_filename(name.sub('liftr', 'liftr/components'))
files += split_filename(name.sub('liftr', 'liftr/lib'))
end
return files + super
end
def split_filename(name)
parts = name.split('/')
name = parts[0..-2].join('/') + '/{_,}' + parts[-1]
return [[name+'.scss', :scss], [name+'.sass', :sass]]
end
def empty(options)
return Sass::Engine.new("", options)
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment