| Module | Sass::Files |
| In: |
lib/sass/files.rb
|
This module contains various bits of functionality related to finding and caching Sass files.
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.
# File lib/sass/files.rb, line 69
69: def find_file_to_import(filename, load_paths)
70: was_sass = was_scss = false
71: original_filename = filename
72:
73: if [".sass", ".scss"].include?(filename[-5..-1])
74: was_sass = filename[-5..-1] == ".sass"
75: was_scss = filename[-5..-1] == ".scss"
76: filename = filename[0...-5]
77: elsif filename[-4..-1] == ".css"
78: return filename
79: end
80:
81: new_filename = nil
82: load_paths = load_paths.uniq
83: load_paths.each do |load_path|
84: new_filename ||= find_full_path("#{filename}.sass", load_path) unless was_scss
85: new_filename ||= find_full_path("#{filename}.scss", load_path) unless was_sass
86: end
87:
88: return new_filename if new_filename
89: unless was_sass || was_scss
90: Haml::Util.haml_warn "WARNING: Neither \#{filename}.sass nor .scss found. Using \#{filename}.css instead.\nThis behavior is deprecated and will be removed in a future version.\nIf you really need \#{filename}.css, import it explicitly.\n"
91: return filename + '.css'
92: end
93:
94: message = "File to import not found or unreadable: #{original_filename}.\n"
95: if load_paths.size == 1
96: message << "Load path: #{load_paths.first}"
97: else
98: message << "Load paths:\n " << load_paths.join("\n ")
99: end
100:
101: raise SyntaxError.new(message)
102: end
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 necessary
# File lib/sass/files.rb, line 19
19: def tree_for(filename, options)
20: default_options = Sass::Engine::DEFAULT_OPTIONS.dup
21: default_options.delete(:syntax)
22: options = default_options.merge!(options)
23: text = File.read(filename)
24:
25: if options[:cache] || options[:read_cache]
26: compiled_filename = sassc_filename(filename, options)
27: sha = Digest::SHA1.hexdigest(text)
28:
29: if root = try_to_read_sassc(filename, compiled_filename, sha)
30: root.options = options.merge(:filename => filename)
31: return root
32: end
33: end
34:
35: options = options.merge(:filename => filename)
36: if filename =~ /\.scss$/
37: options = {:syntax => :scss}.merge(options)
38: elsif filename =~ /\.sass$/
39: options = {:syntax => :sass}.merge(options)
40: end
41:
42: engine = Sass::Engine.new(text, options)
43:
44: root = engine.to_tree
45: try_to_write_sassc(root, compiled_filename, sha, options) if options[:cache]
46: root
47: end
# File lib/sass/files.rb, line 144
144: def find_full_path(filename, load_path)
145: partial_name = File.join(File.dirname(filename), "_#{File.basename(filename)}")
146:
147: if Pathname.new(filename).absolute?
148: [partial_name, filename].each do |name|
149: return name if File.readable?(name)
150: end
151: return nil
152: end
153:
154: [partial_name, filename].each do |name|
155: full_path = File.join(load_path, name)
156: return full_path if File.readable?(full_path)
157: end
158: nil
159: end
# File lib/sass/files.rb, line 111
111: def sassc_filename(filename, options)
112: File.join(options[:cache_location],
113: Digest::SHA1.hexdigest(File.dirname(File.expand_path(filename))),
114: File.basename(filename) + 'c')
115: end
# File lib/sass/files.rb, line 117
117: def try_to_read_sassc(filename, compiled_filename, sha)
118: return unless File.readable?(compiled_filename)
119:
120: File.open(compiled_filename, "rb") do |f|
121: return unless f.readline("\n").strip == Sass::VERSION
122: return unless f.readline("\n").strip == sha
123: return Marshal.load(f.read)
124: end
125: rescue EOFError, TypeError, ArgumentError => e
126: Haml::Util.haml_warn "Warning. Error encountered while reading cache #{compiled_filename}: #{e}"
127: end
# File lib/sass/files.rb, line 129
129: def try_to_write_sassc(root, compiled_filename, sha, options)
130: return unless File.writable?(File.dirname(options[:cache_location]))
131: return if File.exists?(options[:cache_location]) && !File.writable?(options[:cache_location])
132: return if File.exists?(File.dirname(compiled_filename)) && !File.writable?(File.dirname(compiled_filename))
133: return if File.exists?(compiled_filename) && !File.writable?(compiled_filename)
134: FileUtils.mkdir_p(File.dirname(compiled_filename))
135: File.open(compiled_filename, "wb") do |f|
136: f.write(Sass::VERSION)
137: f.write("\n")
138: f.write(sha)
139: f.write("\n")
140: f.write(Marshal.dump(root))
141: end
142: end