@@ -13,7 +13,7 @@ class SandlebarsParser
13
13
def self . truth_hash ( array )
14
14
hash = { }
15
15
array . each { |v | hash [ v ] = true }
16
-
16
+
17
17
return hash
18
18
end
19
19
@@ -23,64 +23,64 @@ def self.truth_hash(array)
23
23
ATTRIBUTES = /([-\: A-Za-z0-9_]+)(?:\s *=\s *(?:(?:"((?:\\ .|[^"])*)")|(?:'((?:\\ .|[^'])*)')|([^>\s ]+)))?/
24
24
25
25
# Types of elements
26
- BLOCK = truth_hash ( %w{ address applet blockquote button center dd del dir div dl dt fieldset form frameset hr iframe ins isindex li map menu noframes noscript object ol p pre script table tbody td tfoot th thead tr ul } )
26
+ BLOCK = truth_hash ( %w{ a address applet blockquote button center dd del dir div dl dt fieldset form frameset hr iframe ins isindex li map menu noframes noscript object ol p pre script table tbody td tfoot th thead tr ul } )
27
27
EMPTY = truth_hash ( %w{ area base basefont br col frame hr img input isindex link meta param embed } )
28
- INLINE = truth_hash ( %w{ a abbr acronym applet b basefont bdo big br button cite code del dfn em font i iframe img input ins kbd label map object q s samp script select small span strike strong sub sup textarea tt u var } )
28
+ INLINE = truth_hash ( %w{ abbr acronym applet b basefont bdo big br button cite code del dfn em font i iframe img input ins kbd label map object q s samp script select small span strike strong sub sup textarea tt u var } )
29
29
CLOSE_SELF = truth_hash ( %w{ colgroup dd dt li options p td tfoot th thead tr } )
30
30
SPECIAL = truth_hash ( %w{ script style } )
31
-
31
+
32
32
FILL_IN_ATTRIBUTES = truth_hash ( %w{ checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected } )
33
-
33
+
34
34
def initialize ( html , handler , file_path = nil )
35
35
@html = StringScanner . new ( html )
36
36
@handler = handler
37
37
@file_path = file_path
38
-
38
+
39
39
@stack = [ ]
40
-
40
+
41
41
parse
42
42
end
43
-
43
+
44
44
def last
45
45
@stack . last
46
46
end
47
-
47
+
48
48
def parse
49
49
loop do
50
50
if last && SPECIAL [ last ]
51
51
# In a script or style tag, just look for the first end
52
52
close_tag = "</#{ last } >"
53
53
body = @html . scan_until ( /#{ close_tag } / )
54
54
body = body [ 0 ..( ( -1 * close_tag . size ) -1 ) ]
55
-
55
+
56
56
body = body . gsub ( /\< \! --(.*?)--\> / , "\\ 1" ) . gsub ( /\< \! \[ CDATA\[ (.*?)\] \] \> / , "\\ 1" )
57
-
57
+
58
58
text ( body )
59
-
59
+
60
60
end_tag ( last , last )
61
61
elsif @html . scan ( /\< \! --/ )
62
62
# start comment
63
63
comment = @html . scan_until ( /--\> / )
64
64
comment = comment [ 0 ..-4 ]
65
-
65
+
66
66
@handler . comment ( comment ) if @handler . respond_to? ( :comment )
67
67
elsif ( tag = @html . scan ( START_TAG ) )
68
68
tag_name = @html [ 1 ]
69
69
rest = @html [ 2 ]
70
70
unary = @html [ 3 ]
71
-
71
+
72
72
start_tag ( tag , tag_name , rest , unary )
73
73
elsif @html . scan ( END_TAG )
74
74
tag_name = @html [ 1 ]
75
-
75
+
76
76
end_tag ( tag_name , tag_name )
77
77
elsif ( escaped = @html . scan ( /\{ \{ \{ (.*?)\} \} \} ([^\} ]|$)/ ) )
78
78
# Anything between {{{ and }}} is escaped and not processed (treaded as text)
79
79
if escaped [ -1 ] != '}'
80
80
# Move back if we matched a new non } for close, skip if we hit the end
81
81
@html . pos = @html . pos - 1
82
82
end
83
-
83
+
84
84
text ( @html [ 1 ] )
85
85
elsif ( binding = @html . scan ( /\{ / ) )
86
86
# We are in text mode and matched the start of a binding
@@ -93,14 +93,14 @@ def parse
93
93
break
94
94
end
95
95
end
96
-
96
+
97
97
end_tag ( nil , nil )
98
98
end
99
-
99
+
100
100
def text ( text )
101
101
@handler . text ( text ) if @handler . respond_to? ( :text )
102
102
end
103
-
103
+
104
104
# Findings the end of a binding
105
105
def start_binding
106
106
binding = ''
@@ -109,7 +109,7 @@ def start_binding
109
109
# scan until we reach a { or }
110
110
loop do
111
111
binding << @html . scan_until ( /([\{ \} \n ]|\Z )/ )
112
-
112
+
113
113
match = @html [ 1 ]
114
114
if match == '}'
115
115
# close
@@ -126,23 +126,23 @@ def start_binding
126
126
raise "should not reach here"
127
127
end
128
128
end
129
-
129
+
130
130
binding = binding [ 0 ..-2 ]
131
- @handler . binding ( binding ) if @handler . respond_to? ( :binding )
131
+ @handler . binding ( binding ) if @handler . respond_to? ( :binding )
132
132
end
133
-
133
+
134
134
def raise_parse_error ( error )
135
135
line_number = @html . pre_match . count ( "\n " ) + 1
136
-
136
+
137
137
error_str = error + " on line: #{ line_number } "
138
138
error_str += " of #{ @file_path } " if @file_path
139
139
140
140
raise HTMLParseError , error_str
141
141
end
142
-
142
+
143
143
def start_tag ( tag , tag_name , rest , unary )
144
144
section_tag = tag_name [ 0 ] == ':' && tag_name [ 1 ] =~ /[A-Z]/
145
-
145
+
146
146
tag_name = tag_name . downcase
147
147
148
148
# handle doctype so we get it output exactly the same way
@@ -157,45 +157,45 @@ def start_tag(tag, tag_name, rest, unary)
157
157
end_tag ( nil , last )
158
158
end
159
159
end
160
-
160
+
161
161
# Some tags close themselves when a new one of themselves is reached.
162
162
# ex, a tr will close the previous tr
163
163
if CLOSE_SELF [ tag_name ] && last == tag_name
164
164
end_tag ( nil , tag_name )
165
165
end
166
-
166
+
167
167
unary = EMPTY [ tag_name ] || !unary . blank?
168
-
168
+
169
169
# Section tag's are also unary
170
170
unless unary || section_tag
171
171
@stack . push ( tag_name )
172
172
end
173
-
173
+
174
174
if @handler . respond_to? ( :start_tag )
175
175
attributes = { }
176
-
176
+
177
177
# Take the rest string and extract the attributes, filling in any
178
178
# "fill in" attribute values if not provided.
179
179
rest . scan ( ATTRIBUTES ) . each do |match |
180
180
name = match [ 0 ]
181
-
181
+
182
182
value = match [ 1 ] || match [ 2 ] || match [ 3 ] || FILL_IN_ATTRIBUTES [ name ] || ''
183
-
183
+
184
184
attributes [ name ] = value
185
185
end
186
-
186
+
187
187
if section_tag
188
188
@handler . start_section ( tag_name , attributes , unary )
189
189
else
190
190
@handler . start_tag ( tag_name , attributes , unary )
191
191
end
192
192
end
193
193
end
194
-
194
+
195
195
def end_tag ( tag , tag_name )
196
196
# If no tag name is provided, close all the way up
197
197
new_size = 0
198
-
198
+
199
199
if tag
200
200
# Find the closest tag that closes.
201
201
( @stack . size -1 ) . downto ( 0 ) do |index |
@@ -205,7 +205,7 @@ def end_tag(tag, tag_name)
205
205
end
206
206
end
207
207
end
208
-
208
+
209
209
if new_size >= 0
210
210
if @handler . respond_to? ( :end_tag )
211
211
( @stack . size -1 ) . downto ( new_size ) do |index |
0 commit comments