hamlet 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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: