Merge branch 'master' into rails31

* master:
  The compass watcher is in quiet mode except for important actions.
  Clear up a Logger class lookup issue that was reported.
  Following a similar API to how the Complier works, don't log anything (don't even load up the logger!) if we pass in the :quiet option.
  Previously, calling directory("/hi") would error, because options would remain nil if self doesn't respond_to?(:options)
  moved config check to perform
  added @chriseppsteins suggestion for issue 
  forgot test files
  added failing test for issue  and fixed the callback typo closes 
  move hashing and comparison methods into SpriteMap class
  removed unneeded file
  refactored the sass importer for sprites

Conflicts:
	lib/compass/sass_extensions/sprites/sprites.rb
This commit is contained in:
Chris Eppstein 2011-06-05 18:04:29 -07:00
commit b0e89239c3
15 changed files with 129 additions and 114 deletions

View File

@ -4,7 +4,7 @@ module Compass
attr_writer :logger attr_writer :logger
def logger def logger
@logger ||= Logger.new @logger ||= ::Compass::Logger.new
end end
# copy/process a template in the compass template directory to the project directory. # copy/process a template in the compass template directory to the project directory.
@ -17,13 +17,14 @@ module Compass
# create a directory and all the directories necessary to reach it. # create a directory and all the directories necessary to reach it.
def directory(dir, options = nil) def directory(dir, options = nil)
options ||= self.options if self.respond_to?(:options) options ||= self.options if self.respond_to?(:options)
options ||= {}
if File.exists?(dir) && File.directory?(dir) if File.exists?(dir) && File.directory?(dir)
# logger.record :exists, basename(dir) unless options[:quiet] # do nothing
elsif File.exists?(dir) elsif File.exists?(dir)
msg = "#{basename(dir)} already exists and is not a directory." msg = "#{basename(dir)} already exists and is not a directory."
raise Compass::FilesystemConflict.new(msg) raise Compass::FilesystemConflict.new(msg)
else else
logger.record :directory, separate("#{basename(dir)}/") log_action :directory, separate("#{basename(dir)}/"), options
FileUtils.mkdir_p(dir) unless options[:dry_run] FileUtils.mkdir_p(dir) unless options[:dry_run]
end end
end end
@ -33,20 +34,19 @@ module Compass
options ||= self.options if self.respond_to?(:options) options ||= self.options if self.respond_to?(:options)
skip_write = options[:dry_run] skip_write = options[:dry_run]
contents = process_erb(contents, options[:erb]) if options[:erb] contents = process_erb(contents, options[:erb]) if options[:erb]
extra = options[:extra] || ""
if File.exists?(file_name) if File.exists?(file_name)
existing_contents = IO.read(file_name) existing_contents = IO.read(file_name)
if existing_contents == contents if existing_contents == contents
logger.record :identical, basename(file_name), extra log_action :identical, basename(file_name), options
skip_write = true skip_write = true
elsif options[:force] elsif options[:force]
logger.record :overwrite, basename(file_name), extra log_action :overwrite, basename(file_name), options
else else
msg = "File #{basename(file_name)} already exists. Run with --force to force overwrite." msg = "File #{basename(file_name)} already exists. Run with --force to force overwrite."
raise Compass::FilesystemConflict.new(msg) raise Compass::FilesystemConflict.new(msg)
end end
else else
logger.record :create, basename(file_name), extra log_action :create, basename(file_name), options
end end
if skip_write if skip_write
FileUtils.touch file_name unless options[:dry_run] FileUtils.touch file_name unless options[:dry_run]
@ -67,7 +67,7 @@ module Compass
def remove(file_name) def remove(file_name)
if File.exists?(file_name) if File.exists?(file_name)
File.unlink file_name File.unlink file_name
logger.record :remove, basename(file_name) log_action :remove, basename(file_name), options
end end
end end
@ -95,5 +95,14 @@ module Compass
(path[-1..-1] == File::SEPARATOR) ? path[0..-2] : path (path[-1..-1] == File::SEPARATOR) ? path[0..-2] : path
end end
def log_action(action, file, options)
quiet = !!options[:quiet]
quiet = false if options[:loud] && options[:loud] == true
quiet = false if options[:loud] && options[:loud].is_a?(Array) && options[:loud].include?(action)
unless quiet
logger.record(action, file, options[:extra].to_s)
end
end
end end
end end

View File

@ -33,6 +33,7 @@ module Compass
def perform def perform
compiler = new_compiler_instance compiler = new_compiler_instance
check_for_sass_files!(compiler) check_for_sass_files!(compiler)
compiler.clean! if compiler.new_config?
compiler.run compiler.run
end end

View File

@ -135,7 +135,7 @@ module Compass
def recompile(base = nil, relative = nil) def recompile(base = nil, relative = nil)
@memory_cache.reset! if @memory_cache @memory_cache.reset! if @memory_cache
compiler = new_compiler_instance(:quiet => true) compiler = new_compiler_instance(:quiet => true, :loud => [:identical, :overwrite, :create])
if file = compiler.out_of_date? if file = compiler.out_of_date?
begin begin
puts ">>> Change detected to: #{relative || compiler.relative_stylesheet_name(file)}" puts ">>> Change detected to: #{relative || compiler.relative_stylesheet_name(file)}"

View File

@ -153,7 +153,7 @@ module Compass
formatted_error = "(Line #{e.sass_line}: #{e.message})" formatted_error = "(Line #{e.sass_line}: #{e.message})"
file = basename(sass_filename) file = basename(sass_filename)
logger.record :error, file, formatted_error logger.record :error, file, formatted_error
Compass.configuration.run_callback(:styesheet_error, sass_filename, formatted_error) Compass.configuration.run_callback(:stylesheet_error, sass_filename, formatted_error)
write_file css_filename, error_contents(e, sass_filename), options.merge(:force => true) write_file css_filename, error_contents(e, sass_filename), options.merge(:force => true)
end end

View File

@ -23,7 +23,7 @@ module Compass
plugin_opts[:cache_location] = cache_path unless cache_path.nil? plugin_opts[:cache_location] = cache_path unless cache_path.nil?
plugin_opts.merge!(sass_options || {}) plugin_opts.merge!(sass_options || {})
plugin_opts[:load_paths] ||= [] plugin_opts[:load_paths] ||= []
plugin_opts[:load_paths] << Compass::Sprites.new plugin_opts[:load_paths] << Compass::SpriteMap.new
plugin_opts plugin_opts
end end
@ -63,7 +63,7 @@ module Compass
next p if p.respond_to?(:find_relative) next p if p.respond_to?(:find_relative)
Sass::Importers::Filesystem.new(p.to_s) Sass::Importers::Filesystem.new(p.to_s)
end end
load_paths << Compass::Sprites.new load_paths << Compass::SpriteMap.new
load_paths load_paths
end end
end end

View File

@ -1,5 +1,4 @@
require 'digest/md5' require 'digest/md5'
require 'compass/sass_extensions/sprites/sprites'
require 'compass/sass_extensions/sprites/sprite_map' require 'compass/sass_extensions/sprites/sprite_map'
require 'compass/sass_extensions/sprites/image' require 'compass/sass_extensions/sprites/image'
require 'compass/sass_extensions/sprites/base' require 'compass/sass_extensions/sprites/base'

View File

@ -7,7 +7,7 @@ module Compass
# Initialize a new aprite object from a relative file path # Initialize a new aprite object from a relative file path
# the path is relative to the <tt>images_path</tt> confguration option # the path is relative to the <tt>images_path</tt> confguration option
def self.from_uri(uri, context, kwargs) def self.from_uri(uri, context, kwargs)
sprite_map = ::Compass::SpriteMap.new(uri.value, {}) sprite_map = ::Compass::SpriteMap.new(:uri => uri.value, :options => {})
sprites = sprite_map.files.map do |sprite| sprites = sprite_map.files.map do |sprite|
sprite.gsub(Compass.configuration.images_path+"/", "") sprite.gsub(Compass.configuration.images_path+"/", "")
end end

View File

@ -1,14 +1,63 @@
module Compass module Compass
class SpriteMap class SpriteMap < Sass::Importers::Base
attr_reader :uri, :options attr_accessor :uri, :options
VAILD_FILE_NAME = /\A#{Sass::SCSS::RX::IDENT}\Z/ VAILD_FILE_NAME = /\A#{Sass::SCSS::RX::IDENT}\Z/
SPRITE_IMPORTER_REGEX = %r{((.+/)?([^\*.]+))/(.+?)\.png}
def find_relative(*args)
nil def self.load(uri, options)
Compass.quick_cache "Sprite_map:#{uri}#{options.inspect}", 5 do
klass = Compass::SpriteMap.new
klass.uri, klass.options = uri, options
klass
end
end end
def initialize(uri, options) def initialize(options ={})
@uri, @options = '', {}
options.each do |key, value|
send("#{key}=", value)
end
end
def find(uri, options)
@uri, @options = uri, options @uri, @options = uri, options
if uri =~ SPRITE_IMPORTER_REGEX
return sass_engine
end
end
def find_relative(uri, base, options)
@uri, @options = uri, options
find(File.join(base, uri), options)
end
def to_s
content_for_images
end
def hash
self.class.name.hash
end
def eql?(other)
other.class == self.class
end
def key(uri, options={})
@uri, @options = uri, options
[self.class.name + ":" + File.dirname(File.expand_path(uri)), File.basename(uri)]
end
def self.path_and_name(uri)
Compass.quick_cache "Sprite_map_name:#{uri}", 5 do
if uri =~ SPRITE_IMPORTER_REGEX
[$1, $3]
else
[nil, nil]
end
end
end end
# Name of this spite # Name of this spite
@ -50,27 +99,8 @@ module Compass
end end
def ensure_path_and_name! def ensure_path_and_name!
@path ||= get_path @path, @name = self.class.path_and_name(uri)
@name ||= get_name end
end
def get_name
_, name = Compass::Sprites.path_and_name(uri)
name
end
def get_path
path, _ = Compass::Sprites.path_and_name(uri)
path
end
def key(uri, options)
Compass::Sprites.key(uri)
end
def mtime(uri, options)
Compass::Sprites.mtime(uri, options)
end
# Generates the Sass for this sprite file # Generates the Sass for this sprite file
def content_for_images(skip_overrides = false) def content_for_images(skip_overrides = false)

View File

@ -1,62 +0,0 @@
module Compass
class Sprites < Sass::Importers::Base
attr_accessor :name, :path
def self.path_and_name(uri)
if uri =~ %r{((.+/)?([^\*.]+))/(.+?)\.png}
[$1, $3]
end
end
def self.discover_sprites(uri)
self.load_map(uri, {}).files
end
def self.sprite_name(file)
File.basename(file, '.png')
end
def self.load_map(uri, options)
Compass.quick_cache("spritemap:#{uri}", 5) do
SpriteMap.new(uri, options)
end
end
# Called by the sass engine to build a new SpriteMap
def find(uri, options)
if uri =~ /\.png$/
map = Compass::Sprites.load_map(uri, options)
self.path, self.name = map.path, map.name
return map.sass_engine
end
end
# Called by the sass engine to identify the SpriteMap
def self.key(uri, options={})
[self.class.name + ":" + File.dirname(File.expand_path(uri)), File.basename(uri)]
end
def self.mtime(uri, options)
Compass.quick_cache("mtime:#{uri}") do
map = Compass::Sprites.load_map(uri, options)
map.files.inject(Time.at(0)) do |max_time, file|
(t = File.mtime(file)) > max_time ? t : max_time
end
end
end
def to_s
self.class.name
end
def hash
self.class.name.hash
end
def eql?(other)
other.class == self.class
end
end
end

View File

@ -0,0 +1,10 @@
# Require any additional compass plugins here.
css_dir = "tmp"
sass_dir = "sass"
images_dir = "assets/images"
javascripts_dir = "assets/javascripts"
# Set this to the root of your project when deployed:
http_path = "/"
# To enable relative paths to assets via compass helper functions. Uncomment:
output_style = :compact
relative_assets = true

View File

@ -0,0 +1,2 @@
test
background: image_url("testing.png)

View File

@ -30,14 +30,16 @@ class CompassTest < Test::Unit::TestCase
# no project with errors exists to test aginst - leep of FAITH! # no project with errors exists to test aginst - leep of FAITH!
# *chriseppstein flogs himself* # *chriseppstein flogs himself*
# def test_on_stylesheet_error_callback def test_on_stylesheet_error_callback
# error = false error = false
# file = nil file = nil
# Compass.configuration.on_stylesheet_error {|filename, message| file = filename; error = true } before_compile = Proc.new do |config|
# within_project(:error) { } #requires a block but we don't need to pass anything - sdavis config.on_stylesheet_error {|filename, message| file = filename; error = true }
# assert error, "Project did not throw a compile error" end
# assert file.is_a?(String), "Filename was not a string" within_project(:error, before_compile) rescue nil;
# end assert error, "Project did not throw a compile error"
assert file.is_a?(String), "Filename was not a string"
end
def test_empty_project def test_empty_project
# With no sass files, we should have no css files. # With no sass files, we should have no css files.

View File

@ -0,0 +1,24 @@
require 'test_helper'
require 'compass'
class ActionsTest < Test::Unit::TestCase
class BaseActionExtender
include Compass::Actions
def options
@@options ||= {}
end
def working_path
"/tmp"
end
end
# When log4r is included, it sometimes breaks the Actions
def test_quiet_option
b = BaseActionExtender.new
b.logger = ""
b.options[:quiet] = true
# logger shouldn't be called... if it is, this will error
b.directory("/tmp/#{(rand * 1000000).to_i}")
end
end

View File

@ -16,7 +16,7 @@ class SpritesBaseTest < Test::Unit::TestCase
end end
def setup_map def setup_map
@map = Compass::SpriteMap.new("selectors/*.png", @options) @map = Compass::SpriteMap.new(:uri => "selectors/*.png", :options => @options)
@base = Compass::SassExtensions::Sprites::Base.new(@map.sprite_names.map{|n| "selectors/#{n}.png"}, @map, @map.sass_engine, @map.options) @base = Compass::SassExtensions::Sprites::Base.new(@map.sprite_names.map{|n| "selectors/#{n}.png"}, @map, @map.sass_engine, @map.options)
end end

View File

@ -19,7 +19,7 @@ class SpritesImageTest < Test::Unit::TestCase
let(:sprite_name) { File.basename(sprite_filename, '.png') } let(:sprite_name) { File.basename(sprite_filename, '.png') }
def parent def parent
map = Compass::SpriteMap.new("selectors/*.png", options) map = Compass::SpriteMap.new(:uri => "selectors/*.png", :options => options)
@parent ||= Compass::SassExtensions::Sprites::Base.new(map.sprite_names.map{|n| "selectors/#{n}.png"}, map, map.sass_engine, map.options) @parent ||= Compass::SassExtensions::Sprites::Base.new(map.sprite_names.map{|n| "selectors/#{n}.png"}, map, map.sass_engine, map.options)
end end