haml-edge 3.1.41 → 3.1.42
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/sass/engine.rb +27 -10
- data/lib/sass/script/lexer.rb +1 -1
- data/lib/sass/scss/parser.rb +17 -6
- data/lib/sass/scss/rx.rb +1 -0
- data/lib/sass/scss/static_parser.rb +1 -7
- data/lib/sass/selector/comma_sequence.rb +7 -0
- data/lib/sass/selector/simple.rb +2 -2
- data/lib/sass/selector.rb +15 -7
- data/test/sass/conversion_test.rb +8 -1
- data/test/sass/engine_test.rb +15 -2
- data/test/sass/scss/css_test.rb +16 -1
- data/test/sass/scss/scss_test.rb +15 -2
- data/test/sass/templates/import.sass +1 -1
- metadata +1 -1
data/EDGE_GEM_VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.1.
|
1
|
+
3.1.42
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.1.
|
1
|
+
3.1.42
|
data/lib/sass/engine.rb
CHANGED
@@ -509,16 +509,7 @@ WARNING
|
|
509
509
|
# If value begins with url( or ",
|
510
510
|
# it's a CSS @import rule and we don't want to touch it.
|
511
511
|
if directive == "import"
|
512
|
-
|
513
|
-
:line => @line + 1) unless line.children.empty?
|
514
|
-
if (match = value.match(Sass::SCSS::RX::STRING) || value.match(Sass::SCSS::RX::URI)) &&
|
515
|
-
!match.post_match.strip.empty? && match.post_match.strip[0] != ?,
|
516
|
-
return Tree::DirectiveNode.new("@import #{value}")
|
517
|
-
end
|
518
|
-
value.split(/,\s*/).map do |f|
|
519
|
-
f = $1 || $2 || $3 if f =~ Sass::SCSS::RX::STRING || f =~ Sass::SCSS::RX::URI
|
520
|
-
Tree::ImportNode.new(f)
|
521
|
-
end
|
512
|
+
parse_import(line, value)
|
522
513
|
elsif directive == "mixin"
|
523
514
|
parse_mixin_definition(line)
|
524
515
|
elsif directive == "include"
|
@@ -597,6 +588,32 @@ WARNING
|
|
597
588
|
nil
|
598
589
|
end
|
599
590
|
|
591
|
+
def parse_import(line, value)
|
592
|
+
raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath import directives.",
|
593
|
+
:line => @line + 1) unless line.children.empty?
|
594
|
+
|
595
|
+
if (match = value.match(Sass::SCSS::RX::STRING) || value.match(Sass::SCSS::RX::URI)) &&
|
596
|
+
match.offset(0).first == 0 && !match.post_match.strip.empty? &&
|
597
|
+
match.post_match.strip[0] != ?,
|
598
|
+
# @import "filename" media-type
|
599
|
+
return Tree::DirectiveNode.new("@import #{value}")
|
600
|
+
end
|
601
|
+
|
602
|
+
value.split(/,\s*/).map do |f|
|
603
|
+
if f =~ Sass::SCSS::RX::URI
|
604
|
+
# All url()s are literal CSS @imports
|
605
|
+
next Tree::DirectiveNode.new("@import #{f}")
|
606
|
+
elsif f =~ Sass::SCSS::RX::STRING
|
607
|
+
f = $1 || $2
|
608
|
+
end
|
609
|
+
|
610
|
+
# http:// URLs are always literal CSS imports
|
611
|
+
next Tree::DirectiveNode.new("@import url(#{f})") if f =~ /^http:\/\//
|
612
|
+
|
613
|
+
Tree::ImportNode.new(f)
|
614
|
+
end
|
615
|
+
end
|
616
|
+
|
600
617
|
MIXIN_DEF_RE = /^(?:=|@mixin)\s*(#{Sass::SCSS::RX::IDENT})(.*)$/
|
601
618
|
def parse_mixin_definition(line)
|
602
619
|
name, arg_string = line.text.scan(MIXIN_DEF_RE).first
|
data/lib/sass/script/lexer.rb
CHANGED
@@ -292,7 +292,7 @@ MESSAGE
|
|
292
292
|
end
|
293
293
|
|
294
294
|
def special_fun
|
295
|
-
return unless str1 = scan(/(calc|expression|progid:[a-z\.]*)\(/i)
|
295
|
+
return unless str1 = scan(/((-[\w-]+-)?calc|expression|progid:[a-z\.]*)\(/i)
|
296
296
|
str2, _ = Haml::Shared.balance(@scanner, ?(, ?), 1)
|
297
297
|
c = str2.count("\n")
|
298
298
|
old_line = @line
|
data/lib/sass/scss/parser.rb
CHANGED
@@ -200,13 +200,13 @@ module Sass
|
|
200
200
|
|
201
201
|
def import_directive
|
202
202
|
@expected = "string or url()"
|
203
|
-
arg = tok(STRING) || tok!(URI)
|
203
|
+
arg = tok(STRING) || (uri = tok!(URI))
|
204
204
|
path = @scanner[1] || @scanner[2] || @scanner[3]
|
205
205
|
ss
|
206
206
|
|
207
207
|
media = str {media_query_list}.strip
|
208
208
|
|
209
|
-
if !media.strip.empty? || use_css_import?
|
209
|
+
if uri || path =~ /^http:\/\// || !media.strip.empty? || use_css_import?
|
210
210
|
return node(Sass::Tree::DirectiveNode.new("@import #{arg} #{media}".strip))
|
211
211
|
end
|
212
212
|
|
@@ -381,6 +381,17 @@ module Sass
|
|
381
381
|
sel.to_a
|
382
382
|
end
|
383
383
|
|
384
|
+
def selector_comma_sequence
|
385
|
+
return unless sel = _selector
|
386
|
+
selectors = [sel]
|
387
|
+
while tok(/,/)
|
388
|
+
ws = str{ss}
|
389
|
+
selectors << expr!(:_selector)
|
390
|
+
selectors[-1] = Selector::Sequence.new(["\n"] + selectors.last.members) if ws.include?("\n")
|
391
|
+
end
|
392
|
+
Selector::CommaSequence.new(selectors)
|
393
|
+
end
|
394
|
+
|
384
395
|
def _selector
|
385
396
|
# The combinator here allows the "> E" hack
|
386
397
|
return unless val = combinator || simple_selector_sequence
|
@@ -533,12 +544,12 @@ MESSAGE
|
|
533
544
|
end
|
534
545
|
|
535
546
|
def negation
|
536
|
-
return unless tok(NOT)
|
547
|
+
return unless name = tok(NOT) || tok(MOZ_ANY)
|
537
548
|
ss
|
538
549
|
@expected = "selector"
|
539
|
-
sel =
|
550
|
+
sel = selector_comma_sequence
|
540
551
|
tok!(/\)/)
|
541
|
-
Selector::
|
552
|
+
Selector::SelectorPseudoClass.new(name[1...-1], sel)
|
542
553
|
end
|
543
554
|
|
544
555
|
def declaration
|
@@ -722,7 +733,7 @@ MESSAGE
|
|
722
733
|
:interp_ident => "identifier",
|
723
734
|
:interp_name => "identifier",
|
724
735
|
:expr => "expression (e.g. 1px, bold)",
|
725
|
-
:
|
736
|
+
:selector_comma_sequence => "selector",
|
726
737
|
:simple_selector_sequence => "selector",
|
727
738
|
}
|
728
739
|
|
data/lib/sass/scss/rx.rb
CHANGED
@@ -109,6 +109,7 @@ module Sass
|
|
109
109
|
# Custom
|
110
110
|
HEXCOLOR = /\#[0-9a-fA-F]+/
|
111
111
|
INTERP_START = /#\{/
|
112
|
+
MOZ_ALL = quote(":-moz-any(", Regexp::IGNORECASE)
|
112
113
|
|
113
114
|
STRING1_NOINTERP = /\"((?:[^\n\r\f\\"#]|#(?!\{)|\\#{NL}|#{ESCAPE})*)\"/
|
114
115
|
STRING2_NOINTERP = /\'((?:[^\n\r\f\\'#]|#(?!\{)|\\#{NL}|#{ESCAPE})*)\'/
|
@@ -17,14 +17,8 @@ module Sass
|
|
17
17
|
# @raise [Sass::SyntaxError] if there's a syntax error in the selector
|
18
18
|
def parse_selector(filename)
|
19
19
|
init_scanner!
|
20
|
-
|
21
|
-
while tok(/,/)
|
22
|
-
ws = str{ss}
|
23
|
-
selectors << expr!(:_selector)
|
24
|
-
selectors[-1] = Selector::Sequence.new(["\n"] + selectors.last.members) if ws.include?("\n")
|
25
|
-
end
|
20
|
+
seq = expr!(:selector_comma_sequence)
|
26
21
|
expected("selector") unless @scanner.eos?
|
27
|
-
seq = Selector::CommaSequence.new(selectors)
|
28
22
|
seq.line = @line
|
29
23
|
seq.filename = filename
|
30
24
|
seq
|
data/lib/sass/selector/simple.rb
CHANGED
@@ -78,10 +78,10 @@ module Sass
|
|
78
78
|
return sels if sels.any? {|sel2| eql?(sel2)}
|
79
79
|
sels_with_ix = Haml::Util.enum_with_index(sels)
|
80
80
|
_, i =
|
81
|
-
if self.is_a?(Pseudo) || self.is_a?(
|
81
|
+
if self.is_a?(Pseudo) || self.is_a?(SelectorPseudoClass)
|
82
82
|
sels_with_ix.find {|sel, _| sel.is_a?(Pseudo) && sels.last.type == :element}
|
83
83
|
else
|
84
|
-
sels_with_ix.find {|sel, _| sel.is_a?(Pseudo) || sel.is_a?(
|
84
|
+
sels_with_ix.find {|sel, _| sel.is_a?(Pseudo) || sel.is_a?(SelectorPseudoClass)}
|
85
85
|
end
|
86
86
|
return sels + [self] unless i
|
87
87
|
return sels[0...i] + [self] + sels[i..-1]
|
data/lib/sass/selector.rb
CHANGED
@@ -332,21 +332,29 @@ module Sass
|
|
332
332
|
end
|
333
333
|
end
|
334
334
|
|
335
|
-
# A
|
336
|
-
|
337
|
-
|
335
|
+
# A pseudoclass selector whose argument is itself a selector
|
336
|
+
# (e.g. `:not(.foo)` or `:-moz-all(.foo, .bar)`).
|
337
|
+
class SelectorPseudoClass < Simple
|
338
|
+
# The name of the pseudoclass.
|
338
339
|
#
|
339
|
-
# @return [
|
340
|
+
# @return [String]
|
341
|
+
attr_reader :name
|
342
|
+
|
343
|
+
# The selector argument.
|
344
|
+
#
|
345
|
+
# @return [Selector::Sequence]
|
340
346
|
attr_reader :selector
|
341
347
|
|
342
|
-
# @param [
|
343
|
-
|
348
|
+
# @param [String] The name of the pseudoclass
|
349
|
+
# @param [Selector::Sequence] The selector argument
|
350
|
+
def initialize(name, selector)
|
351
|
+
@name = name
|
344
352
|
@selector = selector
|
345
353
|
end
|
346
354
|
|
347
355
|
# @see Selector#to_a
|
348
356
|
def to_a
|
349
|
-
[":
|
357
|
+
[":", @name, "("] + @selector.to_a + [")"]
|
350
358
|
end
|
351
359
|
end
|
352
360
|
end
|
@@ -671,11 +671,15 @@ SCSS
|
|
671
671
|
assert_renders <<SASS, <<SCSS
|
672
672
|
@import foo
|
673
673
|
|
674
|
+
@import url(bar.css)
|
675
|
+
|
674
676
|
foo
|
675
677
|
bar: baz
|
676
678
|
SASS
|
677
679
|
@import "foo";
|
678
680
|
|
681
|
+
@import url(bar.css);
|
682
|
+
|
679
683
|
foo {
|
680
684
|
bar: baz; }
|
681
685
|
SCSS
|
@@ -683,11 +687,15 @@ SCSS
|
|
683
687
|
assert_renders <<SASS, <<SCSS
|
684
688
|
@import foo.css
|
685
689
|
|
690
|
+
@import url(bar.css)
|
691
|
+
|
686
692
|
foo
|
687
693
|
bar: baz
|
688
694
|
SASS
|
689
695
|
@import "foo.css";
|
690
696
|
|
697
|
+
@import url(bar.css);
|
698
|
+
|
691
699
|
foo {
|
692
700
|
bar: baz; }
|
693
701
|
SCSS
|
@@ -695,7 +703,6 @@ SCSS
|
|
695
703
|
|
696
704
|
def test_import_as_directive_in_sass
|
697
705
|
assert_equal "@import foo.css\n", to_sass('@import "foo.css"')
|
698
|
-
assert_equal "@import foo.css\n", to_sass('@import url(foo.css)')
|
699
706
|
end
|
700
707
|
|
701
708
|
def test_import_as_directive_in_scss
|
data/test/sass/engine_test.rb
CHANGED
@@ -487,8 +487,21 @@ CSS
|
|
487
487
|
end
|
488
488
|
|
489
489
|
def test_css_import
|
490
|
-
assert_equal("@import url(./fonts.css)
|
491
|
-
|
490
|
+
assert_equal("@import url(./fonts.css);\n", render("@import \"./fonts.css\""))
|
491
|
+
end
|
492
|
+
|
493
|
+
def test_media_import
|
494
|
+
assert_equal("@import \"./fonts.sass\" all;\n",
|
495
|
+
render("@import \"./fonts.sass\" all"))
|
496
|
+
end
|
497
|
+
|
498
|
+
def test_http_import
|
499
|
+
assert_equal("@import url(http://fonts.googleapis.com/css?family=Droid+Sans);\n",
|
500
|
+
render("@import \"http://fonts.googleapis.com/css?family=Droid+Sans\""))
|
501
|
+
end
|
502
|
+
|
503
|
+
def test_url_import
|
504
|
+
assert_equal("@import url(fonts.sass);\n", render("@import url(fonts.sass)"))
|
492
505
|
end
|
493
506
|
|
494
507
|
def test_sass_import
|
data/test/sass/scss/css_test.rb
CHANGED
@@ -382,7 +382,10 @@ SCSS
|
|
382
382
|
def test_calc_function
|
383
383
|
assert_parses <<SCSS
|
384
384
|
foo {
|
385
|
-
a: 12px calc(100%/3 - 2*1em - 2*1px);
|
385
|
+
a: 12px calc(100%/3 - 2*1em - 2*1px);
|
386
|
+
b: 12px -moz-calc(100%/3 - 2*1em - 2*1px);
|
387
|
+
b: 12px -webkit-calc(100%/3 - 2*1em - 2*1px);
|
388
|
+
b: 12px -foobar-calc(100%/3 - 2*1em - 2*1px); }
|
386
389
|
SCSS
|
387
390
|
end
|
388
391
|
|
@@ -703,6 +706,18 @@ SCSS
|
|
703
706
|
|
704
707
|
assert_selector_parses(':not(:hover)')
|
705
708
|
assert_selector_parses(':not(:nth-child(2n + 3))')
|
709
|
+
|
710
|
+
# Not technically allowed, but what the heck
|
711
|
+
assert_selector_parses(':not(:not(#foo))')
|
712
|
+
assert_selector_parses(':not(a#foo.bar)')
|
713
|
+
assert_selector_parses(':not(#foo .bar > baz)')
|
714
|
+
assert_selector_parses(':not(h1, h2, h3)')
|
715
|
+
end
|
716
|
+
|
717
|
+
def test_moz_any_selector
|
718
|
+
assert_selector_parses(':-moz-any(h1, h2, h3)')
|
719
|
+
assert_selector_parses(':-moz-any(.foo)')
|
720
|
+
assert_selector_parses(':-moz-any(foo bar, .baz > .bang)')
|
706
721
|
end
|
707
722
|
|
708
723
|
def test_namespaced_selectors
|
data/test/sass/scss/scss_test.rb
CHANGED
@@ -212,11 +212,24 @@ SCSS
|
|
212
212
|
def test_css_import_directive
|
213
213
|
assert_equal "@import url(foo.css);\n", render('@import "foo.css";')
|
214
214
|
assert_equal "@import url(foo.css);\n", render("@import 'foo.css';")
|
215
|
-
assert_equal "@import url(foo.css);\n", render('@import url("foo.css");')
|
216
|
-
assert_equal "@import url(foo.css);\n", render("@import url('foo.css');")
|
215
|
+
assert_equal "@import url(\"foo.css\");\n", render('@import url("foo.css");')
|
216
|
+
assert_equal "@import url('foo.css');\n", render("@import url('foo.css');")
|
217
217
|
assert_equal "@import url(foo.css);\n", render('@import url(foo.css);')
|
218
218
|
end
|
219
219
|
|
220
|
+
def test_media_import
|
221
|
+
assert_equal("@import \"./fonts.sass\" all;\n", render("@import \"./fonts.sass\" all;"))
|
222
|
+
end
|
223
|
+
|
224
|
+
def test_http_import
|
225
|
+
assert_equal("@import \"http://fonts.googleapis.com/css?family=Droid+Sans\";\n",
|
226
|
+
render("@import \"http://fonts.googleapis.com/css?family=Droid+Sans\";"))
|
227
|
+
end
|
228
|
+
|
229
|
+
def test_url_import
|
230
|
+
assert_equal("@import url(fonts.sass);\n", render("@import url(fonts.sass);"))
|
231
|
+
end
|
232
|
+
|
220
233
|
def test_block_comment_in_script
|
221
234
|
assert_equal <<CSS, render(<<SCSS)
|
222
235
|
foo {
|