class Compass::Compiler
Attributes
from[RW]
importer[RW]
options[RW]
sass_options[RW]
staleness_checker[RW]
to[RW]
working_path[RW]
Public Class Methods
new(working_path, from, to, options)
click to toggle source
# File lib/compass/compiler.rb, line 10 def initialize(working_path, from, to, options) Compass::Deprecation.deprecated!(:compass_compiler_constructor, "Compass::Compiler is deprecated. Use Compass::SassCompiler instead.") self.working_path = working_path.to_s self.from, self.to = File.expand_path(from), to self.logger = options.delete(:logger) sass_opts = options.delete(:sass) || {} self.options = options self.sass_options = options.dup self.sass_options.delete(:quiet) self.sass_options.update(sass_opts) self.sass_options[:cache_location] ||= determine_cache_location self.sass_options[:filesystem_importer] ||= Sass::Importers::Filesystem self.sass_options[:importer] = self.importer = self.sass_options[:filesystem_importer].new(from) self.sass_options[:compass] ||= {} self.sass_options[:compass][:logger] = self.logger self.sass_options[:compass][:environment] = Compass.configuration.environment self.sass_options[:compass][:compiler_in_use] = true reset_staleness_checker! end
Public Instance Methods
clean!()
click to toggle source
# File lib/compass/compiler.rb, line 108 def clean! remove options[:cache_location] css_files.zip(sourcemap_files).each do |css_file, sourcemap_file| remove css_file remove sourcemap_file end end
compile(sass_filename, css_filename, sourcemap_filename = nil)
click to toggle source
Compile one Sass file
# File lib/compass/compiler.rb, line 166 def compile(sass_filename, css_filename, sourcemap_filename = nil) css_content, sourcemap = logger.red do timed(lambda {|r| r[0]}) do engine = engine(sass_filename, css_filename, sourcemap_filename) if sourcemap_filename && options[:sourcemap] engine.render_with_sourcemap(relative_path(css_filename, sourcemap_filename)) else [engine.render, nil] end end end duration = options[:time] ? "(#{(css_content.__duration * 1000).round / 1000.0}s)" : "" write_file(css_filename, css_content, options.merge(:force => true, :extra => duration), sass_options[:unix_newlines]) Compass.configuration.run_stylesheet_saved(css_filename) if sourcemap && sourcemap_filename sourcemap_content = sourcemap.to_json(:css_path => css_filename, :sourcemap_path => sourcemap_filename) write_file(sourcemap_filename, sourcemap_content, options.merge(:force => true), sass_options[:unix_newlines]) Compass.configuration.run_sourcemap_saved(sourcemap_filename) elsif sourcemap_filename && File.exist?(sourcemap_filename) remove sourcemap_filename Compass.configuration.run_sourcemap_removed(sourcemap_filename) end end
compile_if_required(sass_filename, css_filename, sourcemap_filename = nil)
click to toggle source
# File lib/compass/compiler.rb, line 144 def compile_if_required(sass_filename, css_filename, sourcemap_filename = nil) if should_compile?(sass_filename, css_filename, sourcemap_filename) compile sass_filename, css_filename, sourcemap_filename else logger.record :unchanged, basename(sass_filename) unless options[:quiet] remove(sourcemap_filename) if sourcemap_filename && !options[:sourcemap] end end
corresponding_css_file(sass_file)
click to toggle source
# File lib/compass/compiler.rb, line 66 def corresponding_css_file(sass_file) "#{to}/#{stylesheet_name(sass_file)}.css" end
corresponding_sourcemap_file(sass_file)
click to toggle source
# File lib/compass/compiler.rb, line 70 def corresponding_sourcemap_file(sass_file) "#{to}/#{stylesheet_name(sass_file)}.css.map" end
css_files()
click to toggle source
# File lib/compass/compiler.rb, line 58 def css_files @css_files ||= sass_files.map{|sass_file| corresponding_css_file(sass_file)} end
determine_cache_location()
click to toggle source
# File lib/compass/compiler.rb, line 37 def determine_cache_location Compass.configuration.cache_path || Sass::Plugin.options[:cache_location] || File.join(working_path, ".sass-cache") end
engine(sass_filename, css_filename, sourcemap_filename = nil)
click to toggle source
A sass engine for compiling a single file.
# File lib/compass/compiler.rb, line 204 def engine(sass_filename, css_filename, sourcemap_filename = nil) syntax = (sass_filename =~ /\.(s[ac]ss)$/) && $1.to_sym || :sass opts = sass_options.merge(:filename => sass_filename, :css_filename => css_filename, :syntax => syntax, :sourcemap_filename => sourcemap_filename) Sass::Engine.new(open(sass_filename).read, opts) end
error_contents(e, sass_filename)
click to toggle source
Haml refactored this logic in 2.3, this is backwards compatibility for either one
# File lib/compass/compiler.rb, line 227 def error_contents(e, sass_filename) if show_full_exception? e.sass_template = sass_filename Sass::SyntaxError.exception_to_css(e) else header = Sass::SyntaxError.send(:header_string, e, 1) <<END /* #{header.gsub("*/", "*\\/")} Backtrace:\n#{e.backtrace.join("\n").gsub("*/", "*\\/")} */ END end end
handle_exception(sass_filename, css_filename, e)
click to toggle source
Place the syntax error into the target css file, formatted to display in the browser (in development mode) if there's an error.
# File lib/compass/compiler.rb, line 216 def handle_exception(sass_filename, css_filename, e) exception_file = basename(e.sass_filename || sass_filename) file = basename(sass_filename) exception_file = nil if exception_file == file formatted_error = "(Line #{e.sass_line}#{ " of #{exception_file}" if exception_file}: #{e.message})" logger.record :error, file, formatted_error Compass.configuration.run_stylesheet_error(sass_filename, formatted_error) write_file css_filename, error_contents(e, sass_filename), options.merge(:force => true), sass_options[:unix_newlines] end
needs_update?(css_filename, sass_filename)
click to toggle source
# File lib/compass/compiler.rb, line 86 def needs_update?(css_filename, sass_filename) staleness_checker.stylesheet_needs_update?(css_filename, File.expand_path(sass_filename), importer) end
new_config?()
click to toggle source
Determines if the configuration file is newer than any css file
# File lib/compass/compiler.rb, line 91 def new_config? config_file = Compass.detect_configuration_file return false unless config_file config_mtime = File.mtime(config_file) css_files.each do |css_filename| return config_file if File.exists?(css_filename) && config_mtime > File.mtime(css_filename) end nil end
out_of_date?()
click to toggle source
Returns the sass file that needs to be compiled, if any.
# File lib/compass/compiler.rb, line 79 def out_of_date? sass_files.zip(css_files).each do |sass_filename, css_filename| return sass_filename if needs_update?(css_filename, sass_filename) end false end
relative_path(from_path, to_path)
click to toggle source
# File lib/compass/compiler.rb, line 191 def relative_path(from_path, to_path) Pathname.new(to_path).relative_path_from(Pathname.new(from_path).dirname).to_s end
relative_stylesheet_name(sass_file)
click to toggle source
# File lib/compass/compiler.rb, line 46 def relative_stylesheet_name(sass_file) sass_file[(from.length + 1)..-1] end
reset!()
click to toggle source
# File lib/compass/compiler.rb, line 101 def reset! reset_staleness_checker! @sass_files = nil @css_files = nil @sourcemap_files = nil end
reset_staleness_checker!()
click to toggle source
# File lib/compass/compiler.rb, line 31 def reset_staleness_checker! self.staleness_checker = nil #Sass::Plugin::StalenessChecker.dependencies_cache = {} self.staleness_checker = Sass::Plugin::StalenessChecker.new(sass_options) end
run()
click to toggle source
# File lib/compass/compiler.rb, line 116 def run failure_count = 0 if new_config? # Wipe out the cache and force compilation if the configuration has changed. remove options[:cache_location] if options[:cache_location] options[:force] = true end # Make sure the target directories exist target_directories.each {|dir| directory dir} # Compile each sass file. result = timed do sass_files.zip(css_files, sourcemap_files).each do |sass_filename, css_filename, sourcemap_filename| begin compile_if_required sass_filename, css_filename, sourcemap_filename rescue Sass::SyntaxError => e failure_count += 1 handle_exception(sass_filename, css_filename, e) end end end if options[:time] puts "Compilation took #{(result.__duration * 1000).round / 1000.0}s" end return failure_count end
sass_files(options = {})
click to toggle source
# File lib/compass/compiler.rb, line 41 def sass_files(options = {}) exclude_partials = options.fetch(:exclude_partials, true) @sass_files = self.options[:sass_files] || Dir.glob(separate("#{from}/**/#{'[^_]' if exclude_partials}*.s[ac]ss")) end
should_compile?(sass_filename, css_filename, sourcemap_filename = nil)
click to toggle source
# File lib/compass/compiler.rb, line 195 def should_compile?(sass_filename, css_filename, sourcemap_filename = nil) return true if css_filename && !File.exist?(css_filename) return true if sourcemap_filename && options[:sourcemap] && !File.exist?(sourcemap_filename) options[:force] || needs_update?(css_filename, sass_filename) || (options[:sourcemap] && needs_update?(sourcemap_filename, sass_filename)) end
show_full_exception?()
click to toggle source
We don't want to show the full exception in production environments.
# File lib/compass/compiler.rb, line 244 def show_full_exception? Compass.configuration.environment == :development end
sourcemap_files()
click to toggle source
# File lib/compass/compiler.rb, line 62 def sourcemap_files @sourcemap_files ||= sass_files.map{|sass_file| corresponding_sourcemap_file(sass_file)} end
stylesheet_name(sass_file)
click to toggle source
# File lib/compass/compiler.rb, line 50 def stylesheet_name(sass_file) if sass_file.index(from) == 0 sass_file[(from.length + 1)..-6].sub(/\.css$/,'') else raise Compass::Error, "You must compile individual stylesheets from the project directory." end end
target_directories()
click to toggle source
# File lib/compass/compiler.rb, line 74 def target_directories css_files.map{|css_file| File.dirname(css_file)}.uniq.sort.sort_by{|d| d.length } end
timed(timed_thing = lambda {|res| res}) { || ... }
click to toggle source
# File lib/compass/compiler.rb, line 153 def timed(timed_thing = lambda {|res| res}) start_time = Time.now res = yield end_time = Time.now has_duration = timed_thing.call(res) has_duration.instance_variable_set("@__duration", end_time - start_time) def has_duration.__duration @__duration end res end