mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-06 16:19:23 +00:00
LibWeb: Implement Text.wholeText
This getter returns the concatenation of the data of the contiguous Text nodes of `this` (being this plus its siblings) in tree order.
This commit is contained in:
parent
7dacd6be89
commit
69da6a0ce4
Notes:
github-actions[bot]
2024-07-20 17:03:45 +00:00
Author: https://github.com/aescarias 🔰
Commit: 69da6a0ce4
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/725
Reviewed-by: https://github.com/tcl3 ✅
5 changed files with 76 additions and 1 deletions
6
Tests/LibWeb/Text/expected/DOM/Text-wholeText.txt
Normal file
6
Tests/LibWeb/Text/expected/DOM/Text-wholeText.txt
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
Text node A with no siblings: A
|
||||||
|
Text node B with previous sibling A: AB
|
||||||
|
Text node B with previous sibling A and next sibling C: ABC
|
||||||
|
CDATA section D with no siblings: D
|
||||||
|
CDATA section E with previous sibling D: DE
|
||||||
|
CDATA section E with previous sibling D and next sibling F: DEF
|
36
Tests/LibWeb/Text/input/DOM/Text-wholeText.html
Normal file
36
Tests/LibWeb/Text/input/DOM/Text-wholeText.html
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<script src="../include.js"></script>
|
||||||
|
<script>
|
||||||
|
test(() => {
|
||||||
|
// HTML Text Nodes
|
||||||
|
const fragment = document.createDocumentFragment();
|
||||||
|
|
||||||
|
const firstNode = document.createTextNode("A");
|
||||||
|
fragment.appendChild(firstNode);
|
||||||
|
println(`Text node ${firstNode.data} with no siblings: ${firstNode.wholeText}`);
|
||||||
|
|
||||||
|
const secondNode = document.createTextNode("B");
|
||||||
|
fragment.appendChild(secondNode);
|
||||||
|
println(`Text node ${secondNode.data} with previous sibling ${secondNode.previousSibling.data}: ${secondNode.wholeText}`);
|
||||||
|
|
||||||
|
const thirdNode = document.createTextNode("C");
|
||||||
|
fragment.appendChild(thirdNode);
|
||||||
|
println(`Text node ${secondNode.data} with previous sibling ${secondNode.previousSibling.data} and next sibling ${secondNode.nextSibling.data}: ${secondNode.wholeText}`);
|
||||||
|
|
||||||
|
// XML CDATA Sections
|
||||||
|
const xmlDoc = new DOMParser().parseFromString("<root></root>", "application/xml");
|
||||||
|
const xmlFrag = xmlDoc.querySelector("root");
|
||||||
|
|
||||||
|
const firstSection = xmlDoc.createCDATASection("D");
|
||||||
|
xmlFrag.appendChild(firstSection);
|
||||||
|
println(`CDATA section ${firstSection.data} with no siblings: ${firstSection.wholeText}`);
|
||||||
|
|
||||||
|
const secondSection = xmlDoc.createCDATASection("E");
|
||||||
|
xmlFrag.appendChild(secondSection);
|
||||||
|
println(`CDATA section ${secondSection.data} with previous sibling ${secondSection.previousSibling.data}: ${secondSection.wholeText}`);
|
||||||
|
|
||||||
|
const thirdSection = xmlDoc.createCDATASection("F");
|
||||||
|
xmlFrag.appendChild(thirdSection);
|
||||||
|
println(`CDATA section ${secondSection.data} with previous sibling ${secondSection.previousSibling.data} and next sibling ${secondSection.nextSibling.data}: ${secondSection.wholeText}`);
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -117,4 +117,36 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Text>> Text::split_text(size_t offset)
|
||||||
return new_node;
|
return new_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://dom.spec.whatwg.org/#dom-text-wholetext
|
||||||
|
String Text::whole_text()
|
||||||
|
{
|
||||||
|
// https://dom.spec.whatwg.org/#contiguous-text-nodes
|
||||||
|
// The contiguous Text nodes of a node node are node, node’s previous sibling Text node, if any, and its contiguous
|
||||||
|
// Text nodes, and node’s next sibling Text node, if any, and its contiguous Text nodes, avoiding any duplicates.
|
||||||
|
Vector<Text*> nodes;
|
||||||
|
|
||||||
|
nodes.append(this);
|
||||||
|
|
||||||
|
auto* current_node = previous_sibling();
|
||||||
|
while (current_node && (current_node->is_text() || current_node->is_cdata_section())) {
|
||||||
|
nodes.append(static_cast<Text*>(current_node));
|
||||||
|
current_node = current_node->previous_sibling();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reverse nodes so they are in tree order
|
||||||
|
nodes.reverse();
|
||||||
|
|
||||||
|
current_node = next_sibling();
|
||||||
|
while (current_node && (current_node->is_text() || current_node->is_cdata_section())) {
|
||||||
|
nodes.append(static_cast<Text*>(current_node));
|
||||||
|
current_node = current_node->next_sibling();
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder builder;
|
||||||
|
for (auto const& text_node : nodes)
|
||||||
|
builder.append(text_node->data());
|
||||||
|
|
||||||
|
return MUST(builder.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ public:
|
||||||
EditableTextNodeOwner* editable_text_node_owner();
|
EditableTextNodeOwner* editable_text_node_owner();
|
||||||
|
|
||||||
WebIDL::ExceptionOr<JS::NonnullGCPtr<Text>> split_text(size_t offset);
|
WebIDL::ExceptionOr<JS::NonnullGCPtr<Text>> split_text(size_t offset);
|
||||||
|
String whole_text();
|
||||||
|
|
||||||
bool is_password_input() const { return m_is_password_input; }
|
bool is_password_input() const { return m_is_password_input; }
|
||||||
void set_is_password_input(Badge<HTML::HTMLInputElement>, bool b) { m_is_password_input = b; }
|
void set_is_password_input(Badge<HTML::HTMLInputElement>, bool b) { m_is_password_input = b; }
|
||||||
|
|
|
@ -8,7 +8,7 @@ interface Text : CharacterData {
|
||||||
constructor(optional DOMString data = "");
|
constructor(optional DOMString data = "");
|
||||||
|
|
||||||
[NewObject] Text splitText(unsigned long offset);
|
[NewObject] Text splitText(unsigned long offset);
|
||||||
[FIXME] readonly attribute DOMString wholeText;
|
readonly attribute DOMString wholeText;
|
||||||
};
|
};
|
||||||
|
|
||||||
Text includes Slottable;
|
Text includes Slottable;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue