compass/lib/compass/compiler.rb
Chris Eppstein b07f303d9b Merge branch 'stable'
* stable: (36 commits)
  Tweak the changelog.
  [CSS3] The box-shadow $spread value now defaults to using the browser default instead of 0.
  update the lockfile
  some todos
  Move the contributing guide to the tutorials section.
  add on-page anchors to the command line reference page.
  Better docs on the grid image command.
  Move the tutorials to the main nav... I don't think most people see it.
  Don't set the display in the box-flex mixin. This makes nested flex boxes annoying. Closes GH-207
  Add a note about the colorization change.
  Add a note about the compass validator
  Only colorize the action when logging results.
  Update to use the new compass validator during development.
  Fix broken test cases.
  Support true in addition to the inset keyword for the box-shadow mixin. Closes GH-206
  IE8 compat for :last-child selector
  Make the compass configuration file more self documenting by adding comments for preferred_syntax, output_style, and line_comments.
  Pass --no-line-comments to disable line comments.
  A little less noise during installation.
  Change the default Sass directory in standalone projects from src to sass. Closes GH-203
  ...

Conflicts:
	TODO.md
	VERSION.yml
	doc-src/content/CHANGELOG.markdown
	features/command_line.feature
	features/step_definitions/command_line_steps.rb
	lib/compass/commands/write_configuration.rb
2010-11-11 21:45:07 -08:00

141 lines
4.6 KiB
Ruby

module Compass
class Compiler
include Actions
attr_accessor :working_path, :from, :to, :options
def initialize(working_path, from, to, options)
self.working_path = working_path
self.from, self.to = from, to
self.logger = options.delete(:logger)
self.options = options
self.options[:cache_location] ||= determine_cache_location
Compass.configure_sass_plugin!
end
def determine_cache_location
Compass.configuration.cache_path || Sass::Plugin.options[:cache_location] || File.join(working_path, ".sass-cache")
end
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
def stylesheet_name(sass_file)
sass_file[("#{from}/".length)..-6]
end
def css_files
@css_files ||= sass_files.map{|sass_file| corresponding_css_file(sass_file)}
end
def corresponding_css_file(sass_file)
"#{to}/#{stylesheet_name(sass_file)}.css"
end
def target_directories
css_files.map{|css_file| File.dirname(css_file)}.uniq.sort.sort_by{|d| d.length }
end
# Returns the sass file that needs to be compiled, if any.
def out_of_date?
sass_files.zip(css_files).each do |sass_filename, css_filename|
return sass_filename if Sass::Plugin.send(:stylesheet_needs_update?, css_filename, sass_filename)
end
false
end
# Determines if the configuration file is newer than any css file
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
def clean!
FileUtils.rm_rf options[:cache_location]
css_files.each do |css_file|
FileUtils.rm_f css_file
end
end
def run
if new_config?
# Wipe out the cache and force compilation if the configuration has changed.
FileUtils.rm_rf options[:cache_location]
options[:force] = true
end
# Make sure the target directories exist
target_directories.each {|dir| directory dir}
# Compile each sass file.
sass_files.zip(css_files).each do |sass_filename, css_filename|
begin
compile_if_required sass_filename, css_filename
rescue Sass::SyntaxError => e
handle_exception(sass_filename, css_filename, e)
end
end
end
def compile_if_required(sass_filename, css_filename)
if should_compile?(sass_filename, css_filename)
compile sass_filename, css_filename
else
logger.record :unchanged, basename(sass_filename) unless options[:quiet]
end
end
# Compile one Sass file
def compile(sass_filename, css_filename)
css_content = logger.red do
engine(sass_filename, css_filename).render
end
write_file(css_filename, css_content, options.merge(:force => true))
end
def should_compile?(sass_filename, css_filename)
options[:force] || Sass::Plugin.send(:stylesheet_needs_update?, css_filename, sass_filename)
end
# A sass engine for compiling a single file.
def engine(sass_filename, css_filename)
syntax = (sass_filename =~ /\.(s[ac]ss)$/) && $1.to_sym || :sass
opts = options.merge :filename => sass_filename, :css_filename => css_filename, :syntax => syntax
Sass::Engine.new(open(sass_filename).read, opts)
end
# Place the syntax error into the target css file,
# formatted to display in the browser (in development mode)
# if there's an error.
def handle_exception(sass_filename, css_filename, e)
logger.record :error, basename(sass_filename), "(Line #{e.sass_line}: #{e.message})"
write_file css_filename, error_contents(e, sass_filename), options.merge(:force => true)
end
# Haml refactored this logic in 2.3, this is backwards compatibility for either one
def error_contents(e, sass_filename)
if Sass::SyntaxError.respond_to?(:exception_to_css)
e.sass_template = sass_filename
Sass::SyntaxError.exception_to_css(e, :full_exception => show_full_exception?)
else
Sass::Plugin.options[:full_exception] ||= show_full_exception?
Sass::Plugin.send(:exception_string, e)
end
end
# We don't want to show the full exception in production environments.
def show_full_exception?
Compass.configuration.environment == :development
end
end
end