summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-05-24 22:21:25 +0200
committerAndreas Kling <kling@serenityos.org>2020-05-24 23:54:22 +0200
commit65d8d5e83e545db5c9c3d68ffd43704f368ed50b (patch)
treeef857ad17a95af55c1f5562d4101b7ab9c72a763
parent45da08a1e69728d58f3d9c29ca93dfaf43b672c2 (diff)
downloadserenity-65d8d5e83e545db5c9c3d68ffd43704f368ed50b.zip
LibWeb: Yet more work towards parsing www/welcome.html :^)
-rw-r--r--Libraries/LibWeb/Parser/HTMLDocumentParser.cpp95
-rw-r--r--Libraries/LibWeb/Parser/HTMLDocumentParser.h3
-rw-r--r--Libraries/LibWeb/Parser/StackOfOpenElements.cpp17
-rw-r--r--Libraries/LibWeb/Parser/StackOfOpenElements.h3
4 files changed, 111 insertions, 7 deletions
diff --git a/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp b/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp
index 3b7aad8ad3..08200a38f0 100644
--- a/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp
+++ b/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp
@@ -346,13 +346,27 @@ AnythingElse:
// FIXME: Reprocess the current token in InBody!
}
-void HTMLDocumentParser::generate_implied_end_tags()
+void HTMLDocumentParser::generate_implied_end_tags(const FlyString& exception)
{
- Vector<String> names { "dd", "dt", "li", "optgroup", "option", "p", "rb", "rp", "rt", "rtc" };
- while (names.contains_slow(current_node().tag_name()))
+ static Vector<FlyString> names { "dd", "dt", "li", "optgroup", "option", "p", "rb", "rp", "rt", "rtc" };
+ while (current_node().tag_name() != exception && names.contains_slow(current_node().tag_name()))
m_stack_of_open_elements.pop();
}
+void HTMLDocumentParser::close_a_p_element()
+{
+ generate_implied_end_tags("p");
+ if (current_node().tag_name() != "p") {
+ // Parse error.
+ TODO();
+ }
+ for (;;) {
+ auto popped_element = m_stack_of_open_elements.pop();
+ if (popped_element->tag_name() == "p")
+ break;
+ }
+}
+
void HTMLDocumentParser::handle_after_body(HTMLToken& token)
{
if (token.is_character() && token.is_parser_whitespace()) {
@@ -403,6 +417,10 @@ void HTMLDocumentParser::handle_in_body(HTMLToken& token)
insert_character(token.codepoint());
return;
}
+ reconstruct_the_active_formatting_elements();
+ insert_character(token.codepoint());
+ m_frameset_ok = false;
+ return;
}
if (token.is_end_tag() && token.tag_name() == "body") {
@@ -422,6 +440,70 @@ void HTMLDocumentParser::handle_in_body(HTMLToken& token)
}
{
+ static Vector<FlyString> names { "h1", "h2", "h3", "h4", "h5", "h6" };
+ if (token.is_start_tag() && names.contains_slow(token.tag_name())) {
+ if (m_stack_of_open_elements.has_in_button_scope("p"))
+ close_a_p_element();
+ if (names.contains_slow(current_node().tag_name())) {
+ // FIXME: This is a parse error!
+ TODO();
+ }
+ insert_html_element(token);
+ return;
+ }
+ }
+
+ {
+ static Vector<FlyString> names { "h1", "h2", "h3", "h4", "h5", "h6" };
+ if (token.is_end_tag() && names.contains_slow(token.tag_name())) {
+ if (!m_stack_of_open_elements.has_in_scope("h1")
+ && !m_stack_of_open_elements.has_in_scope("h2")
+ && !m_stack_of_open_elements.has_in_scope("h3")
+ && !m_stack_of_open_elements.has_in_scope("h4")
+ && !m_stack_of_open_elements.has_in_scope("h5")
+ && !m_stack_of_open_elements.has_in_scope("h6")) {
+ TODO();
+ }
+
+ generate_implied_end_tags();
+ if (current_node().tag_name() != token.tag_name()) {
+ TODO();
+ }
+
+ for (;;) {
+ auto popped_element = m_stack_of_open_elements.pop();
+ if (popped_element->tag_name() == "h1"
+ || popped_element->tag_name() == "h2"
+ || popped_element->tag_name() == "h3"
+ || popped_element->tag_name() == "h4"
+ || popped_element->tag_name() == "h5"
+ || popped_element->tag_name() == "h6") {
+ break;
+ }
+ }
+ return;
+ }
+ }
+
+ if (token.is_end_tag() && token.tag_name() == "p") {
+ if (!m_stack_of_open_elements.has_in_button_scope("p")) {
+ TODO();
+ }
+ close_a_p_element();
+ return;
+ }
+
+ {
+ static Vector<FlyString> names { "b", "big", "code", "em", "font", "i", "s", "small", "strike", "strong", "tt", "u" };
+ if (token.is_start_tag() && names.contains_slow(token.tag_name())) {
+ reconstruct_the_active_formatting_elements();
+ auto element = insert_html_element(token);
+ m_list_of_active_formatting_elements.append(*element);
+ return;
+ }
+ }
+
+ {
Vector<String> names { "address", "article", "aside", "blockquote", "center", "details", "dialog", "dir", "div", "dl", "fieldset", "figcaption", "figure", "footer", "header", "hgroup", "main", "menu", "nav", "ol", "p", "section", "summary", "ul" };
if (token.is_start_tag() && names.contains_slow(token.tag_name())) {
// FIXME: If the stack of open elements has a p element in button scope, then close a p element.
@@ -447,6 +529,12 @@ void HTMLDocumentParser::handle_in_body(HTMLToken& token)
}
}
+ if (token.is_start_tag()) {
+ reconstruct_the_active_formatting_elements();
+ insert_html_element(token);
+ return;
+ }
+
ASSERT_NOT_REACHED();
}
@@ -504,5 +592,4 @@ Document& HTMLDocumentParser::document()
{
return *m_document;
}
-
}
diff --git a/Libraries/LibWeb/Parser/HTMLDocumentParser.h b/Libraries/LibWeb/Parser/HTMLDocumentParser.h
index 09b92fbe20..0e7c09e207 100644
--- a/Libraries/LibWeb/Parser/HTMLDocumentParser.h
+++ b/Libraries/LibWeb/Parser/HTMLDocumentParser.h
@@ -89,7 +89,7 @@ private:
void handle_after_after_body(HTMLToken&);
void handle_text(HTMLToken&);
- void generate_implied_end_tags();
+ void generate_implied_end_tags(const FlyString& exception = {});
bool stack_of_open_elements_has_element_with_tag_name_in_scope(const FlyString& tag_name);
NonnullRefPtr<Element> create_element_for(HTMLToken&);
RefPtr<Node> find_appropriate_place_for_inserting_node();
@@ -98,6 +98,7 @@ private:
void insert_character(u32 data);
void insert_comment(HTMLToken&);
void reconstruct_the_active_formatting_elements();
+ void close_a_p_element();
void process_using_the_rules_for(InsertionMode, HTMLToken&);
void parse_generic_raw_text_element(HTMLToken&);
void increment_script_nesting_level();
diff --git a/Libraries/LibWeb/Parser/StackOfOpenElements.cpp b/Libraries/LibWeb/Parser/StackOfOpenElements.cpp
index ad607254d6..1c99624446 100644
--- a/Libraries/LibWeb/Parser/StackOfOpenElements.cpp
+++ b/Libraries/LibWeb/Parser/StackOfOpenElements.cpp
@@ -3,13 +3,14 @@
namespace Web {
+static Vector<FlyString> s_base_list { "applet", "caption", "html", "table", "td", "th", "marquee", "object", "template" };
+
StackOfOpenElements::~StackOfOpenElements()
{
}
-bool StackOfOpenElements::has_in_scope(const FlyString& tag_name) const
+bool StackOfOpenElements::has_in_scope_impl(const FlyString& tag_name, const Vector<FlyString> &list) const
{
- static Vector<FlyString> list { "applet", "caption", "html", "table", "td", "th", "marquee", "object", "template" };
for (ssize_t i = m_elements.size() - 1; i >= 0; --i) {
auto& node = m_elements.at(i);
if (node.tag_name() == tag_name)
@@ -20,4 +21,16 @@ bool StackOfOpenElements::has_in_scope(const FlyString& tag_name) const
ASSERT_NOT_REACHED();
}
+bool StackOfOpenElements::has_in_scope(const FlyString& tag_name) const
+{
+ return has_in_scope_impl(tag_name, s_base_list);
+}
+
+bool StackOfOpenElements::has_in_button_scope(const FlyString& tag_name) const
+{
+ auto list = s_base_list;
+ list.append("button");
+ return has_in_scope_impl(tag_name, list);
+}
+
}
diff --git a/Libraries/LibWeb/Parser/StackOfOpenElements.h b/Libraries/LibWeb/Parser/StackOfOpenElements.h
index 56eaad3115..98ac36434b 100644
--- a/Libraries/LibWeb/Parser/StackOfOpenElements.h
+++ b/Libraries/LibWeb/Parser/StackOfOpenElements.h
@@ -45,8 +45,11 @@ public:
Element& current_node() { return m_elements.last(); }
bool has_in_scope(const FlyString& tag_name) const;
+ bool has_in_button_scope(const FlyString& tag_name) const;
private:
+ bool has_in_scope_impl(const FlyString& tag_name, const Vector<FlyString>&) const;
+
NonnullRefPtrVector<Element> m_elements;
};