haml 3.0.25 → 3.1.0.alpha.2

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 (212) hide show
  1. data/.yardopts +1 -1
  2. data/CONTRIBUTING +0 -1
  3. data/EDGE_GEM_VERSION +1 -0
  4. data/MIT-LICENSE +1 -1
  5. data/README.md +10 -175
  6. data/Rakefile +56 -84
  7. data/VERSION +1 -1
  8. data/VERSION_NAME +1 -1
  9. data/init.rb +1 -1
  10. data/lib/haml.rb +14 -12
  11. data/lib/haml/engine.rb +1 -1
  12. data/lib/haml/exec.rb +19 -316
  13. data/lib/haml/helpers/action_view_extensions.rb +1 -1
  14. data/lib/haml/html.rb +69 -76
  15. data/lib/haml/precompiler.rb +34 -41
  16. data/lib/haml/railtie.rb +4 -6
  17. data/lib/haml/template/plugin.rb +6 -16
  18. data/lib/haml/util.rb +91 -107
  19. data/lib/haml/version.rb +7 -0
  20. data/test/benchmark.rb +2 -9
  21. data/test/haml/engine_test.rb +195 -92
  22. data/test/haml/html2haml/erb_tests.rb +0 -14
  23. data/test/haml/util_test.rb +32 -0
  24. data/test/test_helper.rb +0 -39
  25. metadata +96 -324
  26. data/bin/css2sass +0 -13
  27. data/bin/sass +0 -8
  28. data/bin/sass-convert +0 -7
  29. data/extra/haml-mode.el +0 -753
  30. data/extra/sass-mode.el +0 -207
  31. data/lib/haml/util/subset_map.rb +0 -101
  32. data/lib/sass.rb +0 -29
  33. data/lib/sass/callbacks.rb +0 -52
  34. data/lib/sass/css.rb +0 -294
  35. data/lib/sass/engine.rb +0 -720
  36. data/lib/sass/environment.rb +0 -143
  37. data/lib/sass/error.rb +0 -198
  38. data/lib/sass/files.rb +0 -160
  39. data/lib/sass/less.rb +0 -382
  40. data/lib/sass/plugin.rb +0 -279
  41. data/lib/sass/plugin/configuration.rb +0 -221
  42. data/lib/sass/plugin/generic.rb +0 -15
  43. data/lib/sass/plugin/merb.rb +0 -37
  44. data/lib/sass/plugin/rack.rb +0 -47
  45. data/lib/sass/plugin/rails.rb +0 -32
  46. data/lib/sass/plugin/staleness_checker.rb +0 -123
  47. data/lib/sass/repl.rb +0 -58
  48. data/lib/sass/script.rb +0 -63
  49. data/lib/sass/script/bool.rb +0 -18
  50. data/lib/sass/script/color.rb +0 -491
  51. data/lib/sass/script/css_lexer.rb +0 -29
  52. data/lib/sass/script/css_parser.rb +0 -31
  53. data/lib/sass/script/funcall.rb +0 -77
  54. data/lib/sass/script/functions.rb +0 -861
  55. data/lib/sass/script/interpolation.rb +0 -70
  56. data/lib/sass/script/lexer.rb +0 -337
  57. data/lib/sass/script/literal.rb +0 -236
  58. data/lib/sass/script/node.rb +0 -112
  59. data/lib/sass/script/number.rb +0 -423
  60. data/lib/sass/script/operation.rb +0 -95
  61. data/lib/sass/script/parser.rb +0 -401
  62. data/lib/sass/script/string.rb +0 -67
  63. data/lib/sass/script/string_interpolation.rb +0 -93
  64. data/lib/sass/script/unary_operation.rb +0 -57
  65. data/lib/sass/script/variable.rb +0 -48
  66. data/lib/sass/scss.rb +0 -17
  67. data/lib/sass/scss/css_parser.rb +0 -46
  68. data/lib/sass/scss/parser.rb +0 -855
  69. data/lib/sass/scss/rx.rb +0 -126
  70. data/lib/sass/scss/sass_parser.rb +0 -11
  71. data/lib/sass/scss/script_lexer.rb +0 -15
  72. data/lib/sass/scss/script_parser.rb +0 -25
  73. data/lib/sass/scss/static_parser.rb +0 -40
  74. data/lib/sass/selector.rb +0 -361
  75. data/lib/sass/selector/abstract_sequence.rb +0 -62
  76. data/lib/sass/selector/comma_sequence.rb +0 -82
  77. data/lib/sass/selector/sequence.rb +0 -237
  78. data/lib/sass/selector/simple.rb +0 -113
  79. data/lib/sass/selector/simple_sequence.rb +0 -136
  80. data/lib/sass/tree/charset_node.rb +0 -37
  81. data/lib/sass/tree/comment_node.rb +0 -128
  82. data/lib/sass/tree/debug_node.rb +0 -36
  83. data/lib/sass/tree/directive_node.rb +0 -75
  84. data/lib/sass/tree/extend_node.rb +0 -65
  85. data/lib/sass/tree/for_node.rb +0 -55
  86. data/lib/sass/tree/if_node.rb +0 -69
  87. data/lib/sass/tree/import_node.rb +0 -102
  88. data/lib/sass/tree/mixin_def_node.rb +0 -48
  89. data/lib/sass/tree/mixin_node.rb +0 -111
  90. data/lib/sass/tree/node.rb +0 -464
  91. data/lib/sass/tree/prop_node.rb +0 -220
  92. data/lib/sass/tree/root_node.rb +0 -163
  93. data/lib/sass/tree/rule_node.rb +0 -261
  94. data/lib/sass/tree/variable_node.rb +0 -39
  95. data/lib/sass/tree/warn_node.rb +0 -42
  96. data/lib/sass/tree/while_node.rb +0 -36
  97. data/test/haml/util/subset_map_test.rb +0 -91
  98. data/test/sass/callbacks_test.rb +0 -61
  99. data/test/sass/conversion_test.rb +0 -1218
  100. data/test/sass/css2sass_test.rb +0 -364
  101. data/test/sass/data/hsl-rgb.txt +0 -319
  102. data/test/sass/engine_test.rb +0 -2267
  103. data/test/sass/extend_test.rb +0 -1348
  104. data/test/sass/functions_test.rb +0 -556
  105. data/test/sass/less_conversion_test.rb +0 -653
  106. data/test/sass/more_results/more1.css +0 -9
  107. data/test/sass/more_results/more1_with_line_comments.css +0 -26
  108. data/test/sass/more_results/more_import.css +0 -29
  109. data/test/sass/more_templates/_more_partial.sass +0 -2
  110. data/test/sass/more_templates/more1.sass +0 -23
  111. data/test/sass/more_templates/more_import.sass +0 -11
  112. data/test/sass/plugin_test.rb +0 -433
  113. data/test/sass/results/alt.css +0 -4
  114. data/test/sass/results/basic.css +0 -9
  115. data/test/sass/results/compact.css +0 -5
  116. data/test/sass/results/complex.css +0 -86
  117. data/test/sass/results/compressed.css +0 -1
  118. data/test/sass/results/expanded.css +0 -19
  119. data/test/sass/results/import.css +0 -31
  120. data/test/sass/results/import_charset.css +0 -4
  121. data/test/sass/results/import_charset_1_8.css +0 -4
  122. data/test/sass/results/import_charset_ibm866.css +0 -4
  123. data/test/sass/results/line_numbers.css +0 -49
  124. data/test/sass/results/mixins.css +0 -95
  125. data/test/sass/results/multiline.css +0 -24
  126. data/test/sass/results/nested.css +0 -22
  127. data/test/sass/results/options.css +0 -1
  128. data/test/sass/results/parent_ref.css +0 -13
  129. data/test/sass/results/script.css +0 -16
  130. data/test/sass/results/scss_import.css +0 -31
  131. data/test/sass/results/scss_importee.css +0 -2
  132. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +0 -1
  133. data/test/sass/results/subdir/subdir.css +0 -3
  134. data/test/sass/results/units.css +0 -11
  135. data/test/sass/results/warn.css +0 -0
  136. data/test/sass/results/warn_imported.css +0 -0
  137. data/test/sass/script_conversion_test.rb +0 -314
  138. data/test/sass/script_test.rb +0 -470
  139. data/test/sass/scss/css_test.rb +0 -916
  140. data/test/sass/scss/rx_test.rb +0 -156
  141. data/test/sass/scss/scss_test.rb +0 -1122
  142. data/test/sass/scss/test_helper.rb +0 -37
  143. data/test/sass/templates/_imported_charset_ibm866.sass +0 -4
  144. data/test/sass/templates/_imported_charset_utf8.sass +0 -4
  145. data/test/sass/templates/_partial.sass +0 -2
  146. data/test/sass/templates/alt.sass +0 -16
  147. data/test/sass/templates/basic.sass +0 -23
  148. data/test/sass/templates/bork1.sass +0 -2
  149. data/test/sass/templates/bork2.sass +0 -2
  150. data/test/sass/templates/bork3.sass +0 -2
  151. data/test/sass/templates/bork4.sass +0 -2
  152. data/test/sass/templates/compact.sass +0 -17
  153. data/test/sass/templates/complex.sass +0 -305
  154. data/test/sass/templates/compressed.sass +0 -15
  155. data/test/sass/templates/expanded.sass +0 -17
  156. data/test/sass/templates/import.sass +0 -12
  157. data/test/sass/templates/import_charset.sass +0 -7
  158. data/test/sass/templates/import_charset_1_8.sass +0 -4
  159. data/test/sass/templates/import_charset_ibm866.sass +0 -9
  160. data/test/sass/templates/importee.less +0 -2
  161. data/test/sass/templates/importee.sass +0 -19
  162. data/test/sass/templates/line_numbers.sass +0 -13
  163. data/test/sass/templates/mixin_bork.sass +0 -5
  164. data/test/sass/templates/mixins.sass +0 -76
  165. data/test/sass/templates/multiline.sass +0 -20
  166. data/test/sass/templates/nested.sass +0 -25
  167. data/test/sass/templates/nested_bork1.sass +0 -2
  168. data/test/sass/templates/nested_bork2.sass +0 -2
  169. data/test/sass/templates/nested_bork3.sass +0 -2
  170. data/test/sass/templates/nested_bork4.sass +0 -2
  171. data/test/sass/templates/nested_mixin_bork.sass +0 -6
  172. data/test/sass/templates/options.sass +0 -2
  173. data/test/sass/templates/parent_ref.sass +0 -25
  174. data/test/sass/templates/script.sass +0 -101
  175. data/test/sass/templates/scss_import.scss +0 -11
  176. data/test/sass/templates/scss_importee.scss +0 -1
  177. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +0 -2
  178. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +0 -3
  179. data/test/sass/templates/subdir/subdir.sass +0 -6
  180. data/test/sass/templates/units.sass +0 -11
  181. data/test/sass/templates/warn.sass +0 -3
  182. data/test/sass/templates/warn_imported.sass +0 -4
  183. data/vendor/fssm/LICENSE +0 -20
  184. data/vendor/fssm/README.markdown +0 -55
  185. data/vendor/fssm/Rakefile +0 -59
  186. data/vendor/fssm/VERSION.yml +0 -5
  187. data/vendor/fssm/example.rb +0 -9
  188. data/vendor/fssm/fssm.gemspec +0 -77
  189. data/vendor/fssm/lib/fssm.rb +0 -33
  190. data/vendor/fssm/lib/fssm/backends/fsevents.rb +0 -36
  191. data/vendor/fssm/lib/fssm/backends/inotify.rb +0 -26
  192. data/vendor/fssm/lib/fssm/backends/polling.rb +0 -25
  193. data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +0 -131
  194. data/vendor/fssm/lib/fssm/monitor.rb +0 -26
  195. data/vendor/fssm/lib/fssm/path.rb +0 -91
  196. data/vendor/fssm/lib/fssm/pathname.rb +0 -502
  197. data/vendor/fssm/lib/fssm/state/directory.rb +0 -57
  198. data/vendor/fssm/lib/fssm/state/file.rb +0 -24
  199. data/vendor/fssm/lib/fssm/support.rb +0 -63
  200. data/vendor/fssm/lib/fssm/tree.rb +0 -176
  201. data/vendor/fssm/profile/prof-cache.rb +0 -40
  202. data/vendor/fssm/profile/prof-fssm-pathname.html +0 -1231
  203. data/vendor/fssm/profile/prof-pathname.rb +0 -68
  204. data/vendor/fssm/profile/prof-plain-pathname.html +0 -988
  205. data/vendor/fssm/profile/prof.html +0 -2379
  206. data/vendor/fssm/spec/path_spec.rb +0 -75
  207. data/vendor/fssm/spec/root/duck/quack.txt +0 -0
  208. data/vendor/fssm/spec/root/file.css +0 -0
  209. data/vendor/fssm/spec/root/file.rb +0 -0
  210. data/vendor/fssm/spec/root/file.yml +0 -0
  211. data/vendor/fssm/spec/root/moo/cow.txt +0 -0
  212. data/vendor/fssm/spec/spec_helper.rb +0 -14
@@ -1,382 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'less'
4
-
5
- module Less
6
- # This is the class that Treetop defines for parsing Less files.
7
- # Since not everything gets parsed into the AST but is instead resolved at parse-time,
8
- # we need to override some of it so that it can be converted into Sass.
9
- module StyleSheet
10
- # Selector mixins that don't have arguments.
11
- # This depends only on the syntax at the call site;
12
- # if it doesn't use parens, it hits this production,
13
- # regardless of whether the mixin being called has arguments or not.
14
- module Mixin4
15
- def build_with_sass(env)
16
- selectors.build(env, :mixin).each do |path|
17
- el = path.inject(env.root) do |current, node|
18
- current.descend(node.selector, node) or raise MixinNameError, "#{selectors.text_value} in #{env}"
19
- end
20
- if el.is_a?(Node::Mixin::Def)
21
- # Calling a mixin with arguments, which gets compiled to a Sass mixin
22
- env << Node::Mixin::Call.new(el, [], env)
23
- else
24
- # Calling a mixin without arguments, which gets compiled to @extend
25
- sel = selector_str(path)
26
- base = selector_str(selector_base(path))
27
- if base == sel
28
- env << Node::SassNode.new(Sass::Tree::ExtendNode.new([sel]))
29
- else
30
- Haml::Util.haml_warn <<WARNING
31
- WARNING: Sass doesn't support mixing in selector sequences.
32
- Replacing "#{sel}" with "@extend #{base}"
33
- WARNING
34
- env << Node::SassNode.new(Sass::Tree::CommentNode.new("// #{sel};", true))
35
- env << Node::SassNode.new(Sass::Tree::ExtendNode.new([base]))
36
- end
37
- end
38
- end
39
- end
40
- alias_method :build_without_sass, :build
41
- alias_method :build, :build_with_sass
42
-
43
- def selector_base(path)
44
- el, i = Haml::Util.enum_with_index(path).to_a.reverse.find {|e, i| e.selector !~ /^:{1,2}$/} ||
45
- [path.first, 0]
46
- sel = (el.selector =~ /^:{0,2}$/ ? el.selector : "")
47
- [Node::Element.new(el.name, sel)] + path[i+1..-1]
48
- end
49
-
50
- def selector_str(path)
51
- path.map {|e| e.sass_selector_str}.join(' ').gsub(' :', ':')
52
- end
53
- end
54
-
55
- # Property and variable declarations.
56
- # We want to keep track of the line number
57
- # so we don't space out the variables too much in the generated Sass.
58
- module Declaration3
59
- def build_with_sass(env)
60
- build_without_sass(env)
61
- env.rules.last.src_line = input.line_of(interval.first)
62
- end
63
- alias_method :build_without_sass, :build
64
- alias_method :build, :build_with_sass
65
- end
66
-
67
- # Comma-separated selectors.
68
- # Less breaks these into completely separate nodes.
69
- # Since we don't want this duplication in the Sass,
70
- # we modify the production to keep track of the original group
71
- # so we can reconstruct it later on.
72
- module Selectors2
73
- def build_with_sass(env, method)
74
- arr = build_without_sass(env, method)
75
- return arr if method == :mixin
76
- rarr = arr.map {|e| e.top(env)}
77
- rarr.each {|e| e.group = rarr}
78
- arr
79
- end
80
- alias_method :build_without_sass, :build
81
- alias_method :build, :build_with_sass
82
- end
83
-
84
- # Attribute accessors.
85
- # Sass just flat-out doesn't support these,
86
- # so we print a warning to that effect and compile them to comments.
87
- module Accessor1
88
- def build(env)
89
- Haml::Util.haml_warn <<WARNING
90
- WARNING: Sass doesn't support attribute accessors.
91
- Ignoring #{text_value}
92
- WARNING
93
- Node::Anonymous.new("/* #{text_value} */")
94
- end
95
- end
96
-
97
- # @import statements.
98
- # Less handles these during parse-time,
99
- # so we want to wrap them up as a node in the tree.
100
- # We also include the nodes, though,
101
- # since we want to have access to the mixins
102
- # so we can tell if they take arguments or not.
103
- # The included nodes are hidden so they don't appear in the output.
104
- module Import1
105
- def build_with_sass(env)
106
- line = input.line_of(interval.first)
107
- import = Sass::Tree::ImportNode.new(url.value.gsub(/\.less$/, ''))
108
- import.line = input.line_of(interval.first)
109
- env << Node::SassNode.new(import)
110
- old_rules = env.rules.dup
111
- build_without_sass env
112
- (env.rules - old_rules).each {|r| r.hide_in_sass = true}
113
- rescue ImportError => e
114
- raise Sass::SyntaxError.new("File to import #{url.text_value} not found or unreadable", :line => line)
115
- end
116
- alias_method :build_without_sass, :build
117
- alias_method :build, :build_with_sass
118
- end
119
-
120
- # The IE-specific `alpha(opacity=@var)`.
121
- # Less manually resolves the variable here at parse-time.
122
- # We want to keep the variable around,
123
- # so we compile this to a function.
124
- # Less doesn't actually have an `=` operator,
125
- # but that's okay since it's just getting compiled to Sass anyway.
126
- module Entity::Alpha1
127
- def build(env)
128
- Node::Function.new("alpha",
129
- [Node::Expression.new([
130
- Node::Keyword.new("opacity"),
131
- Node::Operator.new("="),
132
- variable.build])])
133
- end
134
- end
135
- end
136
-
137
- # The Less AST classes for the document,
138
- # including both stylesheet-level nodes and expression-level nodes.
139
- # The main purpose of overriding these is to add `#to_sass_tree` functions
140
- # for converting to Sass.
141
- module Node
142
- module Entity
143
- attr_accessor :hide_in_sass
144
- attr_accessor :src_line
145
- end
146
-
147
- class Element
148
- attr_accessor :group
149
-
150
- def top(env)
151
- return self if parent.equal?(env)
152
- return parent.top(env)
153
- end
154
-
155
- def to_sass_tree
156
- if root?
157
- root = Sass::Tree::RootNode.new("")
158
- rules.each {|r| root << r.to_sass_tree}
159
- return root
160
- end
161
- return if hide_in_sass
162
- return if !self.equal?(group.first)
163
-
164
- last_el = nil
165
- sel = group.map do |el|
166
- comma_sel = []
167
- loop do
168
- comma_sel << el.sass_selector_str
169
- break unless el.rules.size == 1 && el.rules.first.is_a?(Element)
170
- el = el.rules.first
171
- end
172
- last_el = el
173
- comma_sel = comma_sel.join(' ').gsub(' :', ':')
174
- comma_sel.gsub!(/^:/, '&:') unless parent.root?
175
- comma_sel
176
- end.join(', ')
177
-
178
- rule = Sass::Tree::RuleNode.new([sel])
179
- last_el.rules.each {|r| rule << r.to_sass_tree}
180
- return rule
181
- end
182
-
183
- def sass_selector_str
184
- case @selector
185
- when /[+>~]/; "#{@selector} #{@name}"
186
- else @selector + @name
187
- end
188
- end
189
- end
190
-
191
- module Mixin
192
- class Call
193
- def to_sass_tree
194
- return if hide_in_sass
195
- Sass::Tree::MixinNode.new(@mixin.name.gsub(/^\./, ''), @params.map {|v| v.to_sass_tree})
196
- end
197
- end
198
-
199
- class Def
200
- def to_sass_tree
201
- return if hide_in_sass
202
- mixin = Sass::Tree::MixinDefNode.new(name, @params.map do |v|
203
- v.value.flatten!
204
- [Sass::Script::Variable.new(v), v.value.to_sass_tree]
205
- end)
206
- rules.each {|r| mixin << r.to_sass_tree}
207
- mixin
208
- end
209
- end
210
- end
211
-
212
- class SassNode
213
- include Entity
214
-
215
- def initialize(node)
216
- @node = node
217
- end
218
-
219
- def to_sass_tree
220
- return if hide_in_sass
221
- @node
222
- end
223
- end
224
-
225
- class Property
226
- def to_sass_tree
227
- return if hide_in_sass
228
- Sass::Tree::PropNode.new([self], @value.to_sass_tree, :new)
229
- end
230
- end
231
-
232
- class Expression
233
- def to_sass_tree
234
- if first.is_a?(Array)
235
- val = map {|e| _to_sass_tree(e)}.inject(nil) do |e, i|
236
- next i unless e
237
- Sass::Script::Operation.new(e, i, :comma)
238
- end
239
- else
240
- val = _to_sass_tree(self)
241
- end
242
- val.options = {}
243
- val
244
- end
245
-
246
- private
247
-
248
- LESS_TO_SASS_OPERATORS = {"-" => :minus, "+" => :plus, "*" => :times, "/" => :div, "=" => :single_eq}
249
-
250
- def _to_sass_tree(arr)
251
- e, rest = _to_sass_tree_plus_minus_eq(arr)
252
- until rest.empty?
253
- e2, rest = _to_sass_tree_plus_minus_eq(rest)
254
- e = Sass::Script::Operation.new(e, e2, :concat)
255
- end
256
- return e
257
- end
258
-
259
- def _to_sass_tree_plus_minus_eq(arr)
260
- e, rest = _to_sass_tree_times_div(arr)
261
- while rest[0] && rest[0].is_a?(Operator) && %w[+ - =].include?(rest[0])
262
- op = LESS_TO_SASS_OPERATORS[rest[0]]
263
- e2, rest = _to_sass_tree_times_div(rest[1..-1])
264
- e = Sass::Script::Operation.new(e, e2, op)
265
- end
266
- return e, rest
267
- end
268
-
269
- def _to_sass_tree_times_div(arr)
270
- e, rest = _to_sass_tree_unary(arr)
271
- while rest[0] && rest[0].is_a?(Operator) && %w[* /].include?(rest[0])
272
- op = LESS_TO_SASS_OPERATORS[rest[0]]
273
- e2, rest = _to_sass_tree_unary(rest[1..-1])
274
- e = Sass::Script::Operation.new(e, e2, op)
275
- end
276
- return e, rest
277
- end
278
-
279
- def _to_sass_tree_unary(arr)
280
- if arr[0] == "-"
281
- first, rest = _sass_split(arr[1..-1])
282
- return Sass::Script::UnaryOperation.new(first, :minus), rest
283
- else
284
- return _sass_split(arr[0..-1])
285
- end
286
- end
287
-
288
- def _sass_split(arr)
289
- return arr[0].to_sass_tree, arr[1..-1] unless arr[0] == "("
290
- parens = 1
291
- i = arr[1..-1].each_with_index do |e, i|
292
- parens += 1 if e == "("
293
- parens -= 1 if e == ")"
294
- break i if parens == 0
295
- end
296
-
297
- return _to_sass_tree(arr[1...i+1]), arr[i+2..-1]
298
- end
299
- end
300
-
301
- class Color
302
- def to_sass_tree
303
- Sass::Script::Color.new(:red => r, :green => g, :blue => b, :alpha => a)
304
- end
305
- end
306
-
307
- class Number
308
- def to_sass_tree
309
- Sass::Script::Number.new(self, [self.unit])
310
- end
311
- end
312
-
313
- class Variable
314
- def to_sass_tree
315
- if @declaration
316
- return if hide_in_sass
317
- node = Sass::Tree::VariableNode.new(self, @value.to_sass_tree, false)
318
- node.line = self.src_line
319
- node
320
- else
321
- Sass::Script::Variable.new(self)
322
- end
323
- end
324
- end
325
-
326
- class Function
327
- def to_sass_tree
328
- Sass::Script::Funcall.new(self, @args.map {|a| a.to_sass_tree})
329
- end
330
- end
331
-
332
- class Keyword
333
- def to_sass_tree
334
- Sass::Script::String.new(self)
335
- end
336
- end
337
-
338
- class Anonymous
339
- def to_sass_tree
340
- Sass::Script::String.new(self)
341
- end
342
- end
343
-
344
- class Quoted
345
- def to_sass_tree
346
- Sass::Script::String.new(self, true)
347
- end
348
- end
349
-
350
- class FontFamily
351
- def to_sass_tree
352
- @family.map {|f| f.to_sass_tree}.inject(nil) do |e, f|
353
- next f unless e
354
- Sass::Script::Operation.new(e, f, :comma)
355
- end
356
- end
357
- end
358
- end
359
-
360
- # The entry point to Less.
361
- # By default Less doesn't preserve the filename of the file being parsed,
362
- # which is unpleasant for error reporting.
363
- # Our monkeypatch keeps it around.
364
- class Engine
365
- def initialize_with_sass(obj, opts = {})
366
- initialize_without_sass(obj, opts)
367
- @filename = obj.path if obj.is_a?(File)
368
- end
369
- alias_method :initialize_without_sass, :initialize
370
- alias_method :initialize, :initialize_with_sass
371
-
372
- def parse_with_sass
373
- parse_without_sass
374
- rescue Sass::SyntaxError => e
375
- e.modify_backtrace(:filename => @filename)
376
- raise e
377
- end
378
- alias_method :parse_without_sass, :parse
379
- alias_method :parse, :parse_with_sass
380
- alias_method :to_tree, :parse
381
- end
382
- end
@@ -1,279 +0,0 @@
1
- require 'fileutils'
2
-
3
- require 'sass'
4
- require 'sass/plugin/configuration'
5
- require 'sass/plugin/staleness_checker'
6
-
7
- module Sass
8
- # This module handles the compilation of Sass/SCSS files.
9
- # It provides global options and checks whether CSS files
10
- # need to be updated.
11
- #
12
- # This module is used as the primary interface with Sass
13
- # when it's used as a plugin for various frameworks.
14
- # All Rack-enabled frameworks are supported out of the box.
15
- # The plugin is {file:SASS_REFERENCE.md#rails_merb_plugin automatically activated for Rails and Merb}.
16
- # Other frameworks must enable it explicitly; see {Sass::Plugin::Rack}.
17
- #
18
- # This module has a large set of callbacks available
19
- # to allow users to run code (such as logging) when certain things happen.
20
- # All callback methods are of the form `on_#{name}`,
21
- # and they all take a block that's called when the given action occurs.
22
- #
23
- # @example Using a callback
24
- # Sass::Plugin.on_updating_stylesheet do |template, css|
25
- # puts "Compiling #{template} to #{css}"
26
- # end
27
- # Sass::Plugin.update_stylesheets
28
- # #=> Compiling app/sass/screen.scss to public/stylesheets/screen.css
29
- # #=> Compiling app/sass/print.scss to public/stylesheets/print.css
30
- # #=> Compiling app/sass/ie.scss to public/stylesheets/ie.css
31
- module Plugin
32
- include Haml::Util
33
-
34
- @checked_for_updates = false
35
-
36
- # Whether or not Sass has **ever** checked if the stylesheets need to be updated
37
- # (in this Ruby instance).
38
- #
39
- # @return [Boolean]
40
- attr_reader :checked_for_updates
41
-
42
- # Same as \{#update\_stylesheets}, but respects \{#checked\_for\_updates}
43
- # and the {file:SASS_REFERENCE.md#always_update-option `:always_update`}
44
- # and {file:SASS_REFERENCE.md#always_check-option `:always_check`} options.
45
- #
46
- # @see #update_stylesheets
47
- def check_for_updates
48
- return unless !Sass::Plugin.checked_for_updates ||
49
- Sass::Plugin.options[:always_update] || Sass::Plugin.options[:always_check]
50
- update_stylesheets
51
- end
52
-
53
- # Updates out-of-date stylesheets.
54
- #
55
- # Checks each Sass/SCSS file in {file:SASS_REFERENCE.md#template_location-option `:template_location`}
56
- # to see if it's been modified more recently than the corresponding CSS file
57
- # in {file:SASS_REFERENCE.md#css_location-option `:css_location`}.
58
- # If it has, it updates the CSS file.
59
- #
60
- # @param individual_files [Array<(String, String)>]
61
- # A list of files to check for updates
62
- # **in addition to those specified by the
63
- # {file:SASS_REFERENCE.md#template_location-option `:template_location` option}.**
64
- # The first string in each pair is the location of the Sass/SCSS file,
65
- # the second is the location of the CSS file that it should be compiled to.
66
- def update_stylesheets(individual_files = [])
67
- return if options[:never_update]
68
-
69
- run_updating_stylesheets individual_files
70
- @checked_for_updates = true
71
- staleness_checker = StalenessChecker.new
72
-
73
- individual_files.each do |t, c|
74
- if options[:always_update] || staleness_checker.stylesheet_needs_update?(c, t)
75
- update_stylesheet(t, c)
76
- end
77
- end
78
-
79
- template_location_array.each do |template_location, css_location|
80
-
81
- Dir.glob(File.join(template_location, "**", "*.s[ca]ss")).sort.each do |file|
82
- # Get the relative path to the file
83
- name = file.sub(template_location.sub(/\/*$/, '/'), "")
84
- css = css_filename(name, css_location)
85
-
86
- next if forbid_update?(name)
87
- if options[:always_update] || staleness_checker.stylesheet_needs_update?(css, file)
88
- update_stylesheet file, css
89
- else
90
- run_not_updating_stylesheet file, css
91
- end
92
- end
93
- end
94
- end
95
-
96
- # Updates all stylesheets, even those that aren't out-of-date.
97
- # Ignores the cache.
98
- #
99
- # @param individual_files [Array<(String, String)>]
100
- # A list of files to check for updates
101
- # **in addition to those specified by the
102
- # {file:SASS_REFERENCE.md#template_location-option `:template_location` option}.**
103
- # The first string in each pair is the location of the Sass/SCSS file,
104
- # the second is the location of the CSS file that it should be compiled to.
105
- # @see #update_stylesheets
106
- def force_update_stylesheets(individual_files = [])
107
- old_options = options
108
- self.options = options.dup
109
- options[:never_update] = false
110
- options[:always_update] = true
111
- options[:cache] = false
112
- update_stylesheets(individual_files)
113
- ensure
114
- self.options = old_options
115
- end
116
-
117
- # Watches the template directory (or directories)
118
- # and updates the CSS files whenever the related Sass/SCSS files change.
119
- # `watch` never returns.
120
- #
121
- # Whenever a change is detected to a Sass/SCSS file in
122
- # {file:SASS_REFERENCE.md#template_location-option `:template_location`},
123
- # the corresponding CSS file in {file:SASS_REFERENCE.md#css_location-option `:css_location`}
124
- # will be recompiled.
125
- # The CSS files of any Sass/SCSS files that import the changed file will also be recompiled.
126
- #
127
- # Before the watching starts in earnest, `watch` calls \{#update\_stylesheets}.
128
- #
129
- # Note that `watch` uses the [FSSM](http://github.com/ttilley/fssm) library
130
- # to monitor the filesystem for changes.
131
- # FSSM isn't loaded until `watch` is run.
132
- # The version of FSSM distributed with Sass is loaded by default,
133
- # but if another version has already been loaded that will be used instead.
134
- #
135
- # @param individual_files [Array<(String, String)>]
136
- # A list of files to watch for updates
137
- # **in addition to those specified by the
138
- # {file:SASS_REFERENCE.md#template_location-option `:template_location` option}.**
139
- # The first string in each pair is the location of the Sass/SCSS file,
140
- # the second is the location of the CSS file that it should be compiled to.
141
- def watch(individual_files = [])
142
- update_stylesheets(individual_files)
143
-
144
- begin
145
- require 'fssm'
146
- rescue LoadError => e
147
- e.message << "\n" <<
148
- if File.exists?(scope(".git"))
149
- 'Run "git submodule update --init" to get the recommended version.'
150
- else
151
- 'Run "gem install fssm" to get it.'
152
- end
153
- raise e
154
- end
155
-
156
- unless individual_files.empty? && FSSM::Backends::Default.name == "FSSM::Backends::FSEvents"
157
- # As of FSSM 0.1.4, it doesn't support FSevents on individual files,
158
- # but it also isn't smart enough to switch to polling itself.
159
- require 'fssm/backends/polling'
160
- Haml::Util.silence_warnings do
161
- FSSM::Backends.const_set(:Default, FSSM::Backends::Polling)
162
- end
163
- end
164
-
165
- # TODO: Keep better track of what depends on what
166
- # so we don't have to run a global update every time anything changes.
167
- FSSM.monitor do |mon|
168
- template_location_array.each do |template_location, css_location|
169
- mon.path template_location do |path|
170
- path.glob '**/*.s[ac]ss'
171
-
172
- path.update do |base, relative|
173
- run_template_modified File.join(base, relative)
174
- update_stylesheets(individual_files)
175
- end
176
-
177
- path.create do |base, relative|
178
- run_template_created File.join(base, relative)
179
- update_stylesheets(individual_files)
180
- end
181
-
182
- path.delete do |base, relative|
183
- run_template_deleted File.join(base, relative)
184
- css = File.join(css_location, relative.gsub(/\.s[ac]ss$/, '.css'))
185
- try_delete_css css
186
- update_stylesheets(individual_files)
187
- end
188
- end
189
- end
190
-
191
- individual_files.each do |template, css|
192
- mon.file template do |path|
193
- path.update do
194
- run_template_modified template
195
- update_stylesheets(individual_files)
196
- end
197
-
198
- path.create do
199
- run_template_created template
200
- update_stylesheets(individual_files)
201
- end
202
-
203
- path.delete do
204
- run_template_deleted template
205
- try_delete_css css
206
- update_stylesheets(individual_files)
207
- end
208
- end
209
- end
210
- end
211
- end
212
-
213
- private
214
-
215
- def update_stylesheet(filename, css)
216
- dir = File.dirname(css)
217
- unless File.exists?(dir)
218
- run_creating_directory dir
219
- FileUtils.mkdir_p dir
220
- end
221
-
222
- begin
223
- result = Sass::Files.tree_for(filename, engine_options(:css_filename => css, :filename => filename)).render
224
- rescue Exception => e
225
- run_compilation_error e, filename, css
226
- result = Sass::SyntaxError.exception_to_css(e, options)
227
- else
228
- run_updating_stylesheet filename, css
229
- end
230
-
231
- # Finally, write the file
232
- flag = 'w'
233
- flag = 'wb' if Haml::Util.windows? && options[:unix_newlines]
234
- File.open(css, flag) do |file|
235
- file.set_encoding(result.encoding) unless Haml::Util.ruby1_8?
236
- file.print(result)
237
- end
238
- end
239
-
240
- def try_delete_css(css)
241
- return unless File.exists?(css)
242
- run_deleting_css css
243
- File.delete css
244
- end
245
-
246
- def load_paths(opts = options)
247
- (opts[:load_paths] || []) + template_locations
248
- end
249
-
250
- def template_locations
251
- template_location_array.to_a.map {|l| l.first}
252
- end
253
-
254
- def css_locations
255
- template_location_array.to_a.map {|l| l.last}
256
- end
257
-
258
- def css_filename(name, path)
259
- "#{path}/#{name}".gsub(/\.s[ac]ss$/, '.css')
260
- end
261
-
262
- def forbid_update?(name)
263
- name.sub(/^.*\//, '')[0] == ?_
264
- end
265
-
266
- # Compass expects this to exist
267
- def stylesheet_needs_update?(css_file, template_file)
268
- StalenessChecker.stylesheet_needs_update?(css_file, template_file)
269
- end
270
- end
271
- end
272
-
273
- if defined?(ActionController)
274
- require 'sass/plugin/rails'
275
- elsif defined?(Merb::Plugins)
276
- require 'sass/plugin/merb'
277
- else
278
- require 'sass/plugin/generic'
279
- end