haml 2.2.4 → 2.2.5
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.
- data/CONTRIBUTING +4 -0
- data/VERSION +1 -1
- data/lib/haml/buffer.rb +1 -1
- data/lib/haml/precompiler.rb +8 -8
- data/test/haml/engine_test.rb +23 -0
- data/test/haml/results/just_stuff.xhtml +3 -3
- data/test/haml/spec/README.md +53 -0
- data/test/haml/spec/lua_haml_spec.lua +37 -0
- data/test/haml/spec/ruby_haml_spec.rb +24 -0
- data/test/haml/spec/tests.json +105 -0
- metadata +8 -2
data/CONTRIBUTING
ADDED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.2.
|
1
|
+
2.2.5
|
data/lib/haml/buffer.rb
CHANGED
@@ -245,7 +245,7 @@ RUBY
|
|
245
245
|
# @return [Hash<String, String>] `to`, after being merged
|
246
246
|
def self.merge_attrs(to, from)
|
247
247
|
if to['id'] && from['id']
|
248
|
-
to['id'] << '_' << from.delete('id')
|
248
|
+
to['id'] << '_' << from.delete('id').to_s
|
249
249
|
elsif to['id'] || from['id']
|
250
250
|
from['id'] ||= to['id']
|
251
251
|
end
|
data/lib/haml/precompiler.rb
CHANGED
@@ -79,7 +79,7 @@ module Haml
|
|
79
79
|
#
|
80
80
|
# The block is ended after <tt>%p no!</tt>, because <tt>else</tt>
|
81
81
|
# is a member of this array.
|
82
|
-
MID_BLOCK_KEYWORD_REGEX =
|
82
|
+
MID_BLOCK_KEYWORD_REGEX = /^-\s*(#{%w[else elsif rescue ensure when end].join('|')})\b/
|
83
83
|
|
84
84
|
# The Regex that matches a Doctype command.
|
85
85
|
DOCTYPE_REGEX = /(\d\.\d)?[\s]*([a-z]*)/i
|
@@ -109,8 +109,8 @@ END
|
|
109
109
|
|
110
110
|
names.map do |name|
|
111
111
|
# Can't use || because someone might explicitly pass in false with a symbol
|
112
|
-
sym_local = "_haml_locals[#{name.to_sym.inspect}]"
|
113
|
-
str_local = "_haml_locals[#{name.to_s.inspect}]"
|
112
|
+
sym_local = "_haml_locals[#{name.to_sym.inspect}]"
|
113
|
+
str_local = "_haml_locals[#{name.to_s.inspect}]"
|
114
114
|
"#{name} = #{sym_local}.nil? ? #{str_local} : #{sym_local}"
|
115
115
|
end.join(';') + ';'
|
116
116
|
end
|
@@ -228,9 +228,9 @@ END
|
|
228
228
|
newline_now
|
229
229
|
|
230
230
|
# Handle stuff like - end.join("|")
|
231
|
-
@to_close_stack.first << false if text =~
|
231
|
+
@to_close_stack.first << false if text =~ /^-\s*end\b/ && !block_opened?
|
232
232
|
|
233
|
-
case_stmt = text =~
|
233
|
+
case_stmt = text =~ /^-\s*case\b/
|
234
234
|
block = block_opened? && !mid_block_keyword?(text)
|
235
235
|
push_and_tabulate([:script]) if block || case_stmt
|
236
236
|
push_and_tabulate(:nil) if block && case_stmt
|
@@ -719,7 +719,7 @@ END
|
|
719
719
|
else
|
720
720
|
open_tag << "\n" unless parse || nuke_inner_whitespace || (self_closing && nuke_outer_whitespace)
|
721
721
|
end
|
722
|
-
|
722
|
+
|
723
723
|
push_merged_text(open_tag, tag_closed || self_closing || nuke_inner_whitespace ? 0 : 1,
|
724
724
|
!nuke_outer_whitespace)
|
725
725
|
|
@@ -775,11 +775,11 @@ END
|
|
775
775
|
raise SyntaxError.new('Illegal nesting: nesting within a tag that already has content is illegal.', @next_line.index)
|
776
776
|
end
|
777
777
|
|
778
|
-
open = "<!--#{conditional}
|
778
|
+
open = "<!--#{conditional}"
|
779
779
|
|
780
780
|
# Render it statically if possible
|
781
781
|
unless line.empty?
|
782
|
-
return push_text("#{open}#{line} #{conditional ? "<![endif]-->" : "-->"}")
|
782
|
+
return push_text("#{open} #{line} #{conditional ? "<![endif]-->" : "-->"}")
|
783
783
|
end
|
784
784
|
|
785
785
|
push_text(open, 1)
|
data/test/haml/engine_test.rb
CHANGED
@@ -107,6 +107,11 @@ class EngineTest < Test::Unit::TestCase
|
|
107
107
|
assert_equal("<div class='atlantis' style='ugly'></div>", render(".atlantis{:style => 'ugly'}").chomp)
|
108
108
|
end
|
109
109
|
|
110
|
+
def test_css_id_as_attribute_should_be_appended_with_underscore
|
111
|
+
assert_equal("<div id='my_id_1'></div>", render("#my_id{:id => '1'}").chomp)
|
112
|
+
assert_equal("<div id='my_id_1'></div>", render("#my_id{:id => 1}").chomp)
|
113
|
+
end
|
114
|
+
|
110
115
|
def test_ruby_code_should_work_inside_attributes
|
111
116
|
author = 'hcatlin'
|
112
117
|
assert_equal("<p class='3'>foo</p>", render("%p{:class => 1+2} foo").chomp)
|
@@ -463,6 +468,24 @@ HTML
|
|
463
468
|
HAML
|
464
469
|
end
|
465
470
|
|
471
|
+
def test_silent_script_with_hyphen_case
|
472
|
+
assert_equal("", render("- 'foo-case-bar-case'"))
|
473
|
+
end
|
474
|
+
|
475
|
+
def test_silent_script_with_hyphen_end
|
476
|
+
assert_equal("", render("- 'foo-end-bar-end'"))
|
477
|
+
end
|
478
|
+
|
479
|
+
def test_silent_script_with_hyphen_end_and_block
|
480
|
+
assert_equal(<<HTML, render(<<HAML))
|
481
|
+
<p>foo-end</p>
|
482
|
+
<p>bar-end</p>
|
483
|
+
HTML
|
484
|
+
- "foo-end-bar-end".gsub(/\\w+-end/) do |s|
|
485
|
+
%p= s
|
486
|
+
HAML
|
487
|
+
end
|
488
|
+
|
466
489
|
# HTML escaping tests
|
467
490
|
|
468
491
|
def test_ampersand_equals_should_escape
|
@@ -26,7 +26,7 @@ stuff followed by whitespace
|
|
26
26
|
yee\ha
|
27
27
|
</p>
|
28
28
|
<!-- Short comment -->
|
29
|
-
<!--
|
29
|
+
<!--
|
30
30
|
This is a block comment
|
31
31
|
cool, huh?
|
32
32
|
<strong>there can even be sub-tags!</strong>
|
@@ -35,13 +35,13 @@ stuff followed by whitespace
|
|
35
35
|
<p class=''>class attribute should appear!</p>
|
36
36
|
<p>this attribute shouldn't appear</p>
|
37
37
|
<!--[if lte IE6]> conditional comment! <![endif]-->
|
38
|
-
<!--[if gte IE7]>
|
38
|
+
<!--[if gte IE7]>
|
39
39
|
<p>Block conditional comment</p>
|
40
40
|
<div>
|
41
41
|
<h1>Cool, eh?</h1>
|
42
42
|
</div>
|
43
43
|
<![endif]-->
|
44
|
-
<!--[if gte IE5.2]>
|
44
|
+
<!--[if gte IE5.2]>
|
45
45
|
Woah a period.
|
46
46
|
<![endif]-->
|
47
47
|
testtest
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# Haml Spec #
|
2
|
+
|
3
|
+
Haml Spec provides a basic suite of tests for Haml interpreters.
|
4
|
+
|
5
|
+
It is intented for developers who are creating or maintaining an
|
6
|
+
implementation of the [Haml](http://haml-lang.com) markup language.
|
7
|
+
|
8
|
+
At the moment, there are test runners for the [original Haml](http://github.com/nex3/haml)
|
9
|
+
in Ruby, and for [Lua Haml](http://github.com/norman/lua-haml). Support for
|
10
|
+
other versions of Haml will be added if their developers/maintainers
|
11
|
+
are interested in using it.
|
12
|
+
|
13
|
+
## The Tests ##
|
14
|
+
|
15
|
+
The tests are kept in JSON format for portability across languages.
|
16
|
+
Each test is a simple key/value pair of input and expected output.
|
17
|
+
The test suite only provides tests for features which are portable,
|
18
|
+
therefore no tests for script are provided, nor for external filters
|
19
|
+
such as :markdown or :textile.
|
20
|
+
|
21
|
+
## Running the Tests ##
|
22
|
+
|
23
|
+
### Ruby ###
|
24
|
+
|
25
|
+
The Ruby test uses RSpec, so just install the gem and run `spec ruby_haml_spec.rb`.
|
26
|
+
I have only tested it against Ruby 1.9; if you want to run it on an older Ruby
|
27
|
+
you'll need to install the "json" gem.
|
28
|
+
|
29
|
+
### Lua ###
|
30
|
+
|
31
|
+
The Lua test depends on [Telescope](http://telescope.luaforge.net/),
|
32
|
+
[jason4lua](http://json.luaforge.net/), and
|
33
|
+
[Lua Haml](http://github.com/norman/lua-haml). Install and
|
34
|
+
run `tsc lua_haml_spec.lua`.
|
35
|
+
|
36
|
+
## Contributing ##
|
37
|
+
|
38
|
+
You can access the Git repo at:
|
39
|
+
|
40
|
+
http://github.com/norman/haml-spec
|
41
|
+
|
42
|
+
As long as any test you add run against Ruby's Haml and are not redundant,
|
43
|
+
I'll be very happy to add them.
|
44
|
+
|
45
|
+
## License ##
|
46
|
+
|
47
|
+
This project is released under the [WTFPL](http://sam.zoy.org/wtfpl/)
|
48
|
+
in order to be as usable as possible in any project, commercial or free.
|
49
|
+
|
50
|
+
|
51
|
+
## Author ##
|
52
|
+
|
53
|
+
[Norman Clarke](mailto:norman@njclarke.com)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'luarocks.require'
|
2
|
+
require 'json'
|
3
|
+
require 'telescope'
|
4
|
+
require 'haml'
|
5
|
+
|
6
|
+
local function get_tests(filename)
|
7
|
+
local self = debug.getinfo(1).short_src
|
8
|
+
if self:match("/") then return "./" .. self:gsub("[^/]*%.lua$", "/" .. filename)
|
9
|
+
elseif self:match("\\") then return self:gsub("[^\\]*%.lua$", "\\" .. filename)
|
10
|
+
else return filename
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
local fh = assert(io.open(get_tests("tests.json")))
|
15
|
+
local input = fh:read '*a'
|
16
|
+
fh:close()
|
17
|
+
|
18
|
+
local contexts = json.decode(input)
|
19
|
+
|
20
|
+
local locals = {
|
21
|
+
var = "value",
|
22
|
+
first = "a",
|
23
|
+
last = "z"
|
24
|
+
}
|
25
|
+
|
26
|
+
describe("The LuaHaml Renderer", function()
|
27
|
+
for context, expectations in pairs(contexts) do
|
28
|
+
describe("When handling " .. context, function()
|
29
|
+
for input, expectation in pairs(expectations) do
|
30
|
+
it(string.format("should render '%s' as '%s'", string.gsub(input, "\n", "\\n"),
|
31
|
+
string.gsub(expectation, "\n", "\\n")), function()
|
32
|
+
assert_equal(haml.render(input, {}, locals), expectation)
|
33
|
+
end)
|
34
|
+
end
|
35
|
+
end)
|
36
|
+
end
|
37
|
+
end)
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "json"
|
2
|
+
require "haml"
|
3
|
+
contexts = JSON.parse(File.read(File.dirname(__FILE__) + "/tests.json"))
|
4
|
+
|
5
|
+
locals = {
|
6
|
+
:var => "value",
|
7
|
+
:first => "a",
|
8
|
+
:last => "z"
|
9
|
+
}
|
10
|
+
|
11
|
+
contexts.each do |context|
|
12
|
+
name = context[0]
|
13
|
+
expectations = context[1]
|
14
|
+
describe "When handling #{name}," do
|
15
|
+
expectations.each do |input, expected|
|
16
|
+
it "should render \"#{input}\" as \"#{expected}\"" do
|
17
|
+
engine = Haml::Engine.new(input)
|
18
|
+
engine.render(Object.new, locals).chomp.should == expected
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
@@ -0,0 +1,105 @@
|
|
1
|
+
{
|
2
|
+
"headers": {
|
3
|
+
"!!! XML": "<?xml version='1.0' encoding='utf-8' ?>",
|
4
|
+
"!!!": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">",
|
5
|
+
"!!! 1.1": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">",
|
6
|
+
"!!! frameset": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Frameset//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd\">",
|
7
|
+
"!!! mobile": "<!DOCTYPE html PUBLIC \"-//WAPFORUM//DTD XHTML Mobile 1.2//EN\" \"http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd\">",
|
8
|
+
"!!! basic": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML Basic 1.1//EN\" \"http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd\">"
|
9
|
+
},
|
10
|
+
|
11
|
+
"basic Haml tags and CSS": {
|
12
|
+
"%p": "<p></p>",
|
13
|
+
"%meta": "<meta />",
|
14
|
+
"#id1": "<div id='id1'></div>",
|
15
|
+
".class1": "<div class='class1'></div>",
|
16
|
+
"%p.class1": "<p class='class1'></p>",
|
17
|
+
"%p.class1.class2": "<p class='class1 class2'></p>",
|
18
|
+
"%p#id1": "<p id='id1'></p>",
|
19
|
+
"%p#id1#id2": "<p id='id2'></p>",
|
20
|
+
"%p.class1#id1": "<p class='class1' id='id1'></p>",
|
21
|
+
"%p#id1.class1": "<p class='class1' id='id1'></p>"
|
22
|
+
},
|
23
|
+
|
24
|
+
"tags with unusual HTML characters": {
|
25
|
+
"%ns:tag": "<ns:tag></ns:tag>",
|
26
|
+
"%snake_case": "<snake_case></snake_case>",
|
27
|
+
"%dashed-tag": "<dashed-tag></dashed-tag>",
|
28
|
+
"%camelCase": "<camelCase></camelCase>",
|
29
|
+
"%PascalCase": "<PascalCase></PascalCase>"
|
30
|
+
},
|
31
|
+
|
32
|
+
"tags with unusual CSS identifiers": {
|
33
|
+
".123": "<div class='123'></div>",
|
34
|
+
".__": "<div class='__'></div>",
|
35
|
+
".--": "<div class='--'></div>"
|
36
|
+
},
|
37
|
+
|
38
|
+
"tags with inline content": {
|
39
|
+
"%p hello": "<p>hello</p>",
|
40
|
+
"%p.class1 hello": "<p class='class1'>hello</p>"
|
41
|
+
},
|
42
|
+
|
43
|
+
"tags with nested content": {
|
44
|
+
"%p\n hello": "<p>\n hello\n</p>"
|
45
|
+
},
|
46
|
+
|
47
|
+
"tags with portable-style attributes": {
|
48
|
+
"%p(a='b')": "<p a='b'></p>",
|
49
|
+
"%p(a='b' c='d')": "<p a='b' c='d'></p>",
|
50
|
+
"%p(a='b'\n c='d')": "<p a='b' c='d'></p>",
|
51
|
+
"%p(class='class1')": "<p class='class1'></p>",
|
52
|
+
"%p.class2(class='class1')": "<p class='class1 class2'></p>",
|
53
|
+
"%p#id(id='1')": "<p id='id_1'></p>",
|
54
|
+
".hello(class=var)": "<div class='hello value'></div>",
|
55
|
+
".b(class=last)": "<div class='b z'></div>",
|
56
|
+
".b(class=first)": "<div class='a b'></div>"
|
57
|
+
},
|
58
|
+
|
59
|
+
"tags with Ruby-style attributes": {
|
60
|
+
"%p{:a => 'b'}": "<p a='b'></p>",
|
61
|
+
"%p{ :a => 'b' }": "<p a='b'></p>",
|
62
|
+
"%p{ :a => 'b', 'c' => 'd' }": "<p a='b' c='d'></p>",
|
63
|
+
"%p{ :a => 'b',\n 'c' => 'd' }": "<p a='b' c='d'></p>",
|
64
|
+
"%p{ :a => var}": "<p a='value'></p>",
|
65
|
+
"%p#id{ :id => '1' }": "<p id='id_1'></p>",
|
66
|
+
"%p#id{ :id => 1 }": "<p id='id_1'></p>",
|
67
|
+
"%p{ :a => \"#{var}\"}": "<p a='value'></p>",
|
68
|
+
".b{ :class => last }": "<div class='b z'></div>",
|
69
|
+
".b{ :class => first }": "<div class='a b'></div>"
|
70
|
+
},
|
71
|
+
|
72
|
+
"inline comments": {
|
73
|
+
"-# hello\n%p": "<p></p>"
|
74
|
+
},
|
75
|
+
|
76
|
+
"silent comments": {
|
77
|
+
"-# nothing\n%p": "<p></p>",
|
78
|
+
"-# nothing\n nested\n%p": "<p></p>"
|
79
|
+
},
|
80
|
+
|
81
|
+
"markup comments": {
|
82
|
+
"/ comment": "<!-- comment -->",
|
83
|
+
"/\n comment\n comment2": "<!--\n comment\n comment2\n-->"
|
84
|
+
},
|
85
|
+
|
86
|
+
"conditional comments": {
|
87
|
+
"/[if IE]\n %p a": "<!--[if IE]>\n <p>a</p>\n<![endif]-->"
|
88
|
+
},
|
89
|
+
|
90
|
+
"internal filters": {
|
91
|
+
":escaped\n <&\">": "<&">",
|
92
|
+
":preserve\n hello\n\n%p": "hello
\n<p></p>",
|
93
|
+
":plain\n hello\n\n%p": "hello\n<p></p>",
|
94
|
+
":javascript\n a();\n%p": "<script type='text/javascript'>\n //<![CDATA[\n a();\n //]]>\n</script>\n<p></p>"
|
95
|
+
},
|
96
|
+
|
97
|
+
"interpolation": {
|
98
|
+
"%p= \"#{var}\"": "<p>value</p>",
|
99
|
+
"%p #{var}": "<p>value</p>",
|
100
|
+
"%p \\#{var}": "<p>#{var}</p>",
|
101
|
+
"%p \\\\#{var}": "<p>\\value</p>",
|
102
|
+
":plain\n #{var} interpolated: #{var}": "value interpolated: value"
|
103
|
+
}
|
104
|
+
|
105
|
+
}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: haml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nathan Weizenbaum
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2009-09-
|
13
|
+
date: 2009-09-18 00:00:00 -07:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -48,6 +48,7 @@ extra_rdoc_files:
|
|
48
48
|
- README.md
|
49
49
|
- VERSION_NAME
|
50
50
|
- REVISION
|
51
|
+
- CONTRIBUTING
|
51
52
|
files:
|
52
53
|
- rails/init.rb
|
53
54
|
- lib/sass.rb
|
@@ -196,6 +197,10 @@ files:
|
|
196
197
|
- test/haml/templates/original_engine.haml
|
197
198
|
- test/haml/templates/breakage.haml
|
198
199
|
- test/haml/templates/action_view.haml
|
200
|
+
- test/haml/spec/tests.json
|
201
|
+
- test/haml/spec/lua_haml_spec.lua
|
202
|
+
- test/haml/spec/ruby_haml_spec.rb
|
203
|
+
- test/haml/spec/README.md
|
199
204
|
- test/haml/results/content_for_layout.xhtml
|
200
205
|
- test/haml/results/just_stuff.xhtml
|
201
206
|
- test/haml/results/whitespace_handling.xhtml
|
@@ -230,6 +235,7 @@ files:
|
|
230
235
|
- README.md
|
231
236
|
- VERSION_NAME
|
232
237
|
- REVISION
|
238
|
+
- CONTRIBUTING
|
233
239
|
has_rdoc: true
|
234
240
|
homepage: http://haml.hamptoncatlin.com/
|
235
241
|
licenses: []
|