haml-edge 2.3.27 → 2.3.28
Sign up to get free protection for your applications and to get access to all the features.
- data/EDGE_GEM_VERSION +1 -1
- data/VERSION +1 -1
- data/lib/haml/exec.rb +1 -1
- data/lib/sass/engine.rb +46 -28
- data/lib/sass/error.rb +130 -25
- data/lib/sass/files.rb +4 -10
- data/lib/sass/plugin.rb +2 -44
- data/lib/sass/script/parser.rb +1 -1
- data/lib/sass/script.rb +2 -6
- data/lib/sass/tree/comment_node.rb +11 -11
- data/lib/sass/tree/directive_node.rb +3 -1
- data/lib/sass/tree/import_node.rb +16 -12
- data/lib/sass/tree/mixin_node.rb +1 -1
- data/lib/sass/tree/node.rb +29 -26
- data/lib/sass/tree/prop_node.rb +8 -11
- data/lib/sass/tree/root_node.rb +56 -0
- data/lib/sass/tree/rule_node.rb +4 -4
- data/test/sass/engine_test.rb +64 -2
- data/test/sass/plugin_test.rb +14 -7
- data/test/sass/templates/{bork.sass → bork1.sass} +0 -0
- data/test/sass/templates/bork3.sass +2 -0
- data/test/sass/templates/nested_bork1.sass +2 -0
- data/test/sass/templates/nested_bork2.sass +2 -0
- data/test/sass/templates/nested_bork3.sass +2 -0
- metadata +8 -3
data/EDGE_GEM_VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.3.
|
1
|
+
2.3.28
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.3.
|
1
|
+
2.3.28
|
data/lib/haml/exec.rb
CHANGED
data/lib/sass/engine.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'strscan'
|
2
2
|
require 'digest/sha1'
|
3
3
|
require 'sass/tree/node'
|
4
|
+
require 'sass/tree/root_node'
|
4
5
|
require 'sass/tree/rule_node'
|
5
6
|
require 'sass/tree/comment_node'
|
6
7
|
require 'sass/tree/prop_node'
|
@@ -155,11 +156,14 @@ module Sass
|
|
155
156
|
# @return [Sass::Tree::Node] The root of the parse tree.
|
156
157
|
# @raise [Sass::SyntaxError] if there's an error in the document
|
157
158
|
def to_tree
|
158
|
-
root = Tree::
|
159
|
+
root = Tree::RootNode.new(@template)
|
159
160
|
append_children(root, tree(tabulate(@template)).first, true)
|
160
161
|
root.options = @options
|
161
162
|
root
|
162
|
-
rescue SyntaxError => e
|
163
|
+
rescue SyntaxError => e
|
164
|
+
e.modify_backtrace(:filename => @options[:filename], :line => @line)
|
165
|
+
e.sass_template = @template
|
166
|
+
raise e
|
163
167
|
end
|
164
168
|
|
165
169
|
private
|
@@ -179,10 +183,11 @@ module Sass
|
|
179
183
|
unless line_tab_str.empty?
|
180
184
|
tab_str ||= line_tab_str
|
181
185
|
|
182
|
-
raise SyntaxError.new("Indenting at the beginning of the document is illegal.",
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
+
raise SyntaxError.new("Indenting at the beginning of the document is illegal.",
|
187
|
+
:line => index) if first
|
188
|
+
|
189
|
+
raise SyntaxError.new("Indentation can't use both tabs and spaces.",
|
190
|
+
:line => index) if tab_str.include?(?\s) && tab_str.include?(?\t)
|
186
191
|
end
|
187
192
|
first &&= !tab_str.nil?
|
188
193
|
if tab_str.nil?
|
@@ -196,10 +201,14 @@ module Sass
|
|
196
201
|
end
|
197
202
|
|
198
203
|
line_tabs = line_tab_str.scan(tab_str).size
|
199
|
-
|
204
|
+
if tab_str * line_tabs != line_tab_str
|
205
|
+
message = <<END.strip.gsub("\n", ' ')
|
200
206
|
Inconsistent indentation: #{Haml::Shared.human_indentation line_tab_str, true} used for indentation,
|
201
207
|
but the rest of the document was indented using #{Haml::Shared.human_indentation tab_str}.
|
202
208
|
END
|
209
|
+
raise SyntaxError.new(message, :line => index)
|
210
|
+
end
|
211
|
+
|
203
212
|
lines << Line.new(line.strip, line_tabs, index, tab_str.size, @options[:filename], [])
|
204
213
|
end
|
205
214
|
lines
|
@@ -212,9 +221,8 @@ END
|
|
212
221
|
nodes = []
|
213
222
|
while (line = arr[i]) && line.tabs >= base
|
214
223
|
if line.tabs > base
|
215
|
-
|
216
|
-
|
217
|
-
end
|
224
|
+
raise SyntaxError.new("The line was indented #{line.tabs - base} levels deeper than the previous line.",
|
225
|
+
:line => line.index) if line.tabs > base + 1
|
218
226
|
|
219
227
|
nodes.last.children, i = tree(arr, i)
|
220
228
|
else
|
@@ -252,7 +260,8 @@ END
|
|
252
260
|
child = build_tree(parent, line, root)
|
253
261
|
|
254
262
|
if child.is_a?(Tree::RuleNode) && child.continued?
|
255
|
-
raise SyntaxError.new("Rules can't end in commas.",
|
263
|
+
raise SyntaxError.new("Rules can't end in commas.",
|
264
|
+
:line => child.line) unless child.children.empty?
|
256
265
|
if continued_rule
|
257
266
|
continued_rule.add_rules child
|
258
267
|
else
|
@@ -262,7 +271,8 @@ END
|
|
262
271
|
end
|
263
272
|
|
264
273
|
if continued_rule
|
265
|
-
raise SyntaxError.new("Rules can't end in commas.",
|
274
|
+
raise SyntaxError.new("Rules can't end in commas.",
|
275
|
+
:line => continued_rule.line) unless child.is_a?(Tree::RuleNode)
|
266
276
|
continued_rule.add_rules child
|
267
277
|
continued_rule.children = child.children
|
268
278
|
continued_rule, child = nil, continued_rule
|
@@ -272,7 +282,8 @@ END
|
|
272
282
|
validate_and_append_child(parent, child, line, root)
|
273
283
|
end
|
274
284
|
|
275
|
-
raise SyntaxError.new("Rules can't end in commas.",
|
285
|
+
raise SyntaxError.new("Rules can't end in commas.",
|
286
|
+
:line => continued_rule.line) if continued_rule
|
276
287
|
|
277
288
|
parent
|
278
289
|
end
|
@@ -281,9 +292,11 @@ END
|
|
281
292
|
unless root
|
282
293
|
case child
|
283
294
|
when Tree::MixinDefNode
|
284
|
-
raise SyntaxError.new("Mixins may only be defined at the root of a document.",
|
295
|
+
raise SyntaxError.new("Mixins may only be defined at the root of a document.",
|
296
|
+
:line => line.index)
|
285
297
|
when Tree::ImportNode
|
286
|
-
raise SyntaxError.new("Import directives may only be used at the root of a document.",
|
298
|
+
raise SyntaxError.new("Import directives may only be used at the root of a document.",
|
299
|
+
:line => line.index)
|
287
300
|
end
|
288
301
|
end
|
289
302
|
|
@@ -349,9 +362,9 @@ LONG
|
|
349
362
|
def parse_property(line, property_regx)
|
350
363
|
name, eq, value = line.text.scan(property_regx)[0]
|
351
364
|
|
352
|
-
|
353
|
-
|
354
|
-
|
365
|
+
raise SyntaxError.new("Invalid property: \"#{line.text}\".",
|
366
|
+
:line => @line) if name.nil? || value.nil?
|
367
|
+
|
355
368
|
expr = if (eq.strip[0] == SCRIPT_CHAR)
|
356
369
|
parse_script(value, :offset => line.offset + line.text.index(value))
|
357
370
|
else
|
@@ -362,8 +375,10 @@ LONG
|
|
362
375
|
|
363
376
|
def parse_variable(line)
|
364
377
|
name, op, value = line.text.scan(Script::MATCH)[0]
|
365
|
-
raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath variable declarations.",
|
366
|
-
|
378
|
+
raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath variable declarations.",
|
379
|
+
:line => @line + 1) unless line.children.empty?
|
380
|
+
raise SyntaxError.new("Invalid variable: \"#{line.text}\".",
|
381
|
+
:line => @line) unless name && value
|
367
382
|
|
368
383
|
Tree::VariableNode.new(name, parse_script(value, :offset => line.offset + line.text.index(value)), op == '||=')
|
369
384
|
end
|
@@ -383,7 +398,8 @@ LONG
|
|
383
398
|
# If value begins with url( or ",
|
384
399
|
# it's a CSS @import rule and we don't want to touch it.
|
385
400
|
if directive == "import" && value !~ /^(url\(|")/
|
386
|
-
raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath import directives.",
|
401
|
+
raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath import directives.",
|
402
|
+
:line => @line + 1) unless line.children.empty?
|
387
403
|
value.split(/,\s*/).map {|f| Tree::ImportNode.new(f)}
|
388
404
|
elsif directive == "for"
|
389
405
|
parse_for(line, root, value)
|
@@ -397,7 +413,8 @@ LONG
|
|
397
413
|
Tree::IfNode.new(parse_script(value, :offset => offset))
|
398
414
|
elsif directive == "debug"
|
399
415
|
raise SyntaxError.new("Invalid debug directive '@debug': expected expression.") unless value
|
400
|
-
raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath debug directives.",
|
416
|
+
raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath debug directives.",
|
417
|
+
:line => @line + 1) unless line.children.empty?
|
401
418
|
offset = line.offset + line.text.index(value).to_i
|
402
419
|
Tree::DebugNode.new(parse_script(value, :offset => offset))
|
403
420
|
else
|
@@ -416,9 +433,9 @@ LONG
|
|
416
433
|
else
|
417
434
|
expected = "'to <expr>' or 'through <expr>'"
|
418
435
|
end
|
419
|
-
raise SyntaxError.new("Invalid for directive '@for #{text}': expected #{expected}."
|
436
|
+
raise SyntaxError.new("Invalid for directive '@for #{text}': expected #{expected}.")
|
420
437
|
end
|
421
|
-
raise SyntaxError.new("Invalid variable \"#{var}\"."
|
438
|
+
raise SyntaxError.new("Invalid variable \"#{var}\".") unless var =~ Script::VALIDATE
|
422
439
|
|
423
440
|
parsed_from = parse_script(from_expr, :offset => line.offset + line.text.index(from_expr))
|
424
441
|
parsed_to = parse_script(to_expr, :offset => line.offset + line.text.index(to_expr))
|
@@ -431,7 +448,7 @@ LONG
|
|
431
448
|
|
432
449
|
if text
|
433
450
|
if text !~ /^if\s+(.+)/
|
434
|
-
raise SyntaxError.new("Invalid else directive '@else #{text}': expected 'if <expr>'."
|
451
|
+
raise SyntaxError.new("Invalid else directive '@else #{text}': expected 'if <expr>'.")
|
435
452
|
end
|
436
453
|
expr = parse_script($1, :offset => line.offset + line.text.index($1))
|
437
454
|
end
|
@@ -444,7 +461,7 @@ LONG
|
|
444
461
|
|
445
462
|
def parse_mixin_definition(line)
|
446
463
|
name, arg_string = line.text.scan(/^=\s*([^(]+)(.*)$/).first
|
447
|
-
raise SyntaxError.new("Invalid mixin \"#{line.text[1..-1]}\"."
|
464
|
+
raise SyntaxError.new("Invalid mixin \"#{line.text[1..-1]}\".") if name.nil?
|
448
465
|
|
449
466
|
offset = line.offset + line.text.size - arg_string.size
|
450
467
|
args = Script::Parser.new(arg_string.strip, @line, offset).parse_mixin_definition_arglist
|
@@ -454,11 +471,12 @@ LONG
|
|
454
471
|
|
455
472
|
def parse_mixin_include(line, root)
|
456
473
|
name, arg_string = line.text.scan(/^\+\s*([^(]+)(.*)$/).first
|
457
|
-
raise SyntaxError.new("Invalid mixin include \"#{line.text}\"."
|
474
|
+
raise SyntaxError.new("Invalid mixin include \"#{line.text}\".") if name.nil?
|
458
475
|
|
459
476
|
offset = line.offset + line.text.size - arg_string.size
|
460
477
|
args = Script::Parser.new(arg_string.strip, @line, offset).parse_mixin_include_arglist
|
461
|
-
raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath mixin directives.",
|
478
|
+
raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath mixin directives.",
|
479
|
+
:line => @line + 1) unless line.children.empty?
|
462
480
|
Tree::MixinNode.new(name, args)
|
463
481
|
end
|
464
482
|
|
data/lib/sass/error.rb
CHANGED
@@ -4,51 +4,156 @@ module Sass
|
|
4
4
|
# and the Sass file that was being parsed (if applicable).
|
5
5
|
#
|
6
6
|
# All Sass errors are raised as {Sass::SyntaxError}s.
|
7
|
+
#
|
8
|
+
# When dealing with SyntaxErrors,
|
9
|
+
# it's important to provide filename and line number information.
|
10
|
+
# This will be used in various error reports to users, including backtraces;
|
11
|
+
# see \{#sass\_backtrace} for details.
|
12
|
+
#
|
13
|
+
# Some of this information is usually provided as part of the constructor.
|
14
|
+
# New backtrace entries can be added with \{#add\_backtrace},
|
15
|
+
# which is called when an exception is raised between files (e.g. with `@import`).
|
16
|
+
#
|
17
|
+
# Often, a chunk of code will all have similar backtrace information -
|
18
|
+
# the same filename or even line.
|
19
|
+
# It may also be useful to have a default line number set.
|
20
|
+
# In those situations, the default values can be used
|
21
|
+
# by omitting the information on the original exception,
|
22
|
+
# and then calling \{#modify\_backtrace} in a wrapper `rescue`.
|
23
|
+
# When doing this, be sure that all exceptions ultimately end up
|
24
|
+
# with the information filled in.
|
7
25
|
class SyntaxError < StandardError
|
8
|
-
# The
|
26
|
+
# The backtrace of the error within Sass files.
|
27
|
+
# This is an array of hashes containing information for a single entry.
|
28
|
+
# The hashes have the following keys:
|
9
29
|
#
|
10
|
-
#
|
11
|
-
|
30
|
+
# `:filename`
|
31
|
+
# : The name of the file in which the exception was raised,
|
32
|
+
# or `nil` if no filename is available.
|
33
|
+
#
|
34
|
+
# `:line`
|
35
|
+
# : The line of the file on which the error occurred. Never nil.
|
36
|
+
#
|
37
|
+
# This information is also included in standard backtrace format
|
38
|
+
# in the output of \{#backtrace}.
|
39
|
+
#
|
40
|
+
# @return [Aray<Hash<Symbol, Object>>]
|
41
|
+
attr_accessor :sass_backtrace
|
12
42
|
|
13
|
-
# The
|
14
|
-
# This could be `nil` if no filename is available.
|
43
|
+
# The text of the template where this error was raised.
|
15
44
|
#
|
16
45
|
# @return [String]
|
17
|
-
|
46
|
+
attr_accessor :sass_template
|
18
47
|
|
19
48
|
# @param msg [String] The error message
|
20
|
-
# @param
|
21
|
-
|
49
|
+
# @param attrs [Hash<Symbol, Object>] The information in the backtrace entry.
|
50
|
+
# See \{#sass\_backtrace}
|
51
|
+
def initialize(msg, attrs = {})
|
22
52
|
@message = msg
|
23
|
-
@
|
53
|
+
@sass_backtrace = []
|
54
|
+
add_backtrace(attrs)
|
24
55
|
end
|
25
56
|
|
26
|
-
#
|
27
|
-
#
|
57
|
+
# The name of the file in which the exception was raised.
|
58
|
+
# This could be `nil` if no filename is available.
|
28
59
|
#
|
29
|
-
# @
|
30
|
-
|
31
|
-
|
32
|
-
def add_metadata(filename, line)
|
33
|
-
self.sass_line ||= line
|
34
|
-
add_backtrace_entry(filename) unless sass_filename
|
35
|
-
raise self
|
60
|
+
# @return [String]
|
61
|
+
def sass_filename
|
62
|
+
sass_backtrace.first[:filename]
|
36
63
|
end
|
37
64
|
|
38
|
-
#
|
65
|
+
# The line of the Sass template on which the error occurred.
|
39
66
|
#
|
40
|
-
# @
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
67
|
+
# @return [Fixnum]
|
68
|
+
def sass_line
|
69
|
+
sass_backtrace.first[:line]
|
70
|
+
end
|
71
|
+
|
72
|
+
# Adds an entry to the exception's Sass backtrace.
|
73
|
+
#
|
74
|
+
# @param attrs [Hash<Symbol, Object>] The information in the backtrace entry.
|
75
|
+
# See \{#sass\_backtrace}
|
76
|
+
def add_backtrace(attrs)
|
77
|
+
sass_backtrace << attrs.reject {|k, v| v.nil?}
|
78
|
+
end
|
79
|
+
|
80
|
+
# Modify the top Sass backtrace entry (that is, the last one)
|
81
|
+
# to have the given attributes.
|
82
|
+
# If that entry already has one of the given attributes set,
|
83
|
+
# that takes precendence.
|
84
|
+
#
|
85
|
+
# @param attrs [Hash<Symbol, Object>] The information to add to the backtrace entry.
|
86
|
+
# See \{#sass\_backtrace}
|
87
|
+
def modify_backtrace(attrs)
|
88
|
+
sass_backtrace[-1] = attrs.reject {|k, v| v.nil?}.merge(sass_backtrace.last)
|
46
89
|
end
|
47
90
|
|
48
91
|
# @return [String] The error message
|
49
92
|
def to_s
|
50
93
|
@message
|
51
94
|
end
|
95
|
+
|
96
|
+
# Returns the standard exception backtrace,
|
97
|
+
# including the Sass backtrace.
|
98
|
+
#
|
99
|
+
# @return [Array<String>]
|
100
|
+
def backtrace
|
101
|
+
return nil if super.nil?
|
102
|
+
sass_backtrace.map {|h| "#{h[:filename] || "(sass)"}:#{h[:line]}"} + super
|
103
|
+
end
|
104
|
+
|
105
|
+
# Returns a string representation of the Sass backtrace.
|
106
|
+
#
|
107
|
+
# @param default_filename [String] The filename to use for unknown files
|
108
|
+
# @see #sass_backtrace
|
109
|
+
# @return [String]
|
110
|
+
def sass_backtrace_str(default_filename = "an unknown file")
|
111
|
+
"Syntax error: #{message}" +
|
112
|
+
Haml::Util.enum_with_index(sass_backtrace).map do |entry, i|
|
113
|
+
"\n #{i == 0 ? "on" : "from"} line #{entry[:line]}" +
|
114
|
+
" of #{entry[:filename] || default_filename}"
|
115
|
+
end.join
|
116
|
+
end
|
117
|
+
|
118
|
+
class << self
|
119
|
+
# Returns an error report for an exception in CSS format.
|
120
|
+
#
|
121
|
+
# @param e [Exception]
|
122
|
+
# @param full_exception [Boolean] The value of
|
123
|
+
# \{file:SASS\_REFERENCE.md#full_exception-option `options[:full_exception]`}
|
124
|
+
def exception_to_css(e, options)
|
125
|
+
return "/* Internal stylesheet error */" unless options[:full_exception]
|
126
|
+
|
127
|
+
header = header_string(e, options)
|
128
|
+
|
129
|
+
<<END
|
130
|
+
/*
|
131
|
+
#{header}
|
132
|
+
|
133
|
+
Backtrace:\n#{e.backtrace.join("\n")}
|
134
|
+
*/
|
135
|
+
body:before {
|
136
|
+
white-space: pre;
|
137
|
+
font-family: monospace;
|
138
|
+
content: "#{header.gsub('"', '\"').gsub("\n", '\\A ')}"; }
|
139
|
+
END
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
def header_string(e, options)
|
145
|
+
return "#{e.class}: #{e.message}" unless e.is_a? Sass::SyntaxError
|
146
|
+
|
147
|
+
line_offset = options[:line] || 1
|
148
|
+
line_num = e.sass_line + 1 - line_offset
|
149
|
+
min = [line_num - 6, 0].max
|
150
|
+
section = e.sass_template.rstrip.split("\n")[min ... line_num + 5]
|
151
|
+
return e.sass_backtrace_str if section.nil? || section.empty?
|
152
|
+
|
153
|
+
e.sass_backtrace_str + "\n\n" + Haml::Util.enum_with_index(section).
|
154
|
+
map {|line, i| "#{line_offset + min + i}: #{line}"}.join("\n")
|
155
|
+
end
|
156
|
+
end
|
52
157
|
end
|
53
158
|
|
54
159
|
# The class for Sass errors that are raised due to invalid unit conversions
|
data/lib/sass/files.rb
CHANGED
@@ -13,7 +13,8 @@ module Sass
|
|
13
13
|
# @param filename [String] The path to the Sass file
|
14
14
|
# @param options [Hash<Symbol, Object>] The options hash.
|
15
15
|
# Only the {file:SASS_REFERENCE.md#cache-option `:cache_location`} option is used
|
16
|
-
# @raise [Sass::SyntaxError] if there's an error in the document
|
16
|
+
# @raise [Sass::SyntaxError] if there's an error in the document.
|
17
|
+
# The caller has responsibility for setting backtrace information, if necessary
|
17
18
|
def tree_for(filename, options)
|
18
19
|
options = Sass::Engine::DEFAULT_OPTIONS.merge(options)
|
19
20
|
text = File.read(filename)
|
@@ -30,15 +31,8 @@ module Sass
|
|
30
31
|
|
31
32
|
engine = Sass::Engine.new(text, options.merge(:filename => filename))
|
32
33
|
|
33
|
-
|
34
|
-
root = engine.to_tree
|
35
|
-
rescue Sass::SyntaxError => err
|
36
|
-
err.add_backtrace_entry(filename)
|
37
|
-
raise err
|
38
|
-
end
|
39
|
-
|
34
|
+
root = engine.to_tree
|
40
35
|
try_to_write_sassc(root, compiled_filename, sha, options) if options[:cache]
|
41
|
-
|
42
36
|
root
|
43
37
|
end
|
44
38
|
|
@@ -77,7 +71,7 @@ module Sass
|
|
77
71
|
|
78
72
|
return new_filename if new_filename
|
79
73
|
return filename + '.css' unless was_sass
|
80
|
-
raise SyntaxError.new("File to import not found or unreadable: #{original_filename}."
|
74
|
+
raise SyntaxError.new("File to import not found or unreadable: #{original_filename}.")
|
81
75
|
end
|
82
76
|
|
83
77
|
private
|
data/lib/sass/plugin.rb
CHANGED
@@ -9,6 +9,7 @@ module Sass
|
|
9
9
|
# when it's used as a plugin for various frameworks.
|
10
10
|
# Currently Rails and Merb are supported out of the box.
|
11
11
|
module Plugin
|
12
|
+
include Haml::Util
|
12
13
|
extend self
|
13
14
|
|
14
15
|
@options = {
|
@@ -82,7 +83,7 @@ module Sass
|
|
82
83
|
result = begin
|
83
84
|
Sass::Files.tree_for(filename, engine_options(:css_filename => css, :filename => filename)).render
|
84
85
|
rescue Exception => e
|
85
|
-
|
86
|
+
Sass::SyntaxError.exception_to_css(e, options)
|
86
87
|
end
|
87
88
|
|
88
89
|
# Create any directories that might be necessary
|
@@ -122,49 +123,6 @@ module Sass
|
|
122
123
|
end
|
123
124
|
end
|
124
125
|
|
125
|
-
def exception_string(e)
|
126
|
-
if options[:full_exception]
|
127
|
-
e_string = "#{e.class}: #{e.message}"
|
128
|
-
|
129
|
-
if e.is_a? Sass::SyntaxError
|
130
|
-
e_string << "\non line #{e.sass_line}"
|
131
|
-
|
132
|
-
if e.sass_filename
|
133
|
-
e_string << " of #{e.sass_filename}"
|
134
|
-
|
135
|
-
if File.exists?(e.sass_filename)
|
136
|
-
e_string << "\n\n"
|
137
|
-
|
138
|
-
min = [e.sass_line - 5, 0].max
|
139
|
-
begin
|
140
|
-
File.read(e.sass_filename).rstrip.split("\n")[
|
141
|
-
min .. e.sass_line + 5
|
142
|
-
].each_with_index do |line, i|
|
143
|
-
e_string << "#{min + i + 1}: #{line}\n"
|
144
|
-
end
|
145
|
-
rescue
|
146
|
-
e_string << "Couldn't read sass file: #{e.sass_filename}"
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
<<END
|
152
|
-
/*
|
153
|
-
#{e_string}
|
154
|
-
|
155
|
-
Backtrace:\n#{e.backtrace.join("\n")}
|
156
|
-
*/
|
157
|
-
body:before {
|
158
|
-
white-space: pre;
|
159
|
-
font-family: monospace;
|
160
|
-
content: "#{e_string.gsub('"', '\"').gsub("\n", '\\A ')}"; }
|
161
|
-
END
|
162
|
-
# Fix an emacs syntax-highlighting hiccup: '
|
163
|
-
else
|
164
|
-
"/* Internal stylesheet error */"
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
126
|
def template_filename(name, path)
|
169
127
|
"#{path}/#{name}.sass"
|
170
128
|
end
|
data/lib/sass/script/parser.rb
CHANGED
@@ -158,7 +158,7 @@ END
|
|
158
158
|
if try_tok(:single_eq)
|
159
159
|
val = assert_expr(:concat)
|
160
160
|
elsif must_have_default
|
161
|
-
raise SyntaxError.new("Required argument #{var.inspect} must come before any optional arguments."
|
161
|
+
raise SyntaxError.new("Required argument #{var.inspect} must come before any optional arguments.")
|
162
162
|
end
|
163
163
|
|
164
164
|
return [[var, val]] unless try_tok(:comma)
|
data/lib/sass/script.rb
CHANGED
@@ -47,12 +47,8 @@ module Sass
|
|
47
47
|
def self.parse(value, line, offset, filename = nil)
|
48
48
|
Parser.parse(value, line, offset, filename)
|
49
49
|
rescue Sass::SyntaxError => e
|
50
|
-
if e.message == "SassScript error"
|
51
|
-
|
52
|
-
@message += ": #{value.dump}."
|
53
|
-
end
|
54
|
-
end
|
55
|
-
e.sass_line = line
|
50
|
+
e.message << ": #{value.inspect}." if e.message == "SassScript error"
|
51
|
+
e.modify_backtrace(:line => line, :filename => filename)
|
56
52
|
raise e
|
57
53
|
end
|
58
54
|
end
|
@@ -38,6 +38,16 @@ module Sass::Tree
|
|
38
38
|
self.class == other.class && value == other.value && silent == other.silent && lines == other.lines
|
39
39
|
end
|
40
40
|
|
41
|
+
# Returns `true` if this is a silent comment
|
42
|
+
# or the current style doesn't render comments.
|
43
|
+
#
|
44
|
+
# @return [Boolean]
|
45
|
+
def invisible?
|
46
|
+
style == :compressed || @silent
|
47
|
+
end
|
48
|
+
|
49
|
+
protected
|
50
|
+
|
41
51
|
# Computes the CSS for the comment.
|
42
52
|
#
|
43
53
|
# Returns `nil` if this is a silent comment
|
@@ -47,7 +57,7 @@ module Sass::Tree
|
|
47
57
|
# @param tabs [Fixnum] The level of indentation for the CSS
|
48
58
|
# @return [String, nil] The resulting CSS
|
49
59
|
# @see #invisible?
|
50
|
-
def
|
60
|
+
def _to_s(tabs = 0, _ = nil)
|
51
61
|
return if invisible?
|
52
62
|
spaces = ' ' * (tabs - 1)
|
53
63
|
|
@@ -60,16 +70,6 @@ module Sass::Tree
|
|
60
70
|
spaces + "/* " + content.join(style == :compact ? '' : "\n#{spaces} *") + " */"
|
61
71
|
end
|
62
72
|
|
63
|
-
# Returns `true` if this is a silent comment
|
64
|
-
# or the current style doesn't render comments.
|
65
|
-
#
|
66
|
-
# @return [Boolean]
|
67
|
-
def invisible?
|
68
|
-
style == :compressed || @silent
|
69
|
-
end
|
70
|
-
|
71
|
-
protected
|
72
|
-
|
73
73
|
# Removes this node from the tree if it's a silent comment.
|
74
74
|
#
|
75
75
|
# @param environment [Sass::Environment] The lexical environment containing
|
@@ -20,11 +20,13 @@ module Sass::Tree
|
|
20
20
|
super()
|
21
21
|
end
|
22
22
|
|
23
|
+
protected
|
24
|
+
|
23
25
|
# Computes the CSS for the directive.
|
24
26
|
#
|
25
27
|
# @param tabs [Fixnum] The level of indentation for the CSS
|
26
28
|
# @return [String] The resulting CSS
|
27
|
-
def
|
29
|
+
def _to_s(tabs)
|
28
30
|
if children.empty?
|
29
31
|
value + ";"
|
30
32
|
else
|
@@ -3,27 +3,28 @@ module Sass
|
|
3
3
|
# A static node that wraps the {Sass::Tree} for an `@import`ed file.
|
4
4
|
# It doesn't have a functional purpose other than to add the `@import`ed file
|
5
5
|
# to the backtrace if an error occurs.
|
6
|
-
class ImportNode <
|
6
|
+
class ImportNode < RootNode
|
7
7
|
# @param imported_filename [String] The name of the imported file
|
8
8
|
def initialize(imported_filename)
|
9
9
|
@imported_filename = imported_filename
|
10
|
-
super()
|
10
|
+
super(nil)
|
11
11
|
end
|
12
12
|
|
13
|
+
def invisible?; to_s.empty?; end
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
13
17
|
# Computes the CSS for the imported file.
|
14
18
|
#
|
15
19
|
# @param args [Array] Ignored
|
16
|
-
def
|
17
|
-
@to_s ||= (style == :compressed ? super
|
20
|
+
def _to_s(*args)
|
21
|
+
@to_s ||= (style == :compressed ? super.strip : super)
|
18
22
|
rescue Sass::SyntaxError => e
|
19
|
-
e.
|
23
|
+
e.modify_backtrace(:filename => children.first.filename)
|
24
|
+
e.add_backtrace(:filename => @filename, :line => @line)
|
20
25
|
raise e
|
21
26
|
end
|
22
27
|
|
23
|
-
def invisible?; to_s.empty?; end
|
24
|
-
|
25
|
-
protected
|
26
|
-
|
27
28
|
# Parses the imported file
|
28
29
|
# and runs the dynamic Sass for it.
|
29
30
|
#
|
@@ -31,10 +32,13 @@ module Sass
|
|
31
32
|
# variable and mixin values
|
32
33
|
def perform!(environment)
|
33
34
|
return unless full_filename = import
|
34
|
-
|
35
|
+
root = Sass::Files.tree_for(full_filename, @options)
|
36
|
+
@template = root.template
|
37
|
+
self.children = root.children
|
35
38
|
self.children = perform_children(environment)
|
36
39
|
rescue Sass::SyntaxError => e
|
37
|
-
e.
|
40
|
+
e.modify_backtrace(:filename => full_filename)
|
41
|
+
e.add_backtrace(:filename => @filename, :line => @line)
|
38
42
|
raise e
|
39
43
|
end
|
40
44
|
|
@@ -50,7 +54,7 @@ module Sass
|
|
50
54
|
begin
|
51
55
|
full_filename = Sass::Files.find_file_to_import(@imported_filename, import_paths)
|
52
56
|
rescue Exception => e
|
53
|
-
raise SyntaxError.new(e.message, self.line)
|
57
|
+
raise SyntaxError.new(e.message, :line => self.line, :filename => @filename)
|
54
58
|
end
|
55
59
|
|
56
60
|
if full_filename =~ /\.css$/
|
data/lib/sass/tree/mixin_node.rb
CHANGED
@@ -24,7 +24,7 @@ module Sass::Tree
|
|
24
24
|
# @raise [Sass::SyntaxError] if an incorrect number of arguments was passed
|
25
25
|
# @see Sass::Tree
|
26
26
|
def _perform(environment)
|
27
|
-
raise Sass::SyntaxError.new("Undefined mixin '#{@name}'."
|
27
|
+
raise Sass::SyntaxError.new("Undefined mixin '#{@name}'.") unless mixin = environment.mixin(@name)
|
28
28
|
|
29
29
|
raise Sass::SyntaxError.new(<<END.gsub("\n", "")) if mixin.args.size < @args.size
|
30
30
|
Mixin #{@name} takes #{mixin.args.size} argument#{'s' if mixin.args.size != 1}
|
data/lib/sass/tree/node.rb
CHANGED
@@ -15,8 +15,7 @@ module Sass
|
|
15
15
|
# Nodes that only appear in the pre-perform state are called **dynamic nodes**;
|
16
16
|
# those that appear in both states are called **static nodes**.
|
17
17
|
module Tree
|
18
|
-
#
|
19
|
-
# and the superclass of all other parse-tree nodes.
|
18
|
+
# The abstract superclass of all parse-tree nodes.
|
20
19
|
class Node
|
21
20
|
# The child nodes of this node.
|
22
21
|
#
|
@@ -66,7 +65,7 @@ module Sass
|
|
66
65
|
# @see #invalid_child?
|
67
66
|
def <<(child)
|
68
67
|
if msg = invalid_child?(child)
|
69
|
-
raise Sass::SyntaxError.new(msg, child.line)
|
68
|
+
raise Sass::SyntaxError.new(msg, :line => child.line)
|
70
69
|
end
|
71
70
|
@children << child
|
72
71
|
end
|
@@ -110,30 +109,28 @@ module Sass
|
|
110
109
|
# @return [Boolean]
|
111
110
|
def invisible?; false; end
|
112
111
|
|
112
|
+
# The output style. See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
|
113
|
+
#
|
114
|
+
# @return [Symbol]
|
115
|
+
def style
|
116
|
+
@options[:style]
|
117
|
+
end
|
118
|
+
|
113
119
|
# Computes the CSS corresponding to this Sass tree.
|
114
120
|
#
|
115
121
|
# Only static-node subclasses need to implement \{#to\_s}.
|
116
122
|
#
|
117
123
|
# This may return `nil`, but it will only do so if \{#invisible?} is true.
|
118
124
|
#
|
125
|
+
# @param args [Array] Passed on to \{#\_to\_s}
|
119
126
|
# @return [String, nil] The resulting CSS
|
120
127
|
# @raise [Sass::SyntaxError] if some element of the tree is invalid
|
121
128
|
# @see Sass::Tree
|
122
|
-
def to_s
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
else
|
128
|
-
next if child.invisible?
|
129
|
-
child_str = child.to_s(1)
|
130
|
-
result << child_str + (style == :compressed ? '' : "\n")
|
131
|
-
end
|
132
|
-
end
|
133
|
-
result.rstrip!
|
134
|
-
return "" if result.empty?
|
135
|
-
return result + "\n"
|
136
|
-
rescue Sass::SyntaxError => e; e.add_metadata(filename, line)
|
129
|
+
def to_s(*args)
|
130
|
+
_to_s(*args)
|
131
|
+
rescue Sass::SyntaxError => e
|
132
|
+
e.modify_backtrace(:filename => filename, :line => line)
|
133
|
+
raise e
|
137
134
|
end
|
138
135
|
|
139
136
|
# Runs the dynamic Sass code:
|
@@ -154,18 +151,24 @@ module Sass
|
|
154
151
|
def perform(environment)
|
155
152
|
environment.options = @options if self.class == Tree::Node
|
156
153
|
_perform(environment)
|
157
|
-
rescue Sass::SyntaxError => e
|
154
|
+
rescue Sass::SyntaxError => e
|
155
|
+
e.modify_backtrace(:filename => filename, :line => line)
|
156
|
+
raise e
|
158
157
|
end
|
159
158
|
|
160
|
-
|
159
|
+
protected
|
160
|
+
|
161
|
+
# Computes the CSS corresponding to this particular Sass node.
|
161
162
|
#
|
162
|
-
# @
|
163
|
-
|
164
|
-
|
163
|
+
# @param args [Array] ignored
|
164
|
+
# @return [String, nil] The resulting CSS
|
165
|
+
# @raise [Sass::SyntaxError] if some element of the tree is invalid
|
166
|
+
# @see #to_s
|
167
|
+
# @see Sass::Tree
|
168
|
+
def _to_s
|
169
|
+
raise NotImplementedError.new("All static-node subclasses of Sass::Tree::Node must override #_to_s or #to_s.")
|
165
170
|
end
|
166
171
|
|
167
|
-
protected
|
168
|
-
|
169
172
|
# Runs any dynamic Sass code in this particular node.
|
170
173
|
# This doesn't modify this node or any of its children.
|
171
174
|
#
|
@@ -228,7 +231,7 @@ module Sass
|
|
228
231
|
def balance(*args)
|
229
232
|
res = Haml::Shared.balance(*args)
|
230
233
|
return res if res
|
231
|
-
raise Sass::SyntaxError.new("Unbalanced brackets.", line)
|
234
|
+
raise Sass::SyntaxError.new("Unbalanced brackets.", :line => line)
|
232
235
|
end
|
233
236
|
|
234
237
|
# Returns an error message if the given child node is invalid,
|
data/lib/sass/tree/prop_node.rb
CHANGED
@@ -34,29 +34,28 @@ module Sass::Tree
|
|
34
34
|
self.class == other.class && name == other.name && value == other.value && super
|
35
35
|
end
|
36
36
|
|
37
|
+
protected
|
38
|
+
|
37
39
|
# Computes the CSS for the property.
|
38
40
|
#
|
39
41
|
# @param tabs [Fixnum] The level of indentation for the CSS
|
40
42
|
# @param parent_name [String] The name of the parent property (e.g. `text`) or nil
|
41
43
|
# @return [String] The resulting CSS
|
42
44
|
# @raise [Sass::SyntaxError] if the property uses invalid syntax
|
43
|
-
def
|
45
|
+
def _to_s(tabs, parent_name = nil)
|
44
46
|
if @options[:property_syntax] == :old && @prop_syntax == :new
|
45
47
|
raise Sass::SyntaxError.new("Illegal property syntax: can't use new syntax when :property_syntax => :old is set.")
|
46
48
|
elsif @options[:property_syntax] == :new && @prop_syntax == :old
|
47
49
|
raise Sass::SyntaxError.new("Illegal property syntax: can't use old syntax when :property_syntax => :new is set.")
|
50
|
+
elsif value[-1] == ?;
|
51
|
+
raise Sass::SyntaxError.new("Invalid property: #{declaration.dump} (no \";\" required at end-of-line).")
|
52
|
+
elsif value.empty? && children.empty?
|
53
|
+
raise Sass::SyntaxError.new("Invalid property: #{declaration.dump} (no value).")
|
48
54
|
end
|
49
55
|
|
50
|
-
if value[-1] == ?;
|
51
|
-
raise Sass::SyntaxError.new("Invalid property: #{declaration.dump} (no \";\" required at end-of-line).", @line)
|
52
|
-
end
|
53
56
|
real_name = name
|
54
57
|
real_name = "#{parent_name}-#{real_name}" if parent_name
|
55
|
-
|
56
|
-
if value.empty? && children.empty?
|
57
|
-
raise Sass::SyntaxError.new("Invalid property: #{declaration.dump} (no value).", @line)
|
58
|
-
end
|
59
|
-
|
58
|
+
|
60
59
|
join_string = case style
|
61
60
|
when :compact; ' '
|
62
61
|
when :compressed; ''
|
@@ -76,8 +75,6 @@ module Sass::Tree
|
|
76
75
|
(style == :compressed && parent_name) ? to_return : to_return[0...-1]
|
77
76
|
end
|
78
77
|
|
79
|
-
protected
|
80
|
-
|
81
78
|
# Runs any SassScript that may be embedded in the property.
|
82
79
|
#
|
83
80
|
# @param environment [Sass::Environment] The lexical environment containing
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Sass
|
2
|
+
module Tree
|
3
|
+
# A static node that is the root node of the Sass document.
|
4
|
+
class RootNode < Node
|
5
|
+
# The Sass template from which this node was created
|
6
|
+
#
|
7
|
+
# @param template [String]
|
8
|
+
attr_reader :template
|
9
|
+
|
10
|
+
# @param template [String] The Sass template from which this node was created
|
11
|
+
def initialize(template)
|
12
|
+
super()
|
13
|
+
@template = template
|
14
|
+
end
|
15
|
+
|
16
|
+
# @see \{Node#to\_s}
|
17
|
+
def to_s(*args)
|
18
|
+
super
|
19
|
+
rescue Sass::SyntaxError => e
|
20
|
+
e.sass_template = @template
|
21
|
+
raise e
|
22
|
+
end
|
23
|
+
|
24
|
+
# @see \{Node#perform}
|
25
|
+
def perform(*args)
|
26
|
+
super
|
27
|
+
rescue Sass::SyntaxError => e
|
28
|
+
e.sass_template = @template
|
29
|
+
raise e
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
|
34
|
+
# Computes the CSS corresponding to this Sass tree.
|
35
|
+
#
|
36
|
+
# @param args [Array] ignored
|
37
|
+
# @return [String] The resulting CSS
|
38
|
+
# @raise [Sass::SyntaxError] if some element of the tree is invalid
|
39
|
+
# @see Sass::Tree
|
40
|
+
def _to_s(*args)
|
41
|
+
result = String.new
|
42
|
+
children.each do |child|
|
43
|
+
raise Sass::SyntaxError.new('Properties aren\'t allowed at the root of a document.',
|
44
|
+
:line => child.line) if child.is_a? PropNode
|
45
|
+
|
46
|
+
next if child.invisible?
|
47
|
+
child_str = child.to_s(1)
|
48
|
+
result << child_str + (style == :compressed ? '' : "\n")
|
49
|
+
end
|
50
|
+
result.rstrip!
|
51
|
+
return "" if result.empty?
|
52
|
+
return result + "\n"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/sass/tree/rule_node.rb
CHANGED
@@ -69,6 +69,8 @@ module Sass::Tree
|
|
69
69
|
@rules.last[-1] == ?,
|
70
70
|
end
|
71
71
|
|
72
|
+
protected
|
73
|
+
|
72
74
|
# Computes the CSS for the rule.
|
73
75
|
#
|
74
76
|
# @param tabs [Fixnum] The level of indentation for the CSS
|
@@ -76,7 +78,7 @@ module Sass::Tree
|
|
76
78
|
# (see \{#rules}), or `nil` if there are no parents
|
77
79
|
# @return [String] The resulting CSS
|
78
80
|
# @raise [Sass::SyntaxError] if the rule has no parents but uses `&`
|
79
|
-
def
|
81
|
+
def _to_s(tabs, super_rules = nil)
|
80
82
|
resolved_rules = resolve_parent_refs(super_rules)
|
81
83
|
|
82
84
|
properties = []
|
@@ -144,8 +146,6 @@ module Sass::Tree
|
|
144
146
|
to_return
|
145
147
|
end
|
146
148
|
|
147
|
-
protected
|
148
|
-
|
149
149
|
# Runs any SassScript that may be embedded in the rule,
|
150
150
|
# and parses the selectors for commas.
|
151
151
|
#
|
@@ -163,7 +163,7 @@ module Sass::Tree
|
|
163
163
|
return @parsed_rules.map do |line|
|
164
164
|
line.map do |rule|
|
165
165
|
if rule.include?(:parent)
|
166
|
-
raise Sass::SyntaxError.new("Base-level rules cannot contain the parent-selector-referencing character '#{PARENT}'."
|
166
|
+
raise Sass::SyntaxError.new("Base-level rules cannot contain the parent-selector-referencing character '#{PARENT}'.")
|
167
167
|
end
|
168
168
|
|
169
169
|
rule.join
|
data/test/sass/engine_test.rb
CHANGED
@@ -180,18 +180,78 @@ SASS
|
|
180
180
|
end
|
181
181
|
|
182
182
|
def test_imported_exception
|
183
|
-
[
|
183
|
+
[1, 2, 3].each do |i|
|
184
184
|
begin
|
185
185
|
Sass::Engine.new("@import bork#{i}", :load_paths => [File.dirname(__FILE__) + '/templates/']).render
|
186
186
|
rescue Sass::SyntaxError => err
|
187
187
|
assert_equal(2, err.sass_line)
|
188
|
-
assert_match(/bork#{i}\.sass$/, err.sass_filename)
|
188
|
+
assert_match(/(\/|^)bork#{i}\.sass$/, err.sass_filename)
|
189
|
+
|
190
|
+
assert_equal(err.sass_filename, err.sass_backtrace.first[:filename])
|
191
|
+
assert_equal(err.sass_line, err.sass_backtrace.first[:line])
|
192
|
+
|
193
|
+
assert_nil(err.sass_backtrace[1][:filename])
|
194
|
+
assert_equal(1, err.sass_backtrace[1][:line])
|
195
|
+
|
196
|
+
assert_match(/(\/|^)bork#{i}\.sass:2$/, err.backtrace.first)
|
197
|
+
assert_equal("(sass):1", err.backtrace[1])
|
198
|
+
else
|
199
|
+
assert(false, "Exception not raised for imported template: bork#{i}")
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def test_double_imported_exception
|
205
|
+
[1, 2, 3].each do |i|
|
206
|
+
begin
|
207
|
+
Sass::Engine.new("@import nested_bork#{i}", :load_paths => [File.dirname(__FILE__) + '/templates/']).render
|
208
|
+
rescue Sass::SyntaxError => err
|
209
|
+
assert_equal(2, err.sass_line)
|
210
|
+
assert_match(/(\/|^)bork#{i}\.sass$/, err.sass_filename)
|
211
|
+
|
212
|
+
assert_equal(err.sass_filename, err.sass_backtrace.first[:filename])
|
213
|
+
assert_equal(err.sass_line, err.sass_backtrace.first[:line])
|
214
|
+
|
215
|
+
assert_match(/(\/|^)nested_bork#{i}\.sass$/, err.sass_backtrace[1][:filename])
|
216
|
+
assert_equal(2, err.sass_backtrace[1][:line])
|
217
|
+
|
218
|
+
assert_nil(err.sass_backtrace[2][:filename])
|
219
|
+
assert_equal(1, err.sass_backtrace[2][:line])
|
220
|
+
|
221
|
+
assert_match(/(\/|^)bork#{i}\.sass:2$/, err.backtrace.first)
|
222
|
+
assert_match(/(\/|^)nested_bork#{i}\.sass:2$/, err.backtrace[1])
|
223
|
+
assert_equal("(sass):1", err.backtrace[2])
|
189
224
|
else
|
190
225
|
assert(false, "Exception not raised for imported template: bork#{i}")
|
191
226
|
end
|
192
227
|
end
|
193
228
|
end
|
194
229
|
|
230
|
+
def test_exception_css_with_offset
|
231
|
+
opts = {:full_exception => true, :line => 362}
|
232
|
+
render(("a\n b: c\n" * 10) + "d\n e:\n" + ("f\n g: h\n" * 10), opts)
|
233
|
+
rescue Sass::SyntaxError => e
|
234
|
+
assert_equal(<<CSS, Sass::SyntaxError.exception_to_css(e, opts).split("\n")[0..15].join("\n"))
|
235
|
+
/*
|
236
|
+
Syntax error: Invalid property: "e: " (no value).
|
237
|
+
on line 383 of test_exception_css_with_offset_inline.sass
|
238
|
+
|
239
|
+
378: a
|
240
|
+
379: b: c
|
241
|
+
380: a
|
242
|
+
381: b: c
|
243
|
+
382: d
|
244
|
+
383: e:
|
245
|
+
384: f
|
246
|
+
385: g: h
|
247
|
+
386: f
|
248
|
+
387: g: h
|
249
|
+
388: f
|
250
|
+
CSS
|
251
|
+
else
|
252
|
+
assert(false, "Exception not raised for test_exception_css_with_offset")
|
253
|
+
end
|
254
|
+
|
195
255
|
def test_css_import
|
196
256
|
assert_equal("@import url(./fonts.css) screen;\n", render("@import url(./fonts.css) screen"))
|
197
257
|
assert_equal("@import \"./fonts.css\" screen;\n", render("@import \"./fonts.css\" screen"))
|
@@ -255,12 +315,14 @@ SASS
|
|
255
315
|
rescue Sass::SyntaxError => e
|
256
316
|
assert_equal("Illegal property syntax: can't use new syntax when :property_syntax => :old is set.",
|
257
317
|
e.message)
|
318
|
+
assert_equal(2, e.sass_line)
|
258
319
|
else
|
259
320
|
assert(false, "SyntaxError not raised for :property_syntax => :old")
|
260
321
|
end
|
261
322
|
|
262
323
|
begin
|
263
324
|
render("a\n :b c", :property_syntax => :new)
|
325
|
+
assert_equal(2, e.sass_line)
|
264
326
|
rescue Sass::SyntaxError => e
|
265
327
|
assert_equal("Illegal property syntax: can't use old syntax when :property_syntax => :new is set.",
|
266
328
|
e.message)
|
data/test/sass/plugin_test.rb
CHANGED
@@ -52,21 +52,28 @@ class SassPluginTest < Test::Unit::TestCase
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def test_full_exception_handling
|
55
|
-
File.delete(tempfile_loc('
|
55
|
+
File.delete(tempfile_loc('bork1'))
|
56
56
|
Sass::Plugin.update_stylesheets
|
57
|
-
File.open(tempfile_loc('
|
58
|
-
assert_equal(
|
57
|
+
File.open(tempfile_loc('bork1')) do |file|
|
58
|
+
assert_equal(<<CSS.strip, file.read.split("\n")[0...6].join("\n"))
|
59
|
+
/*
|
60
|
+
Syntax error: Undefined variable: "!bork".
|
61
|
+
on line 2 of #{template_loc('bork1')}
|
62
|
+
|
63
|
+
1: bork
|
64
|
+
2: :bork= !bork
|
65
|
+
CSS
|
59
66
|
end
|
60
|
-
File.delete(tempfile_loc('
|
67
|
+
File.delete(tempfile_loc('bork1'))
|
61
68
|
end
|
62
69
|
|
63
70
|
def test_nonfull_exception_handling
|
64
71
|
Sass::Plugin.options[:full_exception] = false
|
65
72
|
|
66
|
-
File.delete(tempfile_loc('
|
73
|
+
File.delete(tempfile_loc('bork1'))
|
67
74
|
Sass::Plugin.update_stylesheets
|
68
|
-
assert_equal("/* Internal stylesheet error */", File.read(tempfile_loc('
|
69
|
-
File.delete(tempfile_loc('
|
75
|
+
assert_equal("/* Internal stylesheet error */", File.read(tempfile_loc('bork1')))
|
76
|
+
File.delete(tempfile_loc('bork1'))
|
70
77
|
|
71
78
|
Sass::Plugin.options[:full_exception] = true
|
72
79
|
end
|
File without changes
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: haml-edge
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.3.
|
4
|
+
version: 2.3.28
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nathan Weizenbaum
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2009-
|
13
|
+
date: 2009-09-14 00:00:00 -04:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -110,6 +110,7 @@ files:
|
|
110
110
|
- lib/sass/tree/node.rb
|
111
111
|
- lib/sass/tree/prop_node.rb
|
112
112
|
- lib/sass/tree/rule_node.rb
|
113
|
+
- lib/sass/tree/root_node.rb
|
113
114
|
- lib/sass/tree/variable_node.rb
|
114
115
|
- lib/sass/tree/while_node.rb
|
115
116
|
- bin/css2sass
|
@@ -221,8 +222,9 @@ files:
|
|
221
222
|
- test/sass/templates/_partial.sass
|
222
223
|
- test/sass/templates/alt.sass
|
223
224
|
- test/sass/templates/basic.sass
|
224
|
-
- test/sass/templates/
|
225
|
+
- test/sass/templates/bork1.sass
|
225
226
|
- test/sass/templates/bork2.sass
|
227
|
+
- test/sass/templates/bork3.sass
|
226
228
|
- test/sass/templates/compact.sass
|
227
229
|
- test/sass/templates/complex.sass
|
228
230
|
- test/sass/templates/compressed.sass
|
@@ -233,6 +235,9 @@ files:
|
|
233
235
|
- test/sass/templates/mixins.sass
|
234
236
|
- test/sass/templates/multiline.sass
|
235
237
|
- test/sass/templates/nested.sass
|
238
|
+
- test/sass/templates/nested_bork1.sass
|
239
|
+
- test/sass/templates/nested_bork2.sass
|
240
|
+
- test/sass/templates/nested_bork3.sass
|
236
241
|
- test/sass/templates/parent_ref.sass
|
237
242
|
- test/sass/templates/script.sass
|
238
243
|
- test/sass/templates/subdir
|