Module | Sass::Plugin |
In: |
lib/sass/plugin.rb
lib/sass/plugin/rack.rb |
This module handles the compilation of Sass files. It provides global options and checks whether CSS files need to be updated.
This module is used as the primary interface with Sass when it‘s used as a plugin for various frameworks. All Rack-enabled frameworks are supported out of the box. The plugin is {file:SASS_REFERENCE.md#rails_merb_plugin automatically activated for Rails and Merb}. Other frameworks must enable it explicitly; see {Sass::Plugin::Rack}.
Same as \{update_stylesheets}, but respects \{checked_for_updates} and the {file:SASS_REFERENCE.md#always_update-option `:always_update`} and {file:SASS_REFERENCE.md#always_check-option `:always_check`} options.
@see update_stylesheets
# File lib/sass/plugin.rb, line 59 59: def check_for_updates 60: return unless !Sass::Plugin.checked_for_updates || 61: Sass::Plugin.options[:always_update] || Sass::Plugin.options[:always_check] 62: update_stylesheets 63: end
Non-destructively modifies \{options} so that default values are properly set.
@param additional_options [{Symbol => Object}] An options hash with which to merge \{options} @return [{Symbol => Object}] The modified options hash
# File lib/sass/plugin.rb, line 48 48: def engine_options(additional_options = {}) 49: opts = options.dup.merge(additional_options) 50: opts[:load_paths] = load_paths(opts) 51: opts 52: end
Updates out-of-date stylesheets.
Checks each Sass file in {file:SASS_REFERENCE.md#template_location-option `:template_location`} to see if it‘s been modified more recently than the corresponding CSS file in {file:SASS_REFERENCE.md#css_location-option} `:css_location`}. If it has, it updates the CSS file.
# File lib/sass/plugin.rb, line 71 71: def update_stylesheets 72: return if options[:never_update] 73: 74: @checked_for_updates = true 75: template_locations.zip(css_locations).each do |template_location, css_location| 76: 77: Dir.glob(File.join(template_location, "**", "*.sass")).each do |file| 78: # Get the relative path to the file with no extension 79: name = file.sub(template_location.sub(/\/*$/, '/'), "")[0...-5] 80: 81: if !forbid_update?(name) && (options[:always_update] || stylesheet_needs_update?(name, template_location, css_location)) 82: update_stylesheet(name, template_location, css_location) 83: end 84: end 85: end 86: end
# File lib/sass/plugin.rb, line 183 183: def css_filename(name, path) 184: "#{path}/#{name}.css" 185: end
# File lib/sass/plugin.rb, line 131 131: def css_locations 132: if options[:template_location] && !options[:template_location].is_a?(String) 133: options[:template_location].to_a.map { |l| l.last } 134: else 135: [options[:css_location]] 136: end 137: end
# File lib/sass/plugin.rb, line 212 212: def dependencies(filename) 213: File.readlines(filename).grep(/^@import /).map do |line| 214: line[8..-1].split(',').map do |inc| 215: Sass::Files.find_file_to_import(inc.strip, [File.dirname(filename)] + load_paths) 216: end 217: end.flatten.grep(/\.sass$/) 218: end
# File lib/sass/plugin.rb, line 205 205: def dependency_updated?(css_mtime) 206: lambda do |dep| 207: File.mtime(dep) > css_mtime || 208: dependencies(dep).any?(&dependency_updated?(css_mtime)) 209: end 210: end
# File lib/sass/plugin.rb, line 197 197: def exact_stylesheet_needs_update?(css_file, template_file) 198: return true unless File.exists?(css_file) 199: 200: css_mtime = File.mtime(css_file) 201: File.mtime(template_file) > css_mtime || 202: dependencies(template_file).any?(&dependency_updated?(css_mtime)) 203: end
# File lib/sass/plugin.rb, line 139 139: def exception_string(e) 140: e_string = "#{e.class}: #{e.message}" 141: 142: if e.is_a? Sass::SyntaxError 143: e_string << "\non line #{e.sass_line}" 144: 145: if e.sass_filename 146: e_string << " of #{e.sass_filename}" 147: 148: if File.exists?(e.sass_filename) 149: e_string << "\n\n" 150: 151: min = [e.sass_line - 5, 0].max 152: begin 153: File.read(e.sass_filename).rstrip.split("\n")[ 154: min .. e.sass_line + 5 155: ].each_with_index do |line, i| 156: e_string << "#{min + i + 1}: #{line}\n" 157: end 158: rescue 159: e_string << "Couldn't read sass file: #{e.sass_filename}" 160: end 161: end 162: end 163: end 164: "/*\n\#{e_string}\n\nBacktrace:\\n\#{e.backtrace.join(\"\\n\")}\n*/\nbody:before {\n white-space: pre;\n font-family: monospace;\n content: \"\#{e_string.gsub('\"', '\\\"').gsub(\"\\n\", '\\\\A ')}\"; }\n" 165: # Fix an emacs syntax-highlighting hiccup: ' 166: end
# File lib/sass/plugin.rb, line 187 187: def forbid_update?(name) 188: name.sub(/^.*\//, '')[0] == ?_ 189: end
# File lib/sass/plugin.rb, line 118 118: def load_paths(opts = options) 119: (opts[:load_paths] || []) + template_locations 120: end
Create any successive directories required to be able to write a file to: File.join(base,name)
# File lib/sass/plugin.rb, line 112 112: def mkpath(base, name) 113: dirs = [base] 114: name.split(File::SEPARATOR)[0...-1].each { |dir| dirs << File.join(dirs[-1],dir) } 115: dirs.each { |dir| Dir.mkdir(dir) unless File.exist?(dir) } 116: end
# File lib/sass/plugin.rb, line 191 191: def stylesheet_needs_update?(name, template_path, css_path) 192: css_file = css_filename(name, css_path) 193: template_file = template_filename(name, template_path) 194: exact_stylesheet_needs_update?(css_file, template_file) 195: end
# File lib/sass/plugin.rb, line 179 179: def template_filename(name, path) 180: "#{path}/#{name}.sass" 181: end
# File lib/sass/plugin.rb, line 122 122: def template_locations 123: location = (options[:template_location] || File.join(options[:css_location],'sass')) 124: if location.is_a?(String) 125: [location] 126: else 127: location.to_a.map { |l| l.first } 128: end 129: end
# File lib/sass/plugin.rb, line 90 90: def update_stylesheet(name, template_location, css_location) 91: css = css_filename(name, css_location) 92: File.delete(css) if File.exists?(css) 93: 94: filename = template_filename(name, template_location) 95: result = begin 96: Sass::Files.tree_for(filename, engine_options(:css_filename => css, :filename => filename)).render 97: rescue Exception => e 98: raise e unless options[:full_exception] 99: exception_string(e) 100: end 101: 102: # Create any directories that might be necessary 103: mkpath(css_location, name) 104: 105: # Finally, write the file 106: File.open(css, 'w') do |file| 107: file.print(result) 108: end 109: end