srctree

Robin Linden parent de902650 7375819d
html2: Finish the BeforeHead parser state

inlinesplit
html2/parser_states.cpp added: 43, removed: 4, total 39
@@ -201,11 +201,29 @@ std::optional<InsertionMode> BeforeHead::process(IActions &a, html2::Token const
return {};
}
 
if (std::holds_alternative<html2::DoctypeToken>(token)) {
// Parse error.
return {};
}
 
if (auto const *start = std::get_if<html2::StartTagToken>(&token)) {
if (start->tag_name == "html") {
InBody{}.process(a, token);
return {};
}
 
if (start->tag_name == "head") {
a.insert_element_for(*start);
return InHead{};
}
} else if (auto const *end = std::get_if<html2::EndTagToken>(&token)) {
static constexpr std::array kSortOfHandledEndTags{"head"sv, "body"sv, "html"sv, "br"sv};
if (is_in_array<kSortOfHandledEndTags>(end->tag_name)) {
// Treat as "anything else."
} else {
// Parse error.
return {};
}
}
 
a.insert_element_for(html2::StartTagToken{.tag_name = "head"});
 
html2/parser_states.h added: 43, removed: 4, total 39
@@ -93,7 +93,6 @@ struct BeforeHtml {
};
 
// https://html.spec.whatwg.org/multipage/parsing.html#the-before-head-insertion-mode
// Incomplete.
struct BeforeHead {
std::optional<InsertionMode> process(IActions &, html2::Token const &);
};
 
html2/parser_states_test.cpp added: 43, removed: 4, total 39
@@ -132,11 +132,33 @@ void before_head_tests() {
expect_eq(res.document.html(), dom::Element{"html", {}, {dom::Element{"head", {{"foo", "bar"}}}}});
});
 
etest::test("BeforeHead: doctype", [] {
auto res = parse("<html><!DOCTYPE html><head foo='bar'>", {});
expect_eq(res.document.html(), dom::Element{"html", {}, {dom::Element{"head", {{"foo", "bar"}}}}});
});
 
etest::test("BeforeHead: html tag", [] {
auto res = parse("<html foo=bar><html foo=baz hello=world>", {});
auto const &head = std::get<dom::Element>(res.document.html().children.at(0));
expect_eq(res.document.html().attributes, dom::AttrMap{{"foo", "bar"}, {"hello", "world"}});
expect_eq(head, dom::Element{"head"});
});
 
etest::test("BeforeHead: head tag", [] {
auto res = parse("<head foo='bar'>", {});
expect_eq(res.document.html(), dom::Element{"html", {}, {dom::Element{"head", {{"foo", "bar"}}}}});
});
 
etest::test("BeforeHead: end-tag fallthrough", [] {
auto res = parse("</head>", {});
expect_eq(res.document.html(), dom::Element{"html", {}, {dom::Element{"head"}}});
});
 
etest::test("BeforeHead: ignored end-tag", [] {
auto res = parse("</p><head foo=bar>", {});
expect_eq(res.document.html(), dom::Element{"html", {}, {dom::Element{"head", {{"foo", "bar"}}}}});
});
 
etest::test("BeforeHtml: boring whitespace before head is dropped", [] {
auto res = parse("<html>\t\n\f\r <head foo='bar'>", {});
expect_eq(res.document.html(), dom::Element{"html", {}, {dom::Element{"head", {{"foo", "bar"}}}}});