mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-09 09:39:39 +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;
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
WebIDL::ExceptionOr<JS::NonnullGCPtr<Text>> split_text(size_t offset);
|
||||
String whole_text();
|
||||
|
||||
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; }
|
||||
|
|
|
@ -8,7 +8,7 @@ interface Text : CharacterData {
|
|||
constructor(optional DOMString data = "");
|
||||
|
||||
[NewObject] Text splitText(unsigned long offset);
|
||||
[FIXME] readonly attribute DOMString wholeText;
|
||||
readonly attribute DOMString wholeText;
|
||||
};
|
||||
|
||||
Text includes Slottable;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue