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 +4 -4
- data/CHANGELOG.md +11 -23
- data/README.md +3 -2
- data/REFERENCE.md +24 -9
- data/Rakefile +5 -4
- data/lib/haml/buffer.rb +27 -26
- data/lib/haml/compiler.rb +71 -70
- data/lib/haml/engine.rb +16 -26
- data/lib/haml/exec.rb +9 -7
- data/lib/haml/filters.rb +16 -22
- data/lib/haml/helpers.rb +97 -74
- data/lib/haml/helpers/action_view_extensions.rb +2 -2
- data/lib/haml/helpers/action_view_mods.rb +10 -3
- data/lib/haml/options.rb +6 -14
- data/lib/haml/parser.rb +184 -182
- data/lib/haml/util.rb +67 -78
- data/lib/haml/version.rb +1 -1
- data/test/engine_test.rb +80 -71
- data/test/gemfiles/Gemfile.rails-3.0.x +1 -1
- data/test/gemfiles/Gemfile.rails-3.1.x +1 -1
- data/test/gemfiles/Gemfile.rails-3.2.x +1 -1
- data/test/gemfiles/Gemfile.rails-4.0.x +1 -1
- data/test/gemfiles/Gemfile.rails-4.0.x.lock +101 -0
- data/test/helper_test.rb +85 -33
- data/test/parser_test.rb +22 -0
- data/test/template_test.rb +1 -29
- data/test/templates/with_bom.haml +1 -0
- data/test/test_helper.rb +4 -0
- data/test/util_test.rb +7 -1
- metadata +39 -44
- data/test/haml-spec/LICENSE +0 -14
- data/test/haml-spec/README.md +0 -106
- data/test/haml-spec/lua_haml_spec.lua +0 -38
- data/test/haml-spec/perl_haml_test.pl +0 -81
- data/test/haml-spec/ruby_haml_test.rb +0 -23
- data/test/haml-spec/tests.json +0 -660
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e558b5f2cf40a4dc76dd5a6d4a6fd7410087cea
|
4
|
+
data.tar.gz: de7642c1dd34404f48def114391e5070ea0d78fa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1713fd685aee4177c59ea3f3353c65a875c2cc3cbf8a840c20c96d2bd2308dad11f28c04d73fde0bfcedfd7e3e50e90a2b20ae17ee0fe8769285971cb5f651bf
|
7
|
+
data.tar.gz: f6a1e655ac0fdaeeb9ae8e215fad6b79673da33f9c404ac192dca1f8dbc8bb81becb33250554c3e2b29907054efb6e28b22349a1153126ba09b40fd1ff734de5
|
data/CHANGELOG.md
CHANGED
@@ -1,28 +1,16 @@
|
|
1
1
|
# Haml Changelog
|
2
2
|
|
3
|
-
## 4.0
|
4
|
-
|
5
|
-
|
6
|
-
(
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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.
|
130
|
-
both 1.9 and
|
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
|
|
data/REFERENCE.md
CHANGED
@@ -121,7 +121,7 @@ see {Haml::Options}.
|
|
121
121
|
|
122
122
|
### Encodings
|
123
123
|
|
124
|
-
|
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
|
-
|
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
|
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`).
|
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 `:
|
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
|
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
|
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("
|
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 } }
|
data/lib/haml/buffer.rb
CHANGED
@@ -178,7 +178,7 @@ module Haml
|
|
178
178
|
<% end %>
|
179
179
|
|
180
180
|
if has_newline
|
181
|
-
result
|
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'] <<
|
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
|
-
|
250
|
-
|
249
|
+
from.keys.each do |key|
|
250
|
+
next unless from[key].kind_of?(Hash) || to[key].kind_of?(Hash)
|
251
251
|
|
252
|
-
|
253
|
-
|
254
|
-
|
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
|
-
|
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 =
|
278
|
+
pattern = /([ ]*)<(textarea)([^>]*)>(\n|
)(.*?)(<\/\2>)/im
|
274
279
|
input.gsub!(pattern) do |s|
|
275
280
|
match = pattern.match(s)
|
276
|
-
content = match[
|
277
|
-
if match[
|
281
|
+
content = match[5]
|
282
|
+
if match[4] == '
'
|
278
283
|
content.sub!(/\A /, ' ')
|
279
284
|
else
|
280
285
|
content.sub!(/\A[ ]*/, '')
|
281
286
|
end
|
282
|
-
"
|
287
|
+
"#{match[1]}<#{match[2]}#{match[3]}>\n#{content}</#{match[2]}>"
|
283
288
|
end
|
284
289
|
end
|
285
290
|
|
286
|
-
|
287
|
-
|
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.
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
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
|
data/lib/haml/compiler.rb
CHANGED
@@ -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
|
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
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
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.
|
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.
|
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
|
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
|
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
|
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
|
160
|
-
object_ref =
|
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 ==
|
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 = ",
|
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
|
-
"
|
198
|
+
" />#{"\n" unless t[:nuke_outer_whitespace]}"
|
207
199
|
else
|
208
|
-
"
|
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]
|
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]}
|
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]}
|
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
|
-
|
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]} #{
|
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(
|
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
|
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
|
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
|
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.
|
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
|
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
|
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 =
|
381
|
-
args.map! {|name| opts[name
|
382
|
-
args << !block_given? << @options
|
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
|
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
|
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
|
-
|
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 == '"' ? """ : "'"
|
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
|
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
|
471
|
-
|
472
|
-
|
473
|
-
|
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.
|
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,
|
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
|
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" *
|
513
|
+
"\n" * diff
|
513
514
|
end
|
514
515
|
|
515
516
|
# Get rid of and whitespace at the end of the buffer
|