mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 19:17:44 +00:00
LibWeb: Implement HTML fragment serialisation and use it in innerHTML
The previous implementation was about a half implementation and was tied to Element::innerHTML. This separates it and puts it into HTMLDocumentParser, as this is in the parsing section of the spec. This provides a near finished HTML fragment serialisation algorithm, bar namespaces in attributes and the `is` value.
This commit is contained in:
parent
ed5128d759
commit
f62477c093
6 changed files with 233 additions and 54 deletions
|
@ -256,62 +256,10 @@ void Element::set_inner_html(StringView markup)
|
|||
document().invalidate_layout();
|
||||
}
|
||||
|
||||
// https://w3c.github.io/DOM-Parsing/#dom-innerhtml-innerhtml
|
||||
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<void(const Node&)> recurse = [&](auto& node) {
|
||||
for (auto* child = node.first_child(); child; child = child->next_sibling()) {
|
||||
if (child->is_element()) {
|
||||
auto& element = verify_cast<Element>(*child);
|
||||
builder.append('<');
|
||||
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("</");
|
||||
builder.append(element.local_name());
|
||||
builder.append('>');
|
||||
}
|
||||
if (child->is_text()) {
|
||||
auto& text = verify_cast<Text>(*child);
|
||||
builder.append(escape_string(text.data(), false));
|
||||
}
|
||||
// FIXME: Also handle Comment, ProcessingInstruction, DocumentType
|
||||
}
|
||||
};
|
||||
recurse(*this);
|
||||
|
||||
return builder.to_string();
|
||||
return serialize_fragment(/* FIXME: Providing true for the require well-formed flag (which may throw) */);
|
||||
}
|
||||
|
||||
bool Element::is_focused() const
|
||||
|
@ -376,4 +324,16 @@ void Element::queue_an_element_task(HTML::Task::Source source, Function<void()>
|
|||
HTML::main_thread_event_loop().task_queue().add(move(task));
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/syntax.html#void-elements
|
||||
bool Element::is_void_element() const
|
||||
{
|
||||
return local_name().is_one_of(HTML::TagNames::area, HTML::TagNames::base, HTML::TagNames::br, HTML::TagNames::col, HTML::TagNames::embed, HTML::TagNames::hr, HTML::TagNames::img, HTML::TagNames::input, HTML::TagNames::link, HTML::TagNames::meta, HTML::TagNames::param, HTML::TagNames::source, HTML::TagNames::track, HTML::TagNames::wbr);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/parsing.html#serializes-as-void
|
||||
bool Element::serializes_as_void() const
|
||||
{
|
||||
return is_void_element() || local_name().is_one_of(HTML::TagNames::basefont, HTML::TagNames::bgsound, HTML::TagNames::frame, HTML::TagNames::keygen);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue