haml 3.0.0.beta.3 → 3.0.0.rc.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of haml might be problematic. Click here for more details.
- data/.yardopts +2 -0
- data/REMEMBER +4 -11
- data/Rakefile +24 -2
- data/VERSION +1 -1
- data/lib/haml.rb +5 -2
- data/lib/haml/exec.rb +11 -4
- data/lib/haml/filters.rb +3 -0
- data/lib/haml/helpers.rb +2 -10
- data/lib/haml/helpers/action_view_extensions.rb +4 -2
- data/lib/haml/helpers/action_view_mods.rb +6 -4
- data/lib/haml/html.rb +0 -1
- data/lib/haml/precompiler.rb +37 -30
- data/lib/haml/railtie.rb +6 -2
- data/lib/haml/root.rb +4 -0
- data/lib/haml/template.rb +2 -0
- data/lib/haml/util.rb +74 -0
- data/lib/haml/util/subset_map.rb +101 -0
- data/lib/sass.rb +1 -0
- data/lib/sass/engine.rb +36 -31
- data/lib/sass/files.rb +1 -1
- data/lib/sass/plugin.rb +21 -0
- data/lib/sass/plugin/staleness_checker.rb +9 -9
- data/lib/sass/script.rb +1 -2
- data/lib/sass/script/color.rb +4 -3
- data/lib/sass/script/css_lexer.rb +11 -1
- data/lib/sass/script/css_parser.rb +4 -1
- data/lib/sass/script/funcall.rb +9 -0
- data/lib/sass/script/interpolation.rb +21 -0
- data/lib/sass/script/lexer.rb +30 -13
- data/lib/sass/script/node.rb +1 -1
- data/lib/sass/script/number.rb +4 -5
- data/lib/sass/script/parser.rb +13 -14
- data/lib/sass/script/string.rb +8 -2
- data/lib/sass/script/string_interpolation.rb +27 -4
- data/lib/sass/scss.rb +3 -0
- data/lib/sass/scss/css_parser.rb +5 -3
- data/lib/sass/scss/parser.rb +146 -64
- data/lib/sass/scss/rx.rb +9 -1
- data/lib/sass/scss/sass_parser.rb +11 -0
- data/lib/sass/scss/script_lexer.rb +2 -0
- data/lib/sass/scss/static_parser.rb +48 -0
- data/lib/sass/selector.rb +353 -0
- data/lib/sass/selector/abstract_sequence.rb +40 -0
- data/lib/sass/selector/comma_sequence.rb +80 -0
- data/lib/sass/selector/sequence.rb +194 -0
- data/lib/sass/selector/simple.rb +107 -0
- data/lib/sass/selector/simple_sequence.rb +161 -0
- data/lib/sass/tree/comment_node.rb +1 -0
- data/lib/sass/tree/debug_node.rb +1 -0
- data/lib/sass/tree/directive_node.rb +1 -0
- data/lib/sass/tree/extend_node.rb +60 -0
- data/lib/sass/tree/for_node.rb +1 -0
- data/lib/sass/tree/if_node.rb +2 -0
- data/lib/sass/tree/import_node.rb +2 -0
- data/lib/sass/tree/mixin_def_node.rb +1 -0
- data/lib/sass/tree/mixin_node.rb +21 -5
- data/lib/sass/tree/node.rb +59 -12
- data/lib/sass/tree/prop_node.rb +20 -21
- data/lib/sass/tree/root_node.rb +8 -17
- data/lib/sass/tree/rule_node.rb +49 -100
- data/lib/sass/tree/variable_node.rb +1 -0
- data/lib/sass/tree/warn_node.rb +1 -0
- data/lib/sass/tree/while_node.rb +1 -0
- data/test/haml/engine_test.rb +185 -3
- data/test/haml/helper_test.rb +25 -2
- data/test/haml/template_test.rb +2 -2
- data/test/haml/templates/helpers.haml +13 -0
- data/test/haml/util/subset_map_test.rb +91 -0
- data/test/haml/util_test.rb +25 -0
- data/test/sass/conversion_test.rb +23 -3
- data/test/sass/engine_test.rb +50 -7
- data/test/sass/extend_test.rb +1045 -0
- data/test/sass/results/complex.css +0 -1
- data/test/sass/results/script.css +1 -1
- data/test/sass/script_conversion_test.rb +16 -0
- data/test/sass/script_test.rb +37 -4
- data/test/sass/scss/css_test.rb +17 -3
- data/test/sass/scss/rx_test.rb +1 -1
- data/test/sass/scss/scss_test.rb +30 -0
- data/test/sass/templates/complex.sass +0 -2
- data/test/test_helper.rb +5 -0
- metadata +18 -4
@@ -1,15 +1,26 @@
|
|
1
1
|
module Sass::Script
|
2
|
+
# A SassScript object representing `#{}` interpolation within a string.
|
3
|
+
#
|
4
|
+
# @see Interpolation
|
2
5
|
class StringInterpolation < Node
|
6
|
+
# Interpolation in a string is of the form `"before #{mid} after"`,
|
7
|
+
# where `before` and `after` may include more interpolation.
|
8
|
+
#
|
9
|
+
# @param before [Node] The string before the interpolation
|
10
|
+
# @param mid [Node] The SassScript within the interpolation
|
11
|
+
# @param after [Node] The string after the interpolation
|
3
12
|
def initialize(before, mid, after)
|
4
13
|
@before = before
|
5
14
|
@mid = mid
|
6
15
|
@after = after
|
7
16
|
end
|
8
17
|
|
18
|
+
# @return [String] A human-readable s-expression representation of the interpolation
|
9
19
|
def inspect
|
10
20
|
"(string_interpolation #{@before.inspect} #{@mid.inspect} #{@after.inspect})"
|
11
21
|
end
|
12
22
|
|
23
|
+
# @see Node#to_sass
|
13
24
|
def to_sass(opts = {})
|
14
25
|
# We can get rid of all of this when we remove the deprecated :equals context
|
15
26
|
before_unquote, before_quote_char, before_str = parse_str(@before.to_sass(opts))
|
@@ -39,21 +50,33 @@ module Sass::Script
|
|
39
50
|
res
|
40
51
|
end
|
41
52
|
|
53
|
+
# Returns the three components of the interpolation, `before`, `mid`, and `after`.
|
54
|
+
#
|
55
|
+
# @return [Array<Node>]
|
56
|
+
# @see #initialize
|
57
|
+
# @see Node#children
|
42
58
|
def children
|
43
59
|
[@before, @mid, @after].compact
|
44
60
|
end
|
45
61
|
|
46
62
|
protected
|
47
63
|
|
64
|
+
# Evaluates the interpolation.
|
65
|
+
#
|
66
|
+
# @param environment [Sass::Environment] The environment in which to evaluate the SassScript
|
67
|
+
# @return [Sass::Script::String] The SassScript string that is the value of the interpolation
|
48
68
|
def _perform(environment)
|
49
69
|
res = ""
|
50
|
-
|
51
|
-
|
52
|
-
|
70
|
+
before = @before.perform(environment)
|
71
|
+
res << before.value
|
72
|
+
mid = @mid.perform(environment)
|
73
|
+
res << (mid.is_a?(Sass::Script::String) ? mid.value : mid.to_s)
|
53
74
|
res << @after.perform(environment).value
|
54
|
-
Sass::Script::String.new(res,
|
75
|
+
Sass::Script::String.new(res, before.type)
|
55
76
|
end
|
56
77
|
|
78
|
+
private
|
79
|
+
|
57
80
|
def parse_str(str)
|
58
81
|
case str
|
59
82
|
when /^unquote\((["'])(.*)\1\)$/
|
data/lib/sass/scss.rb
CHANGED
@@ -2,6 +2,9 @@ require 'sass/scss/rx'
|
|
2
2
|
require 'sass/scss/script_lexer'
|
3
3
|
require 'sass/scss/script_parser'
|
4
4
|
require 'sass/scss/parser'
|
5
|
+
require 'sass/scss/sass_parser'
|
6
|
+
require 'sass/scss/static_parser'
|
7
|
+
require 'sass/scss/css_parser'
|
5
8
|
|
6
9
|
module Sass
|
7
10
|
# SCSS is the CSS syntax for Sass.
|
data/lib/sass/scss/css_parser.rb
CHANGED
@@ -2,15 +2,17 @@ require 'sass/script/css_parser'
|
|
2
2
|
|
3
3
|
module Sass
|
4
4
|
module SCSS
|
5
|
-
|
5
|
+
# This is a subclass of {Parser} which only parses plain CSS.
|
6
|
+
# It doesn't support any Sass extensions, such as interpolation,
|
7
|
+
# parent references, nested selectors, and so forth.
|
8
|
+
# It does support all the same CSS hacks as the SCSS parser, though.
|
9
|
+
class CssParser < StaticParser
|
6
10
|
private
|
7
11
|
|
8
|
-
def variable; nil; end
|
9
12
|
def parent_selector; nil; end
|
10
13
|
def interpolation; nil; end
|
11
14
|
def interp_string; tok(STRING); end
|
12
15
|
def interp_ident(ident = IDENT); tok(ident); end
|
13
|
-
def expected_property_separator; '":"'; end
|
14
16
|
def use_css_import?; true; end
|
15
17
|
|
16
18
|
def special_directive(name)
|
data/lib/sass/scss/parser.rb
CHANGED
@@ -6,10 +6,12 @@ module Sass
|
|
6
6
|
# The parser for SCSS.
|
7
7
|
# It parses a string of code into a tree of {Sass::Tree::Node}s.
|
8
8
|
class Parser
|
9
|
-
# @param str [String] The source document to parse
|
10
|
-
|
9
|
+
# @param str [String, StringScanner] The source document to parse
|
10
|
+
# @param line [Fixnum] The line on which the source string appeared,
|
11
|
+
# if it's part of another document
|
12
|
+
def initialize(str, line = 1)
|
11
13
|
@template = str
|
12
|
-
@line =
|
14
|
+
@line = line
|
13
15
|
@strs = []
|
14
16
|
end
|
15
17
|
|
@@ -18,19 +20,39 @@ module Sass
|
|
18
20
|
# @return [Sass::Tree::RootNode] The root node of the document tree
|
19
21
|
# @raise [Sass::SyntaxError] if there's a syntax error in the document
|
20
22
|
def parse
|
21
|
-
|
22
|
-
Haml::Util.check_encoding(@template) do |msg, line|
|
23
|
-
raise Sass::SyntaxError.new(msg, :line => line)
|
24
|
-
end.gsub("\r", ""))
|
23
|
+
init_scanner!
|
25
24
|
root = stylesheet
|
26
25
|
expected("selector or at-rule") unless @scanner.eos?
|
27
26
|
root
|
28
27
|
end
|
29
28
|
|
29
|
+
# Parses an identifier with interpolation.
|
30
|
+
# Note that this won't assert that the identifier takes up the entire input string;
|
31
|
+
# it's meant to be used with `StringScanner`s as part of other parsers.
|
32
|
+
#
|
33
|
+
# @return [Array<String, Sass::Script::Node>, nil]
|
34
|
+
# The interpolated identifier, or nil if none could be parsed
|
35
|
+
def parse_interp_ident
|
36
|
+
init_scanner!
|
37
|
+
interp_ident
|
38
|
+
end
|
39
|
+
|
30
40
|
private
|
31
41
|
|
32
42
|
include Sass::SCSS::RX
|
33
43
|
|
44
|
+
def init_scanner!
|
45
|
+
@scanner =
|
46
|
+
if @template.is_a?(StringScanner)
|
47
|
+
@template
|
48
|
+
else
|
49
|
+
StringScanner.new(
|
50
|
+
Haml::Util.check_encoding(@template) do |msg, line|
|
51
|
+
raise Sass::SyntaxError.new(msg, :line => line)
|
52
|
+
end.gsub("\r", ""))
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
34
56
|
def stylesheet
|
35
57
|
node = node(Sass::Tree::RootNode.new(@scanner.string))
|
36
58
|
block_contents(node, :stylesheet) {s(node)}
|
@@ -77,7 +99,7 @@ module Sass
|
|
77
99
|
node << comment
|
78
100
|
end
|
79
101
|
|
80
|
-
DIRECTIVES = Set[:mixin, :include, :debug, :warn, :for, :while, :if, :import, :media]
|
102
|
+
DIRECTIVES = Set[:mixin, :include, :debug, :warn, :for, :while, :if, :extend, :import, :media]
|
81
103
|
|
82
104
|
def directive
|
83
105
|
return unless tok(/@/)
|
@@ -106,32 +128,32 @@ module Sass
|
|
106
128
|
|
107
129
|
def special_directive(name)
|
108
130
|
sym = name.gsub('-', '_').to_sym
|
109
|
-
DIRECTIVES.include?(sym) && send(sym)
|
131
|
+
DIRECTIVES.include?(sym) && send("#{sym}_directive")
|
110
132
|
end
|
111
133
|
|
112
|
-
def
|
134
|
+
def mixin_directive
|
113
135
|
name = tok! IDENT
|
114
136
|
args = sass_script(:parse_mixin_definition_arglist)
|
115
137
|
ss
|
116
138
|
block(node(Sass::Tree::MixinDefNode.new(name, args)), :directive)
|
117
139
|
end
|
118
140
|
|
119
|
-
def
|
141
|
+
def include_directive
|
120
142
|
name = tok! IDENT
|
121
143
|
args = sass_script(:parse_mixin_include_arglist)
|
122
144
|
ss
|
123
145
|
node(Sass::Tree::MixinNode.new(name, args))
|
124
146
|
end
|
125
147
|
|
126
|
-
def
|
148
|
+
def debug_directive
|
127
149
|
node(Sass::Tree::DebugNode.new(sass_script(:parse)))
|
128
150
|
end
|
129
151
|
|
130
|
-
def
|
152
|
+
def warn_directive
|
131
153
|
node(Sass::Tree::WarnNode.new(sass_script(:parse)))
|
132
154
|
end
|
133
155
|
|
134
|
-
def
|
156
|
+
def for_directive
|
135
157
|
tok!(/\$/)
|
136
158
|
var = tok! IDENT
|
137
159
|
ss
|
@@ -148,13 +170,13 @@ module Sass
|
|
148
170
|
block(node(Sass::Tree::ForNode.new(var, from, to, exclusive)), :directive)
|
149
171
|
end
|
150
172
|
|
151
|
-
def
|
173
|
+
def while_directive
|
152
174
|
expr = sass_script(:parse)
|
153
175
|
ss
|
154
176
|
block(node(Sass::Tree::WhileNode.new(expr)), :directive)
|
155
177
|
end
|
156
178
|
|
157
|
-
def
|
179
|
+
def if_directive
|
158
180
|
expr = sass_script(:parse)
|
159
181
|
ss
|
160
182
|
node = block(node(Sass::Tree::IfNode.new(expr)), :directive)
|
@@ -173,7 +195,11 @@ module Sass
|
|
173
195
|
else_block(node)
|
174
196
|
end
|
175
197
|
|
176
|
-
def
|
198
|
+
def extend_directive
|
199
|
+
node(Sass::Tree::ExtendNode.new(expr!(:selector)))
|
200
|
+
end
|
201
|
+
|
202
|
+
def import_directive
|
177
203
|
@expected = "string or url()"
|
178
204
|
arg = tok(STRING) || tok!(URI)
|
179
205
|
path = @scanner[1] || @scanner[2] || @scanner[3]
|
@@ -190,7 +216,7 @@ module Sass
|
|
190
216
|
|
191
217
|
def use_css_import?; false; end
|
192
218
|
|
193
|
-
def
|
219
|
+
def media_directive
|
194
220
|
val = str {media_query_list}.strip
|
195
221
|
block(node(Sass::Tree::DirectiveNode.new("@media #{val}")), :directive)
|
196
222
|
end
|
@@ -264,15 +290,7 @@ module Sass
|
|
264
290
|
end
|
265
291
|
|
266
292
|
def ruleset
|
267
|
-
rules =
|
268
|
-
return unless v = selector
|
269
|
-
rules.concat v
|
270
|
-
|
271
|
-
while tok(/,/)
|
272
|
-
rules << ',' << str {ss}
|
273
|
-
rules.concat expr!(:selector)
|
274
|
-
end
|
275
|
-
|
293
|
+
return unless rules = selector_sequence
|
276
294
|
block(node(Sass::Tree::RuleNode.new(rules.flatten.compact)), :ruleset)
|
277
295
|
end
|
278
296
|
|
@@ -296,6 +314,7 @@ module Sass
|
|
296
314
|
end
|
297
315
|
|
298
316
|
def block_child(context)
|
317
|
+
return variable || directive || ruleset if context == :stylesheet
|
299
318
|
variable || directive || declaration_or_ruleset
|
300
319
|
end
|
301
320
|
|
@@ -340,75 +359,124 @@ module Sass
|
|
340
359
|
@use_property_exception = old_use_property_exception
|
341
360
|
end
|
342
361
|
|
362
|
+
def selector_sequence
|
363
|
+
if sel = tok(STATIC_SELECTOR)
|
364
|
+
return [sel]
|
365
|
+
end
|
366
|
+
|
367
|
+
rules = []
|
368
|
+
return unless v = selector
|
369
|
+
rules.concat v
|
370
|
+
|
371
|
+
while tok(/,/)
|
372
|
+
rules << ',' << str {ss}
|
373
|
+
rules.concat expr!(:selector)
|
374
|
+
end
|
375
|
+
rules
|
376
|
+
end
|
377
|
+
|
343
378
|
def selector
|
379
|
+
return unless sel = _selector
|
380
|
+
sel.to_a
|
381
|
+
end
|
382
|
+
|
383
|
+
def _selector
|
344
384
|
# The combinator here allows the "> E" hack
|
345
|
-
return unless
|
346
|
-
|
385
|
+
return unless val = combinator || simple_selector_sequence
|
386
|
+
nl = str{ss}.include?("\n")
|
387
|
+
res = []
|
388
|
+
res << val
|
389
|
+
res << "\n" if nl
|
347
390
|
|
348
|
-
while
|
349
|
-
res <<
|
350
|
-
res.
|
391
|
+
while val = combinator || simple_selector_sequence
|
392
|
+
res << val
|
393
|
+
res << "\n" if str{ss}.include?("\n")
|
351
394
|
end
|
352
|
-
res
|
395
|
+
Selector::Sequence.new(res.compact)
|
353
396
|
end
|
354
397
|
|
355
398
|
def combinator
|
356
|
-
tok(PLUS) || tok(GREATER) || tok(TILDE)
|
399
|
+
tok(PLUS) || tok(GREATER) || tok(TILDE)
|
357
400
|
end
|
358
401
|
|
359
402
|
def simple_selector_sequence
|
360
403
|
# This allows for stuff like http://www.w3.org/TR/css3-animations/#keyframes-
|
361
404
|
return expr unless e = element_name || id_selector || class_selector ||
|
362
|
-
attrib || negation || pseudo || parent_selector ||
|
405
|
+
attrib || negation || pseudo || parent_selector || interpolation_selector
|
363
406
|
res = [e]
|
364
407
|
|
365
408
|
# The tok(/\*/) allows the "E*" hack
|
366
409
|
while v = element_name || id_selector || class_selector ||
|
367
|
-
attrib || negation || pseudo ||
|
410
|
+
attrib || negation || pseudo || interpolation_selector ||
|
411
|
+
(tok(/\*/) && Selector::Universal.new(nil))
|
368
412
|
res << v
|
369
413
|
end
|
370
|
-
|
414
|
+
expected('"{"') if tok?(/&/)
|
415
|
+
|
416
|
+
Selector::SimpleSequence.new(res)
|
371
417
|
end
|
372
418
|
|
373
419
|
def parent_selector
|
374
|
-
tok(/&/)
|
420
|
+
return unless tok(/&/)
|
421
|
+
Selector::Parent.new
|
375
422
|
end
|
376
423
|
|
377
424
|
def class_selector
|
378
425
|
return unless tok(/\./)
|
379
426
|
@expected = "class name"
|
380
|
-
|
427
|
+
Selector::Class.new(merge(expr!(:interp_ident)))
|
381
428
|
end
|
382
429
|
|
383
430
|
def id_selector
|
384
431
|
return unless tok(/#(?!\{)/)
|
385
432
|
@expected = "id name"
|
386
|
-
|
433
|
+
Selector::Id.new(merge(expr!(:interp_name)))
|
387
434
|
end
|
388
435
|
|
389
436
|
def element_name
|
390
|
-
return unless name = interp_ident || tok(/\*/) || tok?(/\|/)
|
437
|
+
return unless name = interp_ident || tok(/\*/) || (tok?(/\|/) && "")
|
391
438
|
if tok(/\|/)
|
392
439
|
@expected = "element name or *"
|
393
|
-
|
440
|
+
ns = name
|
441
|
+
name = interp_ident || tok!(/\*/)
|
442
|
+
end
|
443
|
+
|
444
|
+
if name == '*'
|
445
|
+
Selector::Universal.new(merge(ns))
|
446
|
+
else
|
447
|
+
Selector::Element.new(merge(name), merge(ns))
|
394
448
|
end
|
395
|
-
|
449
|
+
end
|
450
|
+
|
451
|
+
def interpolation_selector
|
452
|
+
return unless script = interpolation
|
453
|
+
Selector::Interpolation.new(script)
|
396
454
|
end
|
397
455
|
|
398
456
|
def attrib
|
399
457
|
return unless tok(/\[/)
|
400
|
-
|
458
|
+
ss
|
459
|
+
ns, name = attrib_name!
|
460
|
+
ss
|
401
461
|
|
402
|
-
if
|
462
|
+
if op = tok(/=/) ||
|
403
463
|
tok(INCLUDES) ||
|
404
464
|
tok(DASHMATCH) ||
|
405
465
|
tok(PREFIXMATCH) ||
|
406
466
|
tok(SUFFIXMATCH) ||
|
407
467
|
tok(SUBSTRINGMATCH)
|
408
468
|
@expected = "identifier or string"
|
409
|
-
|
469
|
+
ss
|
470
|
+
if val = tok(IDENT)
|
471
|
+
val = [val]
|
472
|
+
else
|
473
|
+
val = expr!(:interp_string)
|
474
|
+
end
|
475
|
+
ss
|
410
476
|
end
|
411
|
-
|
477
|
+
tok(/\]/)
|
478
|
+
|
479
|
+
Selector::Attribute.new(merge(name), merge(ns), op, merge(val))
|
412
480
|
end
|
413
481
|
|
414
482
|
def attrib_name!
|
@@ -422,19 +490,23 @@ module Sass
|
|
422
490
|
end
|
423
491
|
else
|
424
492
|
# *|E or |E
|
425
|
-
ns = tok(/\*/) || ""
|
493
|
+
ns = [tok(/\*/) || ""]
|
426
494
|
tok!(/\|/)
|
427
495
|
name = expr!(:interp_ident)
|
428
496
|
end
|
429
|
-
return
|
497
|
+
return ns, name
|
430
498
|
end
|
431
499
|
|
432
500
|
def pseudo
|
433
501
|
return unless s = tok(/::?/)
|
434
502
|
@expected = "pseudoclass or pseudoelement"
|
435
|
-
|
436
|
-
|
437
|
-
|
503
|
+
name = expr!(:interp_ident)
|
504
|
+
if tok(/\(/)
|
505
|
+
ss
|
506
|
+
arg = expr!(:pseudo_expr)
|
507
|
+
tok!(/\)/)
|
508
|
+
end
|
509
|
+
Selector::Pseudo.new(s == ':' ? :class : :element, merge(name), merge(arg))
|
438
510
|
end
|
439
511
|
|
440
512
|
def pseudo_expr
|
@@ -450,10 +522,11 @@ module Sass
|
|
450
522
|
|
451
523
|
def negation
|
452
524
|
return unless tok(NOT)
|
453
|
-
|
525
|
+
ss
|
454
526
|
@expected = "selector"
|
455
|
-
|
456
|
-
|
527
|
+
sel = element_name || id_selector || class_selector || attrib || expr!(:pseudo)
|
528
|
+
tok!(/\)/)
|
529
|
+
Selector::Negation.new(sel)
|
457
530
|
end
|
458
531
|
|
459
532
|
def declaration
|
@@ -467,8 +540,8 @@ module Sass
|
|
467
540
|
end
|
468
541
|
ss
|
469
542
|
|
470
|
-
|
471
|
-
space, value =
|
543
|
+
tok!(/:/)
|
544
|
+
space, value = value!
|
472
545
|
ss
|
473
546
|
require_block = tok?(/\{/)
|
474
547
|
|
@@ -478,16 +551,19 @@ module Sass
|
|
478
551
|
nested_properties! node, space
|
479
552
|
end
|
480
553
|
|
481
|
-
def
|
482
|
-
'":" or "="'
|
483
|
-
end
|
484
|
-
|
485
|
-
def value
|
486
|
-
return unless tok(/:/)
|
554
|
+
def value!
|
487
555
|
space = !str {ss}.empty?
|
488
556
|
@use_property_exception ||= space || !tok?(IDENT)
|
489
557
|
|
490
558
|
return true, Sass::Script::String.new("") if tok?(/\{/)
|
559
|
+
# This is a bit of a dirty trick:
|
560
|
+
# if the value is completely static,
|
561
|
+
# we don't parse it at all, and instead return a plain old string
|
562
|
+
# containing the value.
|
563
|
+
# This results in a dramatic speed increase.
|
564
|
+
if val = tok(STATIC_VALUE)
|
565
|
+
return space, Sass::Script::String.new(val.strip)
|
566
|
+
end
|
491
567
|
return space, sass_script(:parse)
|
492
568
|
end
|
493
569
|
|
@@ -616,6 +692,10 @@ MESSAGE
|
|
616
692
|
result
|
617
693
|
end
|
618
694
|
|
695
|
+
def merge(arr)
|
696
|
+
arr && Haml::Util.merge_adjacent_strings([arr].flatten)
|
697
|
+
end
|
698
|
+
|
619
699
|
EXPR_NAMES = {
|
620
700
|
:media_query => "media query (e.g. print, screen, print and screen)",
|
621
701
|
:media_expr => "media expression (e.g. (min-device-width: 800px)))",
|
@@ -623,11 +703,13 @@ MESSAGE
|
|
623
703
|
:interp_ident => "identifier",
|
624
704
|
:interp_name => "identifier",
|
625
705
|
:expr => "expression (e.g. 1px, bold)",
|
706
|
+
:_selector => "selector",
|
707
|
+
:simple_selector_sequence => "selector",
|
626
708
|
}
|
627
709
|
|
628
710
|
TOK_NAMES = Haml::Util.to_hash(
|
629
711
|
Sass::SCSS::RX.constants.map {|c| [Sass::SCSS::RX.const_get(c), c.downcase]}).
|
630
|
-
merge(IDENT => "identifier", /[;}]/ => '";"'
|
712
|
+
merge(IDENT => "identifier", /[;}]/ => '";"')
|
631
713
|
|
632
714
|
def tok?(rx)
|
633
715
|
@scanner.match?(rx)
|