diff --git a/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp b/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp
index ebb5d6e1ec..cd4a40c5dd 100644
--- a/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp
+++ b/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp
@@ -106,6 +106,9 @@ void HTMLDocumentParser::process_using_the_rules_for(InsertionMode mode, HTMLTok
case InsertionMode::Text:
handle_text(token);
break;
+ case InsertionMode::InTable:
+ handle_in_table(token);
+ break;
default:
ASSERT_NOT_REACHED();
}
@@ -567,6 +570,16 @@ void HTMLDocumentParser::handle_in_body(HTMLToken& token)
return;
}
+ if (token.is_start_tag() && token.tag_name() == "table") {
+ // FIXME: If the Document is not set to quirks mode,
+ // and the stack of open elements has a p element in button scope, then close a p element.
+
+ insert_html_element(token);
+ m_frameset_ok = false;
+ m_insertion_mode = InsertionMode::InTable;
+ return;
+ }
+
if (token.is_start_tag()) {
reconstruct_the_active_formatting_elements();
insert_html_element(token);
@@ -635,6 +648,58 @@ void HTMLDocumentParser::handle_text(HTMLToken& token)
ASSERT_NOT_REACHED();
}
+void HTMLDocumentParser::handle_in_table(HTMLToken& token)
+{
+ if (token.is_character() && current_node().tag_name().is_one_of("table", "tbody", "tfoot", "thead", "tr")) {
+ TODO();
+ }
+ if (token.is_comment()) {
+ insert_comment(token);
+ return;
+ }
+ if (token.is_doctype()) {
+ PARSE_ERROR();
+ return;
+ }
+ if (token.is_start_tag() && token.tag_name() == "caption") {
+ TODO();
+ }
+ if (token.is_start_tag() && token.tag_name() == "colgroup") {
+ TODO();
+ }
+ if (token.is_start_tag() && token.tag_name() == "col") {
+ TODO();
+ }
+ if (token.is_start_tag() && token.tag_name().is_one_of("tbody", "tfoot", "thead")) {
+ TODO();
+ }
+ if (token.is_start_tag() && token.tag_name().is_one_of("td", "th", "tr")) {
+ TODO();
+ }
+ if (token.is_start_tag() && token.tag_name() == "table") {
+ PARSE_ERROR();
+ TODO();
+ }
+ if (token.is_end_tag()) {
+ if (!m_stack_of_open_elements.has_in_table_scope("table")) {
+ PARSE_ERROR();
+ return;
+ }
+ while (current_node().tag_name() != "table")
+ m_stack_of_open_elements.pop();
+ m_stack_of_open_elements.pop();
+
+ reset_the_insertion_mode_appropriately();
+ return;
+ }
+ TODO();
+}
+
+void HTMLDocumentParser::reset_the_insertion_mode_appropriately()
+{
+ TODO();
+}
+
const char* HTMLDocumentParser::insertion_mode_name() const
{
switch (m_insertion_mode) {
diff --git a/Libraries/LibWeb/Parser/HTMLDocumentParser.h b/Libraries/LibWeb/Parser/HTMLDocumentParser.h
index 0e7c09e207..a57826b00e 100644
--- a/Libraries/LibWeb/Parser/HTMLDocumentParser.h
+++ b/Libraries/LibWeb/Parser/HTMLDocumentParser.h
@@ -88,6 +88,7 @@ private:
void handle_after_body(HTMLToken&);
void handle_after_after_body(HTMLToken&);
void handle_text(HTMLToken&);
+ void handle_in_table(HTMLToken&);
void generate_implied_end_tags(const FlyString& exception = {});
bool stack_of_open_elements_has_element_with_tag_name_in_scope(const FlyString& tag_name);
@@ -104,6 +105,7 @@ private:
void increment_script_nesting_level();
void decrement_script_nesting_level();
size_t script_nesting_level() const { return m_script_nesting_level; }
+ void reset_the_insertion_mode_appropriately();
InsertionMode m_insertion_mode { InsertionMode::Initial };
InsertionMode m_original_insertion_mode { InsertionMode::Initial };
diff --git a/Libraries/LibWeb/Parser/StackOfOpenElements.cpp b/Libraries/LibWeb/Parser/StackOfOpenElements.cpp
index 82bd86b9c3..8834385300 100644
--- a/Libraries/LibWeb/Parser/StackOfOpenElements.cpp
+++ b/Libraries/LibWeb/Parser/StackOfOpenElements.cpp
@@ -35,7 +35,7 @@ StackOfOpenElements::~StackOfOpenElements()
{
}
-bool StackOfOpenElements::has_in_scope_impl(const FlyString& tag_name, const Vector &list) const
+bool StackOfOpenElements::has_in_scope_impl(const FlyString& tag_name, const Vector& list) const
{
for (ssize_t i = m_elements.size() - 1; i >= 0; --i) {
auto& node = m_elements.at(i);
@@ -59,6 +59,15 @@ bool StackOfOpenElements::has_in_button_scope(const FlyString& tag_name) const
return has_in_scope_impl(tag_name, list);
}
+bool StackOfOpenElements::has_in_table_scope(const FlyString& tag_name) const
+{
+ auto list = s_base_list;
+ list.append("html");
+ list.append("table");
+ list.append("template");
+ return has_in_scope_impl(tag_name, list);
+}
+
bool StackOfOpenElements::contains(const Element& element) const
{
for (auto& element_on_stack : m_elements) {
diff --git a/Libraries/LibWeb/Parser/StackOfOpenElements.h b/Libraries/LibWeb/Parser/StackOfOpenElements.h
index 8403f36158..5e3ed6ae52 100644
--- a/Libraries/LibWeb/Parser/StackOfOpenElements.h
+++ b/Libraries/LibWeb/Parser/StackOfOpenElements.h
@@ -46,6 +46,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 contains(const Element&) const;