Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv ed. | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv ed. |
| 3 * Copyright (C) 2008, 2009, 2010, 2011 Google Inc. All rights reserved. | 3 * Copyright (C) 2008, 2009, 2010, 2011 Google Inc. All rights reserved. |
| 4 * Copyright (C) 2011 Igalia S.L. | 4 * Copyright (C) 2011 Igalia S.L. |
| 5 * Copyright (C) 2011 Motorola Mobility. All rights reserved. | 5 * Copyright (C) 2011 Motorola Mobility. All rights reserved. |
| 6 * | 6 * |
| 7 * Redistribution and use in source and binary forms, with or without | 7 * Redistribution and use in source and binary forms, with or without |
| 8 * modification, are permitted provided that the following conditions | 8 * modification, are permitted provided that the following conditions |
| 9 * are met: | 9 * are met: |
| 10 * 1. Redistributions of source code must retain the above copyright | 10 * 1. Redistributions of source code must retain the above copyright |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 112 // the non-const-ness of styleFromMatchedRulesForElement. | 112 // the non-const-ness of styleFromMatchedRulesForElement. |
| 113 style->mergeStyleFromRules(const_cast<HTMLElement*>(element)); | 113 style->mergeStyleFromRules(const_cast<HTMLElement*>(element)); |
| 114 return style.release(); | 114 return style.release(); |
| 115 } | 115 } |
| 116 | 116 |
| 117 template<typename Strategy> | 117 template<typename Strategy> |
| 118 String StyledMarkupSerializer<Strategy>::createMarkup() | 118 String StyledMarkupSerializer<Strategy>::createMarkup() |
| 119 { | 119 { |
| 120 DEFINE_STATIC_LOCAL(const String, interchangeNewlineString, ("<br class=\"" AppleInterchangeNewline "\">")); | 120 DEFINE_STATIC_LOCAL(const String, interchangeNewlineString, ("<br class=\"" AppleInterchangeNewline "\">")); |
| 121 | 121 |
| 122 StyledMarkupAccumulator markupAccumulator(m_shouldResolveURLs, toTextOffset( m_start.parentAnchoredEquivalent()), toTextOffset(m_end.parentAnchoredEquivalent ()), m_start.document(), m_shouldAnnotate, m_highestNodeToBeSerialized.get(), m_ convertBlocksToInlines); | 122 StyledMarkupAccumulator markupAccumulator(m_shouldResolveURLs, toTextOffset( m_start.parentAnchoredEquivalent()), toTextOffset(m_end.parentAnchoredEquivalent ()), m_start.document(), m_shouldAnnotate, m_highestNodeToBeSerialized.get()); |
| 123 | 123 |
| 124 Node* pastEnd = m_end.nodeAsRangePastLastNode(); | 124 Node* pastEnd = m_end.nodeAsRangePastLastNode(); |
| 125 | 125 |
| 126 Node* firstNode = m_start.nodeAsRangeFirstNode(); | 126 Node* firstNode = m_start.nodeAsRangeFirstNode(); |
| 127 VisiblePosition visibleStart(toPositionInDOMTree(m_start), VP_DEFAULT_AFFINI TY); | 127 VisiblePosition visibleStart(toPositionInDOMTree(m_start), VP_DEFAULT_AFFINI TY); |
| 128 VisiblePosition visibleEnd(toPositionInDOMTree(m_end), VP_DEFAULT_AFFINITY); | 128 VisiblePosition visibleEnd(toPositionInDOMTree(m_end), VP_DEFAULT_AFFINITY); |
| 129 if (m_shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAfte r(visibleStart)) { | 129 if (m_shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAfte r(visibleStart)) { |
| 130 if (visibleStart == visibleEnd.previous()) | 130 if (visibleStart == visibleEnd.previous()) |
| 131 return interchangeNewlineString; | 131 return interchangeNewlineString; |
| 132 | 132 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 147 ASSERT(commonAncestor); | 147 ASSERT(commonAncestor); |
| 148 HTMLBodyElement* body = toHTMLBodyElement(enclosingElementWithTag(firstP ositionInNode(commonAncestor), bodyTag)); | 148 HTMLBodyElement* body = toHTMLBodyElement(enclosingElementWithTag(firstP ositionInNode(commonAncestor), bodyTag)); |
| 149 HTMLBodyElement* fullySelectedRoot = nullptr; | 149 HTMLBodyElement* fullySelectedRoot = nullptr; |
| 150 // FIXME: Do this for all fully selected blocks, not just the body. | 150 // FIXME: Do this for all fully selected blocks, not just the body. |
| 151 if (body && areSameRanges(body, m_start, m_end)) | 151 if (body && areSameRanges(body, m_start, m_end)) |
| 152 fullySelectedRoot = body; | 152 fullySelectedRoot = body; |
| 153 | 153 |
| 154 // Also include all of the ancestors of lastClosed up to this special an cestor. | 154 // Also include all of the ancestors of lastClosed up to this special an cestor. |
| 155 // FIXME: What is ancestor? | 155 // FIXME: What is ancestor? |
| 156 for (ContainerNode* ancestor = Strategy::parent(*lastClosed); ancestor; ancestor = Strategy::parent(*ancestor)) { | 156 for (ContainerNode* ancestor = Strategy::parent(*lastClosed); ancestor; ancestor = Strategy::parent(*ancestor)) { |
| 157 if (ancestor == fullySelectedRoot && !markupAccumulator.convertBlock sToInlines()) { | 157 if (ancestor == fullySelectedRoot && !convertBlocksToInlines()) { |
| 158 RefPtrWillBeRawPtr<EditingStyle> fullySelectedRootStyle = styleF romMatchedRulesAndInlineDecl(fullySelectedRoot); | 158 RefPtrWillBeRawPtr<EditingStyle> fullySelectedRootStyle = styleF romMatchedRulesAndInlineDecl(fullySelectedRoot); |
| 159 | 159 |
| 160 // Bring the background attribute over, but not as an attribute because a background attribute on a div | 160 // Bring the background attribute over, but not as an attribute because a background attribute on a div |
| 161 // appears to have no effect. | 161 // appears to have no effect. |
| 162 if ((!fullySelectedRootStyle || !fullySelectedRootStyle->style() || !fullySelectedRootStyle->style()->getPropertyCSSValue(CSSPropertyBackgroundI mage)) | 162 if ((!fullySelectedRootStyle || !fullySelectedRootStyle->style() || !fullySelectedRootStyle->style()->getPropertyCSSValue(CSSPropertyBackgroundI mage)) |
| 163 && fullySelectedRoot->hasAttribute(backgroundAttr)) | 163 && fullySelectedRoot->hasAttribute(backgroundAttr)) |
| 164 fullySelectedRootStyle->style()->setProperty(CSSPropertyBack groundImage, "url('" + fullySelectedRoot->getAttribute(backgroundAttr) + "')"); | 164 fullySelectedRootStyle->style()->setProperty(CSSPropertyBack groundImage, "url('" + fullySelectedRoot->getAttribute(backgroundAttr) + "')"); |
| 165 | 165 |
| 166 if (fullySelectedRootStyle->style()) { | 166 if (fullySelectedRootStyle->style()) { |
| 167 // Reset the CSS properties to avoid an assertion error in a ddStyleMarkup(). | 167 // Reset the CSS properties to avoid an assertion error in a ddStyleMarkup(). |
| 168 // This assertion is caused at least when we select all text of a <body> element whose | 168 // This assertion is caused at least when we select all text of a <body> element whose |
| 169 // 'text-decoration' property is "inherit", and copy it. | 169 // 'text-decoration' property is "inherit", and copy it. |
| 170 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyTextDecoration)) | 170 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyTextDecoration)) |
| 171 fullySelectedRootStyle->style()->setProperty(CSSProperty TextDecoration, CSSValueNone); | 171 fullySelectedRootStyle->style()->setProperty(CSSProperty TextDecoration, CSSValueNone); |
| 172 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyWebkitTextDecorationsInEffect)) | 172 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyWebkitTextDecorationsInEffect)) |
| 173 fullySelectedRootStyle->style()->setProperty(CSSProperty WebkitTextDecorationsInEffect, CSSValueNone); | 173 fullySelectedRootStyle->style()->setProperty(CSSProperty WebkitTextDecorationsInEffect, CSSValueNone); |
| 174 markupAccumulator.wrapWithStyleNode(fullySelectedRootStyle-> style()); | 174 markupAccumulator.wrapWithStyleNode(fullySelectedRootStyle-> style()); |
| 175 } | 175 } |
| 176 } else { | 176 } else { |
| 177 // Since this node and all the other ancestors are not in the se lection we want to set RangeFullySelectsNode to DoesNotFullySelectNode | 177 RefPtrWillBeRawPtr<EditingStyle> style = nullptr; |
| 178 // so that styles that affect the exterior of the node are not i ncluded. | 178 if (ancestor->isElementNode()) |
| 179 markupAccumulator.wrapWithNode(*ancestor, StyledMarkupAccumulato r::DoesNotFullySelectNode); | 179 style = markupAccumulator.createInlineStyle(toElement(*ances tor), convertBlocksToInlines() && isBlock(ancestor)); |
| 180 // Since this node and all the other ancestors are not in the se lection we want | |
| 181 // styles that affect the exterior of the node not to be not inc luded. | |
| 182 // 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 | |
| 183 // only the ones that affect it and the nodes within it. | |
| 184 if (style && style->style()) | |
| 185 style->style()->removeProperty(CSSPropertyFloat); | |
| 186 wrapWithNode(markupAccumulator, *ancestor, style); | |
| 180 } | 187 } |
| 181 | 188 |
| 182 if (ancestor == m_highestNodeToBeSerialized) | 189 if (ancestor == m_highestNodeToBeSerialized) |
| 183 break; | 190 break; |
| 184 } | 191 } |
| 185 } | 192 } |
| 186 | 193 |
| 187 // FIXME: The interchange newline should be placed in the block that it's in , not after all of the content, unconditionally. | 194 // FIXME: The interchange newline should be placed in the block that it's in , not after all of the content, unconditionally. |
| 188 if (m_shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAt(v isibleEnd)) | 195 if (m_shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAt(v isibleEnd)) |
| 189 markupAccumulator.appendString(interchangeNewlineString); | 196 markupAccumulator.appendString(interchangeNewlineString); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 231 } | 238 } |
| 232 | 239 |
| 233 if (!n->layoutObject() && !enclosingElementWithTag(firstPositionInOrBefo reNode(n), selectTag)) { | 240 if (!n->layoutObject() && !enclosingElementWithTag(firstPositionInOrBefo reNode(n), selectTag)) { |
| 234 next = Strategy::nextSkippingChildren(*n); | 241 next = Strategy::nextSkippingChildren(*n); |
| 235 // Don't skip over pastEnd. | 242 // Don't skip over pastEnd. |
| 236 if (pastEnd && Strategy::isDescendantOf(*pastEnd, *n)) | 243 if (pastEnd && Strategy::isDescendantOf(*pastEnd, *n)) |
| 237 next = pastEnd; | 244 next = pastEnd; |
| 238 } else { | 245 } else { |
| 239 // Add the node to the markup if we're not skipping the descendants | 246 // Add the node to the markup if we're not skipping the descendants |
| 240 if (markupAccumulator) | 247 if (markupAccumulator) |
| 241 markupAccumulator->appendStartTag(*n); | 248 appendStartTag(*markupAccumulator, *n); |
| 242 | 249 |
| 243 // If node has no children, close the tag now. | 250 // If node has no children, close the tag now. |
| 244 if (Strategy::hasChildren(*n)) { | 251 if (Strategy::hasChildren(*n)) { |
| 245 ancestorsToClose.append(toContainerNode(n)); | 252 ancestorsToClose.append(toContainerNode(n)); |
| 246 continue; | 253 continue; |
| 247 } | 254 } |
| 248 if (markupAccumulator && n->isElementNode()) | 255 if (markupAccumulator && n->isElementNode()) |
| 249 markupAccumulator->appendEndTag(toElement(*n)); | 256 markupAccumulator->appendEndTag(toElement(*n)); |
| 250 lastClosed = n; | 257 lastClosed = n; |
| 251 } | 258 } |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 275 | 282 |
| 276 ASSERT(n); | 283 ASSERT(n); |
| 277 Node* lastAncestorClosedOrSelf = Strategy::isDescendantOf(*n, *lastClose d) ? lastClosed : n; | 284 Node* lastAncestorClosedOrSelf = Strategy::isDescendantOf(*n, *lastClose d) ? lastClosed : n; |
| 278 for (ContainerNode* parent = Strategy::parent(*lastAncestorClosedOrSelf) ; parent && parent != nextParent; parent = Strategy::parent(*parent)) { | 285 for (ContainerNode* parent = Strategy::parent(*lastAncestorClosedOrSelf) ; parent && parent != nextParent; parent = Strategy::parent(*parent)) { |
| 279 // All ancestors that aren't in the ancestorsToClose list should eit her be a) unrendered: | 286 // All ancestors that aren't in the ancestorsToClose list should eit her be a) unrendered: |
| 280 if (!parent->layoutObject()) | 287 if (!parent->layoutObject()) |
| 281 continue; | 288 continue; |
| 282 // or b) ancestors that we never encountered during a pre-order trav ersal starting at startNode: | 289 // or b) ancestors that we never encountered during a pre-order trav ersal starting at startNode: |
| 283 ASSERT(startNode); | 290 ASSERT(startNode); |
| 284 ASSERT(Strategy::isDescendantOf(*startNode, *parent)); | 291 ASSERT(Strategy::isDescendantOf(*startNode, *parent)); |
| 285 if (markupAccumulator) | 292 if (markupAccumulator) { |
| 286 markupAccumulator->wrapWithNode(*parent); | 293 RefPtrWillBeRawPtr<EditingStyle> style = nullptr; |
| 294 if (parent->isElementNode()) | |
| 295 style = markupAccumulator->createInlineStyle(toElement(*pare nt), convertBlocksToInlines() && isBlock(parent)); | |
| 296 wrapWithNode(*markupAccumulator, *parent, style); | |
| 297 } | |
| 287 lastClosed = parent; | 298 lastClosed = parent; |
| 288 } | 299 } |
| 289 } | 300 } |
| 290 | 301 |
| 291 return lastClosed; | 302 return lastClosed; |
| 292 } | 303 } |
| 293 | 304 |
| 305 template<typename Strategy> | |
| 306 void StyledMarkupSerializer<Strategy>::appendStartTag(StyledMarkupAccumulator& a ccumulator, Node& node) | |
| 307 { | |
| 308 switch (node.nodeType()) { | |
| 309 case Node::TEXT_NODE: | |
| 310 accumulator.appendText(toText(node)); | |
|
yosin_UTC9
2015/06/09 01:18:11
I understand that StyledMarkupAccumlator still wor
| |
| 311 break; | |
| 312 case Node::ELEMENT_NODE: { | |
| 313 Element& element = toElement(node); | |
| 314 RefPtrWillBeRawPtr<EditingStyle> style = accumulator.createInlineStyle(e lement, false); | |
| 315 accumulator.appendElement(element, false, style); | |
| 316 break; | |
| 317 } | |
| 318 default: | |
| 319 accumulator.appendStartTag(node); | |
| 320 break; | |
| 321 } | |
| 322 } | |
| 323 | |
| 324 template<typename Strategy> | |
| 325 void StyledMarkupSerializer<Strategy>::wrapWithNode(StyledMarkupAccumulator& acc umulator, ContainerNode& node, PassRefPtrWillBeRawPtr<EditingStyle> style) | |
| 326 { | |
| 327 StringBuilder markup; | |
| 328 if (node.isElementNode()) | |
| 329 accumulator.appendElement(markup, toElement(node), convertBlocksToInline s() && isBlock(&node), style); | |
| 330 else | |
| 331 accumulator.appendStartMarkup(markup, node); | |
| 332 accumulator.pushMarkup(markup.toString()); | |
| 333 if (node.isElementNode()) | |
|
yosin_UTC9
2015/06/09 01:18:11
nit: early return is better.
| |
| 334 accumulator.appendEndTag(toElement(node)); | |
| 335 } | |
| 336 | |
| 294 template class StyledMarkupSerializer<EditingStrategy>; | 337 template class StyledMarkupSerializer<EditingStrategy>; |
| 295 | 338 |
| 296 } // namespace blink | 339 } // namespace blink |
| OLD | NEW |