diff --git a/Libraries/LibWeb/DOM/Element.cpp b/Libraries/LibWeb/DOM/Element.cpp index eb5d9fea8c..fa8ea02217 100644 --- a/Libraries/LibWeb/DOM/Element.cpp +++ b/Libraries/LibWeb/DOM/Element.cpp @@ -271,19 +271,48 @@ void Element::set_inner_html(StringView markup) String Element::inner_html() const { + auto escape_string = [](const StringView& string, bool attribute_mode) -> String { + // https://html.spec.whatwg.org/multipage/parsing.html#escapingString + StringBuilder builder; + for (auto& ch : string) { + if (ch == '&') + builder.append("&"); + // FIXME: also replace U+00A0 NO-BREAK SPACE with   + else if (ch == '"' && attribute_mode) + builder.append("""); + else if (ch == '<' && !attribute_mode) + builder.append("<"); + else if (ch == '>' && !attribute_mode) + builder.append(">"); + else + builder.append(ch); + } + return builder.to_string(); + }; + StringBuilder builder; Function recurse = [&](auto& node) { for (auto* child = node.first_child(); child; child = child->next_sibling()) { if (child->is_element()) { + auto& element = downcast(*child); builder.append('<'); - builder.append(downcast(*child).local_name()); + builder.append(element.local_name()); + element.for_each_attribute([&](auto& name, auto& value) { + builder.append(' '); + builder.append(name); + builder.append('='); + builder.append('"'); + builder.append(escape_string(value, true)); + builder.append('"'); + }); builder.append('>'); recurse(*child); + // FIXME: This should be skipped for void elements builder.append("(*child).local_name()); + builder.append(element.local_name()); builder.append('>'); } if (child->is_text()) {