merged version.yml
@ -4,4 +4,4 @@ rvm:
|
|||||||
- jruby
|
- jruby
|
||||||
- rbx
|
- rbx
|
||||||
- ree
|
- ree
|
||||||
script: "bundle exec rake test"
|
script: "bundle exec rake test features"
|
||||||
|
2
Gemfile
@ -5,7 +5,7 @@ gemspec
|
|||||||
gem "cucumber", "~> 0.9.2"
|
gem "cucumber", "~> 0.9.2"
|
||||||
gem "rspec", "~>2.0.0"
|
gem "rspec", "~>2.0.0"
|
||||||
gem "rails", "~>3.0.0.rc"
|
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 "css_parser", "~> 1.0.1"
|
||||||
gem "sass", "~>3.1"
|
gem "sass", "~>3.1"
|
||||||
gem "haml", "~> 3.1"
|
gem "haml", "~> 3.1"
|
||||||
|
@ -7,8 +7,8 @@ GIT
|
|||||||
PATH
|
PATH
|
||||||
remote: .
|
remote: .
|
||||||
specs:
|
specs:
|
||||||
compass (0.11.1.f248c22)
|
compass (0.11.3.b352e8b)
|
||||||
chunky_png (~> 1.1)
|
chunky_png (~> 1.2)
|
||||||
fssm (>= 0.2.7)
|
fssm (>= 0.2.7)
|
||||||
sass (~> 3.1)
|
sass (~> 3.1)
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ GEM
|
|||||||
sys-uname
|
sys-uname
|
||||||
builder (2.1.2)
|
builder (2.1.2)
|
||||||
chunky_png (1.2.0)
|
chunky_png (1.2.0)
|
||||||
compass-validator (3.0.0)
|
compass-validator (3.0.1)
|
||||||
css_parser (1.0.1)
|
css_parser (1.0.1)
|
||||||
cucumber (0.9.4)
|
cucumber (0.9.4)
|
||||||
builder (~> 2.1.2)
|
builder (~> 2.1.2)
|
||||||
@ -136,7 +136,7 @@ DEPENDENCIES
|
|||||||
autotest
|
autotest
|
||||||
autotest-fsevent
|
autotest-fsevent
|
||||||
compass!
|
compass!
|
||||||
compass-validator (= 3.0.0)
|
compass-validator (= 3.0.1)
|
||||||
css_parser (~> 1.0.1)
|
css_parser (~> 1.0.1)
|
||||||
cucumber (~> 0.9.2)
|
cucumber (~> 0.9.2)
|
||||||
diff-lcs (~> 1.1.2)
|
diff-lcs (~> 1.1.2)
|
||||||
|
@ -16,7 +16,7 @@ Gem::Specification.new do |gemspec|
|
|||||||
gemspec.summary = %q{A Real Stylesheet Framework}
|
gemspec.summary = %q{A Real Stylesheet Framework}
|
||||||
|
|
||||||
gemspec.add_dependency 'sass', '~> 3.1'
|
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.add_dependency 'fssm', '>= 0.2.7'
|
||||||
|
|
||||||
gemspec.files = %w(README.markdown LICENSE.markdown VERSION.yml Rakefile)
|
gemspec.files = %w(README.markdown LICENSE.markdown VERSION.yml Rakefile)
|
||||||
|
@ -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/)
|
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 #<Compass::SpriteMap>` when adding or removing sprite files
|
||||||
|
|
||||||
0.11.2 (06/10/2011)
|
0.11.2 (06/10/2011)
|
||||||
-------------------
|
-------------------
|
||||||
* Sprites will now by default remove any old versions of the sprite. A new configuration
|
* Sprites will now by default remove any old versions of the sprite. A new configuration
|
||||||
|
@ -307,10 +307,14 @@ the asset host configuration is ignored.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<a name="asset-cache-buster"></a>
|
||||||
**`asset_cache_buster`** – Pass this function a block of code that defines the
|
**`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
|
cache buster strategy to be used. The block must return nil, a string or a hash.
|
||||||
be appended to a url as a query parameter. The returned string must not include
|
If the returned value is a hash the values of :path and/or :query is used to generate
|
||||||
the starting `?`. The block will be passed the root-relative url of the asset.
|
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
|
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.
|
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
|
||||||
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:
|
To disable the asset cache buster:
|
||||||
|
|
||||||
asset_cache_buster :none
|
asset_cache_buster :none
|
||||||
|
@ -14,11 +14,9 @@ The sprite engine is the work horse of sprite generation it's the interface for
|
|||||||
|
|
||||||
### Requirements
|
### 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)
|
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)
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
### Configuration
|
### Configuration
|
||||||
|
|
||||||
@ -26,7 +24,7 @@ To enable your sprite engine from the config file set
|
|||||||
|
|
||||||
sprite_engine = :<engine name>
|
sprite_engine = :<engine name>
|
||||||
|
|
||||||
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
|
sprite_engine = :chunky_png
|
||||||
|
|
||||||
@ -35,11 +33,14 @@ The example below will load `Compass::SassExtension::Sprites::ChunkyPngEngine`
|
|||||||
module Compass
|
module Compass
|
||||||
module SassExtensions
|
module SassExtensions
|
||||||
module Sprites
|
module Sprites
|
||||||
module <engine name>Engine
|
class ChunkyPngEngine < Compass::SassExtensions::Sprites::Engine
|
||||||
|
|
||||||
# Returns an object
|
|
||||||
def construct_sprite
|
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
|
||||||
|
@ -34,7 +34,7 @@ And you'll get the following CSS output:
|
|||||||
.icon-delete,
|
.icon-delete,
|
||||||
.icon-edit,
|
.icon-edit,
|
||||||
.icon-new,
|
.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-delete { background-position: 0 0; }
|
||||||
.icon-edit { background-position: 0 -32px; }
|
.icon-edit { background-position: 0 -32px; }
|
||||||
@ -74,7 +74,7 @@ And your stylesheet will compile to:
|
|||||||
.actions .new,
|
.actions .new,
|
||||||
.actions .edit,
|
.actions .edit,
|
||||||
.actions .save,
|
.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 .new { background-position: 0 -64px; }
|
||||||
.actions .edit { background-position: 0 -32px; }
|
.actions .edit { background-position: 0 -32px; }
|
||||||
@ -122,7 +122,7 @@ Now in our sass file we add:
|
|||||||
And your stylesheet will compile to:
|
And your stylesheet will compile to:
|
||||||
|
|
||||||
.selectors-sprite, a {
|
.selectors-sprite, a {
|
||||||
background: url('/selectors-edfef809e2.png') no-repeat;
|
background: url('/selectors-sedfef809e2.png') no-repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
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:
|
Alternatively you can use the `@include all-selectors-sprites;` after the import and get the following output:
|
||||||
|
|
||||||
.selectors-sprite, .selectors-ten-by-ten {
|
.selectors-sprite, .selectors-ten-by-ten {
|
||||||
background: url('/selectors-edfef809e2.png') no-repeat;
|
background: url('/selectors-sedfef809e2.png') no-repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
.selectors-ten-by-ten {
|
.selectors-ten-by-ten {
|
||||||
|
@ -145,6 +145,7 @@ Feature: Command Line
|
|||||||
Scenario: Basic help
|
Scenario: Basic help
|
||||||
When I run: compass help
|
When I run: compass help
|
||||||
Then I should see the following "primary" commands:
|
Then I should see the following "primary" commands:
|
||||||
|
| clean |
|
||||||
| compile |
|
| compile |
|
||||||
| create |
|
| create |
|
||||||
| init |
|
| init |
|
||||||
@ -179,6 +180,27 @@ Feature: Command Line
|
|||||||
And I run: compass compile
|
And I run: compass compile
|
||||||
And a css file tmp/layout.css is reported overwritten
|
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
|
Scenario: Watching a project for changes
|
||||||
Given ruby supports fork
|
Given ruby supports fork
|
||||||
Given I am using the existing project in test/fixtures/stylesheets/compass
|
Given I am using the existing project in test/fixtures/stylesheets/compass
|
||||||
@ -218,7 +240,6 @@ Feature: Command Line
|
|||||||
| sass_dir | sass |
|
| sass_dir | sass |
|
||||||
| css_dir | assets/css |
|
| css_dir | assets/css |
|
||||||
|
|
||||||
@now
|
|
||||||
Scenario Outline: Print out a configuration value
|
Scenario Outline: Print out a configuration value
|
||||||
Given I am using the existing project in test/fixtures/stylesheets/compass
|
Given I am using the existing project in test/fixtures/stylesheets/compass
|
||||||
When I run: compass config -p <property>
|
When I run: compass config -p <property>
|
||||||
|
@ -76,7 +76,7 @@ When /^I run in a separate process: compass ([^\s]+) ?(.+)?$/ do |command, args|
|
|||||||
file.puts $stdout.string
|
file.puts $stdout.string
|
||||||
end
|
end
|
||||||
open('/tmp/last_error.compass_test.txt', 'w') do |file|
|
open('/tmp/last_error.compass_test.txt', 'w') do |file|
|
||||||
file.puts @stderr.string
|
file.puts $stderr.string
|
||||||
end
|
end
|
||||||
exit!
|
exit!
|
||||||
end
|
end
|
||||||
@ -116,10 +116,30 @@ Then /^a directory ([^ ]+) is (not )?created$/ do |directory, negated|
|
|||||||
File.directory?(directory).should == !negated
|
File.directory?(directory).should == !negated
|
||||||
end
|
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|
|
Then /an? \w+ file ([^ ]+) is (not )?created/ do |filename, negated|
|
||||||
File.exists?(filename).should == !negated
|
File.exists?(filename).should == !negated
|
||||||
end
|
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|
|
Then /an? \w+ file ([^ ]+) is reported created/ do |filename|
|
||||||
@last_result.should =~ /create.*#{Regexp.escape(filename)}/
|
@last_result.should =~ /create.*#{Regexp.escape(filename)}/
|
||||||
end
|
end
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
// [Easy Clearing](http://www.positioniseverything.net/easyclearing.html)
|
// [Easy Clearing](http://www.positioniseverything.net/easyclearing.html)
|
||||||
// has the advantage of allowing positioned elements to hang
|
// has the advantage of allowing positioned elements to hang
|
||||||
// outside the bounds of the container at the expense of more tricky CSS.
|
// outside the bounds of the container at the expense of more tricky CSS.
|
||||||
@mixin pie-clearfix {
|
@mixin legacy-pie-clearfix {
|
||||||
&:after {
|
&:after {
|
||||||
content : "\0020";
|
content : "\0020";
|
||||||
display : block;
|
display : block;
|
||||||
@ -29,3 +29,16 @@
|
|||||||
}
|
}
|
||||||
@include has-layout;
|
@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;
|
||||||
|
}
|
||||||
|
@ -65,7 +65,10 @@ module Compass
|
|||||||
end
|
end
|
||||||
|
|
||||||
def remove(file_name)
|
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
|
File.unlink file_name
|
||||||
log_action :remove, basename(file_name), options
|
log_action :remove, basename(file_name), options
|
||||||
end
|
end
|
||||||
|
@ -4,7 +4,7 @@ end
|
|||||||
require 'compass/commands/registry'
|
require 'compass/commands/registry'
|
||||||
|
|
||||||
%w(base generate_grid_background default help list_frameworks project_base
|
%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
|
print_version project_stats stamp_pattern sprite validate_project
|
||||||
write_configuration interactive unpack_extension).each do |lib|
|
write_configuration interactive unpack_extension).each do |lib|
|
||||||
require "compass/commands/#{lib}"
|
require "compass/commands/#{lib}"
|
||||||
|
79
lib/compass/commands/clean_project.rb
Normal file
@ -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
|
@ -16,8 +16,10 @@ module Compass::Commands
|
|||||||
matching.first
|
matching.first
|
||||||
elsif name =~ /^-/
|
elsif name =~ /^-/
|
||||||
nil
|
nil
|
||||||
else
|
elsif matching.size > 1
|
||||||
raise Compass::Error, "Ambiguous abbreviation '#{name}'. Did you mean one of: #{matching.join(", ")}"
|
raise Compass::Error, "Ambiguous abbreviation '#{name}'. Did you mean one of: #{matching.join(", ")}"
|
||||||
|
else
|
||||||
|
raise Compass::Error, "Command not found: #{name}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
def abbreviation?(name)
|
def abbreviation?(name)
|
||||||
|
@ -39,7 +39,7 @@ module Compass
|
|||||||
|
|
||||||
def perform
|
def perform
|
||||||
relative_uri = options[:uri].gsub(/^#{Compass.configuration.images_dir}\//, '')
|
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[:output_file] ||= File.join(Compass.configuration.sass_path, "sprites", "_#{sprites.name}.#{Compass.configuration.preferred_syntax}")
|
||||||
options[:skip_overrides] ||= false
|
options[:skip_overrides] ||= false
|
||||||
contents = sprites.content_for_images(options[:skip_overrides])
|
contents = sprites.content_for_images(options[:skip_overrides])
|
||||||
|
@ -51,12 +51,10 @@ module Compass
|
|||||||
|
|
||||||
def new_compiler_instance(additional_options = {})
|
def new_compiler_instance(additional_options = {})
|
||||||
@compiler_opts ||= begin
|
@compiler_opts ||= begin
|
||||||
compiler_opts = Compass.sass_engine_options
|
compiler_opts = {:sass => Compass.sass_engine_options}
|
||||||
compiler_opts.merge!(:force => options[:force],
|
compiler_opts.merge!(options)
|
||||||
:sass_files => explicit_sass_files,
|
compiler_opts[:sass_files] = explicit_sass_files
|
||||||
:dry_run => options[:dry_run])
|
compiler_opts[:cache_location] = determine_cache_location
|
||||||
compiler_opts[:quiet] = options[:quiet] if options[:quiet]
|
|
||||||
compiler_opts[:time] = options[:time] if options[:time]
|
|
||||||
compiler_opts
|
compiler_opts
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -3,16 +3,19 @@ module Compass
|
|||||||
|
|
||||||
include Actions
|
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)
|
def initialize(working_path, from, to, options)
|
||||||
self.working_path = working_path
|
self.working_path = working_path
|
||||||
self.from, self.to = from.gsub('./', ''), to
|
self.from, self.to = from.gsub('./', ''), to
|
||||||
self.logger = options.delete(:logger)
|
self.logger = options.delete(:logger)
|
||||||
|
sass_opts = options.delete(:sass) || {}
|
||||||
self.options = options
|
self.options = options
|
||||||
self.options[:cache_location] ||= determine_cache_location
|
self.sass_options = options.dup
|
||||||
options[:importer] = self.importer = Sass::Importers::Filesystem.new(from)
|
self.sass_options.update(sass_opts)
|
||||||
self.staleness_checker = Sass::Plugin::StalenessChecker.new(options)
|
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
|
end
|
||||||
|
|
||||||
def determine_cache_location
|
def determine_cache_location
|
||||||
@ -72,16 +75,16 @@ module Compass
|
|||||||
end
|
end
|
||||||
|
|
||||||
def clean!
|
def clean!
|
||||||
FileUtils.rm_rf options[:cache_location]
|
remove options[:cache_location]
|
||||||
css_files.each do |css_file|
|
css_files.each do |css_file|
|
||||||
FileUtils.rm_f css_file
|
remove css_file
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
if new_config?
|
if new_config?
|
||||||
# Wipe out the cache and force compilation if the configuration has changed.
|
# 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
|
options[:force] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -142,7 +145,7 @@ module Compass
|
|||||||
# A sass engine for compiling a single file.
|
# A sass engine for compiling a single file.
|
||||||
def engine(sass_filename, css_filename)
|
def engine(sass_filename, css_filename)
|
||||||
syntax = (sass_filename =~ /\.(s[ac]ss)$/) && $1.to_sym || :sass
|
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)
|
Sass::Engine.new(open(sass_filename).read, opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -71,8 +71,10 @@ module Compass
|
|||||||
end
|
end
|
||||||
|
|
||||||
# When called with a block, defines the cache buster strategy to be used.
|
# 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.
|
# If the block returns nil or a string, then it is appended to the url as a query parameter.
|
||||||
# The returned string must not include the starting '?'.
|
# 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.
|
# 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
|
# 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.
|
# that points to the asset on disk -- which may or may not exist.
|
||||||
|
@ -13,6 +13,7 @@ module Compass::Exec
|
|||||||
def run!
|
def run!
|
||||||
begin
|
begin
|
||||||
perform!
|
perform!
|
||||||
|
return 0
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
raise e if e.is_a? SystemExit
|
raise e if e.is_a? SystemExit
|
||||||
if e.is_a?(::Compass::Error) || e.is_a?(OptionParser::ParseError)
|
if e.is_a?(::Compass::Error) || e.is_a?(OptionParser::ParseError)
|
||||||
@ -22,7 +23,6 @@ module Compass::Exec
|
|||||||
end
|
end
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
return 0
|
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
@ -91,9 +91,7 @@ module Compass::SassExtensions::Functions::Urls
|
|||||||
if cache_buster.is_a?(Sass::Script::String)
|
if cache_buster.is_a?(Sass::Script::String)
|
||||||
path += "?#{cache_buster.value}"
|
path += "?#{cache_buster.value}"
|
||||||
else
|
else
|
||||||
if buster = compute_cache_buster(path, real_path)
|
path = cache_busted_path(path, real_path)
|
||||||
path += "?#{buster}"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -137,6 +135,23 @@ module Compass::SassExtensions::Functions::Urls
|
|||||||
end
|
end
|
||||||
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)
|
def compute_cache_buster(path, real_path)
|
||||||
if Compass.configuration.asset_cache_buster
|
if Compass.configuration.asset_cache_buster
|
||||||
args = [path]
|
args = [path]
|
||||||
|
@ -9,6 +9,8 @@ module Compass
|
|||||||
end
|
end
|
||||||
|
|
||||||
require 'compass/sass_extensions/sprites/image'
|
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/sprite_map'
|
||||||
require 'compass/sass_extensions/sprites/engines'
|
require 'compass/sass_extensions/sprites/engines'
|
||||||
|
|
||||||
|
@ -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'
|
require 'compass/sass_extensions/sprites/engines/chunky_png_engine'
|
@ -7,20 +7,19 @@ end
|
|||||||
module Compass
|
module Compass
|
||||||
module SassExtensions
|
module SassExtensions
|
||||||
module Sprites
|
module Sprites
|
||||||
module ChunkyPngEngine
|
class ChunkyPngEngine < Compass::SassExtensions::Sprites::Engine
|
||||||
|
|
||||||
# Returns a PNG object
|
|
||||||
def construct_sprite
|
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|
|
images.each do |image|
|
||||||
input_png = ChunkyPNG::Image.from_file(image.file)
|
input_png = ChunkyPNG::Image.from_file(image.file)
|
||||||
if image.repeat == "no-repeat"
|
if image.repeat == "no-repeat"
|
||||||
output_png.replace! input_png, image.left, image.top
|
canvas.replace! input_png, image.left, image.top
|
||||||
else
|
else
|
||||||
x = image.left - (image.left / image.width).ceil * image.width
|
x = image.left - (image.left / image.width).ceil * image.width
|
||||||
while x < width do
|
while x < width do
|
||||||
begin
|
begin
|
||||||
output_png.replace! input_png, x, image.top
|
canvas.replace! input_png, x, image.top
|
||||||
x += image.width
|
x += image.width
|
||||||
rescue ChunkyPNG::OutOfBounds
|
rescue ChunkyPNG::OutOfBounds
|
||||||
break;
|
break;
|
||||||
@ -28,8 +27,15 @@ module Compass
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
output_png
|
end
|
||||||
end
|
|
||||||
|
def save(filename)
|
||||||
|
if canvas.nil?
|
||||||
|
construct_sprite
|
||||||
|
end
|
||||||
|
canvas.save(filename, :best_compression)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
32
lib/compass/sass_extensions/sprites/image_methods.rb
Normal file
@ -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
|
@ -2,6 +2,11 @@ module Compass
|
|||||||
module SassExtensions
|
module SassExtensions
|
||||||
module Sprites
|
module Sprites
|
||||||
class SpriteMap < Sass::Script::Literal
|
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
|
# Initialize a new sprite object from a relative file path
|
||||||
@ -14,21 +19,7 @@ module Compass
|
|||||||
new(sprites, importer.path, importer.name, context, kwargs)
|
new(sprites, importer.path, importer.name, context, kwargs)
|
||||||
end
|
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)
|
def initialize(sprites, path, name, context, kwargs)
|
||||||
require_engine!
|
|
||||||
@image_names = sprites
|
@image_names = sprites
|
||||||
@path = path
|
@path = path
|
||||||
@name = name
|
@name = name
|
||||||
@ -37,150 +28,12 @@ module Compass
|
|||||||
@images = nil
|
@images = nil
|
||||||
@width = nil
|
@width = nil
|
||||||
@height = nil
|
@height = nil
|
||||||
|
@engine = nil
|
||||||
@evaluation_context = context
|
@evaluation_context = context
|
||||||
validate!
|
validate!
|
||||||
compute_image_metadata!
|
compute_image_metadata!
|
||||||
end
|
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
|
def inspect
|
||||||
to_s
|
to_s
|
||||||
end
|
end
|
||||||
|
134
lib/compass/sass_extensions/sprites/sprite_methods.rb
Normal file
@ -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
|
@ -5,6 +5,13 @@ module Compass
|
|||||||
SPRITE_IMPORTER_REGEX = %r{((.+/)?([^\*.]+))/(.+?)\.png}
|
SPRITE_IMPORTER_REGEX = %r{((.+/)?([^\*.]+))/(.+?)\.png}
|
||||||
VALID_EXTENSIONS = ['.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)
|
def self.load(uri, options)
|
||||||
klass = Compass::SpriteImporter.new
|
klass = Compass::SpriteImporter.new
|
||||||
klass.uri, klass.options = uri, options
|
klass.uri, klass.options = uri, options
|
||||||
@ -31,7 +38,7 @@ module Compass
|
|||||||
end
|
end
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
content_for_images
|
self.class.name
|
||||||
end
|
end
|
||||||
|
|
||||||
def hash
|
def hash
|
||||||
|
@ -1,9 +1,16 @@
|
|||||||
begin
|
begin
|
||||||
require 'rubygems'
|
require 'rubygems'
|
||||||
require 'compass-validator'
|
require 'compass-validator'
|
||||||
rescue LoadError
|
rescue LoadError => e
|
||||||
raise Compass::MissingDependency, %Q{The Compass CSS Validator could not be loaded. Please install it:
|
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
|
sudo gem install compass-validator
|
||||||
}
|
ERRORMSG
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -1,5 +0,0 @@
|
|||||||
require 'spec_helper'
|
|
||||||
require 'fakefs/spec_helpers'
|
|
||||||
|
|
||||||
describe Compass::Sprites do
|
|
||||||
end
|
|
@ -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
|
|
@ -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
|
|
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 2.7 KiB |
29
test/fixtures/stylesheets/busted_image_urls/config.rb
vendored
Normal file
@ -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
|
9
test/fixtures/stylesheets/busted_image_urls/css/screen.css
vendored
Normal file
@ -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'); }
|
BIN
test/fixtures/stylesheets/busted_image_urls/images/feed.png
vendored
Normal file
After Width: | Height: | Size: 691 B |
BIN
test/fixtures/stylesheets/busted_image_urls/images/flags/dk.png
vendored
Normal file
After Width: | Height: | Size: 808 B |
BIN
test/fixtures/stylesheets/busted_image_urls/images/grid.png
vendored
Normal file
After Width: | Height: | Size: 199 B |
14
test/fixtures/stylesheets/busted_image_urls/sass/screen.sass
vendored
Normal file
@ -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")
|
@ -15,3 +15,12 @@
|
|||||||
visibility: hidden; }
|
visibility: hidden; }
|
||||||
.pie-clearfix {
|
.pie-clearfix {
|
||||||
display: block; }
|
display: block; }
|
||||||
|
|
||||||
|
.simplified-pie-clearfix {
|
||||||
|
display: inline-block; }
|
||||||
|
.simplified-pie-clearfix:after {
|
||||||
|
content: "";
|
||||||
|
display: table;
|
||||||
|
clear: both; }
|
||||||
|
.simplified-pie-clearfix {
|
||||||
|
display: block; }
|
||||||
|
@ -12,6 +12,13 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
visibility: hidden; }
|
visibility: hidden; }
|
||||||
|
|
||||||
|
.simple-pie-clearfix {
|
||||||
|
*zoom: 1; }
|
||||||
|
.simple-pie-clearfix:after {
|
||||||
|
content: "";
|
||||||
|
display: table;
|
||||||
|
clear: both; }
|
||||||
|
|
||||||
p.light {
|
p.light {
|
||||||
background-color: #b0201e;
|
background-color: #b0201e;
|
||||||
color: black; }
|
color: black; }
|
||||||
|
@ -7,5 +7,8 @@ $default-has-layout-approach: block;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.pie-clearfix {
|
.pie-clearfix {
|
||||||
|
@include legacy-pie-clearfix;
|
||||||
|
}
|
||||||
|
.simplified-pie-clearfix {
|
||||||
@include pie-clearfix;
|
@include pie-clearfix;
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.pie-clearfix {
|
.pie-clearfix {
|
||||||
|
@include legacy-pie-clearfix;
|
||||||
|
}
|
||||||
|
.simple-pie-clearfix {
|
||||||
@include pie-clearfix;
|
@include pie-clearfix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,6 +73,17 @@ class CompassTest < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
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
|
def test_image_urls
|
||||||
within_project('image_urls') do |proj|
|
within_project('image_urls') do |proj|
|
||||||
each_css_file(proj.css_path) do |css_file|
|
each_css_file(proj.css_path) do |css_file|
|
||||||
|
@ -71,7 +71,7 @@ class SpritesTest < Test::Unit::TestCase
|
|||||||
}
|
}
|
||||||
CSS
|
CSS
|
||||||
assert_equal image_size('squares-s*.png'), [20, 30]
|
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
|
end
|
||||||
|
|
||||||
it "should generate sprite classes with dimensions" do
|
it "should generate sprite classes with dimensions" do
|
||||||
@ -294,7 +294,7 @@ class SpritesTest < Test::Unit::TestCase
|
|||||||
}
|
}
|
||||||
CSS
|
CSS
|
||||||
assert_equal image_size('squares-s*.png'), [20, 30]
|
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
|
end
|
||||||
|
|
||||||
it "should use position adjustments in mixins" do
|
it "should use position adjustments in mixins" do
|
||||||
@ -332,7 +332,7 @@ class SpritesTest < Test::Unit::TestCase
|
|||||||
}
|
}
|
||||||
CSS
|
CSS
|
||||||
assert_equal image_size('squares-s*.png'), [20, 30]
|
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
|
end
|
||||||
|
|
||||||
it "should repeat the image" do
|
it "should repeat the image" do
|
||||||
@ -355,7 +355,7 @@ class SpritesTest < Test::Unit::TestCase
|
|||||||
}
|
}
|
||||||
CSS
|
CSS
|
||||||
assert_equal image_size('squares-s*.png'), [20, 30]
|
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
|
end
|
||||||
|
|
||||||
it "should allow the position of a sprite to be specified in absolute pixels" do
|
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
|
CSS
|
||||||
assert_equal image_size('squares-s*.png'), [30, 30]
|
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
|
end
|
||||||
|
|
||||||
it "should provide a nice errors for lemonade's old users" do
|
it "should provide a nice errors for lemonade's old users" do
|
||||||
|
43
test/units/sprites/engine_test.rb
Normal file
@ -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
|
@ -10,6 +10,10 @@ class ImporterTest < Test::Unit::TestCase
|
|||||||
@importer = Compass::SpriteImporter.new(:uri => URI, :options => options)
|
@importer = Compass::SpriteImporter.new(:uri => URI, :options => options)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def teardown
|
||||||
|
Compass.reset_configuration!
|
||||||
|
end
|
||||||
|
|
||||||
def options
|
def options
|
||||||
{:foo => 'bar'}
|
{:foo => 'bar'}
|
||||||
end
|
end
|
||||||
@ -46,21 +50,17 @@ class ImporterTest < Test::Unit::TestCase
|
|||||||
assert_equal 'bar', @importer.sass_options[:foo]
|
assert_equal 'bar', @importer.sass_options[:foo]
|
||||||
end
|
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')
|
@images_src_path = File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'sprites', 'public', 'images')
|
||||||
file = StringIO.new("images_path = #{@images_src_path.inspect}\n")
|
file = StringIO.new("images_path = #{@images_src_path.inspect}\n")
|
||||||
Compass.add_configuration(file, "sprite_config")
|
Compass.add_configuration(file, "sprite_config")
|
||||||
importer = Compass::SpriteImporter.new(:uri => 'bad_extensions/*.jpg', :options => options)
|
importer = Compass::SpriteImporter.new(:uri => 'bad_extensions/*.jpg', :options => options)
|
||||||
begin
|
begin
|
||||||
importer.sass_engine
|
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
|
rescue Compass::Error => e
|
||||||
assert e.message.include?('.png')
|
assert e.message.include?('.png')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def taredown
|
|
||||||
Compass.reset_configuration!
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
@ -1,8 +1,27 @@
|
|||||||
require 'spec_helper'
|
require 'test_helper'
|
||||||
require 'compass/commands'
|
|
||||||
require 'compass/exec'
|
class SpriteCommandTest < Test::Unit::TestCase
|
||||||
require 'compass/commands/sprite'
|
attr_reader :test_dir
|
||||||
describe Compass::Commands::Sprite 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
|
||||||
|
File.open(File.join(@test_dir, 'config.rb'), 'w') do |f|
|
||||||
|
f << config_data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
def config_data
|
||||||
return <<-CONFIG
|
return <<-CONFIG
|
||||||
images_path = #{@images_tmp_path.inspect}
|
images_path = #{@images_tmp_path.inspect}
|
||||||
@ -25,16 +44,7 @@ describe Compass::Commands::Sprite do
|
|||||||
options.map.flatten!
|
options.map.flatten!
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:test_dir) { @test_dir }
|
def teardown
|
||||||
before :each do
|
|
||||||
@before_dir = ::Dir.pwd
|
|
||||||
create_temp_cli_dir
|
|
||||||
create_sprite_temp
|
|
||||||
File.open(File.join(@test_dir, 'config.rb'), 'w') do |f|
|
|
||||||
f << config_data
|
|
||||||
end
|
|
||||||
end
|
|
||||||
after :each do
|
|
||||||
::Dir.chdir @before_dir
|
::Dir.chdir @before_dir
|
||||||
clean_up_sprites
|
clean_up_sprites
|
||||||
if File.exists?(@test_dir)
|
if File.exists?(@test_dir)
|
||||||
@ -43,13 +53,8 @@ describe Compass::Commands::Sprite do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "should create sprite file" do
|
it "should create sprite file" do
|
||||||
run_compass_with_options(['sprite', "-f", "stylesheet.scss", "'#{@images_tmp_path}/*.png'"]).to_i.should == 0
|
assert_equal 0, run_compass_with_options(['sprite', "-f", 'stylesheet.scss', "'#{@images_tmp_path}/*.png'"]).to_i
|
||||||
File.exists?(File.join(test_dir, 'stylesheet.scss')).should be_true
|
assert File.exists?(File.join(test_dir, 'stylesheet.scss'))
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should fail gracfuly when giving bad arguments" do
|
|
||||||
pending
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|