summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-05-29 22:06:05 +0200
committerAndreas Kling <kling@serenityos.org>2020-05-30 11:31:49 +0200
commit6854f726cebaa9c03960dc22eeab508ac3e6a4c1 (patch)
treec68c28629604cc1bc528439a26d2af1d57579b7c
parent30d64fccdee74167474e3bcc53d30d3dbb450f1f (diff)
downloadserenity-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.cpp27
-rw-r--r--Libraries/LibWeb/Parser/HTMLDocumentParser.h2
-rw-r--r--Libraries/LibWeb/Parser/StackOfOpenElements.cpp22
-rw-r--r--Libraries/LibWeb/Parser/StackOfOpenElements.h3
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 (&current_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;