haml 3.1.0.alpha.14 → 3.1.0.alpha.17

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of haml might be problematic. Click here for more details.

Files changed (222) hide show
  1. data/EDGE_GEM_VERSION +1 -1
  2. data/VERSION +1 -1
  3. data/lib/haml.rb +3 -2
  4. data/lib/haml/exec.rb +0 -226
  5. data/lib/sass.rb +8 -0
  6. data/lib/sass/plugin.rb +8 -0
  7. data/lib/sass/rails2_shim.rb +9 -0
  8. data/lib/sass/rails3_shim.rb +16 -0
  9. data/vendor/sass/CONTRIBUTING +3 -0
  10. data/vendor/sass/MIT-LICENSE +20 -0
  11. data/vendor/sass/README.md +201 -0
  12. data/vendor/sass/Rakefile +363 -0
  13. data/vendor/sass/TODO +39 -0
  14. data/vendor/sass/VERSION +1 -0
  15. data/vendor/sass/VERSION_NAME +1 -0
  16. data/vendor/sass/bin/css2sass +13 -0
  17. data/vendor/sass/bin/sass +8 -0
  18. data/vendor/sass/bin/sass-convert +7 -0
  19. data/vendor/sass/doc-src/FAQ.md +35 -0
  20. data/vendor/sass/doc-src/INDENTED_SYNTAX.md +210 -0
  21. data/vendor/sass/doc-src/SASS_CHANGELOG.md +1878 -0
  22. data/vendor/sass/doc-src/SASS_REFERENCE.md +1713 -0
  23. data/vendor/sass/doc-src/SCSS_FOR_SASS_USERS.md +155 -0
  24. data/vendor/sass/ext/extconf.rb +10 -0
  25. data/vendor/sass/extra/update_watch.rb +13 -0
  26. data/vendor/sass/init.rb +18 -0
  27. data/vendor/sass/lib/sass.rb +71 -0
  28. data/vendor/sass/lib/sass/cache_store.rb +208 -0
  29. data/vendor/sass/lib/sass/callbacks.rb +66 -0
  30. data/vendor/sass/lib/sass/css.rb +294 -0
  31. data/vendor/sass/lib/sass/engine.rb +792 -0
  32. data/vendor/sass/lib/sass/environment.rb +143 -0
  33. data/vendor/sass/lib/sass/error.rb +201 -0
  34. data/vendor/sass/lib/sass/exec.rb +619 -0
  35. data/vendor/sass/lib/sass/importers.rb +22 -0
  36. data/vendor/sass/lib/sass/importers/base.rb +138 -0
  37. data/vendor/sass/lib/sass/importers/filesystem.rb +121 -0
  38. data/vendor/sass/lib/sass/less.rb +363 -0
  39. data/vendor/sass/lib/sass/plugin.rb +126 -0
  40. data/vendor/sass/lib/sass/plugin/compiler.rb +346 -0
  41. data/vendor/sass/lib/sass/plugin/configuration.rb +123 -0
  42. data/vendor/sass/lib/sass/plugin/generic.rb +15 -0
  43. data/vendor/sass/lib/sass/plugin/merb.rb +48 -0
  44. data/vendor/sass/lib/sass/plugin/rack.rb +47 -0
  45. data/vendor/sass/lib/sass/plugin/rails.rb +41 -0
  46. data/vendor/sass/lib/sass/plugin/staleness_checker.rb +145 -0
  47. data/vendor/sass/lib/sass/railtie.rb +8 -0
  48. data/vendor/sass/lib/sass/repl.rb +58 -0
  49. data/vendor/sass/lib/sass/root.rb +7 -0
  50. data/vendor/sass/lib/sass/script.rb +63 -0
  51. data/vendor/sass/lib/sass/script/bool.rb +18 -0
  52. data/vendor/sass/lib/sass/script/color.rb +491 -0
  53. data/vendor/sass/lib/sass/script/css_lexer.rb +29 -0
  54. data/vendor/sass/lib/sass/script/css_parser.rb +31 -0
  55. data/vendor/sass/lib/sass/script/funcall.rb +76 -0
  56. data/vendor/sass/lib/sass/script/functions.rb +852 -0
  57. data/vendor/sass/lib/sass/script/interpolation.rb +70 -0
  58. data/vendor/sass/lib/sass/script/lexer.rb +337 -0
  59. data/vendor/sass/lib/sass/script/literal.rb +236 -0
  60. data/vendor/sass/lib/sass/script/node.rb +112 -0
  61. data/vendor/sass/lib/sass/script/number.rb +423 -0
  62. data/vendor/sass/lib/sass/script/operation.rb +90 -0
  63. data/vendor/sass/lib/sass/script/parser.rb +392 -0
  64. data/vendor/sass/lib/sass/script/string.rb +67 -0
  65. data/vendor/sass/lib/sass/script/string_interpolation.rb +93 -0
  66. data/vendor/sass/lib/sass/script/unary_operation.rb +57 -0
  67. data/vendor/sass/lib/sass/script/variable.rb +48 -0
  68. data/vendor/sass/lib/sass/scss.rb +17 -0
  69. data/vendor/sass/lib/sass/scss/css_parser.rb +51 -0
  70. data/vendor/sass/lib/sass/scss/parser.rb +838 -0
  71. data/vendor/sass/lib/sass/scss/rx.rb +126 -0
  72. data/vendor/sass/lib/sass/scss/sass_parser.rb +11 -0
  73. data/vendor/sass/lib/sass/scss/script_lexer.rb +15 -0
  74. data/vendor/sass/lib/sass/scss/script_parser.rb +25 -0
  75. data/vendor/sass/lib/sass/scss/static_parser.rb +40 -0
  76. data/vendor/sass/lib/sass/selector.rb +361 -0
  77. data/vendor/sass/lib/sass/selector/abstract_sequence.rb +62 -0
  78. data/vendor/sass/lib/sass/selector/comma_sequence.rb +82 -0
  79. data/vendor/sass/lib/sass/selector/sequence.rb +236 -0
  80. data/vendor/sass/lib/sass/selector/simple.rb +113 -0
  81. data/vendor/sass/lib/sass/selector/simple_sequence.rb +135 -0
  82. data/vendor/sass/lib/sass/shared.rb +78 -0
  83. data/vendor/sass/lib/sass/tree/comment_node.rb +128 -0
  84. data/vendor/sass/lib/sass/tree/debug_node.rb +36 -0
  85. data/vendor/sass/lib/sass/tree/directive_node.rb +75 -0
  86. data/vendor/sass/lib/sass/tree/extend_node.rb +65 -0
  87. data/vendor/sass/lib/sass/tree/for_node.rb +67 -0
  88. data/vendor/sass/lib/sass/tree/if_node.rb +81 -0
  89. data/vendor/sass/lib/sass/tree/import_node.rb +124 -0
  90. data/vendor/sass/lib/sass/tree/mixin_def_node.rb +60 -0
  91. data/vendor/sass/lib/sass/tree/mixin_node.rb +123 -0
  92. data/vendor/sass/lib/sass/tree/node.rb +490 -0
  93. data/vendor/sass/lib/sass/tree/prop_node.rb +220 -0
  94. data/vendor/sass/lib/sass/tree/root_node.rb +125 -0
  95. data/vendor/sass/lib/sass/tree/rule_node.rb +273 -0
  96. data/vendor/sass/lib/sass/tree/variable_node.rb +39 -0
  97. data/vendor/sass/lib/sass/tree/warn_node.rb +42 -0
  98. data/vendor/sass/lib/sass/tree/while_node.rb +48 -0
  99. data/vendor/sass/lib/sass/util.rb +700 -0
  100. data/vendor/sass/lib/sass/util/subset_map.rb +101 -0
  101. data/vendor/sass/lib/sass/version.rb +109 -0
  102. data/vendor/sass/rails/init.rb +1 -0
  103. data/vendor/sass/sass.gemspec +32 -0
  104. data/vendor/sass/test/sass/cache_test.rb +74 -0
  105. data/vendor/sass/test/sass/callbacks_test.rb +61 -0
  106. data/vendor/sass/test/sass/conversion_test.rb +1210 -0
  107. data/vendor/sass/test/sass/css2sass_test.rb +364 -0
  108. data/vendor/sass/test/sass/data/hsl-rgb.txt +319 -0
  109. data/vendor/sass/test/sass/engine_test.rb +2305 -0
  110. data/vendor/sass/test/sass/extend_test.rb +1348 -0
  111. data/vendor/sass/test/sass/functions_test.rb +565 -0
  112. data/vendor/sass/test/sass/importer_test.rb +104 -0
  113. data/vendor/sass/test/sass/less_conversion_test.rb +632 -0
  114. data/vendor/sass/test/sass/mock_importer.rb +49 -0
  115. data/vendor/sass/test/sass/more_results/more1.css +9 -0
  116. data/vendor/sass/test/sass/more_results/more1_with_line_comments.css +26 -0
  117. data/vendor/sass/test/sass/more_results/more_import.css +29 -0
  118. data/vendor/sass/test/sass/more_templates/_more_partial.sass +2 -0
  119. data/vendor/sass/test/sass/more_templates/more1.sass +23 -0
  120. data/vendor/sass/test/sass/more_templates/more_import.sass +11 -0
  121. data/vendor/sass/test/sass/plugin_test.rb +430 -0
  122. data/vendor/sass/test/sass/results/alt.css +4 -0
  123. data/vendor/sass/test/sass/results/basic.css +9 -0
  124. data/vendor/sass/test/sass/results/compact.css +5 -0
  125. data/vendor/sass/test/sass/results/complex.css +86 -0
  126. data/vendor/sass/test/sass/results/compressed.css +1 -0
  127. data/vendor/sass/test/sass/results/expanded.css +19 -0
  128. data/vendor/sass/test/sass/results/import.css +31 -0
  129. data/vendor/sass/test/sass/results/line_numbers.css +49 -0
  130. data/vendor/sass/test/sass/results/mixins.css +95 -0
  131. data/vendor/sass/test/sass/results/multiline.css +24 -0
  132. data/vendor/sass/test/sass/results/nested.css +22 -0
  133. data/vendor/sass/test/sass/results/options.css +1 -0
  134. data/vendor/sass/test/sass/results/parent_ref.css +13 -0
  135. data/vendor/sass/test/sass/results/script.css +16 -0
  136. data/vendor/sass/test/sass/results/scss_import.css +31 -0
  137. data/vendor/sass/test/sass/results/scss_importee.css +2 -0
  138. data/vendor/sass/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  139. data/vendor/sass/test/sass/results/subdir/subdir.css +3 -0
  140. data/vendor/sass/test/sass/results/units.css +11 -0
  141. data/vendor/sass/test/sass/results/warn.css +0 -0
  142. data/vendor/sass/test/sass/results/warn_imported.css +0 -0
  143. data/vendor/sass/test/sass/script_conversion_test.rb +254 -0
  144. data/vendor/sass/test/sass/script_test.rb +470 -0
  145. data/vendor/sass/test/sass/scss/css_test.rb +897 -0
  146. data/vendor/sass/test/sass/scss/rx_test.rb +156 -0
  147. data/vendor/sass/test/sass/scss/scss_test.rb +1088 -0
  148. data/vendor/sass/test/sass/scss/test_helper.rb +37 -0
  149. data/vendor/sass/test/sass/templates/_partial.sass +2 -0
  150. data/vendor/sass/test/sass/templates/alt.sass +16 -0
  151. data/vendor/sass/test/sass/templates/basic.sass +23 -0
  152. data/vendor/sass/test/sass/templates/bork1.sass +2 -0
  153. data/vendor/sass/test/sass/templates/bork2.sass +2 -0
  154. data/vendor/sass/test/sass/templates/bork3.sass +2 -0
  155. data/vendor/sass/test/sass/templates/bork4.sass +2 -0
  156. data/vendor/sass/test/sass/templates/compact.sass +17 -0
  157. data/vendor/sass/test/sass/templates/complex.sass +305 -0
  158. data/vendor/sass/test/sass/templates/compressed.sass +15 -0
  159. data/vendor/sass/test/sass/templates/expanded.sass +17 -0
  160. data/vendor/sass/test/sass/templates/import.sass +12 -0
  161. data/vendor/sass/test/sass/templates/importee.less +2 -0
  162. data/vendor/sass/test/sass/templates/importee.sass +19 -0
  163. data/vendor/sass/test/sass/templates/line_numbers.sass +13 -0
  164. data/vendor/sass/test/sass/templates/mixin_bork.sass +5 -0
  165. data/vendor/sass/test/sass/templates/mixins.sass +76 -0
  166. data/vendor/sass/test/sass/templates/multiline.sass +20 -0
  167. data/vendor/sass/test/sass/templates/nested.sass +25 -0
  168. data/vendor/sass/test/sass/templates/nested_bork1.sass +2 -0
  169. data/vendor/sass/test/sass/templates/nested_bork2.sass +2 -0
  170. data/vendor/sass/test/sass/templates/nested_bork3.sass +2 -0
  171. data/vendor/sass/test/sass/templates/nested_bork4.sass +2 -0
  172. data/vendor/sass/test/sass/templates/nested_mixin_bork.sass +6 -0
  173. data/vendor/sass/test/sass/templates/options.sass +2 -0
  174. data/vendor/sass/test/sass/templates/parent_ref.sass +25 -0
  175. data/vendor/sass/test/sass/templates/script.sass +101 -0
  176. data/vendor/sass/test/sass/templates/scss_import.scss +11 -0
  177. data/vendor/sass/test/sass/templates/scss_importee.scss +1 -0
  178. data/vendor/sass/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  179. data/vendor/sass/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  180. data/vendor/sass/test/sass/templates/subdir/subdir.sass +6 -0
  181. data/vendor/sass/test/sass/templates/units.sass +11 -0
  182. data/vendor/sass/test/sass/templates/warn.sass +3 -0
  183. data/vendor/sass/test/sass/templates/warn_imported.sass +4 -0
  184. data/vendor/sass/test/sass/test_helper.rb +8 -0
  185. data/vendor/sass/test/sass/util/subset_map_test.rb +91 -0
  186. data/vendor/sass/test/sass/util_test.rb +275 -0
  187. data/vendor/sass/test/test_helper.rb +64 -0
  188. data/vendor/sass/vendor/fssm/LICENSE +20 -0
  189. data/vendor/sass/vendor/fssm/README.markdown +55 -0
  190. data/vendor/sass/vendor/fssm/Rakefile +59 -0
  191. data/vendor/sass/vendor/fssm/VERSION.yml +5 -0
  192. data/vendor/sass/vendor/fssm/example.rb +9 -0
  193. data/vendor/sass/vendor/fssm/fssm.gemspec +77 -0
  194. data/vendor/sass/vendor/fssm/lib/fssm.rb +33 -0
  195. data/vendor/sass/vendor/fssm/lib/fssm/backends/fsevents.rb +36 -0
  196. data/vendor/sass/vendor/fssm/lib/fssm/backends/inotify.rb +26 -0
  197. data/vendor/sass/vendor/fssm/lib/fssm/backends/polling.rb +25 -0
  198. data/vendor/sass/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +131 -0
  199. data/vendor/sass/vendor/fssm/lib/fssm/monitor.rb +26 -0
  200. data/vendor/sass/vendor/fssm/lib/fssm/path.rb +91 -0
  201. data/vendor/sass/vendor/fssm/lib/fssm/pathname.rb +502 -0
  202. data/vendor/sass/vendor/fssm/lib/fssm/state/directory.rb +57 -0
  203. data/vendor/sass/vendor/fssm/lib/fssm/state/file.rb +24 -0
  204. data/vendor/sass/vendor/fssm/lib/fssm/support.rb +63 -0
  205. data/vendor/sass/vendor/fssm/lib/fssm/tree.rb +176 -0
  206. data/vendor/sass/vendor/fssm/profile/prof-cache.rb +40 -0
  207. data/vendor/sass/vendor/fssm/profile/prof-fssm-pathname.html +1231 -0
  208. data/vendor/sass/vendor/fssm/profile/prof-pathname.rb +68 -0
  209. data/vendor/sass/vendor/fssm/profile/prof-plain-pathname.html +988 -0
  210. data/vendor/sass/vendor/fssm/profile/prof.html +2379 -0
  211. data/vendor/sass/vendor/fssm/spec/path_spec.rb +75 -0
  212. data/vendor/sass/vendor/fssm/spec/root/duck/quack.txt +0 -0
  213. data/vendor/sass/vendor/fssm/spec/root/file.css +0 -0
  214. data/vendor/sass/vendor/fssm/spec/root/file.rb +0 -0
  215. data/vendor/sass/vendor/fssm/spec/root/file.yml +0 -0
  216. data/vendor/sass/vendor/fssm/spec/root/moo/cow.txt +0 -0
  217. data/vendor/sass/vendor/fssm/spec/spec_helper.rb +14 -0
  218. data/vendor/sass/yard/callbacks.rb +29 -0
  219. data/vendor/sass/yard/default/fulldoc/html/css/common.sass +26 -0
  220. data/vendor/sass/yard/default/layout/html/footer.erb +12 -0
  221. data/vendor/sass/yard/inherited_hash.rb +41 -0
  222. metadata +219 -2
@@ -0,0 +1,62 @@
1
+ module Sass
2
+ module Selector
3
+ # The abstract parent class of the various selector sequence classes.
4
+ #
5
+ # All subclasses should implement a `members` method
6
+ # that returns an array of object that respond to `#line=` and `#filename=`.
7
+ class AbstractSequence
8
+ # The line of the Sass template on which this selector was declared.
9
+ #
10
+ # @return [Fixnum]
11
+ attr_reader :line
12
+
13
+ # The name of the file in which this selector was declared.
14
+ #
15
+ # @return [String, nil]
16
+ attr_reader :filename
17
+
18
+ # Sets the line of the Sass template on which this selector was declared.
19
+ # This also sets the line for all child selectors.
20
+ #
21
+ # @param line [Fixnum]
22
+ # @return [Fixnum]
23
+ def line=(line)
24
+ members.each {|m| m.line = line}
25
+ @line = line
26
+ end
27
+
28
+ # Sets the name of the file in which this selector was declared,
29
+ # or `nil` if it was not declared in a file (e.g. on stdin).
30
+ # This also sets the filename for all child selectors.
31
+ #
32
+ # @param filename [String, nil]
33
+ # @return [String, nil]
34
+ def filename=(filename)
35
+ members.each {|m| m.filename = filename}
36
+ @filename = filename
37
+ end
38
+
39
+ # Returns a hash code for this sequence.
40
+ #
41
+ # Subclasses should define `#_hash` rather than overriding this method,
42
+ # which automatically handles memoizing the result.
43
+ #
44
+ # @return [Fixnum]
45
+ def hash
46
+ @_hash ||= _hash
47
+ end
48
+
49
+ # Checks equality between this and another object.
50
+ #
51
+ # Subclasses should define `#_eql?` rather than overriding this method,
52
+ # which handles checking class equality and hash equality.
53
+ #
54
+ # @param other [Object] The object to test equality against
55
+ # @return [Boolean] Whether or not this is equal to `other`
56
+ def eql?(other)
57
+ other.class == self.class && other.hash == self.hash && _eql?(other)
58
+ end
59
+ alias_method :==, :eql?
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,82 @@
1
+ module Sass
2
+ module Selector
3
+ # A comma-separated sequence of selectors.
4
+ class CommaSequence < AbstractSequence
5
+ # The comma-separated selector sequences
6
+ # represented by this class.
7
+ #
8
+ # @return [Array<Sequence>]
9
+ attr_reader :members
10
+
11
+ # @param seqs [Array<Sequence>] See \{#members}
12
+ def initialize(seqs)
13
+ @members = seqs
14
+ end
15
+
16
+ # Resolves the {Parent} selectors within this selector
17
+ # by replacing them with the given parent selector,
18
+ # handling commas appropriately.
19
+ #
20
+ # @param super_cseq [CommaSequence] The parent selector
21
+ # @return [CommaSequence] This selector, with parent references resolved
22
+ # @raise [Sass::SyntaxError] If a parent selector is invalid
23
+ def resolve_parent_refs(super_cseq)
24
+ if super_cseq.nil?
25
+ if @members.any? do |sel|
26
+ sel.members.any? do |sel_or_op|
27
+ sel_or_op.is_a?(SimpleSequence) && sel_or_op.members.any? {|ssel| ssel.is_a?(Parent)}
28
+ end
29
+ end
30
+ raise Sass::SyntaxError.new("Base-level rules cannot contain the parent-selector-referencing character '&'.")
31
+ end
32
+ return self
33
+ end
34
+
35
+ CommaSequence.new(
36
+ super_cseq.members.map do |super_seq|
37
+ @members.map {|seq| seq.resolve_parent_refs(super_seq)}
38
+ end.flatten)
39
+ end
40
+
41
+ # Non-destrucively extends this selector
42
+ # with the extensions specified in a hash
43
+ # (which should be populated via {Sass::Tree::Node#cssize}).
44
+ #
45
+ # @todo Link this to the reference documentation on `@extend`
46
+ # when such a thing exists.
47
+ #
48
+ # @param extends [Sass::Util::SubsetMap{Selector::Simple => Selector::Sequence}]
49
+ # The extensions to perform on this selector
50
+ # @return [CommaSequence] A copy of this selector,
51
+ # with extensions made according to `extends`
52
+ def do_extend(extends)
53
+ CommaSequence.new(members.map {|seq| seq.do_extend(extends)}.flatten)
54
+ end
55
+
56
+ # Returns a string representation of the sequence.
57
+ # This is basically the selector string.
58
+ #
59
+ # @return [String]
60
+ def inspect
61
+ members.map {|m| m.inspect}.join(", ")
62
+ end
63
+
64
+ # @see Simple#to_a
65
+ def to_a
66
+ arr = Sass::Util.intersperse(@members.map {|m| m.to_a}, ", ").flatten
67
+ arr.delete("\n")
68
+ arr
69
+ end
70
+
71
+ private
72
+
73
+ def _hash
74
+ members.hash
75
+ end
76
+
77
+ def _eql?(other)
78
+ other.class == self.class && other.members.eql?(self.members)
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,236 @@
1
+ module Sass
2
+ module Selector
3
+ # An operator-separated sequence of
4
+ # {SimpleSequence simple selector sequences}.
5
+ class Sequence < AbstractSequence
6
+ # Sets the line of the Sass template on which this selector was declared.
7
+ # This also sets the line for all child selectors.
8
+ #
9
+ # @param line [Fixnum]
10
+ # @return [Fixnum]
11
+ def line=(line)
12
+ members.each {|m| m.line = line if m.is_a?(SimpleSequence)}
13
+ line
14
+ end
15
+
16
+ # Sets the name of the file in which this selector was declared,
17
+ # or `nil` if it was not declared in a file (e.g. on stdin).
18
+ # This also sets the filename for all child selectors.
19
+ #
20
+ # @param filename [String, nil]
21
+ # @return [String, nil]
22
+ def filename=(filename)
23
+ members.each {|m| m.filename = filename if m.is_a?(SimpleSequence)}
24
+ filename
25
+ end
26
+
27
+ # The array of {SimpleSequence simple selector sequences}, operators, and newlines.
28
+ # The operators are strings such as `"+"` and `">"`
29
+ # representing the corresponding CSS operators.
30
+ # Newlines are also newline strings;
31
+ # these aren't semantically relevant,
32
+ # but they do affect formatting.
33
+ #
34
+ # @return [Array<SimpleSequence, String>]
35
+ attr_reader :members
36
+
37
+ # @param seqs_and_ops [Array<SimpleSequence, String>] See \{#members}
38
+ def initialize(seqs_and_ops)
39
+ @members = seqs_and_ops
40
+ end
41
+
42
+ # Resolves the {Parent} selectors within this selector
43
+ # by replacing them with the given parent selector,
44
+ # handling commas appropriately.
45
+ #
46
+ # @param super_seq [Sequence] The parent selector sequence
47
+ # @return [Sequence] This selector, with parent references resolved
48
+ # @raise [Sass::SyntaxError] If a parent selector is invalid
49
+ def resolve_parent_refs(super_seq)
50
+ members = @members
51
+ members.slice!(0) if nl = (members.first == "\n")
52
+ unless members.any? do |seq_or_op|
53
+ seq_or_op.is_a?(SimpleSequence) && seq_or_op.members.first.is_a?(Parent)
54
+ end
55
+ members = []
56
+ members << "\n" if nl
57
+ members << SimpleSequence.new([Parent.new])
58
+ members += @members
59
+ end
60
+
61
+ Sequence.new(
62
+ members.map do |seq_or_op|
63
+ next seq_or_op unless seq_or_op.is_a?(SimpleSequence)
64
+ seq_or_op.resolve_parent_refs(super_seq)
65
+ end.flatten)
66
+ end
67
+
68
+ # Non-destructively extends this selector
69
+ # with the extensions specified in a hash
70
+ # (which should be populated via {Sass::Tree::Node#cssize}).
71
+ #
72
+ # @overload def do_extend(extends)
73
+ # @param extends [Sass::Util::SubsetMap{Selector::Simple => Selector::Sequence}]
74
+ # The extensions to perform on this selector
75
+ # @return [Array<Sequence>] A list of selectors generated
76
+ # by extending this selector with `extends`.
77
+ # These correspond to a {CommaSequence}'s {CommaSequence#members members array}.
78
+ # @see CommaSequence#do_extend
79
+ def do_extend(extends, seen = Set.new)
80
+ paths = Sass::Util.paths(members.map do |sseq_or_op|
81
+ next [[sseq_or_op]] unless sseq_or_op.is_a?(SimpleSequence)
82
+ extended = sseq_or_op.do_extend(extends, seen)
83
+ choices = extended.map {|seq| seq.members}
84
+ choices.unshift([sseq_or_op]) unless extended.any? {|seq| seq.superselector?(sseq_or_op)}
85
+ choices
86
+ end)
87
+ Sass::Util.flatten(paths.map {|path| weave(path)}, 1).map {|p| Sequence.new(p)}
88
+ end
89
+
90
+ # Returns whether or not this selector matches all elements
91
+ # that the given selector matches (as well as possibly more).
92
+ #
93
+ # @example
94
+ # (.foo).superselector?(.foo.bar) #=> true
95
+ # (.foo).superselector?(.bar) #=> false
96
+ # (.bar .foo).superselector?(.foo) #=> false
97
+ # @param sseq [SimpleSequence]
98
+ # @return [Boolean]
99
+ def superselector?(sseq)
100
+ return false unless members.size == 1
101
+ members.last.superselector?(sseq)
102
+ end
103
+
104
+ # @see Simple#to_a
105
+ def to_a
106
+ ary = @members.map {|seq_or_op| seq_or_op.is_a?(SimpleSequence) ? seq_or_op.to_a : seq_or_op}
107
+ ary = Sass::Util.intersperse(ary, " ")
108
+ ary = Sass::Util.substitute(ary, [" ", "\n", " "], ["\n"])
109
+ ary.flatten.compact
110
+ end
111
+
112
+ # Returns a string representation of the sequence.
113
+ # This is basically the selector string.
114
+ #
115
+ # @return [String]
116
+ def inspect
117
+ members.map {|m| m.inspect}.join(" ")
118
+ end
119
+
120
+ private
121
+
122
+ # Conceptually, this expands "parenthesized selectors".
123
+ # That is, if we have `.A .B {@extend .C}` and `.D .C {...}`,
124
+ # this conceptually expands into `.D .C, .D (.A .B)`,
125
+ # and this function translates `.D (.A .B)` into `.D .A .B, .A.D .B, .D .A .B`.
126
+ #
127
+ # @param path [Array<Array<SimpleSequence or String>>] A list of parenthesized selector groups.
128
+ # @return [Array<Array<SimpleSequence or String>>] A list of fully-expanded selectors.
129
+ def weave(path)
130
+ befores = [[]]
131
+ afters = path.dup
132
+
133
+ until afters.empty?
134
+ current = afters.shift.dup
135
+ last_current = [current.pop]
136
+ while !current.empty? && last_current.first.is_a?(String) || current.last.is_a?(String)
137
+ last_current.unshift(current.pop)
138
+ end
139
+ befores = Sass::Util.flatten(befores.map do |before|
140
+ subweave(before, current).map {|seqs| seqs + last_current}
141
+ end, 1)
142
+ return befores if afters.empty?
143
+ end
144
+ end
145
+
146
+ # This interweaves two lists of selectors,
147
+ # returning all possible orderings of them (including using unification)
148
+ # that maintain the relative ordering of the input arrays.
149
+ #
150
+ # For example, given `.foo .bar` and `.baz .bang`,
151
+ # this would return `.foo .bar .baz .bang`, `.foo .bar.baz .bang`,
152
+ # `.foo .baz .bar .bang`, `.foo .baz .bar.bang`, `.foo .baz .bang .bar`,
153
+ # and so on until `.baz .bang .foo .bar`.
154
+ #
155
+ # @overload def subweave(seq1, seq2)
156
+ # @param seq1 [Array<SimpleSequence or String>]
157
+ # @param seq2 [Array<SimpleSequence or String>]
158
+ # @return [Array<Array<SimpleSequence or String>>]
159
+ def subweave(seq1, seq2, cache = {})
160
+ return [seq2] if seq1.empty?
161
+ return [seq1] if seq2.empty?
162
+
163
+ seq1 = group_selectors(seq1)
164
+ seq2 = group_selectors(seq2)
165
+ lcs = Sass::Util.lcs(seq2, seq1) do |s1, s2|
166
+ next s1 if s1 == s2
167
+ next unless s1.first.is_a?(SimpleSequence) && s2.first.is_a?(SimpleSequence)
168
+ next s2 if subweave_superselector?(s1, s2)
169
+ next s1 if subweave_superselector?(s2, s1)
170
+ end
171
+
172
+ diff = []
173
+ until lcs.empty?
174
+ diff << chunks(seq1, seq2) {|s| subweave_superselector?(s.first, lcs.first)} << [lcs.shift]
175
+ seq1.shift
176
+ seq2.shift
177
+ end
178
+ diff << chunks(seq1, seq2) {|s| s.empty?}
179
+ diff.reject! {|c| c.empty?}
180
+
181
+ Sass::Util.paths(diff).map {|p| p.flatten}
182
+ end
183
+
184
+ def chunks(seq1, seq2)
185
+ chunk1 = []
186
+ chunk1 << seq1.shift until yield seq1
187
+ chunk2 = []
188
+ chunk2 << seq2.shift until yield seq2
189
+ return [] if chunk1.empty? && chunk2.empty?
190
+ return [chunk2] if chunk1.empty?
191
+ return [chunk1] if chunk2.empty?
192
+ [chunk1 + chunk2, chunk2 + chunk1]
193
+ end
194
+
195
+ def group_selectors(seq)
196
+ newseq = []
197
+ tail = seq.dup
198
+ until tail.empty?
199
+ head = []
200
+ begin
201
+ head << tail.shift
202
+ end while !tail.empty? && head.last.is_a?(String) || tail.first.is_a?(String)
203
+ newseq << head
204
+ end
205
+ return newseq
206
+ end
207
+
208
+ def subweave_superselector?(sseq1, sseq2)
209
+ if sseq1.size > 1
210
+ # More complex selectors are never superselectors of less complex ones
211
+ return unless sseq2.size > 1
212
+ # .foo ~ .bar is a superselector of .foo + .bar
213
+ return unless sseq1[1] == "~" ? sseq2[1] != ">" : sseq2[1] == sseq1[1]
214
+ return unless sseq1.first.superselector?(sseq2.first)
215
+ return true if sseq1.size == 2
216
+ return false if sseq2.size == 2
217
+ return subweave_superselector?(sseq1[2..-1], sseq2[2..-1])
218
+ elsif sseq2.size > 1
219
+ return true if sseq2[1] == ">" && sseq1.first.superselector?(sseq2.first)
220
+ return false if sseq2.size == 2
221
+ return subweave_superselector?(sseq1, sseq2[2..-1])
222
+ else
223
+ sseq1.first.superselector?(sseq2.first)
224
+ end
225
+ end
226
+
227
+ def _hash
228
+ members.reject {|m| m == "\n"}.hash
229
+ end
230
+
231
+ def _eql?(other)
232
+ other.members.reject {|m| m == "\n"}.eql?(self.members.reject {|m| m == "\n"})
233
+ end
234
+ end
235
+ end
236
+ end
@@ -0,0 +1,113 @@
1
+ module Sass
2
+ module Selector
3
+ # The abstract superclass for simple selectors
4
+ # (that is, those that don't compose multiple selectors).
5
+ class Simple
6
+ # The line of the Sass template on which this selector was declared.
7
+ #
8
+ # @return [Fixnum]
9
+ attr_accessor :line
10
+
11
+ # The name of the file in which this selector was declared,
12
+ # or `nil` if it was not declared in a file (e.g. on stdin).
13
+ #
14
+ # @return [String, nil]
15
+ attr_accessor :filename
16
+
17
+ # Returns a representation of the node
18
+ # as an array of strings and potentially {Sass::Script::Node}s
19
+ # (if there's interpolation in the selector).
20
+ # When the interpolation is resolved and the strings are joined together,
21
+ # this will be the string representation of this node.
22
+ #
23
+ # @return [Array<String, Sass::Script::Node>]
24
+ def to_a
25
+ Sass::Util.abstract(self)
26
+ end
27
+
28
+ # Returns a string representation of the node.
29
+ # This is basically the selector string.
30
+ #
31
+ # @return [String]
32
+ def inspect
33
+ to_a.map {|e| e.is_a?(Sass::Script::Node) ? "\#{#{e.to_sass}}" : e}.join
34
+ end
35
+
36
+ # Returns a hash code for this selector object.
37
+ #
38
+ # By default, this is based on the value of \{#to\_a},
39
+ # so if that contains information irrelevant to the identity of the selector,
40
+ # this should be overridden.
41
+ #
42
+ # @return [Fixnum]
43
+ def hash
44
+ @_hash ||= to_a.hash
45
+ end
46
+
47
+ # Checks equality between this and another object.
48
+ #
49
+ # By default, this is based on the value of \{#to\_a},
50
+ # so if that contains information irrelevant to the identity of the selector,
51
+ # this should be overridden.
52
+ #
53
+ # @param other [Object] The object to test equality against
54
+ # @return [Boolean] Whether or not this is equal to `other`
55
+ def eql?(other)
56
+ other.class == self.class && other.hash == self.hash && other.to_a.eql?(to_a)
57
+ end
58
+ alias_method :==, :eql?
59
+
60
+ # Unifies this selector with a {SimpleSequence}'s {SimpleSequence#members members array},
61
+ # returning another `SimpleSequence` members array
62
+ # that matches both this selector and the input selector.
63
+ #
64
+ # By default, this just appends this selector to the end of the array
65
+ # (or returns the original array if this selector already exists in it).
66
+ #
67
+ # @param sels [Array<Simple>] A {SimpleSequence}'s {SimpleSequence#members members array}
68
+ # @return [Array<Simple>, nil] A {SimpleSequence} {SimpleSequence#members members array}
69
+ # matching both `sels` and this selector,
70
+ # or `nil` if this is impossible (e.g. unifying `#foo` and `#bar`)
71
+ # @raise [Sass::SyntaxError] If this selector cannot be unified.
72
+ # This will only ever occur when a dynamic selector,
73
+ # such as {Parent} or {Interpolation}, is used in unification.
74
+ # Since these selectors should be resolved
75
+ # by the time extension and unification happen,
76
+ # this exception will only ever be raised as a result of programmer error
77
+ def unify(sels)
78
+ return sels if sels.any? {|sel2| eql?(sel2)}
79
+ sels_with_ix = Sass::Util.enum_with_index(sels)
80
+ _, i =
81
+ if self.is_a?(Pseudo) || self.is_a?(SelectorPseudoClass)
82
+ sels_with_ix.find {|sel, _| sel.is_a?(Pseudo) && sels.last.type == :element}
83
+ else
84
+ sels_with_ix.find {|sel, _| sel.is_a?(Pseudo) || sel.is_a?(SelectorPseudoClass)}
85
+ end
86
+ return sels + [self] unless i
87
+ return sels[0...i] + [self] + sels[i..-1]
88
+ end
89
+
90
+ protected
91
+
92
+ # Unifies two namespaces,
93
+ # returning a namespace that works for both of them if possible.
94
+ #
95
+ # @param ns1 [String, nil] The first namespace.
96
+ # `nil` means none specified, e.g. `foo`.
97
+ # The empty string means no namespace specified, e.g. `|foo`.
98
+ # `"*"` means any namespace is allowed, e.g. `*|foo`.
99
+ # @param ns2 [String, nil] The second namespace. See `ns1`.
100
+ # @return [Array(String or nil, Boolean)]
101
+ # The first value is the unified namespace, or `nil` for no namespace.
102
+ # The second value is whether or not a namespace that works for both inputs
103
+ # could be found at all.
104
+ # If the second value is `false`, the first should be ignored.
105
+ def unify_namespaces(ns1, ns2)
106
+ return nil, false unless ns1 == ns2 || ns1.nil? || ns1 == ['*'] || ns2.nil? || ns2 == ['*']
107
+ return ns2, true if ns1 == ['*']
108
+ return ns1, true if ns2 == ['*']
109
+ return ns1 || ns2, true
110
+ end
111
+ end
112
+ end
113
+ end