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 |
| 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 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 Node* constrainingAncestor) { | 171 Node* constrainingAncestor) { |
171 Node* firstNode = startPosition.nodeAsRangeFirstNode(); | 172 Node* firstNode = startPosition.nodeAsRangeFirstNode(); |
172 // For compatibility reason, we use container node of start and end | 173 // For compatibility reason, we use container node of start and end |
173 // positions rather than first node and last node in selection. | 174 // positions rather than first node and last node in selection. |
174 Node* commonAncestor = | 175 Node* commonAncestor = |
175 Strategy::commonAncestor(*startPosition.computeContainerNode(), | 176 Strategy::commonAncestor(*startPosition.computeContainerNode(), |
176 *endPosition.computeContainerNode()); | 177 *endPosition.computeContainerNode()); |
177 DCHECK(commonAncestor); | 178 DCHECK(commonAncestor); |
178 HTMLElement* specialCommonAncestor = nullptr; | 179 HTMLElement* specialCommonAncestor = nullptr; |
179 if (shouldAnnotate == AnnotateForInterchange) { | 180 if (shouldAnnotate == AnnotateForInterchange) { |
180 // Include ancestors that aren't completely inside the range but are require
d to retain | 181 // Include ancestors that aren't completely inside the range but are |
181 // the structure and appearance of the copied markup. | 182 // required to retain the structure and appearance of the copied markup. |
182 specialCommonAncestor = | 183 specialCommonAncestor = |
183 ancestorToRetainStructureAndAppearance(commonAncestor); | 184 ancestorToRetainStructureAndAppearance(commonAncestor); |
184 if (Node* parentListNode = enclosingNodeOfType( | 185 if (Node* parentListNode = enclosingNodeOfType( |
185 firstPositionInOrBeforeNode(firstNode), isListItem)) { | 186 firstPositionInOrBeforeNode(firstNode), isListItem)) { |
186 EphemeralRangeTemplate<Strategy> markupRange = | 187 EphemeralRangeTemplate<Strategy> markupRange = |
187 EphemeralRangeTemplate<Strategy>(startPosition, endPosition); | 188 EphemeralRangeTemplate<Strategy>(startPosition, endPosition); |
188 EphemeralRangeTemplate<Strategy> nodeRange = normalizeRange( | 189 EphemeralRangeTemplate<Strategy> nodeRange = normalizeRange( |
189 EphemeralRangeTemplate<Strategy>::rangeOfContents(*parentListNode)); | 190 EphemeralRangeTemplate<Strategy>::rangeOfContents(*parentListNode)); |
190 if (nodeRange == markupRange) { | 191 if (nodeRange == markupRange) { |
191 ContainerNode* ancestor = parentListNode->parentNode(); | 192 ContainerNode* ancestor = parentListNode->parentNode(); |
(...skipping 16 matching lines...) Expand all Loading... |
208 if (checkAncestor->layoutObject()) { | 209 if (checkAncestor->layoutObject()) { |
209 HTMLElement* newSpecialCommonAncestor = | 210 HTMLElement* newSpecialCommonAncestor = |
210 toHTMLElement(highestEnclosingNodeOfType( | 211 toHTMLElement(highestEnclosingNodeOfType( |
211 Position::firstPositionInNode(checkAncestor), | 212 Position::firstPositionInNode(checkAncestor), |
212 &isPresentationalHTMLElement, CanCrossEditingBoundary, | 213 &isPresentationalHTMLElement, CanCrossEditingBoundary, |
213 constrainingAncestor)); | 214 constrainingAncestor)); |
214 if (newSpecialCommonAncestor) | 215 if (newSpecialCommonAncestor) |
215 specialCommonAncestor = newSpecialCommonAncestor; | 216 specialCommonAncestor = newSpecialCommonAncestor; |
216 } | 217 } |
217 | 218 |
218 // If a single tab is selected, commonAncestor will be a text node inside a ta
b span. | 219 // If a single tab is selected, commonAncestor will be a text node inside a |
219 // If two or more tabs are selected, commonAncestor will be the tab span. | 220 // tab span. If two or more tabs are selected, commonAncestor will be the tab |
220 // In either case, if there is a specialCommonAncestor already, it will necess
arily be above | 221 // span. In either case, if there is a specialCommonAncestor already, it will |
221 // any tab span that needs to be included. | 222 // necessarily be above any tab span that needs to be included. |
222 if (!specialCommonAncestor && isTabHTMLSpanElementTextNode(commonAncestor)) | 223 if (!specialCommonAncestor && isTabHTMLSpanElementTextNode(commonAncestor)) |
223 specialCommonAncestor = | 224 specialCommonAncestor = |
224 toHTMLSpanElement(Strategy::parent(*commonAncestor)); | 225 toHTMLSpanElement(Strategy::parent(*commonAncestor)); |
225 if (!specialCommonAncestor && isTabHTMLSpanElement(commonAncestor)) | 226 if (!specialCommonAncestor && isTabHTMLSpanElement(commonAncestor)) |
226 specialCommonAncestor = toHTMLSpanElement(commonAncestor); | 227 specialCommonAncestor = toHTMLSpanElement(commonAncestor); |
227 | 228 |
228 if (HTMLAnchorElement* enclosingAnchor = | 229 if (HTMLAnchorElement* enclosingAnchor = |
229 toHTMLAnchorElement(enclosingElementWithTag( | 230 toHTMLAnchorElement(enclosingElementWithTag( |
230 Position::firstPositionInNode(specialCommonAncestor | 231 Position::firstPositionInNode(specialCommonAncestor |
231 ? specialCommonAncestor | 232 ? specialCommonAncestor |
232 : commonAncestor), | 233 : commonAncestor), |
233 aTag))) | 234 aTag))) |
234 specialCommonAncestor = enclosingAnchor; | 235 specialCommonAncestor = enclosingAnchor; |
235 | 236 |
236 return specialCommonAncestor; | 237 return specialCommonAncestor; |
237 } | 238 } |
238 | 239 |
239 template <typename Strategy> | 240 template <typename Strategy> |
240 class CreateMarkupAlgorithm { | 241 class CreateMarkupAlgorithm { |
241 public: | 242 public: |
242 static String createMarkup( | 243 static String createMarkup( |
243 const PositionTemplate<Strategy>& startPosition, | 244 const PositionTemplate<Strategy>& startPosition, |
244 const PositionTemplate<Strategy>& endPosition, | 245 const PositionTemplate<Strategy>& endPosition, |
245 EAnnotateForInterchange shouldAnnotate = DoNotAnnotateForInterchange, | 246 EAnnotateForInterchange shouldAnnotate = DoNotAnnotateForInterchange, |
246 ConvertBlocksToInlines = ConvertBlocksToInlines::NotConvert, | 247 ConvertBlocksToInlines = ConvertBlocksToInlines::NotConvert, |
247 EAbsoluteURLs shouldResolveURLs = DoNotResolveURLs, | 248 EAbsoluteURLs shouldResolveURLs = DoNotResolveURLs, |
248 Node* constrainingAncestor = nullptr); | 249 Node* constrainingAncestor = nullptr); |
249 }; | 250 }; |
250 | 251 |
251 // FIXME: Shouldn't we omit style info when annotate == DoNotAnnotateForIntercha
nge? | 252 // FIXME: Shouldn't we omit style info when annotate == |
252 // FIXME: At least, annotation and style info should probably not be included in
range.markupString() | 253 // DoNotAnnotateForInterchange? |
| 254 // FIXME: At least, annotation and style info should probably not be included in |
| 255 // range.markupString() |
253 template <typename Strategy> | 256 template <typename Strategy> |
254 String CreateMarkupAlgorithm<Strategy>::createMarkup( | 257 String CreateMarkupAlgorithm<Strategy>::createMarkup( |
255 const PositionTemplate<Strategy>& startPosition, | 258 const PositionTemplate<Strategy>& startPosition, |
256 const PositionTemplate<Strategy>& endPosition, | 259 const PositionTemplate<Strategy>& endPosition, |
257 EAnnotateForInterchange shouldAnnotate, | 260 EAnnotateForInterchange shouldAnnotate, |
258 ConvertBlocksToInlines convertBlocksToInlines, | 261 ConvertBlocksToInlines convertBlocksToInlines, |
259 EAbsoluteURLs shouldResolveURLs, | 262 EAbsoluteURLs shouldResolveURLs, |
260 Node* constrainingAncestor) { | 263 Node* constrainingAncestor) { |
261 if (startPosition.isNull() || endPosition.isNull()) | 264 if (startPosition.isNull() || endPosition.isNull()) |
262 return emptyString(); | 265 return emptyString(); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 return CreateMarkupAlgorithm<EditingInFlatTreeStrategy>::createMarkup( | 306 return CreateMarkupAlgorithm<EditingInFlatTreeStrategy>::createMarkup( |
304 startPosition, endPosition, shouldAnnotate, convertBlocksToInlines, | 307 startPosition, endPosition, shouldAnnotate, convertBlocksToInlines, |
305 shouldResolveURLs, constrainingAncestor); | 308 shouldResolveURLs, constrainingAncestor); |
306 } | 309 } |
307 | 310 |
308 DocumentFragment* createFragmentFromMarkup( | 311 DocumentFragment* createFragmentFromMarkup( |
309 Document& document, | 312 Document& document, |
310 const String& markup, | 313 const String& markup, |
311 const String& baseURL, | 314 const String& baseURL, |
312 ParserContentPolicy parserContentPolicy) { | 315 ParserContentPolicy parserContentPolicy) { |
313 // We use a fake body element here to trick the HTML parser to using the InBod
y insertion mode. | 316 // We use a fake body element here to trick the HTML parser to using the |
| 317 // InBody insertion mode. |
314 HTMLBodyElement* fakeBody = HTMLBodyElement::create(document); | 318 HTMLBodyElement* fakeBody = HTMLBodyElement::create(document); |
315 DocumentFragment* fragment = DocumentFragment::create(document); | 319 DocumentFragment* fragment = DocumentFragment::create(document); |
316 | 320 |
317 fragment->parseHTML(markup, fakeBody, parserContentPolicy); | 321 fragment->parseHTML(markup, fakeBody, parserContentPolicy); |
318 | 322 |
319 if (!baseURL.isEmpty() && baseURL != blankURL() && | 323 if (!baseURL.isEmpty() && baseURL != blankURL() && |
320 baseURL != document.baseURL()) | 324 baseURL != document.baseURL()) |
321 completeURLs(*fragment, baseURL); | 325 completeURLs(*fragment, baseURL); |
322 | 326 |
323 return fragment; | 327 return fragment; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 } | 372 } |
369 } | 373 } |
370 | 374 |
371 DocumentFragment* createFragmentFromMarkupWithContext( | 375 DocumentFragment* createFragmentFromMarkupWithContext( |
372 Document& document, | 376 Document& document, |
373 const String& markup, | 377 const String& markup, |
374 unsigned fragmentStart, | 378 unsigned fragmentStart, |
375 unsigned fragmentEnd, | 379 unsigned fragmentEnd, |
376 const String& baseURL, | 380 const String& baseURL, |
377 ParserContentPolicy parserContentPolicy) { | 381 ParserContentPolicy parserContentPolicy) { |
378 // FIXME: Need to handle the case where the markup already contains these mark
ers. | 382 // FIXME: Need to handle the case where the markup already contains these |
| 383 // markers. |
379 | 384 |
380 StringBuilder taggedMarkup; | 385 StringBuilder taggedMarkup; |
381 taggedMarkup.append(markup.left(fragmentStart)); | 386 taggedMarkup.append(markup.left(fragmentStart)); |
382 MarkupFormatter::appendComment(taggedMarkup, fragmentMarkerTag); | 387 MarkupFormatter::appendComment(taggedMarkup, fragmentMarkerTag); |
383 taggedMarkup.append( | 388 taggedMarkup.append( |
384 markup.substring(fragmentStart, fragmentEnd - fragmentStart)); | 389 markup.substring(fragmentStart, fragmentEnd - fragmentStart)); |
385 MarkupFormatter::appendComment(taggedMarkup, fragmentMarkerTag); | 390 MarkupFormatter::appendComment(taggedMarkup, fragmentMarkerTag); |
386 taggedMarkup.append(markup.substring(fragmentEnd)); | 391 taggedMarkup.append(markup.substring(fragmentEnd)); |
387 | 392 |
388 DocumentFragment* taggedFragment = createFragmentFromMarkup( | 393 DocumentFragment* taggedFragment = createFragmentFromMarkup( |
(...skipping 14 matching lines...) Expand all Loading... |
403 | 408 |
404 Range* range = Range::create( | 409 Range* range = Range::create( |
405 *taggedDocument, | 410 *taggedDocument, |
406 Position::afterNode(nodeBeforeContext).parentAnchoredEquivalent(), | 411 Position::afterNode(nodeBeforeContext).parentAnchoredEquivalent(), |
407 Position::beforeNode(nodeAfterContext).parentAnchoredEquivalent()); | 412 Position::beforeNode(nodeAfterContext).parentAnchoredEquivalent()); |
408 | 413 |
409 Node* commonAncestor = range->commonAncestorContainer(); | 414 Node* commonAncestor = range->commonAncestorContainer(); |
410 HTMLElement* specialCommonAncestor = | 415 HTMLElement* specialCommonAncestor = |
411 ancestorToRetainStructureAndAppearanceWithNoLayoutObject(commonAncestor); | 416 ancestorToRetainStructureAndAppearanceWithNoLayoutObject(commonAncestor); |
412 | 417 |
413 // When there's a special common ancestor outside of the fragment, we must inc
lude it as well to | 418 // When there's a special common ancestor outside of the fragment, we must |
414 // preserve the structure and appearance of the fragment. For example, if the
fragment contains | 419 // include it as well to preserve the structure and appearance of the |
415 // TD, we need to include the enclosing TABLE tag as well. | 420 // fragment. For example, if the fragment contains TD, we need to include the |
| 421 // enclosing TABLE tag as well. |
416 DocumentFragment* fragment = DocumentFragment::create(document); | 422 DocumentFragment* fragment = DocumentFragment::create(document); |
417 if (specialCommonAncestor) | 423 if (specialCommonAncestor) |
418 fragment->appendChild(specialCommonAncestor); | 424 fragment->appendChild(specialCommonAncestor); |
419 else | 425 else |
420 fragment->parserTakeAllChildrenFrom(toContainerNode(*commonAncestor)); | 426 fragment->parserTakeAllChildrenFrom(toContainerNode(*commonAncestor)); |
421 | 427 |
422 trimFragment(fragment, nodeBeforeContext, nodeAfterContext); | 428 trimFragment(fragment, nodeBeforeContext, nodeAfterContext); |
423 | 429 |
424 return fragment; | 430 return fragment; |
425 } | 431 } |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 shouldPreserveNewline(context)) { | 535 shouldPreserveNewline(context)) { |
530 fragment->appendChild(document.createTextNode(string)); | 536 fragment->appendChild(document.createTextNode(string)); |
531 if (string.endsWith('\n')) { | 537 if (string.endsWith('\n')) { |
532 HTMLBRElement* element = HTMLBRElement::create(document); | 538 HTMLBRElement* element = HTMLBRElement::create(document); |
533 element->setAttribute(classAttr, AppleInterchangeNewline); | 539 element->setAttribute(classAttr, AppleInterchangeNewline); |
534 fragment->appendChild(element); | 540 fragment->appendChild(element); |
535 } | 541 } |
536 return fragment; | 542 return fragment; |
537 } | 543 } |
538 | 544 |
539 // A string with no newlines gets added inline, rather than being put into a p
aragraph. | 545 // A string with no newlines gets added inline, rather than being put into a |
| 546 // paragraph. |
540 if (string.find('\n') == kNotFound) { | 547 if (string.find('\n') == kNotFound) { |
541 fillContainerFromString(fragment, string); | 548 fillContainerFromString(fragment, string); |
542 return fragment; | 549 return fragment; |
543 } | 550 } |
544 | 551 |
545 // Break string into paragraphs. Extra line breaks turn into empty paragraphs. | 552 // Break string into paragraphs. Extra line breaks turn into empty paragraphs. |
546 Element* block = | 553 Element* block = |
547 enclosingBlock(context.startPosition().nodeAsRangeFirstNode()); | 554 enclosingBlock(context.startPosition().nodeAsRangeFirstNode()); |
548 bool useClonesOfEnclosingBlock = | 555 bool useClonesOfEnclosingBlock = |
549 block && !isHTMLBodyElement(*block) && !isHTMLHtmlElement(*block) && | 556 block && !isHTMLBodyElement(*block) && !isHTMLHtmlElement(*block) && |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
601 return fragment; | 608 return fragment; |
602 } | 609 } |
603 | 610 |
604 DocumentFragment* createFragmentForTransformToFragment( | 611 DocumentFragment* createFragmentForTransformToFragment( |
605 const String& sourceString, | 612 const String& sourceString, |
606 const String& sourceMIMEType, | 613 const String& sourceMIMEType, |
607 Document& outputDoc) { | 614 Document& outputDoc) { |
608 DocumentFragment* fragment = outputDoc.createDocumentFragment(); | 615 DocumentFragment* fragment = outputDoc.createDocumentFragment(); |
609 | 616 |
610 if (sourceMIMEType == "text/html") { | 617 if (sourceMIMEType == "text/html") { |
611 // As far as I can tell, there isn't a spec for how transformToFragment is s
upposed to work. | 618 // As far as I can tell, there isn't a spec for how transformToFragment is |
612 // Based on the documentation I can find, it looks like we want to start par
sing the fragment in the InBody insertion mode. | 619 // supposed to work. Based on the documentation I can find, it looks like we |
613 // Unfortunately, that's an implementation detail of the parser. | 620 // want to start parsing the fragment in the InBody insertion mode. |
614 // We achieve that effect here by passing in a fake body element as context
for the fragment. | 621 // Unfortunately, that's an implementation detail of the parser. We achieve |
| 622 // that effect here by passing in a fake body element as context for the |
| 623 // fragment. |
615 HTMLBodyElement* fakeBody = HTMLBodyElement::create(outputDoc); | 624 HTMLBodyElement* fakeBody = HTMLBodyElement::create(outputDoc); |
616 fragment->parseHTML(sourceString, fakeBody); | 625 fragment->parseHTML(sourceString, fakeBody); |
617 } else if (sourceMIMEType == "text/plain") { | 626 } else if (sourceMIMEType == "text/plain") { |
618 fragment->parserAppendChild(Text::create(outputDoc, sourceString)); | 627 fragment->parserAppendChild(Text::create(outputDoc, sourceString)); |
619 } else { | 628 } else { |
620 bool successfulParse = fragment->parseXML(sourceString, 0); | 629 bool successfulParse = fragment->parseXML(sourceString, 0); |
621 if (!successfulParse) | 630 if (!successfulParse) |
622 return nullptr; | 631 return nullptr; |
623 } | 632 } |
624 | 633 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
702 return; | 711 return; |
703 } | 712 } |
704 | 713 |
705 // FIXME: This is wrong if containerNode->firstChild() has more than one ref! | 714 // FIXME: This is wrong if containerNode->firstChild() has more than one ref! |
706 if (containerNode->hasOneTextChild() && fragment->hasOneTextChild()) { | 715 if (containerNode->hasOneTextChild() && fragment->hasOneTextChild()) { |
707 toText(containerNode->firstChild()) | 716 toText(containerNode->firstChild()) |
708 ->setData(toText(fragment->firstChild())->data()); | 717 ->setData(toText(fragment->firstChild())->data()); |
709 return; | 718 return; |
710 } | 719 } |
711 | 720 |
712 // FIXME: No need to replace the child it is a text node and its contents are
already == text. | 721 // FIXME: No need to replace the child it is a text node and its contents are |
| 722 // already == text. |
713 if (containerNode->hasOneChild()) { | 723 if (containerNode->hasOneChild()) { |
714 containerNode->replaceChild(fragment, containerNode->firstChild(), | 724 containerNode->replaceChild(fragment, containerNode->firstChild(), |
715 exceptionState); | 725 exceptionState); |
716 return; | 726 return; |
717 } | 727 } |
718 | 728 |
719 containerNode->removeChildren(); | 729 containerNode->removeChildren(); |
720 containerNode->appendChild(fragment, exceptionState); | 730 containerNode->appendChild(fragment, exceptionState); |
721 } | 731 } |
722 | 732 |
723 void replaceChildrenWithText(ContainerNode* container, | 733 void replaceChildrenWithText(ContainerNode* container, |
724 const String& text, | 734 const String& text, |
725 ExceptionState& exceptionState) { | 735 ExceptionState& exceptionState) { |
726 DCHECK(container); | 736 DCHECK(container); |
727 ContainerNode* containerNode(container); | 737 ContainerNode* containerNode(container); |
728 | 738 |
729 ChildListMutationScope mutation(*containerNode); | 739 ChildListMutationScope mutation(*containerNode); |
730 | 740 |
731 // FIXME: This is wrong if containerNode->firstChild() has more than one ref!
Example: | 741 // FIXME: This is wrong if containerNode->firstChild() has more than one ref! |
| 742 // Example: |
732 // <div>foo</div> | 743 // <div>foo</div> |
733 // <script> | 744 // <script> |
734 // var oldText = div.firstChild; | 745 // var oldText = div.firstChild; |
735 // console.log(oldText.data); // foo | 746 // console.log(oldText.data); // foo |
736 // div.innerText = "bar"; | 747 // div.innerText = "bar"; |
737 // console.log(oldText.data); // bar!?! | 748 // console.log(oldText.data); // bar!?! |
738 // </script> | 749 // </script> |
739 // I believe this is an intentional benchmark cheat from years ago. | 750 // I believe this is an intentional benchmark cheat from years ago. |
740 // We should re-visit if we actually want this still. | 751 // We should re-visit if we actually want this still. |
741 if (containerNode->hasOneTextChild()) { | 752 if (containerNode->hasOneTextChild()) { |
742 toText(containerNode->firstChild())->setData(text); | 753 toText(containerNode->firstChild())->setData(text); |
743 return; | 754 return; |
744 } | 755 } |
745 | 756 |
746 // NOTE: This method currently always creates a text node, even if that text n
ode will be empty. | 757 // NOTE: This method currently always creates a text node, even if that text |
| 758 // node will be empty. |
747 Text* textNode = Text::create(containerNode->document(), text); | 759 Text* textNode = Text::create(containerNode->document(), text); |
748 | 760 |
749 // FIXME: No need to replace the child it is a text node and its contents are
already == text. | 761 // FIXME: No need to replace the child it is a text node and its contents are |
| 762 // already == text. |
750 if (containerNode->hasOneChild()) { | 763 if (containerNode->hasOneChild()) { |
751 containerNode->replaceChild(textNode, containerNode->firstChild(), | 764 containerNode->replaceChild(textNode, containerNode->firstChild(), |
752 exceptionState); | 765 exceptionState); |
753 return; | 766 return; |
754 } | 767 } |
755 | 768 |
756 containerNode->removeChildren(); | 769 containerNode->removeChildren(); |
757 containerNode->appendChild(textNode, exceptionState); | 770 containerNode->appendChild(textNode, exceptionState); |
758 } | 771 } |
759 | 772 |
760 void mergeWithNextTextNode(Text* textNode, ExceptionState& exceptionState) { | 773 void mergeWithNextTextNode(Text* textNode, ExceptionState& exceptionState) { |
761 DCHECK(textNode); | 774 DCHECK(textNode); |
762 Node* next = textNode->nextSibling(); | 775 Node* next = textNode->nextSibling(); |
763 if (!next || !next->isTextNode()) | 776 if (!next || !next->isTextNode()) |
764 return; | 777 return; |
765 | 778 |
766 Text* textNext = toText(next); | 779 Text* textNext = toText(next); |
767 textNode->appendData(textNext->data()); | 780 textNode->appendData(textNext->data()); |
768 if (textNext->parentNode()) // Might have been removed by mutation event. | 781 if (textNext->parentNode()) // Might have been removed by mutation event. |
769 textNext->remove(exceptionState); | 782 textNext->remove(exceptionState); |
770 } | 783 } |
771 | 784 |
772 template class CORE_TEMPLATE_EXPORT CreateMarkupAlgorithm<EditingStrategy>; | 785 template class CORE_TEMPLATE_EXPORT CreateMarkupAlgorithm<EditingStrategy>; |
773 template class CORE_TEMPLATE_EXPORT | 786 template class CORE_TEMPLATE_EXPORT |
774 CreateMarkupAlgorithm<EditingInFlatTreeStrategy>; | 787 CreateMarkupAlgorithm<EditingInFlatTreeStrategy>; |
775 | 788 |
776 } // namespace blink | 789 } // namespace blink |
OLD | NEW |