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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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