haml 2.0.10 → 2.2.0

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 (107) hide show
  1. data/.yardopts +5 -0
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +347 -0
  4. data/Rakefile +124 -19
  5. data/VERSION +1 -1
  6. data/VERSION_NAME +1 -0
  7. data/extra/haml-mode.el +397 -78
  8. data/extra/sass-mode.el +148 -36
  9. data/extra/update_watch.rb +13 -0
  10. data/lib/haml.rb +15 -993
  11. data/lib/haml/buffer.rb +131 -84
  12. data/lib/haml/engine.rb +129 -97
  13. data/lib/haml/error.rb +7 -7
  14. data/lib/haml/exec.rb +127 -42
  15. data/lib/haml/filters.rb +107 -42
  16. data/lib/haml/helpers.rb +210 -156
  17. data/lib/haml/helpers/action_view_extensions.rb +34 -39
  18. data/lib/haml/helpers/action_view_mods.rb +132 -139
  19. data/lib/haml/html.rb +77 -65
  20. data/lib/haml/precompiler.rb +404 -213
  21. data/lib/haml/shared.rb +78 -0
  22. data/lib/haml/template.rb +14 -14
  23. data/lib/haml/template/patch.rb +2 -2
  24. data/lib/haml/template/plugin.rb +2 -3
  25. data/lib/haml/util.rb +211 -6
  26. data/lib/haml/version.rb +30 -13
  27. data/lib/sass.rb +7 -856
  28. data/lib/sass/css.rb +169 -161
  29. data/lib/sass/engine.rb +344 -328
  30. data/lib/sass/environment.rb +79 -0
  31. data/lib/sass/error.rb +33 -11
  32. data/lib/sass/files.rb +139 -0
  33. data/lib/sass/plugin.rb +160 -117
  34. data/lib/sass/plugin/merb.rb +7 -6
  35. data/lib/sass/plugin/rails.rb +5 -6
  36. data/lib/sass/repl.rb +58 -0
  37. data/lib/sass/script.rb +59 -0
  38. data/lib/sass/script/bool.rb +17 -0
  39. data/lib/sass/script/color.rb +183 -0
  40. data/lib/sass/script/funcall.rb +50 -0
  41. data/lib/sass/script/functions.rb +198 -0
  42. data/lib/sass/script/lexer.rb +178 -0
  43. data/lib/sass/script/literal.rb +177 -0
  44. data/lib/sass/script/node.rb +14 -0
  45. data/lib/sass/script/number.rb +381 -0
  46. data/lib/sass/script/operation.rb +45 -0
  47. data/lib/sass/script/parser.rb +172 -0
  48. data/lib/sass/script/string.rb +12 -0
  49. data/lib/sass/script/unary_operation.rb +34 -0
  50. data/lib/sass/script/variable.rb +31 -0
  51. data/lib/sass/tree/comment_node.rb +73 -10
  52. data/lib/sass/tree/debug_node.rb +30 -0
  53. data/lib/sass/tree/directive_node.rb +42 -17
  54. data/lib/sass/tree/file_node.rb +41 -0
  55. data/lib/sass/tree/for_node.rb +48 -0
  56. data/lib/sass/tree/if_node.rb +54 -0
  57. data/lib/sass/tree/mixin_def_node.rb +29 -0
  58. data/lib/sass/tree/mixin_node.rb +48 -0
  59. data/lib/sass/tree/node.rb +214 -11
  60. data/lib/sass/tree/prop_node.rb +109 -0
  61. data/lib/sass/tree/rule_node.rb +178 -51
  62. data/lib/sass/tree/variable_node.rb +34 -0
  63. data/lib/sass/tree/while_node.rb +31 -0
  64. data/test/haml/engine_test.rb +331 -36
  65. data/test/haml/helper_test.rb +12 -1
  66. data/test/haml/results/content_for_layout.xhtml +0 -3
  67. data/test/haml/results/filters.xhtml +2 -0
  68. data/test/haml/results/list.xhtml +1 -1
  69. data/test/haml/template_test.rb +7 -2
  70. data/test/haml/templates/content_for_layout.haml +0 -2
  71. data/test/haml/templates/list.haml +1 -1
  72. data/test/haml/util_test.rb +92 -0
  73. data/test/sass/css2sass_test.rb +69 -24
  74. data/test/sass/engine_test.rb +586 -64
  75. data/test/sass/functions_test.rb +125 -0
  76. data/test/sass/more_results/more1.css +9 -0
  77. data/test/sass/more_results/more1_with_line_comments.css +26 -0
  78. data/test/sass/more_results/more_import.css +29 -0
  79. data/test/sass/more_templates/_more_partial.sass +2 -0
  80. data/test/sass/more_templates/more1.sass +23 -0
  81. data/test/sass/more_templates/more_import.sass +11 -0
  82. data/test/sass/plugin_test.rb +81 -28
  83. data/test/sass/results/line_numbers.css +49 -0
  84. data/test/sass/results/{constants.css → script.css} +4 -4
  85. data/test/sass/results/subdir/subdir.css +2 -0
  86. data/test/sass/results/units.css +11 -0
  87. data/test/sass/script_test.rb +258 -0
  88. data/test/sass/templates/import.sass +1 -1
  89. data/test/sass/templates/importee.sass +7 -2
  90. data/test/sass/templates/line_numbers.sass +13 -0
  91. data/test/sass/templates/{constants.sass → script.sass} +11 -10
  92. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  93. data/test/sass/templates/subdir/subdir.sass +2 -2
  94. data/test/sass/templates/units.sass +11 -0
  95. data/test/test_helper.rb +14 -0
  96. metadata +77 -19
  97. data/FAQ +0 -138
  98. data/README.rdoc +0 -319
  99. data/lib/sass/constant.rb +0 -216
  100. data/lib/sass/constant/color.rb +0 -101
  101. data/lib/sass/constant/literal.rb +0 -54
  102. data/lib/sass/constant/nil.rb +0 -9
  103. data/lib/sass/constant/number.rb +0 -87
  104. data/lib/sass/constant/operation.rb +0 -30
  105. data/lib/sass/constant/string.rb +0 -22
  106. data/lib/sass/tree/attr_node.rb +0 -57
  107. data/lib/sass/tree/value_node.rb +0 -20
@@ -1,84 +1,97 @@
1
1
  module Haml
2
- # This class is used only internally. It holds the buffer of XHTML that
3
- # is eventually output by Haml::Engine's to_html method. It's called
4
- # from within the precompiled code, and helps reduce the amount of
5
- # processing done within instance_eval'd code.
2
+ # This class is used only internally. It holds the buffer of HTML that
3
+ # is eventually output as the resulting document.
4
+ # It's called from within the precompiled code,
5
+ # and helps reduce the amount of processing done within `instance_eval`ed code.
6
6
  class Buffer
7
7
  include Haml::Helpers
8
+ include Haml::Util
8
9
 
9
- # The string that holds the compiled XHTML. This is aliased as
10
- # _erbout for compatibility with ERB-specific code.
10
+ # The string that holds the compiled HTML. This is aliased as
11
+ # `_erbout` for compatibility with ERB-specific code.
12
+ #
13
+ # @return [String]
11
14
  attr_accessor :buffer
12
15
 
13
- # The options hash passed in from Haml::Engine.
16
+ # The options hash passed in from {Haml::Engine}.
17
+ #
18
+ # @return [Hash<String, Object>]
19
+ # @see Haml::Engine#options_for_buffer
14
20
  attr_accessor :options
15
21
 
16
- # The Buffer for the enclosing Haml document.
22
+ # The {Buffer} for the enclosing Haml document.
17
23
  # This is set for partials and similar sorts of nested templates.
18
- # It's nil at the top level (see #toplevel?).
24
+ # It's `nil` at the top level (see \{#toplevel?}).
25
+ #
26
+ # @return [Buffer]
19
27
  attr_accessor :upper
20
28
 
21
29
  # nil if there's no capture_haml block running,
22
30
  # and the position at which it's beginning the capture if there is one.
31
+ #
32
+ # @return [Fixnum, nil]
23
33
  attr_accessor :capture_position
24
34
 
25
- # See #active?
35
+ # @return [Boolean]
36
+ # @see #active?
26
37
  attr_writer :active
27
38
 
28
- # True if the format is XHTML
39
+ # @return [Boolean] Whether or not the format is XHTML
29
40
  def xhtml?
30
41
  not html?
31
42
  end
32
43
 
33
- # True if the format is any flavor of HTML
44
+ # @return [Boolean] Whether or not the format is any flavor of HTML
34
45
  def html?
35
46
  html4? or html5?
36
47
  end
37
48
 
38
- # True if the format is HTML4
49
+ # @return [Boolean] Whether or not the format is HTML4
39
50
  def html4?
40
51
  @options[:format] == :html4
41
52
  end
42
53
 
43
- # True if the format is HTML5
54
+ # @return [Boolean] Whether or not the format is HTML5.
44
55
  def html5?
45
56
  @options[:format] == :html5
46
57
  end
47
58
 
48
- # True if this buffer is a top-level template,
49
- # as opposed to a nested partial.
59
+ # @return [Boolean] Whether or not this buffer is a top-level template,
60
+ # as opposed to a nested partial
50
61
  def toplevel?
51
62
  upper.nil?
52
63
  end
53
64
 
54
- # True if this buffer is currently being used to render a Haml template.
55
- # However, this returns false if a subtemplate is being rendered,
65
+ # Whether or not this buffer is currently being used to render a Haml template.
66
+ # Returns `false` if a subtemplate is being rendered,
56
67
  # even if it's a subtemplate of this buffer's template.
68
+ #
69
+ # @return [Boolean]
57
70
  def active?
58
71
  @active
59
72
  end
60
73
 
61
- # Gets the current tabulation of the document.
74
+ # @return [Fixnum] The current indentation level of the document
62
75
  def tabulation
63
76
  @real_tabs + @tabulation
64
77
  end
65
78
 
66
79
  # Sets the current tabulation of the document.
80
+ #
81
+ # @param val [Fixnum] The new tabulation
67
82
  def tabulation=(val)
68
83
  val = val - @real_tabs
69
84
  @tabulation = val > -1 ? val : 0
70
85
  end
71
86
 
72
- # Creates a new buffer.
87
+ # @param upper [Buffer] The parent buffer
88
+ # @param options [Hash<Symbol, Object>] An options hash.
89
+ # See {Haml::Engine#options\_for\_buffer}
73
90
  def initialize(upper = nil, options = {})
74
91
  @active = true
75
92
  @upper = upper
76
- @options = {
77
- :attr_wrapper => "'",
78
- :ugly => false,
79
- :format => :xhtml
80
- }.merge options
81
- @buffer = ""
93
+ @options = options
94
+ @buffer = ruby1_8? ? "" : "".encode(Encoding.find(options[:encoding]))
82
95
  @tabulation = 0
83
96
 
84
97
  # The number of tabs that Engine thinks we should have
@@ -86,10 +99,15 @@ module Haml
86
99
  @real_tabs = 0
87
100
  end
88
101
 
89
- # Renders +text+ with the proper tabulation. This also deals with
90
- # making a possible one-line tag one line or not.
91
- def push_text(text, dont_tab_up = false, tab_change = 0)
92
- if @tabulation > 0 && !@options[:ugly]
102
+ # Appends text to the buffer, properly tabulated.
103
+ # Also modifies the document's indentation.
104
+ #
105
+ # @param text [String] The text to append
106
+ # @param tab_change [Fixnum] The number of tabs by which to increase
107
+ # or decrease the document's indentation
108
+ # @param dont_tab_up [Boolean] If true, don't indent the first line of `text`
109
+ def push_text(text, tab_change, dont_tab_up)
110
+ if @tabulation > 0
93
111
  # Have to push every line in by the extra user set tabulation.
94
112
  # Don't push lines with just whitespace, though,
95
113
  # because that screws up precompiled indentation.
@@ -99,65 +117,85 @@ module Haml
99
117
 
100
118
  @buffer << text
101
119
  @real_tabs += tab_change
102
- @dont_tab_up_next_line = false
103
120
  end
104
121
 
105
- # Properly formats the output of a script that was run in the
106
- # instance_eval.
107
- def push_script(result, preserve_script, in_tag = false, preserve_tag = false,
108
- escape_html = false, nuke_inner_whitespace = false)
109
- tabulation = @real_tabs
110
-
111
- result = result.to_s.rstrip
112
- result = result.lstrip if nuke_inner_whitespace
113
- result = html_escape(result) if escape_html
122
+ # Modifies the indentation of the document.
123
+ #
124
+ # @param tab_change [Fixnum] The number of tabs by which to increase
125
+ # or decrease the document's indentation
126
+ def adjust_tabs(tab_change)
127
+ @real_tabs += tab_change
128
+ end
114
129
 
115
- if preserve_tag
130
+ Haml::Util.def_static_method(self, :format_script, [:result],
131
+ :preserve_script, :in_tag, :preserve_tag, :escape_html,
132
+ :nuke_inner_whitespace, :interpolated, :ugly, <<RUBY)
133
+ <% unless ugly %>
134
+ # If we're interpolated,
135
+ # then the custom tabulation is handled in #push_text.
136
+ # The easiest way to avoid it here is to reset @tabulation.
137
+ <% if interpolated %>
138
+ old_tabulation = @tabulation
139
+ @tabulation = 0
140
+ <% end %>
141
+
142
+ tabulation = @real_tabs
143
+ result = result.to_s.<% if nuke_inner_whitespace %>strip<% else %>rstrip<% end %>
144
+ <% else %>
145
+ result = result.to_s<% if nuke_inner_whitespace %>.strip<% end %>
146
+ <% end %>
147
+
148
+ <% if escape_html %> result = html_escape(result) <% end %>
149
+
150
+ <% if preserve_tag %>
116
151
  result = Haml::Helpers.preserve(result)
117
- elsif preserve_script
152
+ <% elsif preserve_script %>
118
153
  result = Haml::Helpers.find_and_preserve(result, options[:preserve])
119
- end
120
-
121
- has_newline = result.include?("\n")
122
- if in_tag && !nuke_inner_whitespace && (@options[:ugly] || !has_newline || preserve_tag)
123
- @buffer << result
124
- @real_tabs -= 1
125
- return
126
- end
127
-
128
- @buffer << "\n" if in_tag && !nuke_inner_whitespace
129
-
130
- # Precompiled tabulation may be wrong
131
- if @tabulation > 0 && !in_tag
132
- result = tabs + result
133
- end
134
-
135
- if has_newline && !@options[:ugly]
136
- result = result.gsub "\n", "\n" + tabs(tabulation)
137
-
138
- # Add tabulation if it wasn't precompiled
139
- result = tabs(tabulation) + result if in_tag && !nuke_inner_whitespace
140
- end
141
- @buffer << "#{result}"
142
- @buffer << "\n" unless nuke_inner_whitespace
143
-
144
- if in_tag && !nuke_inner_whitespace
145
- # We never get here if @options[:ugly] is true
146
- @buffer << tabs(tabulation-1)
147
- @real_tabs -= 1
148
- end
149
- nil
150
- end
151
-
152
- # Takes the various information about the opening tag for an
153
- # element, formats it, and adds it to the buffer.
154
+ <% end %>
155
+
156
+ <% if ugly %>
157
+ return result
158
+ <% else %>
159
+
160
+ has_newline = result.include?("\\n")
161
+ <% if in_tag && !nuke_inner_whitespace %>
162
+ <% unless preserve_tag %> if !has_newline <% end %>
163
+ @real_tabs -= 1
164
+ <% if interpolated %> @tabulation = old_tabulation <% end %>
165
+ return result
166
+ <% unless preserve_tag %> end <% end %>
167
+ <% end %>
168
+
169
+ # Precompiled tabulation may be wrong
170
+ <% if !interpolated && !in_tag %>
171
+ result = tabs + result if @tabulation > 0
172
+ <% end %>
173
+
174
+ if has_newline
175
+ result = result.gsub "\\n", "\\n" + tabs(tabulation)
176
+
177
+ # Add tabulation if it wasn't precompiled
178
+ <% if in_tag && !nuke_inner_whitespace %> result = tabs(tabulation) + result <% end %>
179
+ end
180
+
181
+ <% if in_tag && !nuke_inner_whitespace %>
182
+ result = "\\n\#{result}\\n\#{tabs(tabulation-1)}"
183
+ @real_tabs -= 1
184
+ <% end %>
185
+ <% if interpolated %> @tabulation = old_tabulation <% end %>
186
+ result
187
+ <% end %>
188
+ RUBY
189
+
190
+ # Takes the various information about the opening tag for an element,
191
+ # formats it, and appends it to the buffer.
154
192
  def open_tag(name, self_closing, try_one_line, preserve_tag, escape_html, class_id,
155
193
  nuke_outer_whitespace, nuke_inner_whitespace, obj_ref, content, *attributes_hashes)
156
194
  tabulation = @real_tabs
157
195
 
158
196
  attributes = class_id
159
197
  attributes_hashes.each do |old|
160
- self.class.merge_attrs(attributes, old.inject({}) {|h, (key, val)| h[key.to_s] = val; h})
198
+ self.class.merge_attrs(attributes, to_hash(old.map {|k, v| [k.to_s, v]}))
161
199
  end
162
200
  self.class.merge_attrs(attributes, parse_object_ref(obj_ref)) if obj_ref
163
201
 
@@ -193,6 +231,18 @@ module Haml
193
231
  buffer << buffer.slice!(capture_position..-1).rstrip
194
232
  end
195
233
 
234
+ # Merges two attribute hashes.
235
+ # This is the same as `to.merge!(from)`,
236
+ # except that it merges id and class attributes.
237
+ #
238
+ # ids are concatenated with `"_"`,
239
+ # and classes are concatenated with `" "`.
240
+ #
241
+ # Destructively modifies both `to` and `from`.
242
+ #
243
+ # @param to [Hash<String, String>] The attribute hash to merge into
244
+ # @param from [Hash<String, String>] The attribute hash to merge from
245
+ # @return [Hash<String, String>] `to`, after being merged
196
246
  def self.merge_attrs(to, from)
197
247
  if to['id'] && from['id']
198
248
  to['id'] << '_' << from.delete('id')
@@ -202,7 +252,7 @@ module Haml
202
252
 
203
253
  if to['class'] && from['class']
204
254
  # Make sure we don't duplicate class names
205
- from['class'] = (from['class'].split(' ') | to['class'].split(' ')).join(' ')
255
+ from['class'] = (from['class'].split(' ') | to['class'].split(' ')).sort.join(' ')
206
256
  elsif to['class'] || from['class']
207
257
  from['class'] ||= to['class']
208
258
  end
@@ -212,11 +262,8 @@ module Haml
212
262
 
213
263
  private
214
264
 
215
- # Some of these methods are exposed as public class methods
216
- # so they can be re-used in helpers.
217
-
218
265
  @@tab_cache = {}
219
- # Gets <tt>count</tt> tabs. Mostly for internal use.
266
+ # Gets `count` tabs. Mostly for internal use.
220
267
  def tabs(count = 0)
221
268
  tabs = [count + @tabulation, 0].max
222
269
  @@tab_cache[tabs] ||= ' ' * tabs
@@ -225,7 +272,7 @@ module Haml
225
272
  # Takes an array of objects and uses the class and id of the first
226
273
  # one to create an attributes hash.
227
274
  # The second object, if present, is used as a prefix,
228
- # just like you can do with dom_id() and dom_class() in Rails
275
+ # just like you can do with `dom_id()` and `dom_class()` in Rails
229
276
  def parse_object_ref(ref)
230
277
  prefix = ref[1]
231
278
  ref = ref[0]
@@ -5,53 +5,68 @@ require 'haml/filters'
5
5
  require 'haml/error'
6
6
 
7
7
  module Haml
8
- # This is the class where all the parsing and processing of the Haml
9
- # template is done. It can be directly used by the user by creating a
10
- # new instance and calling <tt>to_html</tt> to render the template. For example:
8
+ # This is the frontend for using Haml programmatically.
9
+ # It can be directly used by the user by creating a
10
+ # new instance and calling \{#render} to render the template.
11
+ # For example:
11
12
  #
12
- # template = File.read('templates/really_cool_template.haml')
13
- # haml_engine = Haml::Engine.new(template)
14
- # output = haml_engine.to_html
15
- # puts output
13
+ # template = File.read('templates/really_cool_template.haml')
14
+ # haml_engine = Haml::Engine.new(template)
15
+ # output = haml_engine.render
16
+ # puts output
16
17
  class Engine
17
18
  include Precompiler
18
19
 
19
- # Allow reading and writing of the options hash
20
- attr :options, true
20
+ # The options hash.
21
+ # See {file:HAML_REFERENCE.md#haml_options the Haml options documentation}.
22
+ #
23
+ # @return [Hash<Symbol, Object>]
24
+ attr_accessor :options
21
25
 
22
- # This string contains the source code that is evaluated
23
- # to produce the Haml document.
24
- attr :precompiled, true
26
+ # The indentation used in the Haml document,
27
+ # or `nil` if the indentation is ambiguous
28
+ # (for example, for a single-level document).
29
+ #
30
+ # @return [String]
31
+ attr_accessor :indentation
25
32
 
26
- # True if the format is XHTML
33
+ # @return [Boolean] Whether or not the format is XHTML.
27
34
  def xhtml?
28
35
  not html?
29
36
  end
30
37
 
31
- # True if the format is any flavor of HTML
38
+ # @return [Boolean] Whether or not the format is any flavor of HTML.
32
39
  def html?
33
40
  html4? or html5?
34
41
  end
35
42
 
36
- # True if the format is HTML4
43
+ # @return [Boolean] Whether or not the format is HTML4.
37
44
  def html4?
38
45
  @options[:format] == :html4
39
46
  end
40
47
 
41
- # True if the format is HTML5
48
+ # @return [Boolean] Whether or not the format is HTML5.
42
49
  def html5?
43
50
  @options[:format] == :html5
44
51
  end
45
52
 
46
- # Creates a new instace of Haml::Engine that will compile the given
47
- # template string when <tt>render</tt> is called.
48
- # See the Haml module documentation for available options.
53
+ # The source code that is evaluated to produce the Haml document.
49
54
  #
50
- #--
51
- # When adding options, remember to add information about them
52
- # to lib/haml.rb!
53
- #++
55
+ # In Ruby 1.9, this is automatically converted to the correct encoding
56
+ # (see {file:HAML_REFERENCE.md#encoding-option the `:encoding` option}).
57
+ #
58
+ # @return [String]
59
+ def precompiled
60
+ return @precompiled if ruby1_8?
61
+ return @precompiled.encode(Encoding.find(@options[:encoding]))
62
+ end
63
+
64
+ # Precompiles the Haml template.
54
65
  #
66
+ # @param template [String] The Haml template
67
+ # @param options [Hash<Symbol, Object>] An options hash;
68
+ # see {file:HAML_REFERENCE.md#haml_options the Haml options documentation}
69
+ # @raise [Haml::Error] if there's a Haml syntax error in the template
55
70
  def initialize(template, options = {})
56
71
  @options = {
57
72
  :suppress_eval => false,
@@ -65,8 +80,11 @@ module Haml
65
80
  :line => 1,
66
81
  :ugly => false,
67
82
  :format => :xhtml,
68
- :escape_html => false
83
+ :escape_html => false,
69
84
  }
85
+ unless ruby1_8?
86
+ @options[:encoding] = Encoding.default_internal || "utf-8"
87
+ end
70
88
  @options.merge! options
71
89
  @index = 0
72
90
 
@@ -74,28 +92,22 @@ module Haml
74
92
  raise Haml::Error, "Invalid format #{@options[:format].inspect}"
75
93
  end
76
94
 
77
- @template = template.rstrip + "\n-#\n-#"
95
+ if @options[:encoding] && @options[:encoding].is_a?(Encoding)
96
+ @options[:encoding] = @options[:encoding].name
97
+ end
98
+
99
+ # :eod is a special end-of-document marker
100
+ @template = (template.rstrip).split(/\r\n|\r|\n/) + [:eod, :eod]
101
+ @template_index = 0
78
102
  @to_close_stack = []
79
103
  @output_tabs = 0
80
104
  @template_tabs = 0
81
- @flat_spaces = -1
82
105
  @flat = false
83
106
  @newlines = 0
84
107
  @precompiled = ''
85
- @merged_text = ''
108
+ @to_merge = []
86
109
  @tab_change = 0
87
-
88
- if @template =~ /\A(\s*\n)*[ \t]+\S/
89
- raise SyntaxError.new("Indenting at the beginning of the document is illegal.", ($1 || "").count("\n"))
90
- end
91
-
92
- if @options[:filters]
93
- warn <<END
94
- DEPRECATION WARNING:
95
- The Haml :filters option is deprecated and will be removed in version 2.2.
96
- Filters are now automatically registered.
97
- END
98
- end
110
+ @temp_count = 0
99
111
 
100
112
  precompile
101
113
  rescue Haml::Error => e
@@ -105,39 +117,45 @@ END
105
117
 
106
118
  # Processes the template and returns the result as a string.
107
119
  #
108
- # +scope+ is the context in which the template is evaluated.
109
- # If it's a Binding or Proc object,
110
- # Haml uses it as the second argument to Kernel#eval;
111
- # otherwise, Haml just uses its #instance_eval context.
120
+ # `scope` is the context in which the template is evaluated.
121
+ # If it's a `Binding` or `Proc` object,
122
+ # Haml uses it as the second argument to `Kernel#eval`;
123
+ # otherwise, Haml just uses its `#instance_eval` context.
112
124
  #
113
125
  # Note that Haml modifies the evaluation context
114
- # (either the scope object or the "self" object of the scope binding).
115
- # It extends Haml::Helpers, and various instance variables are set
116
- # (all prefixed with "haml").
126
+ # (either the scope object or the `self` object of the scope binding).
127
+ # It extends {Haml::Helpers}, and various instance variables are set
128
+ # (all prefixed with `haml_`).
117
129
  # For example:
118
130
  #
119
- # s = "foobar"
120
- # Haml::Engine.new("%p= upcase").render(s) #=> "<p>FOOBAR</p>"
131
+ # s = "foobar"
132
+ # Haml::Engine.new("%p= upcase").render(s) #=> "<p>FOOBAR</p>"
121
133
  #
122
- # # s now extends Haml::Helpers
123
- # s.responds_to?(:html_attrs) #=> true
134
+ # # s now extends Haml::Helpers
135
+ # s.responds_to?(:html_attrs) #=> true
124
136
  #
125
- # +locals+ is a hash of local variables to make available to the template.
137
+ # `locals` is a hash of local variables to make available to the template.
126
138
  # For example:
127
139
  #
128
- # Haml::Engine.new("%p= foo").render(Object.new, :foo => "Hello, world!") #=> "<p>Hello, world!</p>"
140
+ # Haml::Engine.new("%p= foo").render(Object.new, :foo => "Hello, world!") #=> "<p>Hello, world!</p>"
129
141
  #
130
142
  # If a block is passed to render,
131
- # that block is run when +yield+ is called
143
+ # that block is run when `yield` is called
132
144
  # within the template.
133
145
  #
134
146
  # Due to some Ruby quirks,
135
- # if scope is a Binding or Proc object and a block is given,
147
+ # if `scope` is a `Binding` or `Proc` object and a block is given,
136
148
  # the evaluation context may not be quite what the user expects.
137
- # In particular, it's equivalent to passing <tt>eval("self", scope)</tt> as scope.
149
+ # In particular, it's equivalent to passing `eval("self", scope)` as `scope`.
138
150
  # This won't have an effect in most cases,
139
- # but if you're relying on local variables defined in the context of scope,
151
+ # but if you're relying on local variables defined in the context of `scope`,
140
152
  # they won't work.
153
+ #
154
+ # @param scope [Binding, Proc, Object] The context in which the template is evaluated
155
+ # @param locals [Hash<Symbol, Object>] Local variables that will be made available
156
+ # to the template
157
+ # @param block [#to_proc] A block that can be yielded to within the template
158
+ # @return [String] The rendered template
141
159
  def render(scope = Object.new, locals = {}, &block)
142
160
  buffer = Haml::Buffer.new(scope.instance_variable_get('@haml_buffer'), options_for_buffer)
143
161
 
@@ -156,7 +174,7 @@ END
156
174
  @haml_buffer = buffer
157
175
  end
158
176
 
159
- eval(@precompiled, scope, @options[:filename], @options[:line])
177
+ eval(precompiled, scope, @options[:filename], @options[:line])
160
178
 
161
179
  # Get rid of the current buffer
162
180
  scope_object.instance_eval do
@@ -170,24 +188,27 @@ END
170
188
  # Returns a proc that, when called,
171
189
  # renders the template and returns the result as a string.
172
190
  #
173
- # +scope+ works the same as it does for render.
191
+ # `scope` works the same as it does for render.
174
192
  #
175
193
  # The first argument of the returned proc is a hash of local variable names to values.
176
194
  # However, due to an unfortunate Ruby quirk,
177
195
  # the local variables which can be assigned must be pre-declared.
178
- # This is done with the +local_names+ argument.
196
+ # This is done with the `local_names` argument.
179
197
  # For example:
180
198
  #
181
- # # This works
182
- # Haml::Engine.new("%p= foo").render_proc(Object.new, :foo).call :foo => "Hello!"
183
- # #=> "<p>Hello!</p>"
199
+ # # This works
200
+ # Haml::Engine.new("%p= foo").render_proc(Object.new, :foo).call :foo => "Hello!"
201
+ # #=> "<p>Hello!</p>"
202
+ #
203
+ # # This doesn't
204
+ # Haml::Engine.new("%p= foo").render_proc.call :foo => "Hello!"
205
+ # #=> NameError: undefined local variable or method `foo'
184
206
  #
185
- # # This doesn't
186
- # Haml::Engine.new("%p= foo").render_proc.call :foo => "Hello!"
187
- # #=> NameError: undefined local variable or method `foo'
207
+ # The proc doesn't take a block; any yields in the template will fail.
188
208
  #
189
- # The proc doesn't take a block;
190
- # any yields in the template will fail.
209
+ # @param scope [Binding, Proc, Object] The context in which the template is evaluated
210
+ # @param local_names [Array<Symbol>] The names of the locals that can be passed to the proc
211
+ # @return [Proc] The proc that will run the template
191
212
  def render_proc(scope = Object.new, *local_names)
192
213
  if scope.is_a?(Binding) || scope.is_a?(Proc)
193
214
  scope_object = eval("self", scope)
@@ -200,41 +221,44 @@ END
200
221
  precompiled_with_ambles(local_names) + "}\n", scope, @options[:filename], @options[:line])
201
222
  end
202
223
 
203
- # Defines a method on +object+
204
- # with the given name
224
+ # Defines a method on `object` with the given name
205
225
  # that renders the template and returns the result as a string.
206
226
  #
207
- # If +object+ is a class or module,
227
+ # If `object` is a class or module,
208
228
  # the method will instead by defined as an instance method.
209
229
  # For example:
210
230
  #
211
- # t = Time.now
212
- # Haml::Engine.new("%p\n Today's date is\n .date= self.to_s").def_method(t, :render)
213
- # t.render #=> "<p>\n Today's date is\n <div class='date'>Fri Nov 23 18:28:29 -0800 2007</div>\n</p>\n"
231
+ # t = Time.now
232
+ # Haml::Engine.new("%p\n Today's date is\n .date= self.to_s").def_method(t, :render)
233
+ # t.render #=> "<p>\n Today's date is\n <div class='date'>Fri Nov 23 18:28:29 -0800 2007</div>\n</p>\n"
214
234
  #
215
- # Haml::Engine.new(".upcased= upcase").def_method(String, :upcased_div)
216
- # "foobar".upcased_div #=> "<div class='upcased'>FOOBAR</div>\n"
235
+ # Haml::Engine.new(".upcased= upcase").def_method(String, :upcased_div)
236
+ # "foobar".upcased_div #=> "<div class='upcased'>FOOBAR</div>\n"
217
237
  #
218
238
  # The first argument of the defined method is a hash of local variable names to values.
219
239
  # However, due to an unfortunate Ruby quirk,
220
240
  # the local variables which can be assigned must be pre-declared.
221
- # This is done with the +local_names+ argument.
241
+ # This is done with the `local_names` argument.
222
242
  # For example:
223
243
  #
224
- # # This works
225
- # obj = Object.new
226
- # Haml::Engine.new("%p= foo").def_method(obj, :render, :foo)
227
- # obj.render(:foo => "Hello!") #=> "<p>Hello!</p>"
244
+ # # This works
245
+ # obj = Object.new
246
+ # Haml::Engine.new("%p= foo").def_method(obj, :render, :foo)
247
+ # obj.render(:foo => "Hello!") #=> "<p>Hello!</p>"
228
248
  #
229
- # # This doesn't
230
- # obj = Object.new
231
- # Haml::Engine.new("%p= foo").def_method(obj, :render)
232
- # obj.render(:foo => "Hello!") #=> NameError: undefined local variable or method `foo'
249
+ # # This doesn't
250
+ # obj = Object.new
251
+ # Haml::Engine.new("%p= foo").def_method(obj, :render)
252
+ # obj.render(:foo => "Hello!") #=> NameError: undefined local variable or method `foo'
233
253
  #
234
254
  # Note that Haml modifies the evaluation context
235
- # (either the scope object or the "self" object of the scope binding).
236
- # It extends Haml::Helpers, and various instance variables are set
237
- # (all prefixed with "haml").
255
+ # (either the scope object or the `self` object of the scope binding).
256
+ # It extends {Haml::Helpers}, and various instance variables are set
257
+ # (all prefixed with `haml_`).
258
+ #
259
+ # @param object [Object, Module] The object on which to define the method
260
+ # @param name [String, Symbol] The name of the method to define
261
+ # @param local_names [Array<Symbol>] The names of the locals that can be passed to the proc
238
262
  def def_method(object, name, *local_names)
239
263
  method = object.is_a?(Module) ? :module_eval : :instance_eval
240
264
 
@@ -242,24 +266,32 @@ END
242
266
  @options[:filename], @options[:line])
243
267
  end
244
268
 
245
- private
246
-
247
- def set_locals(locals, scope, scope_object)
248
- scope_object.send(:instance_variable_set, '@_haml_locals', locals)
249
- set_locals = locals.keys.map { |k| "#{k} = @_haml_locals[#{k.inspect}]" }.join("\n")
250
- eval(set_locals, scope)
251
- end
269
+ protected
252
270
 
253
- # Returns a hash of options that Haml::Buffer cares about.
254
- # This should remain loadable from #inspect.
271
+ # Returns a subset of \{#options}: those that {Haml::Buffer} cares about.
272
+ # All of the values here are such that when `#inspect` is called on the hash,
273
+ # it can be `Kernel#eval`ed to get the same result back.
274
+ #
275
+ # See {file:HAML_REFERENCE.md#haml_options the Haml options documentation}.
276
+ #
277
+ # @return [Hash<Symbol, Object>] The options hash
255
278
  def options_for_buffer
256
279
  {
257
280
  :autoclose => @options[:autoclose],
258
281
  :preserve => @options[:preserve],
259
282
  :attr_wrapper => @options[:attr_wrapper],
260
283
  :ugly => @options[:ugly],
261
- :format => @options[:format]
284
+ :format => @options[:format],
285
+ :encoding => @options[:encoding],
262
286
  }
263
287
  end
288
+
289
+ private
290
+
291
+ def set_locals(locals, scope, scope_object)
292
+ scope_object.send(:instance_variable_set, '@_haml_locals', locals)
293
+ set_locals = locals.keys.map { |k| "#{k} = @_haml_locals[#{k.inspect}]" }.join("\n")
294
+ eval(set_locals, scope)
295
+ end
264
296
  end
265
297
  end