haml-edge 2.3.27 → 2.3.28
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/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
|