html5 0.1.0 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +9 -2
- data/Manifest.txt +61 -2
- data/README +41 -5
- data/Rakefile.rb +22 -6
- data/{parse.rb → bin/html5} +11 -11
- data/lib/core_ext/string.rb +17 -0
- data/lib/html5/constants.rb +228 -0
- data/lib/html5/filters/iso639codes.rb +752 -0
- data/lib/html5/filters/rfc2046.rb +30 -0
- data/lib/html5/filters/rfc3987.rb +89 -0
- data/lib/html5/filters/validator.rb +830 -0
- data/lib/html5/html5parser.rb +25 -25
- data/lib/html5/html5parser/after_body_phase.rb +3 -3
- data/lib/html5/html5parser/after_frameset_phase.rb +3 -4
- data/lib/html5/html5parser/after_head_phase.rb +6 -6
- data/lib/html5/html5parser/before_head_phase.rb +1 -1
- data/lib/html5/html5parser/in_body_phase.rb +54 -48
- data/lib/html5/html5parser/in_caption_phase.rb +7 -6
- data/lib/html5/html5parser/in_cell_phase.rb +3 -3
- data/lib/html5/html5parser/in_column_group_phase.rb +1 -1
- data/lib/html5/html5parser/in_frameset_phase.rb +5 -5
- data/lib/html5/html5parser/in_head_phase.rb +10 -10
- data/lib/html5/html5parser/in_row_phase.rb +4 -2
- data/lib/html5/html5parser/in_select_phase.rb +7 -6
- data/lib/html5/html5parser/in_table_body_phase.rb +8 -5
- data/lib/html5/html5parser/in_table_phase.rb +12 -7
- data/lib/html5/html5parser/initial_phase.rb +5 -6
- data/lib/html5/html5parser/phase.rb +5 -9
- data/lib/html5/html5parser/root_element_phase.rb +1 -2
- data/lib/html5/html5parser/trailing_end_phase.rb +3 -3
- data/lib/html5/inputstream.rb +25 -31
- data/lib/html5/liberalxmlparser.rb +2 -2
- data/lib/html5/sanitizer.rb +6 -6
- data/lib/html5/serializer/htmlserializer.rb +2 -3
- data/lib/html5/sniffer.rb +45 -0
- data/lib/html5/tokenizer.rb +57 -59
- data/lib/html5/treebuilders/rexml.rb +7 -6
- data/lib/html5/treebuilders/simpletree.rb +1 -1
- data/lib/html5/treewalkers/base.rb +8 -0
- data/lib/html5/version.rb +3 -0
- data/testdata/encoding/chardet/test_big5.txt +51 -0
- data/testdata/encoding/test-yahoo-jp.dat +10 -0
- data/testdata/encoding/tests1.dat +394 -0
- data/testdata/encoding/tests2.dat +81 -0
- data/testdata/sanitizer/tests1.dat +416 -0
- data/testdata/serializer/core.test +104 -0
- data/testdata/serializer/injectmeta.test +65 -0
- data/testdata/serializer/optionaltags.test +900 -0
- data/testdata/serializer/options.test +60 -0
- data/testdata/serializer/whitespace.test +51 -0
- data/testdata/sites/google-results.htm +1 -0
- data/testdata/sites/python-ref-import.htm +1 -0
- data/testdata/sites/web-apps-old.htm +1 -0
- data/testdata/sites/web-apps.htm +34275 -0
- data/testdata/sniffer/htmlOrFeed.json +43 -0
- data/testdata/tokenizer/contentModelFlags.test +48 -0
- data/testdata/tokenizer/entities.test +2339 -0
- data/testdata/tokenizer/escapeFlag.test +21 -0
- data/testdata/tokenizer/test1.test +172 -0
- data/testdata/tokenizer/test2.test +129 -0
- data/testdata/tokenizer/test3.test +367 -0
- data/testdata/tokenizer/test4.test +198 -0
- data/testdata/tree-construction/tests1.dat +1950 -0
- data/testdata/tree-construction/tests2.dat +773 -0
- data/testdata/tree-construction/tests3.dat +270 -0
- data/testdata/tree-construction/tests4.dat +60 -0
- data/testdata/tree-construction/tests5.dat +175 -0
- data/testdata/tree-construction/tests6.dat +196 -0
- data/testdata/validator/attributes.test +1035 -0
- data/testdata/validator/base-href-attribute.test +787 -0
- data/testdata/validator/base-target-attribute.test +35 -0
- data/testdata/validator/blockquote-cite-attribute.test +7 -0
- data/testdata/validator/classattribute.test +152 -0
- data/testdata/validator/contenteditableattribute.test +59 -0
- data/testdata/validator/contextmenuattribute.test +115 -0
- data/testdata/validator/dirattribute.test +59 -0
- data/testdata/validator/draggableattribute.test +63 -0
- data/testdata/validator/html-xmlns-attribute.test +23 -0
- data/testdata/validator/idattribute.test +115 -0
- data/testdata/validator/inputattributes.test +2795 -0
- data/testdata/validator/irrelevantattribute.test +63 -0
- data/testdata/validator/langattribute.test +5579 -0
- data/testdata/validator/li-value-attribute.test +7 -0
- data/testdata/validator/link-href-attribute.test +7 -0
- data/testdata/validator/link-hreflang-attribute.test +7 -0
- data/testdata/validator/link-rel-attribute.test +271 -0
- data/testdata/validator/ol-start-attribute.test +7 -0
- data/testdata/validator/starttags.test +375 -0
- data/testdata/validator/style-scoped-attribute.test +7 -0
- data/testdata/validator/tabindexattribute.test +79 -0
- data/tests/preamble.rb +7 -17
- data/tests/test_encoding.rb +1 -1
- data/tests/test_lxp.rb +16 -0
- data/tests/test_parser.rb +2 -2
- data/tests/test_sniffer.rb +27 -0
- data/tests/test_treewalkers.rb +41 -22
- data/tests/test_validator.rb +31 -0
- metadata +65 -6
data/lib/html5/html5parser.rb
CHANGED
@@ -46,8 +46,8 @@ module HTML5
|
|
46
46
|
@tree = TreeBuilders::REXML::TreeBuilder
|
47
47
|
|
48
48
|
options.each {|name, value| instance_variable_set("@#{name}", value) }
|
49
|
-
@lowercase_attr_name = nil unless
|
50
|
-
@lowercase_element_name = nil unless
|
49
|
+
@lowercase_attr_name = nil unless instance_variables.include?("@lowercase_attr_name")
|
50
|
+
@lowercase_element_name = nil unless instance_variables.include?("@lowercase_element_name")
|
51
51
|
|
52
52
|
@tree = @tree.new
|
53
53
|
|
@@ -69,15 +69,15 @@ module HTML5
|
|
69
69
|
|
70
70
|
if inner_html
|
71
71
|
case @inner_html = container.downcase
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
72
|
+
when 'title', 'textarea'
|
73
|
+
@tokenizer.content_model_flag = :RCDATA
|
74
|
+
when 'style', 'script', 'xmp', 'iframe', 'noembed', 'noframes', 'noscript'
|
75
|
+
@tokenizer.content_model_flag = :CDATA
|
76
|
+
when 'plaintext'
|
77
|
+
@tokenizer.content_model_flag = :PLAINTEXT
|
78
|
+
else
|
79
79
|
# content_model_flag already is PCDATA
|
80
|
-
|
80
|
+
@tokenizer.content_model_flag = :PCDATA
|
81
81
|
end
|
82
82
|
|
83
83
|
@phase = @phases[:rootElement]
|
@@ -100,17 +100,17 @@ module HTML5
|
|
100
100
|
method = 'process%s' % token[:type]
|
101
101
|
|
102
102
|
case token[:type]
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
103
|
+
when :Characters, :SpaceCharacters, :Comment
|
104
|
+
@phase.send method, token[:data]
|
105
|
+
when :StartTag
|
106
|
+
@phase.send method, token[:name], token[:data]
|
107
|
+
when :EndTag
|
108
|
+
@phase.send method, token[:name]
|
109
|
+
when :Doctype
|
110
|
+
@phase.send method, token[:name], token[:publicId],
|
111
|
+
token[:systemId], token[:correct]
|
112
|
+
else
|
113
|
+
parse_error(token[:data], token[:datavars])
|
114
114
|
end
|
115
115
|
end
|
116
116
|
|
@@ -147,9 +147,9 @@ module HTML5
|
|
147
147
|
@tree.get_fragment
|
148
148
|
end
|
149
149
|
|
150
|
-
def parse_error(
|
150
|
+
def parse_error(code = 'XXX-undefined-error', data = {})
|
151
151
|
# XXX The idea is to make data mandatory.
|
152
|
-
@errors.push([@tokenizer.stream.position, data])
|
152
|
+
@errors.push([@tokenizer.stream.position, code, data])
|
153
153
|
raise ParseError if @strict
|
154
154
|
end
|
155
155
|
|
@@ -163,7 +163,7 @@ module HTML5
|
|
163
163
|
# thing and if it doesn't it's wrong for everyone.
|
164
164
|
|
165
165
|
unless VOID_ELEMENTS.include?(token[:name])
|
166
|
-
parse_error(
|
166
|
+
parse_error("incorrectly-placed-solidus")
|
167
167
|
end
|
168
168
|
|
169
169
|
token[:type] = :StartTag
|
@@ -181,7 +181,7 @@ module HTML5
|
|
181
181
|
end
|
182
182
|
|
183
183
|
elsif token[:type] == :EndTag
|
184
|
-
parse_error(
|
184
|
+
parse_error("attributes-in-end-tag") unless token[:data].empty?
|
185
185
|
token[:name] = token[:name].downcase
|
186
186
|
end
|
187
187
|
|
@@ -12,13 +12,13 @@ module HTML5
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def processCharacters(data)
|
15
|
-
parse_error(
|
15
|
+
parse_error("unexpected-char-after-body")
|
16
16
|
@parser.phase = @parser.phases[:inBody]
|
17
17
|
@parser.phase.processCharacters(data)
|
18
18
|
end
|
19
19
|
|
20
20
|
def processStartTag(name, attributes)
|
21
|
-
parse_error(
|
21
|
+
parse_error("unexpected-start-tag-after-body", {"name" => name})
|
22
22
|
@parser.phase = @parser.phases[:inBody]
|
23
23
|
@parser.phase.processStartTag(name, attributes)
|
24
24
|
end
|
@@ -37,7 +37,7 @@ module HTML5
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def endTagOther(name)
|
40
|
-
parse_error(
|
40
|
+
parse_error("unexpected-end-tag-after-body", {"name" => name})
|
41
41
|
@parser.phase = @parser.phases[:inBody]
|
42
42
|
@parser.phase.processEndTag(name)
|
43
43
|
end
|
@@ -10,7 +10,7 @@ module HTML5
|
|
10
10
|
handle_end 'html'
|
11
11
|
|
12
12
|
def processCharacters(data)
|
13
|
-
parse_error(
|
13
|
+
parse_error("unexpected-char-after-frameset")
|
14
14
|
end
|
15
15
|
|
16
16
|
def startTagNoframes(name, attributes)
|
@@ -18,7 +18,7 @@ module HTML5
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def startTagOther(name, attributes)
|
21
|
-
parse_error(
|
21
|
+
parse_error("unexpected-start-tag-after-frameset", {"name" => name})
|
22
22
|
end
|
23
23
|
|
24
24
|
def endTagHtml(name)
|
@@ -27,8 +27,7 @@ module HTML5
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def endTagOther(name)
|
30
|
-
parse_error(
|
30
|
+
parse_error("unexpected-end-tag-after-frameset", {"name" => name})
|
31
31
|
end
|
32
|
-
|
33
32
|
end
|
34
33
|
end
|
@@ -6,12 +6,12 @@ module HTML5
|
|
6
6
|
handle_start 'html', 'body', 'frameset', %w( base link meta script style title ) => 'FromHead'
|
7
7
|
|
8
8
|
def process_eof
|
9
|
-
|
9
|
+
anything_else
|
10
10
|
@parser.phase.process_eof
|
11
11
|
end
|
12
12
|
|
13
13
|
def processCharacters(data)
|
14
|
-
|
14
|
+
anything_else
|
15
15
|
@parser.phase.processCharacters(data)
|
16
16
|
end
|
17
17
|
|
@@ -26,22 +26,22 @@ module HTML5
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def startTagFromHead(name, attributes)
|
29
|
-
parse_error(
|
29
|
+
parse_error("unexpected-start-tag-out-of-my-head", {"name" => name})
|
30
30
|
@parser.phase = @parser.phases[:inHead]
|
31
31
|
@parser.phase.processStartTag(name, attributes)
|
32
32
|
end
|
33
33
|
|
34
34
|
def startTagOther(name, attributes)
|
35
|
-
|
35
|
+
anything_else
|
36
36
|
@parser.phase.processStartTag(name, attributes)
|
37
37
|
end
|
38
38
|
|
39
39
|
def processEndTag(name)
|
40
|
-
|
40
|
+
anything_else
|
41
41
|
@parser.phase.processEndTag(name)
|
42
42
|
end
|
43
43
|
|
44
|
-
def
|
44
|
+
def anything_else
|
45
45
|
@tree.insert_element('body', {})
|
46
46
|
@parser.phase = @parser.phases[:inBody]
|
47
47
|
end
|
@@ -6,45 +6,45 @@ module HTML5
|
|
6
6
|
# http://www.whatwg.org/specs/web-apps/current-work/#in-body
|
7
7
|
|
8
8
|
handle_start 'html'
|
9
|
-
handle_start %w(
|
9
|
+
handle_start %w(base link meta script style) => 'ProcessInHead'
|
10
10
|
handle_start 'title'
|
11
11
|
|
12
12
|
handle_start 'body', 'form', 'plaintext', 'a', 'button', 'xmp', 'table', 'hr', 'image'
|
13
13
|
|
14
|
-
handle_start 'input', 'textarea', 'select', 'isindex', %w(
|
14
|
+
handle_start 'input', 'textarea', 'select', 'isindex', %w(marquee object)
|
15
15
|
|
16
|
-
handle_start %w(
|
17
|
-
|
18
|
-
handle_start %w( address blockquote center dir div dl fieldset listing menu ol p pre ul ) => 'CloseP'
|
16
|
+
handle_start %w(li dd dt) => 'ListItem'
|
19
17
|
|
20
|
-
handle_start %w(
|
18
|
+
handle_start %w(address blockquote center dir div dl fieldset listing menu ol p pre ul) => 'CloseP'
|
19
|
+
|
20
|
+
handle_start %w(b big em font i s small strike strong tt u) => 'Formatting'
|
21
21
|
handle_start 'nobr'
|
22
22
|
|
23
|
-
handle_start %w(
|
23
|
+
handle_start %w(area basefont bgsound br embed img param spacer wbr) => 'VoidFormatting'
|
24
24
|
|
25
|
-
handle_start %w(
|
25
|
+
handle_start %w(iframe noembed noframes noscript) => 'Cdata', HEADING_ELEMENTS => 'Heading'
|
26
26
|
|
27
|
-
handle_start %w(
|
27
|
+
handle_start %w(caption col colgroup frame frameset head option optgroup tbody td tfoot th thead tr) => 'Misplaced'
|
28
28
|
|
29
|
-
handle_start %w(
|
29
|
+
handle_start %w(event-source section nav article aside header footer datagrid command) => 'New'
|
30
30
|
|
31
|
-
handle_end 'p', 'body', 'html', 'form', %w(
|
31
|
+
handle_end 'p', 'body', 'html', 'form', %w(button marquee object), %w(dd dt li) => 'ListItem'
|
32
32
|
|
33
|
-
handle_end %w(
|
33
|
+
handle_end %w(address blockquote center div dl fieldset listing menu ol pre ul) => 'Block'
|
34
34
|
|
35
35
|
handle_end HEADING_ELEMENTS => 'Heading'
|
36
36
|
|
37
|
-
handle_end %w(
|
37
|
+
handle_end %w(a b big em font i nobr s small strike strong tt u) => 'Formatting'
|
38
38
|
|
39
|
-
handle_end %w(
|
39
|
+
handle_end %w(head frameset select optgroup option table caption colgroup col thead tfoot tbody tr td th) => 'Misplaced'
|
40
40
|
|
41
41
|
handle_end 'br'
|
42
42
|
|
43
|
-
handle_end %w(
|
43
|
+
handle_end %w(area basefont bgsound embed hr image img input isindex param spacer wbr frame) => 'None'
|
44
44
|
|
45
|
-
handle_end %w(
|
45
|
+
handle_end %w(noframes noscript noembed textarea xmp iframe ) => 'CdataTextAreaXmp'
|
46
46
|
|
47
|
-
handle_end %w(
|
47
|
+
handle_end %w(event-source section nav article aside header footer datagrid command) => 'New'
|
48
48
|
|
49
49
|
def initialize(parser, tree)
|
50
50
|
super(parser, tree)
|
@@ -100,14 +100,14 @@ module HTML5
|
|
100
100
|
end
|
101
101
|
|
102
102
|
def startTagTitle(name, attributes)
|
103
|
-
parse_error(
|
103
|
+
parse_error("unexpected-start-tag-out-of-my-head", {"name" => name})
|
104
104
|
@parser.phases[:inHead].processStartTag(name, attributes)
|
105
105
|
end
|
106
106
|
|
107
107
|
def startTagBody(name, attributes)
|
108
|
-
parse_error(
|
108
|
+
parse_error("unexpected-start-tag", {"name" => "body"})
|
109
109
|
|
110
|
-
if
|
110
|
+
if @tree.open_elements.length == 1 || @tree.open_elements[1].name != 'body'
|
111
111
|
assert @parser.inner_html
|
112
112
|
else
|
113
113
|
attributes.each do |attr, value|
|
@@ -126,11 +126,11 @@ module HTML5
|
|
126
126
|
|
127
127
|
def startTagForm(name, attributes)
|
128
128
|
if @tree.formPointer
|
129
|
-
parse_error(
|
129
|
+
parse_error("unexpected-start-tag", {"name" => name})
|
130
130
|
else
|
131
131
|
endTagP('p') if in_scope?('p')
|
132
132
|
@tree.insert_element(name, attributes)
|
133
|
-
@tree.formPointer = @tree.open_elements
|
133
|
+
@tree.formPointer = @tree.open_elements.last
|
134
134
|
end
|
135
135
|
end
|
136
136
|
|
@@ -143,7 +143,10 @@ module HTML5
|
|
143
143
|
if stopName.include?(node.name)
|
144
144
|
poppedNodes = (0..i).collect { @tree.open_elements.pop }
|
145
145
|
if i >= 1
|
146
|
-
parse_error(
|
146
|
+
parse_error(
|
147
|
+
i == 1 ? "missing-end-tag" : "missing-end-tags",
|
148
|
+
{"name" => poppedNodes[0..-1].collect{|n| n.name}.join(", ")})
|
149
|
+
|
147
150
|
end
|
148
151
|
break
|
149
152
|
end
|
@@ -169,7 +172,7 @@ module HTML5
|
|
169
172
|
# Uncomment the following for IE7 behavior:
|
170
173
|
# HEADING_ELEMENTS.each do |element|
|
171
174
|
# if in_scope?(element)
|
172
|
-
# parse_error(
|
175
|
+
# parse_error("unexpected-start-tag", {"name" => name})
|
173
176
|
#
|
174
177
|
# remove_open_elements_until do |element|
|
175
178
|
# HEADING_ELEMENTS.include?(element.name)
|
@@ -183,7 +186,7 @@ module HTML5
|
|
183
186
|
|
184
187
|
def startTagA(name, attributes)
|
185
188
|
if afeAElement = @tree.elementInActiveFormattingElements('a')
|
186
|
-
parse_error(
|
189
|
+
parse_error("unexpected-start-tag-implies-end-tag", {"startName" => "a", "endName" => "a"})
|
187
190
|
endTagFormatting('a')
|
188
191
|
@tree.open_elements.delete(afeAElement) if @tree.open_elements.include?(afeAElement)
|
189
192
|
@tree.activeFormattingElements.delete(afeAElement) if @tree.activeFormattingElements.include?(afeAElement)
|
@@ -200,7 +203,7 @@ module HTML5
|
|
200
203
|
def startTagNobr(name, attributes)
|
201
204
|
@tree.reconstructActiveFormattingElements
|
202
205
|
if in_scope?('nobr')
|
203
|
-
parse_error(
|
206
|
+
parse_error("unexpected-start-tag-implies-end-tag", {"startName" => "nobr", "endName" => "nobr"})
|
204
207
|
processEndTag('nobr')
|
205
208
|
# XXX Need tests that trigger the following
|
206
209
|
@tree.reconstructActiveFormattingElements
|
@@ -210,7 +213,7 @@ module HTML5
|
|
210
213
|
|
211
214
|
def startTagButton(name, attributes)
|
212
215
|
if in_scope?('button')
|
213
|
-
parse_error(
|
216
|
+
parse_error("unexpected-start-tag-implies-end-tag", {"startName" => "button", "endName" => "button"})
|
214
217
|
processEndTag('button')
|
215
218
|
@parser.phase.processStartTag(name, attributes)
|
216
219
|
else
|
@@ -252,7 +255,7 @@ module HTML5
|
|
252
255
|
|
253
256
|
def startTagImage(name, attributes)
|
254
257
|
# No really...
|
255
|
-
parse_error(
|
258
|
+
parse_error("unexpected-start-tag-treated-as", {"originalName" => "image", "newName" => "img"})
|
256
259
|
processStartTag('img', attributes)
|
257
260
|
end
|
258
261
|
|
@@ -267,7 +270,7 @@ module HTML5
|
|
267
270
|
end
|
268
271
|
|
269
272
|
def startTagIsindex(name, attributes)
|
270
|
-
parse_error(
|
273
|
+
parse_error("deprecated-tag", {"name" => "isindex"})
|
271
274
|
return if @tree.formPointer
|
272
275
|
processStartTag('form', {})
|
273
276
|
processStartTag('hr', {})
|
@@ -310,13 +313,13 @@ module HTML5
|
|
310
313
|
# "caption", "col", "colgroup", "frame", "frameset", "head",
|
311
314
|
# "option", "optgroup", "tbody", "td", "tfoot", "th", "thead",
|
312
315
|
# "tr", "noscript"
|
313
|
-
parse_error(
|
316
|
+
parse_error("unexpected-start-tag-ignored", {"name" => name})
|
314
317
|
end
|
315
318
|
|
316
319
|
def startTagNew(name, attributes)
|
317
320
|
# New HTML5 elements, "event-source", "section", "nav",
|
318
321
|
# "article", "aside", "header", "footer", "datagrid", "command"
|
319
|
-
|
322
|
+
# $stderr.puts("Warning: Undefined behaviour for start tag #{name}")
|
320
323
|
startTagOther(name, attributes)
|
321
324
|
#raise NotImplementedError
|
322
325
|
end
|
@@ -328,7 +331,7 @@ module HTML5
|
|
328
331
|
|
329
332
|
def endTagP(name)
|
330
333
|
@tree.generateImpliedEndTags('p') if in_scope?('p')
|
331
|
-
parse_error(
|
334
|
+
parse_error("unexpected-end-tag", {"name" => "p"}) unless @tree.open_elements.last.name == 'p'
|
332
335
|
if in_scope?('p')
|
333
336
|
@tree.open_elements.pop while in_scope?('p')
|
334
337
|
else
|
@@ -347,7 +350,9 @@ module HTML5
|
|
347
350
|
return
|
348
351
|
end
|
349
352
|
unless @tree.open_elements.last.name == 'body'
|
350
|
-
parse_error(
|
353
|
+
parse_error("expected-one-end-tag-but-got-another",
|
354
|
+
{"expectedName" => "body",
|
355
|
+
"gotName" => @tree.open_elements.last.name})
|
351
356
|
end
|
352
357
|
@parser.phase = @parser.phases[:afterBody]
|
353
358
|
end
|
@@ -364,7 +369,7 @@ module HTML5
|
|
364
369
|
@tree.generateImpliedEndTags if in_scope?(name)
|
365
370
|
|
366
371
|
unless @tree.open_elements.last.name == name
|
367
|
-
parse_error(
|
372
|
+
parse_error("end-tag-too-early", {"name" => name})
|
368
373
|
end
|
369
374
|
|
370
375
|
if in_scope?(name)
|
@@ -377,7 +382,7 @@ module HTML5
|
|
377
382
|
@tree.generateImpliedEndTags
|
378
383
|
end
|
379
384
|
if @tree.open_elements.last.name != name
|
380
|
-
parse_error(
|
385
|
+
parse_error("end-tag-too-early-ignored", {"name" => "form"})
|
381
386
|
else
|
382
387
|
@tree.open_elements.pop
|
383
388
|
end
|
@@ -389,7 +394,7 @@ module HTML5
|
|
389
394
|
@tree.generateImpliedEndTags(name) if in_scope?(name)
|
390
395
|
|
391
396
|
unless @tree.open_elements.last.name == name
|
392
|
-
parse_error(
|
397
|
+
parse_error("end-tag-too-early", {"name" => name})
|
393
398
|
end
|
394
399
|
|
395
400
|
remove_open_elements_until(name) if in_scope?(name)
|
@@ -404,7 +409,7 @@ module HTML5
|
|
404
409
|
end
|
405
410
|
|
406
411
|
unless @tree.open_elements.last.name == name
|
407
|
-
parse_error(
|
412
|
+
parse_error("end-tag-too-early", {"name" => name})
|
408
413
|
end
|
409
414
|
|
410
415
|
HEADING_ELEMENTS.each do |element|
|
@@ -423,18 +428,18 @@ module HTML5
|
|
423
428
|
# Step 1 paragraph 1
|
424
429
|
afeElement = @tree.elementInActiveFormattingElements(name)
|
425
430
|
if !afeElement or (@tree.open_elements.include?(afeElement) && !in_scope?(afeElement.name))
|
426
|
-
parse_error(
|
431
|
+
parse_error("adoption-agency-1.1", {"name" => name})
|
427
432
|
return
|
428
433
|
# Step 1 paragraph 2
|
429
434
|
elsif not @tree.open_elements.include?(afeElement)
|
430
|
-
parse_error(
|
435
|
+
parse_error("adoption-agency-1.2", {"name" => name})
|
431
436
|
@tree.activeFormattingElements.delete(afeElement)
|
432
437
|
return
|
433
438
|
end
|
434
439
|
|
435
440
|
# Step 1 paragraph 3
|
436
441
|
if afeElement != @tree.open_elements.last
|
437
|
-
parse_error(
|
442
|
+
parse_error("adoption-agency-1.3", {"name" => name})
|
438
443
|
end
|
439
444
|
|
440
445
|
# Step 2
|
@@ -531,7 +536,7 @@ module HTML5
|
|
531
536
|
@tree.generateImpliedEndTags if in_scope?(name)
|
532
537
|
|
533
538
|
unless @tree.open_elements.last.name == name
|
534
|
-
parse_error(
|
539
|
+
parse_error("end-tag-too-early", {"name" => name})
|
535
540
|
end
|
536
541
|
|
537
542
|
if in_scope?(name)
|
@@ -543,11 +548,12 @@ module HTML5
|
|
543
548
|
|
544
549
|
def endTagMisplaced(name)
|
545
550
|
# This handles elements with end tags in other insertion modes.
|
546
|
-
parse_error(
|
551
|
+
parse_error("unexpected-end-tag", {"name" => name})
|
547
552
|
end
|
548
553
|
|
549
554
|
def endTagBr(name)
|
550
|
-
parse_error(
|
555
|
+
parse_error("unexpected-end-tag-treated-as",
|
556
|
+
{"originalName" => "br", "newName" => "br element"})
|
551
557
|
@tree.reconstructActiveFormattingElements
|
552
558
|
@tree.insert_element(name, {})
|
553
559
|
@tree.open_elements.pop()
|
@@ -555,21 +561,21 @@ module HTML5
|
|
555
561
|
|
556
562
|
def endTagNone(name)
|
557
563
|
# This handles elements with no end tag.
|
558
|
-
parse_error(
|
564
|
+
parse_error("no-end-tag", {"name" => name})
|
559
565
|
end
|
560
566
|
|
561
567
|
def endTagCdataTextAreaXmp(name)
|
562
568
|
if @tree.open_elements.last.name == name
|
563
569
|
@tree.open_elements.pop
|
564
570
|
else
|
565
|
-
parse_error(
|
571
|
+
parse_error("unexpected-end-tag", {"name" => name})
|
566
572
|
end
|
567
573
|
end
|
568
574
|
|
569
575
|
def endTagNew(name)
|
570
576
|
# New HTML5 elements, "event-source", "section", "nav",
|
571
577
|
# "article", "aside", "header", "footer", "datagrid", "command"
|
572
|
-
STDERR.puts "Warning: Undefined behaviour for end tag #{name}"
|
578
|
+
# STDERR.puts "Warning: Undefined behaviour for end tag #{name}"
|
573
579
|
endTagOther(name)
|
574
580
|
#raise NotImplementedError
|
575
581
|
end
|
@@ -581,7 +587,7 @@ module HTML5
|
|
581
587
|
@tree.generateImpliedEndTags
|
582
588
|
|
583
589
|
unless @tree.open_elements.last.name == name
|
584
|
-
parse_error(
|
590
|
+
parse_error("unexpected-end-tag", {"name" => name})
|
585
591
|
end
|
586
592
|
|
587
593
|
remove_open_elements_until {|element| element == node }
|
@@ -589,7 +595,7 @@ module HTML5
|
|
589
595
|
break
|
590
596
|
else
|
591
597
|
if (SPECIAL_ELEMENTS + SCOPING_ELEMENTS).include?(node.name)
|
592
|
-
parse_error(
|
598
|
+
parse_error("unexpected-end-tag", {"name" => name})
|
593
599
|
break
|
594
600
|
end
|
595
601
|
end
|