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
data/lib/haml/util.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
begin
|
2
4
|
require 'erubis/tiny'
|
3
5
|
rescue LoadError
|
@@ -57,7 +59,7 @@ module Haml
|
|
57
59
|
# Returns an ActionView::Template* class.
|
58
60
|
# In pre-3.0 versions of Rails, most of these classes
|
59
61
|
# were of the form `ActionView::TemplateFoo`,
|
60
|
-
# while afterwards they were of the form `ActionView
|
62
|
+
# while afterwards they were of the form `ActionView::Template::Foo`.
|
61
63
|
#
|
62
64
|
# @param name [#to_s] The name of the class to get.
|
63
65
|
# For example, `:Error` will return `ActionView::TemplateError`
|
@@ -89,7 +91,7 @@ module Haml
|
|
89
91
|
text.html_safe
|
90
92
|
end
|
91
93
|
|
92
|
-
# Checks that the encoding of a string is valid
|
94
|
+
# Checks that the encoding of a string is valid
|
93
95
|
# and cleans up potential encoding gotchas like the UTF-8 BOM.
|
94
96
|
# If it's not, yields an error string describing the invalid character
|
95
97
|
# and the line on which it occurrs.
|
@@ -99,89 +101,78 @@ module Haml
|
|
99
101
|
# Only yields if there is an encoding error
|
100
102
|
# @yieldparam msg [String] The error message to be raised
|
101
103
|
# @return [String] `str`, potentially with encoding gotchas like BOMs removed
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
return str.gsub(Regexp.new("\\A\uFEFF".encode(str.encoding.name)), '')
|
113
|
-
else
|
114
|
-
return str
|
115
|
-
end
|
104
|
+
def check_encoding(str)
|
105
|
+
if str.valid_encoding?
|
106
|
+
# Get rid of the Unicode BOM if possible
|
107
|
+
# Shortcut for UTF-8 which might be the majority case
|
108
|
+
if str.encoding == Encoding::UTF_8
|
109
|
+
return str.gsub(/\A\uFEFF/, '')
|
110
|
+
elsif str.encoding.name =~ /^UTF-(16|32)(BE|LE)?$/
|
111
|
+
return str.gsub(Regexp.new("\\A\uFEFF".encode(str.encoding)), '')
|
112
|
+
else
|
113
|
+
return str
|
116
114
|
end
|
115
|
+
end
|
117
116
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
117
|
+
encoding = str.encoding
|
118
|
+
newlines = Regexp.new("\r\n|\r|\n".encode(encoding).force_encoding(Encoding::ASCII_8BIT))
|
119
|
+
str.force_encoding(Encoding::ASCII_8BIT).split(newlines).each_with_index do |line, i|
|
120
|
+
begin
|
121
|
+
line.encode(encoding)
|
122
|
+
rescue Encoding::UndefinedConversionError => e
|
123
|
+
yield <<MSG.rstrip, i + 1
|
125
124
|
Invalid #{encoding.name} character #{e.error_char.dump}
|
126
125
|
MSG
|
127
|
-
end
|
128
126
|
end
|
129
|
-
return str
|
130
127
|
end
|
128
|
+
return str
|
131
129
|
end
|
132
130
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
check_encoding(str, &block)
|
156
|
-
end
|
157
|
-
else
|
158
|
-
def check_haml_encoding(str, &block)
|
159
|
-
str = str.dup if str.frozen?
|
160
|
-
|
161
|
-
bom, encoding = parse_haml_magic_comment(str)
|
162
|
-
if encoding; str.force_encoding(encoding)
|
163
|
-
elsif bom; str.force_encoding("UTF-8")
|
164
|
-
end
|
131
|
+
# Like {\#check\_encoding}, but also checks for a Ruby-style `-# coding:` comment
|
132
|
+
# at the beginning of the template and uses that encoding if it exists.
|
133
|
+
#
|
134
|
+
# The Haml encoding rules are simple.
|
135
|
+
# If a `-# coding:` comment exists,
|
136
|
+
# we assume that that's the original encoding of the document.
|
137
|
+
# Otherwise, we use whatever encoding Ruby has.
|
138
|
+
#
|
139
|
+
# Haml uses the same rules for parsing coding comments as Ruby.
|
140
|
+
# This means that it can understand Emacs-style comments
|
141
|
+
# (e.g. `-*- encoding: "utf-8" -*-`),
|
142
|
+
# and also that it cannot understand non-ASCII-compatible encodings
|
143
|
+
# such as `UTF-16` and `UTF-32`.
|
144
|
+
#
|
145
|
+
# @param str [String] The Haml template of which to check the encoding
|
146
|
+
# @yield [msg] A block in which an encoding error can be raised.
|
147
|
+
# Only yields if there is an encoding error
|
148
|
+
# @yieldparam msg [String] The error message to be raised
|
149
|
+
# @return [String] The original string encoded properly
|
150
|
+
# @raise [ArgumentError] if the document declares an unknown encoding
|
151
|
+
def check_haml_encoding(str, &block)
|
152
|
+
str = str.dup if str.frozen?
|
165
153
|
|
166
|
-
|
154
|
+
bom, encoding = parse_haml_magic_comment(str)
|
155
|
+
if encoding; str.force_encoding(encoding)
|
156
|
+
elsif bom; str.force_encoding(Encoding::UTF_8)
|
167
157
|
end
|
158
|
+
|
159
|
+
return check_encoding(str, &block)
|
168
160
|
end
|
169
161
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
'"' + obj.gsub(/[\x00-\x7F]+/) {|s| s.inspect[1...-1]} + '"'
|
162
|
+
# Like `Object#inspect`, but preserves non-ASCII characters rather than escaping them.
|
163
|
+
# This is necessary so that the precompiled Haml template can be `#encode`d into `@options[:encoding]`
|
164
|
+
# before being evaluated.
|
165
|
+
#
|
166
|
+
# @param obj {Object}
|
167
|
+
# @return {String}
|
168
|
+
def inspect_obj(obj)
|
169
|
+
case obj
|
170
|
+
when String
|
171
|
+
%Q!"#{obj.gsub(/[\x00-\x7F]+/) {|s| s.inspect[1...-1]}}"!
|
172
|
+
when Symbol
|
173
|
+
":#{inspect_obj(obj.to_s)}"
|
174
|
+
else
|
175
|
+
obj.inspect
|
185
176
|
end
|
186
177
|
end
|
187
178
|
|
@@ -283,10 +274,8 @@ METHOD
|
|
283
274
|
# from to
|
284
275
|
#
|
285
276
|
# @param scanner [StringScanner] The string scanner to move
|
286
|
-
# @param start [
|
287
|
-
#
|
288
|
-
# @param finish [Character] The character closing the balanced pair.
|
289
|
-
# A `Fixnum` in 1.8, a `String` in 1.9
|
277
|
+
# @param start [String] The character opening the balanced pair.
|
278
|
+
# @param finish [String] The character closing the balanced pair.
|
290
279
|
# @param count [Fixnum] The number of opening characters matched
|
291
280
|
# before calling this method
|
292
281
|
# @return [(String, String)] The string matched within the balanced pair
|
@@ -350,7 +339,7 @@ METHOD
|
|
350
339
|
# Whether the document begins with a UTF-8 BOM,
|
351
340
|
# and the declared encoding of the document (or nil if none is declared)
|
352
341
|
def parse_haml_magic_comment(str)
|
353
|
-
scanner = StringScanner.new(str.dup.force_encoding(
|
342
|
+
scanner = StringScanner.new(str.dup.force_encoding(Encoding::ASCII_8BIT))
|
354
343
|
bom = scanner.scan(/\xEF\xBB\xBF/n)
|
355
344
|
return bom unless scanner.scan(/-\s*#\s*/n)
|
356
345
|
if coding = try_parse_haml_emacs_magic_comment(scanner)
|
data/lib/haml/version.rb
CHANGED
data/test/engine_test.rb
CHANGED
@@ -113,13 +113,11 @@ class EngineTest < MiniTest::Unit::TestCase
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def setup
|
116
|
-
return if RUBY_VERSION < "1.9"
|
117
116
|
@old_default_internal = Encoding.default_internal
|
118
117
|
silence_warnings{Encoding.default_internal = nil}
|
119
118
|
end
|
120
119
|
|
121
120
|
def teardown
|
122
|
-
return if RUBY_VERSION < "1.9"
|
123
121
|
silence_warnings{Encoding.default_internal = @old_default_internal}
|
124
122
|
end
|
125
123
|
|
@@ -407,9 +405,8 @@ HAML
|
|
407
405
|
|
408
406
|
# Regression tests
|
409
407
|
|
410
|
-
|
411
|
-
|
412
|
-
assert_equal(<<HTML, render(<<HAML))
|
408
|
+
def test_indentation_after_dynamic_attr_hash
|
409
|
+
assert_equal(<<HTML, render(<<HAML))
|
413
410
|
<html>
|
414
411
|
<body>
|
415
412
|
<img src='test'>
|
@@ -423,7 +420,6 @@ HTML
|
|
423
420
|
%img{:src => 'te'+'st'}
|
424
421
|
= "foo\\nbar"
|
425
422
|
HAML
|
426
|
-
end
|
427
423
|
end
|
428
424
|
|
429
425
|
def test_whitespace_nuke_with_both_newlines
|
@@ -1210,6 +1206,16 @@ HAML
|
|
1210
1206
|
render("/[if !(IE 6)|(IE 7)] Bracket: ]"))
|
1211
1207
|
end
|
1212
1208
|
|
1209
|
+
def test_downlevel_revealed_conditional_comments
|
1210
|
+
assert_equal("<!--[if !IE]><!--> A comment <!--<![endif]-->\n",
|
1211
|
+
render("/![if !IE] A comment"))
|
1212
|
+
end
|
1213
|
+
|
1214
|
+
def test_downlevel_revealed_conditional_comments_block
|
1215
|
+
assert_equal("<!--[if !IE]><!-->\n A comment\n<!--<![endif]-->\n",
|
1216
|
+
render("/![if !IE]\n A comment"))
|
1217
|
+
end
|
1218
|
+
|
1213
1219
|
def test_local_assigns_dont_modify_class
|
1214
1220
|
assert_equal("bar\n", render("= foo", :locals => {:foo => 'bar'}))
|
1215
1221
|
assert_equal(nil, defined?(foo))
|
@@ -1467,6 +1473,15 @@ HAML
|
|
1467
1473
|
render("%div{:foo => {:baz => 'bang'}}"))
|
1468
1474
|
end
|
1469
1475
|
|
1476
|
+
def test_arbitrary_attribute_hash_merging
|
1477
|
+
assert_equal(%Q{<a aria-baz='qux' aria-foo='bar'></a>\n}, render(<<-HAML))
|
1478
|
+
- h1 = {:aria => {:foo => :bar}}
|
1479
|
+
- h2 = {:baz => :qux}
|
1480
|
+
%a{h1, :aria => h2}
|
1481
|
+
HAML
|
1482
|
+
end
|
1483
|
+
|
1484
|
+
|
1470
1485
|
def test_html5_data_attributes_with_nested_hash
|
1471
1486
|
assert_equal("<div data-a-b='c'></div>\n", render(<<-HAML))
|
1472
1487
|
- hash = {:a => {:b => 'c'}}
|
@@ -1696,11 +1711,7 @@ HAML
|
|
1696
1711
|
end
|
1697
1712
|
|
1698
1713
|
def test_ruby_character_literals_are_not_continuation
|
1699
|
-
html =
|
1700
|
-
"44\n44\n<p>foo</p>\n"
|
1701
|
-
else
|
1702
|
-
",\n,\n<p>foo</p>\n"
|
1703
|
-
end
|
1714
|
+
html = ",\n,\n<p>foo</p>\n"
|
1704
1715
|
assert_equal(html, render(<<HAML))
|
1705
1716
|
= ?,
|
1706
1717
|
= ?\,
|
@@ -1874,60 +1885,59 @@ HTML
|
|
1874
1885
|
HAML
|
1875
1886
|
end
|
1876
1887
|
|
1877
|
-
|
1878
|
-
|
1879
|
-
assert_equal(Encoding.find("utf-8"), render(<<HAML.encode("us-ascii")).encoding)
|
1888
|
+
def test_default_encoding
|
1889
|
+
assert_equal(Encoding.find("utf-8"), render(<<HAML.encode("us-ascii")).encoding)
|
1880
1890
|
%p bar
|
1881
1891
|
%p foo
|
1882
1892
|
HAML
|
1883
|
-
|
1893
|
+
end
|
1884
1894
|
|
1885
|
-
|
1886
|
-
|
1895
|
+
def test_fake_ascii_encoding
|
1896
|
+
assert_encoded_equal(<<HTML.force_encoding("ascii-8bit"), render(<<HAML, :encoding => "ascii-8bit"))
|
1887
1897
|
<p>bâr</p>
|
1888
1898
|
<p>föö</p>
|
1889
1899
|
HTML
|
1890
1900
|
%p bâr
|
1891
1901
|
%p föö
|
1892
1902
|
HAML
|
1893
|
-
|
1903
|
+
end
|
1894
1904
|
|
1895
|
-
|
1896
|
-
|
1897
|
-
|
1905
|
+
def test_convert_template_render_proc
|
1906
|
+
assert_converts_template_properly {|e| e.render_proc.call}
|
1907
|
+
end
|
1898
1908
|
|
1899
|
-
|
1900
|
-
|
1901
|
-
|
1909
|
+
def test_convert_template_render
|
1910
|
+
assert_converts_template_properly {|e| e.render}
|
1911
|
+
end
|
1902
1912
|
|
1903
|
-
|
1904
|
-
|
1905
|
-
|
1906
|
-
|
1907
|
-
|
1908
|
-
end
|
1913
|
+
def test_convert_template_def_method
|
1914
|
+
assert_converts_template_properly do |e|
|
1915
|
+
o = Object.new
|
1916
|
+
e.def_method(o, :render)
|
1917
|
+
o.render
|
1909
1918
|
end
|
1919
|
+
end
|
1910
1920
|
|
1911
|
-
|
1912
|
-
|
1913
|
-
|
1914
|
-
|
1915
|
-
|
1916
|
-
|
1917
|
-
|
1921
|
+
def test_encoding_error
|
1922
|
+
render("foo\nbar\nb\xFEaz".force_encoding("utf-8"))
|
1923
|
+
assert(false, "Expected exception")
|
1924
|
+
rescue Haml::Error => e
|
1925
|
+
assert_equal(3, e.line)
|
1926
|
+
assert_match(/Invalid .* character/, e.message)
|
1927
|
+
end
|
1918
1928
|
|
1919
|
-
|
1920
|
-
|
1921
|
-
|
1922
|
-
|
1923
|
-
|
1924
|
-
|
1925
|
-
|
1926
|
-
|
1927
|
-
|
1929
|
+
def test_ascii_incompatible_encoding_error
|
1930
|
+
template = "foo\nbar\nb_z".encode("utf-16le")
|
1931
|
+
template[9] = "\xFE".force_encoding("utf-16le")
|
1932
|
+
render(template)
|
1933
|
+
assert(false, "Expected exception")
|
1934
|
+
rescue Haml::Error => e
|
1935
|
+
assert_equal(3, e.line)
|
1936
|
+
assert_match(/Invalid .* character/, e.message)
|
1937
|
+
end
|
1928
1938
|
|
1929
|
-
|
1930
|
-
|
1939
|
+
def test_same_coding_comment_as_encoding
|
1940
|
+
assert_renders_encoded(<<HTML, <<HAML)
|
1931
1941
|
<p>bâr</p>
|
1932
1942
|
<p>föö</p>
|
1933
1943
|
HTML
|
@@ -1935,34 +1945,33 @@ HTML
|
|
1935
1945
|
%p bâr
|
1936
1946
|
%p föö
|
1937
1947
|
HAML
|
1938
|
-
|
1939
|
-
|
1940
|
-
def test_coding_comments
|
1941
|
-
assert_valid_encoding_comment("-# coding: ibm866")
|
1942
|
-
assert_valid_encoding_comment("-# CodINg: IbM866")
|
1943
|
-
assert_valid_encoding_comment("-#coding:ibm866")
|
1944
|
-
assert_valid_encoding_comment("-# CodINg= ibm866")
|
1945
|
-
assert_valid_encoding_comment("-# foo BAR FAOJcoding: ibm866")
|
1946
|
-
assert_valid_encoding_comment("-# coding: ibm866 ASFJ (&(&#!$")
|
1947
|
-
assert_valid_encoding_comment("-# -*- coding: ibm866")
|
1948
|
-
assert_valid_encoding_comment("-# coding: ibm866 -*- coding: blah")
|
1949
|
-
assert_valid_encoding_comment("-# -*- coding: ibm866 -*-")
|
1950
|
-
assert_valid_encoding_comment("-# -*- encoding: ibm866 -*-")
|
1951
|
-
assert_valid_encoding_comment('-# -*- coding: "ibm866" -*-')
|
1952
|
-
assert_valid_encoding_comment("-#-*-coding:ibm866-*-")
|
1953
|
-
assert_valid_encoding_comment("-#-*-coding:ibm866-*-")
|
1954
|
-
assert_valid_encoding_comment("-# -*- foo: bar; coding: ibm866; baz: bang -*-")
|
1955
|
-
assert_valid_encoding_comment("-# foo bar coding: baz -*- coding: ibm866 -*-")
|
1956
|
-
assert_valid_encoding_comment("-# -*- coding: ibm866 -*- foo bar coding: baz")
|
1957
|
-
end
|
1948
|
+
end
|
1958
1949
|
|
1959
|
-
|
1960
|
-
|
1950
|
+
def test_coding_comments
|
1951
|
+
assert_valid_encoding_comment("-# coding: ibm866")
|
1952
|
+
assert_valid_encoding_comment("-# CodINg: IbM866")
|
1953
|
+
assert_valid_encoding_comment("-#coding:ibm866")
|
1954
|
+
assert_valid_encoding_comment("-# CodINg= ibm866")
|
1955
|
+
assert_valid_encoding_comment("-# foo BAR FAOJcoding: ibm866")
|
1956
|
+
assert_valid_encoding_comment("-# coding: ibm866 ASFJ (&(&#!$")
|
1957
|
+
assert_valid_encoding_comment("-# -*- coding: ibm866")
|
1958
|
+
assert_valid_encoding_comment("-# coding: ibm866 -*- coding: blah")
|
1959
|
+
assert_valid_encoding_comment("-# -*- coding: ibm866 -*-")
|
1960
|
+
assert_valid_encoding_comment("-# -*- encoding: ibm866 -*-")
|
1961
|
+
assert_valid_encoding_comment('-# -*- coding: "ibm866" -*-')
|
1962
|
+
assert_valid_encoding_comment("-#-*-coding:ibm866-*-")
|
1963
|
+
assert_valid_encoding_comment("-#-*-coding:ibm866-*-")
|
1964
|
+
assert_valid_encoding_comment("-# -*- foo: bar; coding: ibm866; baz: bang -*-")
|
1965
|
+
assert_valid_encoding_comment("-# foo bar coding: baz -*- coding: ibm866 -*-")
|
1966
|
+
assert_valid_encoding_comment("-# -*- coding: ibm866 -*- foo bar coding: baz")
|
1967
|
+
end
|
1968
|
+
|
1969
|
+
def test_different_coding_than_system
|
1970
|
+
assert_renders_encoded(<<HTML.encode("IBM866"), <<HAML.encode("IBM866"))
|
1961
1971
|
<p>тАЬ</p>
|
1962
1972
|
HTML
|
1963
1973
|
%p тАЬ
|
1964
1974
|
HAML
|
1965
|
-
end
|
1966
1975
|
end
|
1967
1976
|
|
1968
1977
|
def test_block_spacing
|