/scalate-jruby/src/main/resources/haml-3.0.25/lib/sass/selector/simple_sequence.rb

http://github.com/scalate/scalate · Ruby · 136 lines · 58 code · 15 blank · 63 comment · 7 complexity · abb11c85a88261dc7e69331c1f4446f3 MD5 · raw file

  1. module Sass
  2. module Selector
  3. # A unseparated sequence of selectors
  4. # that all apply to a single element.
  5. # For example, `.foo#bar[attr=baz]` is a simple sequence
  6. # of the selectors `.foo`, `#bar`, and `[attr=baz]`.
  7. class SimpleSequence < AbstractSequence
  8. # The array of individual selectors.
  9. #
  10. # @return [Array<Simple>]
  11. attr_reader :members
  12. # Returns the element or universal selector in this sequence,
  13. # if it exists.
  14. #
  15. # @return [Element, Universal, nil]
  16. def base
  17. @base ||= (members.first if members.first.is_a?(Element) || members.first.is_a?(Universal))
  18. end
  19. # Returns the non-base selectors in this sequence.
  20. #
  21. # @return [Set<Simple>]
  22. def rest
  23. @rest ||= Set.new(base ? members[1..-1] : members)
  24. end
  25. # @param selectors [Array<Simple>] See \{#members}
  26. def initialize(selectors)
  27. @members = selectors
  28. end
  29. # Resolves the {Parent} selectors within this selector
  30. # by replacing them with the given parent selector,
  31. # handling commas appropriately.
  32. #
  33. # @param super_seq [Sequence] The parent selector sequence
  34. # @return [Array<SimpleSequence>] This selector, with parent references resolved.
  35. # This is an array because the parent selector is itself a {Sequence}
  36. # @raise [Sass::SyntaxError] If a parent selector is invalid
  37. def resolve_parent_refs(super_seq)
  38. # Parent selector only appears as the first selector in the sequence
  39. return [self] unless @members.first.is_a?(Parent)
  40. return super_seq.members if @members.size == 1
  41. unless super_seq.members.last.is_a?(SimpleSequence)
  42. raise Sass::SyntaxError.new("Invalid parent selector: " + super_seq.to_a.join)
  43. end
  44. super_seq.members[0...-1] +
  45. [SimpleSequence.new(super_seq.members.last.members + @members[1..-1])]
  46. end
  47. # Non-destrucively extends this selector
  48. # with the extensions specified in a hash
  49. # (which should be populated via {Sass::Tree::Node#cssize}).
  50. #
  51. # @overload def do_extend(extends)
  52. # @param extends [{Selector::Simple => Selector::Sequence}]
  53. # The extensions to perform on this selector
  54. # @return [Array<Sequence>] A list of selectors generated
  55. # by extending this selector with `extends`.
  56. # @see CommaSequence#do_extend
  57. def do_extend(extends, seen = Set.new)
  58. extends.get(members.to_set).map do |seq, sels|
  59. # If A {@extend B} and C {...},
  60. # seq is A, sels is B, and self is C
  61. self_without_sel = self.members - sels
  62. next unless unified = seq.members.last.unify(self_without_sel)
  63. [sels, seq.members[0...-1] + [unified]]
  64. end.compact.map do |sels, seq|
  65. seq = Sequence.new(seq)
  66. seen.include?(sels) ? [] : seq.do_extend(extends, seen + [sels])
  67. end.flatten.uniq
  68. end
  69. # Unifies this selector with another {SimpleSequence}'s {SimpleSequence#members members array},
  70. # returning another `SimpleSequence`
  71. # that matches both this selector and the input selector.
  72. #
  73. # @param sels [Array<Simple>] A {SimpleSequence}'s {SimpleSequence#members members array}
  74. # @return [SimpleSequence, nil] A {SimpleSequence} matching both `sels` and this selector,
  75. # or `nil` if this is impossible (e.g. unifying `#foo` and `#bar`)
  76. # @raise [Sass::SyntaxError] If this selector cannot be unified.
  77. # This will only ever occur when a dynamic selector,
  78. # such as {Parent} or {Interpolation}, is used in unification.
  79. # Since these selectors should be resolved
  80. # by the time extension and unification happen,
  81. # this exception will only ever be raised as a result of programmer error
  82. def unify(sels)
  83. return unless sseq = members.inject(sels) do |sseq, sel|
  84. return unless sseq
  85. sel.unify(sseq)
  86. end
  87. SimpleSequence.new(sseq)
  88. end
  89. # Returns whether or not this selector matches all elements
  90. # that the given selector matches (as well as possibly more).
  91. #
  92. # @example
  93. # (.foo).superselector?(.foo.bar) #=> true
  94. # (.foo).superselector?(.bar) #=> false
  95. #
  96. # @param sseq [SimpleSequence]
  97. # @return [Boolean]
  98. def superselector?(sseq)
  99. (base.nil? || base.eql?(sseq.base)) && rest.subset?(sseq.rest)
  100. end
  101. # @see Simple#to_a
  102. def to_a
  103. @members.map {|sel| sel.to_a}.flatten
  104. end
  105. # Returns a string representation of the sequence.
  106. # This is basically the selector string.
  107. #
  108. # @return [String]
  109. def inspect
  110. members.map {|m| m.inspect}.join
  111. end
  112. private
  113. def _hash
  114. [base, Haml::Util.set_hash(rest)].hash
  115. end
  116. def _eql?(other)
  117. other.base.eql?(self.base) && Haml::Util.set_eql?(other.rest, self.rest)
  118. end
  119. end
  120. end
  121. end