srctree

Robin Linden parent e9111a41 1f0e5fc3
engine: Support multiple style elements in the head element

inlinesplit
engine/engine.cpp added: 32, removed: 5, total 27
@@ -67,10 +67,13 @@ void Engine::on_navigation_success() {
dom_ = html::parse(response_.body);
stylesheet_ = css::default_style();
 
if (auto style = dom::nodes_by_xpath(dom_.html(), "/html/head/style"sv);
!style.empty() && !style[0]->children.empty()) {
for (auto const &style : dom::nodes_by_xpath(dom_.html(), "/html/head/style"sv)) {
if (style->children.empty()) {
continue;
}
 
// Style can only contain text, and we enforce this in our HTML parser.
auto const &style_content = std::get<dom::Text>(style[0]->children[0]);
auto const &style_content = std::get<dom::Text>(style->children[0]);
auto new_rules = css::parse(style_content.text);
stylesheet_.reserve(stylesheet_.size() + new_rules.size());
stylesheet_.insert(
 
engine/engine_test.cpp added: 32, removed: 5, total 27
@@ -153,6 +153,30 @@ int main() {
expect_eq(e.layout()->get_property<css::PropertyId::Display>(), style::DisplayValue::Inline);
});
 
etest::test("multiple inline <head><style> elements are allowed", [] {
std::map<std::string, Response> responses{{
"hax://example.com"s,
Response{
.err = Error::Ok,
.status_line = {.status_code = 200},
.body{"<html><head><style>"
"a { color: red; } "
"p { color: green; }"
"</style>"
"<style></style>"
"<style>p { color: cyan; }</style>"
"<p><a>"},
},
}};
engine::Engine e{std::make_unique<FakeProtocolHandler>(std::move(responses))};
e.navigate(uri::Uri::parse("hax://example.com"));
require(e.layout());
auto const *a = dom::nodes_by_xpath(*e.layout(), "//a"sv).at(0);
expect_eq(a->get_property<css::PropertyId::Color>(), gfx::Color::from_css_name("red"));
auto const *p = dom::nodes_by_xpath(*e.layout(), "//p"sv).at(0);
expect_eq(p->get_property<css::PropertyId::Color>(), gfx::Color::from_css_name("cyan"));
});
 
etest::test("stylesheet link, parallel download", [] {
std::map<std::string, Response> responses;
responses["hax://example.com"s] = Response{