hamlet 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +11 -0
- data/hamlet.gemspec +1 -1
- data/lib/hamlet/parser.rb +105 -34
- data/test/slim/helper.rb +3 -1
- data/test/slim/test_html_structure.rb +25 -25
- metadata +24 -24
data/README.md
CHANGED
@@ -60,3 +60,14 @@ I added the same syntax that hamlet.js uses to indicate whitespace: a closing br
|
|
60
60
|
## Limitations
|
61
61
|
|
62
62
|
I just hacked this up the other day - let me know if there are any issues. After some more experience using Slim's syntax I plan on trying to reduce the total available syntax.
|
63
|
+
|
64
|
+
## Development
|
65
|
+
|
66
|
+
Run tests with
|
67
|
+
|
68
|
+
rake test
|
69
|
+
|
70
|
+
or
|
71
|
+
|
72
|
+
ruby -r ./test/slim/helper.rb TEST
|
73
|
+
|
data/hamlet.gemspec
CHANGED
data/lib/hamlet/parser.rb
CHANGED
@@ -45,57 +45,128 @@ module Hamlet
|
|
45
45
|
end
|
46
46
|
|
47
47
|
private
|
48
|
+
def parse_line
|
49
|
+
if @line =~ /\A\s*\Z/
|
50
|
+
@stacks.last << [:newline]
|
51
|
+
return
|
52
|
+
end
|
53
|
+
|
54
|
+
indent = get_indent(@line)
|
55
|
+
|
56
|
+
# Remove the indentation
|
57
|
+
@line.lstrip!
|
58
|
+
indent +=1 if @line[0] == '>'
|
59
|
+
|
60
|
+
# If there's more stacks than indents, it means that the previous
|
61
|
+
# line is expecting this line to be indented.
|
62
|
+
expecting_indentation = @stacks.size > @indents.size
|
63
|
+
|
64
|
+
if indent > @indents.last
|
65
|
+
# This line was actually indented, so we'll have to check if it was
|
66
|
+
# supposed to be indented or not.
|
67
|
+
unless expecting_indentation
|
68
|
+
syntax_error!('Unexpected indentation')
|
69
|
+
end
|
70
|
+
|
71
|
+
@indents << indent
|
72
|
+
else
|
73
|
+
# This line was *not* indented more than the line before,
|
74
|
+
# so we'll just forget about the stack that the previous line pushed.
|
75
|
+
@stacks.pop if expecting_indentation
|
76
|
+
|
77
|
+
# This line was deindented.
|
78
|
+
# Now we're have to go through the all the indents and figure out
|
79
|
+
# how many levels we've deindented.
|
80
|
+
while indent < @indents.last
|
81
|
+
@indents.pop
|
82
|
+
@stacks.pop
|
83
|
+
end
|
84
|
+
|
85
|
+
# This line's indentation happens lie "between" two other line's
|
86
|
+
# indentation:
|
87
|
+
#
|
88
|
+
# hello
|
89
|
+
# world
|
90
|
+
# this # <- This should not be possible!
|
91
|
+
syntax_error!('Malformed indentation') if indent != @indents.last
|
92
|
+
end
|
93
|
+
|
94
|
+
parse_line_indicators
|
95
|
+
end
|
48
96
|
|
49
97
|
def parse_line_indicators
|
50
|
-
|
51
|
-
|
98
|
+
if @needs_space
|
99
|
+
@stacks.last << [:slim, :interpolate, "\n" ]
|
100
|
+
@stacks.last << [:newline]
|
101
|
+
end
|
102
|
+
@needs_space = false
|
103
|
+
case @line[0]
|
104
|
+
when '-' # code block.
|
52
105
|
block = [:multi]
|
53
106
|
@line.slice!(0)
|
54
107
|
@stacks.last << [:slim, :control, parse_broken_line, block]
|
55
108
|
@stacks << block
|
56
|
-
when
|
109
|
+
when '=' # output block.
|
57
110
|
@line =~ /\A=(=?)('?)/
|
58
111
|
@line = $'
|
59
112
|
block = [:multi]
|
60
113
|
@stacks.last << [:slim, :output, $1.empty?, parse_broken_line, block]
|
61
114
|
@stacks.last << [:static, ' '] unless $2.empty?
|
62
115
|
@stacks << block
|
63
|
-
when
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
@stacks << block
|
81
|
-
when /\A(?:\s*>( *))?/ # text block.
|
82
|
-
@stacks.last << [:slim, :interpolate, $1 ? $1 << $' : $']
|
83
|
-
parse_text_block($'.empty? ? nil : @indents.last + $1.to_s.size)
|
116
|
+
when '<'
|
117
|
+
case @line
|
118
|
+
when /\A<(\w+):\s*\Z/ # Embedded template. It is treated as block.
|
119
|
+
block = [:multi]
|
120
|
+
@stacks.last << [:newline] << [:slim, :embedded, $1, block]
|
121
|
+
@stacks << block
|
122
|
+
parse_text_block(nil, :from_embedded)
|
123
|
+
return # Don't append newline, this has already been done before
|
124
|
+
when /\A<([#\.]|\w[:\w-]*)/ # HTML tag.
|
125
|
+
parse_tag($1)
|
126
|
+
when /\A<!--( ?)(.*)\Z/ # HTML comment
|
127
|
+
block = [:multi]
|
128
|
+
@stacks.last << [:html, :comment, block]
|
129
|
+
@stacks << block
|
130
|
+
@stacks.last << [:slim, :interpolate, $2] unless $2.empty?
|
131
|
+
parse_text_block($2.empty? ? nil : @indents.last + $1.size + 2)
|
132
|
+
end
|
84
133
|
else
|
85
|
-
|
134
|
+
if @line =~ %r!\A#\[\s*(.*?)\s*\]\s*\Z! # HTML conditional comment
|
135
|
+
block = [:multi]
|
136
|
+
@stacks.last << [:slim, :condcomment, $1, block]
|
137
|
+
@stacks << block
|
138
|
+
else
|
139
|
+
push_text
|
140
|
+
end
|
86
141
|
end
|
87
142
|
@stacks.last << [:newline]
|
88
143
|
end
|
89
144
|
|
90
|
-
def
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
145
|
+
def push_text
|
146
|
+
@needs_space = true
|
147
|
+
if @line[0] == '>'
|
148
|
+
@line.slice!(0)
|
149
|
+
end
|
150
|
+
if @line =~ /(\A|[^\\])#([^{]|\Z)/
|
151
|
+
@line = $` + $1
|
96
152
|
end
|
153
|
+
@stacks.last << [:slim, :interpolate, @line]
|
154
|
+
end
|
97
155
|
|
156
|
+
# This is fundamentally broken
|
157
|
+
# Can keep this for multi-lie html comment perhaps
|
158
|
+
# But don't lookahead on text otherwise
|
159
|
+
def parse_text_block(text_indent = nil, from = nil)
|
160
|
+
empty_lines = 0
|
98
161
|
first_line = true
|
162
|
+
embedded = nil
|
163
|
+
case from
|
164
|
+
when :from_tag
|
165
|
+
first_line = true
|
166
|
+
when :from_embedded
|
167
|
+
embedded = true
|
168
|
+
end
|
169
|
+
|
99
170
|
close_bracket = false
|
100
171
|
until @lines.empty?
|
101
172
|
if @lines.first =~ /\A\s*>?\s*\Z/
|
@@ -135,7 +206,7 @@ module Hamlet
|
|
135
206
|
if @line =~ /(\A|[^\\])#([^{]|\Z)/
|
136
207
|
@line = $` + $1
|
137
208
|
end
|
138
|
-
@stacks.last << [:newline] if
|
209
|
+
@stacks.last << [:newline] if !first_line && !embedded
|
139
210
|
@stacks.last << [:slim, :interpolate, (text_indent ? "\n" : '') + @line] << [:newline]
|
140
211
|
|
141
212
|
# The indentation of first line of the text block
|
@@ -143,7 +214,6 @@ module Hamlet
|
|
143
214
|
text_indent ||= indent
|
144
215
|
|
145
216
|
first_line = false
|
146
|
-
multi_line = true
|
147
217
|
end
|
148
218
|
end
|
149
219
|
end
|
@@ -161,6 +231,7 @@ module Hamlet
|
|
161
231
|
|
162
232
|
case @line
|
163
233
|
when /\A=(=?)('?)/ # Handle output code
|
234
|
+
@needs_space = true
|
164
235
|
block = [:multi]
|
165
236
|
@line = $'
|
166
237
|
content = [:slim, :output, $1 != '=', parse_broken_line, block]
|
@@ -175,10 +246,10 @@ module Hamlet
|
|
175
246
|
when %r!\A/>!
|
176
247
|
# Do nothing for closing tag
|
177
248
|
else # Text content
|
249
|
+
@needs_space = true
|
178
250
|
content = [:multi, [:slim, :interpolate, @line]]
|
179
251
|
tag << content
|
180
252
|
@stacks << content
|
181
|
-
parse_text_block(@orig_line.size - @line.size, :from_tag)
|
182
253
|
end
|
183
254
|
end
|
184
255
|
|
data/test/slim/helper.rb
CHANGED
@@ -11,7 +11,7 @@ class TestSlimHtmlStructure < TestSlim
|
|
11
11
|
<p>Hello World, meet Slim.
|
12
12
|
}
|
13
13
|
|
14
|
-
assert_html
|
14
|
+
assert_html "<html><head><title>Simple Test Title</title></head>\n<body><p>Hello World, meet Slim.</p></body></html>", source
|
15
15
|
end
|
16
16
|
|
17
17
|
def test_html_tag_with_text_and_empty_line
|
@@ -22,7 +22,7 @@ class TestSlimHtmlStructure < TestSlim
|
|
22
22
|
<p>World
|
23
23
|
}
|
24
24
|
|
25
|
-
assert_html "<p>Hello</p
|
25
|
+
assert_html "<p>Hello</p>\n<p>World</p>", source
|
26
26
|
end
|
27
27
|
|
28
28
|
def test_html_namespaces
|
@@ -68,7 +68,7 @@ class TestSlimHtmlStructure < TestSlim
|
|
68
68
|
= hello_world
|
69
69
|
}
|
70
70
|
|
71
|
-
assert_html
|
71
|
+
assert_html %Q{<h1 id="title">This is my title</h1>\n<div class="hello world" id="notice">Hello World from @env</div>}, source
|
72
72
|
end
|
73
73
|
|
74
74
|
def test_render_with_overwritten_default_tag
|
@@ -96,17 +96,18 @@ class TestSlimHtmlStructure < TestSlim
|
|
96
96
|
<p>Some more markup
|
97
97
|
}
|
98
98
|
|
99
|
-
assert_html
|
99
|
+
assert_html "<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>\n<p>Some more markup</p>", source
|
100
100
|
end
|
101
101
|
|
102
102
|
def test_render_with_text_block_with_trailing_whitespace
|
103
103
|
source = %q{
|
104
|
-
|
105
|
-
|
106
|
-
|
104
|
+
<p>
|
105
|
+
this is
|
106
|
+
> a link to
|
107
|
+
<a href="link">page
|
107
108
|
}
|
108
109
|
|
109
|
-
assert_html "this is\n a link to<a href=\"link\">page</a>", source
|
110
|
+
assert_html "<p>this is\n a link to\n<a href=\"link\">page</a></p>", source
|
110
111
|
end
|
111
112
|
|
112
113
|
def test_nested_text
|
@@ -119,45 +120,44 @@ this is
|
|
119
120
|
<p>This is a new paragraph.
|
120
121
|
}
|
121
122
|
|
122
|
-
assert_html "<p>This is line one.\n This is line two.\n This is line three.\n This is line four.</p
|
123
|
+
assert_html "<p>This is line one.\n This is line two.\n This is line three.\n This is line four.</p>\n<p>This is a new paragraph.</p>", source
|
123
124
|
end
|
124
125
|
|
125
126
|
def test_nested_text_with_nested_html_one_same_line
|
126
127
|
source = %q{
|
127
128
|
<p
|
128
|
-
|
129
|
+
This is line one.
|
129
130
|
> This is line two.
|
130
|
-
|
131
|
+
<span.bold>This is a bold line in the paragraph.
|
131
132
|
> This is more content.
|
132
133
|
}
|
133
134
|
|
134
|
-
assert_html "<p>This is line one.\n This is line two
|
135
|
+
assert_html "<p>This is line one.\n This is line two.\n<span class=\"bold\">This is a bold line in the paragraph.</span>\n This is more content.</p>", source
|
135
136
|
end
|
136
137
|
|
137
138
|
def test_nested_text_with_nested_html_one_same_line2
|
138
139
|
source = %q{
|
139
140
|
<p
|
140
|
-
|
141
|
+
This is line one.
|
141
142
|
> This is line two.
|
142
|
-
|
143
|
+
<span.bold>This is a bold line in the paragraph.
|
143
144
|
> This is more content.
|
144
145
|
}
|
145
146
|
|
146
|
-
assert_html "<p>This is line one.\n This is line two
|
147
|
+
assert_html "<p>This is line one.\n This is line two.\n<span class=\"bold\">This is a bold line in the paragraph.</span>\n This is more content.</p>", source
|
147
148
|
end
|
148
149
|
|
149
150
|
def test_nested_text_with_nested_html
|
150
151
|
source = %q{
|
151
|
-
<p
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
> This is more content.
|
152
|
+
<p>This is line one.
|
153
|
+
> This is line two.
|
154
|
+
> This is line three.
|
155
|
+
> This is line four.
|
156
|
+
<span.bold>This is a bold line in the paragraph.
|
157
|
+
> This is more content.
|
158
158
|
}
|
159
159
|
|
160
|
-
assert_html "<p>This is line one.\n This is line two.\n This is line three.\n This is line four
|
160
|
+
assert_html "<p>This is line one.\n This is line two.\n This is line three.\n This is line four.\n<span class=\"bold\">This is a bold line in the paragraph.</span>\n This is more content.</p>", source
|
161
161
|
end
|
162
162
|
|
163
163
|
def test_simple_paragraph_with_padding
|
@@ -202,7 +202,7 @@ this is
|
|
202
202
|
<p> =hello_world
|
203
203
|
}
|
204
204
|
|
205
|
-
assert_html
|
205
|
+
assert_html "<p>Hello World from @env</p>\n<p> = hello_world</p>\n<p> =hello_world</p>", source
|
206
206
|
end
|
207
207
|
|
208
208
|
def test_single_quoted_attributes
|
@@ -333,7 +333,7 @@ this is
|
|
333
333
|
<p>World
|
334
334
|
}
|
335
335
|
|
336
|
-
assert_html "<p>Hello</p
|
336
|
+
assert_html "<p>Hello</p>\n<!--This is a comment\n\nAnother comment--><p>World</p>", source
|
337
337
|
end
|
338
338
|
|
339
339
|
def test_render_with_html_conditional_and_tag
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hamlet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-10-
|
12
|
+
date: 2011-10-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: slim
|
16
|
-
requirement: &
|
16
|
+
requirement: &3510800 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 1.0.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *3510800
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rake
|
27
|
-
requirement: &
|
27
|
+
requirement: &3486040 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 0.8.7
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *3486040
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: sass
|
38
|
-
requirement: &
|
38
|
+
requirement: &3485160 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 3.1.0
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *3485160
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: minitest
|
49
|
-
requirement: &
|
49
|
+
requirement: &3483060 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *3483060
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: kramdown
|
60
|
-
requirement: &
|
60
|
+
requirement: &3481600 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *3481600
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: yard
|
71
|
-
requirement: &
|
71
|
+
requirement: &3480640 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *3480640
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: creole
|
82
|
-
requirement: &
|
82
|
+
requirement: &3442060 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *3442060
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: builder
|
93
|
-
requirement: &
|
93
|
+
requirement: &3440300 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,10 +98,10 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *3440300
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: pry
|
104
|
-
requirement: &
|
104
|
+
requirement: &3439300 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ! '>='
|
@@ -109,10 +109,10 @@ dependencies:
|
|
109
109
|
version: '0'
|
110
110
|
type: :development
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *3439300
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: ruby-debug19
|
115
|
-
requirement: &
|
115
|
+
requirement: &3437480 !ruby/object:Gem::Requirement
|
116
116
|
none: false
|
117
117
|
requirements:
|
118
118
|
- - ! '>='
|
@@ -120,10 +120,10 @@ dependencies:
|
|
120
120
|
version: '0'
|
121
121
|
type: :development
|
122
122
|
prerelease: false
|
123
|
-
version_requirements: *
|
123
|
+
version_requirements: *3437480
|
124
124
|
- !ruby/object:Gem::Dependency
|
125
125
|
name: rcov
|
126
|
-
requirement: &
|
126
|
+
requirement: &3435020 !ruby/object:Gem::Requirement
|
127
127
|
none: false
|
128
128
|
requirements:
|
129
129
|
- - ! '>='
|
@@ -131,7 +131,7 @@ dependencies:
|
|
131
131
|
version: '0'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
|
-
version_requirements: *
|
134
|
+
version_requirements: *3435020
|
135
135
|
description: Hamlet is a template language whose goal is reduce HTML syntax to the
|
136
136
|
essential parts.
|
137
137
|
email:
|