haml-edge 2.3.100 → 2.3.148

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/.yardopts +3 -0
  2. data/EDGE_GEM_VERSION +1 -1
  3. data/Rakefile +14 -2
  4. data/VERSION +1 -1
  5. data/extra/haml-mode.el +97 -11
  6. data/extra/sass-mode.el +2 -2
  7. data/lib/haml/engine.rb +2 -2
  8. data/lib/haml/exec.rb +121 -25
  9. data/lib/haml/filters.rb +1 -1
  10. data/lib/haml/helpers/action_view_mods.rb +2 -1
  11. data/lib/haml/helpers/xss_mods.rb +43 -13
  12. data/lib/haml/helpers.rb +38 -17
  13. data/lib/haml/html.rb +13 -4
  14. data/lib/haml/precompiler.rb +24 -3
  15. data/lib/haml/template/plugin.rb +7 -3
  16. data/lib/haml/template.rb +3 -3
  17. data/lib/haml/util.rb +40 -0
  18. data/lib/sass/callbacks.rb +50 -0
  19. data/lib/sass/css.rb +1 -1
  20. data/lib/sass/engine.rb +45 -5
  21. data/lib/sass/error.rb +6 -3
  22. data/lib/sass/files.rb +8 -1
  23. data/lib/sass/plugin/rails.rb +2 -2
  24. data/lib/sass/plugin.rb +260 -28
  25. data/lib/sass/script/color.rb +216 -30
  26. data/lib/sass/script/functions.rb +356 -74
  27. data/lib/sass/script/lexer.rb +7 -4
  28. data/lib/sass/script/number.rb +2 -0
  29. data/lib/sass/script/parser.rb +1 -1
  30. data/lib/sass/script.rb +3 -0
  31. data/lib/sass/tree/node.rb +1 -1
  32. data/lib/sass/tree/root_node.rb +6 -0
  33. data/lib/sass/tree/rule_node.rb +1 -0
  34. data/lib/sass.rb +4 -0
  35. data/test/haml/engine_test.rb +25 -0
  36. data/test/haml/helper_test.rb +81 -1
  37. data/test/haml/html2haml_test.rb +13 -0
  38. data/test/haml/spec/README.md +97 -0
  39. data/test/haml/spec/lua_haml_spec.lua +30 -0
  40. data/test/haml/spec/ruby_haml_test.rb +19 -0
  41. data/test/haml/spec/tests.json +534 -0
  42. data/test/haml/spec_test.rb +0 -0
  43. data/test/haml/template_test.rb +18 -4
  44. data/test/haml/util_test.rb +0 -0
  45. data/test/sass/callbacks_test.rb +61 -0
  46. data/test/sass/css2sass_test.rb +1 -0
  47. data/test/sass/engine_test.rb +70 -14
  48. data/test/sass/functions_test.rb +223 -3
  49. data/test/sass/plugin_test.rb +193 -25
  50. data/test/sass/results/options.css +1 -0
  51. data/test/sass/script_test.rb +5 -5
  52. data/test/sass/templates/options.sass +2 -0
  53. data/test/test_helper.rb +12 -5
  54. metadata +19 -9
@@ -2,23 +2,19 @@ module Sass::Script
2
2
  # Methods in this module are accessible from the SassScript context.
3
3
  # For example, you can write
4
4
  #
5
- # !color = hsl(120, 100%, 50%)
5
+ # !color = hsl(120deg, 100%, 50%)
6
6
  #
7
7
  # and it will call {Sass::Script::Functions#hsl}.
8
8
  #
9
9
  # The following functions are provided:
10
10
  #
11
- # \{#hsl}
12
- # : Converts an `hsl(hue, saturation, lightness)` triplet into a color.
13
- #
14
- # \{#hsla}
15
- # : Converts an `hsla(hue, saturation, lightness, alpha)` quadruplet into a color.
11
+ # ## RGB Functions
16
12
  #
17
13
  # \{#rgb}
18
14
  # : Converts an `rgb(red, green, blue)` triplet into a color.
19
15
  #
20
16
  # \{#rgba}
21
- # : Converts an `rgb(red, green, blue, alpha)` triplet into a color.
17
+ # : Converts an `rgba(red, green, blue, alpha)` quadruplet into a color.
22
18
  #
23
19
  # \{#red}
24
20
  # : Gets the red component of a color.
@@ -29,15 +25,63 @@ module Sass::Script
29
25
  # \{#blue}
30
26
  # : Gets the blue component of a color.
31
27
  #
28
+ # \{#mix}
29
+ # : Mixes two colors together.
30
+ #
31
+ # ## HSL Functions
32
+ #
33
+ # \{#hsl}
34
+ # : Converts an `hsl(hue, saturation, lightness)` triplet into a color.
35
+ #
36
+ # \{#hsla}
37
+ # : Converts an `hsla(hue, saturation, lightness, alpha)` quadruplet into a color.
38
+ #
39
+ # \{#hue}
40
+ # : Gets the hue component of a color.
41
+ #
42
+ # \{#saturation}
43
+ # : Gets the saturation component of a color.
44
+ #
45
+ # \{#lightness}
46
+ # : Gets the lightness component of a color.
47
+ #
48
+ # \{#adjust_hue #adjust-hue}
49
+ # : Changes the hue of a color.
50
+ #
51
+ # \{#lighten}
52
+ # : Makes a color lighter.
53
+ #
54
+ # \{#darken}
55
+ # : Makes a color darker.
56
+ #
57
+ # \{#saturate}
58
+ # : Makes a color more saturated.
59
+ #
60
+ # \{#desaturate}
61
+ # : Makes a color less saturated.
62
+ #
63
+ # \{#grayscale}
64
+ # : Converts a color to grayscale.
65
+ #
66
+ # \{#complement}
67
+ # : Returns the complement of a color.
68
+ #
69
+ # ## Opacity Functions
70
+ #
32
71
  # \{#alpha} / \{#opacity}
33
72
  # : Gets the alpha component (opacity) of a color.
34
73
  #
74
+ # \{#rgba}
75
+ # : Sets the alpha component of a color.
76
+ #
35
77
  # \{#opacify} / \{#fade_in #fade-in}
36
78
  # : Makes a color more opaque.
37
79
  #
38
80
  # \{#transparentize} / \{#fade_out #fade-out}
39
81
  # : Makes a color more transparent.
40
82
  #
83
+ # ## Number Functions
84
+ #
41
85
  # \{#percentage}
42
86
  # : Converts a unitless number to a percentage.
43
87
  #
@@ -79,11 +123,16 @@ module Sass::Script
79
123
  #
80
124
  # Second, making Ruby functions accessible from Sass introduces the temptation
81
125
  # to do things like database access within stylesheets.
82
- # This temptation must be resisted.
83
- # Keep in mind that Sass stylesheets are only compiled once
84
- # at a somewhat indeterminate time
85
- # and then left as static CSS files.
86
- # Any dynamic CSS should be left in `<style>` tags in the HTML.
126
+ # This is generally a bad idea;
127
+ # since Sass files are by default only compiled once,
128
+ # dynamic code is not a great fit.
129
+ #
130
+ # If you really, really need to compile Sass on each request,
131
+ # first make sure you have adequate caching set up.
132
+ # Then you can use {Sass::Engine} to render the code,
133
+ # using the {file:SASS_REFERENCE.md#custom-option `options` parameter}
134
+ # to pass in data that {EvaluationContext#options can be accessed}
135
+ # from your Sass functions.
87
136
  #
88
137
  # Within one of the functions in this module,
89
138
  # methods of {EvaluationContext} can be used.
@@ -134,52 +183,78 @@ module Sass::Script
134
183
 
135
184
 
136
185
  # Creates a {Color} object from red, green, and blue values.
137
- # @param red
186
+ #
187
+ # @param red [Number]
138
188
  # A number between 0 and 255 inclusive,
139
189
  # or between 0% and 100% inclusive
140
- # @param green
190
+ # @param green [Number]
141
191
  # A number between 0 and 255 inclusive,
142
192
  # or between 0% and 100% inclusive
143
- # @param blue
193
+ # @param blue [Number]
144
194
  # A number between 0 and 255 inclusive,
145
195
  # or between 0% and 100% inclusive
196
+ # @return [Color]
146
197
  def rgb(red, green, blue)
147
- rgba(red, green, blue, Number.new(1))
148
- end
149
-
150
- # Creates a {Color} object from red, green, and blue values,
151
- # as well as an alpha channel indicating opacity.
152
- #
153
- # @param red
154
- # A number between 0 and 255 inclusive
155
- # @param green
156
- # A number between 0 and 255 inclusive
157
- # @param blue
158
- # A number between 0 and 255 inclusive
159
- # @param alpha
160
- # A number between 0 and 1
161
- def rgba(red, green, blue, alpha)
162
198
  assert_type red, :Number
163
199
  assert_type green, :Number
164
200
  assert_type blue, :Number
165
- assert_type alpha, :Number
166
201
 
167
- rgb = [red, green, blue].map do |c|
168
- v = c.value
169
- if c.numerator_units == ["%"] && c.denominator_units.empty?
170
- next v * 255 / 100.0 if (0..100).include?(v)
171
- raise ArgumentError.new("Color value #{c} must be between 0% and 100% inclusive")
172
- else
173
- next v if (0..255).include?(v)
174
- raise ArgumentError.new("Color value #{v} must be between 0 and 255 inclusive")
202
+ Color.new([red, green, blue].map do |c|
203
+ v = c.value
204
+ if c.numerator_units == ["%"] && c.denominator_units.empty?
205
+ next v * 255 / 100.0 if (0..100).include?(v)
206
+ raise ArgumentError.new("Color value #{c} must be between 0% and 100% inclusive")
207
+ else
208
+ next v if (0..255).include?(v)
209
+ raise ArgumentError.new("Color value #{v} must be between 0 and 255 inclusive")
210
+ end
211
+ end)
212
+ end
213
+
214
+ # @overload rgba(red, green, blue, alpha)
215
+ # Creates a {Color} object from red, green, and blue values,
216
+ # as well as an alpha channel indicating opacity.
217
+ #
218
+ # @param red [Number]
219
+ # A number between 0 and 255 inclusive
220
+ # @param green [Number]
221
+ # A number between 0 and 255 inclusive
222
+ # @param blue [Number]
223
+ # A number between 0 and 255 inclusive
224
+ # @param alpha [Number]
225
+ # A number between 0 and 1
226
+ # @return [Color]
227
+ #
228
+ # @overload rgba(color, alpha)
229
+ # Sets the opacity of a color.
230
+ #
231
+ # @example
232
+ # rgba(#102030, 0.5) => rgba(16, 32, 48, 0.5)
233
+ # rgba(blue, 0.2) => rgba(0, 0, 255, 0.2)
234
+ #
235
+ # @param color [Color]
236
+ # @param alpha [Number]
237
+ # A number between 0 and 1
238
+ # @return [Color]
239
+ def rgba(*args)
240
+ case args.size
241
+ when 2
242
+ color, alpha = args
243
+
244
+ assert_type color, :Color
245
+ assert_type alpha, :Number
246
+
247
+ unless (0..1).include?(alpha.value)
248
+ raise ArgumentError.new("Alpha channel #{alpha.value} must be between 0 and 1 inclusive")
175
249
  end
176
- end
177
250
 
178
- unless (0..1).include?(alpha.value)
179
- raise ArgumentError.new("Alpha channel #{alpha.value} must be between 0 and 1 inclusive")
251
+ color.with(:alpha => alpha.value)
252
+ when 4
253
+ red, green, blue, alpha = args
254
+ rgba(rgb(red, green, blue), alpha)
255
+ else
256
+ raise ArgumentError.new("wrong number of arguments (#{args.size} for 4)")
180
257
  end
181
-
182
- Color.new(rgb + [alpha.value])
183
258
  end
184
259
 
185
260
  # Creates a {Color} object from hue, saturation, and lightness.
@@ -228,17 +303,7 @@ module Sass::Script
228
303
  raise ArgumentError.new("Saturation #{s} must be between 0% and 100%") unless (0..100).include?(s)
229
304
  raise ArgumentError.new("Lightness #{l} must be between 0% and 100%") unless (0..100).include?(l)
230
305
 
231
- h = (h % 360) / 360.0
232
- s /= 100.0
233
- l /= 100.0
234
-
235
- m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s
236
- m1 = l * 2 - m2
237
- Color.new(
238
- [hue_to_rgb(m1, m2, h + 1.0/3),
239
- hue_to_rgb(m1, m2, h),
240
- hue_to_rgb(m1, m2, h - 1.0/3)].map { |c| (c * 0xff).round } +
241
- [alpha.value])
306
+ Color.new(:hue => h, :saturation => s, :lightness => l, :alpha => alpha.value)
242
307
  end
243
308
 
244
309
  # Returns the red component of a color.
@@ -271,6 +336,48 @@ module Sass::Script
271
336
  Sass::Script::Number.new(color.blue)
272
337
  end
273
338
 
339
+ # Returns the hue component of a color.
340
+ #
341
+ # See [the CSS3 HSL specification](http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV).
342
+ #
343
+ # Calculated from RGB where necessary via [this algorithm](http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV).
344
+ #
345
+ # @param color [Color]
346
+ # @return [Number] between 0deg and 360deg
347
+ # @raise [ArgumentError] if `color` isn't a color
348
+ def hue(color)
349
+ assert_type color, :Color
350
+ Sass::Script::Number.new(color.hue, ["deg"])
351
+ end
352
+
353
+ # Returns the saturation component of a color.
354
+ #
355
+ # See [the CSS3 HSL specification](http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV).
356
+ #
357
+ # Calculated from RGB where necessary via [this algorithm](http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV).
358
+ #
359
+ # @param color [Color]
360
+ # @return [Number] between 0% and 100%
361
+ # @raise [ArgumentError] if `color` isn't a color
362
+ def saturation(color)
363
+ assert_type color, :Color
364
+ Sass::Script::Number.new(color.saturation, ["%"])
365
+ end
366
+
367
+ # Returns the hue component of a color.
368
+ #
369
+ # See [the CSS3 HSL specification](http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV).
370
+ #
371
+ # Calculated from RGB where necessary via [this algorithm](http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV).
372
+ #
373
+ # @param color [Color]
374
+ # @return [Number] between 0% and 100%
375
+ # @raise [ArgumentError] if `color` isn't a color
376
+ def lightness(color)
377
+ assert_type color, :Color
378
+ Sass::Script::Number.new(color.lightness, ["%"])
379
+ end
380
+
274
381
  # Returns the alpha component (opacity) of a color.
275
382
  # This is 1 unless otherwise specified.
276
383
  #
@@ -294,16 +401,11 @@ module Sass::Script
294
401
  #
295
402
  # @param color [Color]
296
403
  # @param amount [Number]
404
+ # @return [Color]
297
405
  # @raise [ArgumentError] If `color` isn't a color,
298
406
  # or `number` isn't a number between 0 and 1
299
407
  def opacify(color, amount)
300
- assert_type color, :Color
301
- assert_type amount, :Number
302
- unless (0..1).include?(amount.value)
303
- raise ArgumentError.new("Amount #{amount} must be between 0 and 1")
304
- end
305
-
306
- color.with(:alpha => Haml::Util.restrict(color.alpha + amount.value, 0..1))
408
+ adjust(color, amount, :alpha, 0..1, :+)
307
409
  end
308
410
  alias_method :fade_in, :opacify
309
411
 
@@ -318,18 +420,193 @@ module Sass::Script
318
420
  #
319
421
  # @param color [Color]
320
422
  # @param amount [Number]
423
+ # @return [Color]
321
424
  # @raise [ArgumentError] If `color` isn't a color,
322
425
  # or `number` isn't a number between 0 and 1
323
426
  def transparentize(color, amount)
427
+ adjust(color, amount, :alpha, 0..1, :-)
428
+ end
429
+ alias_method :fade_out, :transparentize
430
+
431
+ # Makes a color lighter.
432
+ # Takes a color and an amount between 0% and 100%,
433
+ # and returns a color with the lightness increased by that value.
434
+ #
435
+ # For example:
436
+ #
437
+ # lighten(hsl(0, 0%, 0%), 30%) => hsl(0, 0, 30)
438
+ # lighten(#800, 20%) => #e00
439
+ #
440
+ # @param color [Color]
441
+ # @param amount [Number]
442
+ # @return [Color]
443
+ # @raise [ArgumentError] If `color` isn't a color,
444
+ # or `number` isn't a number between 0% and 100%
445
+ def lighten(color, amount)
446
+ adjust(color, amount, :lightness, 0..100, :+, "%")
447
+ end
448
+
449
+ # Makes a color darker.
450
+ # Takes a color and an amount between 0% and 100%,
451
+ # and returns a color with the lightness decreased by that value.
452
+ #
453
+ # For example:
454
+ #
455
+ # darken(hsl(25, 100%, 80%), 30%) => hsl(25, 100%, 50%)
456
+ # darken(#800, 20%) => #200
457
+ #
458
+ # @param color [Color]
459
+ # @param amount [Number]
460
+ # @return [Color]
461
+ # @raise [ArgumentError] If `color` isn't a color,
462
+ # or `number` isn't a number between 0% and 100%
463
+ def darken(color, amount)
464
+ adjust(color, amount, :lightness, 0..100, :-, "%")
465
+ end
466
+
467
+ # Makes a color more saturated.
468
+ # Takes a color and an amount between 0% and 100%,
469
+ # and returns a color with the saturation increased by that value.
470
+ #
471
+ # For example:
472
+ #
473
+ # saturate(hsl(120, 30%, 90%), 20%) => hsl(120, 50%, 90%)
474
+ # saturate(#855, 20%) => #9e3f3f
475
+ #
476
+ # @param color [Color]
477
+ # @param amount [Number]
478
+ # @return [Color]
479
+ # @raise [ArgumentError] If `color` isn't a color,
480
+ # or `number` isn't a number between 0% and 100%
481
+ def saturate(color, amount)
482
+ adjust(color, amount, :saturation, 0..100, :+, "%")
483
+ end
484
+
485
+ # Makes a color less saturated.
486
+ # Takes a color and an amount between 0% and 100%,
487
+ # and returns a color with the saturation decreased by that value.
488
+ #
489
+ # For example:
490
+ #
491
+ # desaturate(hsl(120, 30%, 90%), 20%) => hsl(120, 10%, 90%)
492
+ # desaturate(#855, 20%) => #726b6b
493
+ #
494
+ # @param color [Color]
495
+ # @param amount [Number]
496
+ # @return [Color]
497
+ # @raise [ArgumentError] If `color` isn't a color,
498
+ # or `number` isn't a number between 0% and 100%
499
+ def desaturate(color, amount)
500
+ adjust(color, amount, :saturation, 0..100, :-, "%")
501
+ end
502
+
503
+ # Changes the hue of a color while retaining the lightness and saturation.
504
+ # Takes a color and a number of degrees (usually between -360deg and 360deg),
505
+ # and returns a color with the hue rotated by that value.
506
+ #
507
+ # For example:
508
+ #
509
+ # adjust-hue(hsl(120, 30%, 90%), 60deg) => hsl(180, 30%, 90%)
510
+ # adjust-hue(hsl(120, 30%, 90%), 060deg) => hsl(60, 30%, 90%)
511
+ # adjust-hue(#811, 45deg) => #886a11
512
+ #
513
+ # @param color [Color]
514
+ # @param amount [Number]
515
+ # @return [Color]
516
+ # @raise [ArgumentError] If `color` isn't a color, or `number` isn't a number
517
+ def adjust_hue(color, degrees)
324
518
  assert_type color, :Color
325
- assert_type amount, :Number
326
- unless (0..1).include?(amount.value)
327
- raise ArgumentError.new("Amount #{amount} must be between 0 and 1")
519
+ assert_type degrees, :Number
520
+ color.with(:hue => color.hue + degrees.value)
521
+ end
522
+
523
+ # Mixes together two colors.
524
+ # Specifically, takes the average of each of the RGB components,
525
+ # optionally weighted by the given percentage.
526
+ # The opacity of the colors is also considered when weighting the components.
527
+ #
528
+ # The weight specifies the amount of the first color that should be included
529
+ # in the returned color.
530
+ # The default, 50%, means that half the first color
531
+ # and half the second color should be used.
532
+ # 25% means that a quarter of the first color
533
+ # and three quarters of the second color should be used.
534
+ #
535
+ # For example:
536
+ #
537
+ # mix(#f00, #00f) => #7f007f
538
+ # mix(#f00, #00f, 25%) => #3f00bf
539
+ # mix(rgba(255, 0, 0, 0.5), #00f) => rgba(63, 0, 191, 0.75)
540
+ #
541
+ # @overload mix(color1, color2, weight = 50%)
542
+ # @param color1 [Color]
543
+ # @param color2 [Color]
544
+ # @param weight [Number] between 0% and 100%
545
+ # @return [Color]
546
+ # @raise [ArgumentError] if `color1` or `color2` aren't colors,
547
+ # or `weight` isn't a number between 0% and 100%
548
+ def mix(color1, color2, weight = Number.new(50))
549
+ assert_type color1, :Color
550
+ assert_type color2, :Color
551
+ assert_type weight, :Number
552
+
553
+ unless (0..100).include?(weight.value)
554
+ raise ArgumentError.new("Weight #{weight} must be between 0% and 100%")
328
555
  end
329
556
 
330
- color.with(:alpha => Haml::Util.restrict(color.alpha - amount.value, 0..1))
557
+ # This algorithm factors in both the user-provided weight
558
+ # and the difference between the alpha values of the two colors
559
+ # to decide how to perform the weighted average of the two RGB values.
560
+ #
561
+ # It works by first normalizing both parameters to be within [-1, 1],
562
+ # where 1 indicates "only use color1", -1 indicates "only use color 0",
563
+ # and all values in between indicated a proportionately weighted average.
564
+ #
565
+ # Once we have the normalized variables w and a,
566
+ # we apply the formula (w + a)/(1 + w*a)
567
+ # to get the combined weight (in [-1, 1]) of color1.
568
+ # This formula has two especially nice properties:
569
+ #
570
+ # * When either w or a are -1 or 1, the combined weight is also that number
571
+ # (cases where w * a == -1 are undefined, and handled as a special case).
572
+ #
573
+ # * When a is 0, the combined weight is w, and vice versa
574
+ #
575
+ # Finally, the weight of color1 is renormalized to be within [0, 1]
576
+ # and the weight of color2 is given by 1 minus the weight of color1.
577
+ p = weight.value/100.0
578
+ w = p*2 - 1
579
+ a = color1.alpha - color2.alpha
580
+
581
+ w1 = (((w * a == -1) ? w : (w + a)/(1 + w*a)) + 1)/2.0
582
+ w2 = 1 - w1
583
+
584
+ rgb = color1.rgb.zip(color2.rgb).map {|v1, v2| v1*w1 + v2*w2}
585
+ alpha = color1.alpha*p + color2.alpha*(1-p)
586
+ Color.new(rgb + [alpha])
587
+ end
588
+
589
+ # Converts a color to grayscale.
590
+ # This is identical to `desaturate(color, 100%)`.
591
+ #
592
+ # @param color [Color]
593
+ # @return [Color]
594
+ # @raise [ArgumentError] if `color` isn't a color
595
+ # @see #desaturate
596
+ def grayscale(color)
597
+ desaturate color, Number.new(100)
598
+ end
599
+
600
+ # Returns the complement of a color.
601
+ # This is identical to `adjust-hue(color, 180deg)`.
602
+ #
603
+ # @param color [Color]
604
+ # @return [Color]
605
+ # @raise [ArgumentError] if `color` isn't a color
606
+ # @see #adjust_hue #adjust-hue
607
+ def complement(color)
608
+ adjust_hue color, Number.new(180)
331
609
  end
332
- alias_method :fade_out, :transparentize
333
610
 
334
611
  # Converts a decimal number to a percentage.
335
612
  # For example:
@@ -408,13 +685,18 @@ module Sass::Script
408
685
  Sass::Script::Number.new(yield(value.value), value.numerator_units, value.denominator_units)
409
686
  end
410
687
 
411
- def hue_to_rgb(m1, m2, h)
412
- h += 1 if h < 0
413
- h -= 1 if h > 1
414
- return m1 + (m2 - m1) * h * 6 if h * 6 < 1
415
- return m2 if h * 2 < 1
416
- return m1 + (m2 - m1) * (2.0/3 - h) * 6 if h * 3 < 2
417
- return m1
688
+ def adjust(color, amount, attr, range, op, units = "")
689
+ assert_type color, :Color
690
+ assert_type amount, :Number
691
+ unless range.include?(amount.value)
692
+ raise ArgumentError.new("Amount #{amount} must be between #{range.first}#{units} and #{range.last}#{units}")
693
+ end
694
+
695
+ # TODO: is it worth restricting here,
696
+ # or should we do so in the Color constructor itself,
697
+ # and allow clipping in rgb() et al?
698
+ color.with(attr => Haml::Util.restrict(
699
+ color.send(attr).send(op, amount.value), range))
418
700
  end
419
701
  end
420
702
  end
@@ -8,20 +8,21 @@ module Sass
8
8
  class Lexer
9
9
  # A struct containing information about an individual token.
10
10
  #
11
- # `type`: \[{Symbol}\]
11
+ # `type`: \[`Symbol`\]
12
12
  # : The type of token.
13
13
  #
14
- # `value`: \[{Object}\]
14
+ # `value`: \[`Object`\]
15
15
  # : The Ruby object corresponding to the value of the token.
16
16
  #
17
- # `line`: \[{Fixnum}\]
17
+ # `line`: \[`Fixnum`\]
18
18
  # : The line of the source file on which the token appears.
19
19
  #
20
- # `offset`: \[{Fixnum}\]
20
+ # `offset`: \[`Fixnum`\]
21
21
  # : The number of bytes into the line the SassScript token appeared.
22
22
  Token = Struct.new(:type, :value, :line, :offset)
23
23
 
24
24
  # A hash from operator strings to the corresponding token types.
25
+ # @private
25
26
  OPERATORS = {
26
27
  '+' => :plus,
27
28
  '-' => :minus,
@@ -47,9 +48,11 @@ module Sass
47
48
 
48
49
  # A list of operator strings ordered with longer names first
49
50
  # so that `>` and `<` don't clobber `>=` and `<=`.
51
+ # @private
50
52
  OP_NAMES = OPERATORS.keys.sort_by {|o| -o.size}
51
53
 
52
54
  # A hash of regular expressions that are used for tokenizing.
55
+ # @private
53
56
  REGULAR_EXPRESSIONS = {
54
57
  :whitespace => /\s*/,
55
58
  :variable => /!([\w-]+)/,
@@ -351,7 +351,9 @@ module Sass::Script
351
351
  end
352
352
 
353
353
  # A hash of unit names to their index in the conversion table
354
+ # @private
354
355
  CONVERTABLE_UNITS = {"in" => 0, "cm" => 1, "pc" => 2, "mm" => 3, "pt" => 4}
356
+ # @private
355
357
  CONVERSION_TABLE = [[ 1, 2.54, 6, 25.4, 72 ], # in
356
358
  [ nil, 1, 2.36220473, 10, 28.3464567], # cm
357
359
  [ nil, nil, 1, 4.23333333, 12 ], # pc
@@ -149,7 +149,7 @@ RUBY
149
149
  warn(<<END)
150
150
  DEPRECATION WARNING:
151
151
  On line #{name.line}, character #{name.offset}#{" of '#{filename}'" if filename}
152
- Implicit strings have been deprecated and will be removed in version 2.4.
152
+ Implicit strings have been deprecated and will be removed in version 3.0.
153
153
  '#{name.value}' was not quoted. Please add double quotes (e.g. "#{name.value}").
154
154
  END
155
155
  Script::String.new(name.value)
data/lib/sass/script.rb CHANGED
@@ -13,12 +13,15 @@ module Sass
13
13
  # This module contains code that handles the parsing and evaluation of SassScript.
14
14
  module Script
15
15
  # The character that begins a variable.
16
+ # @private
16
17
  VARIABLE_CHAR = ?!
17
18
 
18
19
  # The regular expression used to parse variables.
20
+ # @private
19
21
  MATCH = /^!([a-zA-Z_]\w*)\s*((?:\|\|)?=)\s*(.+)/
20
22
 
21
23
  # The regular expression used to validate variables without matching.
24
+ # @private
22
25
  VALIDATE = /^![a-zA-Z_]\w*$/
23
26
 
24
27
  # Parses a string of SassScript
@@ -64,7 +64,7 @@ module Sass
64
64
  #
65
65
  # @return [String]
66
66
  def filename
67
- @filename || @options[:filename]
67
+ @filename || (@options && @options[:filename])
68
68
  end
69
69
 
70
70
  # Appends a child to the node.
@@ -38,6 +38,12 @@ module Sass
38
38
  raise e
39
39
  end
40
40
 
41
+ # @see \{Node#perform!}
42
+ def perform!(environment)
43
+ environment.options = @options if environment.options.nil? || environment.options.empty?
44
+ super
45
+ end
46
+
41
47
  protected
42
48
 
43
49
  # Destructively converts this static Sass node into a static CSS node,
@@ -6,6 +6,7 @@ module Sass::Tree
6
6
  # @see Sass::Tree
7
7
  class RuleNode < Node
8
8
  # The character used to include the parent selector
9
+ # @private
9
10
  PARENT = '&'
10
11
 
11
12
  # The CSS selectors for this rule.
data/lib/sass.rb CHANGED
@@ -20,5 +20,9 @@ module Sass
20
20
  end
21
21
 
22
22
  require 'haml/util'
23
+
24
+ dir = Haml::Util.scope("vendor/fssm/lib")
25
+ $LOAD_PATH.unshift dir unless $LOAD_PATH.include?(dir)
26
+
23
27
  require 'sass/engine'
24
28
  require 'sass/plugin' if defined?(Merb::Plugins)