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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 52 { | 52 { |
| 53 if (position.isNull()) | 53 if (position.isNull()) |
| 54 return TextOffset(); | 54 return TextOffset(); |
| 55 | 55 |
| 56 if (!position.containerNode()->isTextNode()) | 56 if (!position.containerNode()->isTextNode()) |
| 57 return TextOffset(); | 57 return TextOffset(); |
| 58 | 58 |
| 59 return TextOffset(toText(position.containerNode()), position.offsetInContain erNode()); | 59 return TextOffset(toText(position.containerNode()), position.offsetInContain erNode()); |
| 60 } | 60 } |
| 61 | 61 |
| 62 template<typename Strategy> | |
| 63 class Traverser { | |
| 64 WTF_MAKE_NONCOPYABLE(Traverser); | |
| 65 STACK_ALLOCATED(); | |
| 66 public: | |
| 67 Traverser() | |
| 68 : Traverser(nullptr, nullptr) | |
| 69 { | |
| 70 } | |
| 71 Traverser(StyledMarkupAccumulator* accumulator, Node* lastClosed) | |
|
yosin_UTC9
2015/06/17 13:07:57
How about moving this ctor before L244, I hope cod
hajimehoshi
2015/06/18 02:04:56
Done.
| |
| 72 : m_accumulator(accumulator) | |
|
yosin_UTC9
2015/06/17 13:07:57
ASSERT(m_lastClosed || !m_accumlator)?
I think wh
hajimehoshi
2015/06/18 02:04:56
Done.
| |
| 73 , m_lastClosed(lastClosed) | |
|
yosin_UTC9
2015/06/17 13:07:58
It is better to initialize |m_wrappingStyle| to nu
hajimehoshi
2015/06/18 02:04:56
Done.
| |
| 74 { | |
| 75 if (m_accumulator && m_lastClosed && Strategy::parent(*m_lastClosed)) | |
|
yosin_UTC9
2015/06/17 13:07:58
Let's use early return pattern.
hajimehoshi
2015/06/18 02:04:56
Done.
| |
| 76 m_wrappingStyle = EditingStyle::wrappingStyleForSerialization(Strate gy::parent(*m_lastClosed), m_accumulator->shouldAnnotate()); | |
|
yosin_UTC9
2015/06/17 13:31:02
Since, we use |m_accumulator->shouldAnnotate()| fo
hajimehoshi
2015/06/18 02:04:56
Done.
| |
| 77 } | |
| 78 Node* traverseNodesForSerialization(Node*, Node*); | |
| 79 void wrapWithNode(ContainerNode&, PassRefPtrWillBeRawPtr<EditingStyle>); | |
| 80 RefPtrWillBeRawPtr<EditingStyle> createInlineStyleIfNeeded(Node&); | |
| 81 | |
| 82 private: | |
| 83 void appendStartMarkup(Node&); | |
| 84 void appendEndMarkup(Node&); | |
| 85 RefPtrWillBeRawPtr<EditingStyle> createInlineStyle(Element&); | |
| 86 bool needsInlineStyle(const Element&); | |
| 87 bool shouldApplyWrappingStyle(const Node&) const; | |
| 88 | |
| 89 StyledMarkupAccumulator* m_accumulator; | |
| 90 Node* m_lastClosed; | |
| 91 RefPtrWillBeMember<EditingStyle> m_wrappingStyle; | |
| 92 }; | |
| 93 | |
| 62 } // namespace | 94 } // namespace |
| 63 | 95 |
| 64 using namespace HTMLNames; | 96 using namespace HTMLNames; |
| 65 | 97 |
| 66 static Position toPositionInDOMTree(const Position& position) | 98 static Position toPositionInDOMTree(const Position& position) |
| 67 { | 99 { |
| 68 return position; | 100 return position; |
| 69 } | 101 } |
| 70 | 102 |
| 71 template<typename Strategy> | 103 template<typename Strategy> |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 111 RefPtrWillBeRawPtr<EditingStyle> style = EditingStyle::create(element->inlin eStyle()); | 143 RefPtrWillBeRawPtr<EditingStyle> style = EditingStyle::create(element->inlin eStyle()); |
| 112 // FIXME: Having to const_cast here is ugly, but it is quite a bit of work t o untangle | 144 // FIXME: Having to const_cast here is ugly, but it is quite a bit of work t o untangle |
| 113 // the non-const-ness of styleFromMatchedRulesForElement. | 145 // the non-const-ness of styleFromMatchedRulesForElement. |
| 114 style->mergeStyleFromRules(const_cast<HTMLElement*>(element)); | 146 style->mergeStyleFromRules(const_cast<HTMLElement*>(element)); |
| 115 return style.release(); | 147 return style.release(); |
| 116 } | 148 } |
| 117 | 149 |
| 118 template<typename Strategy> | 150 template<typename Strategy> |
| 119 String StyledMarkupSerializer<Strategy>::createMarkup() | 151 String StyledMarkupSerializer<Strategy>::createMarkup() |
| 120 { | 152 { |
| 121 StyledMarkupAccumulator markupAccumulator(m_shouldResolveURLs, toTextOffset( m_start.parentAnchoredEquivalent()), toTextOffset(m_end.parentAnchoredEquivalent ()), m_start.document(), m_shouldAnnotate); | 153 StyledMarkupAccumulator markupAccumulator(m_shouldResolveURLs, toTextOffset( m_start.parentAnchoredEquivalent()), toTextOffset(m_end.parentAnchoredEquivalent ()), m_start.document(), m_shouldAnnotate, m_convertBlocksToInlines); |
| 122 | 154 |
| 123 Node* pastEnd = m_end.nodeAsRangePastLastNode(); | 155 Node* pastEnd = m_end.nodeAsRangePastLastNode(); |
| 124 | 156 |
| 125 Node* firstNode = m_start.nodeAsRangeFirstNode(); | 157 Node* firstNode = m_start.nodeAsRangeFirstNode(); |
| 126 VisiblePosition visibleStart(toPositionInDOMTree(m_start), VP_DEFAULT_AFFINI TY); | 158 VisiblePosition visibleStart(toPositionInDOMTree(m_start), VP_DEFAULT_AFFINI TY); |
| 127 VisiblePosition visibleEnd(toPositionInDOMTree(m_end), VP_DEFAULT_AFFINITY); | 159 VisiblePosition visibleEnd(toPositionInDOMTree(m_end), VP_DEFAULT_AFFINITY); |
| 128 if (shouldAnnotate() && needInterchangeNewlineAfter(visibleStart)) { | 160 if (shouldAnnotate() && needInterchangeNewlineAfter(visibleStart)) { |
| 129 markupAccumulator.appendInterchangeNewline(); | 161 markupAccumulator.appendInterchangeNewline(); |
| 130 if (visibleStart == visibleEnd.previous()) | 162 if (visibleStart == visibleEnd.previous()) |
| 131 return markupAccumulator.takeResults(); | 163 return markupAccumulator.takeResults(); |
| 132 | 164 |
| 133 firstNode = visibleStart.next().deepEquivalent().deprecatedNode(); | 165 firstNode = visibleStart.next().deepEquivalent().deprecatedNode(); |
| 134 | 166 |
| 135 if (pastEnd && Strategy::PositionType::beforeNode(firstNode).compareTo(S trategy::PositionType::beforeNode(pastEnd)) >= 0) { | 167 if (pastEnd && Strategy::PositionType::beforeNode(firstNode).compareTo(S trategy::PositionType::beforeNode(pastEnd)) >= 0) { |
| 136 // This condition hits in editing/pasteboard/copy-display-none.html. | 168 // This condition hits in editing/pasteboard/copy-display-none.html. |
| 137 return markupAccumulator.takeResults(); | 169 return markupAccumulator.takeResults(); |
| 138 } | 170 } |
| 139 } | 171 } |
| 140 | 172 |
| 141 Node* lastClosed = serializeNodes(firstNode, pastEnd, &markupAccumulator); | 173 if (!m_lastClosed) |
| 174 m_lastClosed = Traverser<Strategy>().traverseNodesForSerialization(first Node, pastEnd); | |
| 175 Traverser<Strategy> traverser(&markupAccumulator, m_lastClosed); | |
| 176 Node* lastClosed = traverser.traverseNodesForSerialization(firstNode, pastEn d); | |
| 142 | 177 |
| 143 if (m_highestNodeToBeSerialized && lastClosed) { | 178 if (m_highestNodeToBeSerialized && lastClosed) { |
| 144 // TODO(hajimehoshi): This is calculated at createMarkupInternal too. | 179 // TODO(hajimehoshi): This is calculated at createMarkupInternal too. |
| 145 Node* commonAncestor = Strategy::commonAncestor(*m_start.containerNode() , *m_end.containerNode()); | 180 Node* commonAncestor = Strategy::commonAncestor(*m_start.containerNode() , *m_end.containerNode()); |
| 146 ASSERT(commonAncestor); | 181 ASSERT(commonAncestor); |
| 147 HTMLBodyElement* body = toHTMLBodyElement(enclosingElementWithTag(firstP ositionInNode(commonAncestor), bodyTag)); | 182 HTMLBodyElement* body = toHTMLBodyElement(enclosingElementWithTag(firstP ositionInNode(commonAncestor), bodyTag)); |
| 148 HTMLBodyElement* fullySelectedRoot = nullptr; | 183 HTMLBodyElement* fullySelectedRoot = nullptr; |
| 149 // FIXME: Do this for all fully selected blocks, not just the body. | 184 // FIXME: Do this for all fully selected blocks, not just the body. |
| 150 if (body && areSameRanges(body, m_start, m_end)) | 185 if (body && areSameRanges(body, m_start, m_end)) |
| 151 fullySelectedRoot = body; | 186 fullySelectedRoot = body; |
| 152 | 187 |
| 153 // Also include all of the ancestors of lastClosed up to this special an cestor. | 188 // Also include all of the ancestors of lastClosed up to this special an cestor. |
| 154 // FIXME: What is ancestor? | 189 // FIXME: What is ancestor? |
| 155 for (ContainerNode* ancestor = Strategy::parent(*lastClosed); ancestor; ancestor = Strategy::parent(*ancestor)) { | 190 for (ContainerNode* ancestor = Strategy::parent(*lastClosed); ancestor; ancestor = Strategy::parent(*ancestor)) { |
| 156 if (ancestor == fullySelectedRoot && !convertBlocksToInlines()) { | 191 if (ancestor == fullySelectedRoot && !markupAccumulator.convertBlock sToInlines()) { |
| 157 RefPtrWillBeRawPtr<EditingStyle> fullySelectedRootStyle = styleF romMatchedRulesAndInlineDecl(fullySelectedRoot); | 192 RefPtrWillBeRawPtr<EditingStyle> fullySelectedRootStyle = styleF romMatchedRulesAndInlineDecl(fullySelectedRoot); |
| 158 | 193 |
| 159 // Bring the background attribute over, but not as an attribute because a background attribute on a div | 194 // Bring the background attribute over, but not as an attribute because a background attribute on a div |
| 160 // appears to have no effect. | 195 // appears to have no effect. |
| 161 if ((!fullySelectedRootStyle || !fullySelectedRootStyle->style() || !fullySelectedRootStyle->style()->getPropertyCSSValue(CSSPropertyBackgroundI mage)) | 196 if ((!fullySelectedRootStyle || !fullySelectedRootStyle->style() || !fullySelectedRootStyle->style()->getPropertyCSSValue(CSSPropertyBackgroundI mage)) |
| 162 && fullySelectedRoot->hasAttribute(backgroundAttr)) | 197 && fullySelectedRoot->hasAttribute(backgroundAttr)) |
| 163 fullySelectedRootStyle->style()->setProperty(CSSPropertyBack groundImage, "url('" + fullySelectedRoot->getAttribute(backgroundAttr) + "')"); | 198 fullySelectedRootStyle->style()->setProperty(CSSPropertyBack groundImage, "url('" + fullySelectedRoot->getAttribute(backgroundAttr) + "')"); |
| 164 | 199 |
| 165 if (fullySelectedRootStyle->style()) { | 200 if (fullySelectedRootStyle->style()) { |
| 166 // Reset the CSS properties to avoid an assertion error in a ddStyleMarkup(). | 201 // Reset the CSS properties to avoid an assertion error in a ddStyleMarkup(). |
| 167 // This assertion is caused at least when we select all text of a <body> element whose | 202 // This assertion is caused at least when we select all text of a <body> element whose |
| 168 // 'text-decoration' property is "inherit", and copy it. | 203 // 'text-decoration' property is "inherit", and copy it. |
| 169 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyTextDecoration)) | 204 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyTextDecoration)) |
| 170 fullySelectedRootStyle->style()->setProperty(CSSProperty TextDecoration, CSSValueNone); | 205 fullySelectedRootStyle->style()->setProperty(CSSProperty TextDecoration, CSSValueNone); |
| 171 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyWebkitTextDecorationsInEffect)) | 206 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyWebkitTextDecorationsInEffect)) |
| 172 fullySelectedRootStyle->style()->setProperty(CSSProperty WebkitTextDecorationsInEffect, CSSValueNone); | 207 fullySelectedRootStyle->style()->setProperty(CSSProperty WebkitTextDecorationsInEffect, CSSValueNone); |
| 173 markupAccumulator.wrapWithStyleNode(fullySelectedRootStyle-> style()); | 208 markupAccumulator.wrapWithStyleNode(fullySelectedRootStyle-> style()); |
| 174 } | 209 } |
| 175 } else { | 210 } else { |
| 176 RefPtrWillBeRawPtr<EditingStyle> style = createInlineStyleIfNeed ed(*ancestor); | 211 RefPtrWillBeRawPtr<EditingStyle> style = traverser.createInlineS tyleIfNeeded(*ancestor); |
| 177 // Since this node and all the other ancestors are not in the se lection we want | 212 // Since this node and all the other ancestors are not in the se lection we want |
| 178 // styles that affect the exterior of the node not to be not inc luded. | 213 // styles that affect the exterior of the node not to be not inc luded. |
| 179 // 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 | 214 // 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 |
| 180 // only the ones that affect it and the nodes within it. | 215 // only the ones that affect it and the nodes within it. |
| 181 if (style && style->style()) | 216 if (style && style->style()) |
| 182 style->style()->removeProperty(CSSPropertyFloat); | 217 style->style()->removeProperty(CSSPropertyFloat); |
| 183 wrapWithNode(markupAccumulator, *ancestor, style); | 218 traverser.wrapWithNode(*ancestor, style); |
| 184 } | 219 } |
| 185 | 220 |
| 186 if (ancestor == m_highestNodeToBeSerialized) | 221 if (ancestor == m_highestNodeToBeSerialized) |
| 187 break; | 222 break; |
| 188 } | 223 } |
| 189 } | 224 } |
| 190 | 225 |
| 191 // FIXME: The interchange newline should be placed in the block that it's in , not after all of the content, unconditionally. | 226 // FIXME: The interchange newline should be placed in the block that it's in , not after all of the content, unconditionally. |
| 192 if (shouldAnnotate() && needInterchangeNewlineAt(visibleEnd)) | 227 if (shouldAnnotate() && needInterchangeNewlineAt(visibleEnd)) |
| 193 markupAccumulator.appendInterchangeNewline(); | 228 markupAccumulator.appendInterchangeNewline(); |
| 194 | 229 |
| 195 return markupAccumulator.takeResults(); | 230 return markupAccumulator.takeResults(); |
| 196 } | 231 } |
| 197 | 232 |
| 198 template<typename Strategy> | 233 template<typename Strategy> |
| 199 Node* StyledMarkupSerializer<Strategy>::serializeNodes(Node* startNode, Node* pa stEnd, StyledMarkupAccumulator* markupAccumulator) | 234 Node* Traverser<Strategy>::traverseNodesForSerialization(Node* startNode, Node* pastEnd) |
| 200 { | |
| 201 if (!m_lastClosed) | |
| 202 m_lastClosed = traverseNodesForSerialization(startNode, pastEnd, nullptr ); | |
| 203 if (m_lastClosed && Strategy::parent(*m_lastClosed)) | |
| 204 m_wrappingStyle = EditingStyle::wrappingStyleForSerialization(Strategy:: parent(*m_lastClosed), shouldAnnotate()); | |
| 205 return traverseNodesForSerialization(startNode, pastEnd, markupAccumulator); | |
| 206 } | |
| 207 | |
| 208 template<typename Strategy> | |
| 209 Node* StyledMarkupSerializer<Strategy>::traverseNodesForSerialization(Node* star tNode, Node* pastEnd, StyledMarkupAccumulator* markupAccumulator) | |
| 210 { | 235 { |
| 211 WillBeHeapVector<RawPtrWillBeMember<ContainerNode>> ancestorsToClose; | 236 WillBeHeapVector<RawPtrWillBeMember<ContainerNode>> ancestorsToClose; |
| 212 Node* next; | 237 Node* next; |
| 213 Node* lastClosed = nullptr; | 238 Node* lastClosed = nullptr; |
| 214 for (Node* n = startNode; n != pastEnd; n = next) { | 239 for (Node* n = startNode; n != pastEnd; n = next) { |
| 215 // According to <rdar://problem/5730668>, it is possible for n to blow | 240 // According to <rdar://problem/5730668>, it is possible for n to blow |
| 216 // past pastEnd and become null here. This shouldn't be possible. | 241 // past pastEnd and become null here. This shouldn't be possible. |
| 217 // This null check will prevent crashes (but create too much markup) | 242 // This null check will prevent crashes (but create too much markup) |
| 218 // and the ASSERT will hopefully lead us to understanding the problem. | 243 // and the ASSERT will hopefully lead us to understanding the problem. |
| 219 ASSERT(n); | 244 ASSERT(n); |
| 220 if (!n) | 245 if (!n) |
| 221 break; | 246 break; |
| 222 | 247 |
| 223 next = Strategy::next(*n); | 248 next = Strategy::next(*n); |
| 224 | 249 |
| 225 if (isBlock(n) && canHaveChildrenForEditing(n) && next == pastEnd) { | 250 if (isBlock(n) && canHaveChildrenForEditing(n) && next == pastEnd) { |
| 226 // Don't write out empty block containers that aren't fully selected . | 251 // Don't write out empty block containers that aren't fully selected . |
| 227 continue; | 252 continue; |
| 228 } | 253 } |
| 229 | 254 |
| 230 if (!n->layoutObject() && !enclosingElementWithTag(firstPositionInOrBefo reNode(n), selectTag)) { | 255 if (!n->layoutObject() && !enclosingElementWithTag(firstPositionInOrBefo reNode(n), selectTag)) { |
| 231 next = Strategy::nextSkippingChildren(*n); | 256 next = Strategy::nextSkippingChildren(*n); |
| 232 // Don't skip over pastEnd. | 257 // Don't skip over pastEnd. |
| 233 if (pastEnd && Strategy::isDescendantOf(*pastEnd, *n)) | 258 if (pastEnd && Strategy::isDescendantOf(*pastEnd, *n)) |
| 234 next = pastEnd; | 259 next = pastEnd; |
| 235 } else { | 260 } else { |
| 236 // Add the node to the markup if we're not skipping the descendants | 261 // Add the node to the markup if we're not skipping the descendants |
| 237 if (markupAccumulator) | 262 appendStartMarkup(*n); |
| 238 appendStartMarkup(*markupAccumulator, *n); | |
| 239 | 263 |
| 240 // If node has no children, close the tag now. | 264 // If node has no children, close the tag now. |
| 241 if (Strategy::hasChildren(*n)) { | 265 if (Strategy::hasChildren(*n)) { |
| 242 ancestorsToClose.append(toContainerNode(n)); | 266 ancestorsToClose.append(toContainerNode(n)); |
| 243 continue; | 267 continue; |
| 244 } | 268 } |
| 245 if (markupAccumulator && n->isElementNode()) | 269 appendEndMarkup(*n); |
| 246 markupAccumulator->appendEndTag(toElement(*n)); | |
| 247 lastClosed = n; | 270 lastClosed = n; |
| 248 } | 271 } |
| 249 | 272 |
| 250 // If we didn't insert open tag and there's no more siblings or we're at the end of the traversal, take care of ancestors. | 273 // If we didn't insert open tag and there's no more siblings or we're at the end of the traversal, take care of ancestors. |
| 251 // FIXME: What happens if we just inserted open tag and reached the end? | 274 // FIXME: What happens if we just inserted open tag and reached the end? |
| 252 if (Strategy::nextSibling(*n) && next != pastEnd) | 275 if (Strategy::nextSibling(*n) && next != pastEnd) |
| 253 continue; | 276 continue; |
| 254 | 277 |
| 255 // Close up the ancestors. | 278 // Close up the ancestors. |
| 256 while (!ancestorsToClose.isEmpty()) { | 279 while (!ancestorsToClose.isEmpty()) { |
| 257 ContainerNode* ancestor = ancestorsToClose.last(); | 280 ContainerNode* ancestor = ancestorsToClose.last(); |
| 258 ASSERT(ancestor); | 281 ASSERT(ancestor); |
| 259 if (next != pastEnd && Strategy::isDescendantOf(*next, *ancestor)) | 282 if (next != pastEnd && Strategy::isDescendantOf(*next, *ancestor)) |
| 260 break; | 283 break; |
| 261 // Not at the end of the range, close ancestors up to sibling of nex t node. | 284 // Not at the end of the range, close ancestors up to sibling of nex t node. |
| 262 if (markupAccumulator && ancestor->isElementNode()) | 285 appendEndMarkup(*ancestor); |
| 263 markupAccumulator->appendEndTag(toElement(*ancestor)); | |
| 264 lastClosed = ancestor; | 286 lastClosed = ancestor; |
| 265 ancestorsToClose.removeLast(); | 287 ancestorsToClose.removeLast(); |
| 266 } | 288 } |
| 267 | 289 |
| 268 // Surround the currently accumulated markup with markup for ancestors w e never opened as we leave the subtree(s) rooted at those ancestors. | 290 // Surround the currently accumulated markup with markup for ancestors w e never opened as we leave the subtree(s) rooted at those ancestors. |
| 269 ContainerNode* nextParent = next ? Strategy::parent(*next) : nullptr; | 291 ContainerNode* nextParent = next ? Strategy::parent(*next) : nullptr; |
| 270 if (next == pastEnd || n == nextParent) | 292 if (next == pastEnd || n == nextParent) |
| 271 continue; | 293 continue; |
| 272 | 294 |
| 273 ASSERT(n); | 295 ASSERT(n); |
| 274 Node* lastAncestorClosedOrSelf = Strategy::isDescendantOf(*n, *lastClose d) ? lastClosed : n; | 296 Node* lastAncestorClosedOrSelf = Strategy::isDescendantOf(*n, *lastClose d) ? lastClosed : n; |
| 275 for (ContainerNode* parent = Strategy::parent(*lastAncestorClosedOrSelf) ; parent && parent != nextParent; parent = Strategy::parent(*parent)) { | 297 for (ContainerNode* parent = Strategy::parent(*lastAncestorClosedOrSelf) ; parent && parent != nextParent; parent = Strategy::parent(*parent)) { |
| 276 // All ancestors that aren't in the ancestorsToClose list should eit her be a) unrendered: | 298 // All ancestors that aren't in the ancestorsToClose list should eit her be a) unrendered: |
| 277 if (!parent->layoutObject()) | 299 if (!parent->layoutObject()) |
| 278 continue; | 300 continue; |
| 279 // or b) ancestors that we never encountered during a pre-order trav ersal starting at startNode: | 301 // or b) ancestors that we never encountered during a pre-order trav ersal starting at startNode: |
| 280 ASSERT(startNode); | 302 ASSERT(startNode); |
| 281 ASSERT(Strategy::isDescendantOf(*startNode, *parent)); | 303 ASSERT(Strategy::isDescendantOf(*startNode, *parent)); |
| 282 if (markupAccumulator) { | 304 RefPtrWillBeRawPtr<EditingStyle> style = createInlineStyleIfNeeded(* parent); |
| 283 RefPtrWillBeRawPtr<EditingStyle> style = createInlineStyleIfNeed ed(*parent); | 305 wrapWithNode(*parent, style); |
| 284 wrapWithNode(*markupAccumulator, *parent, style); | |
| 285 } | |
| 286 lastClosed = parent; | 306 lastClosed = parent; |
| 287 } | 307 } |
| 288 } | 308 } |
| 289 | 309 |
| 290 return lastClosed; | 310 return lastClosed; |
| 291 } | 311 } |
| 292 | 312 |
| 293 template<typename Strategy> | 313 template<typename Strategy> |
| 294 bool StyledMarkupSerializer<Strategy>::needsInlineStyle(const Element& element) | 314 bool Traverser<Strategy>::needsInlineStyle(const Element& element) |
| 295 { | 315 { |
| 296 if (!element.isHTMLElement()) | 316 if (!element.isHTMLElement()) |
| 297 return false; | 317 return false; |
| 298 if (shouldAnnotate()) | 318 if (m_accumulator->shouldAnnotate()) |
| 299 return true; | 319 return true; |
| 300 return convertBlocksToInlines() && isBlock(&element); | 320 return m_accumulator->convertBlocksToInlines() && isBlock(&element); |
| 301 } | 321 } |
| 302 | 322 |
| 303 template<typename Strategy> | 323 template<typename Strategy> |
| 304 void StyledMarkupSerializer<Strategy>::wrapWithNode(StyledMarkupAccumulator& acc umulator, ContainerNode& node, PassRefPtrWillBeRawPtr<EditingStyle> style) | 324 void Traverser<Strategy>::wrapWithNode(ContainerNode& node, PassRefPtrWillBeRawP tr<EditingStyle> style) |
| 305 { | 325 { |
| 326 if (!m_accumulator) | |
| 327 return; | |
| 306 StringBuilder markup; | 328 StringBuilder markup; |
| 307 if (node.isDocumentNode()) { | 329 if (node.isDocumentNode()) { |
| 308 MarkupFormatter::appendXMLDeclaration(markup, toDocument(node)); | 330 MarkupFormatter::appendXMLDeclaration(markup, toDocument(node)); |
| 309 accumulator.pushMarkup(markup.toString()); | 331 m_accumulator->pushMarkup(markup.toString()); |
| 310 return; | 332 return; |
| 311 } | 333 } |
| 312 if (!node.isElementNode()) | 334 if (!node.isElementNode()) |
| 313 return; | 335 return; |
| 314 Element& element = toElement(node); | 336 Element& element = toElement(node); |
| 315 if (shouldApplyWrappingStyle(element) || needsInlineStyle(element)) | 337 if (shouldApplyWrappingStyle(element) || needsInlineStyle(element)) |
|
yosin_UTC9
2015/06/17 14:33:06
Note: in ALL-IN-ONE, we check |shouldApplyWrapping
hajimehoshi
2015/06/18 02:04:56
As we talked, let's do such fix later.
| |
| 316 accumulator.appendElementWithInlineStyle(markup, element, style); | 338 m_accumulator->appendElementWithInlineStyle(markup, element, style); |
| 317 else | 339 else |
| 318 accumulator.appendElement(markup, element); | 340 m_accumulator->appendElement(markup, element); |
| 319 accumulator.pushMarkup(markup.toString()); | 341 m_accumulator->pushMarkup(markup.toString()); |
| 320 accumulator.appendEndTag(toElement(node)); | 342 m_accumulator->appendEndTag(toElement(node)); |
| 321 } | 343 } |
| 322 | 344 |
| 323 template<typename Strategy> | 345 template<typename Strategy> |
| 324 RefPtrWillBeRawPtr<EditingStyle> StyledMarkupSerializer<Strategy>::createInlineS tyleIfNeeded(Node& node) | 346 RefPtrWillBeRawPtr<EditingStyle> Traverser<Strategy>::createInlineStyleIfNeeded( Node& node) |
| 325 { | 347 { |
| 348 if (!m_accumulator) | |
| 349 return nullptr; | |
| 326 if (!node.isElementNode()) | 350 if (!node.isElementNode()) |
| 327 return nullptr; | 351 return nullptr; |
| 328 RefPtrWillBeRawPtr<EditingStyle> inlineStyle = createInlineStyle(toElement(n ode)); | 352 RefPtrWillBeRawPtr<EditingStyle> inlineStyle = createInlineStyle(toElement(n ode)); |
| 329 if (convertBlocksToInlines() && isBlock(&node)) | 353 if (m_accumulator->convertBlocksToInlines() && isBlock(&node)) |
|
yosin_UTC9
2015/06/17 14:06:28
We have two |m_accumulator->convertBlocksToInlines
hajimehoshi
2015/06/18 02:04:56
Done.
| |
| 330 inlineStyle->forceInline(); | 354 inlineStyle->forceInline(); |
| 331 return inlineStyle; | 355 return inlineStyle; |
| 332 } | 356 } |
| 333 | 357 |
| 334 template<typename Strategy> | 358 template<typename Strategy> |
| 335 void StyledMarkupSerializer<Strategy>::appendStartMarkup(StyledMarkupAccumulator & accumulator, Node& node) | 359 void Traverser<Strategy>::appendStartMarkup(Node& node) |
| 336 { | 360 { |
| 361 if (!m_accumulator) | |
| 362 return; | |
| 337 switch (node.nodeType()) { | 363 switch (node.nodeType()) { |
| 338 case Node::TEXT_NODE: { | 364 case Node::TEXT_NODE: { |
| 339 Text& text = toText(node); | 365 Text& text = toText(node); |
| 340 if (text.parentElement() && text.parentElement()->tagQName() == textarea Tag) { | 366 if (text.parentElement() && text.parentElement()->tagQName() == textarea Tag) { |
|
yosin_UTC9
2015/06/17 13:31:01
isHTMLTextAreaElement(text.parentElement())
hajimehoshi
2015/06/18 02:04:56
Done.
| |
| 341 accumulator.appendText(text); | 367 m_accumulator->appendText(text); |
| 342 break; | 368 break; |
| 343 } | 369 } |
| 344 RefPtrWillBeRawPtr<EditingStyle> inlineStyle = nullptr; | 370 RefPtrWillBeRawPtr<EditingStyle> inlineStyle = nullptr; |
| 345 if (shouldApplyWrappingStyle(text)) { | 371 if (shouldApplyWrappingStyle(text)) { |
| 346 inlineStyle = m_wrappingStyle->copy(); | 372 inlineStyle = m_wrappingStyle->copy(); |
| 347 // FIXME: <rdar://problem/5371536> Style rules that match pasted con tent can change it's appearance | 373 // FIXME: <rdar://problem/5371536> Style rules that match pasted con tent can change it's appearance |
| 348 // Make sure spans are inline style in paste side e.g. span { displa y: block }. | 374 // Make sure spans are inline style in paste side e.g. span { displa y: block }. |
| 349 inlineStyle->forceInline(); | 375 inlineStyle->forceInline(); |
| 350 // FIXME: Should this be included in forceInline? | 376 // FIXME: Should this be included in forceInline? |
| 351 inlineStyle->style()->setProperty(CSSPropertyFloat, CSSValueNone); | 377 inlineStyle->style()->setProperty(CSSPropertyFloat, CSSValueNone); |
| 352 } | 378 } |
| 353 accumulator.appendTextWithInlineStyle(text, inlineStyle); | 379 m_accumulator->appendTextWithInlineStyle(text, inlineStyle); |
|
yosin_UTC9
2015/06/17 13:31:02
Note: For supporting composed tree, we should have
hajimehoshi
2015/06/18 02:04:56
As we talked, do such fix later.
| |
| 354 break; | 380 break; |
| 355 } | 381 } |
| 356 case Node::ELEMENT_NODE: { | 382 case Node::ELEMENT_NODE: { |
| 357 Element& element = toElement(node); | 383 Element& element = toElement(node); |
| 358 if ((element.isHTMLElement() && shouldAnnotate()) || shouldApplyWrapping Style(element)) { | 384 if ((element.isHTMLElement() && m_accumulator->shouldAnnotate()) || shou ldApplyWrappingStyle(element)) { |
| 359 RefPtrWillBeRawPtr<EditingStyle> inlineStyle = createInlineStyle(ele ment); | 385 RefPtrWillBeRawPtr<EditingStyle> inlineStyle = createInlineStyle(ele ment); |
| 360 accumulator.appendElementWithInlineStyle(element, inlineStyle); | 386 m_accumulator->appendElementWithInlineStyle(element, inlineStyle); |
| 361 break; | 387 break; |
| 362 } | 388 } |
| 363 accumulator.appendElement(element); | 389 m_accumulator->appendElement(element); |
| 364 break; | 390 break; |
| 365 } | 391 } |
| 366 default: | 392 default: |
| 367 accumulator.appendStartMarkup(node); | 393 m_accumulator->appendStartMarkup(node); |
| 368 break; | 394 break; |
| 369 } | 395 } |
| 370 } | 396 } |
| 371 | 397 |
| 372 template<typename Strategy> | 398 template<typename Strategy> |
| 373 bool StyledMarkupSerializer<Strategy>::shouldApplyWrappingStyle(const Node& node ) const | 399 void Traverser<Strategy>::appendEndMarkup(Node& node) |
| 400 { | |
| 401 if (m_accumulator && node.isElementNode()) | |
|
yosin_UTC9
2015/06/17 13:31:02
Let's use early return pattern.
hajimehoshi
2015/06/18 02:04:56
Done.
| |
| 402 m_accumulator->appendEndTag(toElement(node)); | |
|
yosin_UTC9
2015/06/17 14:06:28
We need to check whether we use empty tag or not,
hajimehoshi
2015/06/18 02:04:56
As we talked, do such fix later.
| |
| 403 } | |
| 404 | |
| 405 template<typename Strategy> | |
| 406 bool Traverser<Strategy>::shouldApplyWrappingStyle(const Node& node) const | |
| 374 { | 407 { |
| 375 return m_lastClosed && Strategy::parent(*m_lastClosed) == Strategy::parent(n ode) | 408 return m_lastClosed && Strategy::parent(*m_lastClosed) == Strategy::parent(n ode) |
| 376 && m_wrappingStyle && m_wrappingStyle->style(); | 409 && m_wrappingStyle && m_wrappingStyle->style(); |
| 377 } | 410 } |
| 378 | 411 |
| 379 template<typename Strategy> | 412 template<typename Strategy> |
| 380 RefPtrWillBeRawPtr<EditingStyle> StyledMarkupSerializer<Strategy>::createInlineS tyle(Element& element) | 413 RefPtrWillBeRawPtr<EditingStyle> Traverser<Strategy>::createInlineStyle(Element& element) |
| 381 { | 414 { |
| 382 RefPtrWillBeRawPtr<EditingStyle> inlineStyle = nullptr; | 415 RefPtrWillBeRawPtr<EditingStyle> inlineStyle = nullptr; |
| 383 | 416 |
| 384 if (shouldApplyWrappingStyle(element)) { | 417 if (shouldApplyWrappingStyle(element)) { |
| 385 inlineStyle = m_wrappingStyle->copy(); | 418 inlineStyle = m_wrappingStyle->copy(); |
| 386 inlineStyle->removePropertiesInElementDefaultStyle(&element); | 419 inlineStyle->removePropertiesInElementDefaultStyle(&element); |
| 387 inlineStyle->removeStyleConflictingWithStyleOfElement(&element); | 420 inlineStyle->removeStyleConflictingWithStyleOfElement(&element); |
| 388 } else { | 421 } else { |
| 389 inlineStyle = EditingStyle::create(); | 422 inlineStyle = EditingStyle::create(); |
| 390 } | 423 } |
| 391 | 424 |
| 392 if (element.isStyledElement() && element.inlineStyle()) | 425 if (element.isStyledElement() && element.inlineStyle()) |
| 393 inlineStyle->overrideWithStyle(element.inlineStyle()); | 426 inlineStyle->overrideWithStyle(element.inlineStyle()); |
| 394 | 427 |
| 395 if (element.isHTMLElement() && shouldAnnotate()) | 428 if (element.isHTMLElement() && m_accumulator->shouldAnnotate()) |
| 396 inlineStyle->mergeStyleFromRulesForSerialization(&toHTMLElement(element) ); | 429 inlineStyle->mergeStyleFromRulesForSerialization(&toHTMLElement(element) ); |
| 397 | 430 |
| 398 return inlineStyle; | 431 return inlineStyle; |
| 399 } | 432 } |
| 400 | 433 |
| 401 template class StyledMarkupSerializer<EditingStrategy>; | 434 template class StyledMarkupSerializer<EditingStrategy>; |
| 402 | 435 |
| 403 } // namespace blink | 436 } // namespace blink |
| OLD | NEW |