class Sass::Selector::SimpleSequence - sass-3.2.19 Documentation

# class 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>]

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 {#do_extend} process.

@return {Set<Sequence>}

subject[W]

@see {#subject?}

### Public Class Methods

new(selectors, subject, sources = Set.new) click to toggle source

@param selectors [Array<Simple>] See {#members} @param subject [Boolean] See {#subject?} @param sources [Set<Sequence>]

    # File lib/sass/selector/simple_sequence.rb, line 64
    def initialize(selectors, subject, sources = Set.new)
      @members = selectors
      @subject = subject
      @sources = sources
    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 36
    def base
      @base ||= (members.first if members.first.is_a?(Element) || members.first.is_a?(Universal))
    end

do_extend(extends, parent_directives, seen = Set.new) click to toggle source

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

@overload def #do_extend(extends, parent_directives) @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.

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

    by extending this selector with `extends`.

@see Sass::Selector::CommaSequence#do_extend

    # File lib/sass/selector/simple_sequence.rb, line 106
    def do_extend(extends, parent_directives, seen = Set.new)
      Sass::Util.group_by_to_a(extends.get(members.to_set)) {|ex, _| ex.extender}.map do |seq, group|
        sels = group.map {|_, s| s}.flatten
        # If A {@extend B} and C {...},
        # seq is A, sels is B, and self is C

        self_without_sel = Sass::Util.array_minus(self.members, sels)
        group.each {|e, _| e.result = :failed_to_unify unless e.result == :succeeded}
        next unless unified = seq.members.last.unify(self_without_sel, subject?)
        group.each {|e, _| e.result = :succeeded}
        next if group.map {|e, _| check_directives_match!(e, parent_directives)}.none?
        new_seq = Sequence.new(seq.members[0...-1] + [unified])
        new_seq.add_sources!(sources + [seq])
        [sels, new_seq]
      end.compact.map do |sels, seq|
        seen.include?(sels) ? [] : seq.do_extend(extends, parent_directives, seen + [sels])
      end.flatten.uniq
    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 172
    def inspect
      members.map {|m| m.inspect}.join
    end

pseudo_elements() click to toggle source

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

resolve_parent_refs(super_seq) click to toggle source

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

@param super_seq [Sequence] The parent selector sequence @return [Array<SimpleSequence>] This selector, with parent references resolved.

    This is an array because the parent selector is itself a {Sequence}

@raise [Sass::SyntaxError] If a parent selector is invalid

    # File lib/sass/selector/simple_sequence.rb, line 78
    def resolve_parent_refs(super_seq)
      # Parent selector only appears as the first selector in the sequence
      return [self] unless @members.first.is_a?(Parent)

      members = super_seq.members.dup
      newline = members.pop if members.last == "\n"
      return members if @members.size == 1
      unless members.last.is_a?(SimpleSequence)
        raise Sass::SyntaxError.new("Invalid parent selector: " + super_seq.to_a.join)
      end

      members[0...-1] +
        [SimpleSequence.new(members.last.members + @members[1..-1], subject?)] +
        [newline].compact
    end

rest() click to toggle source

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

@return [Set<Simple>]

    # File lib/sass/selector/simple_sequence.rb, line 48
    def rest
      @rest ||= Set.new(members - [base] - pseudo_elements)
    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 57
    def subject?
      @subject
    end

superselector?(sseq) 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 sseq [SimpleSequence] @return [Boolean]

    # File lib/sass/selector/simple_sequence.rb, line 155
    def superselector?(sseq)
      (base.nil? || base.eql?(sseq.base)) &&
        pseudo_elements.eql?(sseq.pseudo_elements) &&
        rest.subset?(sseq.rest)
    end

to_a() click to toggle source

@see Sass::Selector::Simple#to_a

    # File lib/sass/selector/simple_sequence.rb, line 162
    def to_a
      res = @members.map {|sel| sel.to_a}.flatten
      res << '!' if subject?
      res
    end

unify(sels, other_subject) click to toggle source

Unifies this selector with another {SimpleSequence}'s {SimpleSequence#members members array}, returning another `SimpleSequence` that matches both this selector and the input selector.

@param sels [Array<Simple>] A {SimpleSequence}'s {SimpleSequence#members members array} @param subject [Boolean] Whether the {SimpleSequence} being merged is a subject. @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 139
    def unify(sels, other_subject)
      return unless sseq = members.inject(sels) do |member, sel|
        return unless member
        sel.unify(member)
      end
      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 {#sources} set.

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

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

### Private Instance Methods

_eql?(other) click to toggle source

    # File lib/sass/selector/simple_sequence.rb, line 209
    def _eql?(other)
      other.base.eql?(self.base) && other.pseudo_elements == pseudo_elements &&
        Sass::Util.set_eql?(other.rest, self.rest) && other.subject? == self.subject?
    end

_hash() click to toggle source

    # File lib/sass/selector/simple_sequence.rb, line 205
    def _hash
      [base, Sass::Util.set_hash(rest)].hash
    end

check_directives_match!(extend, parent_directives) click to toggle source

    # File lib/sass/selector/simple_sequence.rb, line 190
          def check_directives_match!(extend, parent_directives)
            dirs1 = extend.directives.map {|d| d.resolved_value}
            dirs2 = parent_directives.map {|d| d.resolved_value}
            return true if Sass::Util.subsequence?(dirs1, dirs2)

            Sass::Util.sass_warn <<WARNING
    DEPRECATION WARNING on line #{extend.node.line}#{" of #{extend.node.filename}" if extend.node.filename}:
      @extending an outer selector from within #{extend.directives.last.name} is deprecated.
      You may only @extend selectors within the same directive.
      This will be an error in Sass 3.3.
      It can only work once @extend is supported natively in the browser.
    WARNING
            return false
          end