Changeset 65854 in webkit
- Timestamp:
- Aug 23, 2010 7:14:02 PM (14 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r65853 r65854 1 2010-08-23 Ryosuke Niwa <rniwa@webkit.org> 2 3 Reviewed by Eric Seidel. 4 5 MarkupAccumulator::appendStartMarkup should be broken down into pieces 6 https://bugs.webkit.org/show_bug.cgi?id=44288 7 8 Extracted appendText, appendComment, appendProcessingInstruction, appendElement and appendCDATASection. 9 Also simplified the conditionals in appendText. 10 11 No new tests are added since this is a cleanup. 12 13 * editing/markup.cpp: 14 (WebCore::MarkupAccumulator::appendText): 15 (WebCore::MarkupAccumulator::appendComment): 16 (WebCore::MarkupAccumulator::appendProcessingInstruction): 17 (WebCore::MarkupAccumulator::appendElement): 18 (WebCore::MarkupAccumulator::appendCDATASection): 19 (WebCore::MarkupAccumulator::appendStartMarkup): 20 1 21 2010-08-23 Simon Fraser <simon.fraser@apple.com> 2 22 -
trunk/WebCore/editing/markup.cpp
r65845 r65854 124 124 bool shouldAddNamespaceAttribute(const Attribute*, Namespaces&); 125 125 void appendNamespace(Vector<UChar>& result, const AtomicString& prefix, const AtomicString& namespaceURI, Namespaces&); 126 void appendText(Vector<UChar>& out, Text*); 127 void appendComment(Vector<UChar>& out, const String& comment); 126 128 void appendDocumentType(Vector<UChar>& result, const DocumentType*); 129 void appendProcessingInstruction(Vector<UChar>& out, const String& target, const String& data); 127 130 void removeExteriorStyles(CSSMutableStyleDeclaration*); 131 void appendElement(Vector<UChar>& out, Element* element, bool addDisplayInline, Namespaces*, RangeFullySelectsNode); 132 void appendCDATASection(Vector<UChar>& out, const String& section); 128 133 void appendStartMarkup(Vector<UChar>& result, const Node*, bool convertBlocksToInlines, Namespaces*, RangeFullySelectsNode); 129 134 bool shouldSelfClose(const Node*); … … 481 486 } 482 487 488 void MarkupAccumulator::appendText(Vector<UChar>& out, Text* text) 489 { 490 const QualifiedName* parentName = 0; 491 if (text->parentElement()) 492 parentName = &static_cast<Element*>(text->parentElement())->tagQName(); 493 494 if (parentName && (*parentName == scriptTag || *parentName == styleTag || *parentName == xmpTag)) { 495 appendUCharRange(out, ucharRange(text, m_range)); 496 return; 497 } 498 499 if (!shouldAnnotate() || (parentName && *parentName == textareaTag)) { 500 appendEscapedContent(out, ucharRange(text, m_range), text->document()->isHTMLDocument()); 501 return; 502 } 503 504 bool useRenderedText = !enclosingNodeWithTag(Position(text, 0), selectTag); 505 String markup = escapeContentText(useRenderedText ? renderedText(text, m_range) : stringValueForRange(text, m_range), false); 506 markup = convertHTMLTextToInterchangeFormat(markup, text); 507 append(out, markup); 508 } 509 510 void MarkupAccumulator::appendComment(Vector<UChar>& out, const String& comment) 511 { 512 // FIXME: Comment content is not escaped, but XMLSerializer (and possibly other callers) should raise an exception if it includes "-->". 513 append(out, "<!--"); 514 append(out, comment); 515 append(out, "-->"); 516 } 517 483 518 void MarkupAccumulator::appendDocumentType(Vector<UChar>& result, const DocumentType* n) 484 519 { … … 510 545 } 511 546 547 void MarkupAccumulator::appendProcessingInstruction(Vector<UChar>& out, const String& target, const String& data) 548 { 549 // FIXME: PI data is not escaped, but XMLSerializer (and possibly other callers) this should raise an exception if it includes "?>". 550 append(out, "<?"); 551 append(out, target); 552 append(out, " "); 553 append(out, data); 554 append(out, "?>"); 555 } 556 512 557 void MarkupAccumulator::removeExteriorStyles(CSSMutableStyleDeclaration* style) 513 558 { 514 559 style->removeProperty(CSSPropertyFloat); 560 } 561 562 void MarkupAccumulator::appendElement(Vector<UChar>& out, Element* element, bool addDisplayInline, Namespaces* namespaces, RangeFullySelectsNode rangeFullySelectsNode) 563 { 564 bool documentIsHTML = element->document()->isHTMLDocument(); 565 out.append('<'); 566 append(out, element->nodeNamePreservingCase()); 567 if (!documentIsHTML && namespaces && shouldAddNamespaceElement(element)) 568 appendNamespace(out, element->prefix(), element->namespaceURI(), *namespaces); 569 570 NamedNodeMap* attributes = element->attributes(); 571 unsigned length = attributes->length(); 572 for (unsigned int i = 0; i < length; i++) { 573 Attribute* attribute = attributes->attributeItem(i); 574 // We'll handle the style attribute separately, below. 575 if (attribute->name() == styleAttr && element->isHTMLElement() && (shouldAnnotate() || addDisplayInline)) 576 continue; 577 out.append(' '); 578 579 if (documentIsHTML) 580 append(out, attribute->name().localName()); 581 else 582 append(out, attribute->name().toString()); 583 584 out.append('='); 585 586 if (element->isURLAttribute(attribute)) { 587 // We don't want to complete file:/// URLs because it may contain sensitive information 588 // about the user's system. 589 if (shouldResolveURLs() && !element->document()->url().isLocalFile()) 590 appendQuotedURLAttributeValue(out, element->document()->completeURL(attribute->value()).string()); 591 else 592 appendQuotedURLAttributeValue(out, attribute->value().string()); 593 } else { 594 out.append('\"'); 595 appendAttributeValue(out, attribute->value(), documentIsHTML); 596 out.append('\"'); 597 } 598 599 if (!documentIsHTML && namespaces && shouldAddNamespaceAttribute(attribute, *namespaces)) 600 appendNamespace(out, attribute->prefix(), attribute->namespaceURI(), *namespaces); 601 } 602 603 if (element->isHTMLElement() && (shouldAnnotate() || addDisplayInline)) { 604 RefPtr<CSSMutableStyleDeclaration> style = static_cast<HTMLElement*>(element)->getInlineStyleDecl()->copy(); 605 if (shouldAnnotate()) { 606 RefPtr<CSSMutableStyleDeclaration> styleFromMatchedRules = styleFromMatchedRulesForElement(const_cast<Element*>(element)); 607 // Styles from the inline style declaration, held in the variable "style", take precedence 608 // over those from matched rules. 609 styleFromMatchedRules->merge(style.get()); 610 style = styleFromMatchedRules; 611 612 RefPtr<CSSComputedStyleDeclaration> computedStyleForElement = computedStyle(element); 613 RefPtr<CSSMutableStyleDeclaration> fromComputedStyle = CSSMutableStyleDeclaration::create(); 614 615 { 616 CSSMutableStyleDeclaration::const_iterator end = style->end(); 617 for (CSSMutableStyleDeclaration::const_iterator it = style->begin(); it != end; ++it) { 618 const CSSProperty& property = *it; 619 CSSValue* value = property.value(); 620 // The property value, if it's a percentage, may not reflect the actual computed value. 621 // For example: style="height: 1%; overflow: visible;" in quirksmode 622 // FIXME: There are others like this, see <rdar://problem/5195123> Slashdot copy/paste fidelity problem 623 if (value->cssValueType() == CSSValue::CSS_PRIMITIVE_VALUE) 624 if (static_cast<CSSPrimitiveValue*>(value)->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) 625 if (RefPtr<CSSValue> computedPropertyValue = computedStyleForElement->getPropertyCSSValue(property.id())) 626 fromComputedStyle->addParsedProperty(CSSProperty(property.id(), computedPropertyValue)); 627 } 628 } 629 style->merge(fromComputedStyle.get()); 630 } 631 if (addDisplayInline) 632 style->setProperty(CSSPropertyDisplay, CSSValueInline, true); 633 // 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 634 // only the ones that affect it and the nodes within it. 635 if (rangeFullySelectsNode == DoesNotFullySelectNode) 636 removeExteriorStyles(style.get()); 637 if (style->length() > 0) { 638 DEFINE_STATIC_LOCAL(const String, stylePrefix, (" style=\"")); 639 append(out, stylePrefix); 640 appendAttributeValue(out, style->cssText(), documentIsHTML); 641 out.append('\"'); 642 } 643 } 644 645 if (shouldSelfClose(element)) { 646 if (element->isHTMLElement()) 647 out.append(' '); // XHTML 1.0 <-> HTML compatibility. 648 out.append('/'); 649 } 650 out.append('>'); 651 } 652 653 void MarkupAccumulator::appendCDATASection(Vector<UChar>& out, const String& section) 654 { 655 // FIXME: CDATA content is not escaped, but XMLSerializer (and possibly other callers) should raise an exception if it includes "]]>". 656 append(out, "<![CDATA["); 657 append(out, section); 658 append(out, "]]>"); 515 659 } 516 660 … … 520 664 namespaces->checkConsistency(); 521 665 522 bool documentIsHTML = node->document()->isHTMLDocument();523 666 switch (node->nodeType()) { 524 case Node::TEXT_NODE: { 525 if (Node* parent = node->parentNode()) { 526 if (parent->hasTagName(scriptTag) 527 || parent->hasTagName(styleTag) 528 || parent->hasTagName(xmpTag)) { 529 appendUCharRange(result, ucharRange(node, m_range)); 530 break; 531 } 532 if (parent->hasTagName(textareaTag)) { 533 appendEscapedContent(result, ucharRange(node, m_range), documentIsHTML); 534 break; 535 } 536 } 537 if (shouldAnnotate()) { 538 bool useRenderedText = !enclosingNodeWithTag(Position(const_cast<Node*>(node), 0), selectTag); 539 String markup = escapeContentText(useRenderedText ? renderedText(node, m_range) : stringValueForRange(node, m_range), false); 540 markup = convertHTMLTextToInterchangeFormat(markup, static_cast<const Text*>(node)); 541 append(result, markup); 542 break; 543 } 544 appendEscapedContent(result, ucharRange(node, m_range), documentIsHTML); 667 case Node::TEXT_NODE: 668 appendText(result, static_cast<Text*>(const_cast<Node*>(node))); 545 669 break; 546 }547 670 case Node::COMMENT_NODE: 548 // FIXME: Comment content is not escaped, but XMLSerializer (and possibly other callers) should raise an exception if it includes "-->". 549 append(result, "<!--"); 550 append(result, static_cast<const Comment*>(node)->data()); 551 append(result, "-->"); 671 appendComment(result, static_cast<const Comment*>(node)->data()); 552 672 break; 553 673 case Node::DOCUMENT_NODE: … … 557 677 appendDocumentType(result, static_cast<const DocumentType*>(node)); 558 678 break; 559 case Node::PROCESSING_INSTRUCTION_NODE: { 560 // FIXME: PI data is not escaped, but XMLSerializer (and possibly other callers) this should raise an exception if it includes "?>". 561 const ProcessingInstruction* n = static_cast<const ProcessingInstruction*>(node); 562 append(result, "<?"); 563 append(result, n->target()); 564 append(result, " "); 565 append(result, n->data()); 566 append(result, "?>"); 679 case Node::PROCESSING_INSTRUCTION_NODE: 680 appendProcessingInstruction(result, static_cast<const ProcessingInstruction*>(node)->target(), static_cast<const ProcessingInstruction*>(node)->data()); 567 681 break; 568 } 569 case Node::ELEMENT_NODE: { 570 result.append('<'); 571 Element* element = const_cast<Element*>(static_cast<const Element*>(node)); 572 bool convert = convertBlocksToInlines && isBlock(const_cast<Node*>(node)); 573 append(result, element->nodeNamePreservingCase()); 574 if (!documentIsHTML && namespaces && shouldAddNamespaceElement(element)) 575 appendNamespace(result, element->prefix(), element->namespaceURI(), *namespaces); 576 577 NamedNodeMap* attributes = element->attributes(); 578 unsigned length = attributes->length(); 579 for (unsigned int i = 0; i < length; i++) { 580 Attribute* attribute = attributes->attributeItem(i); 581 // We'll handle the style attribute separately, below. 582 if (attribute->name() == styleAttr && element->isHTMLElement() && (shouldAnnotate() || convert)) 583 continue; 584 result.append(' '); 585 586 if (documentIsHTML) 587 append(result, attribute->name().localName()); 588 else 589 append(result, attribute->name().toString()); 590 591 result.append('='); 592 593 if (element->isURLAttribute(attribute)) { 594 // We don't want to complete file:/// URLs because it may contain sensitive information 595 // about the user's system. 596 if (shouldResolveURLs() && !node->document()->url().isLocalFile()) 597 appendQuotedURLAttributeValue(result, node->document()->completeURL(attribute->value()).string()); 598 else 599 appendQuotedURLAttributeValue(result, attribute->value().string()); 600 } else { 601 result.append('\"'); 602 appendAttributeValue(result, attribute->value(), documentIsHTML); 603 result.append('\"'); 604 } 605 606 if (!documentIsHTML && namespaces && shouldAddNamespaceAttribute(attribute, *namespaces)) 607 appendNamespace(result, attribute->prefix(), attribute->namespaceURI(), *namespaces); 608 } 609 610 if (element->isHTMLElement() && (shouldAnnotate() || convert)) { 611 RefPtr<CSSMutableStyleDeclaration> style = static_cast<HTMLElement*>(element)->getInlineStyleDecl()->copy(); 612 if (shouldAnnotate()) { 613 RefPtr<CSSMutableStyleDeclaration> styleFromMatchedRules = styleFromMatchedRulesForElement(const_cast<Element*>(element)); 614 // Styles from the inline style declaration, held in the variable "style", take precedence 615 // over those from matched rules. 616 styleFromMatchedRules->merge(style.get()); 617 style = styleFromMatchedRules; 618 619 RefPtr<CSSComputedStyleDeclaration> computedStyleForElement = computedStyle(element); 620 RefPtr<CSSMutableStyleDeclaration> fromComputedStyle = CSSMutableStyleDeclaration::create(); 621 622 { 623 CSSMutableStyleDeclaration::const_iterator end = style->end(); 624 for (CSSMutableStyleDeclaration::const_iterator it = style->begin(); it != end; ++it) { 625 const CSSProperty& property = *it; 626 CSSValue* value = property.value(); 627 // The property value, if it's a percentage, may not reflect the actual computed value. 628 // For example: style="height: 1%; overflow: visible;" in quirksmode 629 // FIXME: There are others like this, see <rdar://problem/5195123> Slashdot copy/paste fidelity problem 630 if (value->cssValueType() == CSSValue::CSS_PRIMITIVE_VALUE) 631 if (static_cast<CSSPrimitiveValue*>(value)->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) 632 if (RefPtr<CSSValue> computedPropertyValue = computedStyleForElement->getPropertyCSSValue(property.id())) 633 fromComputedStyle->addParsedProperty(CSSProperty(property.id(), computedPropertyValue)); 634 } 635 } 636 style->merge(fromComputedStyle.get()); 637 } 638 if (convert) 639 style->setProperty(CSSPropertyDisplay, CSSValueInline, true); 640 // 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 641 // only the ones that affect it and the nodes within it. 642 if (rangeFullySelectsNode == DoesNotFullySelectNode) 643 removeExteriorStyles(style.get()); 644 if (style->length() > 0) { 645 DEFINE_STATIC_LOCAL(const String, stylePrefix, (" style=\"")); 646 append(result, stylePrefix); 647 appendAttributeValue(result, style->cssText(), documentIsHTML); 648 result.append('\"'); 649 } 650 } 651 652 if (shouldSelfClose(element)) { 653 if (element->isHTMLElement()) 654 result.append(' '); // XHTML 1.0 <-> HTML compatibility. 655 result.append('/'); 656 } 657 result.append('>'); 682 case Node::ELEMENT_NODE: 683 appendElement(result, static_cast<Element*>(const_cast<Node*>(node)), convertBlocksToInlines && isBlock(const_cast<Node*>(node)), namespaces, rangeFullySelectsNode); 658 684 break; 659 } 660 case Node::CDATA_SECTION_NODE: { 661 // FIXME: CDATA content is not escaped, but XMLSerializer (and possibly other callers) should raise an exception if it includes "]]>". 662 const CDATASection* n = static_cast<const CDATASection*>(node); 663 append(result, "<![CDATA["); 664 append(result, n->data()); 665 append(result, "]]>"); 685 case Node::CDATA_SECTION_NODE: 686 appendCDATASection(result, static_cast<const CDATASection*>(node)->data()); 666 687 break; 667 }668 688 case Node::ATTRIBUTE_NODE: 669 689 case Node::ENTITY_NODE:
Note: See TracChangeset
for help on using the changeset viewer.