Class: Sass::Selector::Sequence

Inherits:
AbstractSequence show all
Defined in:
lib/sass/selector/sequence.rb

Overview

An operator-separated sequence of simple selector sequences.

Instance Attribute Summary collapse

Attributes inherited from AbstractSequence

#filename, #line

Instance Method Summary collapse

Methods inherited from AbstractSequence

#_specificity, #eql?, #has_placeholder?, #hash, #specificity

Constructor Details

#initialize(seqs_and_ops) ⇒ Sequence

Returns a new instance of Sequence.

Parameters:



38
39
40
# File 'lib/sass/selector/sequence.rb', line 38

def initialize(seqs_and_ops)
  @members = seqs_and_ops
end

Instance Attribute Details

#membersArray<SimpleSequence, String|Array<Sass::Tree::Node, String>> (readonly)

The array of simple selector sequences, operators, and newlines. The operators are strings such as "+" and ">" representing the corresponding CSS operators, or interpolated SassScript. Newlines are also newline strings; these aren't semantically relevant, but they do affect formatting.

Returns:



34
35
36
# File 'lib/sass/selector/sequence.rb', line 34

def members
  @members
end

Instance Method Details

#add_sources!(sources)

Add to the Sass::Selector::SimpleSequence#sources sets of the child simple sequences. This destructively modifies this sequence's members array, but not the child simple sequences.

Parameters:



166
167
168
# File 'lib/sass/selector/sequence.rb', line 166

def add_sources!(sources)
  members.map! {|m| m.is_a?(SimpleSequence) ? m.with_more_sources(sources) : m}
end

#do_extend(extends, parent_directives, replace, seen, original) ⇒ Array<Sequence>

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

The extensions to perform on this selector

Parameters:

Returns:

See Also:



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/sass/selector/sequence.rb', line 98

def do_extend(extends, parent_directives, replace, seen, original)
  extended_not_expanded = members.map do |sseq_or_op|
    next [[sseq_or_op]] unless sseq_or_op.is_a?(SimpleSequence)
    extended = sseq_or_op.do_extend(extends, parent_directives, replace, seen)

    # The First Law of Extend says that the generated selector should have
    # specificity greater than or equal to that of the original selector.
    # In order to ensure that, we record the original selector's
    # (`extended.first`) original specificity.
    extended.first.add_sources!([self]) if original && !has_placeholder?

    extended.map {|seq| seq.members}
  end
  weaves = Sass::Util.paths(extended_not_expanded).map {|path| weave(path)}
  trim(weaves).map {|p| Sequence.new(p)}
end

#filename=(filename) ⇒ String?

Sets the name of the file in which this selector was declared, or nil if it was not declared in a file (e.g. on stdin). This also sets the filename for all child selectors.

Parameters:

  • filename (String, nil)

Returns:

  • (String, nil)


22
23
24
25
# File 'lib/sass/selector/sequence.rb', line 22

def filename=(filename)
  members.each {|m| m.filename = filename if m.is_a?(SimpleSequence)}
  filename
end

#inspectString

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

Returns:

  • (String)


157
158
159
# File 'lib/sass/selector/sequence.rb', line 157

def inspect
  members.map {|m| m.inspect}.join(" ")
end

#line=(line) ⇒ Fixnum

Sets the line of the Sass template on which this selector was declared. This also sets the line for all child selectors.

Parameters:

  • line (Fixnum)

Returns:

  • (Fixnum)


11
12
13
14
# File 'lib/sass/selector/sequence.rb', line 11

def line=(line)
  members.each {|m| m.line = line if m.is_a?(SimpleSequence)}
  line
end

#resolve_parent_refs(super_cseq, implicit_parent) ⇒ CommaSequence

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

Parameters:

  • super_cseq (CommaSequence)

    The parent selector

  • implicit_parent (Boolean)

    Whether the the parent selector should automatically be prepended to the resolved selector if it contains no parent refs.

Returns:

  • (CommaSequence)

    This selector, with parent references resolved

Raises:



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/sass/selector/sequence.rb', line 52

def resolve_parent_refs(super_cseq, implicit_parent)
  members = @members.dup
  nl = (members.first == "\n" && members.shift)
  contains_parent_ref = members.any? do |seq_or_op|
    seq_or_op.is_a?(SimpleSequence) && seq_or_op.members.first.is_a?(Parent)
  end
  return CommaSequence.new([self]) if !implicit_parent && !contains_parent_ref

  unless contains_parent_ref
    old_members, members = members, []
    members << nl if nl
    members << SimpleSequence.new([Parent.new], false)
    members += old_members
  end

  CommaSequence.new(Sass::Util.paths(members.map do |sseq_or_op|
    next [sseq_or_op] unless sseq_or_op.is_a?(SimpleSequence)
    sseq_or_op.resolve_parent_refs(super_cseq).members
  end).map do |path|
    Sequence.new(path.map do |seq_or_op|
      next seq_or_op unless seq_or_op.is_a?(Sequence)
      seq_or_op.members
    end.flatten)
  end)
end

#subjectless

Converts the subject operator "!", if it exists, into a ":has()" selector.



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/sass/selector/sequence.rb', line 174

def subjectless
  pre_subject = []
  has = []
  subject = nil
  members.each do |sseq_or_op|
    if subject
      has << sseq_or_op
    elsif sseq_or_op.is_a?(String) || !sseq_or_op.subject?
      pre_subject << sseq_or_op
    else
      subject = sseq_or_op.dup
      subject.members = sseq_or_op.members.dup
      subject.subject = false
      has = []
    end
  end

  return self unless subject

  unless has.empty?
    subject.members << Pseudo.new(:class, 'has', nil, CommaSequence.new([Sequence.new(has)]))
  end
  Sequence.new(pre_subject + [subject])
end

#superselector?(seq) ⇒ Boolean

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

Examples:

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

Parameters:

Returns:

  • (Boolean)


144
145
146
# File 'lib/sass/selector/sequence.rb', line 144

def superselector?(seq)
  _superselector?(members, seq.members)
end

#to_s



149
150
151
# File 'lib/sass/selector/sequence.rb', line 149

def to_s
  @members.join(" ").gsub(/ ?\n ?/, "\n")
end

#unify(other) ⇒ CommaSequence?

Unifies this with another selector sequence to produce a selector that matches (a subset of) the intersection of the two inputs.

Parameters:

Returns:

  • (CommaSequence, nil)

    The unified selector, or nil if unification failed.

Raises:

  • (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



126
127
128
129
130
131
132
133
134
# File 'lib/sass/selector/sequence.rb', line 126

def unify(other)
  base = members.last
  other_base = other.members.last
  return unless base.is_a?(SimpleSequence) && other_base.is_a?(SimpleSequence)
  return unless (unified = other_base.unify(base))

  woven = weave([members[0...-1], other.members[0...-1] + [unified]])
  CommaSequence.new(woven.map {|w| Sequence.new(w)})
end