void Node::normalize()
{
// Go through the subtree beneath us, normalizing all nodes. This means that
// any two adjacent text nodes are merged and any empty text nodes are removed.
RefPtr<Node> node = this;
while (Node* firstChild = node->firstChild())
node = firstChild;
while (node) {
NodeType type = node->nodeType();
if (type == ELEMENT_NODE)
toElement(node.get())->normalizeAttributes();
if (node == this)
break;
if (type != TEXT_NODE) {
node = NodeTraversal::nextPostOrder(node.get());
continue;
}
RefPtr<Text> text = toText(node.get());
// Remove empty text nodes.
if (!text->length()) {
// Care must be taken to get the next node before removing the current node.
node = NodeTraversal::nextPostOrder(node.get());
text->remove(IGNORE_EXCEPTION);
continue;
}
// Merge text nodes.
while (Node* nextSibling = node->nextSibling()) {
if (nextSibling->nodeType() != TEXT_NODE)
break;
RefPtr<Text> nextText = toText(nextSibling);
// Remove empty text nodes.
if (!nextText->length()) {
nextText->remove(IGNORE_EXCEPTION);
continue;
}
// Both non-empty text nodes. Merge them.
unsigned offset = text->length();
text->appendData(nextText->data(), IGNORE_EXCEPTION);
document()->textNodesMerged(nextText.get(), offset);
nextText->remove(IGNORE_EXCEPTION);
}
node = NodeTraversal::nextPostOrder(node.get());
}
}