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
@@ -19,7 +19,7 @@ module Haml
19
19
  #
20
20
  # <div class="entry show">My Div</div>
21
21
  #
22
- # Then, in a stylesheet (shown here as {Sass}),
22
+ # Then, in a stylesheet (shown here as [Sass](http://sass-lang.com)),
23
23
  # you could refer to this specific action:
24
24
  #
25
25
  # .entry.show
@@ -3,90 +3,81 @@ require File.dirname(__FILE__) + '/../haml'
3
3
  require 'haml/engine'
4
4
  require 'rubygems'
5
5
  require 'cgi'
6
- require 'hpricot'
7
6
 
8
7
  module Haml
9
8
  class HTML
10
9
  # A module containing utility methods that every Hpricot node
11
10
  # should have.
12
11
  module Node
13
- # We have to do everything in `#included`
14
- # rather than including the methods in the module itself
15
- # because if we do that, they don't propagate to the already-defined subclasses
16
- # of the modules including this.
17
- def self.included(base)
18
- base.class_eval do
19
- # Whether this node has already been converted to Haml.
20
- # Only used for text nodes and elements.
21
- #
22
- # @return [Boolean]
23
- attr_accessor :converted_to_haml
24
-
25
- # Returns the Haml representation of the given node.
26
- #
27
- # @param tabs [Fixnum] The indentation level of the resulting Haml.
28
- # @option options (see Haml::HTML#initialize)
29
- def to_haml(tabs, options)
30
- return "" if converted_to_haml || to_s.strip.empty?
31
- text = uninterp(self.to_s)
32
- node = next_node
33
- while node.is_a?(::Hpricot::Elem) && node.name == "haml:loud"
34
- node.converted_to_haml = true
35
- text << '#{' <<
36
- CGI.unescapeHTML(node.inner_text).gsub(/\n\s*/, ' ').strip << '}'
37
-
38
- if node.next_node.is_a?(::Hpricot::Text)
39
- node = node.next_node
40
- text << uninterp(node.to_s)
41
- node.converted_to_haml = true
42
- end
43
-
44
- node = node.next_node
45
- end
46
- return parse_text_with_interpolation(text, tabs)
12
+ # Whether this node has already been converted to Haml.
13
+ # Only used for text nodes and elements.
14
+ #
15
+ # @return [Boolean]
16
+ attr_accessor :converted_to_haml
17
+
18
+ # Returns the Haml representation of the given node.
19
+ #
20
+ # @param tabs [Fixnum] The indentation level of the resulting Haml.
21
+ # @option options (see Haml::HTML#initialize)
22
+ def to_haml(tabs, options)
23
+ return "" if converted_to_haml || to_s.strip.empty?
24
+ text = uninterp(self.to_s)
25
+ node = next_node
26
+ while node.is_a?(::Hpricot::Elem) && node.name == "haml:loud"
27
+ node.converted_to_haml = true
28
+ text << '#{' <<
29
+ CGI.unescapeHTML(node.inner_text).gsub(/\n\s*/, ' ').strip << '}'
30
+
31
+ if node.next_node.is_a?(::Hpricot::Text)
32
+ node = node.next_node
33
+ text << uninterp(node.to_s)
34
+ node.converted_to_haml = true
47
35
  end
48
36
 
49
- private
50
-
51
- def erb_to_interpolation(text, options)
52
- return text unless options[:erb]
53
- text = CGI.escapeHTML(uninterp(text))
54
- %w[<haml:loud> </haml:loud>].each {|str| text.gsub!(CGI.escapeHTML(str), str)}
55
- ::Hpricot::XML(text).children.inject("") do |str, elem|
56
- if elem.is_a?(::Hpricot::Text)
57
- str + CGI.unescapeHTML(elem.to_s)
58
- else # <haml:loud> element
59
- str + '#{' + CGI.unescapeHTML(elem.innerText.strip) + '}'
60
- end
61
- end
62
- end
37
+ node = node.next_node
38
+ end
39
+ return parse_text_with_interpolation(text, tabs)
40
+ end
63
41
 
64
- def tabulate(tabs)
65
- ' ' * tabs
66
- end
42
+ private
67
43
 
68
- def uninterp(text)
69
- text.gsub('#{', '\#{') #'
44
+ def erb_to_interpolation(text, options)
45
+ return text unless options[:erb]
46
+ text = CGI.escapeHTML(uninterp(text))
47
+ %w[<haml:loud> </haml:loud>].each {|str| text.gsub!(CGI.escapeHTML(str), str)}
48
+ ::Hpricot::XML(text).children.inject("") do |str, elem|
49
+ if elem.is_a?(::Hpricot::Text)
50
+ str + CGI.unescapeHTML(elem.to_s)
51
+ else # <haml:loud> element
52
+ str + '#{' + CGI.unescapeHTML(elem.innerText.strip) + '}'
70
53
  end
54
+ end
55
+ end
71
56
 
72
- def attr_hash
73
- attributes.to_hash
74
- end
57
+ def tabulate(tabs)
58
+ ' ' * tabs
59
+ end
75
60
 
76
- def parse_text(text, tabs)
77
- parse_text_with_interpolation(uninterp(text), tabs)
78
- end
61
+ def uninterp(text)
62
+ text.gsub('#{', '\#{') #'
63
+ end
79
64
 
80
- def parse_text_with_interpolation(text, tabs)
81
- text.strip!
82
- return "" if text.empty?
65
+ def attr_hash
66
+ attributes.to_hash
67
+ end
83
68
 
84
- text.split("\n").map do |line|
85
- line.strip!
86
- "#{tabulate(tabs)}#{'\\' if Haml::Engine::SPECIAL_CHARACTERS.include?(line[0])}#{line}\n"
87
- end.join
88
- end
89
- end
69
+ def parse_text(text, tabs)
70
+ parse_text_with_interpolation(uninterp(text), tabs)
71
+ end
72
+
73
+ def parse_text_with_interpolation(text, tabs)
74
+ text.strip!
75
+ return "" if text.empty?
76
+
77
+ text.split("\n").map do |line|
78
+ line.strip!
79
+ "#{tabulate(tabs)}#{'\\' if Haml::Engine::SPECIAL_CHARACTERS.include?(line[0])}#{line}\n"
80
+ end.join
90
81
  end
91
82
  end
92
83
  end
@@ -107,16 +98,11 @@ module Hpricot
107
98
  end
108
99
  end
109
100
 
101
+ require 'hpricot'
102
+
110
103
  # @private
111
104
  HAML_TAGS = %w[haml:block haml:loud haml:silent]
112
105
 
113
- HAML_TAGS.each do |t|
114
- Hpricot::ElementContent[t] = {}
115
- Hpricot::ElementContent.keys.each do |key|
116
- Hpricot::ElementContent[t][key.hash] = true
117
- end
118
- end
119
-
120
106
  Hpricot::ElementContent.keys.each do |k|
121
107
  HAML_TAGS.each do |el|
122
108
  val = Hpricot::ElementContent[k]
@@ -124,6 +110,13 @@ Hpricot::ElementContent.keys.each do |k|
124
110
  end
125
111
  end
126
112
 
113
+ HAML_TAGS.each do |t|
114
+ Hpricot::ElementContent[t] = {}
115
+ Hpricot::ElementContent.keys.each do |key|
116
+ Hpricot::ElementContent[t][key.hash] = true
117
+ end
118
+ end
119
+
127
120
  module Haml
128
121
  # Converts HTML documents into Haml templates.
129
122
  # Depends on [Hpricot](http://github.com/whymirror/hpricot) for HTML parsing.
@@ -118,8 +118,8 @@ END
118
118
 
119
119
  names.map do |name|
120
120
  # Can't use || because someone might explicitly pass in false with a symbol
121
- sym_local = "_haml_locals[#{inspect_obj(name.to_sym)}]"
122
- str_local = "_haml_locals[#{inspect_obj(name.to_s)}]"
121
+ sym_local = "_haml_locals[#{name.to_sym.inspect}]"
122
+ str_local = "_haml_locals[#{name.to_s.inspect}]"
123
123
  "#{name} = #{sym_local}.nil? ? #{str_local} : #{sym_local}"
124
124
  end.join(';') + ';'
125
125
  end
@@ -320,7 +320,7 @@ END
320
320
  @to_merge.each do |type, val, tabs|
321
321
  case type
322
322
  when :text
323
- str << inspect_obj(val)[1...-1]
323
+ str << val.inspect[1...-1]
324
324
  mtabs += tabs
325
325
  when :script
326
326
  if mtabs != 0 && !@options[:ugly]
@@ -336,14 +336,12 @@ END
336
336
  end
337
337
  end
338
338
 
339
- unless str.empty?
340
- @precompiled <<
341
- if @options[:ugly]
342
- "_hamlout.buffer << \"#{str}\";"
343
- else
344
- "_hamlout.push_text(\"#{str}\", #{mtabs}, #{@dont_tab_up_next_text.inspect});"
345
- end
346
- end
339
+ @precompiled <<
340
+ if @options[:ugly]
341
+ "_hamlout.buffer << \"#{str}\";"
342
+ else
343
+ "_hamlout.push_text(\"#{str}\", #{mtabs}, #{@dont_tab_up_next_text.inspect});"
344
+ end
347
345
  @precompiled << "\n" * newlines
348
346
  @to_merge = []
349
347
  @dont_tab_up_next_text = false
@@ -579,17 +577,17 @@ END
579
577
  raise SyntaxError.new("Invalid tag: \"#{line}\".") unless match = line.scan(/%([-:\w]+)([-:\w\.\#]*)(.*)/)[0]
580
578
  tag_name, attributes, rest = match
581
579
  new_attributes_hash = old_attributes_hash = last_line = object_ref = nil
582
- attributes_hashes = {}
580
+ attributes_hashes = []
583
581
  while rest
584
582
  case rest[0]
585
583
  when ?{
586
584
  break if old_attributes_hash
587
585
  old_attributes_hash, rest, last_line = parse_old_attributes(rest)
588
- attributes_hashes[:old] = old_attributes_hash
586
+ attributes_hashes << [:old, old_attributes_hash]
589
587
  when ?(
590
588
  break if new_attributes_hash
591
589
  new_attributes_hash, rest, last_line = parse_new_attributes(rest)
592
- attributes_hashes[:new] = new_attributes_hash
590
+ attributes_hashes << [:new, new_attributes_hash]
593
591
  when ?[
594
592
  break if object_ref
595
593
  object_ref, rest = balance(rest, ?[, ?])
@@ -662,7 +660,7 @@ END
662
660
  if type == :static
663
661
  static_attributes[name] = val
664
662
  else
665
- dynamic_attributes << inspect_obj(name) << " => " << val << ","
663
+ dynamic_attributes << name.inspect << " => " << val << ","
666
664
  end
667
665
  end
668
666
  dynamic_attributes << "}"
@@ -697,7 +695,7 @@ END
697
695
 
698
696
  return name, [:static, content.first[1]] if content.size == 1
699
697
  return name, [:dynamic,
700
- '"' + content.map {|(t, v)| t == :str ? inspect_obj(v)[1...-1] : "\#{#{v}}"}.join + '"']
698
+ '"' + content.map {|(t, v)| t == :str ? v.inspect[1...-1] : "\#{#{v}}"}.join + '"']
701
699
  end
702
700
 
703
701
  # Parses a line that will render as an XHTML tag, and adds the code that will
@@ -757,21 +755,16 @@ END
757
755
  object_ref = "nil" if object_ref.nil? || @options[:suppress_eval]
758
756
 
759
757
  attributes = Precompiler.parse_class_and_id(attributes)
760
- attributes_list = []
761
-
762
- if attributes_hashes[:new]
763
- static_attributes, attributes_hash = attributes_hashes[:new]
764
- Buffer.merge_attrs(attributes, static_attributes) if static_attributes
765
- attributes_list << attributes_hash
766
- end
767
-
768
- if attributes_hashes[:old]
769
- static_attributes = parse_static_hash(attributes_hashes[:old])
758
+ attributes_hashes.map! do |syntax, attributes_hash|
759
+ if syntax == :old
760
+ static_attributes = parse_static_hash(attributes_hash)
761
+ attributes_hash = nil if static_attributes || @options[:suppress_eval]
762
+ else
763
+ static_attributes, attributes_hash = attributes_hash
764
+ end
770
765
  Buffer.merge_attrs(attributes, static_attributes) if static_attributes
771
- attributes_list << attributes_hashes[:old] unless static_attributes || @options[:suppress_eval]
772
- end
773
-
774
- attributes_list.compact!
766
+ attributes_hash
767
+ end.compact!
775
768
 
776
769
  raise SyntaxError.new("Illegal nesting: nesting within a self-closing tag is illegal.", @next_line.index) if block_opened? && self_closing
777
770
  raise SyntaxError.new("There's no Ruby code for #{action} to evaluate.", last_line - 1) if parse && value.empty?
@@ -789,7 +782,7 @@ END
789
782
  (nuke_inner_whitespace && block_opened?)
790
783
 
791
784
  # Check if we can render the tag directly to text and not process it in the buffer
792
- if object_ref == "nil" && attributes_list.empty? && !preserve_script
785
+ if object_ref == "nil" && attributes_hashes.empty? && !preserve_script
793
786
  tag_closed = !block_opened? && !self_closing && !parse
794
787
 
795
788
  open_tag = prerender_tag(tag_name, self_closing, attributes)
@@ -807,19 +800,19 @@ END
807
800
  return if tag_closed
808
801
  else
809
802
  flush_merged_text
810
- content = parse ? 'nil' : inspect_obj(value)
811
- if attributes_list.empty?
812
- attributes_list = ''
813
- elsif attributes_list.size == 1
814
- attributes_list = ", #{attributes_list.first}"
803
+ content = parse ? 'nil' : value.inspect
804
+ if attributes_hashes.empty?
805
+ attributes_hashes = ''
806
+ elsif attributes_hashes.size == 1
807
+ attributes_hashes = ", #{attributes_hashes.first}"
815
808
  else
816
- attributes_list = ", (#{attributes_list.join(").merge(")})"
809
+ attributes_hashes = ", (#{attributes_hashes.join(").merge(")})"
817
810
  end
818
811
 
819
812
  args = [tag_name, self_closing, !block_opened?, preserve_tag, escape_html,
820
813
  attributes, nuke_outer_whitespace, nuke_inner_whitespace
821
- ].map {|v| inspect_obj(v)}.join(', ')
822
- push_silent "_hamlout.open_tag(#{args}, #{object_ref}, #{content}#{attributes_list})"
814
+ ].map { |v| v.inspect }.join(', ')
815
+ push_silent "_hamlout.open_tag(#{args}, #{object_ref}, #{content}#{attributes_hashes})"
823
816
  @dont_tab_up_next_text = @dont_indent_next_line = dont_indent_next_line
824
817
  end
825
818
 
@@ -1024,14 +1017,14 @@ END
1024
1017
 
1025
1018
  def unescape_interpolation(str, opts = {})
1026
1019
  res = ''
1027
- rest = Haml::Shared.handle_interpolation inspect_obj(str) do |scan|
1020
+ rest = Haml::Shared.handle_interpolation str.dump do |scan|
1028
1021
  escapes = (scan[2].size - 1) / 2
1029
1022
  res << scan.matched[0...-3 - escapes]
1030
1023
  if escapes % 2 == 1
1031
1024
  res << '#{'
1032
1025
  else
1033
1026
  content = eval('"' + balance(scan, ?{, ?}, 1)[0][0...-1] + '"')
1034
- content = "Haml::Helpers.html_escape((#{content}))" if opts[:escape_html]
1027
+ content = "Haml::Helpers.html_escape(#{content})" if opts[:escape_html]
1035
1028
  res << '#{' + content + "}"# Use eval to get rid of string escapes
1036
1029
  end
1037
1030
  end
@@ -1,6 +1,6 @@
1
1
  if Haml::Util.ap_geq_3? && !Haml::Util.ap_geq?("3.0.0.beta4")
2
2
  raise <<ERROR
3
- Haml and Sass no longer support Rails 3 versions before beta 4.
3
+ Haml no longer supports Rails 3 versions before beta 4.
4
4
  Please upgrade to Rails 3.0.0.beta4 or later.
5
5
  ERROR
6
6
  end
@@ -8,12 +8,10 @@ end
8
8
  # Rails 3.0.0.beta.2+
9
9
  if defined?(ActiveSupport) && Haml::Util.has?(:public_method, ActiveSupport, :on_load)
10
10
  require 'haml/template/options'
11
- require 'sass/plugin/configuration'
11
+ autoload(:Sass, 'sass/rails3_shim')
12
12
  ActiveSupport.on_load(:before_initialize) do
13
- require 'sass'
14
- require 'sass/plugin'
15
-
16
- # Haml requires AV, but Sass doesn't
13
+ # resolve autoload if it looks like they're using Sass without options
14
+ Sass if File.exist?(File.join(Rails.root, 'public/stylesheets/sass'))
17
15
  ActiveSupport.on_load(:action_view) do
18
16
  Haml.init_rails(binding)
19
17
  end
@@ -2,17 +2,12 @@
2
2
  # using the > 2.0.1 template handler API.
3
3
 
4
4
  module Haml
5
- # In Rails 3.1+, template handlers don't inherit from anything. In <= 3.0, they do.
6
- # To avoid messy logic figuring this out, we just inherit from whatever the ERB handler does.
7
- class Plugin < Haml::Util.av_template_class(:Handlers)::ERB.superclass
8
- if ((defined?(ActionView::TemplateHandlers) &&
9
- defined?(ActionView::TemplateHandlers::Compilable)) ||
10
- (defined?(ActionView::Template) &&
11
- defined?(ActionView::Template::Handlers) &&
12
- defined?(ActionView::Template::Handlers::Compilable))) &&
13
- # In Rails 3.1+, we don't need to include Compilable.
14
- Haml::Util.av_template_class(:Handlers)::ERB.include?(
15
- Haml::Util.av_template_class(:Handlers)::Compilable)
5
+ class Plugin < Haml::Util.av_template_class(:Handler)
6
+ if (defined?(ActionView::TemplateHandlers) &&
7
+ defined?(ActionView::TemplateHandlers::Compilable)) ||
8
+ (defined?(ActionView::Template) &&
9
+ defined?(ActionView::Template::Handlers) &&
10
+ defined?(ActionView::Template::Handlers::Compilable))
16
11
  include Haml::Util.av_template_class(:Handlers)::Compilable
17
12
  end
18
13
 
@@ -34,11 +29,6 @@ module Haml
34
29
  Haml::Engine.new(source, options).send(:precompiled_with_ambles, [])
35
30
  end
36
31
 
37
- # In Rails 3.1+, #call takes the place of #compile
38
- def self.call(template)
39
- new.compile(template)
40
- end
41
-
42
32
  def cache_fragment(block, name = {}, options = nil)
43
33
  @view.fragment_for(block, name, options) do
44
34
  eval("_hamlout.buffer", block.binding)
@@ -6,7 +6,6 @@ require 'strscan'
6
6
  require 'rbconfig'
7
7
 
8
8
  require 'haml/root'
9
- require 'haml/util/subset_map'
10
9
 
11
10
  module Haml
12
11
  # A module containing various useful functions.
@@ -17,11 +16,6 @@ module Haml
17
16
  # @api public
18
17
  RUBY_VERSION = ::RUBY_VERSION.split(".").map {|s| s.to_i}
19
18
 
20
- # The Ruby engine we're running under. Defaults to `"ruby"`
21
- # if the top-level constant is undefined.
22
- # @api public
23
- RUBY_ENGINE = defined?(::RUBY_ENGINE) ? ::RUBY_ENGINE : "ruby"
24
-
25
19
  # Returns the path of a file relative to the Haml root directory.
26
20
  #
27
21
  # @param file [String] The filename relative to the Haml root
@@ -31,11 +25,10 @@ module Haml
31
25
  end
32
26
 
33
27
  # Converts an array of `[key, value]` pairs to a hash.
34
- # For example:
35
- #
36
- # to_hash([[:foo, "bar"], [:baz, "bang"]])
37
- # #=> {:foo => "bar", :baz => "bang"}
38
28
  #
29
+ # @example
30
+ # to_hash([[:foo, "bar"], [:baz, "bang"]])
31
+ # #=> {:foo => "bar", :baz => "bang"}
39
32
  # @param arr [Array<(Object, Object)>] An array of pairs
40
33
  # @return [Hash] A hash
41
34
  def to_hash(arr)
@@ -43,11 +36,10 @@ module Haml
43
36
  end
44
37
 
45
38
  # Maps the keys in a hash according to a block.
46
- # For example:
47
- #
48
- # map_keys({:foo => "bar", :baz => "bang"}) {|k| k.to_s}
49
- # #=> {"foo" => "bar", "baz" => "bang"}
50
39
  #
40
+ # @example
41
+ # map_keys({:foo => "bar", :baz => "bang"}) {|k| k.to_s}
42
+ # #=> {"foo" => "bar", "baz" => "bang"}
51
43
  # @param hash [Hash] The hash to map
52
44
  # @yield [key] A block in which the keys are transformed
53
45
  # @yieldparam key [Object] The key that should be mapped
@@ -60,11 +52,10 @@ module Haml
60
52
  end
61
53
 
62
54
  # Maps the values in a hash according to a block.
63
- # For example:
64
- #
65
- # map_values({:foo => "bar", :baz => "bang"}) {|v| v.to_sym}
66
- # #=> {:foo => :bar, :baz => :bang}
67
55
  #
56
+ # @example
57
+ # map_values({:foo => "bar", :baz => "bang"}) {|v| v.to_sym}
58
+ # #=> {:foo => :bar, :baz => :bang}
68
59
  # @param hash [Hash] The hash to map
69
60
  # @yield [value] A block in which the values are transformed
70
61
  # @yieldparam value [Object] The value that should be mapped
@@ -77,11 +68,10 @@ module Haml
77
68
  end
78
69
 
79
70
  # Maps the key-value pairs of a hash according to a block.
80
- # For example:
81
- #
82
- # map_hash({:foo => "bar", :baz => "bang"}) {|k, v| [k.to_s, v.to_sym]}
83
- # #=> {"foo" => :bar, "baz" => :bang}
84
71
  #
72
+ # @example
73
+ # map_hash({:foo => "bar", :baz => "bang"}) {|k, v| [k.to_s, v.to_sym]}
74
+ # #=> {"foo" => :bar, "baz" => :bang}
85
75
  # @param hash [Hash] The hash to map
86
76
  # @yield [key, value] A block in which the key-value pairs are transformed
87
77
  # @yieldparam [key] The hash key
@@ -96,11 +86,10 @@ module Haml
96
86
 
97
87
  # Computes the powerset of the given array.
98
88
  # This is the set of all subsets of the array.
99
- # For example:
100
- #
101
- # powerset([1, 2, 3]) #=>
102
- # Set[Set[], Set[1], Set[2], Set[3], Set[1, 2], Set[2, 3], Set[1, 3], Set[1, 2, 3]]
103
89
  #
90
+ # @example
91
+ # powerset([1, 2, 3]) #=>
92
+ # Set[Set[], Set[1], Set[2], Set[3], Set[1, 2], Set[2, 3], Set[1, 3], Set[1, 2, 3]]
104
93
  # @param arr [Enumerable]
105
94
  # @return [Set<Set>] The subsets of `arr`
106
95
  def powerset(arr)
@@ -127,11 +116,10 @@ module Haml
127
116
 
128
117
  # Concatenates all strings that are adjacent in an array,
129
118
  # while leaving other elements as they are.
130
- # For example:
131
- #
132
- # merge_adjacent_strings([1, "foo", "bar", 2, "baz"])
133
- # #=> [1, "foobar", 2, "baz"]
134
119
  #
120
+ # @example
121
+ # merge_adjacent_strings([1, "foo", "bar", 2, "baz"])
122
+ # #=> [1, "foobar", 2, "baz"]
135
123
  # @param enum [Enumerable]
136
124
  # @return [Array] The enumerable with strings merged
137
125
  def merge_adjacent_strings(enum)
@@ -194,11 +182,11 @@ module Haml
194
182
  # @return [Array<Arrays>]
195
183
  #
196
184
  # @example
197
- # paths([[1, 2], [3, 4], [5]]) #=>
198
- # # [[1, 3, 5],
199
- # # [2, 3, 5],
200
- # # [1, 4, 5],
201
- # # [2, 4, 5]]
185
+ # paths([[1, 2], [3, 4], [5]]) #=>
186
+ # # [[1, 3, 5],
187
+ # # [2, 3, 5],
188
+ # # [1, 4, 5],
189
+ # # [2, 4, 5]]
202
190
  def paths(arrs)
203
191
  arrs.inject([[]]) do |paths, arr|
204
192
  flatten(arr.map {|e| paths.map {|path| path + [e]}}, 1)
@@ -274,6 +262,43 @@ module Haml
274
262
  version_gt(v1, v2) || !version_gt(v2, v1)
275
263
  end
276
264
 
265
+ # A wrapper for `Marshal.dump` that calls `#_before_dump` on the object
266
+ # before dumping it, `#_after_dump` afterwards.
267
+ # It also calls `#_around_dump` and passes it a block in which the object is dumped.
268
+ #
269
+ # If any of these methods are undefined, they are not called.
270
+ #
271
+ # @param obj [Object] The object to dump.
272
+ # @return [String] The dumped data.
273
+ def dump(obj)
274
+ obj._before_dump if obj.respond_to?(:_before_dump)
275
+ return Marshal.dump(obj) unless obj.respond_to?(:_around_dump)
276
+ res = nil
277
+ obj._around_dump {res = Marshal.dump(obj)}
278
+ res
279
+ ensure
280
+ obj._after_dump if obj.respond_to?(:_after_dump)
281
+ end
282
+
283
+ # A wrapper for `Marshal.load` that calls `#_after_load` on the object
284
+ # after loading it, if it's defined.
285
+ #
286
+ # @param data [String] The data to load.
287
+ # @return [Object] The loaded object.
288
+ def load(data)
289
+ obj = Marshal.load(data)
290
+ obj._after_load if obj.respond_to?(:_after_load)
291
+ obj
292
+ end
293
+
294
+ # Throws a NotImplementedError for an abstract method.
295
+ #
296
+ # @param obj [Object] `self`
297
+ # @raise [NotImplementedError]
298
+ def abstract(obj)
299
+ raise NotImplementedError.new("#{obj.class} must implement ##{caller_info[2]}")
300
+ end
301
+
277
302
  # Silence all output to STDERR within a block.
278
303
  #
279
304
  # @yield A block in which no output will be printed to STDERR
@@ -304,6 +329,35 @@ module Haml
304
329
  warn(msg)
305
330
  end
306
331
 
332
+ # Try loading Sass. If the `sass` gem isn't installed,
333
+ # print a warning and load from the vendored gem.
334
+ #
335
+ # @return [Boolean] True if Sass was successfully loaded from the `sass` gem,
336
+ # false otherwise.
337
+ def try_sass
338
+ return true if defined?(::SASS_BEGUN_TO_LOAD)
339
+ begin
340
+ require 'sass/version'
341
+ loaded = Sass.respond_to?(:version) && Sass.version[:major] &&
342
+ Sass.version[:minor] && ((Sass.version[:major] > 3 && Sass.version[:minor] > 1) ||
343
+ ((Sass.version[:major] == 3 && Sass.version[:minor] == 1) &&
344
+ (Sass.version[:prerelease] || Sass.version[:name] != "Bleeding Edge")))
345
+ rescue LoadError => e
346
+ loaded = false
347
+ end
348
+
349
+ unless loaded
350
+ haml_warn(<<WARNING)
351
+ Sass is in the process of being separated from Haml,
352
+ and will no longer be bundled at all in Haml 3.2.0.
353
+ Please install the 'sass' gem if you want to use Sass.
354
+ WARNING
355
+ $".delete('sass/version')
356
+ $LOAD_PATH.unshift(scope("vendor/sass/lib"))
357
+ end
358
+ loaded
359
+ end
360
+
307
361
  ## Cross Rails Version Compatibility
308
362
 
309
363
  # Returns the root of the Rails application,
@@ -420,25 +474,13 @@ module Haml
420
474
  RbConfig::CONFIG['host_os'] =~ /mswin|windows|mingw/i
421
475
  end
422
476
 
423
- # Whether or not this is running on IronRuby.
424
- #
425
- # @return [Boolean]
426
- def ironruby?
427
- RUBY_ENGINE == "ironruby"
428
- end
429
-
430
477
  ## Cross-Ruby-Version Compatibility
431
478
 
432
479
  # Whether or not this is running under Ruby 1.8 or lower.
433
480
  #
434
- # Note that IronRuby counts as Ruby 1.8,
435
- # because it doesn't support the Ruby 1.9 encoding API.
436
- #
437
481
  # @return [Boolean]
438
482
  def ruby1_8?
439
- # IronRuby says its version is 1.9, but doesn't support any of the encoding APIs.
440
- # We have to fall back to 1.8 behavior.
441
- ironruby? || (Haml::Util::RUBY_VERSION[0] == 1 && Haml::Util::RUBY_VERSION[1] < 9)
483
+ Haml::Util::RUBY_VERSION[0] == 1 && Haml::Util::RUBY_VERSION[1] < 9
442
484
  end
443
485
 
444
486
  # Whether or not this is running under Ruby 1.8.6 or lower.
@@ -488,7 +530,7 @@ MSG
488
530
  # Like {\#check\_encoding}, but also checks for a Ruby-style `-# coding:` comment
489
531
  # at the beginning of the template and uses that encoding if it exists.
490
532
  #
491
- # The Sass encoding rules are simple.
533
+ # The Haml encoding rules are simple.
492
534
  # If a `-# coding:` comment exists,
493
535
  # we assume that that's the original encoding of the document.
494
536
  # Otherwise, we use whatever encoding Ruby has.
@@ -517,51 +559,6 @@ MSG
517
559
  return check_encoding(str, &block)
518
560
  end
519
561
 
520
- # Like {\#check\_encoding}, but also checks for a `@charset` declaration
521
- # at the beginning of the file and uses that encoding if it exists.
522
- #
523
- # The Sass encoding rules are simple.
524
- # If a `@charset` declaration exists,
525
- # we assume that that's the original encoding of the document.
526
- # Otherwise, we use whatever encoding Ruby has.
527
- # Then we convert that to UTF-8 to process internally.
528
- # The UTF-8 end result is what's returned by this method.
529
- #
530
- # @param str [String] The string of which to check the encoding
531
- # @yield [msg] A block in which an encoding error can be raised.
532
- # Only yields if there is an encoding error
533
- # @yieldparam msg [String] The error message to be raised
534
- # @return [(String, Encoding)] The original string encoded as UTF-8,
535
- # and the source encoding of the string (or `nil` under Ruby 1.8)
536
- # @raise [Encoding::UndefinedConversionError] if the source encoding
537
- # cannot be converted to UTF-8
538
- # @raise [ArgumentError] if the document uses an unknown encoding with `@charset`
539
- def check_sass_encoding(str, &block)
540
- return check_encoding(str, &block), nil if ruby1_8?
541
- # We allow any printable ASCII characters but double quotes in the charset decl
542
- bin = str.dup.force_encoding("BINARY")
543
- encoding = Haml::Util::ENCODINGS_TO_CHECK.find do |enc|
544
- bin =~ Haml::Util::CHARSET_REGEXPS[enc]
545
- end
546
- charset, bom = $1, $2
547
- if charset
548
- charset = charset.force_encoding(encoding).encode("UTF-8")
549
- if endianness = encoding[/[BL]E$/]
550
- begin
551
- Encoding.find(charset + endianness)
552
- charset << endianness
553
- rescue ArgumentError # Encoding charset + endianness doesn't exist
554
- end
555
- end
556
- str.force_encoding(charset)
557
- elsif bom
558
- str.force_encoding(encoding)
559
- end
560
-
561
- str = check_encoding(str, &block)
562
- return str.encode("UTF-8"), str.encoding
563
- end
564
-
565
562
  unless ruby1_8?
566
563
  # @private
567
564
  def _enc(string, encoding)
@@ -673,19 +670,6 @@ MSG
673
670
  set1.to_a.uniq.sort_by {|e| e.hash}.eql?(set2.to_a.uniq.sort_by {|e| e.hash})
674
671
  end
675
672
 
676
- # Like `Object#inspect`, but preserves non-ASCII characters rather than escaping them under Ruby 1.9.2.
677
- # This is necessary so that the precompiled Haml template can be `#encode`d into `@options[:encoding]`
678
- # before being evaluated.
679
- #
680
- # @param obj {Object}
681
- # @return {String}
682
- def inspect_obj(obj)
683
- return obj.inspect unless version_geq(::RUBY_VERSION, "1.9.2")
684
- return ':' + inspect_obj(obj.to_s) if obj.is_a?(Symbol)
685
- return obj.inspect unless obj.is_a?(String)
686
- '"' + obj.gsub(/[\x00-\x7F]+/) {|s| s.inspect[1...-1]} + '"'
687
- end
688
-
689
673
  ## Static Method Stuff
690
674
 
691
675
  # The context in which the ERB for \{#def\_static\_method} will be run.