Don't rely on reading the environment within the sprite code. Instead accept variable keyword args.
This commit is contained in:
parent
043d082033
commit
40d32606bb
@ -3,16 +3,32 @@ require 'chunky_png'
|
|||||||
module Compass::SassExtensions::Functions::Sprites
|
module Compass::SassExtensions::Functions::Sprites
|
||||||
SASS_NULL = Sass::Script::Number::new(0)
|
SASS_NULL = Sass::Script::Number::new(0)
|
||||||
|
|
||||||
def generate_sprite_image(uri)
|
# 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
|
||||||
|
|
||||||
|
def generate_sprite_image(uri, kwargs = {})
|
||||||
|
kwargs.extend VariableReader
|
||||||
path, name = Compass::Sprites.path_and_name(uri.value)
|
path, name = Compass::Sprites.path_and_name(uri.value)
|
||||||
last_spacing = 0
|
last_spacing = 0
|
||||||
width = 0
|
width = 0
|
||||||
height = 0
|
height = 0
|
||||||
|
|
||||||
|
# Get image metadata
|
||||||
|
Compass::Sprites.discover_sprites(uri.value).each do |file|
|
||||||
|
Compass::Sprites.compute_image_metadata! file, path, name
|
||||||
|
end
|
||||||
|
|
||||||
images = Compass::Sprites.sprites(path, name)
|
images = Compass::Sprites.sprites(path, name)
|
||||||
|
|
||||||
# Calculation
|
# Calculation
|
||||||
images.each do |image|
|
images.each do |image|
|
||||||
current_spacing = number_from_var("#{name}-#{image[:name]}-spacing")
|
current_spacing = number_from_var(kwargs, "#{image[:name]}-spacing", 0)
|
||||||
if height > 0
|
if height > 0
|
||||||
height += [current_spacing, last_spacing].max
|
height += [current_spacing, last_spacing].max
|
||||||
end
|
end
|
||||||
@ -27,14 +43,18 @@ module Compass::SassExtensions::Functions::Sprites
|
|||||||
images.each do |image|
|
images.each do |image|
|
||||||
input_png = ChunkyPNG::Image.from_file(image[:file])
|
input_png = ChunkyPNG::Image.from_file(image[:file])
|
||||||
|
|
||||||
position = environment.var("#{name}-#{image[:name]}-position")
|
position = kwargs.get_var("#{image[:name]}-position") || Sass::Script::Number.new(0, ["%"])
|
||||||
if position.unit_str == "%"
|
if position.unit_str == "%"
|
||||||
image[:x] = (width - image[:width]) * (position.value / 100)
|
image[:x] = (width - image[:width]) * (position.value / 100)
|
||||||
else
|
else
|
||||||
image[:x] = position.value
|
image[:x] = position.value
|
||||||
end
|
end
|
||||||
|
|
||||||
repeat = environment.var("#{name}-#{image[:name]}-repeat").to_s
|
repeat = if (var = kwargs.get_var("#{image[:name]}-repeat"))
|
||||||
|
var.value
|
||||||
|
else
|
||||||
|
"no-repeat"
|
||||||
|
end
|
||||||
if repeat == "no-repeat"
|
if repeat == "no-repeat"
|
||||||
output_png.replace input_png, image[:x], image[:y]
|
output_png.replace input_png, image[:x], image[:y]
|
||||||
else
|
else
|
||||||
@ -49,6 +69,7 @@ module Compass::SassExtensions::Functions::Sprites
|
|||||||
|
|
||||||
sprite_url(uri)
|
sprite_url(uri)
|
||||||
end
|
end
|
||||||
|
Sass::Script::Functions.declare :generate_sprite_image, [:uri], :var_kwargs => true
|
||||||
|
|
||||||
def sprite_image(uri, x_shift = SASS_NULL, y_shift = SASS_NULL, depricated_1 = nil, depricated_2 = nil)
|
def sprite_image(uri, x_shift = SASS_NULL, y_shift = SASS_NULL, depricated_1 = nil, depricated_2 = nil)
|
||||||
check_spacing_deprecation uri, depricated_1, depricated_2
|
check_spacing_deprecation uri, depricated_1, depricated_2
|
||||||
@ -80,11 +101,12 @@ module Compass::SassExtensions::Functions::Sprites
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def number_from_var(var_name)
|
def number_from_var(kwargs, var_name, default_value)
|
||||||
if var = environment.var(var_name)
|
if number = kwargs.get_var(var_name)
|
||||||
var.value
|
assert_type number, :Number
|
||||||
|
number.value
|
||||||
else
|
else
|
||||||
0
|
default_value
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -28,6 +28,25 @@ module Compass
|
|||||||
raise Compass::Error, %Q(`@import` statement missing. Please add `@import "#{path}/*.png";`.)
|
raise Compass::Error, %Q(`@import` statement missing. Please add `@import "#{path}/*.png";`.)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def discover_sprites(uri)
|
||||||
|
glob = File.join(Compass.configuration.images_path, uri)
|
||||||
|
Dir.glob(glob).sort
|
||||||
|
end
|
||||||
|
|
||||||
|
def compute_image_metadata!(file, path, name)
|
||||||
|
width, height = Compass::SassExtensions::Functions::ImageSize::ImageProperties.new(file).size
|
||||||
|
sprite_name = File.basename(file, '.png');
|
||||||
|
unless sprite_name =~ /\A#{Sass::SCSS::RX::IDENT}\Z/
|
||||||
|
raise Sass::SyntaxError, "#{sprite_name} must be a legal css identifier"
|
||||||
|
end
|
||||||
|
sprites(path, name, true) << {
|
||||||
|
:name => sprite_name,
|
||||||
|
:file => file,
|
||||||
|
:height => height,
|
||||||
|
:width => width
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def images
|
def images
|
||||||
@ -37,68 +56,78 @@ module Compass
|
|||||||
def find(uri, options)
|
def find(uri, options)
|
||||||
if uri =~ /\.png$/
|
if uri =~ /\.png$/
|
||||||
self.path, self.name = Compass::Sprites.path_and_name(uri)
|
self.path, self.name = Compass::Sprites.path_and_name(uri)
|
||||||
glob = File.join(Compass.configuration.images_path, uri)
|
|
||||||
Dir.glob(glob).sort.each do |file|
|
|
||||||
width, height = Compass::SassExtensions::Functions::ImageSize::ImageProperties.new(file).size
|
|
||||||
images << {
|
|
||||||
:name => File.basename(file, '.png'),
|
|
||||||
:file => file,
|
|
||||||
:height => height,
|
|
||||||
:width => width
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
contents = <<-SCSS
|
|
||||||
$#{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;
|
|
||||||
|
|
||||||
#{images.map do |sprite|
|
|
||||||
<<-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}-sprite-base-class} {
|
|
||||||
background: generate-sprite-image("#{uri}") no-repeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin #{name}-sprite-dimensions($sprite) {
|
|
||||||
height: image-height("#{name}/\#{$sprite}.png");
|
|
||||||
width: image-width("#{name}/\#{$sprite}.png");
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin #{name}-sprite-position($sprite, $x: 0, $y: 0) {
|
|
||||||
background-position: sprite-position("#{path}/\#{$sprite}.png", $x, $y);
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin #{name}-sprite($sprite, $dimensions: $#{name}-sprite-dimensions, $x: 0, $y: 0) {
|
|
||||||
@extend \#{$#{name}-sprite-base-class};
|
|
||||||
@include #{name}-sprite-position($sprite, $x, $y);
|
|
||||||
@if $dimensions {
|
|
||||||
@include #{name}-sprite-dimensions($sprite);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin all-#{name}-sprites {
|
|
||||||
#{images.map do |sprite|
|
|
||||||
<<-SCSS
|
|
||||||
.#{name}-#{sprite[:name]} {
|
|
||||||
@include #{name}-sprite("#{sprite[:name]}");
|
|
||||||
}
|
|
||||||
SCSS
|
|
||||||
end.join}
|
|
||||||
}
|
|
||||||
SCSS
|
|
||||||
options.merge! :filename => name, :syntax => :scss, :importer => self
|
options.merge! :filename => name, :syntax => :scss, :importer => self
|
||||||
Sass::Engine.new(contents, options)
|
image_names = Compass::Sprites.discover_sprites(uri).map{|i| File.basename(i, '.png')}
|
||||||
|
Sass::Engine.new(content_for_images(uri, name, image_names), options)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def content_for_images(uri, name, images)
|
||||||
|
<<-SCSS
|
||||||
|
// 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}
|
||||||
|
|
||||||
|
// All sprites should extend this class
|
||||||
|
// The #{name}-sprite mixin will do so for you.
|
||||||
|
\#{$#{name}-sprite-base-class} {
|
||||||
|
background: generate-sprite-image("#{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")}) no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use this to set the dimensions of an element
|
||||||
|
// based on the size of the original image.
|
||||||
|
@mixin #{name}-sprite-dimensions($sprite) {
|
||||||
|
height: image-height("#{name}/\#{$sprite}.png");
|
||||||
|
width: image-width("#{name}/\#{$sprite}.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the background position to display the sprite.
|
||||||
|
@mixin #{name}-sprite-position($sprite, $x: 0, $y: 0) {
|
||||||
|
background-position: sprite-position("#{path}/\#{$sprite}.png", $x, $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($sprite, $dimensions: $#{name}-sprite-dimensions, $x: 0, $y: 0) {
|
||||||
|
@extend \#{$#{name}-sprite-base-class};
|
||||||
|
@include #{name}-sprite-position($sprite, $x, $y);
|
||||||
|
@if $dimensions {
|
||||||
|
@include #{name}-sprite-dimensions($sprite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates a class for each sprited image.
|
||||||
|
@mixin all-#{name}-sprites {
|
||||||
|
#{images.map do |sprite_name|
|
||||||
|
<<-SCSS
|
||||||
|
.#{name}-#{sprite_name} {
|
||||||
|
@include #{name}-sprite("#{sprite_name}");
|
||||||
|
}
|
||||||
|
SCSS
|
||||||
|
end.join}
|
||||||
|
}
|
||||||
|
SCSS
|
||||||
|
end
|
||||||
|
|
||||||
def key(uri, options)
|
def key(uri, options)
|
||||||
[self.class.name + ":" + File.dirname(File.expand_path(uri)),
|
[self.class.name + ":" + File.dirname(File.expand_path(uri)),
|
||||||
File.basename(uri)]
|
File.basename(uri)]
|
||||||
|
Loading…
Reference in New Issue
Block a user