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 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
+
@@ -4,7 +4,7 @@ require 'date'
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'hamlet'
7
- s.version = '0.3.0'
7
+ s.version = '0.4.0'
8
8
  s.date = Date.today.to_s
9
9
  s.authors = ['Greg Weber']
10
10
  s.email = ['greg@gregweber.info']
@@ -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
- case @line
51
- when /\A-/ # code block.
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 /\A=/ # output block.
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 /\A<(\w+):\s*\Z/ # Embedded template. It is treated as block.
64
- block = [:multi]
65
- @stacks.last << [:newline] << [:slim, :embedded, $1, block]
66
- @stacks << block
67
- parse_text_block(nil, true)
68
- return # Don't append newline, this has already been done before
69
- when /\A<([#\.]|\w[:\w-]*)/ # HTML tag.
70
- parse_tag($1)
71
- when /\A<!--( ?)(.*)\Z/ # HTML comment
72
- block = [:multi]
73
- @stacks.last << [:html, :comment, block]
74
- @stacks << block
75
- @stacks.last << [:slim, :interpolate, $2] unless $2.empty?
76
- parse_text_block($2.empty? ? nil : @indents.last + $1.size + 2)
77
- when %r{\A#\[\s*(.*?)\s*\]\s*\Z} # HTML conditional comment
78
- block = [:multi]
79
- @stacks.last << [:slim, :condcomment, $1, block]
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
- syntax_error! 'Unknown line indicator'
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 parse_text_block(text_indent = nil, special = nil)
91
- empty_lines = 0
92
- multi_line = false
93
- if special == :from_tag
94
- multi_line = true
95
- special = nil
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 multi_line && !special
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
 
@@ -1,9 +1,11 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'rubygems'
3
+ require 'bundler'
4
+ Bundler.setup
4
5
  require 'minitest/unit'
5
6
  require 'hamlet'
6
7
  require 'slim/grammar'
8
+ $:.unshift(File.expand_path('..', __FILE__))
7
9
 
8
10
  MiniTest::Unit.autorun
9
11
 
@@ -11,7 +11,7 @@ class TestSlimHtmlStructure < TestSlim
11
11
  <p>Hello World, meet Slim.
12
12
  }
13
13
 
14
- assert_html '<html><head><title>Simple Test Title</title></head><body><p>Hello World, meet Slim.</p></body></html>', source
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><p>World</p>", source
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 '<h1 id="title">This is my title</h1><div class="hello world" id="notice">Hello World from @env</div>', source
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 '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p><p>Some more markup</p>', source
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
- this is
105
- a link to
106
- <a href="link">page
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><p>This is a new paragraph.</p>", source
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
- This is line one.
129
+ This is line one.
129
130
  > This is line two.
130
- <span.bold>This is a bold line in the paragraph.
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.<span class=\"bold\">This is a bold line in the paragraph.</span> This is more content.</p>", source
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
- This is line one.
141
+ This is line one.
141
142
  > This is line two.
142
- <span.bold>This is a bold line in the paragraph.
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.<span class=\"bold\">This is a bold line in the paragraph.</span> This is more content.</p>", source
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
- >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.
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.<span class=\"bold\">This is a bold line in the paragraph.</span> This is more content.</p>", source
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 '<p>Hello World from @env</p><p> = hello_world</p><p> =hello_world</p>', source
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><!--This is a comment\n\nAnother comment--><p>World</p>", source
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.3.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-29 00:00:00.000000000 Z
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: &3510320 !ruby/object:Gem::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: *3510320
24
+ version_requirements: *3510800
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rake
27
- requirement: &3485760 !ruby/object:Gem::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: *3485760
35
+ version_requirements: *3486040
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: sass
38
- requirement: &3484840 !ruby/object:Gem::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: *3484840
46
+ version_requirements: *3485160
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: minitest
49
- requirement: &3483280 !ruby/object:Gem::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: *3483280
57
+ version_requirements: *3483060
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: kramdown
60
- requirement: &3481100 !ruby/object:Gem::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: *3481100
68
+ version_requirements: *3481600
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: yard
71
- requirement: &3480020 !ruby/object:Gem::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: *3480020
79
+ version_requirements: *3480640
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: creole
82
- requirement: &3441840 !ruby/object:Gem::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: *3441840
90
+ version_requirements: *3442060
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: builder
93
- requirement: &3440280 !ruby/object:Gem::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: *3440280
101
+ version_requirements: *3440300
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: pry
104
- requirement: &3439140 !ruby/object:Gem::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: *3439140
112
+ version_requirements: *3439300
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: ruby-debug19
115
- requirement: &3437460 !ruby/object:Gem::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: *3437460
123
+ version_requirements: *3437480
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: rcov
126
- requirement: &3434620 !ruby/object:Gem::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: *3434620
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: