Compare commits
43 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
9731c17de1 | ||
|
0954c8d59b | ||
|
610f3cdafe | ||
|
7aba64eb41 | ||
|
f209524228 | ||
|
247d6dc8e6 | ||
|
1d9e2cbc8a | ||
|
7d763f76d7 | ||
|
4603ac9900 | ||
|
5567e7b13f | ||
|
0354dd92a5 | ||
|
94fbfd9aa8 | ||
|
40d32606bb | ||
|
043d082033 | ||
|
d5fa05bc7d | ||
|
8c7223575a | ||
|
c55896b493 | ||
|
e25508f336 | ||
|
109687c7d0 | ||
|
47cec8151c | ||
|
330b39002a | ||
|
014c609118 | ||
|
df05620508 | ||
|
c0c39c53d7 | ||
|
7077b76225 | ||
|
3e7cd28635 | ||
|
53d975ffae | ||
|
acd720b41f | ||
|
6d0315ad77 | ||
|
c17fe444b6 | ||
|
c1756302ca | ||
|
fdef9d4e44 | ||
|
9380326186 | ||
|
29d39e808d | ||
|
4b75ef471e | ||
|
62157f6a7e | ||
|
6a44d58b7c | ||
|
ac85ca1e7a | ||
|
d79dea68db | ||
|
87b624a56e | ||
|
d0f33a74b9 | ||
|
a14a4f33ad | ||
|
d1708dd2c3 |
10
Gemfile
10
Gemfile
@ -1,12 +1,14 @@
|
|||||||
source :rubygems
|
source :rubygems
|
||||||
|
|
||||||
gem "compass", :path => "."
|
gem "compass", :path => "."
|
||||||
gem "cucumber"
|
gem "cucumber", "~> 0.9.2"
|
||||||
gem "rspec"
|
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.0"
|
||||||
gem "css_parser"
|
gem "css_parser", "~> 1.0.1"
|
||||||
gem "sass", "~> 3.1"
|
gem "sass", "~> 3.1", :path => "../sass"
|
||||||
gem "rcov"
|
gem "rcov"
|
||||||
gem "rubyzip"
|
gem "rubyzip"
|
||||||
gem "livereload"
|
gem "livereload"
|
||||||
|
gem "chunky_png", "~> 0.10.1"
|
||||||
|
gem "ruby-prof"
|
||||||
|
14
Rakefile
14
Rakefile
@ -29,6 +29,20 @@ To run with an alternate version of Rails, make test/rails a symlink to that ver
|
|||||||
To run with an alternate version of Haml & Sass, make test/haml a symlink to that version.
|
To run with an alternate version of Haml & Sass, make test/haml a symlink to that version.
|
||||||
END
|
END
|
||||||
|
|
||||||
|
begin
|
||||||
|
require 'rspec/core/rake_task'
|
||||||
|
|
||||||
|
RSpec::Core::RakeTask.new(:spec)
|
||||||
|
|
||||||
|
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
||||||
|
spec.rcov = true
|
||||||
|
end
|
||||||
|
|
||||||
|
task :default => :spec
|
||||||
|
rescue LoadError
|
||||||
|
puts "Rspec (or a dependency) is not available. Try running bundler install"
|
||||||
|
end
|
||||||
|
|
||||||
desc "Compile Examples into HTML and CSS"
|
desc "Compile Examples into HTML and CSS"
|
||||||
task :examples do
|
task :examples do
|
||||||
linked_haml = "tests/haml"
|
linked_haml = "tests/haml"
|
||||||
|
19
bin/compass
19
bin/compass
@ -21,6 +21,21 @@ fallback_load_path(File.join(File.dirname(__FILE__), '..', 'lib')) do
|
|||||||
require 'compass/exec'
|
require 'compass/exec'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
runner = Proc.new do
|
||||||
command_line_class = Compass::Exec::Helpers.select_appropriate_command_line_ui(ARGV)
|
command_line_class = Compass::Exec::Helpers.select_appropriate_command_line_ui(ARGV)
|
||||||
exit command_line_class.new(ARGV).run!
|
command_line_class.new(ARGV).run!
|
||||||
|
end
|
||||||
|
|
||||||
|
if ARGV.delete("--profile")
|
||||||
|
require 'ruby-prof'
|
||||||
|
RubyProf.start
|
||||||
|
exit_code = runner.call
|
||||||
|
result = RubyProf.stop
|
||||||
|
|
||||||
|
# Print a flat profile to text
|
||||||
|
printer = RubyProf::FlatPrinter.new(result)
|
||||||
|
printer.print(STDERR, 0)
|
||||||
|
exit exit_code
|
||||||
|
else
|
||||||
|
exit runner.call
|
||||||
|
end
|
||||||
|
@ -7,7 +7,7 @@ Gem::Specification.new do |gemspec|
|
|||||||
gemspec.date = "#{Time.now.year}-#{Time.now.month}-#{Time.now.day}" # Automatically update for each build
|
gemspec.date = "#{Time.now.year}-#{Time.now.month}-#{Time.now.day}" # Automatically update for each build
|
||||||
gemspec.description = "Compass is a Sass-based Stylesheet Framework that streamlines the creation and maintainance of CSS."
|
gemspec.description = "Compass is a Sass-based Stylesheet Framework that streamlines the creation and maintainance of CSS."
|
||||||
gemspec.homepage = "http://compass-style.org"
|
gemspec.homepage = "http://compass-style.org"
|
||||||
gemspec.authors = ["Chris Eppstein", "Eric A. Meyer", "Brandon Mathis"]
|
gemspec.authors = ["Chris Eppstein", "Eric A. Meyer", "Brandon Mathis", "Nico Hagenburger"]
|
||||||
gemspec.email = "chris@eppsteins.net"
|
gemspec.email = "chris@eppsteins.net"
|
||||||
gemspec.default_executable = "compass"
|
gemspec.default_executable = "compass"
|
||||||
gemspec.executables = %w(compass)
|
gemspec.executables = %w(compass)
|
||||||
@ -15,7 +15,10 @@ Gem::Specification.new do |gemspec|
|
|||||||
gemspec.require_paths = %w(lib)
|
gemspec.require_paths = %w(lib)
|
||||||
gemspec.rubygems_version = "1.3.5"
|
gemspec.rubygems_version = "1.3.5"
|
||||||
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', '~> 0.10.3'
|
||||||
|
|
||||||
gemspec.files = %w(README.markdown LICENSE.markdown VERSION.yml Rakefile)
|
gemspec.files = %w(README.markdown LICENSE.markdown VERSION.yml Rakefile)
|
||||||
gemspec.files += Dir.glob("bin/*")
|
gemspec.files += Dir.glob("bin/*")
|
||||||
gemspec.files += Dir.glob("examples/**/*.*")
|
gemspec.files += Dir.glob("examples/**/*.*")
|
||||||
|
@ -9,7 +9,8 @@ gem 'fssm'
|
|||||||
gem 'serve', "1.0.0"
|
gem 'serve', "1.0.0"
|
||||||
gem 'nokogiri'
|
gem 'nokogiri'
|
||||||
gem 'coderay'
|
gem 'coderay'
|
||||||
gem 'haml', ">=3.0.23", :require => 'sass'
|
gem 'sass', :path => "../../sass"
|
||||||
|
gem 'haml', ">= 3.1.0.alpha.36"
|
||||||
gem 'rake'
|
gem 'rake'
|
||||||
gem 'compass', :path => ".."
|
gem 'compass', :path => ".."
|
||||||
gem 'compass-susy-plugin', ">=0.7.0.pre8"
|
gem 'compass-susy-plugin', ">=0.7.0.pre8"
|
||||||
|
@ -1,20 +1,27 @@
|
|||||||
GIT
|
GIT
|
||||||
remote: git://github.com/chriseppstein/nanoc.git
|
remote: git://github.com/chriseppstein/nanoc.git
|
||||||
revision: 4ecb400489c83fd2068659de0c651733b8dad28f
|
revision: 4eee0e60c5121b90498caa88605d416521553378
|
||||||
specs:
|
specs:
|
||||||
nanoc3 (3.2.0a3)
|
nanoc3 (3.2.0a3)
|
||||||
cri (>= 1.0.0)
|
cri (>= 1.0.0)
|
||||||
|
|
||||||
PATH
|
PATH
|
||||||
remote: /Users/bmathis/Documents/Workspace/compass-projects/compass
|
remote: /Users/chris/Projects/compass
|
||||||
specs:
|
specs:
|
||||||
compass (0.11.alpha.1.488fddf)
|
compass (0.11.alpha.1.610f3cd)
|
||||||
|
chunky_png (~> 0.10.3)
|
||||||
sass (~> 3.1)
|
sass (~> 3.1)
|
||||||
|
|
||||||
|
PATH
|
||||||
|
remote: /Users/chris/Projects/sass
|
||||||
|
specs:
|
||||||
|
sass (3.1.0.alpha.0)
|
||||||
|
|
||||||
GEM
|
GEM
|
||||||
remote: http://rubygems.org/
|
remote: http://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
activesupport (3.0.1)
|
activesupport (3.0.1)
|
||||||
|
chunky_png (0.10.5)
|
||||||
coderay (0.9.5)
|
coderay (0.9.5)
|
||||||
compass-susy-plugin (0.8.1)
|
compass-susy-plugin (0.8.1)
|
||||||
compass (>= 0.10.0)
|
compass (>= 0.10.0)
|
||||||
@ -22,7 +29,7 @@ GEM
|
|||||||
css-slideshow (0.2.0)
|
css-slideshow (0.2.0)
|
||||||
compass (>= 0.10.0.rc3)
|
compass (>= 0.10.0.rc3)
|
||||||
fssm (0.2.0)
|
fssm (0.2.0)
|
||||||
haml (3.0.23)
|
haml (3.1.0.alpha.36)
|
||||||
i18n (0.4.2)
|
i18n (0.4.2)
|
||||||
json (1.4.6)
|
json (1.4.6)
|
||||||
mime-types (1.16)
|
mime-types (1.16)
|
||||||
@ -30,7 +37,6 @@ GEM
|
|||||||
rack (1.2.1)
|
rack (1.2.1)
|
||||||
rake (0.8.7)
|
rake (0.8.7)
|
||||||
rdiscount (1.6.5)
|
rdiscount (1.6.5)
|
||||||
sass (3.1.0.alpha.28)
|
|
||||||
serve (1.0.0)
|
serve (1.0.0)
|
||||||
activesupport (~> 3.0.1)
|
activesupport (~> 3.0.1)
|
||||||
i18n (~> 0.4.1)
|
i18n (~> 0.4.1)
|
||||||
@ -48,7 +54,7 @@ DEPENDENCIES
|
|||||||
compass-susy-plugin (>= 0.7.0.pre8)
|
compass-susy-plugin (>= 0.7.0.pre8)
|
||||||
css-slideshow (= 0.2.0)
|
css-slideshow (= 0.2.0)
|
||||||
fssm
|
fssm
|
||||||
haml (>= 3.0.23)
|
haml (>= 3.1.0.alpha.36)
|
||||||
json
|
json
|
||||||
mime-types
|
mime-types
|
||||||
nanoc3!
|
nanoc3!
|
||||||
@ -56,5 +62,6 @@ DEPENDENCIES
|
|||||||
rack
|
rack
|
||||||
rake
|
rake
|
||||||
rdiscount
|
rdiscount
|
||||||
|
sass!
|
||||||
serve (= 1.0.0)
|
serve (= 1.0.0)
|
||||||
thor
|
thor
|
||||||
|
1
doc-src/assets/javascripts/shBrushSass.js
vendored
1
doc-src/assets/javascripts/shBrushSass.js
vendored
@ -110,3 +110,4 @@
|
|||||||
// CommonJS
|
// CommonJS
|
||||||
typeof(exports) != 'undefined' ? exports.Brush = Brush : null;
|
typeof(exports) != 'undefined' ? exports.Brush = Brush : null;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
1
doc-src/assets/javascripts/shCore.js
vendored
1
doc-src/assets/javascripts/shCore.js
vendored
File diff suppressed because one or more lines are too long
8
doc-src/content/help/tutorials/spriting.markdown
Normal file
8
doc-src/content/help/tutorials/spriting.markdown
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
title: Spriting with Compass
|
||||||
|
layout: tutorial
|
||||||
|
crumb: Spriting
|
||||||
|
classnames:
|
||||||
|
- tutorial
|
||||||
|
---
|
||||||
|
# Spriting with Compass
|
132
doc-src/content/reference/compass/helpers/sprites.haml
Normal file
132
doc-src/content/reference/compass/helpers/sprites.haml
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
---
|
||||||
|
title: Compass Sprite Helpers
|
||||||
|
crumb: Sprites
|
||||||
|
framework: compass
|
||||||
|
meta_description: Helper functions for working with Sprite images.
|
||||||
|
layout: core
|
||||||
|
classnames:
|
||||||
|
- reference
|
||||||
|
- core
|
||||||
|
- helpers
|
||||||
|
---
|
||||||
|
%h1 Compass Sprite Helpers
|
||||||
|
|
||||||
|
:markdown
|
||||||
|
These helpers make it easier to build and to work with sprites.
|
||||||
|
|
||||||
|
While it is allowed to use these directly, to do so is considered "advanced usage".
|
||||||
|
It is recommended that you instead use the sprite mixins that are designed to work
|
||||||
|
with these functions.
|
||||||
|
|
||||||
|
See the [Spriting Tutorial](/help/tutorials/spriting/) for more information.
|
||||||
|
|
||||||
|
#sprite-map.helper
|
||||||
|
%h3
|
||||||
|
%a(href="#sprite-map")
|
||||||
|
sprite-map(<span class="arg">$glob</span>, <span class="arg">...</span>)
|
||||||
|
.details
|
||||||
|
:markdown
|
||||||
|
Generates a sprite map from the files matching the glob pattern. Uses the
|
||||||
|
keyword-style arguments passed in to control the placement.
|
||||||
|
|
||||||
|
Only PNG files can be made into sprites at this time.
|
||||||
|
|
||||||
|
The `$glob` should be glob pattern relative to the images directory that specifies
|
||||||
|
what files will be in the sprite. For example:
|
||||||
|
|
||||||
|
$icons: sprite-map("icons/*.png");
|
||||||
|
background: $icons;
|
||||||
|
|
||||||
|
This will generate a sprite map and return a reference to it. It's important to
|
||||||
|
capture this to a variable, because you will need to use it later when creating
|
||||||
|
sprites. In the above example you might end up with a new file named
|
||||||
|
`images/sprites/icons-a2ef041.png` and your css stylesheet will have:
|
||||||
|
|
||||||
|
background: url('/images/sprites/icons-a2ef041.png?1234678') no-repeat;
|
||||||
|
|
||||||
|
The exact image name is not something you should depend on as it may change based on the
|
||||||
|
arguments you pass in. Instead, you can use the `sprite-url()` function to create a
|
||||||
|
reference to the sprite map without generating the image again. Alternatively, simply
|
||||||
|
using the sprite map variable in an property will have the same effect as calling
|
||||||
|
`sprite-url()`.
|
||||||
|
|
||||||
|
For each sprite in the sprite map you can control the position, spacing, and whether or
|
||||||
|
not it repeats. You do this by passing arguments to this function that tell each sprite
|
||||||
|
how to behave. For instance if there is a icons/new.png then you can control it like so:
|
||||||
|
|
||||||
|
$icon-sprite: sprite-map("icons/*.png",
|
||||||
|
$new-position: 100%, $new-spacing: 15px, $new-repeat: no-repeat);
|
||||||
|
|
||||||
|
If you don't specify these options they will default to `0%` for `position`,
|
||||||
|
`0px` for spacing, and `no-repeat` for `repeat`.
|
||||||
|
|
||||||
|
Default values for all sprites can be specified by passing values for `$position`,
|
||||||
|
`$spacing`, and `$repeat`.
|
||||||
|
|
||||||
|
#sprite.helper
|
||||||
|
%h3
|
||||||
|
%a(href="#sprite")
|
||||||
|
sprite(<span class="arg">$map</span>, <span class="arg">$sprite</span>, <span class="arg" data-default-value="0">$offset-x</span>, <span class="arg" data-default-value="0">$offset-y</span>)
|
||||||
|
.details
|
||||||
|
:markdown
|
||||||
|
Returns the image and background position for use in a single shorthand property:
|
||||||
|
|
||||||
|
$icons: sprite-map("icons/*.png"); // contains icons/new.png among others.
|
||||||
|
background: sprite($icons, new) no-repeat;
|
||||||
|
|
||||||
|
Becomes:
|
||||||
|
|
||||||
|
background: url('/images/icons.png?12345678') 0 -24px no-repeat;
|
||||||
|
|
||||||
|
#sprite-map-name.helper
|
||||||
|
%h3
|
||||||
|
%a(href="#sprite-map-name")
|
||||||
|
sprite-map-name(<span class="arg">$map</span>)
|
||||||
|
.details
|
||||||
|
:markdown
|
||||||
|
Returns the name of a sprite map
|
||||||
|
The name is derived from the folder than contains the sprites.
|
||||||
|
|
||||||
|
#sprite-file.helper
|
||||||
|
%h3
|
||||||
|
%a(href="#sprite-file")
|
||||||
|
sprite-file(<span class="arg">$map</span>, <span class="arg">$sprite</span>)
|
||||||
|
.details
|
||||||
|
:markdown
|
||||||
|
Returns the relative path (from the images directory) to the original file
|
||||||
|
used when construction the sprite. This is suitable for passing to the
|
||||||
|
`image-width` and `image-height` helpers.
|
||||||
|
|
||||||
|
#sprite-url.helper
|
||||||
|
%h3
|
||||||
|
%a(href="#sprite-url")
|
||||||
|
sprite-url(<span class="arg">$map</span>)
|
||||||
|
.details
|
||||||
|
:markdown
|
||||||
|
Returns a url to the sprite image.
|
||||||
|
|
||||||
|
#sprite-position.helper
|
||||||
|
%h3
|
||||||
|
%a(href="#sprite-position")
|
||||||
|
sprite-position(<span class="arg">$map</span>, <span class="arg">$sprite</span>, <span class="arg" data-default-value="0">$offset-x</span>, <span class="arg" data-default-value="0">$offset-y</span>)
|
||||||
|
.details
|
||||||
|
:markdown
|
||||||
|
Returns the position for the original image in the sprite.
|
||||||
|
This is suitable for use as a value to background-position:
|
||||||
|
|
||||||
|
$icons: sprite-map("icons/*.png");
|
||||||
|
background-position: sprite-position($icons, new);
|
||||||
|
|
||||||
|
Might generate something like:
|
||||||
|
|
||||||
|
background-position: 0 -34px;
|
||||||
|
|
||||||
|
You can adjust the background relative to this position by passing values for
|
||||||
|
`$offset-x` and `$offset-y`:
|
||||||
|
|
||||||
|
$icons: sprite-map("icons/*.png");
|
||||||
|
background-position: sprite-position($icons, new, 3px, -2px);
|
||||||
|
|
||||||
|
Would change the above output to:
|
||||||
|
|
||||||
|
background-position: 3px -36px;
|
@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
title: Compass Sprite Base
|
||||||
|
crumb: Sprite Base
|
||||||
|
framework: compass
|
||||||
|
stylesheet: compass/utilities/sprites/_base.scss
|
||||||
|
layout: core
|
||||||
|
nav_stylesheet: compass/_utilities.scss
|
||||||
|
classnames:
|
||||||
|
- reference
|
||||||
|
- core
|
||||||
|
- utilities
|
||||||
|
---
|
||||||
|
- render 'reference' do
|
||||||
|
:markdown
|
||||||
|
These mixins are useful for working with sprites. This file is imported by
|
||||||
|
magic sprite imports.
|
||||||
|
|
||||||
|
See the [Spriting Tutorial](/help/tutorials/spriting/) for more information.
|
@ -1,6 +1,6 @@
|
|||||||
// Default Syntax Highlighter theme.
|
// Default Syntax Highlighter theme.
|
||||||
//@import "shCore.scss";
|
@import "shCore.scss";
|
||||||
//@import "shThemeRDark.scss";
|
@import "shThemeRDark.scss";
|
||||||
|
|
||||||
/*.syntaxhighlighter {
|
/*.syntaxhighlighter {
|
||||||
.keyword { font-weight: bold !important; }
|
.keyword { font-weight: bold !important; }
|
||||||
|
@ -156,6 +156,7 @@ Feature: Command Line
|
|||||||
| imports |
|
| imports |
|
||||||
| install |
|
| install |
|
||||||
| interactive |
|
| interactive |
|
||||||
|
| sprite |
|
||||||
| stats |
|
| stats |
|
||||||
| unpack |
|
| unpack |
|
||||||
| validate |
|
| validate |
|
||||||
|
38
frameworks/compass/stylesheets/_lemonade.scss
Normal file
38
frameworks/compass/stylesheets/_lemonade.scss
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
@mixin image-dimensions($file) {
|
||||||
|
height: image-height($file);
|
||||||
|
width: image-width($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin sprite-image($file) {
|
||||||
|
background: sprite-image($file) $repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin sized-sprite-image($file) {
|
||||||
|
background: sprite-image($file);
|
||||||
|
@include image-dimensions($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin sprite-folder($folder, $image-dimensions: false) {
|
||||||
|
.#{$folder} {
|
||||||
|
@if $image-dimensions {
|
||||||
|
background: sprite-url($folder);
|
||||||
|
}
|
||||||
|
@else {
|
||||||
|
background: sprite-url($folder) no-repeat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@for $i from 0 to sprite-files-in-folder($folder) {
|
||||||
|
$file: sprite-file-from-folder($folder, $i);
|
||||||
|
.#{$folder}-#{image-basename($file)} {
|
||||||
|
@extend .#{$folder};
|
||||||
|
background-position: sprite-position(sprite-file-from-folder($folder, $i));
|
||||||
|
@if $image-dimensions {
|
||||||
|
@include image-dimensions($file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin sized-sprite-folder($folder) {
|
||||||
|
@include sprite-folder($folder, true);
|
||||||
|
}
|
@ -9,6 +9,8 @@ $default-background-size: 100% auto !default;
|
|||||||
// * percentages are relative to the background-origin (default = padding-box)
|
// * percentages are relative to the background-origin (default = padding-box)
|
||||||
// * mixin defaults to: `$default-background-size`
|
// * mixin defaults to: `$default-background-size`
|
||||||
@mixin background-size($size: $default-background-size) {
|
@mixin background-size($size: $default-background-size) {
|
||||||
|
@if type-of($size) == string {
|
||||||
$size: unquote($size);
|
$size: unquote($size);
|
||||||
|
}
|
||||||
@include experimental(background-size, $size, -moz, -webkit, -o, not -ms, not -khtml);
|
@include experimental(background-size, $size, -moz, -webkit, -o, not -ms, not -khtml);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
// Set the width and height of an element to the original
|
||||||
|
// dimensions of an image before it was included in the sprite.
|
||||||
|
@mixin sprite-dimensions($map, $sprite) {
|
||||||
|
height: image-height(sprite-file($map, $sprite));
|
||||||
|
width: image-width(sprite-file($map, $sprite));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the background position of the given sprite `$map` to display the
|
||||||
|
// sprite of the given `$sprite` name. You can move the image relative to its
|
||||||
|
// natural position by passing `$offset-x` and `$offset-y`.
|
||||||
|
@mixin sprite-position($map, $sprite, $offset-x: 0, $offset-y: 0) {
|
||||||
|
background-position: sprite-position($map, $sprite, $offset-x, $offset-y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Include the position and (optionally) dimensions of this `$sprite`
|
||||||
|
// in the given sprite `$map`. The sprite url should come from either a base
|
||||||
|
// class or you can specify the `sprite-url` explicitly like this:
|
||||||
|
//
|
||||||
|
// background: $map no-repeat;
|
||||||
|
@mixin sprite($map, $sprite, $dimensions: false, $offset-x: 0, $offset-y: 0) {
|
||||||
|
@include sprite-position($map, $sprite, $offset-x, $offset-y);
|
||||||
|
@if $dimensions {
|
||||||
|
@include sprite-dimensions($map, $sprite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates a class for each space separated name in `$sprite-names`.
|
||||||
|
// The class will be of the form .<map-name>-<sprite-name>.
|
||||||
|
//
|
||||||
|
// If a base class is provided, then each class will extend it.
|
||||||
|
//
|
||||||
|
// If `$dimensions` is `true`, the sprite dimensions will specified.
|
||||||
|
@mixin sprites($map, $sprite-names, $base-class: false, $dimensions: false) {
|
||||||
|
@each $sprite-name in $sprite-names {
|
||||||
|
.#{sprite-map-name($map)}-#{$sprite-name} {
|
||||||
|
@if $base-class { @extend #{$base-class}; }
|
||||||
|
@include sprite($map, $sprite-name, $dimensions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
module Compass
|
module Compass
|
||||||
end
|
end
|
||||||
|
|
||||||
%w(dependencies util sass_extensions core_ext version errors).each do |lib|
|
%w(dependencies util sass_extensions core_ext version errors quick_cache).each do |lib|
|
||||||
require "compass/#{lib}"
|
require "compass/#{lib}"
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -13,8 +13,9 @@ module Compass
|
|||||||
File.expand_path(File.join(File.dirname(__FILE__)))
|
File.expand_path(File.join(File.dirname(__FILE__)))
|
||||||
end
|
end
|
||||||
module_function :base_directory, :lib_directory
|
module_function :base_directory, :lib_directory
|
||||||
|
extend QuickCache
|
||||||
end
|
end
|
||||||
|
|
||||||
%w(configuration frameworks app_integration actions compiler).each do |lib|
|
%w(configuration frameworks app_integration actions compiler sprites).each do |lib|
|
||||||
require "compass/#{lib}"
|
require "compass/#{lib}"
|
||||||
end
|
end
|
||||||
|
@ -61,7 +61,7 @@ This can be done in one of the following ways:
|
|||||||
compass watch [path/to/project]
|
compass watch [path/to/project]
|
||||||
|
|
||||||
More Resources:
|
More Resources:
|
||||||
* Wiki: http://wiki.github.com/chriseppstein/compass
|
* Website: http://compass-style.org/
|
||||||
* Sass: http://sass-lang.com
|
* Sass: http://sass-lang.com
|
||||||
* Community: http://groups.google.com/group/compass-users/
|
* Community: http://groups.google.com/group/compass-users/
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ require 'compass/commands/registry'
|
|||||||
|
|
||||||
%w(base generate_grid_background help list_frameworks project_base
|
%w(base generate_grid_background help list_frameworks project_base
|
||||||
update_project watch_project create_project imports installer_command
|
update_project watch_project create_project imports installer_command
|
||||||
print_version project_stats stamp_pattern 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}"
|
||||||
end
|
end
|
||||||
|
87
lib/compass/commands/sprite.rb
Normal file
87
lib/compass/commands/sprite.rb
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
require 'compass/commands/project_base'
|
||||||
|
require 'compass/commands/update_project'
|
||||||
|
|
||||||
|
module Compass
|
||||||
|
module Commands
|
||||||
|
module SpriteOptionsParser
|
||||||
|
def set_options(opts)
|
||||||
|
opts.on("-f SPRITE_FILE") do |output_file|
|
||||||
|
self.options[:output_file] = output_file
|
||||||
|
end
|
||||||
|
opts.banner = %Q{
|
||||||
|
Usage: compass sprite [options] "images/path/to/sprites/*.png"
|
||||||
|
|
||||||
|
Description:
|
||||||
|
Generate a sprite import based on the given sprite directory.
|
||||||
|
Alternatively, you can simply do this in your sass files:
|
||||||
|
|
||||||
|
@import "sprite-folder/*.png"
|
||||||
|
|
||||||
|
And a magical, custom made sprite file will be imported.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
}.strip.split("\n").map{|l| l.gsub(/^ {0,10}/,'')}.join("\n")
|
||||||
|
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
class Sprite < ProjectBase
|
||||||
|
|
||||||
|
register :sprite
|
||||||
|
|
||||||
|
def initialize(working_path, options)
|
||||||
|
super
|
||||||
|
assert_project_directory_exists!
|
||||||
|
end
|
||||||
|
|
||||||
|
def perform
|
||||||
|
sprites = Compass::Sprites.new
|
||||||
|
relative_uri = options[:uri].gsub(/^#{Compass.configuration.images_dir}\//, '')
|
||||||
|
sprite_images = Compass::Sprites.discover_sprites(relative_uri)
|
||||||
|
image_names = sprite_images.map{|i| File.basename(i, '.png')}
|
||||||
|
sprites.path, sprites.name = Compass::Sprites.path_and_name(relative_uri)
|
||||||
|
options[:output_file] ||= File.join(Compass.configuration.sass_path, "sprites", "_#{sprites.name}.#{Compass.configuration.preferred_syntax}")
|
||||||
|
contents = sprites.content_for_images(relative_uri, sprites.name, image_names)
|
||||||
|
if options[:output_file][-4..-1] != "scss"
|
||||||
|
contents = Sass::Engine.new(contents, Compass.sass_engine_options.merge(:syntax => :scss)).to_tree.to_sass
|
||||||
|
end
|
||||||
|
directory File.dirname(options[:output_file])
|
||||||
|
write_file options[:output_file], contents
|
||||||
|
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(SpriteOptionsParser)
|
||||||
|
end
|
||||||
|
|
||||||
|
def usage
|
||||||
|
option_parser([]).to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def description(command)
|
||||||
|
"Generate an import for your sprites."
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse!(arguments)
|
||||||
|
parser = option_parser(arguments)
|
||||||
|
parser.parse!
|
||||||
|
parse_arguments!(parser, arguments)
|
||||||
|
parser.options
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_arguments!(parser, arguments)
|
||||||
|
parser.options[:uri] = arguments.shift
|
||||||
|
unless arguments.size == 0
|
||||||
|
raise Compass::Error, "Please specify at least one image to sprite."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -22,6 +22,8 @@ module Compass
|
|||||||
plugin_opts[:cache] = cache unless cache.nil?
|
plugin_opts[:cache] = cache unless cache.nil?
|
||||||
plugin_opts[:cache_location] = cache_path unless cache_path.nil?
|
plugin_opts[:cache_location] = cache_path unless cache_path.nil?
|
||||||
plugin_opts.merge!(sass_options || {})
|
plugin_opts.merge!(sass_options || {})
|
||||||
|
plugin_opts[:load_paths] ||= []
|
||||||
|
plugin_opts[:load_paths] << Compass::Sprites.new
|
||||||
plugin_opts
|
plugin_opts
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -57,6 +59,7 @@ module Compass
|
|||||||
load_paths << framework.stylesheets_directory if File.exists?(framework.stylesheets_directory)
|
load_paths << framework.stylesheets_directory if File.exists?(framework.stylesheets_directory)
|
||||||
end
|
end
|
||||||
load_paths += resolve_additional_import_paths
|
load_paths += resolve_additional_import_paths
|
||||||
|
load_paths << Compass::Sprites.new
|
||||||
load_paths
|
load_paths
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -2,5 +2,11 @@ begin
|
|||||||
require 'sass'
|
require 'sass'
|
||||||
rescue LoadError
|
rescue LoadError
|
||||||
require 'rubygems'
|
require 'rubygems'
|
||||||
|
begin
|
||||||
require 'sass'
|
require 'sass'
|
||||||
|
rescue LoadError
|
||||||
|
puts "Unable to load Sass. Please install it with one of the following commands:"
|
||||||
|
puts " gem install sass --pre"
|
||||||
|
raise
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -47,7 +47,7 @@ This can be done in one of the following ways:
|
|||||||
compass watch [path/to/project]
|
compass watch [path/to/project]
|
||||||
|
|
||||||
More Resources:
|
More Resources:
|
||||||
* Wiki: http://wiki.github.com/chriseppstein/compass
|
* Website: http://compass-style.org/
|
||||||
* Sass: http://sass-lang.com
|
* Sass: http://sass-lang.com
|
||||||
* Community: http://groups.google.com/group/compass-users/
|
* Community: http://groups.google.com/group/compass-users/
|
||||||
NEXTSTEPS
|
NEXTSTEPS
|
||||||
|
15
lib/compass/quick_cache.rb
Normal file
15
lib/compass/quick_cache.rb
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
module QuickCache
|
||||||
|
|
||||||
|
# cache a value in memory for just a few seconds
|
||||||
|
# This can speed up reads of values that change relatively infrequently
|
||||||
|
# but might be read many times in a short burst of reads.
|
||||||
|
def quick_cache(key, ttl = 1)
|
||||||
|
@quick_cache ||= {}
|
||||||
|
if @quick_cache[key] && @quick_cache[key].first > Time.now - ttl
|
||||||
|
@quick_cache[key].last
|
||||||
|
else
|
||||||
|
(@quick_cache[key] = [Time.now, yield]).last
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@ -4,7 +4,7 @@ end
|
|||||||
%w(
|
%w(
|
||||||
selectors enumerate urls display
|
selectors enumerate urls display
|
||||||
inline_image image_size constants gradient_support
|
inline_image image_size constants gradient_support
|
||||||
font_files lists colors trig
|
font_files lists colors trig sprites
|
||||||
).each do |func|
|
).each do |func|
|
||||||
require "compass/sass_extensions/functions/#{func}"
|
require "compass/sass_extensions/functions/#{func}"
|
||||||
end
|
end
|
||||||
@ -22,6 +22,7 @@ module Sass::Script::Functions
|
|||||||
include Compass::SassExtensions::Functions::Lists
|
include Compass::SassExtensions::Functions::Lists
|
||||||
include Compass::SassExtensions::Functions::Colors
|
include Compass::SassExtensions::Functions::Colors
|
||||||
include Compass::SassExtensions::Functions::Trig
|
include Compass::SassExtensions::Functions::Trig
|
||||||
|
include Compass::SassExtensions::Functions::Sprites
|
||||||
end
|
end
|
||||||
|
|
||||||
# Wierd that this has to be re-included to pick up sub-modules. Ruby bug?
|
# Wierd that this has to be re-included to pick up sub-modules. Ruby bug?
|
||||||
|
@ -13,17 +13,6 @@ module Compass::SassExtensions::Functions::ImageSize
|
|||||||
Sass::Script::Number.new(height, ["px"])
|
Sass::Script::Number.new(height, ["px"])
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
def real_path(image_file)
|
|
||||||
path = image_file.value
|
|
||||||
# Compute the real path to the image on the file stystem if the images_dir is set.
|
|
||||||
if Compass.configuration.images_path
|
|
||||||
File.join(Compass.configuration.images_path, path)
|
|
||||||
else
|
|
||||||
File.join(Compass.configuration.project_path, path)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class ImageProperties
|
class ImageProperties
|
||||||
def initialize(file)
|
def initialize(file)
|
||||||
@file = file
|
@file = file
|
||||||
@ -55,6 +44,17 @@ private
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def real_path(image_file)
|
||||||
|
path = image_file.value
|
||||||
|
# Compute the real path to the image on the file stystem if the images_dir is set.
|
||||||
|
if Compass.configuration.images_path
|
||||||
|
File.join(Compass.configuration.images_path, path)
|
||||||
|
else
|
||||||
|
File.join(Compass.configuration.project_path, path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class JPEG
|
class JPEG
|
||||||
attr_reader :width, :height, :bits
|
attr_reader :width, :height, :bits
|
||||||
|
|
||||||
|
324
lib/compass/sass_extensions/functions/sprites.rb
Normal file
324
lib/compass/sass_extensions/functions/sprites.rb
Normal file
@ -0,0 +1,324 @@
|
|||||||
|
require 'chunky_png'
|
||||||
|
|
||||||
|
module Compass::SassExtensions::Functions::Sprites
|
||||||
|
ZERO = Sass::Script::Number::new(0)
|
||||||
|
|
||||||
|
# Provides a consistent interface for getting a variable in ruby
|
||||||
|
# from a keyword argument hash that accounts for underscores/dash equivalence
|
||||||
|
# and allows the caller to pass a symbol instead of a string.
|
||||||
|
module VariableReader
|
||||||
|
def get_var(variable_name)
|
||||||
|
self[variable_name.to_s.gsub(/-/,"_")]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class SpriteMap < Sass::Script::Literal
|
||||||
|
|
||||||
|
attr_accessor :image_names, :path, :name, :options
|
||||||
|
attr_accessor :images, :width, :height
|
||||||
|
|
||||||
|
def self.from_uri(uri, context, kwargs)
|
||||||
|
path, name = Compass::Sprites.path_and_name(uri.value)
|
||||||
|
new(Compass::Sprites.discover_sprites(uri.value), path, name, context, kwargs)
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(image_names, path, name, context, options)
|
||||||
|
@image_names, @path, @name, @options = image_names, path, name, options
|
||||||
|
@images = nil
|
||||||
|
@width = nil
|
||||||
|
@height = nil
|
||||||
|
@evaluation_context = context
|
||||||
|
validate!
|
||||||
|
compute_image_metadata!
|
||||||
|
end
|
||||||
|
|
||||||
|
def sprite_names
|
||||||
|
image_names.map{|f| Compass::Sprites.sprite_name(f) }
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# Calculates the overal image dimensions
|
||||||
|
# collects image sizes and input parameters for each sprite
|
||||||
|
def compute_image_metadata!
|
||||||
|
@images = []
|
||||||
|
@width = 0
|
||||||
|
image_names.each do |file|
|
||||||
|
relative_file = file.gsub(Compass.configuration.images_path+"/", "")
|
||||||
|
width, height = Compass::SassExtensions::Functions::ImageSize::ImageProperties.new(file).size
|
||||||
|
sprite_name = Compass::Sprites.sprite_name(relative_file)
|
||||||
|
@width = [@width, width].max
|
||||||
|
@images << {
|
||||||
|
:name => sprite_name,
|
||||||
|
:file => file,
|
||||||
|
:relative_file => relative_file,
|
||||||
|
:height => height,
|
||||||
|
:width => width,
|
||||||
|
:repeat => repeat_for(sprite_name),
|
||||||
|
:spacing => spacing_for(sprite_name),
|
||||||
|
:position => position_for(sprite_name)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
@images.each_with_index do |image, index|
|
||||||
|
if index == 0
|
||||||
|
image[:top] = 0
|
||||||
|
else
|
||||||
|
last_image = @images[index-1]
|
||||||
|
image[:top] = last_image[:top] + last_image[:height] + [image[:spacing], last_image[:spacing]].max
|
||||||
|
end
|
||||||
|
if image[:position].unit_str == "%"
|
||||||
|
image[:left] = (@width - image[:width]) * (image[:position].value / 100)
|
||||||
|
else
|
||||||
|
image[:left] = image[:position].value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
@height = @images.last[:top] + @images.last[:height]
|
||||||
|
end
|
||||||
|
|
||||||
|
def position_for(name)
|
||||||
|
options.get_var("#{name}-position") || options.get_var("position") || Sass::Script::Number.new(0, ["px"])
|
||||||
|
end
|
||||||
|
|
||||||
|
def repeat_for(name)
|
||||||
|
if (var = options.get_var("#{name}-repeat"))
|
||||||
|
var.value
|
||||||
|
elsif (var = options.get_var("repeat"))
|
||||||
|
var.value
|
||||||
|
else
|
||||||
|
"no-repeat"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def spacing_for(name)
|
||||||
|
(options.get_var("#{name}-spacing") ||
|
||||||
|
options.get_var("spacing") ||
|
||||||
|
ZERO).value
|
||||||
|
end
|
||||||
|
|
||||||
|
def image_for(name)
|
||||||
|
@images.detect{|img| img[:name] == name}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Calculate the size of the sprite
|
||||||
|
def size
|
||||||
|
[width, height]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generate a sprite image if necessary
|
||||||
|
def generate
|
||||||
|
if generation_required?
|
||||||
|
save!(construct_sprite)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def generation_required?
|
||||||
|
!File.exists?(filename) || outdated?
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns a PNG object
|
||||||
|
def construct_sprite
|
||||||
|
output_png = 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]
|
||||||
|
else
|
||||||
|
x = image[:left] - (image[:left] / image[:width]).ceil * image[:width]
|
||||||
|
while x < width do
|
||||||
|
output_png.replace input_png, x, image[:top]
|
||||||
|
x += image[:width]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
output_png
|
||||||
|
end
|
||||||
|
|
||||||
|
# The on-the-disk filename of the sprite
|
||||||
|
def filename
|
||||||
|
File.join(Compass.configuration.images_path, "#{path}.png")
|
||||||
|
end
|
||||||
|
|
||||||
|
# saves the sprite for later retrieval
|
||||||
|
def save!(output_png)
|
||||||
|
output_png.save filename
|
||||||
|
end
|
||||||
|
|
||||||
|
# All the full-path filenames involved in this sprite
|
||||||
|
def image_filenames
|
||||||
|
image_names.map do |image_name|
|
||||||
|
File.join(Compass.configuration.images_path, image_name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Checks whether this sprite is outdated
|
||||||
|
def outdated?
|
||||||
|
last_update = self.mtime
|
||||||
|
image_filenames.each do |image|
|
||||||
|
return true if File.mtime(image) > last_update
|
||||||
|
end
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def mtime
|
||||||
|
File.mtime(filename)
|
||||||
|
end
|
||||||
|
|
||||||
|
def inspect
|
||||||
|
to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s(options = self.options)
|
||||||
|
sprite_url(self).value
|
||||||
|
end
|
||||||
|
|
||||||
|
def respond_to?(meth)
|
||||||
|
super || @evaluation_context.respond_to?(meth)
|
||||||
|
end
|
||||||
|
|
||||||
|
def method_missing(meth, *args, &block)
|
||||||
|
if @evaluation_context.respond_to?(meth)
|
||||||
|
@evaluation_context.send(meth, *args, &block)
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
# Creates a SpriteMap object. A sprite map, when used in a property is the same
|
||||||
|
# as calling sprite-url. So the following background properties are equivalent:
|
||||||
|
#
|
||||||
|
# $icons: sprite-map("icons/*.png");
|
||||||
|
# background: sprite-url($icons) no-repeat;
|
||||||
|
# background: $icons no-repeat;
|
||||||
|
#
|
||||||
|
# The sprite map object will generate the sprite map image, if necessary,
|
||||||
|
# the first time it is converted to a url. Simply constructing it has no side-effects.
|
||||||
|
def sprite_map(glob, kwargs = {})
|
||||||
|
kwargs.extend VariableReader
|
||||||
|
SpriteMap.from_uri(glob, self, kwargs)
|
||||||
|
end
|
||||||
|
Sass::Script::Functions.declare :sprite_map, [:glob], :var_kwargs => true
|
||||||
|
|
||||||
|
# Returns the image and background position for use in a single shorthand property:
|
||||||
|
#
|
||||||
|
# $icons: sprite-map("icons/*.png"); // contains icons/new.png among others.
|
||||||
|
# background: sprite($icons, new) no-repeat;
|
||||||
|
#
|
||||||
|
# Becomes:
|
||||||
|
#
|
||||||
|
# background: url('/images/icons.png?12345678') 0 -24px no-repeat;
|
||||||
|
def sprite(map, sprite, offset_x = ZERO, offset_y = ZERO)
|
||||||
|
unless map.is_a?(SpriteMap)
|
||||||
|
missing_sprite!("sprite")
|
||||||
|
end
|
||||||
|
unless sprite.is_a?(Sass::Script::String)
|
||||||
|
raise Sass::SyntaxError, %Q(The second argument to sprite() must be a sprite name. See http://beta.compass-style.org/help/tutorials/spriting/ for more information.)
|
||||||
|
end
|
||||||
|
url = sprite_url(map)
|
||||||
|
position = sprite_position(map, sprite, offset_x, offset_y)
|
||||||
|
Sass::Script::List.new([url] + position.value, :space)
|
||||||
|
end
|
||||||
|
Sass::Script::Functions.declare :sprite, [:map, :sprite]
|
||||||
|
Sass::Script::Functions.declare :sprite, [:map, :sprite, :offset_x]
|
||||||
|
Sass::Script::Functions.declare :sprite, [:map, :sprite, :offset_x, :offset_y]
|
||||||
|
|
||||||
|
# Returns the name of a sprite map
|
||||||
|
# The name is derived from the folder than contains the sprites.
|
||||||
|
def sprite_map_name(map)
|
||||||
|
unless map.is_a?(SpriteMap)
|
||||||
|
missing_sprite!("sprite-map-name")
|
||||||
|
end
|
||||||
|
Sass::Script::String.new(map.name)
|
||||||
|
end
|
||||||
|
Sass::Script::Functions.declare :sprite_name, [:sprite]
|
||||||
|
|
||||||
|
# Returns the path to the original image file for the sprite with the given name
|
||||||
|
def sprite_file(map, sprite)
|
||||||
|
unless map.is_a?(SpriteMap)
|
||||||
|
missing_sprite!("sprite-file")
|
||||||
|
end
|
||||||
|
if image = map.image_for(sprite.value)
|
||||||
|
Sass::Script::String.new(image[:relative_file])
|
||||||
|
else
|
||||||
|
missing_image!(map, sprite)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Sass::Script::Functions.declare :sprite_file, [:map, :sprite]
|
||||||
|
|
||||||
|
# Returns a url to the sprite image.
|
||||||
|
def sprite_url(map)
|
||||||
|
unless map.is_a?(SpriteMap)
|
||||||
|
missing_sprite!("sprite-url")
|
||||||
|
end
|
||||||
|
map.generate
|
||||||
|
image_url(Sass::Script::String.new("#{map.path}.png"))
|
||||||
|
end
|
||||||
|
Sass::Script::Functions.declare :sprite_url, [:map]
|
||||||
|
|
||||||
|
# Returns the position for the original image in the sprite.
|
||||||
|
# This is suitable for use as a value to background-position:
|
||||||
|
#
|
||||||
|
# $icons: sprite-map("icons/*.png");
|
||||||
|
# background-position: sprite-position($icons, new);
|
||||||
|
#
|
||||||
|
# Might generate something like:
|
||||||
|
#
|
||||||
|
# background-position: 0 -34px;
|
||||||
|
#
|
||||||
|
# You can adjust the background relative to this position by passing values for
|
||||||
|
# `$offset-x` and `$offset-y`:
|
||||||
|
#
|
||||||
|
# $icons: sprite-map("icons/*.png");
|
||||||
|
# background-position: sprite-position($icons, new, 3px, -2px);
|
||||||
|
#
|
||||||
|
# Would change the above output to:
|
||||||
|
#
|
||||||
|
# background-position: 3px -36px;
|
||||||
|
def sprite_position(map, sprite = nil, offset_x = ZERO, offset_y = ZERO)
|
||||||
|
unless map.is_a?(SpriteMap)
|
||||||
|
missing_sprite!("sprite-position")
|
||||||
|
end
|
||||||
|
unless sprite && sprite.is_a?(Sass::Script::String)
|
||||||
|
raise Sass::SyntaxError, %Q(The second argument to sprite-position must be a sprite name. See http://beta.compass-style.org/help/tutorials/spriting/ for more information.)
|
||||||
|
end
|
||||||
|
image = map.image_for(sprite.value)
|
||||||
|
unless image
|
||||||
|
missing_image!(map, sprite)
|
||||||
|
end
|
||||||
|
if offset_x.unit_str == "%"
|
||||||
|
x = offset_x # CE: Shouldn't this be a percentage of the total width?
|
||||||
|
else
|
||||||
|
x = offset_x.value - image[:left]
|
||||||
|
x = Sass::Script::Number.new(x, x == 0 ? [] : ["px"])
|
||||||
|
end
|
||||||
|
y = offset_y.value - image[:top]
|
||||||
|
y = Sass::Script::Number.new(y, y == 0 ? [] : ["px"])
|
||||||
|
Sass::Script::List.new([x, y],:space)
|
||||||
|
end
|
||||||
|
Sass::Script::Functions.declare :sprite_position, [:map]
|
||||||
|
Sass::Script::Functions.declare :sprite_position, [:map, :sprite]
|
||||||
|
Sass::Script::Functions.declare :sprite_position, [:map, :sprite, :offset_x]
|
||||||
|
Sass::Script::Functions.declare :sprite_position, [:map, :sprite, :offset_x, :offset_y]
|
||||||
|
|
||||||
|
def sprite_image(*args)
|
||||||
|
raise Sass::SyntaxError, %Q(The sprite-image() function has been replaced by sprite(). See http://beta.compass-style.org/help/tutorials/spriting/ for more information.)
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def missing_image!(map, sprite)
|
||||||
|
raise Sass::SyntaxError, "No sprite called #{sprite} found in sprite map #{map.path}/#{map.name}. Did you mean one of: #{map.sprite_names.join(", ")}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def missing_sprite!(function_name)
|
||||||
|
raise Sass::SyntaxError, %Q(The first argument to #{function_name}() must be a sprite map. See http://beta.compass-style.org/help/tutorials/spriting/ for more information.)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@ -6,7 +6,7 @@ module Sass
|
|||||||
visitor.visit(self)
|
visitor.visit(self)
|
||||||
visitor.down(self) if children.any? and visitor.respond_to?(:down)
|
visitor.down(self) if children.any? and visitor.respond_to?(:down)
|
||||||
if is_a?(ImportNode) && visitor.import?(self)
|
if is_a?(ImportNode) && visitor.import?(self)
|
||||||
root = Sass::Files.tree_for(import, @options)
|
root = Sass::Engine.for_file(import, @options).to_tree
|
||||||
imported_children = root.children
|
imported_children = root.children
|
||||||
end
|
end
|
||||||
|
|
||||||
|
122
lib/compass/sprites.rb
Normal file
122
lib/compass/sprites.rb
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
module Compass
|
||||||
|
class Sprites < Sass::Importers::Base
|
||||||
|
attr_accessor :name
|
||||||
|
attr_accessor :path
|
||||||
|
|
||||||
|
class << self
|
||||||
|
def path_and_name(uri)
|
||||||
|
if uri =~ %r{((.+/)?(.+))/(.+?)\.png}
|
||||||
|
[$1, $3, $4]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def discover_sprites(uri)
|
||||||
|
glob = File.join(Compass.configuration.images_path, uri)
|
||||||
|
Dir.glob(glob).sort
|
||||||
|
end
|
||||||
|
|
||||||
|
def sprite_name(file)
|
||||||
|
File.basename(file, '.png')
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_relative(*args)
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def find(uri, options)
|
||||||
|
if uri =~ /\.png$/
|
||||||
|
self.path, self.name = Compass::Sprites.path_and_name(uri)
|
||||||
|
options.merge! :filename => name, :syntax => :scss, :importer => self
|
||||||
|
sprite_files = Compass::Sprites.discover_sprites(uri)
|
||||||
|
image_names = sprite_files.map {|i| Compass::Sprites.sprite_name(i) }
|
||||||
|
Sass::Engine.new(content_for_images(uri, name, image_names), options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def content_for_images(uri, name, images)
|
||||||
|
<<-SCSS
|
||||||
|
@import "compass/utilities/sprites/base";
|
||||||
|
|
||||||
|
// General Sprite Defaults
|
||||||
|
// You can override them before you import this file.
|
||||||
|
$#{name}-sprite-base-class: ".#{name}-sprite" !default;
|
||||||
|
$#{name}-sprite-dimensions: false !default;
|
||||||
|
$#{name}-position: 0% !default;
|
||||||
|
$#{name}-spacing: 0 !default;
|
||||||
|
$#{name}-repeat: no-repeat !default;
|
||||||
|
|
||||||
|
// These variables control the generated sprite output
|
||||||
|
// You can override them selectively before you import this file.
|
||||||
|
#{images.map do |sprite_name|
|
||||||
|
<<-SCSS
|
||||||
|
$#{name}-#{sprite_name}-position: $#{name}-position !default;
|
||||||
|
$#{name}-#{sprite_name}-spacing: $#{name}-spacing !default;
|
||||||
|
$#{name}-#{sprite_name}-repeat: $#{name}-repeat !default;
|
||||||
|
SCSS
|
||||||
|
end.join}
|
||||||
|
|
||||||
|
$#{name}-sprites: sprite-map("#{uri}",
|
||||||
|
#{images.map do |sprite_name|
|
||||||
|
%Q{ $#{sprite_name}-position: $#{name}-#{sprite_name}-position,
|
||||||
|
$#{sprite_name}-spacing: $#{name}-#{sprite_name}-spacing,
|
||||||
|
$#{sprite_name}-repeat: $#{name}-#{sprite_name}-repeat}
|
||||||
|
end.join(",\n")});
|
||||||
|
|
||||||
|
// All sprites should extend this class
|
||||||
|
// The #{name}-sprite mixin will do so for you.
|
||||||
|
\#{$#{name}-sprite-base-class} {
|
||||||
|
background: $#{name}-sprites no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use this to set the dimensions of an element
|
||||||
|
// based on the size of the original image.
|
||||||
|
@mixin #{name}-sprite-dimensions($name) {
|
||||||
|
@include sprite-dimensions($#{name}-sprites, $name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the background position to display the sprite.
|
||||||
|
@mixin #{name}-sprite-position($name, $offset-x: 0, $offset-y: 0) {
|
||||||
|
@include sprite-position($#{name}-sprites, $name, $offset-x, $offset-y)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extends the sprite base class and set the background position for the desired sprite.
|
||||||
|
// It will also apply the image dimensions if $dimensions is true.
|
||||||
|
@mixin #{name}-sprite($name, $dimensions: $#{name}-sprite-dimensions, $offset-x: 0, $offset-y: 0) {
|
||||||
|
@extend \#{$#{name}-sprite-base-class};
|
||||||
|
@include sprite($#{name}-sprites, $name, $dimensions, $offset-x, $offset-y)
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin #{name}-sprites($sprite-names, $dimensions: $#{name}-sprite-dimensions) {
|
||||||
|
@include sprites($#{name}-sprites, $sprite-names, $#{name}-sprite-base-class, $dimensions)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates a class for each sprited image.
|
||||||
|
@mixin all-#{name}-sprites($dimensions: $#{name}-sprite-dimensions) {
|
||||||
|
@include #{name}-sprites(#{images.join(" ")}, $dimensions);
|
||||||
|
}
|
||||||
|
SCSS
|
||||||
|
end
|
||||||
|
|
||||||
|
def key(uri, options)
|
||||||
|
[self.class.name + ":" + File.dirname(File.expand_path(uri)),
|
||||||
|
File.basename(uri)]
|
||||||
|
end
|
||||||
|
|
||||||
|
def mtime(uri, options)
|
||||||
|
Compass.quick_cache("mtime:#{uri}") do
|
||||||
|
self.path, self.name = Compass::Sprites.path_and_name(uri)
|
||||||
|
glob = File.join(Compass.configuration.images_path, uri)
|
||||||
|
Dir.glob(glob).inject(Time.at(0)) do |max_time, file|
|
||||||
|
(t = File.mtime(file)) > max_time ? t : max_time
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
""
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
7
spec/spec_helper.rb
Normal file
7
spec/spec_helper.rb
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
||||||
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
||||||
|
|
||||||
|
require 'rubygems'
|
||||||
|
require 'compass'
|
||||||
|
require 'rspec'
|
||||||
|
require 'rspec/autorun'
|
390
spec/sprites_spec.rb
Normal file
390
spec/sprites_spec.rb
Normal file
@ -0,0 +1,390 @@
|
|||||||
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
||||||
|
require "compass/sprites"
|
||||||
|
require 'digest/md5'
|
||||||
|
|
||||||
|
describe Compass::Sprites 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
|
||||||
|
Compass.configuration.images_path = @images_tmp_path
|
||||||
|
Compass.configure_sass_plugin!
|
||||||
|
end
|
||||||
|
|
||||||
|
after :each do
|
||||||
|
FileUtils.rm_r @images_tmp_path
|
||||||
|
end
|
||||||
|
|
||||||
|
def image_size(file)
|
||||||
|
IO.read(File.join(@images_tmp_path, file))[0x10..0x18].unpack('NN')
|
||||||
|
end
|
||||||
|
|
||||||
|
def image_md5(file)
|
||||||
|
md5 = Digest::MD5.new
|
||||||
|
md5.update IO.read(File.join(@images_tmp_path, 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
|
||||||
|
|
||||||
|
# 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.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 == 'e8cd71d546aae6951ea44cb01af35820'
|
||||||
|
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.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.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.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.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.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.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.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.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.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 == 'b61700e6d402d9df5f3820b73479f371'
|
||||||
|
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.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 == 'b61700e6d402d9df5f3820b73479f371'
|
||||||
|
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.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 == '0187306f3858136feee87d3017e7f307'
|
||||||
|
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.png') 0 -10px no-repeat;
|
||||||
|
}
|
||||||
|
CSS
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
BIN
spec/test_project/public/images/squares/ten-by-ten.png
Normal file
BIN
spec/test_project/public/images/squares/ten-by-ten.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
BIN
spec/test_project/public/images/squares/twenty-by-twenty.png
Normal file
BIN
spec/test_project/public/images/squares/twenty-by-twenty.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
Loading…
Reference in New Issue
Block a user