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,135 @@
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
+
13
+ # Returns the element or universal selector in this sequence,
14
+ # if it exists.
15
+ #
16
+ # @return [Element, Universal, nil]
17
+ def base
18
+ @base ||= (members.first if members.first.is_a?(Element) || members.first.is_a?(Universal))
19
+ end
20
+
21
+ # Returns the non-base selectors in this sequence.
22
+ #
23
+ # @return [Set<Simple>]
24
+ def rest
25
+ @rest ||= Set.new(base ? members[1..-1] : members)
26
+ end
27
+
28
+ # @param selectors [Array<Simple>] See \{#members}
29
+ def initialize(selectors)
30
+ @members = selectors
31
+ end
32
+
33
+ # Resolves the {Parent} selectors within this selector
34
+ # by replacing them with the given parent selector,
35
+ # handling commas appropriately.
36
+ #
37
+ # @param super_seq [Sequence] The parent selector sequence
38
+ # @return [Array<SimpleSequence>] This selector, with parent references resolved.
39
+ # This is an array because the parent selector is itself a {Sequence}
40
+ # @raise [Sass::SyntaxError] If a parent selector is invalid
41
+ def resolve_parent_refs(super_seq)
42
+ # Parent selector only appears as the first selector in the sequence
43
+ return [self] unless @members.first.is_a?(Parent)
44
+
45
+ return super_seq.members if @members.size == 1
46
+ unless super_seq.members.last.is_a?(SimpleSequence)
47
+ raise Sass::SyntaxError.new("Invalid parent selector: " + super_seq.to_a.join)
48
+ end
49
+
50
+ super_seq.members[0...-1] +
51
+ [SimpleSequence.new(super_seq.members.last.members + @members[1..-1])]
52
+ end
53
+
54
+ # Non-destrucively extends this selector
55
+ # with the extensions specified in a hash
56
+ # (which should be populated via {Sass::Tree::Node#cssize}).
57
+ #
58
+ # @overload def do_extend(extends)
59
+ # @param extends [{Selector::Simple => Selector::Sequence}]
60
+ # The extensions to perform on this selector
61
+ # @return [Array<Sequence>] A list of selectors generated
62
+ # by extending this selector with `extends`.
63
+ # @see CommaSequence#do_extend
64
+ def do_extend(extends, seen = Set.new)
65
+ extends.get(members.to_set).map do |seq, sels|
66
+ # If A {@extend B} and C {...},
67
+ # seq is A, sels is B, and self is C
68
+
69
+ self_without_sel = self.members - sels
70
+ next unless unified = seq.members.last.unify(self_without_sel)
71
+ [sels, seq.members[0...-1] + [unified]]
72
+ end.compact.map do |sels, seq|
73
+ seq = Sequence.new(seq)
74
+ seen.include?(sels) ? [] : seq.do_extend(extends, seen + [sels])
75
+ end.flatten.uniq
76
+ end
77
+
78
+ # Unifies this selector with another {SimpleSequence}'s {SimpleSequence#members members array},
79
+ # returning another `SimpleSequence`
80
+ # that matches both this selector and the input selector.
81
+ #
82
+ # @param sels [Array<Simple>] A {SimpleSequence}'s {SimpleSequence#members members array}
83
+ # @return [SimpleSequence, nil] A {SimpleSequence} matching both `sels` and this selector,
84
+ # or `nil` if this is impossible (e.g. unifying `#foo` and `#bar`)
85
+ # @raise [Sass::SyntaxError] If this selector cannot be unified.
86
+ # This will only ever occur when a dynamic selector,
87
+ # such as {Parent} or {Interpolation}, is used in unification.
88
+ # Since these selectors should be resolved
89
+ # by the time extension and unification happen,
90
+ # this exception will only ever be raised as a result of programmer error
91
+ def unify(sels)
92
+ return unless sseq = members.inject(sels) do |sseq, sel|
93
+ return unless sseq
94
+ sel.unify(sseq)
95
+ end
96
+ SimpleSequence.new(sseq)
97
+ end
98
+
99
+ # Returns whether or not this selector matches all elements
100
+ # that the given selector matches (as well as possibly more).
101
+ #
102
+ # @example
103
+ # (.foo).superselector?(.foo.bar) #=> true
104
+ # (.foo).superselector?(.bar) #=> false
105
+ # @param sseq [SimpleSequence]
106
+ # @return [Boolean]
107
+ def superselector?(sseq)
108
+ (base.nil? || base.eql?(sseq.base)) && rest.subset?(sseq.rest)
109
+ end
110
+
111
+ # @see Simple#to_a
112
+ def to_a
113
+ @members.map {|sel| sel.to_a}.flatten
114
+ end
115
+
116
+ # Returns a string representation of the sequence.
117
+ # This is basically the selector string.
118
+ #
119
+ # @return [String]
120
+ def inspect
121
+ members.map {|m| m.inspect}.join
122
+ end
123
+
124
+ private
125
+
126
+ def _hash
127
+ [base, Sass::Util.set_hash(rest)].hash
128
+ end
129
+
130
+ def _eql?(other)
131
+ other.base.eql?(self.base) && Sass::Util.set_eql?(other.rest, self.rest)
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,78 @@
1
+ require 'strscan'
2
+
3
+ module Sass
4
+ # This module contains functionality that's shared between Haml and Sass.
5
+ module Shared
6
+ extend self
7
+
8
+ # Scans through a string looking for the interoplation-opening `#{`
9
+ # and, when it's found, yields the scanner to the calling code
10
+ # so it can handle it properly.
11
+ #
12
+ # The scanner will have any backslashes immediately in front of the `#{`
13
+ # as the second capture group (`scan[2]`),
14
+ # and the text prior to that as the first (`scan[1]`).
15
+ #
16
+ # @yieldparam scan [StringScanner] The scanner scanning through the string
17
+ # @return [String] The text remaining in the scanner after all `#{`s have been processed
18
+ def handle_interpolation(str)
19
+ scan = StringScanner.new(str)
20
+ yield scan while scan.scan(/(.*?)(\\*)\#\{/)
21
+ scan.rest
22
+ end
23
+
24
+ # Moves a scanner through a balanced pair of characters.
25
+ # For example:
26
+ #
27
+ # Foo (Bar (Baz bang) bop) (Bang (bop bip))
28
+ # ^ ^
29
+ # from to
30
+ #
31
+ # @param scanner [StringScanner] The string scanner to move
32
+ # @param start [Character] The character opening the balanced pair.
33
+ # A `Fixnum` in 1.8, a `String` in 1.9
34
+ # @param finish [Character] The character closing the balanced pair.
35
+ # A `Fixnum` in 1.8, a `String` in 1.9
36
+ # @param count [Fixnum] The number of opening characters matched
37
+ # before calling this method
38
+ # @return [(String, String)] The string matched within the balanced pair
39
+ # and the rest of the string.
40
+ # `["Foo (Bar (Baz bang) bop)", " (Bang (bop bip))"]` in the example above.
41
+ def balance(scanner, start, finish, count = 0)
42
+ str = ''
43
+ scanner = StringScanner.new(scanner) unless scanner.is_a? StringScanner
44
+ regexp = Regexp.new("(.*?)[\\#{start.chr}\\#{finish.chr}]", Regexp::MULTILINE)
45
+ while scanner.scan(regexp)
46
+ str << scanner.matched
47
+ count += 1 if scanner.matched[-1] == start
48
+ count -= 1 if scanner.matched[-1] == finish
49
+ return [str.strip, scanner.rest] if count == 0
50
+ end
51
+ end
52
+
53
+ # Formats a string for use in error messages about indentation.
54
+ #
55
+ # @param indentation [String] The string used for indentation
56
+ # @param was [Boolean] Whether or not to add `"was"` or `"were"`
57
+ # (depending on how many characters were in `indentation`)
58
+ # @return [String] The name of the indentation (e.g. `"12 spaces"`, `"1 tab"`)
59
+ def human_indentation(indentation, was = false)
60
+ if !indentation.include?(?\t)
61
+ noun = 'space'
62
+ elsif !indentation.include?(?\s)
63
+ noun = 'tab'
64
+ else
65
+ return indentation.inspect + (was ? ' was' : '')
66
+ end
67
+
68
+ singular = indentation.length == 1
69
+ if was
70
+ was = singular ? ' was' : ' were'
71
+ else
72
+ was = ''
73
+ end
74
+
75
+ "#{indentation.length} #{noun}#{'s' unless singular}#{was}"
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,128 @@
1
+ require 'sass/tree/node'
2
+
3
+ module Sass::Tree
4
+ # A static node representing a Sass comment (silent or loud).
5
+ #
6
+ # @see Sass::Tree
7
+ class CommentNode < Node
8
+ # The text of the comment, not including `/*` and `*/`.
9
+ #
10
+ # @return [String]
11
+ attr_accessor :value
12
+
13
+ # Whether or not the comment is silent (that is, doesn't output to CSS).
14
+ #
15
+ # @return [Boolean]
16
+ attr_accessor :silent
17
+
18
+ # @param value [String] See \{#value}
19
+ # @param silent [Boolean] See \{#silent}
20
+ def initialize(value, silent)
21
+ @lines = []
22
+ @value = normalize_indentation value
23
+ @silent = silent
24
+ super()
25
+ end
26
+
27
+ # Compares the contents of two comments.
28
+ #
29
+ # @param other [Object] The object to compare with
30
+ # @return [Boolean] Whether or not this node and the other object
31
+ # are the same
32
+ def ==(other)
33
+ self.class == other.class && value == other.value && silent == other.silent
34
+ end
35
+
36
+ # Returns `true` if this is a silent comment
37
+ # or the current style doesn't render comments.
38
+ #
39
+ # @return [Boolean]
40
+ def invisible?
41
+ style == :compressed || @silent
42
+ end
43
+
44
+ # @see Node#to_sass
45
+ def to_sass(tabs, opts = {})
46
+ content = value.gsub(/\*\/$/, '').rstrip
47
+ if content =~ /\A[ \t]/
48
+ # Re-indent SCSS comments like this:
49
+ # /* foo
50
+ # bar
51
+ # baz */
52
+ content.gsub!(/^/, ' ')
53
+ content.sub!(/\A([ \t]*)\/\*/, '/*\1')
54
+ end
55
+
56
+ content =
57
+ unless content.include?("\n")
58
+ content
59
+ else
60
+ content.gsub!(/\n( \*|\/\/)/, "\n ")
61
+ spaces = content.scan(/\n( *)/).map {|s| s.first.size}.min
62
+ sep = silent ? "\n//" : "\n *"
63
+ if spaces >= 2
64
+ content.gsub(/\n /, sep)
65
+ else
66
+ content.gsub(/\n#{' ' * spaces}/, sep)
67
+ end
68
+ end
69
+
70
+ content.gsub!(/\A\/\*/, '//') if silent
71
+ content.gsub!(/^/, ' ' * tabs)
72
+ content.rstrip + "\n"
73
+ end
74
+
75
+ # @see Node#to_scss
76
+ def to_scss(tabs, opts = {})
77
+ spaces = (' ' * [tabs - value[/^ */].size, 0].max)
78
+ if silent
79
+ value.gsub(/^[\/ ]\*/, '//').gsub(/ *\*\/$/, '')
80
+ else
81
+ value
82
+ end.gsub(/^/, spaces) + "\n"
83
+ end
84
+
85
+ protected
86
+
87
+ # Computes the CSS for the comment.
88
+ #
89
+ # Returns `nil` if this is a silent comment
90
+ # or the current style doesn't render comments.
91
+ #
92
+ # @overload to_s(tabs = 0)
93
+ # @param tabs [Fixnum] The level of indentation for the CSS
94
+ # @return [String, nil] The resulting CSS
95
+ # @see #invisible?
96
+ def _to_s(tabs = 0, _ = nil)
97
+ return if invisible?
98
+ spaces = (' ' * [tabs - 1 - value[/^ */].size, 0].max)
99
+
100
+ content = value.gsub(/^/, spaces)
101
+ content.gsub!(/\n +(\* *(?!\/))?/, ' ') if style == :compact
102
+ content
103
+ end
104
+
105
+ # Removes this node from the tree if it's a silent comment.
106
+ #
107
+ # @param environment [Sass::Environment] The lexical environment containing
108
+ # variable and mixin values
109
+ # @return [Tree::Node, Array<Tree::Node>] The resulting static nodes
110
+ # @see Sass::Tree
111
+ def _perform(environment)
112
+ return [] if @silent
113
+ self
114
+ end
115
+
116
+ private
117
+
118
+ def normalize_indentation(str)
119
+ pre = str.split("\n").inject(str[/^[ \t]*/].split("")) do |pre, line|
120
+ line[/^[ \t]*/].split("").zip(pre).inject([]) do |arr, (a, b)|
121
+ break arr if a != b
122
+ arr + [a]
123
+ end
124
+ end.join
125
+ str.gsub(/^#{pre}/, '')
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,36 @@
1
+ module Sass
2
+ module Tree
3
+ # A dynamic node representing a Sass `@debug` statement.
4
+ #
5
+ # @see Sass::Tree
6
+ class DebugNode < Node
7
+ # @param expr [Script::Node] The expression to print
8
+ def initialize(expr)
9
+ @expr = expr
10
+ super()
11
+ end
12
+
13
+ protected
14
+
15
+ # @see Node#to_src
16
+ def to_src(tabs, opts, fmt)
17
+ "#{' ' * tabs}@debug #{@expr.to_sass(opts)}#{semi fmt}\n"
18
+ end
19
+
20
+ # Prints the expression to STDERR.
21
+ #
22
+ # @param environment [Sass::Environment] The lexical environment containing
23
+ # variable and mixin values
24
+ def _perform(environment)
25
+ res = @expr.perform(environment)
26
+ res = res.value if res.is_a?(Sass::Script::String)
27
+ if filename
28
+ $stderr.puts "#{filename}:#{line} DEBUG: #{res}"
29
+ else
30
+ $stderr.puts "Line #{line} DEBUG: #{res}"
31
+ end
32
+ []
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,75 @@
1
+ module Sass::Tree
2
+ # A static node representing an unproccessed Sass `@`-directive.
3
+ # Directives known to Sass, like `@for` and `@debug`,
4
+ # are handled by their own nodes;
5
+ # only CSS directives like `@media` and `@font-face` become {DirectiveNode}s.
6
+ #
7
+ # `@import` is a bit of a weird case;
8
+ # it becomes an {ImportNode}.
9
+ #
10
+ # @see Sass::Tree
11
+ class DirectiveNode < Node
12
+ # The text of the directive, `@` and all.
13
+ #
14
+ # @return [String]
15
+ attr_accessor :value
16
+
17
+ # @param value [String] See \{#value}
18
+ def initialize(value)
19
+ @value = value
20
+ super()
21
+ end
22
+
23
+ protected
24
+
25
+ # @see Node#to_src
26
+ def to_src(tabs, opts, fmt)
27
+ res = "#{' ' * tabs}#{value}"
28
+ return res + "#{semi fmt}\n" unless has_children
29
+ res + children_to_src(tabs, opts, fmt) + "\n"
30
+ end
31
+
32
+ # Computes the CSS for the directive.
33
+ #
34
+ # @param tabs [Fixnum] The level of indentation for the CSS
35
+ # @return [String] The resulting CSS
36
+ def _to_s(tabs)
37
+ return value + ";" unless has_children
38
+ return value + " {}" if children.empty?
39
+ result = if style == :compressed
40
+ "#{value}{"
41
+ else
42
+ "#{' ' * (tabs - 1)}#{value} {" + (style == :compact ? ' ' : "\n")
43
+ end
44
+ was_prop = false
45
+ first = true
46
+ children.each do |child|
47
+ next if child.invisible?
48
+ if style == :compact
49
+ if child.is_a?(PropNode)
50
+ result << "#{child.to_s(first || was_prop ? 1 : tabs + 1)} "
51
+ else
52
+ if was_prop
53
+ result[-1] = "\n"
54
+ end
55
+ rendered = child.to_s(tabs + 1).dup
56
+ rendered = rendered.lstrip if first
57
+ result << rendered.rstrip + "\n"
58
+ end
59
+ was_prop = child.is_a?(PropNode)
60
+ first = false
61
+ elsif style == :compressed
62
+ result << (was_prop ? ";#{child.to_s(1)}" : child.to_s(1))
63
+ was_prop = child.is_a?(PropNode)
64
+ else
65
+ result << child.to_s(tabs + 1) + "\n"
66
+ end
67
+ end
68
+ result.rstrip + if style == :compressed
69
+ "}"
70
+ else
71
+ (style == :expanded ? "\n" : " ") + "}\n"
72
+ end
73
+ end
74
+ end
75
+ end