Skip to content

Commit

Permalink
html2: Handle dd & dt start tags
Browse files Browse the repository at this point in the history
  • Loading branch information
robinlinden committed Nov 26, 2024
1 parent 1490b83 commit 3a9dd9e
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 34 deletions.
33 changes: 33 additions & 0 deletions html2/parser_states.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,39 @@ std::optional<InsertionMode> InBody::process(IActions &a, html2::Token const &to
return {};
}

if (start != nullptr && (start->tag_name == "dd" || start->tag_name == "dt")) {
a.set_frameset_ok(false);

auto open_elements = a.names_of_open_elements();
assert(!open_elements.empty());
for (auto node : open_elements) {
if (node == "dd" || node == "dt") {
generate_implied_end_tags(a, node);
if (a.current_node_name() != node) {
// Parse error.
}

while (a.current_node_name() != node) {
a.pop_current_node();
}

a.pop_current_node();
break;
}

if (is_special(node) && node != "address" && node != "div" && node != "p") {
break;
}
}

if (a.has_element_in_button_scope("p")) {
close_a_p_element();
}

a.insert_element_for(*start);
return {};
}

// TODO(robinlinden): Most things.

static constexpr auto kImmediatelyPoppedElements = std::to_array<std::string_view>({
Expand Down
71 changes: 37 additions & 34 deletions html2/parser_states_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
#include "etest/etest.h"
#include "html/parser_actions.h"

#include <array>
#include <cstddef>
#include <format>
#include <string_view>
#include <tuple>
#include <utility>
Expand Down Expand Up @@ -519,40 +521,41 @@ void in_body_tests() {
std::ignore = parse("<body><template>", {}); //
});

etest::test("InBody: <li>", [] {
auto res = parse("<body><ul><li><p>hello<li>world", {});
auto const &body = std::get<dom::Element>(res.document.html().children.at(1));
expect_eq(body.children.size(), std::size_t{1});
auto const &ul = std::get<dom::Element>(body.children.at(0));

expect_eq(ul,
dom::Element{
"ul",
{},
{
dom::Element{"li", {}, {dom::Element{"p", {}, {dom::Text{"hello"}}}}},
dom::Element{"li", {}, {dom::Text{"world"}}},
},
});
});

etest::test("InBody: <li>, weird specials", [] {
auto res = parse("<body><section><p><li>hello<a><li>world", {});
auto const &body = std::get<dom::Element>(res.document.html().children.at(1));
expect_eq(body.children.size(), std::size_t{1});
auto const &section = std::get<dom::Element>(body.children.at(0));

expect_eq(section,
dom::Element{
"section",
{},
{
dom::Element{"p"},
dom::Element{"li", {}, {dom::Text{"hello"}, dom::Element{"a"}}},
dom::Element{"li", {}, {dom::Text{"world"}}},
},
});
});
for (auto tag : std::to_array<std::string_view>({"li", "dt", "dd"})) {
etest::test(std::format("InBody: <{}>", tag), [tag] {
auto html = std::format("<body><{}><p>hello<{}>world", tag, tag);
auto res = parse(html, {});
auto const &body = std::get<dom::Element>(res.document.html().children.at(1));

expect_eq(body,
dom::Element{
"body",
{},
{
dom::Element{std::string{tag}, {}, {dom::Element{"p", {}, {dom::Text{"hello"}}}}},
dom::Element{std::string{tag}, {}, {dom::Text{"world"}}},
},
});
});

etest::test(std::format("InBody: <{}>, weird specials", tag), [tag] {
auto res = parse(std::format("<body><section><p><{}>hello<a><{}>world", tag, tag), {});
auto const &body = std::get<dom::Element>(res.document.html().children.at(1));
expect_eq(body.children.size(), std::size_t{1});
auto const &section = std::get<dom::Element>(body.children.at(0));

expect_eq(section,
dom::Element{
"section",
{},
{
dom::Element{"p"},
dom::Element{std::string{tag}, {}, {dom::Text{"hello"}, dom::Element{"a"}}},
dom::Element{std::string{tag}, {}, {dom::Text{"world"}}},
},
});
});
}

etest::test("InBody: body end tag, disallowed element", [] {
auto res = parse("<body><foo></body>", {});
Expand Down

0 comments on commit 3a9dd9e

Please sign in to comment.