From 71e8ddcd1c03c606c844a970986fa6834a5fae64 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 7 Oct 2019 19:06:47 +0200 Subject: [PATCH] LibHTML: Start adding support for This patch adds basic support for external stylesheets. It currently only works with file:// URLs. We do a synchronous full relayout after loading a stylesheet, which is definitely on the aggressive side, but it gives us something to work on improving. :^) --- Base/home/anon/www/link.css | 8 +++++ Base/home/anon/www/link.html | 9 +++++ Base/home/anon/www/welcome.html | 1 + Libraries/LibHTML/DOM/HTMLLinkElement.cpp | 41 +++++++++++++++++++++++ Libraries/LibHTML/DOM/HTMLLinkElement.h | 21 ++++++++++++ Libraries/LibHTML/HtmlView.cpp | 6 +++- Libraries/LibHTML/Makefile.shared | 1 + Libraries/LibHTML/Parser/HTMLParser.cpp | 3 ++ 8 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 Base/home/anon/www/link.css create mode 100644 Base/home/anon/www/link.html create mode 100644 Libraries/LibHTML/DOM/HTMLLinkElement.cpp create mode 100644 Libraries/LibHTML/DOM/HTMLLinkElement.h diff --git a/Base/home/anon/www/link.css b/Base/home/anon/www/link.css new file mode 100644 index 0000000000..d3a9998259 --- /dev/null +++ b/Base/home/anon/www/link.css @@ -0,0 +1,8 @@ +#foo { + background-color: teal; + color: white; + padding-left: 20; + padding-top: 20; + padding-right: 20; + padding-bottom: 20; +} diff --git a/Base/home/anon/www/link.html b/Base/home/anon/www/link.html new file mode 100644 index 0000000000..6556a486e2 --- /dev/null +++ b/Base/home/anon/www/link.html @@ -0,0 +1,9 @@ + + +Link element test + + + +
I should be styled!
+ + diff --git a/Base/home/anon/www/welcome.html b/Base/home/anon/www/welcome.html index a486f5d66a..32b0885565 100644 --- a/Base/home/anon/www/welcome.html +++ b/Base/home/anon/www/welcome.html @@ -22,6 +22,7 @@ h1 {
  • presentational hints
  • images
  • selectors
  • +
  • link element
  • diff --git a/Libraries/LibHTML/DOM/HTMLLinkElement.cpp b/Libraries/LibHTML/DOM/HTMLLinkElement.cpp new file mode 100644 index 0000000000..adf25d92aa --- /dev/null +++ b/Libraries/LibHTML/DOM/HTMLLinkElement.cpp @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include + +HTMLLinkElement::HTMLLinkElement(Document& document, const String& tag_name) + : HTMLElement(document, tag_name) +{ +} + +HTMLLinkElement::~HTMLLinkElement() +{ +} + +void HTMLLinkElement::inserted_into(Node&) +{ + if (rel() == "stylesheet") { + URL url = document().complete_url(href()); + if (url.protocol() != "file") { + ASSERT_NOT_REACHED(); + } + auto file = CFile::construct(url.path()); + if (!file->open(CIODevice::ReadOnly)) { + dbg() << "Failed to open " << url.to_string(); + ASSERT_NOT_REACHED(); + return; + } + auto data = file->read_all(); + auto sheet = parse_css(String::copy(data)); + + if (!sheet) { + dbg() << "Failed to parse " << url.to_string(); + ASSERT_NOT_REACHED(); + return; + } + + document().add_sheet(*sheet); + document().invalidate_layout(); + } +} diff --git a/Libraries/LibHTML/DOM/HTMLLinkElement.h b/Libraries/LibHTML/DOM/HTMLLinkElement.h new file mode 100644 index 0000000000..232fa6d405 --- /dev/null +++ b/Libraries/LibHTML/DOM/HTMLLinkElement.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +class HTMLLinkElement final : public HTMLElement { +public: + HTMLLinkElement(Document&, const String& tag_name); + virtual ~HTMLLinkElement() override; + + virtual void inserted_into(Node&) override; + + String rel() const { return attribute("rel"); } + String type() const { return attribute("type"); } + String href() const { return attribute("href"); } +}; + +template<> +inline bool is(const Node& node) +{ + return is(node) && to(node).tag_name().to_lowercase() == "link"; +} diff --git a/Libraries/LibHTML/HtmlView.cpp b/Libraries/LibHTML/HtmlView.cpp index cc84ee4030..8c42658512 100644 --- a/Libraries/LibHTML/HtmlView.cpp +++ b/Libraries/LibHTML/HtmlView.cpp @@ -36,7 +36,11 @@ void HtmlView::set_document(Document* document) m_document->on_invalidate_layout = nullptr; m_document = document; - m_document->on_invalidate_layout = [this]() { layout_and_sync_size(); }; + m_document->on_invalidate_layout = [this]() { + m_layout_root = m_document->create_layout_tree(m_document->style_resolver(), nullptr); + layout_and_sync_size(); + update(); + }; main_frame().set_document(document); diff --git a/Libraries/LibHTML/Makefile.shared b/Libraries/LibHTML/Makefile.shared index 831eefa4c2..312bff2c7b 100644 --- a/Libraries/LibHTML/Makefile.shared +++ b/Libraries/LibHTML/Makefile.shared @@ -13,6 +13,7 @@ LIBHTML_OBJS = \ DOM/HTMLBodyElement.o \ DOM/HTMLFontElement.o \ DOM/HTMLImageElement.o \ + DOM/HTMLLinkElement.o \ DOM/Document.o \ DOM/Text.o \ CSS/Selector.o \ diff --git a/Libraries/LibHTML/Parser/HTMLParser.cpp b/Libraries/LibHTML/Parser/HTMLParser.cpp index 61178459b2..9593799576 100644 --- a/Libraries/LibHTML/Parser/HTMLParser.cpp +++ b/Libraries/LibHTML/Parser/HTMLParser.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,8 @@ static NonnullRefPtr create_element(Document& document, const String& t return adopt(*new HTMLStyleElement(document, tag_name)); if (lowercase_tag_name == "title") return adopt(*new HTMLTitleElement(document, tag_name)); + if (lowercase_tag_name == "link") + return adopt(*new HTMLLinkElement(document, tag_name)); if (lowercase_tag_name == "img") return adopt(*new HTMLImageElement(document, tag_name)); if (lowercase_tag_name == "h1"