b07f303d9b
* 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
141 lines
4.6 KiB
Ruby
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
|