require'digest/sha1'require'pathname'require'fileutils'moduleSass# This module contains various bits of functionality# related to finding and caching Sass files.moduleFilesextendself# Returns the {Sass::Tree} for the given file,# reading it from the Sass cache if possible.## @param filename [String] The path to the Sass or SCSS file# @param options [{Symbol => Object}] The options hash.# Only the {file:SASS_REFERENCE.md#cache-option `:cache_location`} option is used# @raise [Sass::SyntaxError] if there's an error in the document.# The caller has responsibility for setting backtrace information, if necessarydeftree_for(filename,options)default_options=Sass::Engine::DEFAULT_OPTIONS.dupdefault_options.delete(:syntax)options=default_options.merge!(options)text=File.read(filename)ifoptions[:cache]||options[:read_cache]compiled_filename=sassc_filename(filename,options)sha=Digest::SHA1.hexdigest(text)ifroot=try_to_read_sassc(filename,compiled_filename,sha)root.options=options.merge(:filename=>filename)returnrootendendoptions=options.merge(:filename=>filename)iffilename=~/\.scss$/options={:syntax=>:scss}.merge(options)elsiffilename=~/\.sass$/options={:syntax=>:sass}.merge(options)endengine=Sass::Engine.new(text,options)root=engine.to_treetry_to_write_sassc(root,compiled_filename,sha,options)ifoptions[:cache]rootend# Find the full filename of a Sass, SCSS, or CSS file to import.# This follows Sass's import rules:# if the filename given ends in `".sass"`, `".scss"`, or `".css"`,# it will try to find that type of file;# otherwise, it will try to find the corresponding Sass/SCSS file# and fall back on CSS if it's not available.## Any Sass/SCSS filename returned will correspond to# an actual file of the corresponding type on the filesystem.# CSS filenames, however, may not;# they're expected to be put through directly to the stylesheet# as CSS `@import` statements.## @param filename [String] The filename to search for# @param load_paths [Array<String>] The set of filesystem paths# to search for Sass/SCSS files.# @return [String] The filename of the imported file.# This is an absolute path if the file is a `".sass"` or `".scss"` file.# @raise [Sass::SyntaxError] if `filename` ends in `".sass"` or `".scss"`# and no corresponding Sass/SCSS file could be found.deffind_file_to_import(filename,load_paths)was_sass=was_scss=falseoriginal_filename=filenameif[".sass",".scss"].include?(filename[-5..-1])was_sass=filename[-5..-1]==".sass"was_scss=filename[-5..-1]==".scss"filename=filename[0...-5]elsiffilename[-4..-1]==".css"returnfilenameendnew_filename=nilload_paths=load_paths.uniqload_paths.eachdo|load_path|new_filename||=find_full_path("#{filename}.sass",load_path)unlesswas_scssnew_filename||=find_full_path("#{filename}.scss",load_path)unlesswas_sassendreturnnew_filenameifnew_filenameunlesswas_sass||was_scssHaml::Util.haml_warn<<END
WARNING: Neither #{filename}.sass nor .scss found. Using #{filename}.css instead.
This behavior is deprecated and will be removed in a future version.
If you really need #{filename}.css, import it explicitly.
ENDreturnfilename+'.css'endmessage="File to import not found or unreadable: #{original_filename}.\n"ifload_paths.size==1message<<"Load path: #{load_paths.first}"elsemessage<<"Load paths:\n "<<load_paths.join("\n ")endraiseSyntaxError.new(message)endprivatedefsassc_filename(filename,options)File.join(options[:cache_location],Digest::SHA1.hexdigest(File.dirname(File.expand_path(filename))),File.basename(filename)+'c')enddeftry_to_read_sassc(filename,compiled_filename,sha)returnunlessFile.readable?(compiled_filename)File.open(compiled_filename,"rb")do|f|returnunlessf.readline("\n").strip==Sass::VERSIONreturnunlessf.readline("\n").strip==shareturnMarshal.load(f.read)endrescueEOFError,TypeError,ArgumentError=>eHaml::Util.haml_warn"Warning. Error encountered while reading cache #{compiled_filename}: #{e}"enddeftry_to_write_sassc(root,compiled_filename,sha,options)returnunlessFile.writable?(File.dirname(options[:cache_location]))returnifFile.exists?(options[:cache_location])&&!File.writable?(options[:cache_location])returnifFile.exists?(File.dirname(compiled_filename))&&!File.writable?(File.dirname(compiled_filename))returnifFile.exists?(compiled_filename)&&!File.writable?(compiled_filename)FileUtils.mkdir_p(File.dirname(compiled_filename))File.open(compiled_filename,"wb")do|f|f.write(Sass::VERSION)f.write("\n")f.write(sha)f.write("\n")f.write(Marshal.dump(root))endenddeffind_full_path(filename,load_path)partial_name=File.join(File.dirname(filename),"_#{File.basename(filename)}")ifPathname.new(filename).absolute?[partial_name,filename].eachdo|name|returnnameifFile.readable?(name)endreturnnilend[partial_name,filename].eachdo|name|full_path=File.join(load_path,name)returnfull_pathifFile.readable?(full_path)endnilendendend