haml-edge 2.3.100 → 2.3.148
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.
- data/.yardopts +3 -0
- data/EDGE_GEM_VERSION +1 -1
- data/Rakefile +14 -2
- data/VERSION +1 -1
- data/extra/haml-mode.el +97 -11
- data/extra/sass-mode.el +2 -2
- data/lib/haml/engine.rb +2 -2
- data/lib/haml/exec.rb +121 -25
- data/lib/haml/filters.rb +1 -1
- data/lib/haml/helpers/action_view_mods.rb +2 -1
- data/lib/haml/helpers/xss_mods.rb +43 -13
- data/lib/haml/helpers.rb +38 -17
- data/lib/haml/html.rb +13 -4
- data/lib/haml/precompiler.rb +24 -3
- data/lib/haml/template/plugin.rb +7 -3
- data/lib/haml/template.rb +3 -3
- data/lib/haml/util.rb +40 -0
- data/lib/sass/callbacks.rb +50 -0
- data/lib/sass/css.rb +1 -1
- data/lib/sass/engine.rb +45 -5
- data/lib/sass/error.rb +6 -3
- data/lib/sass/files.rb +8 -1
- data/lib/sass/plugin/rails.rb +2 -2
- data/lib/sass/plugin.rb +260 -28
- data/lib/sass/script/color.rb +216 -30
- data/lib/sass/script/functions.rb +356 -74
- data/lib/sass/script/lexer.rb +7 -4
- data/lib/sass/script/number.rb +2 -0
- data/lib/sass/script/parser.rb +1 -1
- data/lib/sass/script.rb +3 -0
- data/lib/sass/tree/node.rb +1 -1
- data/lib/sass/tree/root_node.rb +6 -0
- data/lib/sass/tree/rule_node.rb +1 -0
- data/lib/sass.rb +4 -0
- data/test/haml/engine_test.rb +25 -0
- data/test/haml/helper_test.rb +81 -1
- data/test/haml/html2haml_test.rb +13 -0
- data/test/haml/spec/README.md +97 -0
- data/test/haml/spec/lua_haml_spec.lua +30 -0
- data/test/haml/spec/ruby_haml_test.rb +19 -0
- data/test/haml/spec/tests.json +534 -0
- data/test/haml/spec_test.rb +0 -0
- data/test/haml/template_test.rb +18 -4
- data/test/haml/util_test.rb +0 -0
- data/test/sass/callbacks_test.rb +61 -0
- data/test/sass/css2sass_test.rb +1 -0
- data/test/sass/engine_test.rb +70 -14
- data/test/sass/functions_test.rb +223 -3
- data/test/sass/plugin_test.rb +193 -25
- data/test/sass/results/options.css +1 -0
- data/test/sass/script_test.rb +5 -5
- data/test/sass/templates/options.sass +2 -0
- data/test/test_helper.rb +12 -5
- 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(
|
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
|
-
#
|
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 `
|
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
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#
|
86
|
-
#
|
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
|
-
#
|
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
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
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
|
-
|
179
|
-
|
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
|
-
|
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
|
-
|
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
|
326
|
-
|
327
|
-
|
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
|
-
|
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
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
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
|
data/lib/sass/script/lexer.rb
CHANGED
@@ -8,20 +8,21 @@ module Sass
|
|
8
8
|
class Lexer
|
9
9
|
# A struct containing information about an individual token.
|
10
10
|
#
|
11
|
-
# `type`: \[
|
11
|
+
# `type`: \[`Symbol`\]
|
12
12
|
# : The type of token.
|
13
13
|
#
|
14
|
-
# `value`: \[
|
14
|
+
# `value`: \[`Object`\]
|
15
15
|
# : The Ruby object corresponding to the value of the token.
|
16
16
|
#
|
17
|
-
# `line`: \[
|
17
|
+
# `line`: \[`Fixnum`\]
|
18
18
|
# : The line of the source file on which the token appears.
|
19
19
|
#
|
20
|
-
# `offset`: \[
|
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-]+)/,
|
data/lib/sass/script/number.rb
CHANGED
@@ -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
|
data/lib/sass/script/parser.rb
CHANGED
@@ -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
|
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
|
data/lib/sass/tree/node.rb
CHANGED
data/lib/sass/tree/root_node.rb
CHANGED
@@ -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,
|
data/lib/sass/tree/rule_node.rb
CHANGED