haml 4.0.7 → 4.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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b7a38de787ab9e47ac3221b040c9c38ecf4884df
4
- data.tar.gz: 29497caf8377f40940a0e094d1477ea2403f380f
3
+ metadata.gz: 3e558b5f2cf40a4dc76dd5a6d4a6fd7410087cea
4
+ data.tar.gz: de7642c1dd34404f48def114391e5070ea0d78fa
5
5
  SHA512:
6
- metadata.gz: 3c71810f7359be3c7536eea848acefb06d09859443d6b80a31908ea07b6c109dc082a7ad8a7e95f1305b08aefeabbe46dd48cc186dff66eb4fe46bdd258956e1
7
- data.tar.gz: 0d85d5e2164cef71dab787d7967ab4a3e7ecd1dd0b5e212188032bd94faa6d4923cdb39cd5fdffcdaed6da13b6f637d1d5d5c8171ca878fa017ac64c345d589f
6
+ metadata.gz: 1713fd685aee4177c59ea3f3353c65a875c2cc3cbf8a840c20c96d2bd2308dad11f28c04d73fde0bfcedfd7e3e50e90a2b20ae17ee0fe8769285971cb5f651bf
7
+ data.tar.gz: f6a1e655ac0fdaeeb9ae8e215fad6b79673da33f9c404ac192dca1f8dbc8bb81becb33250554c3e2b29907054efb6e28b22349a1153126ba09b40fd1ff734de5
@@ -1,28 +1,16 @@
1
1
  # Haml Changelog
2
2
 
3
- ## 4.0.7
4
-
5
- Released on August 10, 2015
6
- ([diff](https://github.com/haml/haml/compare/4.0.6...4.0.7)).
7
-
8
- * Significantly improve performance of regexp used to fix whitespace handling in textareas (thanks [Stan Hu](https://github.com/stanhu)).
9
-
10
- ## 4.0.6
11
-
12
- Released on Dec 1, 2014 ([diff](https://github.com/haml/haml/compare/4.0.5...4.0.6)).
13
-
14
-
15
- * Fix warning on Ruby 1.8.7 "regexp has invalid interval" (thanks [Elia Schito](https://github.com/elia)).
16
-
17
- ## 4.0.5
18
-
19
- Released on Jan 7, 2014 ([diff](https://github.com/haml/haml/compare/4.0.4...4.0.5)).
20
-
21
- * Fix haml_concat appending unescaped HTML after a call to haml_tag.
22
- * Fix for bug whereby when HAML :ugly option is "true",
23
- ActionView::Helpers::CaptureHelper::capture returns the whole view buffer
24
- when passed a block that returns nothing (thanks [Mircea
25
- Moise](https://github.com/mmircea16)).
3
+ ## 4.1.0 (Unreleased)
4
+
5
+ * Haml now requires Ruby 1.9.2 or above.
6
+ * Fix for attribute merging. When an attribute method (or literal nested hash)
7
+ was used in an old style attribute hash and there is also a (non-static) new
8
+ style hash there is an error. The fix can result in different behavior in
9
+ some circumstances. See the [commit message](https://github.com/haml/haml/tree/e475b015d3171fb4c4f140db304f7970c787d6e3)
10
+ for detailed info. (Matt Wildig)
11
+ * Make escape_once respect hexadecimal references. (Matt Wildig)
12
+ * General performance and memory usage improvements. (Akira Matsuda)
13
+ * Don't treat the 'data' attribute specially when merging attribute hashes. (Matt Wildig and Norman Clarke)
26
14
 
27
15
  ## 4.0.4
28
16
 
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Haml
2
2
 
3
3
  [![Build Status](https://secure.travis-ci.org/haml/haml.png?branch=master)](http://travis-ci.org/haml/haml)
4
+ [![Code Climate](https://codeclimate.com/github/haml/haml.png)](https://codeclimate.com/github/haml/haml)
4
5
 
5
6
  Haml is a templating engine for HTML. It's designed to make it both easier and
6
7
  more pleasant to write HTML documents, by eliminating redundancy, reflecting the
@@ -126,8 +127,8 @@ on a specific area:
126
127
 
127
128
  ruby -Itest test/helper_test.rb -n test_buffer_access
128
129
 
129
- Haml supports Ruby 1.8.7 and higher, so please make sure your changes run on
130
- both 1.9 and 1.8.
130
+ Haml supports Ruby 1.9.2 and higher, so please make sure your changes run on
131
+ both 1.9 and 2.0.
131
132
 
132
133
  ## Team
133
134
 
@@ -121,7 +121,7 @@ see {Haml::Options}.
121
121
 
122
122
  ### Encodings
123
123
 
124
- When using Ruby 1.9 or later, Haml supports the same sorts of
124
+ Haml supports the same sorts of
125
125
  encoding-declaration comments that Ruby does. Although both Ruby and Haml
126
126
  support several different styles, the easiest it just to add `-# coding:
127
127
  encoding-name` at the beginning of the Haml template (it must come before all
@@ -306,7 +306,7 @@ hash-style attributes:
306
306
 
307
307
  #### Ruby 1.9-style Hashes
308
308
 
309
- On Ruby 1.9, Haml also supports Ruby's new hash syntax:
309
+ Haml also supports Ruby's new hash syntax:
310
310
 
311
311
  %a{title: @title, href: href} Stuff
312
312
 
@@ -329,7 +329,7 @@ This is compiled to:
329
329
  </html>
330
330
 
331
331
  You can use as many such attribute methods as you want by separating them with
332
- commas, like a Ruby argument list. All the hashes will be merged together, from
332
+ commas, like a Ruby argument list. All the hashes will me merged together, from
333
333
  left to right. For example, if you defined
334
334
 
335
335
  def hash1
@@ -496,23 +496,23 @@ and is compiled to:
496
496
  The forward slash character, when placed at the end of a tag definition, causes
497
497
  Haml to treat it as being an empty (or void) element. Depending on the format,
498
498
  the tag will be rendered either without a closing tag (`:html4` or `:html5`), or
499
- as a self-closing tag (`:xhtml`). For example:
499
+ as a self-closing tag (`:xhtml`).
500
+
501
+ Taking the following as an example:
500
502
 
501
503
  %br/
502
504
  %meta{'http-equiv' => 'Content-Type', :content => 'text/html'}/
503
505
 
504
- is compiled to:
506
+ When the format is `:html4` or `:html5` this is compiled to:
505
507
 
506
508
  <br>
507
509
  <meta content='text/html' http-equiv='Content-Type'>
508
510
 
509
- when the format is `:html4` or `:html5`, and to
511
+ and when the format is `:xhtml` it is compiled to:
510
512
 
511
513
  <br />
512
514
  <meta content='text/html' http-equiv='Content-Type' />
513
515
 
514
- when the format is `:xhtml`.
515
-
516
516
  Some tags are automatically treated as being empty, as long as they have no
517
517
  content in the Haml source. `meta`, `img`, `link`, `br`, `hr`, `input`,
518
518
  `area`, `param`, `col` and `base` tags are treated as empty by default. This
@@ -779,6 +779,21 @@ is compiled to:
779
779
  </a>
780
780
  <![endif]-->
781
781
 
782
+ To generate “downlevel-revealed” conditional comments, where the content is
783
+ hidden from IE but not other browsers, add a `!` before the brackets: `/![]`.
784
+ Haml will produce valid HTML when generating this kind of conditional comment.
785
+
786
+ For example:
787
+
788
+ /![if !IE]
789
+ You are not using Internet Explorer, or are using version 10+.
790
+
791
+ is compiled to:
792
+
793
+ <!--[if !IE]><!-->
794
+ You are not using Internet Explorer, or are using version 10+.
795
+ <!--<![endif]-->
796
+
782
797
  ### Haml Comments: `-#`
783
798
 
784
799
  The hyphen followed immediately by the pound sign signifies a silent comment.
@@ -1093,7 +1108,7 @@ Surrounds the filtered text with CDATA tags.
1093
1108
 
1094
1109
  {#coffee-filter}
1095
1110
  ### `:coffee`
1096
- Compiles the filtered text to Javascript using Cofeescript. You can also
1111
+ Compiles the filtered text to Javascript using Coffeescript. You can also
1097
1112
  reference this filter as `:coffeescript`. This filter is implemented using
1098
1113
  Tilt.
1099
1114
 
data/Rakefile CHANGED
@@ -25,6 +25,7 @@ Rake::TestTask.new do |t|
25
25
  files = Dir["test/*_test.rb"]
26
26
  files.concat(Dir['test/haml-spec/*_test.rb'])
27
27
  t.test_files = files
28
+ t.warning = true
28
29
  t.verbose = true
29
30
  end
30
31
 
@@ -32,7 +33,7 @@ task :set_coverage_env do
32
33
  ENV["COVERAGE"] = "true"
33
34
  end
34
35
 
35
- desc "Run Simplecov (only works on 1.9)"
36
+ desc "Run Simplecov"
36
37
  task :coverage => [:set_coverage_env, :test]
37
38
 
38
39
  gemspec = File.expand_path("../haml.gemspec", __FILE__)
@@ -80,13 +81,13 @@ Profile Haml.
80
81
  END
81
82
  task :profile do
82
83
  times = (ENV['TIMES'] || '1000').to_i
83
- file = ENV['FILE']
84
+ file = ENV['FILE'] || 'test/templates/standard.haml'
84
85
 
85
86
  require 'bundler/setup'
86
87
  require 'ruby-prof'
87
88
  require 'haml'
88
-
89
- file = File.read(File.expand_path("../test/templates/#{file || 'standard'}.haml", __FILE__))
89
+ default =
90
+ file = File.read(File.expand_path("../#{file}", __FILE__))
90
91
  obj = Object.new
91
92
  Haml::Engine.new(file, :ugly => true).def_method(obj, :render)
92
93
  result = RubyProf.profile { times.times { obj.render } }
@@ -178,7 +178,7 @@ module Haml
178
178
  <% end %>
179
179
 
180
180
  if has_newline
181
- result = result.gsub "\\n", "\\n" + tabs(tabulation)
181
+ result.gsub! "\\n", "\\n" + tabs(tabulation)
182
182
 
183
183
  # Add tabulation if it wasn't precompiled
184
184
  <% if in_tag && !nuke_inner_whitespace %> result = tabs(tabulation) + result <% end %>
@@ -233,7 +233,7 @@ RUBY
233
233
  def self.merge_attrs(to, from)
234
234
  from['id'] = Compiler.filter_and_join(from['id'], '_') if from['id']
235
235
  if to['id'] && from['id']
236
- to['id'] << '_' << from.delete('id').to_s
236
+ to['id'] << "_#{from.delete('id')}"
237
237
  elsif to['id'] || from['id']
238
238
  from['id'] ||= to['id']
239
239
  end
@@ -246,16 +246,21 @@ RUBY
246
246
  from['class'] ||= to['class']
247
247
  end
248
248
 
249
- from_data = from.delete('data') || {}
250
- to_data = to.delete('data') || {}
249
+ from.keys.each do |key|
250
+ next unless from[key].kind_of?(Hash) || to[key].kind_of?(Hash)
251
251
 
252
- # forces to_data & from_data into a hash
253
- from_data = { nil => from_data } unless from_data.is_a?(Hash)
254
- to_data = { nil => to_data } unless to_data.is_a?(Hash)
252
+ from_data = from.delete(key)
253
+ # forces to_data & from_data into a hash
254
+ from_data = { nil => from_data } if from_data && !from_data.is_a?(Hash)
255
+ to[key] = { nil => to[key] } if to[key] && !to[key].is_a?(Hash)
255
256
 
256
- merged_data = to_data.merge(from_data)
257
+ if from_data && !to[key]
258
+ to[key] = from_data
259
+ elsif from_data && to[key]
260
+ to[key].merge! from_data
261
+ end
262
+ end
257
263
 
258
- to['data'] = merged_data unless merged_data.empty?
259
264
  to.merge!(from)
260
265
  end
261
266
 
@@ -270,27 +275,21 @@ RUBY
270
275
  # @since Haml 4.0.1
271
276
  # @private
272
277
  def fix_textareas!(input)
273
- pattern = /<(textarea)([^>]*)>(\n|&#x000A;)(.*?)<\/textarea>/im
278
+ pattern = /([ ]*)<(textarea)([^>]*)>(\n|&#x000A;)(.*?)(<\/\2>)/im
274
279
  input.gsub!(pattern) do |s|
275
280
  match = pattern.match(s)
276
- content = match[4]
277
- if match[3] == '&#x000A;'
281
+ content = match[5]
282
+ if match[4] == '&#x000A;'
278
283
  content.sub!(/\A /, '&#x0020;')
279
284
  else
280
285
  content.sub!(/\A[ ]*/, '')
281
286
  end
282
- "<#{match[1]}#{match[2]}>\n#{content}</#{match[1]}>"
287
+ "#{match[1]}<#{match[2]}#{match[3]}>\n#{content}</#{match[2]}>"
283
288
  end
284
289
  end
285
290
 
286
- if RUBY_VERSION < "1.9"
287
- def new_encoded_string
288
- ""
289
- end
290
- else
291
- def new_encoded_string
292
- "".encode(Encoding.find(options[:encoding]))
293
- end
291
+ def new_encoded_string
292
+ "".encode(Encoding.find(options[:encoding]))
294
293
  end
295
294
 
296
295
  @@tab_cache = {}
@@ -335,11 +334,13 @@ RUBY
335
334
  # Based on the method of the same name in Rails' Inflector,
336
335
  # but copied here so it'll run properly without Rails.
337
336
  def underscore(camel_cased_word)
338
- camel_cased_word.to_s.gsub(/::/, '_').
339
- gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
340
- gsub(/([a-z\d])([A-Z])/,'\1_\2').
341
- tr("-", "_").
342
- downcase
337
+ word = camel_cased_word.to_s.dup
338
+ word.gsub!(/::/, '_')
339
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
340
+ word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
341
+ word.tr!('-', '_')
342
+ word.downcase!
343
+ word
343
344
  end
344
345
  end
345
346
  end
@@ -1,5 +1,3 @@
1
- require 'cgi'
2
-
3
1
  module Haml
4
2
  class Compiler
5
3
  include Haml::Util
@@ -11,11 +9,11 @@ module Haml
11
9
  @output_tabs = 0
12
10
  @to_merge = []
13
11
  @precompiled = ''
12
+ @node = nil
14
13
  end
15
14
 
16
15
  def compile(node)
17
- parent = instance_variable_defined?('@node') ? @node : nil
18
- @node = node
16
+ parent, @node = @node, node
19
17
  if node.children.empty?
20
18
  send(:"compile_#{node.type}")
21
19
  else
@@ -25,26 +23,20 @@ module Haml
25
23
  @node = parent
26
24
  end
27
25
 
28
- if RUBY_VERSION < "1.9"
29
- # The source code that is evaluated to produce the Haml document.
30
- #
31
- # In Ruby 1.9, this is automatically converted to the correct encoding
32
- # (see {file:REFERENCE.md#encodings the `:encoding` option}).
33
- #
34
- # @return [String]
35
- def precompiled
36
- @precompiled
37
- end
38
- else
39
- def precompiled
40
- encoding = Encoding.find(@options[:encoding])
41
- return @precompiled.force_encoding(encoding) if encoding == Encoding::BINARY
42
- return @precompiled.encode(encoding)
43
- end
26
+ # The source code that is evaluated to produce the Haml document.
27
+ #
28
+ # This is automatically converted to the correct encoding
29
+ # (see {file:REFERENCE.md#encodings the `:encoding` option}).
30
+ #
31
+ # @return [String]
32
+ def precompiled
33
+ encoding = Encoding.find(@options.encoding)
34
+ return @precompiled.force_encoding(encoding) if encoding == Encoding::ASCII_8BIT
35
+ return @precompiled.encode(encoding)
44
36
  end
45
37
 
46
38
  def precompiled_with_return_value
47
- precompiled + ";" + precompiled_method_return_value
39
+ "#{precompiled};#{precompiled_method_return_value}"
48
40
  end
49
41
 
50
42
  # Returns the precompiled string with the preamble and postamble.
@@ -53,20 +45,20 @@ module Haml
53
45
  # to avoid ordering issues with partial layouts in Rails. If not available,
54
46
  # initializes to nil.
55
47
  def precompiled_with_ambles(local_names)
56
- preamble = <<END.gsub("\n", ";")
48
+ preamble = <<END.tr("\n", ';')
57
49
  begin
58
50
  extend Haml::Helpers
59
51
  _hamlout = @haml_buffer = Haml::Buffer.new(haml_buffer, #{options.for_buffer.inspect})
60
52
  _erbout = _hamlout.buffer
61
53
  @output_buffer = output_buffer ||= ActionView::OutputBuffer.new rescue nil
62
54
  END
63
- postamble = <<END.gsub("\n", ";")
55
+ postamble = <<END.tr("\n", ';')
64
56
  #{precompiled_method_return_value}
65
57
  ensure
66
58
  @haml_buffer = @haml_buffer.upper if @haml_buffer
67
59
  end
68
60
  END
69
- preamble + locals_code(local_names) + precompiled + postamble
61
+ "#{preamble}#{locals_code(local_names)}#{precompiled}#{postamble}"
70
62
  end
71
63
 
72
64
  private
@@ -78,21 +70,21 @@ END
78
70
  end
79
71
 
80
72
  def locals_code(names)
81
- names = names.keys if Hash == names
73
+ names = names.keys if Hash === names
82
74
 
83
75
  names.map do |name|
84
76
  # Can't use || because someone might explicitly pass in false with a symbol
85
77
  sym_local = "_haml_locals[#{inspect_obj(name.to_sym)}]"
86
78
  str_local = "_haml_locals[#{inspect_obj(name.to_s)}]"
87
- "#{name} = #{sym_local}.nil? ? #{str_local} : #{sym_local}"
88
- end.join(';') + ';'
79
+ "#{name} = #{sym_local}.nil? ? #{str_local} : #{sym_local};"
80
+ end.join
89
81
  end
90
82
 
91
83
  def compile_root
92
84
  @dont_indent_next_line = @dont_tab_up_next_text = false
93
85
  @output_line = 1
94
86
  @indentation = nil
95
- yield
87
+ yield if block_given?
96
88
  flush_merged_text
97
89
  end
98
90
 
@@ -119,7 +111,7 @@ END
119
111
  end
120
112
 
121
113
  def compile_silent_script
122
- return if @options[:suppress_eval]
114
+ return if @options.suppress_eval
123
115
  push_silent(@node.value[:text])
124
116
  keyword = @node.value[:keyword]
125
117
 
@@ -156,8 +148,8 @@ END
156
148
  (t[:nuke_outer_whitespace] && !block_given?) ||
157
149
  (t[:nuke_inner_whitespace] && block_given?)
158
150
 
159
- if @options[:suppress_eval]
160
- object_ref = "nil"
151
+ if @options.suppress_eval
152
+ object_ref = :nil
161
153
  parse = false
162
154
  value = t[:parse] ? nil : t[:value]
163
155
  attributes_hashes = {}
@@ -171,7 +163,7 @@ END
171
163
  end
172
164
 
173
165
  # Check if we can render the tag directly to text and not process it in the buffer
174
- if object_ref == "nil" && attributes_hashes.empty? && !preserve_script
166
+ if (object_ref == :nil) && attributes_hashes.empty? && !preserve_script
175
167
  tag_closed = !block_given? && !t[:self_closing] && !parse
176
168
 
177
169
  open_tag = prerender_tag(t[:name], t[:self_closing], t[:attributes])
@@ -195,7 +187,7 @@ END
195
187
  elsif attributes_hashes.size == 1
196
188
  attributes_hashes = ", #{attributes_hashes.first}"
197
189
  else
198
- attributes_hashes = ", (#{attributes_hashes.join(").merge(")})"
190
+ attributes_hashes = ", #{attributes_hashes.join(", ")}"
199
191
  end
200
192
 
201
193
  push_merged_text "<#{t[:name]}", 0, !t[:nuke_outer_whitespace]
@@ -203,17 +195,13 @@ END
203
195
  "_hamlout.attributes(#{inspect_obj(t[:attributes])}, #{object_ref}#{attributes_hashes})")
204
196
  concat_merged_text(
205
197
  if t[:self_closing] && @options.xhtml?
206
- " />" + (t[:nuke_outer_whitespace] ? "" : "\n")
198
+ " />#{"\n" unless t[:nuke_outer_whitespace]}"
207
199
  else
208
- ">" + ((if t[:self_closing] && @options.html?
209
- t[:nuke_outer_whitespace]
210
- else
211
- !block_given? || t[:preserve_tag] || t[:nuke_inner_whitespace]
212
- end) ? "" : "\n")
200
+ ">#{"\n" unless (t[:self_closing] && @options.html?) ? t[:nuke_outer_whitespace] : (!block_given? || t[:preserve_tag] || t[:nuke_inner_whitespace])}"
213
201
  end)
214
202
 
215
203
  if value && !parse
216
- concat_merged_text("#{value}</#{t[:name]}>#{t[:nuke_outer_whitespace] ? "" : "\n"}")
204
+ concat_merged_text("#{value}</#{t[:name]}>#{"\n" unless t[:nuke_outer_whitespace]}")
217
205
  elsif !t[:nuke_inner_whitespace] && !t[:self_closing]
218
206
  @to_merge << [:text, '', 1]
219
207
  end
@@ -228,7 +216,7 @@ END
228
216
  yield if block_given?
229
217
  @output_tabs -= 1 unless t[:nuke_inner_whitespace]
230
218
  rstrip_buffer! if t[:nuke_inner_whitespace]
231
- push_merged_text("</#{t[:name]}>" + (t[:nuke_outer_whitespace] ? "" : "\n"),
219
+ push_merged_text("</#{t[:name]}>#{"\n" unless t[:nuke_outer_whitespace]}",
232
220
  t[:nuke_inner_whitespace] ? 0 : -1, !t[:nuke_inner_whitespace])
233
221
  @dont_indent_next_line = t[:nuke_outer_whitespace]
234
222
  return
@@ -236,16 +224,21 @@ END
236
224
 
237
225
  if parse
238
226
  push_script(value, t.merge(:in_tag => true))
239
- concat_merged_text("</#{t[:name]}>" + (t[:nuke_outer_whitespace] ? "" : "\n"))
227
+ concat_merged_text("</#{t[:name]}>#{"\n" unless t[:nuke_outer_whitespace]}")
240
228
  end
241
229
  end
242
230
 
243
231
  def compile_comment
244
- open = "<!--#{@node.value[:conditional]}"
232
+ condition = "#{@node.value[:conditional]}>" if @node.value[:conditional]
233
+ revealed = @node.value[:revealed]
234
+
235
+ open = "<!--#{condition}#{'<!-->' if revealed}"
236
+
237
+ close = "#{'<!--' if revealed}#{'<![endif]' if condition}-->"
245
238
 
246
239
  # Render it statically if possible
247
240
  unless block_given?
248
- push_text("#{open} #{@node.value[:text]} #{@node.value[:conditional] ? "<![endif]-->" : "-->"}")
241
+ push_text("#{open} #{@node.value[:text]} #{close}")
249
242
  return
250
243
  end
251
244
 
@@ -253,7 +246,7 @@ END
253
246
  @output_tabs += 1
254
247
  yield if block_given?
255
248
  @output_tabs -= 1
256
- push_text(@node.value[:conditional] ? "<![endif]-->" : "-->", -1)
249
+ push_text(close, -1)
257
250
  end
258
251
 
259
252
  def compile_doctype
@@ -276,7 +269,7 @@ END
276
269
  def text_for_doctype
277
270
  if @node.value[:type] == "xml"
278
271
  return nil if @options.html?
279
- wrapper = @options[:attr_wrapper]
272
+ wrapper = @options.attr_wrapper
280
273
  return "<?xml version=#{wrapper}1.0#{wrapper} encoding=#{wrapper}#{@node.value[:encoding] || "utf-8"}#{wrapper} ?>"
281
274
  end
282
275
 
@@ -316,13 +309,13 @@ END
316
309
  return if can_suppress && @options.suppress_eval?
317
310
  newline = (text == "end") ? ";" : "\n"
318
311
  @precompiled << "#{resolve_newlines}#{text}#{newline}"
319
- @output_line += (text + newline).count("\n")
312
+ @output_line = @output_line + text.count("\n") + newline.count("\n")
320
313
  end
321
314
 
322
315
  # Adds `text` to `@buffer` with appropriate tabulation
323
316
  # without parsing it.
324
317
  def push_merged_text(text, tab_change = 0, indent = true)
325
- text = !indent || @dont_indent_next_line || @options[:ugly] ? text : "#{' ' * @output_tabs}#{text}"
318
+ text = !indent || @dont_indent_next_line || @options.ugly ? text : "#{' ' * @output_tabs}#{text}"
326
319
  @to_merge << [:text, text, tab_change]
327
320
  @dont_indent_next_line = false
328
321
  end
@@ -339,27 +332,27 @@ END
339
332
  def flush_merged_text
340
333
  return if @to_merge.empty?
341
334
 
342
- str = ""
343
335
  mtabs = 0
344
- @to_merge.each do |type, val, tabs|
336
+ @to_merge.map! do |type, val, tabs|
345
337
  case type
346
338
  when :text
347
- str << inspect_obj(val)[1...-1]
348
339
  mtabs += tabs
340
+ inspect_obj(val)[1...-1]
349
341
  when :script
350
- if mtabs != 0 && !@options[:ugly]
342
+ if mtabs != 0 && !@options.ugly
351
343
  val = "_hamlout.adjust_tabs(#{mtabs}); " + val
352
344
  end
353
- str << "\#{#{val}}"
354
345
  mtabs = 0
346
+ "\#{#{val}}"
355
347
  else
356
348
  raise SyntaxError.new("[HAML BUG] Undefined entry in Haml::Compiler@to_merge.")
357
349
  end
358
350
  end
351
+ str = @to_merge.join
359
352
 
360
353
  unless str.empty?
361
354
  @precompiled <<
362
- if @options[:ugly]
355
+ if @options.ugly
363
356
  "_hamlout.buffer << \"#{str}\";"
364
357
  else
365
358
  "_hamlout.push_text(\"#{str}\", #{mtabs}, #{@dont_tab_up_next_text.inspect});"
@@ -377,11 +370,11 @@ END
377
370
  def push_script(text, opts = {})
378
371
  return if @options.suppress_eval?
379
372
 
380
- args = %w[preserve_script in_tag preserve_tag escape_html nuke_inner_whitespace]
381
- args.map! {|name| opts[name.to_sym]}
382
- args << !block_given? << @options[:ugly]
373
+ args = [:preserve_script, :in_tag, :preserve_tag, :escape_html, :nuke_inner_whitespace]
374
+ args.map! {|name| opts[name]}
375
+ args << !block_given? << @options.ugly
383
376
 
384
- no_format = @options[:ugly] &&
377
+ no_format = @options.ugly &&
385
378
  !(opts[:preserve_script] || opts[:preserve_tag] || opts[:escape_html])
386
379
  output_expr = "(#{text}\n)"
387
380
  static_method = "_hamlout.#{static_method_name(:format_script, *args)}"
@@ -400,7 +393,7 @@ END
400
393
  yield
401
394
  push_silent('end', :can_suppress) unless @node.value[:dont_push_end]
402
395
  @precompiled << "_hamlout.buffer << #{no_format ? "haml_temp.to_s;" : "#{static_method}(haml_temp);"}"
403
- concat_merged_text("\n") unless opts[:in_tag] || opts[:nuke_inner_whitespace] || @options[:ugly]
396
+ concat_merged_text("\n") unless opts[:in_tag] || opts[:nuke_inner_whitespace] || @options.ugly
404
397
  end
405
398
 
406
399
  def push_generated_script(text)
@@ -410,7 +403,7 @@ END
410
403
 
411
404
  # This is a class method so it can be accessed from Buffer.
412
405
  def self.build_attributes(is_html, attr_wrapper, escape_attrs, hyphenate_data_attrs, attributes = {})
413
- # @TODO this is an absolutely ridiculous amount of arguments. At least
406
+ # @TODO this is an absolutely ridiculous amount of arguments. At least
414
407
  # some of this needs to be moved into an instance method.
415
408
  quote_escape = attr_wrapper == '"' ? "&#x0022;" : "&#x0027;"
416
409
  other_quote_char = attr_wrapper == '"' ? "'" : '"'
@@ -463,14 +456,23 @@ END
463
456
  end
464
457
  " #{attr}=#{this_attr_wrapper}#{value}#{this_attr_wrapper}"
465
458
  end
466
- result.compact.sort.join
459
+ result.compact!
460
+ result.sort!
461
+ result.join
467
462
  end
468
463
 
469
464
  def self.filter_and_join(value, separator)
470
- return "" if value == ""
471
- value = [value] unless value.is_a?(Array)
472
- value = value.flatten.collect {|item| item ? item.to_s : nil}.compact.join(separator)
473
- return !value.empty? && value
465
+ return '' if (value.respond_to?(:empty?) && value.empty?)
466
+
467
+ if value.is_a?(Array)
468
+ value.flatten!
469
+ value.map! {|item| item ? item.to_s : nil}
470
+ value.compact!
471
+ value = value.join(separator)
472
+ else
473
+ value = value ? value.to_s : nil
474
+ end
475
+ !value.nil? && !value.empty? && value
474
476
  end
475
477
 
476
478
  def self.build_data_keys(data_hash, hyphenate, attr_name="data")
@@ -478,7 +480,7 @@ END
478
480
  if name == nil
479
481
  [attr_name, value]
480
482
  elsif hyphenate
481
- ["#{attr_name}-#{name.to_s.gsub(/_/, '-')}", value]
483
+ ["#{attr_name}-#{name.to_s.tr('_', '-')}", value]
482
484
  else
483
485
  ["#{attr_name}-#{name}", value]
484
486
  end
@@ -491,8 +493,7 @@ END
491
493
  return {key => nil} if seen.include? data.object_id
492
494
  seen << data.object_id
493
495
 
494
- data.sort {|x, y| x[0].to_s <=> y[0].to_s}.inject({}) do |hash, array|
495
- k, v = array
496
+ data.sort {|x, y| x[0].to_s <=> y[0].to_s}.inject({}) do |hash, (k, v)|
496
497
  joined = key == '' ? k : [key, k].join(join_char)
497
498
  hash.merge! flatten_data_attributes(v, joined, join_char, seen)
498
499
  end
@@ -501,7 +502,7 @@ END
501
502
  def prerender_tag(name, self_close, attributes)
502
503
  # TODO: consider just passing in the damn options here
503
504
  attributes_string = Compiler.build_attributes(
504
- @options.html?, @options[:attr_wrapper], @options[:escape_attrs], @options[:hyphenate_data_attrs], attributes)
505
+ @options.html?, @options.attr_wrapper, @options.escape_attrs, @options.hyphenate_data_attrs, attributes)
505
506
  "<#{name}#{attributes_string}#{self_close && @options.xhtml? ? ' /' : ''}>"
506
507
  end
507
508
 
@@ -509,7 +510,7 @@ END
509
510
  diff = @node.line - @output_line
510
511
  return "" if diff <= 0
511
512
  @output_line = @node.line
512
- "\n" * [diff, 0].max
513
+ "\n" * diff
513
514
  end
514
515
 
515
516
  # Get rid of and whitespace at the end of the buffer