compass 0.11.beta.4 → 0.11.beta.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,4 +2,4 @@
2
2
  :major: 0
3
3
  :minor: 11
4
4
  :state: beta
5
- :build: 4
5
+ :build: 5
@@ -24,6 +24,19 @@
24
24
  }
25
25
  }
26
26
 
27
+ // Include the selectors for the `$sprite` given the `$map` and the
28
+ // `$full-sprite-name`
29
+ // @private
30
+ @mixin sprite_selectors($map, $sprite-name, $full-sprite-name) {
31
+ @each $selector in $sprite-selectors {
32
+ @if sprite_has_selector($map, $sprite-name, $selector) {
33
+ .#{$full-sprite-name}:#{$selector}, .#{$full-sprite-name}_#{$selector}, .#{$full-sprite-name}-#{$selector} {
34
+ @include sprite($map, "#{$sprite-name}_#{$selector}");
35
+ }
36
+ }
37
+ }
38
+ }
39
+
27
40
  // Generates a class for each space separated name in `$sprite-names`.
28
41
  // The class will be of the form .<map-name>-<sprite-name>.
29
42
  //
@@ -32,10 +45,13 @@
32
45
  // If `$dimensions` is `true`, the sprite dimensions will specified.
33
46
  @mixin sprites($map, $sprite-names, $base-class: false, $dimensions: false, $prefix: sprite-map-name($map)) {
34
47
  @each $sprite-name in $sprite-names {
35
- $full-sprite-name: if($prefix and $prefix != "", "#{$prefix}-#{$sprite-name}", $sprite-name);
36
- .#{$full-sprite-name} {
37
- @if $base-class { @extend #{$base-class}; }
38
- @include sprite($map, $sprite-name, $dimensions);
48
+ @if sprite_does_not_have_parent($map, $sprite-name) {
49
+ $full-sprite-name: "#{$prefix}-#{$sprite-name}";
50
+ .#{$full-sprite-name} {
51
+ @if $base-class { @extend #{$base-class}; }
52
+ @include sprite($map, $sprite-name, $dimensions);
53
+ }
54
+ @include sprite_selectors($map, $sprite-name, $full-sprite-name);
39
55
  }
40
56
  }
41
57
  }
@@ -24,6 +24,8 @@ $sprite-image-default-width: $sprite-default-size !default;
24
24
 
25
25
  $sprite-image-default-height: $sprite-default-size !default;
26
26
 
27
+ $sprite-selectors: hover, target, active !default;
28
+
27
29
  // Sets all the rules for a sprite from a given sprite image to show just one of the sprites.
28
30
  // To reduce duplication use a sprite-bg mixin for common properties and a sprite-select mixin for positioning.
29
31
  @mixin sprite-img($img, $col, $row: 1, $width: $sprite-image-default-width, $height: $sprite-image-default-height, $margin: $sprite-default-margin) {
@@ -1,6 +1,6 @@
1
1
  module Compass::SassExtensions::Functions::Sprites
2
2
  ZERO = Sass::Script::Number::new(0)
3
-
3
+ VALID_SELECTORS = %w(hover active target)
4
4
  # Provides a consistent interface for getting a variable in ruby
5
5
  # from a keyword argument hash that accounts for underscores/dash equivalence
6
6
  # and allows the caller to pass a symbol instead of a string.
@@ -34,9 +34,7 @@ module Compass::SassExtensions::Functions::Sprites
34
34
  #
35
35
  # background: url('/images/icons.png?12345678') 0 -24px no-repeat;
36
36
  def sprite(map, sprite, offset_x = ZERO, offset_y = ZERO)
37
- unless map.is_a?(Compass::SassExtensions::Sprites::Base)
38
- missing_sprite!("sprite")
39
- end
37
+ verify_map(map)
40
38
  unless sprite.is_a?(Sass::Script::String)
41
39
  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.)
42
40
  end
@@ -51,18 +49,15 @@ module Compass::SassExtensions::Functions::Sprites
51
49
  # Returns the name of a sprite map
52
50
  # The name is derived from the folder than contains the sprites.
53
51
  def sprite_map_name(map)
54
- unless map.is_a?(Compass::SassExtensions::Sprites::Base)
55
- missing_sprite!("sprite-map-name")
56
- end
52
+ verify_map(map, "sprite-map-name")
57
53
  Sass::Script::String.new(map.name)
58
54
  end
59
55
  Sass::Script::Functions.declare :sprite_name, [:sprite]
60
56
 
61
57
  # Returns the path to the original image file for the sprite with the given name
62
58
  def sprite_file(map, sprite)
63
- unless map.is_a?(Compass::SassExtensions::Sprites::Base)
64
- missing_sprite!("sprite-file")
65
- end
59
+ verify_map(map, "sprite")
60
+ verify_sprite(sprite)
66
61
  if image = map.image_for(sprite.value)
67
62
  Sass::Script::String.new(image.relative_file)
68
63
  else
@@ -71,11 +66,31 @@ module Compass::SassExtensions::Functions::Sprites
71
66
  end
72
67
  Sass::Script::Functions.declare :sprite_file, [:map, :sprite]
73
68
 
69
+ # Returns voolean if sprite has a parent
70
+ def sprite_does_not_have_parent(map, sprite)
71
+ verify_map map
72
+ verify_sprite sprite
73
+ Sass::Script::Bool.new map.image_for(sprite.value).parent.nil?
74
+ end
75
+
76
+ Sass::Script::Functions.declare :sprite_does_not_have_parent, [:map, :sprite]
77
+
78
+ # Returns boolean if sprite has the selector
79
+ def sprite_has_selector(map, sprite, selector)
80
+ verify_map map
81
+ verify_sprite sprite
82
+ unless VALID_SELECTORS.include?(selector.value)
83
+ raise Sass::SyntaxError, "Invalid Selctor did you mean one of: #{VALID_SELECTORS.join(', ')}"
84
+ end
85
+ Sass::Script::Bool.new map.send(:"has_#{selector.value}?", sprite)
86
+ end
87
+
88
+ Sass::Script::Functions.declare :sprite_has_selector, [:map, :sprite, :selector]
89
+
90
+
74
91
  # Returns a url to the sprite image.
75
92
  def sprite_url(map)
76
- unless map.is_a?(Compass::SassExtensions::Sprites::Base)
77
- missing_sprite!("sprite-url")
78
- end
93
+ verify_map(map, "sprite-url")
79
94
  map.generate
80
95
  image_url(Sass::Script::String.new("#{map.path}-#{map.uniqueness_hash}.png"),
81
96
  Sass::Script::Bool.new(false),
@@ -103,9 +118,7 @@ module Compass::SassExtensions::Functions::Sprites
103
118
  #
104
119
  # background-position: 3px -36px;
105
120
  def sprite_position(map, sprite = nil, offset_x = ZERO, offset_y = ZERO)
106
- unless map.is_a?(Compass::SassExtensions::Sprites::Base)
107
- missing_sprite!("sprite-position")
108
- end
121
+ verify_map(map, "sprite-position")
109
122
  unless sprite && sprite.is_a?(Sass::Script::String)
110
123
  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.)
111
124
  end
@@ -134,6 +147,18 @@ module Compass::SassExtensions::Functions::Sprites
134
147
 
135
148
  protected
136
149
 
150
+ def verify_map(map, error = "sprite")
151
+ unless map.is_a?(Compass::SassExtensions::Sprites::Base)
152
+ missing_sprite!(error)
153
+ end
154
+ end
155
+
156
+ def verify_sprite(sprite)
157
+ unless sprite.is_a?(Sass::Script::String)
158
+ 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.)
159
+ end
160
+ end
161
+
137
162
  def missing_image!(map, sprite)
138
163
  raise Sass::SyntaxError, "No sprite called #{sprite} found in sprite map #{map.path}/#{map.name}. Did you mean one of: #{map.sprite_names.join(", ")}"
139
164
  end
@@ -2,6 +2,10 @@ module Compass
2
2
  module SassExtensions
3
3
  module Sprites
4
4
  class Base < Sass::Script::Literal
5
+
6
+
7
+ # Initialize a new aprite object from a relative file path
8
+ # the path is relative to the <tt>images_path</tt> confguration option
5
9
  def self.from_uri(uri, context, kwargs)
6
10
  sprite_map = ::Compass::SpriteMap.new(uri.value, {})
7
11
 
@@ -10,7 +14,8 @@ module Compass
10
14
  end
11
15
  new(sprites, sprite_map.path, sprite_map.name, context, kwargs)
12
16
  end
13
-
17
+
18
+ # Loads the sprite engine
14
19
  def require_engine!
15
20
  self.class.send(:include, eval("::Compass::SassExtensions::Sprites::#{modulize}Engine"))
16
21
  end
@@ -41,13 +46,15 @@ module Compass
41
46
 
42
47
  # Calculates the overal image dimensions
43
48
  # collects image sizes and input parameters for each sprite
49
+ # Calculates the height
44
50
  def compute_image_metadata!
45
51
  @width = 0
46
52
  init_images
47
53
  compute_image_positions!
48
54
  @height = @images.last.top + @images.last.height
49
55
  end
50
-
56
+
57
+ # Creates the Sprite::Image objects for each image and calculates the width
51
58
  def init_images
52
59
  @images = image_names.collect do |relative_file|
53
60
  image = Compass::SassExtensions::Sprites::Image.new(self, relative_file, options)
@@ -66,27 +73,34 @@ module Compass
66
73
  image.top = last_image.top + last_image.height + [image.spacing, last_image.spacing].max
67
74
  end
68
75
  end
69
-
76
+
77
+ # Fetches the Sprite::Image object for the supplied name
70
78
  def image_for(name)
71
79
  @images.detect { |img| img.name == name}
72
80
  end
73
81
 
82
+ # Returns true if the image name has a hover selector image
74
83
  def has_hover?(name)
75
84
  !image_for("#{name}_hover").nil?
76
85
  end
77
86
 
87
+ # Returns true if the image name has a target selector image
78
88
  def has_target?(name)
79
89
  !image_for("#{name}_target").nil?
80
90
  end
81
91
 
92
+ # Returns true if the image name has an active selector image
82
93
  def has_active?(name)
83
94
  !image_for("#{name}_active").nil?
84
95
  end
85
96
 
97
+ # Return and array of image names that make up this sprite
86
98
  def sprite_names
87
99
  image_names.map { |f| File.basename(f, '.png') }
88
100
  end
89
101
 
102
+
103
+ # Validates that the sprite_names are valid sass
90
104
  def validate!
91
105
  for sprite_name in sprite_names
92
106
  unless sprite_name =~ /\A#{Sass::SCSS::RX::IDENT}\Z/
@@ -108,11 +122,13 @@ module Compass
108
122
  Compass.configuration.run_callback(:sprite_generated, sprite_data)
109
123
  end
110
124
  end
111
-
125
+
126
+ # Does this sprite need to be generated
112
127
  def generation_required?
113
128
  !File.exists?(filename) || outdated?
114
129
  end
115
130
 
131
+ # Returns the uniqueness hash for this sprite object
116
132
  def uniqueness_hash
117
133
  @uniqueness_hash ||= begin
118
134
  sum = Digest::MD5.new
@@ -128,6 +144,7 @@ module Compass
128
144
  @uniqueness_hash
129
145
  end
130
146
 
147
+ # Saves the sprite engine
131
148
  def save!(output_png)
132
149
  saved = output_png.save filename
133
150
  Compass.configuration.run_callback(:sprite_saved, filename)
@@ -142,13 +159,14 @@ module Compass
142
159
  # Checks whether this sprite is outdated
143
160
  def outdated?
144
161
  if File.exists?(filename)
145
- return @images.map(&:mtime).any? { |mtime| mtime > self.mtime }
162
+ return @images.map(&:mtime).any? { |imtime| imtime.to_i > self.mtime.to_i }
146
163
  end
147
164
  true
148
165
  end
149
166
 
167
+ # Mtime of the sprite file
150
168
  def mtime
151
- File.mtime(filename)
169
+ @mtime ||= File.mtime(filename)
152
170
  end
153
171
 
154
172
  def inspect
@@ -11,7 +11,6 @@ module Compass
11
11
 
12
12
  # Returns a PNG object
13
13
  def construct_sprite
14
- #require_png_library!
15
14
  output_png = ChunkyPNG::Image.new(width, height, ChunkyPNG::Color::TRANSPARENT)
16
15
  images.each do |image|
17
16
  input_png = ChunkyPNG::Image.from_file(image.file)
@@ -2,6 +2,11 @@ module Compass
2
2
  module SassExtensions
3
3
  module Sprites
4
4
  class Image
5
+ ACTIVE = %r{[_-]active$}
6
+ TARGET = %r{[_-]target$}
7
+ HOVER = %r{[_-]hover$}
8
+ PARENT = %r{(.+)[-_](.+)$}
9
+
5
10
  attr_reader :relative_file, :options, :base
6
11
  attr_accessor :top, :left
7
12
 
@@ -9,23 +14,28 @@ module Compass
9
14
  @base, @relative_file, @options = base, relative_file, options
10
15
  @left = @top = 0
11
16
  end
12
-
17
+
18
+ # The Full path to the image
13
19
  def file
14
20
  File.join(Compass.configuration.images_path, relative_file)
15
21
  end
16
-
22
+
23
+ # Width of the image
17
24
  def width
18
25
  dimensions.first
19
26
  end
20
-
27
+
28
+ # Height of the image
21
29
  def height
22
30
  dimensions.last
23
31
  end
24
-
32
+
33
+ # Basename of the image
25
34
  def name
26
35
  File.basename(relative_file, '.png')
27
36
  end
28
37
 
38
+ # Value of <tt> $#{name}-repeat </tt> or <tt> $repeat </tt>
29
39
  def repeat
30
40
  [ "#{name}-repeat", "repeat" ].each { |which|
31
41
  if var = options.get_var(which)
@@ -35,49 +45,69 @@ module Compass
35
45
  "no-repeat"
36
46
  end
37
47
 
48
+ # Value of <tt> $#{name}-position </tt> or <tt> $position </tt> defaults o <tt>0px</tt>
38
49
  def position
39
50
  options.get_var("#{name}-position") || options.get_var("position") || Sass::Script::Number.new(0, ["px"])
40
51
  end
41
-
52
+
53
+ # Offset within the sprite
42
54
  def offset
43
55
  (position.unitless? || position.unit_str == "px") ? position.value : 0
44
56
  end
45
-
57
+
58
+ # Spacing between this image and the next
46
59
  def spacing
47
60
  (options.get_var("#{name}-spacing") || options.get_var("spacing") || Sass::Script::Number.new(0)).value
48
61
  end
49
62
 
63
+ # MD5 hash of this file
50
64
  def digest
51
65
  Digest::MD5.file(file).hexdigest
52
66
  end
53
-
67
+
68
+ # mtime of this file
54
69
  def mtime
55
70
  File.mtime(file)
56
71
  end
57
72
 
73
+ # Is hover selector
58
74
  def hover?
59
- base.has_hover?(name)
75
+ name =~ HOVER
60
76
  end
61
77
 
78
+ # Hover selector Image object if exsists
62
79
  def hover
63
80
  base.image_for("#{name}_hover")
64
81
  end
65
82
 
83
+ # Is target selector
66
84
  def target?
67
- base.has_target?(name)
85
+ name =~ TARGET
68
86
  end
69
87
 
88
+ # Target selector Image object if exsists
70
89
  def target
71
90
  base.image_for("#{name}_target")
72
91
  end
73
92
 
93
+ # Is active selector
74
94
  def active?
75
- base.has_active?(name)
95
+ name =~ ACTIVE
76
96
  end
77
97
 
98
+ # Active selector Image object if exsists
78
99
  def active
79
100
  base.image_for("#{name}_active")
80
101
  end
102
+
103
+
104
+ def parent
105
+ if [hover?, target?, active?].any?
106
+ PARENT.match name
107
+ base.image_for($1)
108
+ end
109
+ end
110
+
81
111
 
82
112
  private
83
113
  def dimensions
@@ -2,49 +2,60 @@ module Compass
2
2
  class SpriteMap
3
3
  attr_reader :uri, :options
4
4
 
5
+
6
+ def find_relative(*args)
7
+ nil
8
+ end
9
+
5
10
  def initialize(uri, options)
6
11
  @uri, @options = uri, options
7
12
  end
8
13
 
14
+ # Name of this spite
9
15
  def name
10
16
  ensure_path_and_name!
11
17
  @name
12
18
  end
13
19
 
20
+ # The on-disk location of this sprite
14
21
  def path
15
22
  ensure_path_and_name!
16
23
  @path
17
24
  end
18
-
25
+
26
+ # Returns the Glob of image files for this sprite
19
27
  def files
20
28
  @files ||= Dir[File.join(Compass.configuration.images_path, uri)].sort
21
29
  end
22
30
 
31
+ # Returns an Array of image names without the file extension
23
32
  def sprite_names
24
33
  @sprite_names ||= files.collect { |file| File.basename(file, '.png') }
25
34
  end
26
-
35
+
36
+ # Returns the sass options for this sprite
27
37
  def sass_options
28
38
  @sass_options ||= options.merge(:filename => name, :syntax => :scss, :importer => self)
29
39
  end
30
-
31
- def mtime
32
- Compass.quick_cache("mtime:#{uri}") do
33
- files.collect { |file| File.mtime(file) }.max
34
- end
35
- end
36
-
40
+
41
+ # Returns a Sass::Engine for this sprite object
37
42
  def sass_engine
38
- Sass::Engine.new(content_for_images, options)
43
+ Sass::Engine.new(content_for_images, sass_options)
39
44
  end
40
-
41
- private
45
+
42
46
  def ensure_path_and_name!
43
- return if @path && @name
44
- uri =~ %r{((.+/)?(.+))/(.+?)\.png}
45
- @path, @name = $1, $3
47
+ @path, @name = Compass::Sprites.path_and_name(uri)
48
+ end
49
+
50
+ def key(uri, options)
51
+ Compass::Sprites.key(uri)
46
52
  end
47
53
 
54
+ def mtime(uri, options)
55
+ Compass::Sprites.mtime(uri, options)
56
+ end
57
+
58
+ # Generates the Sass for this sprite file
48
59
  def content_for_images(skip_overrides = false)
49
60
  <<-SCSS
50
61
  @import "compass/utilities/sprites/base";
@@ -94,7 +105,11 @@ $#{name}-prefix: '' !default;
94
105
  }
95
106
  SCSS
96
107
  end
97
-
108
+
109
+ # Generates the override defaults for this Sprite
110
+ # <tt>$#{name}-#{sprite_name}-position </tt>
111
+ # <tt> $#{name}-#{sprite_name}-spacing </tt>
112
+ # <tt> #{name}-#{sprite_name}-repeat: </tt>
98
113
  def generate_overrides
99
114
  content = <<-TXT
100
115
  // These variables control the generated sprite output
@@ -1,24 +1,51 @@
1
1
  module Compass
2
2
  class Sprites < Sass::Importers::Base
3
- def find_relative(*args)
4
- nil
3
+ attr_accessor :name, :path
4
+
5
+ def self.path_and_name(uri)
6
+ if uri =~ %r{((.+/)?(.+))/(.+?)\.png}
7
+ [$1, $3, $4]
8
+ end
5
9
  end
6
10
 
11
+ def self.discover_sprites(uri)
12
+ self.load_map(uri, options).files
13
+ end
14
+
15
+ def self.sprite_name(file)
16
+ File.basename(file, '.png')
17
+ end
18
+
19
+ def self.load_map(uri, options)
20
+ Compass.quick_cache("spritemap:#{uri}", 5) do
21
+ SpriteMap.new(uri, options)
22
+ end
23
+ end
24
+
25
+
26
+ # Called by the sass engine to build a new SpriteMap
7
27
  def find(uri, options)
8
28
  if uri =~ /\.png$/
9
- SpriteMap.new(uri, options).sass_engine
29
+ map = Compass::Sprites.load_map(uri, options)
30
+ self.path, self.name = map.path, map.name
31
+ return map.sass_engine
10
32
  end
11
33
  end
12
-
13
- def key(uri, options)
14
- [self.class.name + ":" + File.dirname(File.expand_path(uri)),
15
- File.basename(uri)]
34
+
35
+ # Called by the sass engine to identify the SpriteMap
36
+ def self.key(uri, options={})
37
+ [self.class.name + ":" + File.dirname(File.expand_path(uri)), File.basename(uri)]
16
38
  end
17
39
 
18
- def mtime(uri, options)
19
- SpriteMap.new(uri, options).mtime
40
+ def self.mtime(uri, options)
41
+ Compass.quick_cache("mtime:#{uri}") do
42
+ map = Compass::Sprites.load_map(uri, options)
43
+ map.files.inject(Time.at(0)) do |max_time, file|
44
+ (t = File.mtime(file)) > max_time ? t : max_time
45
+ end
46
+ end
20
47
  end
21
-
48
+
22
49
  def to_s
23
50
  ""
24
51
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: compass
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease: 5
5
- version: 0.11.beta.4
5
+ version: 0.11.beta.5
6
6
  platform: ruby
7
7
  authors:
8
8
  - Chris Eppstein
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-03-24 00:00:00 -07:00
17
+ date: 2011-03-26 00:00:00 -07:00
18
18
  default_executable: compass
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency