Class: Sass::Selector::SimpleSequence

### Home Classes Methods

### In Files

- lib/sass/selector/simple_sequence.rb

### Parent

Sass::Selector::AbstractSequence

### Methods

- ::new
- #base
- #do_extend
- #inspect
- #pseudo_elements
- #resolve_parent_refs
- #rest
- #selector_pseudo_classes
- #subject?
- #superselector?
- #to_s
- #unify
- #with_more_sources

### Class/Module Index

Quicksearch

- Sass
- Sass::BaseEnvironment
- Sass::CSS
- Sass::CacheStores
- Sass::CacheStores::Base
- Sass::CacheStores::Chain
- Sass::CacheStores::Filesystem
- Sass::CacheStores::Memory
- Sass::CacheStores::Null
- Sass::Callbacks
- Sass::Callbacks::InstanceMethods
- Sass::Engine
- Sass::Engine::Line
- Sass::Environment
- Sass::Exec
- Sass::Exec::Base
- Sass::Exec::SassConvert
- Sass::Exec::SassScss
- Sass::Exec::SassScss::Sass::Plugin.compiler
- Sass::Features
- Sass::Importers
- Sass::Importers::Base
- Sass::Importers::Filesystem
- Sass::Logger
- Sass::Logger::Base
- Sass::Logger::LogLevel
- Sass::Logger::LogLevel::ClassMethods
- Sass::Media
- Sass::Media::Query
- Sass::Media::QueryList
- Sass::Plugin
- Sass::Plugin::Compiler
- Sass::Plugin::Configuration
- Sass::Plugin::MerbBootLoader
- Sass::Plugin::Rack
- Sass::Plugin::StalenessChecker
- Sass::ReadOnlyEnvironment
- Sass::Repl
- Sass::SCSS
- Sass::SCSS::CssParser
- Sass::SCSS::Parser
- Sass::SCSS::RX
- Sass::SCSS::ScriptLexer
- Sass::SCSS::ScriptParser
- Sass::SCSS::StaticParser
- Sass::Script
- Sass::Script::CssLexer
- Sass::Script::CssParser
- Sass::Script::Functions
- Sass::Script::Functions::EvaluationContext
- Sass::Script::Lexer
- Sass::Script::Parser
- Sass::Script::Tree
- Sass::Script::Tree::Funcall
- Sass::Script::Tree::Interpolation
- Sass::Script::Tree::ListLiteral
- Sass::Script::Tree::Literal
- Sass::Script::Tree::MapLiteral
- Sass::Script::Tree::Node
- Sass::Script::Tree::Operation
- Sass::Script::Tree::Selector
- Sass::Script::Tree::StringInterpolation
- Sass::Script::Tree::UnaryOperation
- Sass::Script::Tree::Variable
- Sass::Script::Value
- Sass::Script::Value::ArgList
- Sass::Script::Value::Base
- Sass::Script::Value::Bool
- Sass::Script::Value::Color
- Sass::Script::Value::Helpers
- Sass::Script::Value::List
- Sass::Script::Value::Map
- Sass::Script::Value::Null
- Sass::Script::Value::Number
- Sass::Selector
- Sass::Selector::AbstractSequence
- Sass::Selector::Attribute
- Sass::Selector::Class
- Sass::Selector::CommaSequence
- Sass::Selector::Element
- Sass::Selector::Id
- Sass::Selector::Parent
- Sass::Selector::Placeholder
- Sass::Selector::Pseudo
- Sass::Selector::Sequence
- Sass::Selector::Simple
- Sass::Selector::SimpleSequence
- Sass::Selector::Universal
- Sass::SemiGlobalEnvironment
- Sass::Shared
- Sass::Source
- Sass::Source::Map
- Sass::Source::Map::Mapping
- Sass::Source::Position
- Sass::Source::Range
- Sass::Stack
- Sass::Stack::Frame
- Sass::Supports
- Sass::Supports::Condition
- Sass::Supports::Declaration
- Sass::Supports::Interpolation
- Sass::Supports::Negation
- Sass::Supports::Operator
- Sass::SyntaxError
- Sass::Tree
- Sass::Tree::AtRootNode
- Sass::Tree::CharsetNode
- Sass::Tree::CommentNode
- Sass::Tree::ContentNode
- Sass::Tree::CssImportNode
- Sass::Tree::DebugNode
- Sass::Tree::DirectiveNode
- Sass::Tree::EachNode
- Sass::Tree::ErrorNode
- Sass::Tree::ExtendNode
- Sass::Tree::ForNode
- Sass::Tree::FunctionNode
- Sass::Tree::IfNode
- Sass::Tree::ImportNode
- Sass::Tree::KeyframeRuleNode
- Sass::Tree::MediaNode
- Sass::Tree::MixinDefNode
- Sass::Tree::MixinNode
- Sass::Tree::Node
- Sass::Tree::PropNode
- Sass::Tree::ReturnNode
- Sass::Tree::RootNode
- Sass::Tree::RuleNode
- Sass::Tree::SupportsNode
- Sass::Tree::TraceNode
- Sass::Tree::VariableNode
- Sass::Tree::Visitors
- Sass::Tree::Visitors::Base
- Sass::Tree::Visitors::CheckNesting
- Sass::Tree::Visitors::Convert
- Sass::Tree::Visitors::Cssize
- Sass::Tree::Visitors::Cssize::Bubble
- Sass::Tree::Visitors::DeepCopy
- Sass::Tree::Visitors::Extend
- Sass::Tree::Visitors::Perform
- Sass::Tree::Visitors::SetOptions
- Sass::Tree::Visitors::ToCss
- Sass::Tree::WarnNode
- Sass::Tree::WhileNode
- Sass::UnitConversionError
- Sass::Util
- Sass::Util::CrossPlatformRandom
- Sass::Util::MultibyteStringScanner
- Sass::Util::NormalizedMap
- Sass::Util::SubsetMap
- Sass::Util::Test
- Sass::Version
- ActionController
- ActionController::Base
- Object
- OrderedHash

No matching classes.

# Sass::Selector::SimpleSequence

A unseparated sequence of selectors that all apply to a single element. For example, `.foo#bar` is a simple sequence of the selectors `.foo`, `bar`, and `[attr=baz]`.

### Attributes

members[RW]

The array of individual selectors.

@return [Array<Simple>]

source_range[RW]

This sequence source range.

@return [Sass::Source::Range]

sources[RW]

The extending selectors that caused this selector sequence to be generated. For example:

    a.foo { ... }
    b.bar {@extend a}
    c.baz {@extend b}

The generated selector `b.foo.bar` has `{b.bar}` as its `sources` set, and the generated selector `c.foo.bar.baz` has `{b.bar, c.baz}` as its `sources` set.

This is populated during the {Sequence#do_extend} process.

@return {Set<Sequence>}

subject[W]

@see {#subject?}

### Public Class Methods

new(selectors, subject, source_range = nil) click to toggle source

@param selectors [Array<Simple>] See {#members} @param subject [Boolean] See {#subject?} @param source_range [Sass::Source::Range]

    # File lib/sass/selector/simple_sequence.rb, line 74
    def initialize(selectors, subject, source_range = nil)
      @members = selectors
      @subject = subject
      @sources = Set.new
      @source_range = source_range
    end

### Public Instance Methods

base() click to toggle source

Returns the element or universal selector in this sequence, if it exists.

@return [Element, Universal, nil]

    # File lib/sass/selector/simple_sequence.rb, line 41
    def base
      @base ||= (members.first if members.first.is_a?(Element) || members.first.is_a?(Universal))
    end

do_extend(extends, parent_directives, replace, seen) click to toggle source

Non-destructively extends this selector with the extensions specified in a hash (which should come from {Sass::Tree::Visitors::Cssize}).

@param extends [{Selector::Simple =>

                   Sass::Tree::Visitors::Cssize::Extend}]
    The extensions to perform on this selector

@param parent_directives [Array<Sass::Tree::DirectiveNode>]

    The directives containing this selector.

@param seen [Set<Array<Selector::Simple>>]

    The set of simple sequences that are currently being replaced.

@param original [Boolean]

    Whether this is the original selector being extended, as opposed to
    the result of a previous extension that's being re-extended.

@return [Array<Sequence>] A list of selectors generated

    by extending this selector with `extends`.

@see CommaSequence#do_extend

    # File lib/sass/selector/simple_sequence.rb, line 157
    def do_extend(extends, parent_directives, replace, seen)
      seen_with_pseudo_selectors = seen.dup

      modified_original = false
      members = Sass::Util.enum_with_index(self.members).map do |sel, i|
        next sel unless sel.is_a?(Pseudo) && sel.selector
        next sel if seen.include?([sel])
        extended = sel.selector.do_extend(extends, parent_directives, replace, seen, !:original)
        next sel if extended == sel.selector
        extended.members.reject! {|seq| seq.has_placeholder?}

        # For `:not()`, we usually want to get rid of any complex
        # selectors becuase that will cause the selector to fail to
        # parse on all browsers at time of writing. We can keep them
        # if either the original selector had a complex selector, or
        # the result of extending has only complex selectors,
        # because either way we aren't breaking anything that isn't
        # already broken.
        if sel.normalized_name == 'not' &&
            (sel.selector.members.none? {|seq| seq.members.length > 1} &&
             extended.members.any? {|seq| seq.members.length == 1})
          extended.members.reject! {|seq| seq.members.length > 1}
        end

        modified_original = true
        result = sel.with_selector(extended)
        result.each {|new_sel| seen_with_pseudo_selectors << [new_sel]}
        result
      end.flatten

      groups = Sass::Util.group_by_to_a(extends[members.to_set]) {|ex| ex.extender}
      groups.map! do |seq, group|
        sels = group.map {|e| e.target}.flatten
        # If A {@extend B} and C {...},
        # seq is A, sels is B, and self is C

        self_without_sel = Sass::Util.array_minus(members, sels)
        group.each {|e| e.result = :failed_to_unify unless e.result == :succeeded}
        unified = seq.members.last.unify(SimpleSequence.new(self_without_sel, subject?))
        next unless unified
        group.each {|e| e.result = :succeeded}
        group.each {|e| check_directives_match!(e, parent_directives)}
        new_seq = Sequence.new(seq.members[0...-1] + [unified])
        new_seq.add_sources!(sources + [seq])
        [sels, new_seq]
      end
      groups.compact!
      groups.map! do |sels, seq|
        next [] if seen.include?(sels)
        seq.do_extend(
          extends, parent_directives, !:replace, seen_with_pseudo_selectors + [sels], !:original)
      end
      groups.flatten!

      if modified_original || !replace || groups.empty?
        # First Law of Extend: the result of extending a selector should
        # (almost) always contain the base selector.
        #
        # See https://github.com/nex3/sass/issues/324.
        original = Sequence.new([SimpleSequence.new(members, @subject, source_range)])
        original.add_sources! sources
        groups.unshift original
      end
      groups.uniq!
      groups
    end

inspect() click to toggle source

Returns a string representation of the sequence. This is basically the selector string.

@return [String]

    # File lib/sass/selector/simple_sequence.rb, line 298
    def inspect
      res = members.map {|m| m.inspect}.join
      res << '!' if subject?
      res
    end

pseudo_elements() click to toggle source

    # File lib/sass/selector/simple_sequence.rb, line 45
    def pseudo_elements
      @pseudo_elements ||= members.select {|sel| sel.is_a?(Pseudo) && sel.type == :element}
    end

resolve_parent_refs(super_cseq) click to toggle source

Resolves the {Parent} selectors within this selector by replacing them with the given parent selector, handling commas appropriately.

@param super_cseq [CommaSequence] The parent selector @return [CommaSequence] This selector, with parent references resolved @raise [Sass::SyntaxError] If a parent selector is invalid

    # File lib/sass/selector/simple_sequence.rb, line 88
    def resolve_parent_refs(super_cseq)
      resolved_members = @members.map do |sel|
        next sel unless sel.is_a?(Pseudo) && sel.selector
        sel.with_selector(sel.selector.resolve_parent_refs(super_cseq, !:implicit_parent))
      end.flatten

      # Parent selector only appears as the first selector in the sequence
      unless (parent = resolved_members.first).is_a?(Parent)
        return CommaSequence.new([Sequence.new([SimpleSequence.new(resolved_members, subject?)])])
      end

      return super_cseq if @members.size == 1 && parent.suffix.nil?

      CommaSequence.new(super_cseq.members.map do |super_seq|
        members = super_seq.members.dup
        newline = members.pop if members.last == "\n"
        unless members.last.is_a?(SimpleSequence)
          raise Sass::SyntaxError.new("Invalid parent selector for \"#{self}\": \"" +
            super_seq.to_s + '"')
        end

        parent_sub = members.last.members
        unless parent.suffix.nil?
          parent_sub = parent_sub.dup
          parent_sub[-1] = parent_sub.last.dup
          case parent_sub.last
          when Sass::Selector::Class, Sass::Selector::Id, Sass::Selector::Placeholder
            parent_sub[-1] = parent_sub.last.class.new(parent_sub.last.name + parent.suffix)
          when Sass::Selector::Element
            parent_sub[-1] = parent_sub.last.class.new(
              parent_sub.last.name + parent.suffix,
              parent_sub.last.namespace)
          when Sass::Selector::Pseudo
            if parent_sub.last.arg || parent_sub.last.selector
              raise Sass::SyntaxError.new("Invalid parent selector for \"#{self}\": \"" +
                super_seq.to_s + '"')
            end
            parent_sub[-1] = Sass::Selector::Pseudo.new(
              parent_sub.last.type,
              parent_sub.last.name + parent.suffix,
              nil, nil)
          else
            raise Sass::SyntaxError.new("Invalid parent selector for \"#{self}\": \"" +
              super_seq.to_s + '"')
          end
        end

        Sequence.new(members[0...-1] +
          [SimpleSequence.new(parent_sub + resolved_members[1..-1], subject?)] +
          [newline].compact)
        end)
    end

rest() click to toggle source

Returns the non-base, non-pseudo-element selectors in this sequence.

@return [Set<Simple>]

    # File lib/sass/selector/simple_sequence.rb, line 58
    def rest
      @rest ||= Set.new(members - [base] - pseudo_elements)
    end

selector_pseudo_classes() click to toggle source

    # File lib/sass/selector/simple_sequence.rb, line 49
    def selector_pseudo_classes
      @selector_pseudo_classes ||= members.
        select {|sel| sel.is_a?(Pseudo) && sel.type == :class && sel.selector}.
        group_by {|sel| sel.normalized_name}
    end

subject?() click to toggle source

Whether or not this compound selector is the subject of the parent selector; that is, whether it is prepended with `$` and represents the actual element that will be selected.

@return [Boolean]

    # File lib/sass/selector/simple_sequence.rb, line 67
    def subject?
      @subject
    end

superselector?(their_sseq, parents = []) click to toggle source

Returns whether or not this selector matches all elements that the given selector matches (as well as possibly more).

@example

    (.foo).superselector?(.foo.bar) #=> true
    (.foo).superselector?(.bar) #=> false

@param their_sseq [SimpleSequence] @param parents [Array<SimpleSequence, String>] The parent selectors of `their_sseq`, if any. @return [Boolean]

    # File lib/sass/selector/simple_sequence.rb, line 255
    def superselector?(their_sseq, parents = [])
      return false unless base.nil? || base.eql?(their_sseq.base)
      return false unless pseudo_elements.eql?(their_sseq.pseudo_elements)
      our_spcs = selector_pseudo_classes
      their_spcs = their_sseq.selector_pseudo_classes

      # Some psuedo-selectors can be subselectors of non-pseudo selectors.
      # Pull those out here so we can efficiently check against them below.
      their_subselector_pseudos = ]matches any nth-child nth-last-child].
        map {|name| their_spcs[name] || []}.flatten

      # If `self`'s non-pseudo simple selectors aren't a subset of `their_sseq`'s,
      # it's definitely not a superselector. This also considers being matched
      # by `:matches` or `:any`.
      return false unless rest.all? do |our_sel|
        next true if our_sel.is_a?(Pseudo) && our_sel.selector
        next true if their_sseq.rest.include?(our_sel)
        their_subselector_pseudos.any? do |their_pseudo|
          their_pseudo.selector.members.all? do |their_seq|
            next false unless their_seq.members.length == 1
            their_sseq = their_seq.members.first
            next false unless their_sseq.is_a?(SimpleSequence)
            their_sseq.rest.include?(our_sel)
          end
        end
      end

      our_spcs.all? do |name, pseudos|
        pseudos.all? {|pseudo| pseudo.superselector?(their_sseq, parents)}
      end
    end

to_s() click to toggle source

@see Simple#to_s

    # File lib/sass/selector/simple_sequence.rb, line 288
    def to_s
      res = @members.join
      res << '!' if subject?
      res
    end

unify(other) click to toggle source

Unifies this selector with another {SimpleSequence}, returning another `SimpleSequence` that is a subselector of both input selectors.

@param other [SimpleSequence] @return [SimpleSequence, nil] A {SimpleSequence} matching both `sels` and this selector,

    or `nil` if this is impossible (e.g. unifying `#foo` and `#bar`)

@raise [Sass::SyntaxError] If this selector cannot be unified.

    This will only ever occur when a dynamic selector,
    such as {Parent} or {Interpolation}, is used in unification.
    Since these selectors should be resolved
    by the time extension and unification happen,
    this exception will only ever be raised as a result of programmer error

    # File lib/sass/selector/simple_sequence.rb, line 237
    def unify(other)
      sseq = members.inject(other.members) do |member, sel|
        return unless member
        sel.unify(member)
      end
      return unless sseq
      SimpleSequence.new(sseq, other.subject? || subject?)
    end

with_more_sources(sources) click to toggle source

Return a copy of this simple sequence with `sources` merged into the {SimpleSequence#sources} set.

@param sources [Set<Sequence>] @return [SimpleSequence]

    # File lib/sass/selector/simple_sequence.rb, line 309
    def with_more_sources(sources)
      sseq = dup
      sseq.members = members.dup
      sseq.sources = self.sources | sources
      sseq
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.