diff options
author | Andreas Kling <kling@serenityos.org> | 2020-05-29 22:06:05 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-05-30 11:31:49 +0200 |
commit | 6854f726cebaa9c03960dc22eeab508ac3e6a4c1 (patch) | |
tree | c68c28629604cc1bc528439a26d2af1d57579b7c | |
parent | 30d64fccdee74167474e3bcc53d30d3dbb450f1f (diff) | |
download | serenity-6854f726cebaa9c03960dc22eeab508ac3e6a4c1.zip |
LibWeb: Improve support for "a" and "li" during "in body" insertion
We can now parse welcome.html once again, without resorting to hacks
or fallbacks during "in body" :^)
-rw-r--r-- | Libraries/LibWeb/Parser/HTMLDocumentParser.cpp | 27 | ||||
-rw-r--r-- | Libraries/LibWeb/Parser/HTMLDocumentParser.h | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/Parser/StackOfOpenElements.cpp | 22 | ||||
-rw-r--r-- | Libraries/LibWeb/Parser/StackOfOpenElements.h | 3 |
4 files changed, 47 insertions, 7 deletions
diff --git a/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp b/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp index d504633f73..e4a72302aa 100644 --- a/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp +++ b/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp @@ -623,10 +623,7 @@ void HTMLDocumentParser::run_the_adoption_agency_algorithm(HTMLToken& token) PARSE_ERROR(); } - // FIXME: Let furthest block be the topmost node in the stack of open elements - // that is lower in the stack than formatting element, and is an element - // in the special category. There might not be one. - RefPtr<Element> furthest_block = nullptr; + RefPtr<Element> furthest_block = m_stack_of_open_elements.topmost_special_node_below(*formatting_element); if (!furthest_block) { while (¤t_node() != formatting_element) @@ -642,7 +639,7 @@ void HTMLDocumentParser::run_the_adoption_agency_algorithm(HTMLToken& token) TODO(); } -static bool is_special_tag(const FlyString& tag_name) +bool HTMLDocumentParser::is_special_tag(const FlyString& tag_name) { return tag_name.is_one_of( "address", @@ -911,7 +908,17 @@ void HTMLDocumentParser::handle_in_body(HTMLToken& token) } if (token.is_end_tag() && token.tag_name() == "li") { - TODO(); + if (!m_stack_of_open_elements.has_in_list_item_scope("li")) { + PARSE_ERROR(); + return; + } + generate_implied_end_tags("li"); + if (current_node().tag_name() != "li") { + PARSE_ERROR(); + dbg() << "Expected <li> current node, but had <" << current_node().tag_name() << ">"; + } + m_stack_of_open_elements.pop_until_an_element_with_tag_name_has_been_popped("li"); + return; } if (token.is_end_tag() && token.tag_name().is_one_of("dd", "dt")) { @@ -943,7 +950,13 @@ void HTMLDocumentParser::handle_in_body(HTMLToken& token) } if (token.is_start_tag() && token.tag_name() == "a") { - TODO(); + if (m_list_of_active_formatting_elements.last_element_with_tag_name_before_marker("a")) { + TODO(); + } + reconstruct_the_active_formatting_elements(); + auto element = insert_html_element(token); + m_list_of_active_formatting_elements.add(*element); + return; } if (token.is_start_tag() && token.tag_name().is_one_of("b", "big", "code", "em", "font", "i", "s", "small", "strike", "strong", "tt", "u")) { diff --git a/Libraries/LibWeb/Parser/HTMLDocumentParser.h b/Libraries/LibWeb/Parser/HTMLDocumentParser.h index df98658e4c..9ac19091fc 100644 --- a/Libraries/LibWeb/Parser/HTMLDocumentParser.h +++ b/Libraries/LibWeb/Parser/HTMLDocumentParser.h @@ -76,6 +76,8 @@ public: InsertionMode insertion_mode() const { return m_insertion_mode; } + static bool is_special_tag(const FlyString& tag_name); + private: const char* insertion_mode_name() const; diff --git a/Libraries/LibWeb/Parser/StackOfOpenElements.cpp b/Libraries/LibWeb/Parser/StackOfOpenElements.cpp index ff07739702..807fc40c0e 100644 --- a/Libraries/LibWeb/Parser/StackOfOpenElements.cpp +++ b/Libraries/LibWeb/Parser/StackOfOpenElements.cpp @@ -25,6 +25,7 @@ */ #include <LibWeb/DOM/Element.h> +#include <LibWeb/Parser/HTMLDocumentParser.h> #include <LibWeb/Parser/StackOfOpenElements.h> namespace Web { @@ -85,6 +86,14 @@ bool StackOfOpenElements::has_in_table_scope(const FlyString& tag_name) const return has_in_scope_impl(tag_name, list); } +bool StackOfOpenElements::has_in_list_item_scope(const FlyString& tag_name) const +{ + auto list = s_base_list; + list.append("ol"); + list.append("ul"); + return has_in_scope_impl(tag_name, list); +} + bool StackOfOpenElements::contains(const Element& element) const { for (auto& element_on_stack : m_elements) { @@ -101,4 +110,17 @@ void StackOfOpenElements::pop_until_an_element_with_tag_name_has_been_popped(con pop(); } +Element* StackOfOpenElements::topmost_special_node_below(const Element& formatting_element) +{ + Element* found_element = nullptr; + for (ssize_t i = m_elements.size() - 1; i >= 0; ++i) { + auto& element = m_elements[i]; + if (&element == &formatting_element) + break; + if (HTMLDocumentParser::is_special_tag(element.tag_name())) + found_element = &element; + } + return found_element; +} + } diff --git a/Libraries/LibWeb/Parser/StackOfOpenElements.h b/Libraries/LibWeb/Parser/StackOfOpenElements.h index 9918158dc9..e7637c5855 100644 --- a/Libraries/LibWeb/Parser/StackOfOpenElements.h +++ b/Libraries/LibWeb/Parser/StackOfOpenElements.h @@ -50,6 +50,7 @@ public: bool has_in_scope(const FlyString& tag_name) const; bool has_in_button_scope(const FlyString& tag_name) const; bool has_in_table_scope(const FlyString& tag_name) const; + bool has_in_list_item_scope(const FlyString& tag_name) const; bool has_in_scope(const Element&) const; @@ -59,6 +60,8 @@ public: void pop_until_an_element_with_tag_name_has_been_popped(const FlyString&); + Element* topmost_special_node_below(const Element&); + private: bool has_in_scope_impl(const FlyString& tag_name, const Vector<FlyString>&) const; bool has_in_scope_impl(const Element& target_node, const Vector<FlyString>&) const; |