String StyledMarkupSerializer<Strategy>::createMarkup() { StyledMarkupAccumulator markupAccumulator(m_shouldResolveURLs, toTextOffset(m_start.parentAnchoredEquivalent()), toTextOffset(m_end.parentAnchoredEquivalent()), m_start.document(), m_shouldAnnotate, m_convertBlocksToInlines); Node* pastEnd = m_end.nodeAsRangePastLastNode(); Node* firstNode = m_start.nodeAsRangeFirstNode(); const VisiblePositionTemplate<Strategy> visibleStart = createVisiblePosition(m_start); const VisiblePositionTemplate<Strategy> visibleEnd = createVisiblePosition(m_end); if (shouldAnnotate() && needInterchangeNewlineAfter(visibleStart)) { markupAccumulator.appendInterchangeNewline(); if (visibleStart.deepEquivalent() == previousPositionOf(visibleEnd).deepEquivalent()) return markupAccumulator.takeResults(); firstNode = nextPositionOf(visibleStart).deepEquivalent().anchorNode(); if (pastEnd && PositionTemplate<Strategy>::beforeNode(firstNode).compareTo(PositionTemplate<Strategy>::beforeNode(pastEnd)) >= 0) { // This condition hits in editing/pasteboard/copy-display-none.html. return markupAccumulator.takeResults(); } } if (!m_lastClosed) m_lastClosed = StyledMarkupTraverser<Strategy>().traverse(firstNode, pastEnd); StyledMarkupTraverser<Strategy> traverser(&markupAccumulator, m_lastClosed); Node* lastClosed = traverser.traverse(firstNode, pastEnd); if (m_highestNodeToBeSerialized && lastClosed) { // TODO(hajimehoshi): This is calculated at createMarkupInternal too. Node* commonAncestor = Strategy::commonAncestor(*m_start.computeContainerNode(), *m_end.computeContainerNode()); ASSERT(commonAncestor); HTMLBodyElement* body = toHTMLBodyElement(enclosingElementWithTag(firstPositionInNode(commonAncestor), bodyTag)); HTMLBodyElement* fullySelectedRoot = nullptr; // FIXME: Do this for all fully selected blocks, not just the body. if (body && areSameRanges(body, m_start, m_end)) fullySelectedRoot = body; // Also include all of the ancestors of lastClosed up to this special ancestor. // FIXME: What is ancestor? for (ContainerNode* ancestor = Strategy::parent(*lastClosed); ancestor; ancestor = Strategy::parent(*ancestor)) { if (ancestor == fullySelectedRoot && !markupAccumulator.convertBlocksToInlines()) { RawPtr<EditingStyle> fullySelectedRootStyle = styleFromMatchedRulesAndInlineDecl(fullySelectedRoot); // Bring the background attribute over, but not as an attribute because a background attribute on a div // appears to have no effect. if ((!fullySelectedRootStyle || !fullySelectedRootStyle->style() || !fullySelectedRootStyle->style()->getPropertyCSSValue(CSSPropertyBackgroundImage)) && fullySelectedRoot->hasAttribute(backgroundAttr)) fullySelectedRootStyle->style()->setProperty(CSSPropertyBackgroundImage, "url('" + fullySelectedRoot->getAttribute(backgroundAttr) + "')"); if (fullySelectedRootStyle->style()) { // Reset the CSS properties to avoid an assertion error in addStyleMarkup(). // This assertion is caused at least when we select all text of a <body> element whose // 'text-decoration' property is "inherit", and copy it. if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->style(), CSSPropertyTextDecoration)) fullySelectedRootStyle->style()->setProperty(CSSPropertyTextDecoration, CSSValueNone); if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->style(), CSSPropertyWebkitTextDecorationsInEffect)) fullySelectedRootStyle->style()->setProperty(CSSPropertyWebkitTextDecorationsInEffect, CSSValueNone); markupAccumulator.wrapWithStyleNode(fullySelectedRootStyle->style()); } } else { RawPtr<EditingStyle> style = traverser.createInlineStyleIfNeeded(*ancestor); // Since this node and all the other ancestors are not in the selection we want // styles that affect the exterior of the node not to be not included. // If the node is not fully selected by the range, then we don't want to keep styles that affect its relationship to the nodes around it // only the ones that affect it and the nodes within it. if (style && style->style()) style->style()->removeProperty(CSSPropertyFloat); traverser.wrapWithNode(*ancestor, style); } if (ancestor == m_highestNodeToBeSerialized) break; } } // FIXME: The interchange newline should be placed in the block that it's in, not after all of the content, unconditionally. if (shouldAnnotate() && needInterchangeNewlineAt(visibleEnd)) markupAccumulator.appendInterchangeNewline(); return markupAccumulator.takeResults(); }