diff --git a/doc-src/SASS_CHANGELOG.md b/doc-src/SASS_CHANGELOG.md index affd224951..8f37526297 100644 --- a/doc-src/SASS_CHANGELOG.md +++ b/doc-src/SASS_CHANGELOG.md @@ -28,6 +28,11 @@ In anticipation of wider browser support, in fact, *any* function named `-*-calc` (such as `-webkit-calc` or `-ms-calc`) will be parsed the same as the `calc` function. +## `:-moz-any` Support + +The [`:-moz-any` pseudoclass selector](http://hacks.mozilla.org/2010/05/moz-any-selector-grouping/) +is now parsed by Sass. + ## Rails 3 Support Support for Rails 3 versions prior to beta 4 has been removed. diff --git a/lib/sass/scss/parser.rb b/lib/sass/scss/parser.rb index 9778c23b77..de4aa383d7 100644 --- a/lib/sass/scss/parser.rb +++ b/lib/sass/scss/parser.rb @@ -544,12 +544,12 @@ def pseudo_expr end def negation - return unless tok(NOT) + return unless name = tok(NOT) || tok(MOZ_ANY) ss @expected = "selector" sel = selector_comma_sequence tok!(/\)/) - Selector::Negation.new(sel) + Selector::SelectorPseudoClass.new(name[1...-1], sel) end def declaration diff --git a/lib/sass/scss/rx.rb b/lib/sass/scss/rx.rb index 386b716c92..a14bdb490a 100644 --- a/lib/sass/scss/rx.rb +++ b/lib/sass/scss/rx.rb @@ -109,6 +109,7 @@ def self.quote(str, flags = 0) # Custom HEXCOLOR = /\#[0-9a-fA-F]+/ INTERP_START = /#\{/ + MOZ_ALL = quote(":-moz-any(", Regexp::IGNORECASE) STRING1_NOINTERP = /\"((?:[^\n\r\f\\"#]|#(?!\{)|\\#{NL}|#{ESCAPE})*)\"/ STRING2_NOINTERP = /\'((?:[^\n\r\f\\'#]|#(?!\{)|\\#{NL}|#{ESCAPE})*)\'/ diff --git a/lib/sass/selector.rb b/lib/sass/selector.rb index ac41e02c67..027e90b628 100644 --- a/lib/sass/selector.rb +++ b/lib/sass/selector.rb @@ -332,21 +332,29 @@ def unify(sels) end end - # A negation pseudoclass selector (e.g. `:not(.foo)`). - class Negation < Simple - # The selector to negate. + # A pseudoclass selector whose argument is itself a selector + # (e.g. `:not(.foo)` or `:-moz-all(.foo, .bar)`). + class SelectorPseudoClass < Simple + # The name of the pseudoclass. + # + # @return [String] + attr_reader :name + + # The selector argument. # # @return [Selector::Sequence] attr_reader :selector - # @param [Selector::Sequence] The selector to negate - def initialize(selector) + # @param [String] The name of the pseudoclass + # @param [Selector::Sequence] The selector argument + def initialize(name, selector) + @name = name @selector = selector end # @see Selector#to_a def to_a - [":not("] + @selector.to_a + [")"] + [":", @name, "("] + @selector.to_a + [")"] end end end diff --git a/lib/sass/selector/simple.rb b/lib/sass/selector/simple.rb index f346cf64d0..b2e8099a57 100644 --- a/lib/sass/selector/simple.rb +++ b/lib/sass/selector/simple.rb @@ -78,10 +78,10 @@ def unify(sels) return sels if sels.any? {|sel2| eql?(sel2)} sels_with_ix = Haml::Util.enum_with_index(sels) _, i = - if self.is_a?(Pseudo) || self.is_a?(Negation) + if self.is_a?(Pseudo) || self.is_a?(SelectorPseudoClass) sels_with_ix.find {|sel, _| sel.is_a?(Pseudo) && sels.last.type == :element} else - sels_with_ix.find {|sel, _| sel.is_a?(Pseudo) || sel.is_a?(Negation)} + sels_with_ix.find {|sel, _| sel.is_a?(Pseudo) || sel.is_a?(SelectorPseudoClass)} end return sels + [self] unless i return sels[0...i] + [self] + sels[i..-1] diff --git a/test/sass/scss/css_test.rb b/test/sass/scss/css_test.rb index 05908ea0d7..28fd0aaf40 100755 --- a/test/sass/scss/css_test.rb +++ b/test/sass/scss/css_test.rb @@ -714,6 +714,12 @@ def test_negation_selectors assert_selector_parses(':not(h1, h2, h3)') end + def test_moz_any_selector + assert_selector_parses(':-moz-any(h1, h2, h3)') + assert_selector_parses(':-moz-any(.foo)') + assert_selector_parses(':-moz-any(foo bar, .baz > .bang)') + end + def test_namespaced_selectors assert_selector_parses('foo|E') assert_selector_parses('*|E')