Last active
December 18, 2015 21:58
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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