html5 0.1.0 → 0.10.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/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
|