haml-edge 3.1.41 → 3.1.42
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/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 {
|