compass 0.11.beta.3 → 0.11.beta.4

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: 3
5
+ :build: 4
@@ -20,3 +20,10 @@ Feature: Extensions
20
20
  When I run: compass frameworks
21
21
  Then the list of frameworks includes "testing"
22
22
 
23
+ @listframeworks
24
+ Scenario: Shared extensions directory
25
+ Given I am using the existing project in test/fixtures/stylesheets/compass
26
+ And the "~/.compass/extensions" directory exists
27
+ And and I have a fake extension at ~/.compass/extensions/testing
28
+ When I run: compass frameworks
29
+ Then the list of frameworks includes "testing"
@@ -198,10 +198,10 @@ $default-skew-y : 5deg !default;
198
198
  //
199
199
  // @include transform-style( [ style ] )
200
200
  //
201
- // where `style` can be either `flat` or `preserves-3d`
202
- // browsers default to `flat`, mixin defaults to `preserves-3d`
203
- @mixin transform-style($style: preserves-3d) {
204
- @include experimental(perspective-origin, $style,
201
+ // where `style` can be either `flat` or `preserve-3d`
202
+ // browsers default to `flat`, mixin defaults to `preserve-3d`
203
+ @mixin transform-style($style: preserve-3d) {
204
+ @include experimental(transform-style, $style,
205
205
  not -moz, -webkit, not -o, not -ms, not -khtml, official
206
206
  );
207
207
  }
@@ -1,7 +1,7 @@
1
1
  module Compass
2
2
  end
3
3
 
4
- %w(dependencies util browser_support sass_extensions core_ext version errors quick_cache).each do |lib|
4
+ %w(dependencies util browser_support sass_extensions version errors quick_cache).each do |lib|
5
5
  require "compass/#{lib}"
6
6
  end
7
7
 
@@ -14,10 +14,13 @@ module Compass
14
14
  def lib_directory
15
15
  File.expand_path(File.join(File.dirname(__FILE__)))
16
16
  end
17
- module_function :base_directory, :lib_directory
17
+ def shared_extension_paths
18
+ [File.expand_path("~/.compass/extensions")]
19
+ end
20
+ module_function :base_directory, :lib_directory, :shared_extension_paths
18
21
  extend QuickCache
19
22
  end
20
23
 
21
- %w(configuration frameworks app_integration actions compiler sprites).each do |lib|
24
+ %w(configuration frameworks app_integration actions compiler).each do |lib|
22
25
  require "compass/#{lib}"
23
26
  end
@@ -47,18 +47,18 @@ css_framework = ask("What CSS Framework install do you want to use with Compass?
47
47
 
48
48
  # sass storage prompt
49
49
  sass_dir = ask("Where would you like to keep your sass files within your project? (default: 'app/stylesheets')")
50
- sass_dir = "app/stylesheets" if sass_dir.blank?
50
+ sass_dir = "app/stylesheets" if Compass::Util.blank?(sass_dir)
51
51
 
52
52
  # compiled css storage prompt
53
53
  css_dir = ask("Where would you like Compass to store your compiled css files? (default: 'public/stylesheets/compiled')")
54
- css_dir = "public/stylesheets/compiled" if css_dir.blank?
54
+ css_dir = "public/stylesheets/compiled" if Compass::Util.blank?(css_dir)
55
55
 
56
56
  # use sudo for gem commands?
57
57
  use_sudo = nil
58
58
  if sudo_is_an_option? # dont give them the option if they are on a system that can't use sudo (aka windows)
59
59
  use_sudo = yes?("Use sudo for the gem commands? (the default for your system is #{sudo_is_an_option? ? 'yes' : 'no'})")
60
60
  end
61
- use_sudo = sudo_is_an_option? if use_sudo.blank?
61
+ use_sudo = sudo_is_an_option? if Compass::Util.blank?(use_sudo)
62
62
 
63
63
  # define dependencies
64
64
  gem "haml", :version => ">=3.0.0"
@@ -71,7 +71,7 @@ rake "gems:unpack GEM=compass --trace"
71
71
 
72
72
  # build out compass command
73
73
  compass_command = "compass init rails . --css-dir=#{css_dir} --sass-dir=#{sass_dir} "
74
- compass_command << "--using #{css_framework} " unless css_framework.blank?
74
+ compass_command << "--using #{css_framework} " unless Compass::Util.blank?(css_framework)
75
75
 
76
76
  # integrate it!
77
77
  run "haml --rails ."
@@ -37,7 +37,8 @@ module Compass
37
37
  :line_comments,
38
38
  :color_output,
39
39
  :preferred_syntax,
40
- :disable_warnings
40
+ :disable_warnings,
41
+ :sprite_engine
41
42
  ].flatten
42
43
 
43
44
  end
@@ -128,6 +128,11 @@ module Compass
128
128
  def default_preferred_syntax
129
129
  :scss
130
130
  end
131
+
132
+ def default_sprite_engine
133
+ :chunky_png
134
+ end
135
+
131
136
  # helper functions
132
137
 
133
138
  def http_join(*segments)
@@ -65,11 +65,14 @@ module Compass
65
65
  Sass::Plugin.add_template_location sass_dir, css_dir
66
66
  end
67
67
  end
68
- Sass::Plugin.on_updating_stylesheet do |sass_file, css_file|
69
- Compass.configuration.run_callback(:stylesheet_saved, css_file)
70
- end
71
- Sass::Plugin.on_compilation_error do |e, filename, css|
72
- Compass.configuration.run_callback(:stylesheet_error, filename, e.message)
68
+ unless defined?(CallbacksSetup)
69
+ Sass::Plugin.on_updating_stylesheet do |sass_file, css_file|
70
+ Compass.configuration.run_callback(:stylesheet_saved, css_file)
71
+ end
72
+ Sass::Plugin.on_compilation_error do |e, filename, css|
73
+ Compass.configuration.run_callback(:stylesheet_error, filename, e.message)
74
+ end
75
+ const_set('CallbacksSetup', true)
73
76
  end
74
77
  end
75
78
 
@@ -98,7 +101,12 @@ module Compass
98
101
  end
99
102
 
100
103
  def discover_extensions!
101
- if File.exists?(configuration.extensions_path)
104
+ Compass.shared_extension_paths.each do |extensions_path|
105
+ if File.directory?(extensions_path)
106
+ Compass::Frameworks.discover(extensions_path)
107
+ end
108
+ end
109
+ if File.directory?(configuration.extensions_path)
102
110
  Compass::Frameworks.discover(configuration.extensions_path)
103
111
  end
104
112
  end
@@ -3,3 +3,4 @@ end
3
3
 
4
4
  require 'compass/sass_extensions/functions'
5
5
  require 'compass/sass_extensions/monkey_patches'
6
+ require 'compass/sass_extensions/sprites'
@@ -1,5 +1,3 @@
1
- require 'digest/md5'
2
-
3
1
  module Compass::SassExtensions::Functions::Sprites
4
2
  ZERO = Sass::Script::Number::new(0)
5
3
 
@@ -12,224 +10,7 @@ module Compass::SassExtensions::Functions::Sprites
12
10
  end
13
11
  end
14
12
 
15
- class SpriteMap < Sass::Script::Literal
16
-
17
- # Changing this string will invalidate all previously generated sprite images.
18
- # We should do so only when the packing algorithm changes
19
- SPRITE_VERSION = "1"
20
-
21
- attr_accessor :image_names, :path, :name, :options
22
- attr_accessor :images, :width, :height
23
-
24
- def self.from_uri(uri, context, kwargs)
25
- path, name = Compass::Sprites.path_and_name(uri.value)
26
- sprites = Compass::Sprites.discover_sprites(uri.value).map do |sprite|
27
- sprite.gsub(Compass.configuration.images_path+"/", "")
28
- end
29
- new(sprites, path, name, context, kwargs)
30
- end
31
-
32
- def initialize(image_names, path, name, context, options)
33
- @image_names, @path, @name, @options = image_names, path, name, options
34
- @images = nil
35
- @width = nil
36
- @height = nil
37
- @evaluation_context = context
38
- validate!
39
- compute_image_metadata!
40
- end
41
-
42
- def sprite_names
43
- image_names.map{|f| Compass::Sprites.sprite_name(f) }
44
- end
45
-
46
- def validate!
47
- for sprite_name in sprite_names
48
- unless sprite_name =~ /\A#{Sass::SCSS::RX::IDENT}\Z/
49
- raise Sass::SyntaxError, "#{sprite_name} must be a legal css identifier"
50
- end
51
- end
52
- end
53
-
54
- # Calculates the overal image dimensions
55
- # collects image sizes and input parameters for each sprite
56
- def compute_image_metadata!
57
- @images = []
58
- @width = 0
59
- image_names.each do |relative_file|
60
- file = File.join(Compass.configuration.images_path, relative_file)
61
- width, height = Compass::SassExtensions::Functions::ImageSize::ImageProperties.new(file).size
62
- sprite_name = Compass::Sprites.sprite_name(relative_file)
63
- position = position_for(sprite_name)
64
- offset = (position.unitless? || position.unit_str == "px") ? position.value : 0
65
- @images << {
66
- :name => sprite_name,
67
- :file => file,
68
- :relative_file => relative_file,
69
- :height => height,
70
- :width => width,
71
- :repeat => repeat_for(sprite_name),
72
- :spacing => spacing_for(sprite_name),
73
- :position => position,
74
- :digest => Digest::MD5.file(file).hexdigest
75
- }
76
- @width = [@width, width + offset].max
77
- end
78
- @images.each_with_index do |image, index|
79
- if index == 0
80
- image[:top] = 0
81
- else
82
- last_image = @images[index-1]
83
- image[:top] = last_image[:top] + last_image[:height] + [image[:spacing], last_image[:spacing]].max
84
- end
85
- if image[:position].unit_str == "%"
86
- image[:left] = (@width - image[:width]) * (image[:position].value / 100)
87
- else
88
- image[:left] = image[:position].value
89
- end
90
- end
91
- @height = @images.last[:top] + @images.last[:height]
92
- end
93
-
94
- def position_for(name)
95
- options.get_var("#{name}-position") || options.get_var("position") || Sass::Script::Number.new(0, ["px"])
96
- end
97
-
98
- def repeat_for(name)
99
- if (var = options.get_var("#{name}-repeat"))
100
- var.value
101
- elsif (var = options.get_var("repeat"))
102
- var.value
103
- else
104
- "no-repeat"
105
- end
106
- end
107
-
108
- def spacing_for(name)
109
- (options.get_var("#{name}-spacing") ||
110
- options.get_var("spacing") ||
111
- ZERO).value
112
- end
113
-
114
- def image_for(name)
115
- @images.detect{|img| img[:name] == name}
116
- end
117
-
118
- # Calculate the size of the sprite
119
- def size
120
- [width, height]
121
- end
122
-
123
- # Generate a sprite image if necessary
124
- def generate
125
- if generation_required?
126
- sprite_data = construct_sprite
127
- save!(sprite_data)
128
- Compass.configuration.run_callback(:sprite_generated, sprite_data)
129
- end
130
- end
131
-
132
- def generation_required?
133
- !File.exists?(filename) || outdated?
134
- end
135
-
136
- def require_png_library!
137
- begin
138
- require 'oily_png'
139
- rescue LoadError
140
- require 'chunky_png'
141
- end
142
- end
143
-
144
- # Returns a PNG object
145
- def construct_sprite
146
- require_png_library!
147
- output_png = ChunkyPNG::Image.new(width, height, ChunkyPNG::Color::TRANSPARENT)
148
- images.each do |image|
149
- input_png = ChunkyPNG::Image.from_file(image[:file])
150
- if image[:repeat] == "no-repeat"
151
- output_png.replace input_png, image[:left], image[:top]
152
- else
153
- x = image[:left] - (image[:left] / image[:width]).ceil * image[:width]
154
- while x < width do
155
- output_png.replace input_png, x, image[:top]
156
- x += image[:width]
157
- end
158
- end
159
- end
160
- output_png
161
- end
162
-
163
- # The on-the-disk filename of the sprite
164
- def filename
165
- File.join(Compass.configuration.images_path, "#{path}-#{uniqueness_hash}.png")
166
- end
167
-
168
- def uniqueness_hash
169
- @uniqueness_hash ||= begin
170
- sum = Digest::MD5.new
171
- sum << SPRITE_VERSION
172
- sum << path
173
- images.each do |image|
174
- [:relative_file, :height, :width, :repeat, :spacing, :position, :digest].each do |attr|
175
- sum << image[attr].to_s
176
- end
177
- end
178
- sum.hexdigest[0...10]
179
- end
180
- @uniqueness_hash
181
- end
182
-
183
- # saves the sprite for later retrieval
184
- def save!(output_png)
185
- saved = output_png.save filename
186
- Compass.configuration.run_callback(:sprite_saved, filename)
187
- saved
188
- end
189
-
190
- # All the full-path filenames involved in this sprite
191
- def image_filenames
192
- image_names.map do |image_name|
193
- File.join(Compass.configuration.images_path, image_name)
194
- end
195
- end
196
-
197
- # Checks whether this sprite is outdated
198
- def outdated?
199
- last_update = self.mtime
200
- image_filenames.each do |image|
201
- return true if File.mtime(image) > last_update
202
- end
203
- false
204
- end
205
-
206
- def mtime
207
- File.mtime(filename)
208
- end
209
-
210
- def inspect
211
- to_s
212
- end
213
-
214
- def to_s(options = self.options)
215
- sprite_url(self).value
216
- end
217
-
218
- def respond_to?(meth)
219
- super || @evaluation_context.respond_to?(meth)
220
- end
221
-
222
- def method_missing(meth, *args, &block)
223
- if @evaluation_context.respond_to?(meth)
224
- @evaluation_context.send(meth, *args, &block)
225
- else
226
- super
227
- end
228
- end
229
-
230
- end
231
-
232
- # Creates a SpriteMap object. A sprite map, when used in a property is the same
13
+ # Creates a Compass::SassExtensions::Sprites::Base object. A sprite map, when used in a property is the same
233
14
  # as calling sprite-url. So the following background properties are equivalent:
234
15
  #
235
16
  # $icons: sprite-map("icons/*.png");
@@ -240,7 +21,7 @@ module Compass::SassExtensions::Functions::Sprites
240
21
  # the first time it is converted to a url. Simply constructing it has no side-effects.
241
22
  def sprite_map(glob, kwargs = {})
242
23
  kwargs.extend VariableReader
243
- SpriteMap.from_uri(glob, self, kwargs)
24
+ Compass::SassExtensions::Sprites::Base.from_uri(glob, self, kwargs)
244
25
  end
245
26
  Sass::Script::Functions.declare :sprite_map, [:glob], :var_kwargs => true
246
27
 
@@ -253,7 +34,7 @@ module Compass::SassExtensions::Functions::Sprites
253
34
  #
254
35
  # background: url('/images/icons.png?12345678') 0 -24px no-repeat;
255
36
  def sprite(map, sprite, offset_x = ZERO, offset_y = ZERO)
256
- unless map.is_a?(SpriteMap)
37
+ unless map.is_a?(Compass::SassExtensions::Sprites::Base)
257
38
  missing_sprite!("sprite")
258
39
  end
259
40
  unless sprite.is_a?(Sass::Script::String)
@@ -270,7 +51,7 @@ module Compass::SassExtensions::Functions::Sprites
270
51
  # Returns the name of a sprite map
271
52
  # The name is derived from the folder than contains the sprites.
272
53
  def sprite_map_name(map)
273
- unless map.is_a?(SpriteMap)
54
+ unless map.is_a?(Compass::SassExtensions::Sprites::Base)
274
55
  missing_sprite!("sprite-map-name")
275
56
  end
276
57
  Sass::Script::String.new(map.name)
@@ -279,11 +60,11 @@ module Compass::SassExtensions::Functions::Sprites
279
60
 
280
61
  # Returns the path to the original image file for the sprite with the given name
281
62
  def sprite_file(map, sprite)
282
- unless map.is_a?(SpriteMap)
63
+ unless map.is_a?(Compass::SassExtensions::Sprites::Base)
283
64
  missing_sprite!("sprite-file")
284
65
  end
285
66
  if image = map.image_for(sprite.value)
286
- Sass::Script::String.new(image[:relative_file])
67
+ Sass::Script::String.new(image.relative_file)
287
68
  else
288
69
  missing_image!(map, sprite)
289
70
  end
@@ -292,7 +73,7 @@ module Compass::SassExtensions::Functions::Sprites
292
73
 
293
74
  # Returns a url to the sprite image.
294
75
  def sprite_url(map)
295
- unless map.is_a?(SpriteMap)
76
+ unless map.is_a?(Compass::SassExtensions::Sprites::Base)
296
77
  missing_sprite!("sprite-url")
297
78
  end
298
79
  map.generate
@@ -322,7 +103,7 @@ module Compass::SassExtensions::Functions::Sprites
322
103
  #
323
104
  # background-position: 3px -36px;
324
105
  def sprite_position(map, sprite = nil, offset_x = ZERO, offset_y = ZERO)
325
- unless map.is_a?(SpriteMap)
106
+ unless map.is_a?(Compass::SassExtensions::Sprites::Base)
326
107
  missing_sprite!("sprite-position")
327
108
  end
328
109
  unless sprite && sprite.is_a?(Sass::Script::String)
@@ -335,10 +116,10 @@ module Compass::SassExtensions::Functions::Sprites
335
116
  if offset_x.unit_str == "%"
336
117
  x = offset_x # CE: Shouldn't this be a percentage of the total width?
337
118
  else
338
- x = offset_x.value - image[:left]
119
+ x = offset_x.value - image.left
339
120
  x = Sass::Script::Number.new(x, x == 0 ? [] : ["px"])
340
121
  end
341
- y = offset_y.value - image[:top]
122
+ y = offset_y.value - image.top
342
123
  y = Sass::Script::Number.new(y, y == 0 ? [] : ["px"])
343
124
  Sass::Script::List.new([x, y],:space)
344
125
  end