diff --git a/.travis.yml b/.travis.yml index 3bb2dc2d..a388edde 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,4 +4,4 @@ rvm: - jruby - rbx - ree -script: "bundle exec rake test" +script: "bundle exec rake test features" diff --git a/Gemfile b/Gemfile index c25f6833..8be637a1 100644 --- a/Gemfile +++ b/Gemfile @@ -5,7 +5,7 @@ gemspec gem "cucumber", "~> 0.9.2" gem "rspec", "~>2.0.0" gem "rails", "~>3.0.0.rc" -gem "compass-validator", "3.0.0" +gem "compass-validator", "3.0.1" gem "css_parser", "~> 1.0.1" gem "sass", "~>3.1" gem "haml", "~> 3.1" diff --git a/Gemfile.lock b/Gemfile.lock index 9f979828..319f703a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,8 +7,8 @@ GIT PATH remote: . specs: - compass (0.11.1.f248c22) - chunky_png (~> 1.1) + compass (0.11.3.b352e8b) + chunky_png (~> 1.2) fssm (>= 0.2.7) sass (~> 3.1) @@ -51,7 +51,7 @@ GEM sys-uname builder (2.1.2) chunky_png (1.2.0) - compass-validator (3.0.0) + compass-validator (3.0.1) css_parser (1.0.1) cucumber (0.9.4) builder (~> 2.1.2) @@ -136,7 +136,7 @@ DEPENDENCIES autotest autotest-fsevent compass! - compass-validator (= 3.0.0) + compass-validator (= 3.0.1) css_parser (~> 1.0.1) cucumber (~> 0.9.2) diff-lcs (~> 1.1.2) diff --git a/compass.gemspec b/compass.gemspec index 87e2436f..d6c1194e 100644 --- a/compass.gemspec +++ b/compass.gemspec @@ -16,7 +16,7 @@ Gem::Specification.new do |gemspec| gemspec.summary = %q{A Real Stylesheet Framework} gemspec.add_dependency 'sass', '~> 3.1' - gemspec.add_dependency 'chunky_png', '~> 1.1' + gemspec.add_dependency 'chunky_png', '~> 1.2' gemspec.add_dependency 'fssm', '>= 0.2.7' gemspec.files = %w(README.markdown LICENSE.markdown VERSION.yml Rakefile) diff --git a/doc-src/content/CHANGELOG.markdown b/doc-src/content/CHANGELOG.markdown index a8c18baa..588b699b 100644 --- a/doc-src/content/CHANGELOG.markdown +++ b/doc-src/content/CHANGELOG.markdown @@ -14,6 +14,29 @@ The Documentation for the [latest stable release](http://compass-style.org/docs/ The Documentation for the [latest preview release](http://beta.compass-style.org/) +0.11.3 (06/11/2011) +------------------- + +**Note:** Due to some internal changes to compass you may have issue with your sass cache. Run `compass clean` to clear your cache. + +* The `pie-clearfix` mixin has been updated. If you have to + support Firefox < 3.5, please update your stylesheets + to use `legacy-pie-clearfix` instead. +* Added a new command: `compass clean` which removes any generated + css files and clears the sass cache. +* Enable IE 10 support for flexible box with the -ms prefix. +* A small change to how generated sprites are named for better + rails 3.1 compatibility. +* Fixes for the compass --quiet mode. +* It is now possible to generate cache buster urls that manipulate + the path of the image instead of the query string. This makes + images work better with proxies, but will require some web server + configuration. [Docs](/help/tutorials/configuration-reference/#asset-cache-buster) +* Numerous small bug fixes to sprites. +* Sprite Engines are now classes see [Docs](/help/tutorials/extending) for more information +* Sprite classes have bee re-factored into modules for readability +* Sprites will no longer cause `undefined method 'find' for #` when adding or removing sprite files + 0.11.2 (06/10/2011) ------------------- * Sprites will now by default remove any old versions of the sprite. A new configuration diff --git a/doc-src/content/help/tutorials/configuration-reference.markdown b/doc-src/content/help/tutorials/configuration-reference.markdown index af6d6ea7..642707ca 100644 --- a/doc-src/content/help/tutorials/configuration-reference.markdown +++ b/doc-src/content/help/tutorials/configuration-reference.markdown @@ -307,10 +307,14 @@ the asset host configuration is ignored. --- + **`asset_cache_buster`** – Pass this function a block of code that defines the -cache buster strategy to be used. The block must return nil or a string that can -be appended to a url as a query parameter. The returned string must not include -the starting `?`. The block will be passed the root-relative url of the asset. +cache buster strategy to be used. The block must return nil, a string or a hash. +If the returned value is a hash the values of :path and/or :query is used to generate +a cache busted path to the asset. If a string value is returned, it is added as a query string. +The returned values for query strings must not include the starting `?`. + +The block will be passed the root-relative url of the asset. If the block accepts two arguments, it will also be passed a path that points to the asset on disk — which may or may not exist. @@ -324,6 +328,18 @@ that points to the asset on disk — which may or may not exist. end end +Busting the cache via path: + + asset_cache_buster do |path, real_path| + if File.exists?(real_path) + pathname = Pathname.new(path) + modified_time = File.mtime(real_path).strftime("%s") + new_path = "%s/%s-%s%s" % [pathname.dirname, pathname.basename(pathname.extname), modified_time, pathname.extname] + + {:path => new_path, :query => nil} + end + end + To disable the asset cache buster: asset_cache_buster :none diff --git a/doc-src/content/help/tutorials/extending.markdown b/doc-src/content/help/tutorials/extending.markdown index 9d7f4d88..e07fe249 100644 --- a/doc-src/content/help/tutorials/extending.markdown +++ b/doc-src/content/help/tutorials/extending.markdown @@ -14,11 +14,9 @@ The sprite engine is the work horse of sprite generation it's the interface for ### Requirements -A sprite engine requires only one method and that is `construct_sprite` which must return an object that responds to `save(filepath)` +A sprite engine requires two methods `construct_sprite`, and `save(filename)` -Once inside this method you have access to `images` which is a collection of [Compass::SassExtensions::Sprites::Image](http://rdoc.info/github/chriseppstein/compass/dda7c9/Compass/SassExtensions/Sprites/Image) - -Since the Engine module extends base you also have access to all methods in [Compass::SassExtensions::Sprites::Base](http://rdoc.info/github/chriseppstein/compass/dda7c9/Compass/SassExtensions/Sprites/Base) +Once inside the class you have access to `images` which is a collection of [Compass::SassExtensions::Sprites::Image](http://rdoc.info/github/chriseppstein/compass/dda7c9/Compass/SassExtensions/Sprites/Image) ### Configuration @@ -26,7 +24,7 @@ To enable your sprite engine from the config file set sprite_engine = : -The example below will load `Compass::SassExtension::Sprites::ChunkyPngEngine` +The example below will load `Compass::SassExtension::Sprites::ChunkyPngEngine.new(width, height, images)` sprite_engine = :chunky_png @@ -35,13 +33,16 @@ The example below will load `Compass::SassExtension::Sprites::ChunkyPngEngine` module Compass module SassExtensions module Sprites - module Engine + class ChunkyPngEngine < Compass::SassExtensions::Sprites::Engine - # Returns an object def construct_sprite - #must return a image object that responds to save(filename) + #do something + end + + def save(filename) + #save file end - + end end end diff --git a/doc-src/content/help/tutorials/spriting.markdown b/doc-src/content/help/tutorials/spriting.markdown index bf3d1b08..82874aef 100644 --- a/doc-src/content/help/tutorials/spriting.markdown +++ b/doc-src/content/help/tutorials/spriting.markdown @@ -34,7 +34,7 @@ And you'll get the following CSS output: .icon-delete, .icon-edit, .icon-new, - .icon-save { background: url('/images/icon-34fe0604ab.png') no-repeat; } + .icon-save { background: url('/images/icon-s34fe0604ab.png') no-repeat; } .icon-delete { background-position: 0 0; } .icon-edit { background-position: 0 -32px; } @@ -74,7 +74,7 @@ And your stylesheet will compile to: .actions .new, .actions .edit, .actions .save, - .actions .delete { background: url('/images/icon-34fe0604ab.png') no-repeat; } + .actions .delete { background: url('/images/icon-s34fe0604ab.png') no-repeat; } .actions .new { background-position: 0 -64px; } .actions .edit { background-position: 0 -32px; } @@ -122,7 +122,7 @@ Now in our sass file we add: And your stylesheet will compile to: .selectors-sprite, a { - background: url('/selectors-edfef809e2.png') no-repeat; + background: url('/selectors-sedfef809e2.png') no-repeat; } a { @@ -141,7 +141,7 @@ And your stylesheet will compile to: Alternatively you can use the `@include all-selectors-sprites;` after the import and get the following output: .selectors-sprite, .selectors-ten-by-ten { - background: url('/selectors-edfef809e2.png') no-repeat; + background: url('/selectors-sedfef809e2.png') no-repeat; } .selectors-ten-by-ten { diff --git a/features/command_line.feature b/features/command_line.feature index f0be79b1..06e0060c 100644 --- a/features/command_line.feature +++ b/features/command_line.feature @@ -145,6 +145,7 @@ Feature: Command Line Scenario: Basic help When I run: compass help Then I should see the following "primary" commands: + | clean | | compile | | create | | init | @@ -179,6 +180,27 @@ Feature: Command Line And I run: compass compile And a css file tmp/layout.css is reported overwritten + Scenario: Cleaning a project + Given I am using the existing project in test/fixtures/stylesheets/compass + When I run: compass compile + And I run: compass clean + Then the following files are reported removed: + | .sass-cache/ | + | tmp/border_radius.css | + | tmp/box.css | + | tmp/box_shadow.css | + | tmp/columns.css | + | tmp/fonts.css | + | images/flag-s03c3b29b35.png | + And the following files are removed: + | .sass-cache/ | + | tmp/border_radius.css | + | tmp/box.css | + | tmp/box_shadow.css | + | tmp/columns.css | + | tmp/fonts.css | + | images/flag-s03c3b29b35.png | + Scenario: Watching a project for changes Given ruby supports fork Given I am using the existing project in test/fixtures/stylesheets/compass @@ -218,7 +240,6 @@ Feature: Command Line | sass_dir | sass | | css_dir | assets/css | - @now Scenario Outline: Print out a configuration value Given I am using the existing project in test/fixtures/stylesheets/compass When I run: compass config -p diff --git a/features/step_definitions/command_line_steps.rb b/features/step_definitions/command_line_steps.rb index 0b4407fa..5bddd7a7 100644 --- a/features/step_definitions/command_line_steps.rb +++ b/features/step_definitions/command_line_steps.rb @@ -76,7 +76,7 @@ When /^I run in a separate process: compass ([^\s]+) ?(.+)?$/ do |command, args| file.puts $stdout.string end open('/tmp/last_error.compass_test.txt', 'w') do |file| - file.puts @stderr.string + file.puts $stderr.string end exit! end @@ -116,10 +116,30 @@ Then /^a directory ([^ ]+) is (not )?created$/ do |directory, negated| File.directory?(directory).should == !negated end +Then /an? \w+ file ([^ ]+) is (not )?removed/ do |filename, negated| + File.exists?(filename).should == !!negated +end + Then /an? \w+ file ([^ ]+) is (not )?created/ do |filename, negated| File.exists?(filename).should == !negated end +Then "the following files are reported removed:" do |table| + table.rows.each do |css_file| + Then %Q{a css file #{css_file.first} is reported removed} + end +end + +Then "the following files are removed:" do |table| + table.rows.each do |css_file| + Then %Q{a css file #{css_file.first} is removed} + end +end + +Then /an? \w+ file ([^ ]+) is reported removed/ do |filename| + @last_result.should =~ /remove.*#{Regexp.escape(filename)}/ +end + Then /an? \w+ file ([^ ]+) is reported created/ do |filename| @last_result.should =~ /create.*#{Regexp.escape(filename)}/ end diff --git a/frameworks/compass/stylesheets/compass/utilities/general/_clearfix.scss b/frameworks/compass/stylesheets/compass/utilities/general/_clearfix.scss index 2c097cc1..73f9254c 100644 --- a/frameworks/compass/stylesheets/compass/utilities/general/_clearfix.scss +++ b/frameworks/compass/stylesheets/compass/utilities/general/_clearfix.scss @@ -18,7 +18,7 @@ // [Easy Clearing](http://www.positioniseverything.net/easyclearing.html) // has the advantage of allowing positioned elements to hang // outside the bounds of the container at the expense of more tricky CSS. -@mixin pie-clearfix { +@mixin legacy-pie-clearfix { &:after { content : "\0020"; display : block; @@ -29,3 +29,16 @@ } @include has-layout; } + +// This is an updated version of the PIE clearfix method that reduces the amount of CSS output. +// If you need to support Firefox before 3.5 you need to use `legacy-pie-clearfix` instead. +// +// Adapted from: [A new micro clearfix hack](http://nicolasgallagher.com/micro-clearfix-hack/) +@mixin pie-clearfix { + &:after { + content: ""; + display: table; + clear: both; + } + @include has-layout; +} diff --git a/lib/compass/actions.rb b/lib/compass/actions.rb index bc4a2b82..4e924f1b 100644 --- a/lib/compass/actions.rb +++ b/lib/compass/actions.rb @@ -65,7 +65,10 @@ module Compass end def remove(file_name) - if File.exists?(file_name) + if File.directory?(file_name) + FileUtils.rm_rf file_name + log_action :remove, basename(file_name)+"/", options + elsif File.exists?(file_name) File.unlink file_name log_action :remove, basename(file_name), options end diff --git a/lib/compass/commands.rb b/lib/compass/commands.rb index f4230ef4..42ca37ab 100644 --- a/lib/compass/commands.rb +++ b/lib/compass/commands.rb @@ -4,7 +4,7 @@ end require 'compass/commands/registry' %w(base generate_grid_background default help list_frameworks project_base - update_project watch_project create_project imports installer_command + update_project watch_project create_project clean_project imports installer_command print_version project_stats stamp_pattern sprite validate_project write_configuration interactive unpack_extension).each do |lib| require "compass/commands/#{lib}" diff --git a/lib/compass/commands/clean_project.rb b/lib/compass/commands/clean_project.rb new file mode 100644 index 00000000..e6792326 --- /dev/null +++ b/lib/compass/commands/clean_project.rb @@ -0,0 +1,79 @@ +require 'compass/commands/project_base' +require 'compass/compiler' + +module Compass + module Commands + module CleanProjectOptionsParser + def set_options(opts) + opts.banner = %Q{ + Usage: compass clean [path/to/project] [options] + + Description: + Remove generated files and the sass cache. + + Options: + }.split("\n").map{|l| l.gsub(/^ */,'')}.join("\n") + + super + end + end + + class CleanProject < UpdateProject + + register :clean + + def initialize(working_path, options) + super + assert_project_directory_exists! + end + + def perform + compiler = new_compiler_instance + compiler.clean! + Compass::SpriteImporter.find_all_sprite_map_files(Compass.configuration.images_path).each do |sprite| + remove sprite + end + end + + def determine_cache_location + Compass.configuration.cache_path || Sass::Plugin.options[:cache_location] || File.join(working_path, ".sass-cache") + end + + class << self + def option_parser(arguments) + parser = Compass::Exec::CommandOptionParser.new(arguments) + parser.extend(Compass::Exec::GlobalOptionsParser) + parser.extend(Compass::Exec::ProjectOptionsParser) + parser.extend(CleanProjectOptionsParser) + end + + def usage + option_parser([]).to_s + end + + def primary; true; end + + def description(command) + "Remove generated files and the sass cache" + end + + def parse!(arguments) + parser = option_parser(arguments) + parser.parse! + parse_arguments!(parser, arguments) + parser.options + end + + def parse_arguments!(parser, arguments) + if arguments.size > 0 + parser.options[:project_name] = arguments.shift if File.directory?(arguments.first) + unless arguments.empty? + parser.options[:sass_files] = arguments.dup + parser.options[:force] = true + end + end + end + end + end + end +end diff --git a/lib/compass/commands/registry.rb b/lib/compass/commands/registry.rb index 64372079..3b5c0d16 100644 --- a/lib/compass/commands/registry.rb +++ b/lib/compass/commands/registry.rb @@ -16,8 +16,10 @@ module Compass::Commands matching.first elsif name =~ /^-/ nil - else + elsif matching.size > 1 raise Compass::Error, "Ambiguous abbreviation '#{name}'. Did you mean one of: #{matching.join(", ")}" + else + raise Compass::Error, "Command not found: #{name}" end end def abbreviation?(name) diff --git a/lib/compass/commands/sprite.rb b/lib/compass/commands/sprite.rb index b1c8bee9..b93705ed 100644 --- a/lib/compass/commands/sprite.rb +++ b/lib/compass/commands/sprite.rb @@ -39,7 +39,7 @@ module Compass def perform relative_uri = options[:uri].gsub(/^#{Compass.configuration.images_dir}\//, '') - sprites = Compass::SpriteImporter.new(relative_uri, Compass.sass_engine_options) + sprites = Compass::SpriteImporter.new(:uri => relative_uri, :options => Compass.sass_engine_options) options[:output_file] ||= File.join(Compass.configuration.sass_path, "sprites", "_#{sprites.name}.#{Compass.configuration.preferred_syntax}") options[:skip_overrides] ||= false contents = sprites.content_for_images(options[:skip_overrides]) diff --git a/lib/compass/commands/update_project.rb b/lib/compass/commands/update_project.rb index 1eb0a595..30e2654f 100644 --- a/lib/compass/commands/update_project.rb +++ b/lib/compass/commands/update_project.rb @@ -51,12 +51,10 @@ module Compass def new_compiler_instance(additional_options = {}) @compiler_opts ||= begin - compiler_opts = Compass.sass_engine_options - compiler_opts.merge!(:force => options[:force], - :sass_files => explicit_sass_files, - :dry_run => options[:dry_run]) - compiler_opts[:quiet] = options[:quiet] if options[:quiet] - compiler_opts[:time] = options[:time] if options[:time] + compiler_opts = {:sass => Compass.sass_engine_options} + compiler_opts.merge!(options) + compiler_opts[:sass_files] = explicit_sass_files + compiler_opts[:cache_location] = determine_cache_location compiler_opts end diff --git a/lib/compass/compiler.rb b/lib/compass/compiler.rb index e7f6feef..fe00ef66 100644 --- a/lib/compass/compiler.rb +++ b/lib/compass/compiler.rb @@ -3,16 +3,19 @@ module Compass include Actions - attr_accessor :working_path, :from, :to, :options, :staleness_checker, :importer + attr_accessor :working_path, :from, :to, :options, :sass_options, :staleness_checker, :importer def initialize(working_path, from, to, options) self.working_path = working_path self.from, self.to = from.gsub('./', ''), to self.logger = options.delete(:logger) + sass_opts = options.delete(:sass) || {} self.options = options - self.options[:cache_location] ||= determine_cache_location - options[:importer] = self.importer = Sass::Importers::Filesystem.new(from) - self.staleness_checker = Sass::Plugin::StalenessChecker.new(options) + self.sass_options = options.dup + self.sass_options.update(sass_opts) + self.sass_options[:cache_location] ||= determine_cache_location + self.sass_options[:importer] = self.importer = Sass::Importers::Filesystem.new(from) + self.staleness_checker = Sass::Plugin::StalenessChecker.new(sass_options) end def determine_cache_location @@ -72,16 +75,16 @@ module Compass end def clean! - FileUtils.rm_rf options[:cache_location] + remove options[:cache_location] css_files.each do |css_file| - FileUtils.rm_f css_file + remove 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] + remove options[:cache_location] options[:force] = true end @@ -142,7 +145,7 @@ module Compass # 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 + opts = sass_options.merge(:filename => sass_filename, :css_filename => css_filename, :syntax => syntax) Sass::Engine.new(open(sass_filename).read, opts) end diff --git a/lib/compass/configuration/data.rb b/lib/compass/configuration/data.rb index 9cde724d..ddc2de3a 100644 --- a/lib/compass/configuration/data.rb +++ b/lib/compass/configuration/data.rb @@ -71,8 +71,10 @@ module Compass end # When called with a block, defines the cache buster strategy to be used. - # The block must return nil or a string that can be appended to a url as a query parameter. - # The returned string must not include the starting '?'. + # If the block returns nil or a string, then it is appended to the url as a query parameter. + # In this case, the returned string must not include the starting '?'. + # The block may also return a hash with :path and/or :query values and it + # will replace the original path and query string with the busted values returned. # The block will be passed the root-relative url of the asset. # If the block accepts two arguments, it will also be passed a File object # that points to the asset on disk -- which may or may not exist. diff --git a/lib/compass/exec/sub_command_ui.rb b/lib/compass/exec/sub_command_ui.rb index 972f82c8..43a5a308 100644 --- a/lib/compass/exec/sub_command_ui.rb +++ b/lib/compass/exec/sub_command_ui.rb @@ -13,6 +13,7 @@ module Compass::Exec def run! begin perform! + return 0 rescue Exception => e raise e if e.is_a? SystemExit if e.is_a?(::Compass::Error) || e.is_a?(OptionParser::ParseError) @@ -22,7 +23,6 @@ module Compass::Exec end return 1 end - return 0 end protected diff --git a/lib/compass/sass_extensions/functions/urls.rb b/lib/compass/sass_extensions/functions/urls.rb index d140c8a5..50ffab52 100644 --- a/lib/compass/sass_extensions/functions/urls.rb +++ b/lib/compass/sass_extensions/functions/urls.rb @@ -91,9 +91,7 @@ module Compass::SassExtensions::Functions::Urls if cache_buster.is_a?(Sass::Script::String) path += "?#{cache_buster.value}" else - if buster = compute_cache_buster(path, real_path) - path += "?#{buster}" - end + path = cache_busted_path(path, real_path) end end @@ -137,6 +135,23 @@ module Compass::SassExtensions::Functions::Urls end end + def cache_busted_path(path, real_path) + cache_buster = compute_cache_buster(path, real_path) + if cache_buster.nil? + return path + elsif cache_buster.is_a?(String) + cache_buster = {:query => cache_buster} + else + path = cache_buster[:path] if cache_buster[:path] + end + + if cache_buster[:query] + "%s?%s" % [path, cache_buster[:query]] + else + path + end + end + def compute_cache_buster(path, real_path) if Compass.configuration.asset_cache_buster args = [path] diff --git a/lib/compass/sass_extensions/sprites.rb b/lib/compass/sass_extensions/sprites.rb index d22ab96b..ab35d84e 100644 --- a/lib/compass/sass_extensions/sprites.rb +++ b/lib/compass/sass_extensions/sprites.rb @@ -9,6 +9,8 @@ module Compass end require 'compass/sass_extensions/sprites/image' +require 'compass/sass_extensions/sprites/sprite_methods' +require 'compass/sass_extensions/sprites/image_methods' require 'compass/sass_extensions/sprites/sprite_map' require 'compass/sass_extensions/sprites/engines' diff --git a/lib/compass/sass_extensions/sprites/engines.rb b/lib/compass/sass_extensions/sprites/engines.rb index 26a73260..0fa6d1b5 100644 --- a/lib/compass/sass_extensions/sprites/engines.rb +++ b/lib/compass/sass_extensions/sprites/engines.rb @@ -1 +1,25 @@ +module Compass + module SassExtensions + module Sprites + class Engine + attr_accessor :width, :height, :images, :canvas + def initialize(width, height, images) + @width, @height, @images = width, height, images + @canvas = nil + end + + def construct_sprite + raise ::Compass::Error, "You must impliment construct_sprite" + end + + def save(filename) + raise ::Compass::Error, "You must impliment save(filename)" + end + + end + end + end +end + + require 'compass/sass_extensions/sprites/engines/chunky_png_engine' \ No newline at end of file diff --git a/lib/compass/sass_extensions/sprites/engines/chunky_png_engine.rb b/lib/compass/sass_extensions/sprites/engines/chunky_png_engine.rb index dd7a6455..c26caa11 100644 --- a/lib/compass/sass_extensions/sprites/engines/chunky_png_engine.rb +++ b/lib/compass/sass_extensions/sprites/engines/chunky_png_engine.rb @@ -7,20 +7,19 @@ end module Compass module SassExtensions module Sprites - module ChunkyPngEngine - - # Returns a PNG object + class ChunkyPngEngine < Compass::SassExtensions::Sprites::Engine + def construct_sprite - output_png = ChunkyPNG::Image.new(width, height, ChunkyPNG::Color::TRANSPARENT) + @canvas = ChunkyPNG::Image.new(width, height, ChunkyPNG::Color::TRANSPARENT) images.each do |image| input_png = ChunkyPNG::Image.from_file(image.file) if image.repeat == "no-repeat" - output_png.replace! input_png, image.left, image.top + canvas.replace! input_png, image.left, image.top else x = image.left - (image.left / image.width).ceil * image.width while x < width do begin - output_png.replace! input_png, x, image.top + canvas.replace! input_png, x, image.top x += image.width rescue ChunkyPNG::OutOfBounds break; @@ -28,8 +27,15 @@ module Compass end end end - output_png + end + + def save(filename) + if canvas.nil? + construct_sprite + end + canvas.save(filename, :best_compression) end + end end end diff --git a/lib/compass/sass_extensions/sprites/image_methods.rb b/lib/compass/sass_extensions/sprites/image_methods.rb new file mode 100644 index 00000000..f492d59f --- /dev/null +++ b/lib/compass/sass_extensions/sprites/image_methods.rb @@ -0,0 +1,32 @@ +module Compass + module SassExtensions + module Sprites + module ImageMethods + # Fetches the Sprite::Image object for the supplied name + def image_for(name) + @images.detect { |img| img.name == name} + end + + # Returns true if the image name has a hover selector image + def has_hover?(name) + !image_for("#{name}_hover").nil? + end + + # Returns true if the image name has a target selector image + def has_target?(name) + !image_for("#{name}_target").nil? + end + + # Returns true if the image name has an active selector image + def has_active?(name) + !image_for("#{name}_active").nil? + end + + # Return and array of image names that make up this sprite + def sprite_names + image_names.map { |f| File.basename(f, '.png') } + end + end + end + end +end \ No newline at end of file diff --git a/lib/compass/sass_extensions/sprites/sprite_map.rb b/lib/compass/sass_extensions/sprites/sprite_map.rb index bf1e813d..546dd1d1 100644 --- a/lib/compass/sass_extensions/sprites/sprite_map.rb +++ b/lib/compass/sass_extensions/sprites/sprite_map.rb @@ -2,8 +2,13 @@ module Compass module SassExtensions module Sprites class SpriteMap < Sass::Script::Literal - - + attr_accessor :image_names, :path, :name, :map, :kwargs + attr_accessor :images, :width, :height, :engine + + include SpriteMethods + include ImageMethods + + # Initialize a new sprite object from a relative file path # the path is relative to the images_path confguration option def self.from_uri(uri, context, kwargs) @@ -13,22 +18,8 @@ module Compass end new(sprites, importer.path, importer.name, context, kwargs) end - - # Loads the sprite engine - def require_engine! - self.class.send(:include, eval("::Compass::SassExtensions::Sprites::#{modulize}Engine")) - end - - # Changing this string will invalidate all previously generated sprite images. - # We should do so only when the packing algorithm changes - SPRITE_VERSION = "1" - - attr_accessor :image_names, :path, :name, :kwargs - attr_accessor :images, :width, :height - def initialize(sprites, path, name, context, kwargs) - require_engine! @image_names = sprites @path = path @name = name @@ -37,150 +28,12 @@ module Compass @images = nil @width = nil @height = nil + @engine = nil @evaluation_context = context validate! compute_image_metadata! end - # Calculate the size of the sprite - def size - [width, height] - end - - # Calculates the overal image dimensions - # collects image sizes and input parameters for each sprite - # Calculates the height - def compute_image_metadata! - @width = 0 - init_images - compute_image_positions! - @height = @images.last.top + @images.last.height - end - - # Creates the Sprite::Image objects for each image and calculates the width - def init_images - @images = image_names.collect do |relative_file| - image = Compass::SassExtensions::Sprites::Image.new(self, relative_file, kwargs) - @width = [ @width, image.width + image.offset ].max - image - end - end - - # Calculates the overal image dimensions - # collects image sizes and input parameters for each sprite - def compute_image_positions! - @images.each_with_index do |image, index| - image.left = image.position.unit_str == "%" ? (@width - image.width) * (image.position.value / 100) : image.position.value - next if index == 0 - last_image = @images[index-1] - image.top = last_image.top + last_image.height + [image.spacing, last_image.spacing].max - end - end - - # Fetches the Sprite::Image object for the supplied name - def image_for(name) - @images.detect { |img| img.name == name} - end - - # Returns true if the image name has a hover selector image - def has_hover?(name) - !image_for("#{name}_hover").nil? - end - - # Returns true if the image name has a target selector image - def has_target?(name) - !image_for("#{name}_target").nil? - end - - # Returns true if the image name has an active selector image - def has_active?(name) - !image_for("#{name}_active").nil? - end - - # Return and array of image names that make up this sprite - def sprite_names - image_names.map { |f| File.basename(f, '.png') } - end - - - # Validates that the sprite_names are valid sass - def validate! - for sprite_name in sprite_names - unless sprite_name =~ /\A#{Sass::SCSS::RX::IDENT}\Z/ - raise Sass::SyntaxError, "#{sprite_name} must be a legal css identifier" - end - end - end - - # The on-the-disk filename of the sprite - def filename - File.join(Compass.configuration.images_path, "#{path}-s#{uniqueness_hash}.png") - end - - # Generate a sprite image if necessary - def generate - if generation_required? - if kwargs.get_var('cleanup').value - cleanup_old_sprites - end - sprite_data = construct_sprite - save!(sprite_data) - Compass.configuration.run_callback(:sprite_generated, sprite_data) - end - end - - def cleanup_old_sprites - Dir[File.join(Compass.configuration.images_path, "#{path}-*.png")].each do |file| - FileUtils.rm file - end - end - - # Does this sprite need to be generated - def generation_required? - !File.exists?(filename) || outdated? - end - - # Returns the uniqueness hash for this sprite object - def uniqueness_hash - @uniqueness_hash ||= begin - sum = Digest::MD5.new - sum << SPRITE_VERSION - sum << path - images.each do |image| - [:relative_file, :height, :width, :repeat, :spacing, :position, :digest].each do |attr| - sum << image.send(attr).to_s - end - end - sum.hexdigest[0...10] - end - @uniqueness_hash - end - - # Saves the sprite engine - def save!(output_png) - saved = output_png.save filename - Compass.configuration.run_callback(:sprite_saved, filename) - saved - end - - # All the full-path filenames involved in this sprite - def image_filenames - @images.map(&:file) - end - - # Checks whether this sprite is outdated - def outdated? - if File.exists?(filename) - return @images.map(&:mtime).any? { |imtime| imtime.to_i > self.mtime.to_i } - end - true - end - - # Mtime of the sprite file - def mtime - @mtime ||= File.mtime(filename) - end - def inspect to_s end @@ -200,14 +53,14 @@ module Compass super end end - + private - + def modulize @modulize ||= Compass::configuration.sprite_engine.to_s.scan(/([^_.]+)/).flatten.map {|chunk| "#{chunk[0].chr.upcase}#{chunk[1..-1]}" }.join end - + end end end -end +end \ No newline at end of file diff --git a/lib/compass/sass_extensions/sprites/sprite_methods.rb b/lib/compass/sass_extensions/sprites/sprite_methods.rb new file mode 100644 index 00000000..c620e95a --- /dev/null +++ b/lib/compass/sass_extensions/sprites/sprite_methods.rb @@ -0,0 +1,134 @@ +module Compass + module SassExtensions + module Sprites + module SpriteMethods + + # Changing this string will invalidate all previously generated sprite images. + # We should do so only when the packing algorithm changes + SPRITE_VERSION = "1" + + # Calculates the overal image dimensions + # collects image sizes and input parameters for each sprite + # Calculates the height + def compute_image_metadata! + @width = 0 + init_images + compute_image_positions! + @height = @images.last.top + @images.last.height + init_engine + end + + def init_engine + @engine = eval("::Compass::SassExtensions::Sprites::#{modulize}Engine.new(nil, nil, nil)") + @engine.width = @width + @engine.height = @height + @engine.images = @images + end + + # Creates the Sprite::Image objects for each image and calculates the width + def init_images + @images = image_names.collect do |relative_file| + image = Compass::SassExtensions::Sprites::Image.new(self, relative_file, kwargs) + @width = [ @width, image.width + image.offset ].max + image + end + end + + # Calculates the overal image dimensions + # collects image sizes and input parameters for each sprite + def compute_image_positions! + @images.each_with_index do |image, index| + image.left = image.position.unit_str == "%" ? (@width - image.width) * (image.position.value / 100) : image.position.value + next if index == 0 + last_image = @images[index-1] + image.top = last_image.top + last_image.height + [image.spacing, last_image.spacing].max + end + end + + # Validates that the sprite_names are valid sass + def validate! + for sprite_name in sprite_names + unless sprite_name =~ /\A#{Sass::SCSS::RX::IDENT}\Z/ + raise Sass::SyntaxError, "#{sprite_name} must be a legal css identifier" + end + end + end + + # The on-the-disk filename of the sprite + def filename + File.join(Compass.configuration.images_path, "#{path}-s#{uniqueness_hash}.png") + end + + # Generate a sprite image if necessary + def generate + if generation_required? + if kwargs.get_var('cleanup').value + cleanup_old_sprites + end + engine.construct_sprite + Compass.configuration.run_callback(:sprite_generated, engine.canvas) + save! + end + end + + def cleanup_old_sprites + Dir[File.join(Compass.configuration.images_path, "#{path}-*.png")].each do |file| + FileUtils.rm file + end + end + + # Does this sprite need to be generated + def generation_required? + !File.exists?(filename) || outdated? + end + + # Returns the uniqueness hash for this sprite object + def uniqueness_hash + @uniqueness_hash ||= begin + sum = Digest::MD5.new + sum << SPRITE_VERSION + sum << path + images.each do |image| + [:relative_file, :height, :width, :repeat, :spacing, :position, :digest].each do |attr| + sum << image.send(attr).to_s + end + end + sum.hexdigest[0...10] + end + @uniqueness_hash + end + + # Saves the sprite engine + def save! + saved = engine.save(filename) + Compass.configuration.run_callback(:sprite_saved, filename) + saved + end + + # All the full-path filenames involved in this sprite + def image_filenames + @images.map(&:file) + end + + # Checks whether this sprite is outdated + def outdated? + if File.exists?(filename) + return @images.map(&:mtime).any? { |imtime| imtime.to_i > self.mtime.to_i } + end + true + end + + # Mtime of the sprite file + def mtime + @mtime ||= File.mtime(filename) + end + + # Calculate the size of the sprite + def size + [width, height] + end + + end + end + end +end \ No newline at end of file diff --git a/lib/compass/sprite_importer.rb b/lib/compass/sprite_importer.rb index 94d3b11e..3dd1bd3e 100644 --- a/lib/compass/sprite_importer.rb +++ b/lib/compass/sprite_importer.rb @@ -4,7 +4,14 @@ module Compass VAILD_FILE_NAME = /\A#{Sass::SCSS::RX::IDENT}\Z/ SPRITE_IMPORTER_REGEX = %r{((.+/)?([^\*.]+))/(.+?)\.png} VALID_EXTENSIONS = ['.png'] - + + # finds all sprite files + def self.find_all_sprite_map_files(path) + hex = "[0-9a-f]" + glob = "*-{,s}#{hex*10}{#{VALID_EXTENSIONS.join(",")}}" + Dir.glob(File.join(path, "**", glob)) + end + def self.load(uri, options) klass = Compass::SpriteImporter.new klass.uri, klass.options = uri, options @@ -31,7 +38,7 @@ module Compass end def to_s - content_for_images + self.class.name end def hash diff --git a/lib/compass/validator.rb b/lib/compass/validator.rb index adb9b9d8..f8197a3f 100644 --- a/lib/compass/validator.rb +++ b/lib/compass/validator.rb @@ -1,9 +1,16 @@ begin require 'rubygems' require 'compass-validator' -rescue LoadError - raise Compass::MissingDependency, %Q{The Compass CSS Validator could not be loaded. Please install it: - +rescue LoadError => e + if e.message =~ /core_ext/ + raise Compass::MissingDependency, <<-ERRORMSG +The Compass CSS Validator is out of date. Please upgrade it: +sudo gem install compass-validator --version ">= 3.0.1" +ERRORMSG + else + raise Compass::MissingDependency, <<-ERRORMSG +The Compass CSS Validator could not be loaded. Please install it: sudo gem install compass-validator -} +ERRORMSG + end end diff --git a/spec/compass/sass_extensions/sprites/base_spec.rb b/spec/compass/sass_extensions/sprites/base_spec.rb deleted file mode 100644 index 4769e172..00000000 --- a/spec/compass/sass_extensions/sprites/base_spec.rb +++ /dev/null @@ -1,57 +0,0 @@ -require 'spec_helper' -describe Compass::SassExtensions::Sprites::Base do - - before :each do - @images_src_path = File.join(File.dirname(__FILE__), '..', '..', '..', 'test_project', 'public', 'images') - @images_tmp_path = File.join(File.dirname(__FILE__), '..', '..', '..', 'test_project', 'public', 'images-tmp') - FileUtils.cp_r @images_src_path, @images_tmp_path - config = Compass::Configuration::Data.new('config') - config.images_path = @images_tmp_path - Compass.add_configuration(config) - Compass.configure_sass_plugin! - #fix this eww - options = Compass.sass_engine_options.extend Compass::SassExtensions::Functions::Sprites::VariableReader - @map = Compass::SpriteImporter.new("selectors/*.png", options) - @base = Compass::SassExtensions::Sprites::Base.new(@map.sprite_names.map{|n| "selectors/#{n}.png"}, @map.path, 'selectors', @map.sass_engine, @map.options) - end - - after :each do - FileUtils.rm_r @images_tmp_path - end - - subject { @base } - - its(:size) { should == [10,40] } - its(:sprite_names) { should == @map.sprite_names } - its(:image_filenames) { should == Dir["#{@images_tmp_path}/selectors/*.png"].sort } - its(:generation_required?) { should be_true } - its(:uniqueness_hash) { should == 'ef52c5c63a'} - its(:outdated?) { should be_true } - its(:filename) { should == File.join(@images_tmp_path, "#{@base.path}-s#{@base.uniqueness_hash}.png")} - - it "should return the 'ten-by-ten' image" do - subject.image_for('ten-by-ten').name.should == 'ten-by-ten' - subject.image_for('ten-by-ten').should be_a Compass::SassExtensions::Sprites::Image - end - - %w(target hover active).each do |selector| - it "should have a #{selector}" do - subject.send(:"has_#{selector}?", 'ten-by-ten').should be_true - end - - it "should return #{selector} image class" do - subject.image_for('ten-by-ten').send(:"#{selector}").name.should == "ten-by-ten_#{selector}" - end - - end - context "#generate" do - before { @base.generate } - it "should generate sprite" do - File.exists?(@base.filename).should be_true - end - - its(:generation_required?) { should be_false } - its(:outdated?) { should be_false } - end - -end \ No newline at end of file diff --git a/spec/compass/sass_extensions/sprites/image_spec.rb b/spec/compass/sass_extensions/sprites/image_spec.rb deleted file mode 100644 index f328a535..00000000 --- a/spec/compass/sass_extensions/sprites/image_spec.rb +++ /dev/null @@ -1,161 +0,0 @@ -require 'spec_helper' -require 'compass/sass_extensions/sprites/image' - -describe Compass::SassExtensions::Sprites::Image do - let(:sprite_filename) { 'squares/ten-by-ten.png' } - let(:sprite_path) { File.join(images_src_path, sprite_filename) } - let(:sprite_name) { File.basename(sprite_filename, '.png') } - let(:parent) do - mock - end - before do - parent.stubs(:image_for).with('ten-by-ten').returns(image) - parent.stubs(:image_for).with('ten-by-ten_hover').returns(hover_image) - end - let(:image) { self.class.describes.new(parent, File.join(sprite_filename), options)} - let(:hover_image) { self.class.describes.new(parent, File.join('selectors/ten-by-ten_hover.png'), options)} - let(:digest) { Digest::MD5.file(sprite_path).hexdigest } - subject { image } - - before { - file = StringIO.new("images_path = #{images_src_path.inspect}\n") - Compass.add_configuration(file, "sprite_config") - } - - describe '#initialize' do - its(:name) { should == sprite_name } - its(:file) { should == sprite_path } - its(:relative_file) { should == sprite_filename } - its(:width) { should == 10 } - its(:height) { should == 10 } - its(:digest) { should == digest } - its(:top) { should == 0 } - its(:left) { should == 0 } - end - - let(:get_var_expects) { nil } - let(:get_var_return) { nil } - - let(:options) { - options = mock - options.stubs(:get_var).with(anything).returns(nil) - options.stubs(:get_var).with(get_var_expects).returns(get_var_return) - options - } - - describe '#parent' do - context '_hover' do - subject { hover_image } - its(:parent) { should == image } - end - context 'no parent' do - subject { image } - its(:parent) { should be_nil } - end - end - - describe '#repeat' do - let(:type) { nil } - let(:get_var_return) { OpenStruct.new(:value => type) } - - context 'specific image' do - let(:type) { 'specific' } - let(:get_var_expects) { "#{sprite_name}-repeat" } - - its(:repeat) { should == type } - end - - context 'global' do - let(:type) { 'global' } - let(:get_var_expects) { 'repeat' } - - its(:repeat) { should == type } - end - - context 'default' do - let(:get_var_expects) { nil } - - its(:repeat) { should == "no-repeat" } - end - end - - describe '#position' do - let(:type) { nil } - let(:get_var_return) { type } - - context 'specific image' do - let(:type) { 'specific' } - let(:get_var_expects) { "#{sprite_name}-position" } - - its(:position) { should == type } - end - - context 'global' do - let(:type) { 'global' } - let(:get_var_expects) { 'position' } - - its(:position) { should == type } - end - - context 'default' do - let(:get_var_expects) { nil } - - its(:position) { should == Sass::Script::Number.new(0, ["px"]) } - end - end - - describe '#spacing' do - let(:type) { nil } - let(:get_var_return) { OpenStruct.new(:value => type) } - - context 'specific image' do - let(:type) { 'specific' } - let(:get_var_expects) { "#{sprite_name}-spacing" } - - its(:spacing) { should == type } - end - - context 'global' do - let(:type) { 'global' } - let(:get_var_expects) { 'spacing' } - - its(:spacing) { should == type } - end - - context 'default' do - let(:get_var_expects) { nil } - - its(:spacing) { should == Sass::Script::Number.new(0).value } - end - end - - describe '#offset' do - before { image.stubs(:position).returns(stub_position) } - - let(:offset) { 100 } - let(:stub_position) { - stub(:value => offset) - } - - context 'unitless' do - before { stub_position.stubs(:unitless?).returns(true) } - before { stub_position.stubs(:unit_str).returns('em') } - - its(:offset) { should == offset } - end - - context 'pixels' do - before { stub_position.stubs(:unitless?).returns(false) } - before { stub_position.stubs(:unit_str).returns('px') } - - its(:offset) { should == offset } - end - - context 'neither, use 0' do - before { stub_position.stubs(:unitless?).returns(false) } - before { stub_position.stubs(:unit_str).returns('em') } - - its(:offset) { should == 0 } - end - end -end diff --git a/spec/compass/sass_extensions/sprites/sprite_map_spec.rb b/spec/compass/sass_extensions/sprites/sprite_map_spec.rb deleted file mode 100644 index 30a3895d..00000000 --- a/spec/compass/sass_extensions/sprites/sprite_map_spec.rb +++ /dev/null @@ -1,54 +0,0 @@ -require 'spec_helper' -require 'fakefs/spec_helpers' -require 'timecop' - -describe Compass::SpriteImporter do - include FakeFS::SpecHelpers - - let(:sprite_map) { self.class.describes.new(uri, options) } - let(:options) { { :test => :test2 } } - - subject { sprite_map } - - let(:path) { 'path' } - let(:dir) { "dir/#{name}" } - let(:name) { 'subdir' } - - let(:sprite_path) { File.join(path, dir) } - let(:files) { (1..3).collect { |i| File.join(sprite_path, "#{i}.png") } } - let(:expanded_files) { files.collect { |file| File.expand_path(file) } } - - let(:configuration) { stub(:images_path => path) } - let(:mtime) { Time.now - 30 } - - before { - Compass.stubs(:configuration).returns(configuration) - - FileUtils.mkdir_p(sprite_path) - Timecop.freeze(mtime) do - files.each { |file| File.open(file, 'w') } - end - Timecop.return - } - - describe '#initialize' do - let(:uri) { 'dir/subdir/*.png' } - - its(:uri) { should == uri } - its(:path) { should == dir } - its(:name) { should == name } - - its(:files) { should == expanded_files } - - its(:sass_options) { should == options.merge(:filename => name, :syntax => :scss, :importer => sprite_map) } - - - it "should have a correct mtime" do - sprite_map.mtime(uri, subject.sass_options).should == mtime - end - - it "should have a test for the sass engine" do - pending 'sass' - end - end -end diff --git a/spec/compass/sass_extensions/sprites/sprites_spec.rb b/spec/compass/sass_extensions/sprites/sprites_spec.rb deleted file mode 100644 index 9246d8d3..00000000 --- a/spec/compass/sass_extensions/sprites/sprites_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'spec_helper' -require 'fakefs/spec_helpers' - -describe Compass::Sprites do -end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb deleted file mode 100644 index 9fee20ea..00000000 --- a/spec/spec_helper.rb +++ /dev/null @@ -1,37 +0,0 @@ -$LOAD_PATH.unshift(File.dirname(__FILE__)) -$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) -require 'rubygems' -require 'compass' -require 'rspec' -require 'rspec/autorun' -require 'mocha' - -module CompassGlobalInclude - class << self - def included(klass) - klass.instance_eval do - let(:images_src_path) { File.join(File.dirname(__FILE__), 'test_project', 'public', 'images') } - end - end - end -end - -module CompassSpriteHelpers - def create_sprite_temp - ::FileUtils.cp_r @images_src_path, @images_tmp_path - end - - def clean_up_sprites - ::FileUtils.rm_r @images_tmp_path - end -end - -RSpec.configure do |config| - config.include(CompassGlobalInclude) - config.include(CompassSpriteHelpers) - config.before :each do - @images_src_path = File.join(File.dirname(__FILE__), 'test_project', 'public', 'images') - @images_tmp_path = File.join(File.dirname(__FILE__), 'test_project', 'public', 'images-tmp') - end - config.mock_with :mocha -end \ No newline at end of file diff --git a/spec/sprites_spec.rb b/spec/sprites_spec.rb deleted file mode 100644 index 2b39c8a3..00000000 --- a/spec/sprites_spec.rb +++ /dev/null @@ -1,571 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/spec_helper') -require 'digest/md5' - -describe Compass::Sprites do - - before :each do - create_sprite_temp - file = StringIO.new("images_path = #{@images_tmp_path.inspect}\n") - Compass.add_configuration(file, "sprite_config") - Compass.configure_sass_plugin! - end - - after :each do - clean_up_sprites - end - - def map_location(file) - Dir.glob(File.join(@images_tmp_path, file)).first - end - - def image_size(file) - IO.read(map_location(file))[0x10..0x18].unpack('NN') - end - - def image_md5(file) - md5 = Digest::MD5.new - md5.update IO.read(map_location(file)) - md5.hexdigest - end - - def render(scss) - scss = %Q(@import "compass"; #{scss}) - options = Compass.sass_engine_options - options[:line_comments] = false - options[:style] = :expanded - options[:syntax] = :scss - css = Sass::Engine.new(scss, options).render - # reformat to fit result of heredoc: - " #{css.gsub('@charset "UTF-8";', '').gsub(/\n/, "\n ").strip}\n" - end - - #Callbacks - describe 'callbacks' do - it "should fire on_sprite_saved" do - saved = false - path = nil - Compass.configuration.on_sprite_saved {|filepath| path = filepath; saved = true } - render <<-SCSS - @import "squares/*.png"; - @include all-squares-sprites; - SCSS - saved.should eq true - path.should be_kind_of String - end - it "should fire on_sprite_generated" do - saved = false - sprite_data = nil - Compass.configuration.on_sprite_generated {|data| sprite_data = data; saved = true } - render <<-SCSS - @import "squares/*.png"; - @include all-squares-sprites; - SCSS - sprite_data.should be_kind_of ChunkyPNG::Image - saved.should eq true - end - end - - # DEFAULT USAGE: - it "should generate sprite classes" do - css = render <<-SCSS - @import "squares/*.png"; - @include all-squares-sprites; - SCSS - css.should == <<-CSS - .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { - background: url('/squares-161c60ad78.png') no-repeat; - } - - .squares-ten-by-ten { - background-position: 0 0; - } - - .squares-twenty-by-twenty { - background-position: 0 -10px; - } - CSS - image_size('squares-*.png').should == [20, 30] - image_md5('squares-*.png').should == 'fcc93d7b279c2ad6898fbca49cbd01e1' - end - - it "should generate sprite classes with dimensions" do - css = render <<-SCSS - $squares-sprite-dimensions: true; - @import "squares/*.png"; - @include all-squares-sprites; - SCSS - css.should == <<-CSS - .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { - background: url('/squares-161c60ad78.png') no-repeat; - } - - .squares-ten-by-ten { - background-position: 0 0; - height: 10px; - width: 10px; - } - - .squares-twenty-by-twenty { - background-position: 0 -10px; - height: 20px; - width: 20px; - } - CSS - image_size('squares-*.png').should == [20, 30] - end - - it "should provide sprite mixin" do - css = render <<-SCSS - @import "squares/*.png"; - - .cubicle { - @include squares-sprite("ten-by-ten"); - } - - .large-cube { - @include squares-sprite("twenty-by-twenty", true); - } - SCSS - css.should == <<-CSS - .squares-sprite, .cubicle, .large-cube { - background: url('/squares-161c60ad78.png') no-repeat; - } - - .cubicle { - background-position: 0 0; - } - - .large-cube { - background-position: 0 -10px; - height: 20px; - width: 20px; - } - CSS - image_size('squares-*.png').should == [20, 30] - end - - # CUSTOMIZATIONS: - - it "should be possible to change the base class" do - css = render <<-SCSS - $squares-sprite-base-class: ".circles"; - @import "squares/*.png"; - SCSS - css.should == <<-CSS - .circles { - background: url('/squares-161c60ad78.png') no-repeat; - } - CSS - image_size('squares-*.png').should == [20, 30] - end - - it "should calculate the spacing between images but not before first image" do - css = render <<-SCSS - $squares-ten-by-ten-spacing: 33px; - @import "squares/*.png"; - @include all-squares-sprites; - SCSS - css.should == <<-CSS - .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { - background: url('/squares-89450808af.png') no-repeat; - } - - .squares-ten-by-ten { - background-position: 0 0; - } - - .squares-twenty-by-twenty { - background-position: 0 -43px; - } - CSS - image_size('squares-*.png').should == [20, 63] - end - - it "should calculate the spacing between images" do - css = render <<-SCSS - $squares-twenty-by-twenty-spacing: 33px; - @import "squares/*.png"; - @include all-squares-sprites; - SCSS - css.should == <<-CSS - .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { - background: url('/squares-673837183a.png') no-repeat; - } - - .squares-ten-by-ten { - background-position: 0 0; - } - - .squares-twenty-by-twenty { - background-position: 0 -43px; - } - CSS - image_size('squares-*.png').should == [20, 63] - end - - it "should calculate the maximum spacing between images" do - css = render <<-SCSS - $squares-ten-by-ten-spacing: 44px; - $squares-twenty-by-twenty-spacing: 33px; - @import "squares/*.png"; - @include all-squares-sprites; - SCSS - css.should == <<-CSS - .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { - background: url('/squares-1cd84c9068.png') no-repeat; - } - - .squares-ten-by-ten { - background-position: 0 0; - } - - .squares-twenty-by-twenty { - background-position: 0 -54px; - } - CSS - image_size('squares-*.png').should == [20, 74] - end - - it "should calculate the maximum spacing between images in reversed order" do - css = render <<-SCSS - $squares-ten-by-ten-spacing: 33px; - $squares-twenty-by-twenty-spacing: 44px; - @import "squares/*.png"; - @include all-squares-sprites; - SCSS - css.should == <<-CSS - .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { - background: url('/squares-f25b7090ca.png') no-repeat; - } - - .squares-ten-by-ten { - background-position: 0 0; - } - - .squares-twenty-by-twenty { - background-position: 0 -54px; - } - CSS - image_size('squares-*.png').should == [20, 74] - end - - it "should calculate the default spacing between images" do - css = render <<-SCSS - $squares-spacing: 22px; - @import "squares/*.png"; - @include all-squares-sprites; - SCSS - css.should == <<-CSS - .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { - background: url('/squares-d66bf24bab.png') no-repeat; - } - - .squares-ten-by-ten { - background-position: 0 0; - } - - .squares-twenty-by-twenty { - background-position: 0 -32px; - } - CSS - image_size('squares-*.png').should == [20, 52] - end - - it "should use position adjustments in functions" do - css = render <<-SCSS - $squares: sprite-map("squares/*.png", $position: 100%); - .squares-sprite { - background: $squares no-repeat; - } - - .adjusted-percentage { - background-position: sprite-position($squares, ten-by-ten, 100%); - } - - .adjusted-px-1 { - background-position: sprite-position($squares, ten-by-ten, 4px); - } - - .adjusted-px-2 { - background-position: sprite-position($squares, twenty-by-twenty, -3px, 2px); - } - SCSS - css.should == <<-CSS - .squares-sprite { - background: url('/squares-8e490168dd.png') no-repeat; - } - - .adjusted-percentage { - background-position: 100% 0; - } - - .adjusted-px-1 { - background-position: -6px 0; - } - - .adjusted-px-2 { - background-position: -3px -8px; - } - CSS - image_size('squares-*.png').should == [20, 30] - image_md5('squares-*.png').should == '652b67f5e9092520d6f26caae7e18012' - end - - it "should use position adjustments in mixins" do - css = render <<-SCSS - $squares-position: 100%; - @import "squares/*.png"; - - .adjusted-percentage { - @include squares-sprite("ten-by-ten", $offset-x: 100%); - } - - .adjusted-px-1 { - @include squares-sprite("ten-by-ten", $offset-x: 4px); - } - - .adjusted-px-2 { - @include squares-sprite("twenty-by-twenty", $offset-x: -3px, $offset-y: 2px); - } - SCSS - css.should == <<-CSS - .squares-sprite, .adjusted-percentage, .adjusted-px-1, .adjusted-px-2 { - background: url('/squares-8e490168dd.png') no-repeat; - } - - .adjusted-percentage { - background-position: 100% 0; - } - - .adjusted-px-1 { - background-position: -6px 0; - } - - .adjusted-px-2 { - background-position: -3px -8px; - } - CSS - image_size('squares-*.png').should == [20, 30] - image_md5('squares-*.png').should == '652b67f5e9092520d6f26caae7e18012' - end - - it "should repeat the image" do - css = render <<-SCSS - $squares-repeat: repeat; - @import "squares/*.png"; - @include all-squares-sprites; - SCSS - css.should == <<-CSS - .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { - background: url('/squares-a5550fd132.png') no-repeat; - } - - .squares-ten-by-ten { - background-position: 0 0; - } - - .squares-twenty-by-twenty { - background-position: 0 -10px; - } - CSS - image_size('squares-*.png').should == [20, 30] - image_md5('squares-*.png').should == '94abae8440f1b58617f52920b70aaed2' - end - - it "should allow the position of a sprite to be specified in absolute pixels" do - css = render <<-SCSS - $squares-ten-by-ten-position: 10px; - $squares-twenty-by-twenty-position: 10px; - @import "squares/*.png"; - @include all-squares-sprites; - SCSS - css.should == <<-CSS - .squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty { - background: url('/squares-89a274044e.png') no-repeat; - } - - .squares-ten-by-ten { - background-position: -10px 0; - } - - .squares-twenty-by-twenty { - background-position: -10px -10px; - } - CSS - image_size('squares-*.png').should == [30, 30] - image_md5('squares-*.png').should == '2fb19ef9c83018c93c6f147af3a56cb2' - end - - it "should provide a nice errors for lemonade's old users" do - proc do - render <<-SCSS - .squares { - background: sprite-url("squares/*.png") no-repeat; - } - SCSS - end.should raise_error Sass::SyntaxError, - %q(The first argument to sprite-url() must be a sprite map. See http://beta.compass-style.org/help/tutorials/spriting/ for more information.) - proc do - render <<-SCSS - .squares { - background: sprite-image("squares/twenty-by-twenty.png") no-repeat; - } - SCSS - end.should raise_error Sass::SyntaxError, - %q(The sprite-image() function has been replaced by sprite(). See http://beta.compass-style.org/help/tutorials/spriting/ for more information.) - proc do - render <<-SCSS - @import "squares/*.png"; - - .squares { - background: sprite-position("squares/twenty-by-twenty.png") no-repeat; - } - SCSS - end.should raise_error Sass::SyntaxError, - %q(The first argument to sprite-position() must be a sprite map. See http://beta.compass-style.org/help/tutorials/spriting/ for more information.) - end - - it "should work even if @import is missing" do - actual_css = render <<-SCSS - .squares { - background: sprite(sprite-map("squares/*.png"), twenty-by-twenty) no-repeat; - } - SCSS - actual_css.should == <<-CSS - .squares { - background: url('/squares-145869726f.png') 0 -10px no-repeat; - } - CSS - end - - it "should calculate corret sprite demsions when givin spacing via issue#253" do - css = render <<-SCSS - $squares-spacing: 10px; - @import "squares/*.png"; - .foo { - @include sprite-background-position($squares-sprites, "twenty-by-twenty"); - } - .bar { - @include sprite-background-position($squares-sprites, "ten-by-ten"); - } - SCSS - image_size('squares-*.png').should == [20, 40] - css.should == <<-CSS - .squares-sprite { - background: url('/squares-e3c68372d9.png') no-repeat; - } - - .foo { - background-position: 0 -20px; - } - - .bar { - background-position: 0 0; - } - CSS - end - - it "should render corret sprite with css selectors via issue#248" do - css = render <<-SCSS - @import "selectors/*.png"; - @include all-selectors-sprites; - SCSS - css.should == <<-CSS - .selectors-sprite, .selectors-ten-by-ten { - background: url('/selectors-edfef809e2.png') no-repeat; - } - - .selectors-ten-by-ten { - background-position: 0 0; - } - .selectors-ten-by-ten:hover, .selectors-ten-by-ten.ten-by-ten_hover, .selectors-ten-by-ten.ten-by-ten-hover { - background-position: 0 -20px; - } - .selectors-ten-by-ten:target, .selectors-ten-by-ten.ten-by-ten_target, .selectors-ten-by-ten.ten-by-ten-target { - background-position: 0 -30px; - } - .selectors-ten-by-ten:active, .selectors-ten-by-ten.ten-by-ten_active, .selectors-ten-by-ten.ten-by-ten-active { - background-position: 0 -10px; - } - CSS - end - - it "should render corret sprite with css selectors via magic mixin" do - css = render <<-SCSS - @import "selectors/*.png"; - a { - @include selectors-sprite(ten-by-ten) - } - SCSS - css.should == <<-CSS - .selectors-sprite, a { - background: url('/selectors-edfef809e2.png') no-repeat; - } - - a { - background-position: 0 0; - } - a:hover, a.ten-by-ten_hover, a.ten-by-ten-hover { - background-position: 0 -20px; - } - a:target, a.ten-by-ten_target, a.ten-by-ten-target { - background-position: 0 -30px; - } - a:active, a.ten-by-ten_active, a.ten-by-ten-active { - background-position: 0 -10px; - } - CSS - end - - it "should not render corret sprite with css selectors via magic mixin" do - css = render <<-SCSS - @import "selectors/*.png"; - a { - $disable-magic-sprite-selectors:true; - @include selectors-sprite(ten-by-ten) - } - SCSS - css.should == <<-CSS - .selectors-sprite, a { - background: url('/selectors-edfef809e2.png') no-repeat; - } - - a { - background-position: 0 0; - } - CSS - end - - it "should raise error on filenames that are not valid sass syntax" do - lambda do - render <<-SCSS - @import "prefix/*.png"; - a { - @include squares-sprite(20-by-20); - } - SCSS - end.should raise_error Compass::Error - end - - it "should generate sprite with bad repeat-x dimensions" do - css = render <<-SCSS - $ko-starbg26x27-repeat: repeat-x; - @import "ko/*.png"; - @include all-ko-sprites; - SCSS - css.should == <<-CSS - .ko-sprite, .ko-default_background, .ko-starbg26x27 { - background: url('/ko-cc3f80660d.png') no-repeat; - } - - .ko-default_background { - background-position: 0 0; - } - - .ko-starbg26x27 { - background-position: 0 -128px; - } - CSS - end - -end diff --git a/spec/test_project/public/images/ko/default_background.png b/spec/test_project/public/images/ko/default_background.png deleted file mode 100644 index b98cd7f9..00000000 Binary files a/spec/test_project/public/images/ko/default_background.png and /dev/null differ diff --git a/spec/test_project/public/images/ko/starbg26x27.png b/spec/test_project/public/images/ko/starbg26x27.png deleted file mode 100755 index 48dee0db..00000000 Binary files a/spec/test_project/public/images/ko/starbg26x27.png and /dev/null differ diff --git a/spec/test_project/public/images/prefix/20-by-20.png b/spec/test_project/public/images/prefix/20-by-20.png deleted file mode 100644 index 4e5e297f..00000000 Binary files a/spec/test_project/public/images/prefix/20-by-20.png and /dev/null differ diff --git a/spec/test_project/public/images/prefix/ten-by-ten.png b/spec/test_project/public/images/prefix/ten-by-ten.png deleted file mode 100644 index c0ae53cc..00000000 Binary files a/spec/test_project/public/images/prefix/ten-by-ten.png and /dev/null differ diff --git a/spec/test_project/public/images/selectors/ten-by-ten.png b/spec/test_project/public/images/selectors/ten-by-ten.png deleted file mode 100644 index c0ae53cc..00000000 Binary files a/spec/test_project/public/images/selectors/ten-by-ten.png and /dev/null differ diff --git a/spec/test_project/public/images/selectors/ten-by-ten_active.png b/spec/test_project/public/images/selectors/ten-by-ten_active.png deleted file mode 100644 index c0ae53cc..00000000 Binary files a/spec/test_project/public/images/selectors/ten-by-ten_active.png and /dev/null differ diff --git a/spec/test_project/public/images/selectors/ten-by-ten_hover.png b/spec/test_project/public/images/selectors/ten-by-ten_hover.png deleted file mode 100644 index c0ae53cc..00000000 Binary files a/spec/test_project/public/images/selectors/ten-by-ten_hover.png and /dev/null differ diff --git a/spec/test_project/public/images/selectors/ten-by-ten_target.png b/spec/test_project/public/images/selectors/ten-by-ten_target.png deleted file mode 100644 index c0ae53cc..00000000 Binary files a/spec/test_project/public/images/selectors/ten-by-ten_target.png and /dev/null differ diff --git a/spec/test_project/public/images/squares/ten-by-ten.png b/spec/test_project/public/images/squares/ten-by-ten.png deleted file mode 100644 index c0ae53cc..00000000 Binary files a/spec/test_project/public/images/squares/ten-by-ten.png and /dev/null differ diff --git a/spec/test_project/public/images/squares/twenty-by-twenty.png b/spec/test_project/public/images/squares/twenty-by-twenty.png deleted file mode 100644 index 4e5e297f..00000000 Binary files a/spec/test_project/public/images/squares/twenty-by-twenty.png and /dev/null differ diff --git a/test/fixtures/stylesheets/busted_image_urls/config.rb b/test/fixtures/stylesheets/busted_image_urls/config.rb new file mode 100644 index 00000000..13821b8e --- /dev/null +++ b/test/fixtures/stylesheets/busted_image_urls/config.rb @@ -0,0 +1,29 @@ +# Require any additional compass plugins here. +project_type = :stand_alone +css_dir = "tmp" +sass_dir = "sass" +images_dir = "images" +output_style = :compact +# To enable relative image paths using the images_url() function: +# http_images_path = :relative +http_images_path = "/images" +line_comments = false + +asset_cache_buster do |path, file| + pathname = Pathname.new(path) + + case pathname.basename(pathname.extname).to_s + when "grid" + new_path = "%s/%s-BUSTED%s" % [pathname.dirname, pathname.basename(pathname.extname), pathname.extname] + {:path => new_path, :query => nil} + when "feed" + "query_string" + when "dk" + {:query => "query_string"} + end +end + + +asset_host do |path| + "http://assets%d.example.com" % (path.size % 4) +end diff --git a/test/fixtures/stylesheets/busted_image_urls/css/screen.css b/test/fixtures/stylesheets/busted_image_urls/css/screen.css new file mode 100644 index 00000000..ab36dbc7 --- /dev/null +++ b/test/fixtures/stylesheets/busted_image_urls/css/screen.css @@ -0,0 +1,9 @@ +.showgrid { background-image: url('http://assets0.example.com/images/grid-BUSTED.png'); } + +.inlinegrid { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAUEAYAAACv1qP4AAAABmJLR0T///////8JWPfcAAAACXBIWXMAAABIAAAASABGyWs+AAAAZ0lEQVRYw+3QwQ2AIBAFUTEUwI3+uzN7gDscsIgxEuO8An52J11X73OudfxMraXkzHfO3Y98nQEhA0IGhAwIGRAyIGRAyICQASEDQgaEDAgZEDIgZEDIgJABoZzSGK3tPuN9ERFP7Nw4fg+c5g8V1wAAAABJRU5ErkJggg=='); } + +.no-buster { background-image: url('http://assets0.example.com/images/grid.png'); } + +.feed { background-image: url('http://assets0.example.com/images/feed.png?query_string'); } + +.dk { background-image: url('http://assets0.example.com/images/flags/dk.png?query_string'); } diff --git a/test/fixtures/stylesheets/busted_image_urls/images/feed.png b/test/fixtures/stylesheets/busted_image_urls/images/feed.png new file mode 100644 index 00000000..315c4f4f Binary files /dev/null and b/test/fixtures/stylesheets/busted_image_urls/images/feed.png differ diff --git a/test/fixtures/stylesheets/busted_image_urls/images/flags/dk.png b/test/fixtures/stylesheets/busted_image_urls/images/flags/dk.png new file mode 100644 index 00000000..5f660619 Binary files /dev/null and b/test/fixtures/stylesheets/busted_image_urls/images/flags/dk.png differ diff --git a/test/fixtures/stylesheets/busted_image_urls/images/grid.png b/test/fixtures/stylesheets/busted_image_urls/images/grid.png new file mode 100644 index 00000000..76aaa851 Binary files /dev/null and b/test/fixtures/stylesheets/busted_image_urls/images/grid.png differ diff --git a/test/fixtures/stylesheets/busted_image_urls/sass/screen.sass b/test/fixtures/stylesheets/busted_image_urls/sass/screen.sass new file mode 100644 index 00000000..b469b120 --- /dev/null +++ b/test/fixtures/stylesheets/busted_image_urls/sass/screen.sass @@ -0,0 +1,14 @@ +.showgrid + background-image: image-url("grid.png") + +.inlinegrid + background-image: inline-image("grid.png") + +.no-buster + background-image: image-url("grid.png", $only-path: false, $cache-buster: false) + +.feed + background-image: image-url("feed.png") + +.dk + background-image: image-url("flags/dk.png") \ No newline at end of file diff --git a/test/fixtures/stylesheets/compass/css/legacy_clearfix.css b/test/fixtures/stylesheets/compass/css/legacy_clearfix.css index 2a287628..54086726 100644 --- a/test/fixtures/stylesheets/compass/css/legacy_clearfix.css +++ b/test/fixtures/stylesheets/compass/css/legacy_clearfix.css @@ -15,3 +15,12 @@ visibility: hidden; } .pie-clearfix { display: block; } + +.simplified-pie-clearfix { + display: inline-block; } + .simplified-pie-clearfix:after { + content: ""; + display: table; + clear: both; } + .simplified-pie-clearfix { + display: block; } diff --git a/test/fixtures/stylesheets/compass/css/utilities.css b/test/fixtures/stylesheets/compass/css/utilities.css index 354c84dc..8a6c64b1 100644 --- a/test/fixtures/stylesheets/compass/css/utilities.css +++ b/test/fixtures/stylesheets/compass/css/utilities.css @@ -12,6 +12,13 @@ overflow: hidden; visibility: hidden; } +.simple-pie-clearfix { + *zoom: 1; } + .simple-pie-clearfix:after { + content: ""; + display: table; + clear: both; } + p.light { background-color: #b0201e; color: black; } diff --git a/test/fixtures/stylesheets/compass/sass/legacy_clearfix.scss b/test/fixtures/stylesheets/compass/sass/legacy_clearfix.scss index 5a9f6396..906e49b1 100644 --- a/test/fixtures/stylesheets/compass/sass/legacy_clearfix.scss +++ b/test/fixtures/stylesheets/compass/sass/legacy_clearfix.scss @@ -7,5 +7,8 @@ $default-has-layout-approach: block; } .pie-clearfix { + @include legacy-pie-clearfix; +} +.simplified-pie-clearfix { @include pie-clearfix; } diff --git a/test/fixtures/stylesheets/compass/sass/utilities.scss b/test/fixtures/stylesheets/compass/sass/utilities.scss index 7daac2f6..d579a6ca 100644 --- a/test/fixtures/stylesheets/compass/sass/utilities.scss +++ b/test/fixtures/stylesheets/compass/sass/utilities.scss @@ -5,7 +5,10 @@ } .pie-clearfix { - @include pie-clearfix; + @include legacy-pie-clearfix; +} +.simple-pie-clearfix { + @include pie-clearfix; } p.light { @include contrasted(#B0201E); } diff --git a/test/integrations/compass_test.rb b/test/integrations/compass_test.rb index c8f4f5f8..b505debb 100644 --- a/test/integrations/compass_test.rb +++ b/test/integrations/compass_test.rb @@ -73,6 +73,17 @@ class CompassTest < Test::Unit::TestCase end end + def test_busted_image_urls + within_project('busted_image_urls') do |proj| + each_css_file(proj.css_path) do |css_file| + assert_no_errors css_file, 'busted_image_urls' + end + each_sass_file do |sass_file| + assert_renders_correctly sass_file + end + end + end + def test_image_urls within_project('image_urls') do |proj| each_css_file(proj.css_path) do |css_file| diff --git a/test/integrations/sprites_test.rb b/test/integrations/sprites_test.rb index 126ad8c3..723dac7d 100644 --- a/test/integrations/sprites_test.rb +++ b/test/integrations/sprites_test.rb @@ -71,7 +71,7 @@ class SpritesTest < Test::Unit::TestCase } CSS assert_equal image_size('squares-s*.png'), [20, 30] - assert_equal image_md5('squares-s*.png'), 'fcc93d7b279c2ad6898fbca49cbd01e1' + assert_equal image_md5('squares-s*.png'), '7349a0f4e88ea80abddcf6ac2486abe3' end it "should generate sprite classes with dimensions" do @@ -294,7 +294,7 @@ class SpritesTest < Test::Unit::TestCase } CSS assert_equal image_size('squares-s*.png'), [20, 30] - assert_equal image_md5('squares-s*.png'), '652b67f5e9092520d6f26caae7e18012' + assert_equal image_md5('squares-s*.png'), '9cc7ce48cfaf304381c2d08adefd2fb6' end it "should use position adjustments in mixins" do @@ -332,7 +332,7 @@ class SpritesTest < Test::Unit::TestCase } CSS assert_equal image_size('squares-s*.png'), [20, 30] - assert_equal image_md5('squares-s*.png'), '652b67f5e9092520d6f26caae7e18012' + assert_equal image_md5('squares-s*.png'), '9cc7ce48cfaf304381c2d08adefd2fb6' end it "should repeat the image" do @@ -355,7 +355,7 @@ class SpritesTest < Test::Unit::TestCase } CSS assert_equal image_size('squares-s*.png'), [20, 30] - assert_equal image_md5('squares-s*.png'), '94abae8440f1b58617f52920b70aaed2' + assert_equal image_md5('squares-s*.png'), 'a77a2fd43f04d791722b706aa7c9f1c1' end it "should allow the position of a sprite to be specified in absolute pixels" do @@ -379,7 +379,7 @@ class SpritesTest < Test::Unit::TestCase } CSS assert_equal image_size('squares-s*.png'), [30, 30] - assert_equal image_md5('squares-s*.png'), '2fb19ef9c83018c93c6f147af3a56cb2' + assert_equal image_md5('squares-s*.png'), '9856ced9e8211b6b28ff782019a0d905' end it "should provide a nice errors for lemonade's old users" do diff --git a/test/units/sprites/engine_test.rb b/test/units/sprites/engine_test.rb new file mode 100644 index 00000000..a172c518 --- /dev/null +++ b/test/units/sprites/engine_test.rb @@ -0,0 +1,43 @@ +require 'test_helper' + +class EngineTest < Test::Unit::TestCase + + def setup + sprite_filename = 'squares/ten-by-ten.png' + @images = [ + Compass::SassExtensions::Sprites::Image.new(nil, File.join(sprite_filename), {}) + ] + @engine = Compass::SassExtensions::Sprites::Engine.new(100, 100, @images) + end + + + test "should have width of 100" do + assert_equal 100, @engine.width + end + + test "should have height of 100" do + assert_equal 100, @engine.height + end + + test "should have correct images" do + assert_equal @images, @engine.images + end + + test "raises Compass::Error when calling save" do + begin + @engine.save('foo') + assert false, '#save did not raise an exception' + rescue Compass::Error + assert true + end + end + + test "raises Compass::Error when calling construct_sprite" do + begin + @engine.construct_sprite + assert false, '#construct_sprite did not raise an exception' + rescue Compass::Error + assert true + end + end +end \ No newline at end of file diff --git a/test/units/sprites/importer_test.rb b/test/units/sprites/importer_test.rb index d25bff1e..79fdc800 100644 --- a/test/units/sprites/importer_test.rb +++ b/test/units/sprites/importer_test.rb @@ -9,6 +9,10 @@ class ImporterTest < Test::Unit::TestCase Compass.add_configuration(file, "sprite_config") @importer = Compass::SpriteImporter.new(:uri => URI, :options => options) end + + def teardown + Compass.reset_configuration! + end def options {:foo => 'bar'} @@ -46,21 +50,17 @@ class ImporterTest < Test::Unit::TestCase assert_equal 'bar', @importer.sass_options[:foo] end - test "should fail givin bad sprite extensions" do + test "should fail given bad sprite extensions" do @images_src_path = File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'sprites', 'public', 'images') file = StringIO.new("images_path = #{@images_src_path.inspect}\n") Compass.add_configuration(file, "sprite_config") importer = Compass::SpriteImporter.new(:uri => 'bad_extensions/*.jpg', :options => options) begin importer.sass_engine - assert false, "Somthing happened an invalid sprite file made it past validation" + assert false, "An invalid sprite file made it past validation." rescue Compass::Error => e assert e.message.include?('.png') end end - def taredown - Compass.reset_configuration! - end - end \ No newline at end of file diff --git a/spec/compass/commands/sprite_spec.rb b/test/units/sprites/sprite_command_test.rb similarity index 54% rename from spec/compass/commands/sprite_spec.rb rename to test/units/sprites/sprite_command_test.rb index 6980dcc5..240b00c3 100644 --- a/spec/compass/commands/sprite_spec.rb +++ b/test/units/sprites/sprite_command_test.rb @@ -1,32 +1,11 @@ -require 'spec_helper' -require 'compass/commands' -require 'compass/exec' -require 'compass/commands/sprite' -describe Compass::Commands::Sprite do - def config_data - return <<-CONFIG - images_path = #{@images_tmp_path.inspect} - CONFIG - end +require 'test_helper' + +class SpriteCommandTest < Test::Unit::TestCase + attr_reader :test_dir - def create_temp_cli_dir - directory = File.join(File.expand_path('../', __FILE__), 'test') - ::FileUtils.mkdir_p directory - @test_dir = directory - end - - def run_compass_with_options(options) - output = 'foo' - ::Dir.chdir @test_dir - %x{compass #{options.join(' ')}} - end - - def options_to_cli(options) - options.map.flatten! - end - - let(:test_dir) { @test_dir } - before :each do + def setup + @images_src_path = File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'sprites', 'public', 'images') + @images_tmp_path = File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'sprites', 'public', 'images-tmp') @before_dir = ::Dir.pwd create_temp_cli_dir create_sprite_temp @@ -34,22 +13,48 @@ describe Compass::Commands::Sprite do f << config_data end end - after :each do + + def create_sprite_temp + ::FileUtils.cp_r @images_src_path, @images_tmp_path + end + + def clean_up_sprites + ::FileUtils.rm_r @images_tmp_path + end + + def config_data + return <<-CONFIG + images_path = #{@images_tmp_path.inspect} + CONFIG + end + + def create_temp_cli_dir + directory = File.join(File.expand_path('../', __FILE__), 'test') + ::FileUtils.mkdir_p directory + @test_dir = directory + end + + def run_compass_with_options(options) + output = 'foo' + ::Dir.chdir @test_dir + %x{compass #{options.join(' ')}} + end + + def options_to_cli(options) + options.map.flatten! + end + + def teardown ::Dir.chdir @before_dir clean_up_sprites if File.exists?(@test_dir) ::FileUtils.rm_r @test_dir end end - + it "should create sprite file" do - run_compass_with_options(['sprite', "-f", "stylesheet.scss", "'#{@images_tmp_path}/*.png'"]).to_i.should == 0 - File.exists?(File.join(test_dir, 'stylesheet.scss')).should be_true + assert_equal 0, run_compass_with_options(['sprite', "-f", 'stylesheet.scss', "'#{@images_tmp_path}/*.png'"]).to_i + assert File.exists?(File.join(test_dir, 'stylesheet.scss')) end - - it "should fail gracfuly when giving bad arguments" do - pending - end - - + end \ No newline at end of file