srctree

Robin Linden parent 6074b917 aefcfddf
html2: Handle start tags that belong in InHead in AfterHead

inlinesplit
html/parser_actions.h added: 64, removed: 4, total 60
@@ -97,6 +97,26 @@ public:
// TODO(robinlinden): Implement.
}
 
void push_head_as_current_open_element() override {
auto head = std::ranges::find_if(document_.html().children, [](auto const &node) {
return std::holds_alternative<dom::Element>(node) && std::get<dom::Element>(node).name == "head";
});
 
assert(head != document_.html().children.end());
assert(std::ranges::find(open_elements_, &std::get<dom::Element>(*head)) == open_elements_.end());
 
open_elements_.push_back(&std::get<dom::Element>(*head));
}
 
void remove_from_open_elements(std::string_view element_name) override {
auto const it = std::ranges::find_if(open_elements_, [element_name](auto const &element) {
return element->name == element_name; //
});
 
assert(it != open_elements_.end());
open_elements_.erase(it);
}
 
private:
void insert(dom::Element element) {
if (element.name == "html") {
 
html2/iparser_actions.h added: 64, removed: 4, total 60
@@ -36,6 +36,8 @@ public:
virtual void store_original_insertion_mode(InsertionMode) = 0;
virtual InsertionMode original_insertion_mode() = 0;
virtual void set_frameset_ok(bool) = 0;
virtual void push_head_as_current_open_element() = 0;
virtual void remove_from_open_elements(std::string_view element_name) = 0;
 
virtual InsertionMode current_insertion_mode() const = 0;
};
 
html2/parser_states.cpp added: 64, removed: 4, total 60
@@ -42,6 +42,10 @@ public:
InsertionMode original_insertion_mode() override { return wrapped_.original_insertion_mode(); }
InsertionMode current_insertion_mode() const override { return current_insertion_mode_override_; }
void set_frameset_ok(bool ok) override { wrapped_.set_frameset_ok(ok); }
void push_head_as_current_open_element() override { wrapped_.push_head_as_current_open_element(); }
void remove_from_open_elements(std::string_view element_name) override {
wrapped_.remove_from_open_elements(element_name);
}
 
private:
IActions &wrapped_;
@@ -406,6 +410,30 @@ std::optional<InsertionMode> AfterHead::process(IActions &a, html2::Token const
a.set_frameset_ok(false);
return InBody{};
}
 
// TODO(robinlinden): frameset
 
static constexpr auto kInHeadElements = std::to_array<std::string_view>({
"base"sv,
"basefont"sv,
"bgsound"sv,
"link"sv,
"meta"sv,
"noframes"sv,
"script"sv,
"style"sv,
"template"sv,
"title"sv,
});
 
if (std::ranges::find(kInHeadElements, start->tag_name) != std::ranges::end(kInHeadElements)) {
// Parse error.
a.push_head_as_current_open_element();
auto mode_override = current_insertion_mode_override(a, AfterHead{});
InHead{}.process(mode_override, token);
a.remove_from_open_elements("head");
return {};
}
}
 
return {};
 
html2/parser_states_test.cpp added: 64, removed: 4, total 60
@@ -286,6 +286,16 @@ void after_head_tests() {
auto res = parse("<body>", {});
expect_eq(res.document.html(), dom::Element{"html", {}, {dom::Element{"head"}, dom::Element{"body"}}});
});
 
etest::test("AfterHead: base, basefont, bgsound, link", [] {
auto res = parse("<head></head><base> <basefont> <bgsound> <link>", {});
 
auto head_children =
NodeVec{dom::Element{"base"}, dom::Element{"basefont"}, dom::Element{"bgsound"}, dom::Element{"link"}};
auto head = dom::Element{"head", {}, std::move(head_children)};
 
expect_eq(res.document.html(), dom::Element{"html", {}, {std::move(head)}});
});
}
 
} // namespace