sass 3.2.0.alpha.104 → 3.2.0.alpha.236
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/REVISION +1 -1
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/lib/sass/engine.rb +8 -1
- data/lib/sass/exec.rb +2 -2
- data/lib/sass/plugin/compiler.rb +51 -43
- data/lib/sass/script/color.rb +4 -9
- data/lib/sass/script/funcall.rb +11 -2
- data/lib/sass/script/functions.rb +16 -30
- data/lib/sass/script/lexer.rb +7 -1
- data/lib/sass/script/list.rb +2 -2
- data/lib/sass/script/literal.rb +8 -0
- data/lib/sass/script/null.rb +34 -0
- data/lib/sass/script/operation.rb +4 -0
- data/lib/sass/script/parser.rb +4 -2
- data/lib/sass/scss/parser.rb +1 -5
- data/lib/sass/scss/rx.rb +1 -1
- data/lib/sass/tree/directive_node.rb +5 -0
- data/lib/sass/tree/media_node.rb +3 -0
- data/lib/sass/tree/prop_node.rb +7 -3
- data/lib/sass/tree/visitors/base.rb +1 -1
- data/lib/sass/tree/visitors/check_nesting.rb +21 -18
- data/lib/sass/tree/visitors/convert.rb +1 -0
- data/lib/sass/tree/visitors/perform.rb +3 -2
- data/lib/sass/tree/visitors/to_css.rb +1 -0
- data/lib/sass/util.rb +28 -0
- data/test/sass/conversion_test.rb +33 -0
- data/test/sass/engine_test.rb +118 -3
- data/test/sass/functions_test.rb +56 -24
- data/test/sass/script_test.rb +60 -4
- data/test/sass/scss/scss_test.rb +10 -0
- data/vendor/listen/CHANGELOG.md +19 -1
- data/vendor/listen/README.md +27 -12
- data/vendor/listen/lib/listen/adapter.rb +9 -1
- data/vendor/listen/lib/listen/adapters/linux.rb +18 -7
- data/vendor/listen/lib/listen/adapters/windows.rb +7 -8
- data/vendor/listen/lib/listen/directory_record.rb +108 -48
- data/vendor/listen/lib/listen/listener.rb +28 -11
- data/vendor/listen/lib/listen/multi_listener.rb +6 -6
- data/vendor/listen/lib/listen/version.rb +1 -1
- data/vendor/listen/spec/listen/adapters/linux_spec.rb +11 -0
- data/vendor/listen/spec/listen/directory_record_spec.rb +268 -41
- data/vendor/listen/spec/listen/listener_spec.rb +8 -4
- data/vendor/listen/spec/listen/multi_listener_spec.rb +9 -4
- data/vendor/listen/spec/support/adapter_helper.rb +178 -0
- data/vendor/listen/spec/support/directory_record_helper.rb +24 -4
- data/vendor/listen/spec/support/listeners_helper.rb +11 -0
- metadata +11 -11
- data/lib/sass/plugin/listener.rb +0 -61
data/REVISION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
4f1b0c5be641db7ccb1d6cd7e50d1b8c809f3b4d
|
data/Rakefile
CHANGED
@@ -51,7 +51,7 @@ task :permissions do
|
|
51
51
|
end
|
52
52
|
|
53
53
|
task :revision_file do
|
54
|
-
require 'lib/sass'
|
54
|
+
require scope('lib/sass')
|
55
55
|
|
56
56
|
release = Rake.application.top_level_tasks.include?('release') || File.exist?(scope('EDGE_GEM_VERSION'))
|
57
57
|
if Sass.version[:rev] && !release
|
@@ -147,7 +147,7 @@ def get_version
|
|
147
147
|
version.map! {|n| n =~ /^[0-9]+$/ ? n.to_i : n}
|
148
148
|
return written_version unless version.size == 5 && version[3] == "alpha" # prerelease
|
149
149
|
|
150
|
-
return written_version if (commit_count = `git log --pretty=oneline
|
150
|
+
return written_version if (commit_count = `git log --pretty=oneline HEAD ^stable | wc -l`).empty?
|
151
151
|
version[4] = commit_count.strip
|
152
152
|
version.join('.')
|
153
153
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.2.0.alpha.
|
1
|
+
3.2.0.alpha.236
|
data/lib/sass/engine.rb
CHANGED
@@ -600,7 +600,14 @@ WARNING
|
|
600
600
|
else
|
601
601
|
expr = parse_script(value, :offset => line.offset + line.text.index(value))
|
602
602
|
end
|
603
|
-
Tree::PropNode.new(parse_interp(name), expr, prop)
|
603
|
+
node = Tree::PropNode.new(parse_interp(name), expr, prop)
|
604
|
+
if value.strip.empty? && line.children.empty?
|
605
|
+
raise SyntaxError.new(
|
606
|
+
"Invalid property: \"#{node.declaration}\" (no value)." +
|
607
|
+
node.pseudo_class_selector_message)
|
608
|
+
end
|
609
|
+
|
610
|
+
node
|
604
611
|
end
|
605
612
|
|
606
613
|
def parse_variable(line)
|
data/lib/sass/exec.rb
CHANGED
@@ -452,7 +452,7 @@ MSG
|
|
452
452
|
def probably_dest_dir?(path)
|
453
453
|
return false unless path
|
454
454
|
return false if colon_path?(path)
|
455
|
-
return
|
455
|
+
return Sass::Util.glob(File.join(path, "*.s[ca]ss")).empty?
|
456
456
|
end
|
457
457
|
end
|
458
458
|
|
@@ -595,7 +595,7 @@ END
|
|
595
595
|
end
|
596
596
|
|
597
597
|
ext = @options[:from]
|
598
|
-
|
598
|
+
Sass::Util.glob("#{@options[:input]}/**/*.#{ext}") do |f|
|
599
599
|
output =
|
600
600
|
if @options[:in_place]
|
601
601
|
f
|
data/lib/sass/plugin/compiler.rb
CHANGED
@@ -5,7 +5,6 @@ require 'sass'
|
|
5
5
|
require 'sass/callbacks'
|
6
6
|
require 'sass/plugin/configuration'
|
7
7
|
require 'sass/plugin/staleness_checker'
|
8
|
-
require 'sass/plugin/listener'
|
9
8
|
|
10
9
|
module Sass::Plugin
|
11
10
|
|
@@ -188,7 +187,7 @@ module Sass::Plugin
|
|
188
187
|
staleness_checker = StalenessChecker.new(engine_options)
|
189
188
|
|
190
189
|
template_location_array.each do |template_location, css_location|
|
191
|
-
|
190
|
+
Sass::Util.glob(File.join(template_location, "**", "[^_]*.s[ca]ss")).sort.each do |file|
|
192
191
|
# Get the relative path to the file
|
193
192
|
name = file.sub(template_location.to_s.sub(/\/*$/, '/'), "")
|
194
193
|
css = css_filename(name, css_location)
|
@@ -252,52 +251,61 @@ module Sass::Plugin
|
|
252
251
|
end
|
253
252
|
end
|
254
253
|
|
254
|
+
template_paths = template_locations # cache the locations
|
255
|
+
individual_files_hash = individual_files.inject({}) do |h, files|
|
256
|
+
parent = File.dirname(files.first)
|
257
|
+
(h[parent] ||= []) << files unless template_paths.include?(parent)
|
258
|
+
h
|
259
|
+
end
|
260
|
+
directories = template_paths + individual_files_hash.keys +
|
261
|
+
[{:relative_paths => true}]
|
262
|
+
|
255
263
|
# TODO: Keep better track of what depends on what
|
256
264
|
# so we don't have to run a global update every time anything changes.
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
:added => lambda do |base, relative|
|
267
|
-
next if relative !~ /\.s[ac]ss$/
|
268
|
-
run_template_created File.join(base, relative)
|
269
|
-
update_stylesheets(individual_files)
|
270
|
-
end,
|
271
|
-
|
272
|
-
:removed => lambda do |base, relative|
|
273
|
-
next if relative !~ /\.s[ac]ss$/
|
274
|
-
run_template_deleted File.join(base, relative)
|
275
|
-
css = File.join(css_location, relative.gsub(/\.s[ac]ss$/, '.css'))
|
276
|
-
try_delete_css css
|
277
|
-
update_stylesheets(individual_files)
|
278
|
-
end
|
279
|
-
})
|
265
|
+
listener = Listen::MultiListener.new(*directories) do |modified, added, removed|
|
266
|
+
modified.each do |f|
|
267
|
+
parent = File.dirname(f)
|
268
|
+
if files = individual_files_hash[parent]
|
269
|
+
next unless files.first == f
|
270
|
+
else
|
271
|
+
next unless f =~ /\.s[ac]ss$/
|
272
|
+
end
|
273
|
+
run_template_modified(f)
|
280
274
|
end
|
281
275
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
276
|
+
added.each do |f|
|
277
|
+
parent = File.dirname(f)
|
278
|
+
if files = individual_files_hash[parent]
|
279
|
+
next unless files.first == f
|
280
|
+
else
|
281
|
+
next unless f =~ /\.s[ac]ss$/
|
282
|
+
end
|
283
|
+
run_template_created(f)
|
284
|
+
end
|
285
|
+
|
286
|
+
removed.each do |f|
|
287
|
+
parent = File.dirname(f)
|
288
|
+
if files = individual_files_hash[parent]
|
289
|
+
next unless files.first == f
|
290
|
+
try_delete_css files[1]
|
291
|
+
else
|
292
|
+
next unless f =~ /\.s[ac]ss$/
|
293
|
+
try_delete_css f.gsub(/\.s[ac]ss$/, '.css')
|
294
|
+
end
|
295
|
+
run_template_deleted(f)
|
300
296
|
end
|
297
|
+
|
298
|
+
update_stylesheets(individual_files)
|
299
|
+
end
|
300
|
+
|
301
|
+
# The native windows listener is much slower than the polling
|
302
|
+
# option, according to https://github.com/nex3/sass/commit/a3031856b22bc834a5417dedecb038b7be9b9e3e#commitcomment-1295118
|
303
|
+
listener.force_polling(true) if Sass::Util.windows?
|
304
|
+
|
305
|
+
begin
|
306
|
+
listener.start
|
307
|
+
rescue Exception => e
|
308
|
+
raise e unless e.is_a?(Interrupt)
|
301
309
|
end
|
302
310
|
end
|
303
311
|
|
data/lib/sass/script/color.rb
CHANGED
@@ -232,21 +232,16 @@ module Sass::Script
|
|
232
232
|
[:red, :green, :blue].each do |k|
|
233
233
|
next if @attrs[k].nil?
|
234
234
|
@attrs[k] = @attrs[k].to_i
|
235
|
-
|
236
|
-
raise ArgumentError.new("#{k.to_s.capitalize} value must be between 0 and 255")
|
235
|
+
Sass::Util.check_range("#{k.to_s.capitalize} value", 0..255, @attrs[k])
|
237
236
|
end
|
238
237
|
|
239
238
|
[:saturation, :lightness].each do |k|
|
240
239
|
next if @attrs[k].nil?
|
241
|
-
|
242
|
-
@attrs[k] =
|
243
|
-
next if (0..100).include?(@attrs[k])
|
244
|
-
raise ArgumentError.new("#{k.to_s.capitalize} must be between 0 and 100")
|
240
|
+
value = Number.new(@attrs[k], ['%']) # Get correct unit for error messages
|
241
|
+
@attrs[k] = Sass::Util.check_range("#{k.to_s.capitalize}", 0..100, value, '%')
|
245
242
|
end
|
246
243
|
|
247
|
-
|
248
|
-
raise ArgumentError.new("Alpha channel must be between 0 and 1")
|
249
|
-
end
|
244
|
+
@attrs[:alpha] = Sass::Util.check_range("Alpha channel", 0..1, @attrs[:alpha])
|
250
245
|
end
|
251
246
|
|
252
247
|
# The red component of the color.
|
data/lib/sass/script/funcall.rb
CHANGED
@@ -136,7 +136,12 @@ module Sass
|
|
136
136
|
if signature.var_kwargs
|
137
137
|
args << keywords
|
138
138
|
else
|
139
|
-
|
139
|
+
argname = keywords.keys.sort.first
|
140
|
+
if signature.args.include?(argname)
|
141
|
+
raise Sass::SyntaxError.new("Function #{name} was passed argument $#{argname} both by position and by name")
|
142
|
+
else
|
143
|
+
raise Sass::SyntaxError.new("Function #{name} doesn't have an argument named $#{argname}")
|
144
|
+
end
|
140
145
|
end
|
141
146
|
end
|
142
147
|
|
@@ -158,9 +163,13 @@ module Sass
|
|
158
163
|
|
159
164
|
environment = function.args.zip(args).
|
160
165
|
inject(Sass::Environment.new(function.environment)) do |env, ((var, default), value)|
|
166
|
+
if value && keywords.include?(var.underscored_name)
|
167
|
+
raise Sass::SyntaxError.new("Function #{@name} was passed argument $#{var.name} both by position and by name")
|
168
|
+
end
|
169
|
+
|
161
170
|
env.set_local_var(var.name,
|
162
171
|
value || keywords[var.underscored_name] || (default && default.perform(env)))
|
163
|
-
raise Sass::SyntaxError.new("Function #{@name} is missing
|
172
|
+
raise Sass::SyntaxError.new("Function #{@name} is missing argument #{var.inspect}") unless env.var(var.name)
|
164
173
|
env
|
165
174
|
end
|
166
175
|
|
@@ -375,11 +375,10 @@ module Sass::Script
|
|
375
375
|
Color.new([red, green, blue].map do |c|
|
376
376
|
v = c.value
|
377
377
|
if c.numerator_units == ["%"] && c.denominator_units.empty?
|
378
|
-
|
379
|
-
|
378
|
+
v = Sass::Util.check_range("Color value", 0..100, c, '%')
|
379
|
+
v * 255 / 100.0
|
380
380
|
else
|
381
|
-
|
382
|
-
raise ArgumentError.new("Color value #{v} must be between 0 and 255 inclusive")
|
381
|
+
Sass::Util.check_range("Color value", 0..255, c)
|
383
382
|
end
|
384
383
|
end)
|
385
384
|
end
|
@@ -419,10 +418,7 @@ module Sass::Script
|
|
419
418
|
assert_type color, :Color
|
420
419
|
assert_type alpha, :Number
|
421
420
|
|
422
|
-
|
423
|
-
raise ArgumentError.new("Alpha channel #{alpha.value} must be between 0 and 1 inclusive")
|
424
|
-
end
|
425
|
-
|
421
|
+
Sass::Util.check_range('Alpha channel', 0..1, alpha)
|
426
422
|
color.with(:alpha => alpha.value)
|
427
423
|
when 4
|
428
424
|
red, green, blue, alpha = args
|
@@ -472,16 +468,11 @@ module Sass::Script
|
|
472
468
|
assert_type lightness, :Number
|
473
469
|
assert_type alpha, :Number
|
474
470
|
|
475
|
-
|
476
|
-
raise ArgumentError.new("Alpha channel #{alpha.value} must be between 0 and 1")
|
477
|
-
end
|
471
|
+
Sass::Util.check_range('Alpha channel', 0..1, alpha)
|
478
472
|
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
h, s, l = [hue, saturation, lightness].map { |a| a.value }
|
483
|
-
raise ArgumentError.new("Saturation #{s} must be between 0% and 100%") unless (0..100).include?(s)
|
484
|
-
raise ArgumentError.new("Lightness #{l} must be between 0% and 100%") unless (0..100).include?(l)
|
473
|
+
h = hue.value
|
474
|
+
s = Sass::Util.check_range('Saturation', 0..100, saturation, '%')
|
475
|
+
l = Sass::Util.check_range('Lightness', 0..100, lightness, '%')
|
485
476
|
|
486
477
|
Color.new(:hue => h, :saturation => s, :lightness => l, :alpha => alpha.value)
|
487
478
|
end
|
@@ -804,9 +795,7 @@ module Sass::Script
|
|
804
795
|
|
805
796
|
next unless val = kwargs.delete(name)
|
806
797
|
assert_type val, :Number, name
|
807
|
-
|
808
|
-
raise ArgumentError.new("$#{name}: Amount #{val} must be between #{range.first}#{units} and #{range.last}#{units}")
|
809
|
-
end
|
798
|
+
Sass::Util.check_range("$#{name}: Amount", range, val, units) if range
|
810
799
|
adjusted = color.send(name) + val.value
|
811
800
|
adjusted = [0, Sass::Util.restrict(adjusted, range)].max if range
|
812
801
|
[name.to_sym, adjusted]
|
@@ -875,8 +864,8 @@ module Sass::Script
|
|
875
864
|
assert_type val, :Number, name
|
876
865
|
if !(val.numerator_units == ['%'] && val.denominator_units.empty?)
|
877
866
|
raise ArgumentError.new("$#{name}: Amount #{val} must be a % (e.g. #{val.value}%)")
|
878
|
-
|
879
|
-
|
867
|
+
else
|
868
|
+
Sass::Util.check_range("$#{name}: Amount", -100..100, val, '%')
|
880
869
|
end
|
881
870
|
|
882
871
|
current = color.send(name)
|
@@ -970,9 +959,7 @@ module Sass::Script
|
|
970
959
|
assert_type color2, :Color
|
971
960
|
assert_type weight, :Number
|
972
961
|
|
973
|
-
|
974
|
-
raise ArgumentError.new("Weight #{weight} must be between 0% and 100%")
|
975
|
-
end
|
962
|
+
Sass::Util.check_range("Weight", 0..100, weight, '%')
|
976
963
|
|
977
964
|
# This algorithm factors in both the user-provided weight
|
978
965
|
# and the difference between the alpha values of the two colors
|
@@ -1054,6 +1041,7 @@ module Sass::Script
|
|
1054
1041
|
:green => (255 - color.green),
|
1055
1042
|
:blue => (255 - color.blue))
|
1056
1043
|
end
|
1044
|
+
declare :invert, [:color]
|
1057
1045
|
|
1058
1046
|
# Removes quotes from a string if the string is quoted,
|
1059
1047
|
# or returns the same string if it's not.
|
@@ -1186,8 +1174,8 @@ module Sass::Script
|
|
1186
1174
|
# Rounds a number up to the nearest whole number.
|
1187
1175
|
#
|
1188
1176
|
# @example
|
1189
|
-
#
|
1190
|
-
#
|
1177
|
+
# ceil(10.4px) => 11px
|
1178
|
+
# ceil(10.6px) => 11px
|
1191
1179
|
# @param value [Number] The number
|
1192
1180
|
# @return [Number] The rounded number
|
1193
1181
|
# @raise [ArgumentError] if `value` isn't a number
|
@@ -1438,9 +1426,7 @@ module Sass::Script
|
|
1438
1426
|
def _adjust(color, amount, attr, range, op, units = "")
|
1439
1427
|
assert_type color, :Color
|
1440
1428
|
assert_type amount, :Number
|
1441
|
-
|
1442
|
-
raise ArgumentError.new("Amount #{amount} must be between #{range.first}#{units} and #{range.last}#{units}")
|
1443
|
-
end
|
1429
|
+
Sass::Util.check_range('Amount', range, amount, units)
|
1444
1430
|
|
1445
1431
|
# TODO: is it worth restricting here,
|
1446
1432
|
# or should we do so in the Color constructor itself,
|
data/lib/sass/script/lexer.rb
CHANGED
@@ -90,6 +90,7 @@ module Sass
|
|
90
90
|
:number => /(-)?(?:(\d*\.\d+)|(\d+))([a-zA-Z%]+)?/,
|
91
91
|
:color => HEXCOLOR,
|
92
92
|
:bool => /(true|false)\b/,
|
93
|
+
:null => /null\b/,
|
93
94
|
:ident_op => %r{(#{Regexp.union(*IDENT_OP_NAMES.map{|s| Regexp.new(Regexp.escape(s) + "(?!#{NMCHAR}|\Z)")})})},
|
94
95
|
:op => %r{(#{Regexp.union(*OP_NAMES)})},
|
95
96
|
}
|
@@ -234,7 +235,7 @@ module Sass
|
|
234
235
|
end
|
235
236
|
|
236
237
|
variable || string(:double, false) || string(:single, false) || number ||
|
237
|
-
color || bool || string(:uri, false) || raw(UNICODERANGE) ||
|
238
|
+
color || bool || null || string(:uri, false) || raw(UNICODERANGE) ||
|
238
239
|
special_fun || special_val || ident_op || ident || op
|
239
240
|
end
|
240
241
|
|
@@ -292,6 +293,11 @@ MESSAGE
|
|
292
293
|
[:bool, Script::Bool.new(s == 'true')]
|
293
294
|
end
|
294
295
|
|
296
|
+
def null
|
297
|
+
return unless scan(REGULAR_EXPRESSIONS[:null])
|
298
|
+
[:null, Script::Null.new]
|
299
|
+
end
|
300
|
+
|
295
301
|
def special_fun
|
296
302
|
return unless str1 = scan(/((-[\w-]+-)?(calc|element)|expression|progid:[a-z\.]*)\(/i)
|
297
303
|
str2, _ = Sass::Shared.balance(@scanner, ?(, ?), 1)
|
data/lib/sass/script/list.rb
CHANGED
@@ -41,14 +41,14 @@ module Sass::Script
|
|
41
41
|
# @see Node#to_s
|
42
42
|
def to_s(opts = {})
|
43
43
|
raise Sass::SyntaxError.new("() isn't a valid CSS value.") if value.empty?
|
44
|
-
return value.reject {|e| e.is_a?(List) && e.value.empty?}.map {|e| e.to_s(opts)}.join(sep_str)
|
44
|
+
return value.reject {|e| e.is_a?(Null) || e.is_a?(List) && e.value.empty?}.map {|e| e.to_s(opts)}.join(sep_str)
|
45
45
|
end
|
46
46
|
|
47
47
|
# @see Node#to_sass
|
48
48
|
def to_sass(opts = {})
|
49
49
|
return "()" if value.empty?
|
50
50
|
precedence = Sass::Script::Parser.precedence_of(separator)
|
51
|
-
value.map do |v|
|
51
|
+
value.reject {|e| e.is_a?(Null)}.map do |v|
|
52
52
|
if v.is_a?(List) && Sass::Script::Parser.precedence_of(v.separator) <= precedence
|
53
53
|
"(#{v.to_sass(opts)})"
|
54
54
|
else
|
data/lib/sass/script/literal.rb
CHANGED
@@ -9,6 +9,7 @@ module Sass::Script
|
|
9
9
|
require 'sass/script/number'
|
10
10
|
require 'sass/script/color'
|
11
11
|
require 'sass/script/bool'
|
12
|
+
require 'sass/script/null'
|
12
13
|
require 'sass/script/list'
|
13
14
|
|
14
15
|
# Returns the Ruby value of the literal.
|
@@ -217,6 +218,13 @@ MSG
|
|
217
218
|
end
|
218
219
|
alias_method :to_sass, :to_s
|
219
220
|
|
221
|
+
# Returns whether or not this object is null.
|
222
|
+
#
|
223
|
+
# @return [Boolean] `false`
|
224
|
+
def null?
|
225
|
+
false
|
226
|
+
end
|
227
|
+
|
220
228
|
protected
|
221
229
|
|
222
230
|
# Evaluates the literal.
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'sass/script/literal'
|
2
|
+
|
3
|
+
module Sass::Script
|
4
|
+
# A SassScript object representing a null value.
|
5
|
+
class Null < Literal
|
6
|
+
# Creates a new null literal.
|
7
|
+
def initialize
|
8
|
+
super nil
|
9
|
+
end
|
10
|
+
|
11
|
+
# @return [Boolean] `false` (the Ruby boolean value)
|
12
|
+
def to_bool
|
13
|
+
false
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [Boolean] `true`
|
17
|
+
def null?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [String] '' (An empty string)
|
22
|
+
def to_s(opts = {})
|
23
|
+
''
|
24
|
+
end
|
25
|
+
alias_method :to_sass, :to_s
|
26
|
+
|
27
|
+
# Returns a string representing a null value.
|
28
|
+
#
|
29
|
+
# @return [String]
|
30
|
+
def inspect
|
31
|
+
'null'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -82,6 +82,10 @@ module Sass::Script
|
|
82
82
|
|
83
83
|
literal2 = @operand2.perform(environment)
|
84
84
|
|
85
|
+
if literal1.is_a?(Null) || literal2.is_a?(Null)
|
86
|
+
raise Sass::SyntaxError.new("Invalid null operation: \"#{literal1.inspect} #{@operator} #{literal2.inspect}\".")
|
87
|
+
end
|
88
|
+
|
85
89
|
begin
|
86
90
|
opts(literal1.send(@operator, literal2))
|
87
91
|
rescue NoMethodError => e
|