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

http://github.com/scalate/scalate · Ruby · 361 lines · 147 code · 40 blank · 174 comment · 20 complexity · 400645f96a2238dacf91757157c66c4f MD5 · raw file

  1. require 'sass/selector/simple'
  2. require 'sass/selector/abstract_sequence'
  3. require 'sass/selector/comma_sequence'
  4. require 'sass/selector/sequence'
  5. require 'sass/selector/simple_sequence'
  6. module Sass
  7. # A namespace for nodes in the parse tree for selectors.
  8. #
  9. # {CommaSequence} is the toplevel seelctor,
  10. # representing a comma-separated sequence of {Sequence}s,
  11. # such as `foo bar, baz bang`.
  12. # {Sequence} is the next level,
  13. # representing {SimpleSequence}s separated by combinators (e.g. descendant or child),
  14. # such as `foo bar` or `foo > bar baz`.
  15. # {SimpleSequence} is a sequence of selectors that all apply to a single element,
  16. # such as `foo.bar[attr=val]`.
  17. # Finally, {Simple} is the superclass of the simplest selectors,
  18. # such as `.foo` or `#bar`.
  19. module Selector
  20. # A parent-referencing selector (`&` in Sass).
  21. # The function of this is to be replaced by the parent selector
  22. # in the nested hierarchy.
  23. class Parent < Simple
  24. # @see Selector#to_a
  25. def to_a
  26. ["&"]
  27. end
  28. # Always raises an exception.
  29. #
  30. # @raise [Sass::SyntaxError] Parent selectors should be resolved before unification
  31. # @see Selector#unify
  32. def unify(sels)
  33. raise Sass::SyntaxError.new("[BUG] Cannot unify parent selectors.")
  34. end
  35. end
  36. # A class selector (e.g. `.foo`).
  37. class Class < Simple
  38. # The class name.
  39. #
  40. # @return [Array<String, Sass::Script::Node>]
  41. attr_reader :name
  42. # @param name [Array<String, Sass::Script::Node>] The class name
  43. def initialize(name)
  44. @name = name
  45. end
  46. # @see Selector#to_a
  47. def to_a
  48. [".", *@name]
  49. end
  50. end
  51. # An id selector (e.g. `#foo`).
  52. class Id < Simple
  53. # The id name.
  54. #
  55. # @return [Array<String, Sass::Script::Node>]
  56. attr_reader :name
  57. # @param name [Array<String, Sass::Script::Node>] The id name
  58. def initialize(name)
  59. @name = name
  60. end
  61. # @see Selector#to_a
  62. def to_a
  63. ["#", *@name]
  64. end
  65. # Returns `nil` if `sels` contains an {Id} selector
  66. # with a different name than this one.
  67. #
  68. # @see Selector#unify
  69. def unify(sels)
  70. return if sels.any? {|sel2| sel2.is_a?(Id) && self.name != sel2.name}
  71. super
  72. end
  73. end
  74. # A universal selector (`*` in CSS).
  75. class Universal < Simple
  76. # The selector namespace.
  77. # `nil` means the default namespace,
  78. # `[""]` means no namespace,
  79. # `["*"]` means any namespace.
  80. #
  81. # @return [Array<String, Sass::Script::Node>, nil]
  82. attr_reader :namespace
  83. # @param namespace [Array<String, Sass::Script::Node>, nil] See \{#namespace}
  84. def initialize(namespace)
  85. @namespace = namespace
  86. end
  87. # @see Selector#to_a
  88. def to_a
  89. @namespace ? @namespace + ["|*"] : ["*"]
  90. end
  91. # Unification of a universal selector is somewhat complicated,
  92. # especially when a namespace is specified.
  93. # If there is no namespace specified
  94. # or any namespace is specified (namespace `"*"`),
  95. # then `sel` is returned without change
  96. # (unless it's empty, in which case `"*"` is required).
  97. #
  98. # If a namespace is specified
  99. # but `sel` does not specify a namespace,
  100. # then the given namespace is applied to `sel`,
  101. # either by adding this {Universal} selector
  102. # or applying this namespace to an existing {Element} selector.
  103. #
  104. # If both this selector *and* `sel` specify namespaces,
  105. # those namespaces are unified via {Simple#unify_namespaces}
  106. # and the unified namespace is used, if possible.
  107. #
  108. # @todo There are lots of cases that this documentation specifies;
  109. # make sure we thoroughly test **all of them**.
  110. # @todo Keep track of whether a default namespace has been declared
  111. # and handle namespace-unspecified selectors accordingly.
  112. # @todo If any branch of a CommaSequence ends up being just `"*"`,
  113. # then all other branches should be eliminated
  114. #
  115. # @see Selector#unify
  116. def unify(sels)
  117. name =
  118. case sels.first
  119. when Universal; :universal
  120. when Element; sels.first.name
  121. else
  122. return [self] + sels unless namespace.nil? || namespace == ['*']
  123. return sels unless sels.empty?
  124. return [self]
  125. end
  126. ns, accept = unify_namespaces(namespace, sels.first.namespace)
  127. return unless accept
  128. [name == :universal ? Universal.new(ns) : Element.new(name, ns)] + sels[1..-1]
  129. end
  130. end
  131. # An element selector (e.g. `h1`).
  132. class Element < Simple
  133. # The element name.
  134. #
  135. # @return [Array<String, Sass::Script::Node>]
  136. attr_reader :name
  137. # The selector namespace.
  138. # `nil` means the default namespace,
  139. # `[""]` means no namespace,
  140. # `["*"]` means any namespace.
  141. #
  142. # @return [Array<String, Sass::Script::Node>, nil]
  143. attr_reader :namespace
  144. # @param name [Array<String, Sass::Script::Node>] The element name
  145. # @param namespace [Array<String, Sass::Script::Node>, nil] See \{#namespace}
  146. def initialize(name, namespace)
  147. @name = name
  148. @namespace = namespace
  149. end
  150. # @see Selector#to_a
  151. def to_a
  152. @namespace ? @namespace + ["|"] + @name : @name
  153. end
  154. # Unification of an element selector is somewhat complicated,
  155. # especially when a namespace is specified.
  156. # First, if `sel` contains another {Element} with a different \{#name},
  157. # then the selectors can't be unified and `nil` is returned.
  158. #
  159. # Otherwise, if `sel` doesn't specify a namespace,
  160. # or it specifies any namespace (via `"*"`),
  161. # then it's returned with this element selector
  162. # (e.g. `.foo` becomes `a.foo` or `svg|a.foo`).
  163. # Similarly, if this selector doesn't specify a namespace,
  164. # the namespace from `sel` is used.
  165. #
  166. # If both this selector *and* `sel` specify namespaces,
  167. # those namespaces are unified via {Simple#unify_namespaces}
  168. # and the unified namespace is used, if possible.
  169. #
  170. # @todo There are lots of cases that this documentation specifies;
  171. # make sure we thoroughly test **all of them**.
  172. # @todo Keep track of whether a default namespace has been declared
  173. # and handle namespace-unspecified selectors accordingly.
  174. #
  175. # @see Selector#unify
  176. def unify(sels)
  177. case sels.first
  178. when Universal;
  179. when Element; return unless name == sels.first.name
  180. else return [self] + sels
  181. end
  182. ns, accept = unify_namespaces(namespace, sels.first.namespace)
  183. return unless accept
  184. [Element.new(name, ns)] + sels[1..-1]
  185. end
  186. end
  187. # Selector interpolation (`#{}` in Sass).
  188. class Interpolation < Simple
  189. # The script to run.
  190. #
  191. # @return [Sass::Script::Node]
  192. attr_reader :script
  193. # @param script [Sass::Script::Node] The script to run
  194. def initialize(script)
  195. @script = script
  196. end
  197. # @see Selector#to_a
  198. def to_a
  199. [@script]
  200. end
  201. # Always raises an exception.
  202. #
  203. # @raise [Sass::SyntaxError] Interpolation selectors should be resolved before unification
  204. # @see Selector#unify
  205. def unify(sels)
  206. raise Sass::SyntaxError.new("[BUG] Cannot unify interpolation selectors.")
  207. end
  208. end
  209. # An attribute selector (e.g. `[href^="http://"]`).
  210. class Attribute < Simple
  211. # The attribute name.
  212. #
  213. # @return [Array<String, Sass::Script::Node>]
  214. attr_reader :name
  215. # The attribute namespace.
  216. # `nil` means the default namespace,
  217. # `[""]` means no namespace,
  218. # `["*"]` means any namespace.
  219. #
  220. # @return [Array<String, Sass::Script::Node>, nil]
  221. attr_reader :namespace
  222. # The matching operator, e.g. `"="` or `"^="`.
  223. #
  224. # @return [String]
  225. attr_reader :operator
  226. # The right-hand side of the operator.
  227. #
  228. # @return [Array<String, Sass::Script::Node>]
  229. attr_reader :value
  230. # @param name [Array<String, Sass::Script::Node>] The attribute name
  231. # @param namespace [Array<String, Sass::Script::Node>, nil] See \{#namespace}
  232. # @param operator [String] The matching operator, e.g. `"="` or `"^="`
  233. # @param value [Array<String, Sass::Script::Node>] See \{#value}
  234. def initialize(name, namespace, operator, value)
  235. @name = name
  236. @namespace = namespace
  237. @operator = operator
  238. @value = value
  239. end
  240. # @see Selector#to_a
  241. def to_a
  242. res = ["["]
  243. res.concat(@namespace) << "|" if @namespace
  244. res.concat @name
  245. (res << @operator).concat @value if @value
  246. res << "]"
  247. end
  248. end
  249. # A pseudoclass (e.g. `:visited`) or pseudoelement (e.g. `::first-line`) selector.
  250. # It can have arguments (e.g. `:nth-child(2n+1)`).
  251. class Pseudo < Simple
  252. # The type of the selector.
  253. # `:class` if this is a pseudoclass selector,
  254. # `:element` if it's a pseudoelement.
  255. #
  256. # @return [Symbol]
  257. attr_reader :type
  258. # The name of the selector.
  259. #
  260. # @return [Array<String, Sass::Script::Node>]
  261. attr_reader :name
  262. # The argument to the selector,
  263. # or `nil` if no argument was given.
  264. #
  265. # This may include SassScript nodes that will be run during resolution.
  266. # Note that this should not include SassScript nodes
  267. # after resolution has taken place.
  268. #
  269. # @return [Array<String, Sass::Script::Node>, nil]
  270. attr_reader :arg
  271. # @param type [Symbol] See \{#type}
  272. # @param name [Array<String, Sass::Script::Node>] The name of the selector
  273. # @param arg [nil, Array<String, Sass::Script::Node>] The argument to the selector,
  274. # or nil if no argument was given
  275. def initialize(type, name, arg)
  276. @type = type
  277. @name = name
  278. @arg = arg
  279. end
  280. # @see Selector#to_a
  281. def to_a
  282. res = [@type == :class ? ":" : "::"] + @name
  283. (res << "(").concat(Haml::Util.strip_string_array(@arg)) << ")" if @arg
  284. res
  285. end
  286. # Returns `nil` if this is a pseudoclass selector
  287. # and `sels` contains a pseudoclass selector different than this one.
  288. #
  289. # @see Selector#unify
  290. def unify(sels)
  291. return if type == :element && sels.any? do |sel|
  292. sel.is_a?(Pseudo) && sel.type == :element &&
  293. (sel.name != self.name || sel.arg != self.arg)
  294. end
  295. super
  296. end
  297. end
  298. # A pseudoclass selector whose argument is itself a selector
  299. # (e.g. `:not(.foo)` or `:-moz-all(.foo, .bar)`).
  300. class SelectorPseudoClass < Simple
  301. # The name of the pseudoclass.
  302. #
  303. # @return [String]
  304. attr_reader :name
  305. # The selector argument.
  306. #
  307. # @return [Selector::Sequence]
  308. attr_reader :selector
  309. # @param [String] The name of the pseudoclass
  310. # @param [Selector::Sequence] The selector argument
  311. def initialize(name, selector)
  312. @name = name
  313. @selector = selector
  314. end
  315. # @see Selector#to_a
  316. def to_a
  317. [":", @name, "("] + @selector.to_a + [")"]
  318. end
  319. end
  320. end
  321. end