Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(118)

Side by Side Diff: third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.cpp

Issue 2393243003: Reflow comments in //third_party/WebKit/Sourcecore/editing/serializers (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
3 * reserved.
3 * Copyright (C) 2008, 2009, 2010, 2011 Google Inc. All rights reserved. 4 * Copyright (C) 2008, 2009, 2010, 2011 Google Inc. All rights reserved.
4 * Copyright (C) 2011 Igalia S.L. 5 * Copyright (C) 2011 Igalia S.L.
5 * Copyright (C) 2011 Motorola Mobility. All rights reserved. 6 * Copyright (C) 2011 Motorola Mobility. All rights reserved.
6 * 7 *
7 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
9 * are met: 10 * are met:
10 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 m_lastClosed(highestNodeToBeSerialized) {} 135 m_lastClosed(highestNodeToBeSerialized) {}
135 136
136 template <typename Strategy> 137 template <typename Strategy>
137 static bool needInterchangeNewlineAfter( 138 static bool needInterchangeNewlineAfter(
138 const VisiblePositionTemplate<Strategy>& v) { 139 const VisiblePositionTemplate<Strategy>& v) {
139 const VisiblePositionTemplate<Strategy> next = nextPositionOf(v); 140 const VisiblePositionTemplate<Strategy> next = nextPositionOf(v);
140 Node* upstreamNode = 141 Node* upstreamNode =
141 mostBackwardCaretPosition(next.deepEquivalent()).anchorNode(); 142 mostBackwardCaretPosition(next.deepEquivalent()).anchorNode();
142 Node* downstreamNode = 143 Node* downstreamNode =
143 mostForwardCaretPosition(v.deepEquivalent()).anchorNode(); 144 mostForwardCaretPosition(v.deepEquivalent()).anchorNode();
144 // Add an interchange newline if a paragraph break is selected and a br won't already be added to the markup to represent it. 145 // Add an interchange newline if a paragraph break is selected and a br won't
146 // already be added to the markup to represent it.
145 return isEndOfParagraph(v) && isStartOfParagraph(next) && 147 return isEndOfParagraph(v) && isStartOfParagraph(next) &&
146 !(isHTMLBRElement(*upstreamNode) && upstreamNode == downstreamNode); 148 !(isHTMLBRElement(*upstreamNode) && upstreamNode == downstreamNode);
147 } 149 }
148 150
149 template <typename Strategy> 151 template <typename Strategy>
150 static bool needInterchangeNewlineAt( 152 static bool needInterchangeNewlineAt(
151 const VisiblePositionTemplate<Strategy>& v) { 153 const VisiblePositionTemplate<Strategy>& v) {
152 return needInterchangeNewlineAfter(previousPositionOf(v)); 154 return needInterchangeNewlineAfter(previousPositionOf(v));
153 } 155 }
154 156
155 template <typename Strategy> 157 template <typename Strategy>
156 static bool areSameRanges(Node* node, 158 static bool areSameRanges(Node* node,
157 const PositionTemplate<Strategy>& startPosition, 159 const PositionTemplate<Strategy>& startPosition,
158 const PositionTemplate<Strategy>& endPosition) { 160 const PositionTemplate<Strategy>& endPosition) {
159 DCHECK(node); 161 DCHECK(node);
160 const EphemeralRange range = 162 const EphemeralRange range =
161 VisibleSelection::selectionFromContentsOfNode(node) 163 VisibleSelection::selectionFromContentsOfNode(node)
162 .toNormalizedEphemeralRange(); 164 .toNormalizedEphemeralRange();
163 return toPositionInDOMTree(startPosition) == range.startPosition() && 165 return toPositionInDOMTree(startPosition) == range.startPosition() &&
164 toPositionInDOMTree(endPosition) == range.endPosition(); 166 toPositionInDOMTree(endPosition) == range.endPosition();
165 } 167 }
166 168
167 static EditingStyle* styleFromMatchedRulesAndInlineDecl( 169 static EditingStyle* styleFromMatchedRulesAndInlineDecl(
168 const HTMLElement* element) { 170 const HTMLElement* element) {
169 EditingStyle* style = EditingStyle::create(element->inlineStyle()); 171 EditingStyle* style = EditingStyle::create(element->inlineStyle());
170 // FIXME: Having to const_cast here is ugly, but it is quite a bit of work to untangle 172 // FIXME: Having to const_cast here is ugly, but it is quite a bit of work to
171 // the non-const-ness of styleFromMatchedRulesForElement. 173 // untangle the non-const-ness of styleFromMatchedRulesForElement.
172 style->mergeStyleFromRules(const_cast<HTMLElement*>(element)); 174 style->mergeStyleFromRules(const_cast<HTMLElement*>(element));
173 return style; 175 return style;
174 } 176 }
175 177
176 template <typename Strategy> 178 template <typename Strategy>
177 String StyledMarkupSerializer<Strategy>::createMarkup() { 179 String StyledMarkupSerializer<Strategy>::createMarkup() {
178 StyledMarkupAccumulator markupAccumulator( 180 StyledMarkupAccumulator markupAccumulator(
179 m_shouldResolveURLs, toTextOffset(m_start.parentAnchoredEquivalent()), 181 m_shouldResolveURLs, toTextOffset(m_start.parentAnchoredEquivalent()),
180 toTextOffset(m_end.parentAnchoredEquivalent()), m_start.document(), 182 toTextOffset(m_end.parentAnchoredEquivalent()), m_start.document(),
181 m_shouldAnnotate, m_convertBlocksToInlines); 183 m_shouldAnnotate, m_convertBlocksToInlines);
(...skipping 14 matching lines...) Expand all
196 firstNode = nextPositionOf(visibleStart).deepEquivalent().anchorNode(); 198 firstNode = nextPositionOf(visibleStart).deepEquivalent().anchorNode();
197 199
198 if (pastEnd && 200 if (pastEnd &&
199 PositionTemplate<Strategy>::beforeNode(firstNode).compareTo( 201 PositionTemplate<Strategy>::beforeNode(firstNode).compareTo(
200 PositionTemplate<Strategy>::beforeNode(pastEnd)) >= 0) { 202 PositionTemplate<Strategy>::beforeNode(pastEnd)) >= 0) {
201 // This condition hits in editing/pasteboard/copy-display-none.html. 203 // This condition hits in editing/pasteboard/copy-display-none.html.
202 return markupAccumulator.takeResults(); 204 return markupAccumulator.takeResults();
203 } 205 }
204 } 206 }
205 207
206 // If there is no the highest node in the selected nodes, |m_lastClosed| can b e #text 208 // If there is no the highest node in the selected nodes, |m_lastClosed| can
207 // when its parent is a formatting tag. In this case, #text is wrapped by <spa n> tag, 209 // be #text when its parent is a formatting tag. In this case, #text is
208 // but this text should be wrapped by the formatting tag. See http://crbug.com /634482 210 // wrapped by <span> tag, but this text should be wrapped by the formatting
211 // tag. See http://crbug.com/634482
209 bool shouldAppendParentTag = false; 212 bool shouldAppendParentTag = false;
210 if (!m_lastClosed) { 213 if (!m_lastClosed) {
211 m_lastClosed = 214 m_lastClosed =
212 StyledMarkupTraverser<Strategy>().traverse(firstNode, pastEnd); 215 StyledMarkupTraverser<Strategy>().traverse(firstNode, pastEnd);
213 if (m_lastClosed && m_lastClosed->isTextNode() && 216 if (m_lastClosed && m_lastClosed->isTextNode() &&
214 isPresentationalHTMLElement(m_lastClosed->parentNode())) { 217 isPresentationalHTMLElement(m_lastClosed->parentNode())) {
215 m_lastClosed = m_lastClosed->parentElement(); 218 m_lastClosed = m_lastClosed->parentElement();
216 shouldAppendParentTag = true; 219 shouldAppendParentTag = true;
217 } 220 }
218 } 221 }
219 222
220 StyledMarkupTraverser<Strategy> traverser(&markupAccumulator, m_lastClosed); 223 StyledMarkupTraverser<Strategy> traverser(&markupAccumulator, m_lastClosed);
221 Node* lastClosed = traverser.traverse(firstNode, pastEnd); 224 Node* lastClosed = traverser.traverse(firstNode, pastEnd);
222 225
223 if (m_highestNodeToBeSerialized && lastClosed) { 226 if (m_highestNodeToBeSerialized && lastClosed) {
224 // TODO(hajimehoshi): This is calculated at createMarkupInternal too. 227 // TODO(hajimehoshi): This is calculated at createMarkupInternal too.
225 Node* commonAncestor = Strategy::commonAncestor( 228 Node* commonAncestor = Strategy::commonAncestor(
226 *m_start.computeContainerNode(), *m_end.computeContainerNode()); 229 *m_start.computeContainerNode(), *m_end.computeContainerNode());
227 DCHECK(commonAncestor); 230 DCHECK(commonAncestor);
228 HTMLBodyElement* body = toHTMLBodyElement(enclosingElementWithTag( 231 HTMLBodyElement* body = toHTMLBodyElement(enclosingElementWithTag(
229 Position::firstPositionInNode(commonAncestor), bodyTag)); 232 Position::firstPositionInNode(commonAncestor), bodyTag));
230 HTMLBodyElement* fullySelectedRoot = nullptr; 233 HTMLBodyElement* fullySelectedRoot = nullptr;
231 // FIXME: Do this for all fully selected blocks, not just the body. 234 // FIXME: Do this for all fully selected blocks, not just the body.
232 if (body && areSameRanges(body, m_start, m_end)) 235 if (body && areSameRanges(body, m_start, m_end))
233 fullySelectedRoot = body; 236 fullySelectedRoot = body;
234 237
235 // Also include all of the ancestors of lastClosed up to this special ancest or. 238 // Also include all of the ancestors of lastClosed up to this special
239 // ancestor.
236 // FIXME: What is ancestor? 240 // FIXME: What is ancestor?
237 for (ContainerNode* ancestor = Strategy::parent(*lastClosed); ancestor; 241 for (ContainerNode* ancestor = Strategy::parent(*lastClosed); ancestor;
238 ancestor = Strategy::parent(*ancestor)) { 242 ancestor = Strategy::parent(*ancestor)) {
239 if (ancestor == fullySelectedRoot && 243 if (ancestor == fullySelectedRoot &&
240 !markupAccumulator.convertBlocksToInlines()) { 244 !markupAccumulator.convertBlocksToInlines()) {
241 EditingStyle* fullySelectedRootStyle = 245 EditingStyle* fullySelectedRootStyle =
242 styleFromMatchedRulesAndInlineDecl(fullySelectedRoot); 246 styleFromMatchedRulesAndInlineDecl(fullySelectedRoot);
243 247
244 // Bring the background attribute over, but not as an attribute because a background attribute on a div 248 // Bring the background attribute over, but not as an attribute because
245 // appears to have no effect. 249 // a background attribute on a div appears to have no effect.
246 if ((!fullySelectedRootStyle || !fullySelectedRootStyle->style() || 250 if ((!fullySelectedRootStyle || !fullySelectedRootStyle->style() ||
247 !fullySelectedRootStyle->style()->getPropertyCSSValue( 251 !fullySelectedRootStyle->style()->getPropertyCSSValue(
248 CSSPropertyBackgroundImage)) && 252 CSSPropertyBackgroundImage)) &&
249 fullySelectedRoot->hasAttribute(backgroundAttr)) 253 fullySelectedRoot->hasAttribute(backgroundAttr))
250 fullySelectedRootStyle->style()->setProperty( 254 fullySelectedRootStyle->style()->setProperty(
251 CSSPropertyBackgroundImage, 255 CSSPropertyBackgroundImage,
252 "url('" + fullySelectedRoot->getAttribute(backgroundAttr) + "')"); 256 "url('" + fullySelectedRoot->getAttribute(backgroundAttr) + "')");
253 257
254 if (fullySelectedRootStyle->style()) { 258 if (fullySelectedRootStyle->style()) {
255 // Reset the CSS properties to avoid an assertion error in addStyleMar kup(). 259 // Reset the CSS properties to avoid an assertion error in
256 // This assertion is caused at least when we select all text of a <bod y> element whose 260 // addStyleMarkup(). This assertion is caused at least when we select
257 // 'text-decoration' property is "inherit", and copy it. 261 // all text of a <body> element whose 'text-decoration' property is
262 // "inherit", and copy it.
258 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->style(), 263 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->style(),
259 CSSPropertyTextDecoration)) 264 CSSPropertyTextDecoration))
260 fullySelectedRootStyle->style()->setProperty( 265 fullySelectedRootStyle->style()->setProperty(
261 CSSPropertyTextDecoration, CSSValueNone); 266 CSSPropertyTextDecoration, CSSValueNone);
262 if (!propertyMissingOrEqualToNone( 267 if (!propertyMissingOrEqualToNone(
263 fullySelectedRootStyle->style(), 268 fullySelectedRootStyle->style(),
264 CSSPropertyWebkitTextDecorationsInEffect)) 269 CSSPropertyWebkitTextDecorationsInEffect))
265 fullySelectedRootStyle->style()->setProperty( 270 fullySelectedRootStyle->style()->setProperty(
266 CSSPropertyWebkitTextDecorationsInEffect, CSSValueNone); 271 CSSPropertyWebkitTextDecorationsInEffect, CSSValueNone);
267 markupAccumulator.wrapWithStyleNode(fullySelectedRootStyle->style()); 272 markupAccumulator.wrapWithStyleNode(fullySelectedRootStyle->style());
268 } 273 }
269 } else { 274 } else {
270 EditingStyle* style = traverser.createInlineStyleIfNeeded(*ancestor); 275 EditingStyle* style = traverser.createInlineStyleIfNeeded(*ancestor);
271 // Since this node and all the other ancestors are not in the selection we want 276 // Since this node and all the other ancestors are not in the selection
272 // styles that affect the exterior of the node not to be not included. 277 // we want styles that affect the exterior of the node not to be not
273 // 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 278 // included. If the node is not fully selected by the range, then we
274 // only the ones that affect it and the nodes within it. 279 // don't want to keep styles that affect its relationship to the nodes
280 // around it only the ones that affect it and the nodes within it.
275 if (style && style->style()) 281 if (style && style->style())
276 style->style()->removeProperty(CSSPropertyFloat); 282 style->style()->removeProperty(CSSPropertyFloat);
277 traverser.wrapWithNode(*ancestor, style); 283 traverser.wrapWithNode(*ancestor, style);
278 } 284 }
279 285
280 if (ancestor == m_highestNodeToBeSerialized) 286 if (ancestor == m_highestNodeToBeSerialized)
281 break; 287 break;
282 } 288 }
283 } else if (shouldAppendParentTag) { 289 } else if (shouldAppendParentTag) {
284 EditingStyle* style = traverser.createInlineStyleIfNeeded(*m_lastClosed); 290 EditingStyle* style = traverser.createInlineStyleIfNeeded(*m_lastClosed);
285 traverser.wrapWithNode(*toContainerNode(m_lastClosed), style); 291 traverser.wrapWithNode(*toContainerNode(m_lastClosed), style);
286 } 292 }
287 293
288 // FIXME: The interchange newline should be placed in the block that it's in, not after all of the content, unconditionally. 294 // FIXME: The interchange newline should be placed in the block that it's in,
295 // not after all of the content, unconditionally.
289 if (shouldAnnotate() && needInterchangeNewlineAt(visibleEnd)) 296 if (shouldAnnotate() && needInterchangeNewlineAt(visibleEnd))
290 markupAccumulator.appendInterchangeNewline(); 297 markupAccumulator.appendInterchangeNewline();
291 298
292 return markupAccumulator.takeResults(); 299 return markupAccumulator.takeResults();
293 } 300 }
294 301
295 template <typename Strategy> 302 template <typename Strategy>
296 StyledMarkupTraverser<Strategy>::StyledMarkupTraverser() 303 StyledMarkupTraverser<Strategy>::StyledMarkupTraverser()
297 : StyledMarkupTraverser(nullptr, nullptr) {} 304 : StyledMarkupTraverser(nullptr, nullptr) {}
298 305
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 // If node has no children, close the tag now. 362 // If node has no children, close the tag now.
356 if (Strategy::hasChildren(*n)) { 363 if (Strategy::hasChildren(*n)) {
357 ancestorsToClose.append(toContainerNode(n)); 364 ancestorsToClose.append(toContainerNode(n));
358 continue; 365 continue;
359 } 366 }
360 appendEndMarkup(*n); 367 appendEndMarkup(*n);
361 lastClosed = n; 368 lastClosed = n;
362 } 369 }
363 } 370 }
364 371
365 // 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. 372 // If we didn't insert open tag and there's no more siblings or we're at the
373 // end of the traversal, take care of ancestors.
366 // FIXME: What happens if we just inserted open tag and reached the end? 374 // FIXME: What happens if we just inserted open tag and reached the end?
367 if (Strategy::nextSibling(*n) && next != pastEnd) 375 if (Strategy::nextSibling(*n) && next != pastEnd)
368 continue; 376 continue;
369 377
370 // Close up the ancestors. 378 // Close up the ancestors.
371 while (!ancestorsToClose.isEmpty()) { 379 while (!ancestorsToClose.isEmpty()) {
372 ContainerNode* ancestor = ancestorsToClose.last(); 380 ContainerNode* ancestor = ancestorsToClose.last();
373 DCHECK(ancestor); 381 DCHECK(ancestor);
374 if (next && next != pastEnd && Strategy::isDescendantOf(*next, *ancestor)) 382 if (next && next != pastEnd && Strategy::isDescendantOf(*next, *ancestor))
375 break; 383 break;
376 // Not at the end of the range, close ancestors up to sibling of next node . 384 // Not at the end of the range, close ancestors up to sibling of next
385 // node.
377 appendEndMarkup(*ancestor); 386 appendEndMarkup(*ancestor);
378 lastClosed = ancestor; 387 lastClosed = ancestor;
379 ancestorsToClose.removeLast(); 388 ancestorsToClose.removeLast();
380 } 389 }
381 390
382 // Surround the currently accumulated markup with markup for ancestors we ne ver opened as we leave the subtree(s) rooted at those ancestors. 391 // Surround the currently accumulated markup with markup for ancestors we
392 // never opened as we leave the subtree(s) rooted at those ancestors.
383 ContainerNode* nextParent = next ? Strategy::parent(*next) : nullptr; 393 ContainerNode* nextParent = next ? Strategy::parent(*next) : nullptr;
384 if (next == pastEnd || n == nextParent) 394 if (next == pastEnd || n == nextParent)
385 continue; 395 continue;
386 396
387 DCHECK(n); 397 DCHECK(n);
388 Node* lastAncestorClosedOrSelf = 398 Node* lastAncestorClosedOrSelf =
389 (lastClosed && Strategy::isDescendantOf(*n, *lastClosed)) ? lastClosed 399 (lastClosed && Strategy::isDescendantOf(*n, *lastClosed)) ? lastClosed
390 : n; 400 : n;
391 for (ContainerNode* parent = Strategy::parent(*lastAncestorClosedOrSelf); 401 for (ContainerNode* parent = Strategy::parent(*lastAncestorClosedOrSelf);
392 parent && parent != nextParent; parent = Strategy::parent(*parent)) { 402 parent && parent != nextParent; parent = Strategy::parent(*parent)) {
393 // All ancestors that aren't in the ancestorsToClose list should either be a) unrendered: 403 // All ancestors that aren't in the ancestorsToClose list should either be
404 // a) unrendered:
394 if (!parent->layoutObject()) 405 if (!parent->layoutObject())
395 continue; 406 continue;
396 // or b) ancestors that we never encountered during a pre-order traversal starting at startNode: 407 // or b) ancestors that we never encountered during a pre-order traversal
408 // starting at startNode:
397 DCHECK(startNode); 409 DCHECK(startNode);
398 DCHECK(Strategy::isDescendantOf(*startNode, *parent)); 410 DCHECK(Strategy::isDescendantOf(*startNode, *parent));
399 EditingStyle* style = createInlineStyleIfNeeded(*parent); 411 EditingStyle* style = createInlineStyleIfNeeded(*parent);
400 wrapWithNode(*parent, style); 412 wrapWithNode(*parent, style);
401 lastClosed = parent; 413 lastClosed = parent;
402 } 414 }
403 } 415 }
404 416
405 return lastClosed; 417 return lastClosed;
406 } 418 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
456 switch (node.getNodeType()) { 468 switch (node.getNodeType()) {
457 case Node::kTextNode: { 469 case Node::kTextNode: {
458 Text& text = toText(node); 470 Text& text = toText(node);
459 if (text.parentElement() && isHTMLTextAreaElement(text.parentElement())) { 471 if (text.parentElement() && isHTMLTextAreaElement(text.parentElement())) {
460 m_accumulator->appendText(text); 472 m_accumulator->appendText(text);
461 break; 473 break;
462 } 474 }
463 EditingStyle* inlineStyle = nullptr; 475 EditingStyle* inlineStyle = nullptr;
464 if (shouldApplyWrappingStyle(text)) { 476 if (shouldApplyWrappingStyle(text)) {
465 inlineStyle = m_wrappingStyle->copy(); 477 inlineStyle = m_wrappingStyle->copy();
466 // FIXME: <rdar://problem/5371536> Style rules that match pasted content can change it's appearance 478 // FIXME: <rdar://problem/5371536> Style rules that match pasted content
467 // Make sure spans are inline style in paste side e.g. span { display: b lock }. 479 // can change it's appearance.
Nico 2016/10/06 03:26:21 nit: s/it's/its/
dcheng 2016/10/06 03:59:23 Done.
480 // Make sure spans are inline style in paste side e.g. span { display:
Nico 2016/10/06 03:26:21 nit: merge with previous line?
dcheng 2016/10/06 03:59:23 As far as I can tell, this was a distinct FIXME: h
481 // block }.
468 inlineStyle->forceInline(); 482 inlineStyle->forceInline();
469 // FIXME: Should this be included in forceInline? 483 // FIXME: Should this be included in forceInline?
470 inlineStyle->style()->setProperty(CSSPropertyFloat, CSSValueNone); 484 inlineStyle->style()->setProperty(CSSPropertyFloat, CSSValueNone);
471 } 485 }
472 m_accumulator->appendTextWithInlineStyle(text, inlineStyle); 486 m_accumulator->appendTextWithInlineStyle(text, inlineStyle);
473 break; 487 break;
474 } 488 }
475 case Node::kElementNode: { 489 case Node::kElementNode: {
476 Element& element = toElement(node); 490 Element& element = toElement(node);
477 if ((element.isHTMLElement() && shouldAnnotate()) || 491 if ((element.isHTMLElement() && shouldAnnotate()) ||
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 if (element.isHTMLElement() && shouldAnnotate()) 537 if (element.isHTMLElement() && shouldAnnotate())
524 inlineStyle->mergeStyleFromRulesForSerialization(&toHTMLElement(element)); 538 inlineStyle->mergeStyleFromRulesForSerialization(&toHTMLElement(element));
525 539
526 return inlineStyle; 540 return inlineStyle;
527 } 541 }
528 542
529 template class StyledMarkupSerializer<EditingStrategy>; 543 template class StyledMarkupSerializer<EditingStrategy>;
530 template class StyledMarkupSerializer<EditingInFlatTreeStrategy>; 544 template class StyledMarkupSerializer<EditingInFlatTreeStrategy>;
531 545
532 } // namespace blink 546 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698