TEST_F(EditingUtilitiesTest, enclosingNodeOfType) { const char* bodyContent = "<p id='host'><b id='one'>11</b></p>"; const char* shadowContent = "<content select=#two></content><div id='three'><content select=#one></div></content>"; setBodyContent(bodyContent); RefPtrWillBeRawPtr<ShadowRoot> shadowRoot = setShadowContent(shadowContent, "host"); updateLayoutAndStyleForPainting(); Node* host = document().getElementById("host"); Node* one = document().getElementById("one"); Node* three = shadowRoot->getElementById("three"); EXPECT_EQ(host, enclosingNodeOfType(Position(one, 0), isEnclosingBlock)); EXPECT_EQ(three, enclosingNodeOfType(PositionInComposedTree(one, 0), isEnclosingBlock)); }
void AppendNodeCommand::doApply() { ASSERT(m_childToAppend); ASSERT(m_parentNode); // If the child to append is already in a tree, appending it will remove it from it's old location // in an non-undoable way. We might eventually find it useful to do an undoable remove in this case. ASSERT(!m_childToAppend->parent()); ASSERT(enclosingNodeOfType(Position(m_parentNode.get(), 0), &isContentEditable) || !m_parentNode->attached()); ExceptionCode ec = 0; m_parentNode->appendChild(m_childToAppend.get(), ec); ASSERT(ec == 0); }
void InsertNodeBeforeCommand::doApply() { ASSERT(m_insertChild); ASSERT(m_refChild); ASSERT(m_refChild->parentNode()); // If the child to insert is already in a tree, inserting it will remove it from it's old location // in an non-undoable way. We might eventually find it useful to do an undoable remove in this case. ASSERT(!m_insertChild->parent()); ASSERT(enclosingNodeOfType(Position(m_refChild->parentNode(), 0), &isContentEditable) || !m_refChild->parentNode()->attached()); ExceptionCode ec = 0; m_refChild->parentNode()->insertBefore(m_insertChild.get(), m_refChild.get(), ec); ASSERT(ec == 0); }
static HTMLElement* highestAncestorToWrapMarkup( const PositionTemplate<Strategy>& startPosition, const PositionTemplate<Strategy>& endPosition, EAnnotateForInterchange shouldAnnotate, Node* constrainingAncestor) { Node* firstNode = startPosition.nodeAsRangeFirstNode(); // For compatibility reason, we use container node of start and end // positions rather than first node and last node in selection. Node* commonAncestor = Strategy::commonAncestor(*startPosition.computeContainerNode(), *endPosition.computeContainerNode()); DCHECK(commonAncestor); HTMLElement* specialCommonAncestor = nullptr; if (shouldAnnotate == AnnotateForInterchange) { // Include ancestors that aren't completely inside the range but are // required to retain the structure and appearance of the copied markup. specialCommonAncestor = ancestorToRetainStructureAndAppearance(commonAncestor); if (Node* parentListNode = enclosingNodeOfType( firstPositionInOrBeforeNode(firstNode), isListItem)) { EphemeralRangeTemplate<Strategy> markupRange = EphemeralRangeTemplate<Strategy>(startPosition, endPosition); EphemeralRangeTemplate<Strategy> nodeRange = normalizeRange( EphemeralRangeTemplate<Strategy>::rangeOfContents(*parentListNode)); if (nodeRange == markupRange) { ContainerNode* ancestor = parentListNode->parentNode(); while (ancestor && !isHTMLListElement(ancestor)) ancestor = ancestor->parentNode(); specialCommonAncestor = toHTMLElement(ancestor); } } // Retain the Mail quote level by including all ancestor mail block quotes. if (HTMLQuoteElement* highestMailBlockquote = toHTMLQuoteElement(highestEnclosingNodeOfType( firstPositionInOrBeforeNode(firstNode), isMailHTMLBlockquoteElement, CanCrossEditingBoundary))) specialCommonAncestor = highestMailBlockquote; } Node* checkAncestor = specialCommonAncestor ? specialCommonAncestor : commonAncestor; if (checkAncestor->layoutObject()) { HTMLElement* newSpecialCommonAncestor = toHTMLElement(highestEnclosingNodeOfType( Position::firstPositionInNode(checkAncestor), &isPresentationalHTMLElement, CanCrossEditingBoundary, constrainingAncestor)); if (newSpecialCommonAncestor) specialCommonAncestor = newSpecialCommonAncestor; } // If a single tab is selected, commonAncestor will be a text node inside a // tab span. If two or more tabs are selected, commonAncestor will be the tab // span. In either case, if there is a specialCommonAncestor already, it will // necessarily be above any tab span that needs to be included. if (!specialCommonAncestor && isTabHTMLSpanElementTextNode(commonAncestor)) specialCommonAncestor = toHTMLSpanElement(Strategy::parent(*commonAncestor)); if (!specialCommonAncestor && isTabHTMLSpanElement(commonAncestor)) specialCommonAncestor = toHTMLSpanElement(commonAncestor); if (HTMLAnchorElement* enclosingAnchor = toHTMLAnchorElement(enclosingElementWithTag( Position::firstPositionInNode(specialCommonAncestor ? specialCommonAncestor : commonAncestor), aTag))) specialCommonAncestor = enclosingAnchor; return specialCommonAncestor; }
static inline HTMLElement* ancestorToRetainStructureAndAppearanceWithNoLayoutObject(Node* commonAncestor) { HTMLElement* commonAncestorBlock = toHTMLElement(enclosingNodeOfType( firstPositionInOrBeforeNode(commonAncestor), isHTMLBlockElement)); return ancestorToRetainStructureAndAppearanceForBlock(commonAncestorBlock); }