Title: [92620] trunk
Revision
92620
Author
[email protected]
Date
2011-08-08 12:15:16 -0700 (Mon, 08 Aug 2011)

Log Message

Remove redundant inline styles from the pasted contents more aggressively
https://bugs.webkit.org/show_bug.cgi?id=65833

Reviewed by Tony Chang.

Source/WebCore: 

Make removeRedundantStylesAndKeepStyleSpanInline more aggressively remove redundant styles by realizing that
when an editing inheritable property in an inline style declaration of an element can be safely removed
if it is present either in style rules or in its ancestor and not overridden by style rules or default style
of the element.

Test: editing/pasteboard/paste-with-redundant-style.html

* css/CSSStyleSelector.cpp:
(WebCore::CSSStyleSelector::pseudoStyleRulesForElement): Do not match author style sheets if AuthorCSSRules
is not included in the rules to include. This is used in EditingStyle::removePropertiesInElementDefaultStyle.
* editing/ApplyStyleCommand.cpp:
(WebCore::isStyleSpanOrSpanWithOnlyStyleAttribute): Added; returns true if the element is a style span or
span possibly with a style attribute.
* editing/ApplyStyleCommand.h:
* editing/EditingStyle.cpp:
(WebCore::styleFromMatchedRulesForElement): Takes rulesToInclude.
(WebCore::EditingStyle::mergeStyleFromRules): Calls styleFromMatchedRulesForElement with AuthorCSSRules
| CrossOriginCSSRules to keep the original behavior.
(WebCore::EditingStyle::removeStyleFromRulesAndContext): Renamed from removeStyleFromRules; removes styles that
are present in context and not overridden by matched rules.
(WebCore::EditingStyle::removePropertiesInElementDefaultStyle): Added.
* editing/EditingStyle.h:
* editing/ReplaceSelectionCommand.cpp:
(WebCore::ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline): See the description above.

LayoutTests: 

Added a test to paste contents with many redundant styles. WebKit should remove as much style spans as possible
(all of this in this case).

* editing/pasteboard/4930986-2-expected.txt: style attribute now has a trailing space.
* editing/pasteboard/interchange-newline-1-expected.txt: No longer has a wrapping span without any attributes.
* editing/pasteboard/nested-blocks-with-text-area-expected.txt: Ditto.
* editing/pasteboard/nested-blocks-with-text-field-expected.txt: Ditto.
* editing/pasteboard/paste-blockquote-into-blockquote-2-expected.txt: Ditto.
* editing/pasteboard/paste-blockquote-into-blockquote-expected.txt: Ditto.
* editing/pasteboard/prevent-block-nesting-01-expected.txt: Ditto.
* editing/pasteboard/paste-with-redundant-style-expected.txt: Added.
* editing/pasteboard/paste-with-redundant-style.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (92619 => 92620)


--- trunk/LayoutTests/ChangeLog	2011-08-08 19:11:33 UTC (rev 92619)
+++ trunk/LayoutTests/ChangeLog	2011-08-08 19:15:16 UTC (rev 92620)
@@ -1,3 +1,23 @@
+2011-08-08  Ryosuke Niwa  <[email protected]>
+
+        Remove redundant inline styles from the pasted contents more aggressively
+        https://bugs.webkit.org/show_bug.cgi?id=65833
+
+        Reviewed by Tony Chang.
+
+        Added a test to paste contents with many redundant styles. WebKit should remove as much style spans as possible
+        (all of this in this case).
+
+        * editing/pasteboard/4930986-2-expected.txt: style attribute now has a trailing space.
+        * editing/pasteboard/interchange-newline-1-expected.txt: No longer has a wrapping span without any attributes.
+        * editing/pasteboard/nested-blocks-with-text-area-expected.txt: Ditto.
+        * editing/pasteboard/nested-blocks-with-text-field-expected.txt: Ditto.
+        * editing/pasteboard/paste-blockquote-into-blockquote-2-expected.txt: Ditto.
+        * editing/pasteboard/paste-blockquote-into-blockquote-expected.txt: Ditto.
+        * editing/pasteboard/prevent-block-nesting-01-expected.txt: Ditto.
+        * editing/pasteboard/paste-with-redundant-style-expected.txt: Added.
+        * editing/pasteboard/paste-with-redundant-style.html: Added.
+
 2011-08-08  Oliver Hunt  <[email protected]>
 
         Non-extensibility does not prevent mutating [[Prototype]]

Modified: trunk/LayoutTests/editing/pasteboard/4930986-2-expected.txt (92619 => 92620)


--- trunk/LayoutTests/editing/pasteboard/4930986-2-expected.txt	2011-08-08 19:11:33 UTC (rev 92619)
+++ trunk/LayoutTests/editing/pasteboard/4930986-2-expected.txt	2011-08-08 19:15:16 UTC (rev 92620)
@@ -1,2 +1,2 @@
 This tests to make sure that content that is colored by the user is pasted with that color during a Paste as Quotation.
-<blockquote><span class="Apple-style-span" style="color: red;">This text should be red (it should be wrapped in a style span).</span></blockquote>
+<blockquote><span class="Apple-style-span" style="color: red; ">This text should be red (it should be wrapped in a style span).</span></blockquote>

Modified: trunk/LayoutTests/editing/pasteboard/interchange-newline-1-expected.txt (92619 => 92620)


--- trunk/LayoutTests/editing/pasteboard/interchange-newline-1-expected.txt	2011-08-08 19:11:33 UTC (rev 92619)
+++ trunk/LayoutTests/editing/pasteboard/interchange-newline-1-expected.txt	2011-08-08 19:15:16 UTC (rev 92620)
@@ -10,8 +10,7 @@
 There is an interchange newline at the end of the incoming fragment. "bar" and "x" should be in separate paragraphs
 The paragraph "bar" is inside a div wrapped in a span, and the old paste code that handled interchange newlines did not handle this case.
 | "x"
-| <span>
-|   "foo"
-|   <div>
-|     "bar"
+| "foo"
+| <div>
+|   "bar"
 | "<#selection-caret>x"

Modified: trunk/LayoutTests/editing/pasteboard/nested-blocks-with-text-area-expected.txt (92619 => 92620)


--- trunk/LayoutTests/editing/pasteboard/nested-blocks-with-text-area-expected.txt	2011-08-08 19:11:33 UTC (rev 92619)
+++ trunk/LayoutTests/editing/pasteboard/nested-blocks-with-text-area-expected.txt	2011-08-08 19:15:16 UTC (rev 92620)
@@ -5,7 +5,7 @@
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 1 of #text > SPAN > DIV > DIV > BODY > HTML > #document to 1 of #text > SPAN > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 1 of #text > DIV > DIV > BODY > HTML > #document to 1 of #text > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
@@ -30,8 +30,7 @@
 |           " "
 |     " 
 "
-|     <span>
-|       "x<#selection-caret>"
+|     "x<#selection-caret>"
 |     "
 "
 | "

Modified: trunk/LayoutTests/editing/pasteboard/nested-blocks-with-text-field-expected.txt (92619 => 92620)


--- trunk/LayoutTests/editing/pasteboard/nested-blocks-with-text-field-expected.txt	2011-08-08 19:11:33 UTC (rev 92619)
+++ trunk/LayoutTests/editing/pasteboard/nested-blocks-with-text-field-expected.txt	2011-08-08 19:15:16 UTC (rev 92620)
@@ -5,7 +5,7 @@
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 1 of #text > SPAN > DIV > DIV > BODY > HTML > #document to 1 of #text > SPAN > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 1 of #text > DIV > DIV > BODY > HTML > #document to 1 of #text > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
@@ -29,8 +29,7 @@
 |         <div>
 |     " 
 "
-|     <span>
-|       "x<#selection-caret>"
+|     "x<#selection-caret>"
 |     "
 "
 | "

Modified: trunk/LayoutTests/editing/pasteboard/paste-blockquote-into-blockquote-2-expected.txt (92619 => 92620)


--- trunk/LayoutTests/editing/pasteboard/paste-blockquote-into-blockquote-2-expected.txt	2011-08-08 19:11:33 UTC (rev 92619)
+++ trunk/LayoutTests/editing/pasteboard/paste-blockquote-into-blockquote-2-expected.txt	2011-08-08 19:15:16 UTC (rev 92620)
@@ -4,10 +4,9 @@
 |   type="cite"
 |   "One"
 |   "Two"
-| <span>
+| <blockquote>
+|   type="cite"
 |   <blockquote>
 |     type="cite"
-|     <blockquote>
-|       type="cite"
-|       <div>
-|         "Three<#selection-caret>"
+|     <div>
+|       "Three<#selection-caret>"

Modified: trunk/LayoutTests/editing/pasteboard/paste-blockquote-into-blockquote-expected.txt (92619 => 92620)


--- trunk/LayoutTests/editing/pasteboard/paste-blockquote-into-blockquote-expected.txt	2011-08-08 19:11:33 UTC (rev 92619)
+++ trunk/LayoutTests/editing/pasteboard/paste-blockquote-into-blockquote-expected.txt	2011-08-08 19:15:16 UTC (rev 92620)
@@ -4,8 +4,7 @@
 |   type="cite"
 |   "One"
 |   "Two"
-| <span>
-|   <blockquote>
-|     type="cite"
-|     <div>
-|       "Three<#selection-caret>"
+| <blockquote>
+|   type="cite"
+|   <div>
+|     "Three<#selection-caret>"

Added: trunk/LayoutTests/editing/pasteboard/paste-with-redundant-style-expected.txt (0 => 92620)


--- trunk/LayoutTests/editing/pasteboard/paste-with-redundant-style-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/editing/pasteboard/paste-with-redundant-style-expected.txt	2011-08-08 19:15:16 UTC (rev 92620)
@@ -0,0 +1,12 @@
+This tests pasting content with redundant inline style.
+You should not see any style attributes except one on the b element and there should be no spans.
+| <b>
+|   style="font-style: italic;"
+|   <em>
+|     "hello world"
+|   <br>
+|   "WebKit"
+|   <br>
+|   <em>
+|     "rocks<#selection-caret>"
+|   <br>

Added: trunk/LayoutTests/editing/pasteboard/paste-with-redundant-style.html (0 => 92620)


--- trunk/LayoutTests/editing/pasteboard/paste-with-redundant-style.html	                        (rev 0)
+++ trunk/LayoutTests/editing/pasteboard/paste-with-redundant-style.html	2011-08-08 19:15:16 UTC (rev 92620)
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+em { text-decoration: underline; font-style: none; }
+</style>
+</head>
+<body>
+<div id="test" contenteditable><b style="font-style: italic;"><br></b></div>
+<script src=""
+<script>
+
+document.getElementById('test').focus();
+document.execCommand('insertHTML', false,
+    '<em style="font-style: none; text-decoration: underline; font-weight: bold;"><span style="color: black;">hello world</span></em><br>'
+    + '<span style="font-weight: bold;"><span class="Apple-style-span" style="font-weight: bold;">WebKit</span></span><br>'
+    + '<em><span style="font-style: italic;">rocks</span></em>');
+
+Markup.description('This tests pasting content with redundant inline style.\n'
+    + 'You should not see any style attributes except one on the b element and there should be no spans.');
+Markup.dump('test');
+
+</script>
+</body>
+</html>

Modified: trunk/LayoutTests/editing/pasteboard/prevent-block-nesting-01-expected.txt (92619 => 92620)


--- trunk/LayoutTests/editing/pasteboard/prevent-block-nesting-01-expected.txt	2011-08-08 19:11:33 UTC (rev 92619)
+++ trunk/LayoutTests/editing/pasteboard/prevent-block-nesting-01-expected.txt	2011-08-08 19:15:16 UTC (rev 92620)
@@ -9,8 +9,7 @@
 EDITING DELEGATE: webViewDidEndEditing:WebViewDidEndEditingNotification
 The code in paste that prevents block nesting had a bug where the order of pasted paragraphs could be reversed.
 | "There should be an empty line between these two paragraphs."
-| <span>
-|   <div>
-|     <br>
 | <div>
+|   <br>
+| <div>
 |   "This paragraph and the empty line should have be in their own divs with a red border.<#selection-caret>"

Modified: trunk/Source/WebCore/ChangeLog (92619 => 92620)


--- trunk/Source/WebCore/ChangeLog	2011-08-08 19:11:33 UTC (rev 92619)
+++ trunk/Source/WebCore/ChangeLog	2011-08-08 19:15:16 UTC (rev 92620)
@@ -1,3 +1,35 @@
+2011-08-08  Ryosuke Niwa  <[email protected]>
+
+        Remove redundant inline styles from the pasted contents more aggressively
+        https://bugs.webkit.org/show_bug.cgi?id=65833
+
+        Reviewed by Tony Chang.
+
+        Make removeRedundantStylesAndKeepStyleSpanInline more aggressively remove redundant styles by realizing that
+        when an editing inheritable property in an inline style declaration of an element can be safely removed
+        if it is present either in style rules or in its ancestor and not overridden by style rules or default style
+        of the element.
+
+        Test: editing/pasteboard/paste-with-redundant-style.html
+
+        * css/CSSStyleSelector.cpp:
+        (WebCore::CSSStyleSelector::pseudoStyleRulesForElement): Do not match author style sheets if AuthorCSSRules
+        is not included in the rules to include. This is used in EditingStyle::removePropertiesInElementDefaultStyle.
+        * editing/ApplyStyleCommand.cpp:
+        (WebCore::isStyleSpanOrSpanWithOnlyStyleAttribute): Added; returns true if the element is a style span or
+        span possibly with a style attribute.
+        * editing/ApplyStyleCommand.h:
+        * editing/EditingStyle.cpp:
+        (WebCore::styleFromMatchedRulesForElement): Takes rulesToInclude.
+        (WebCore::EditingStyle::mergeStyleFromRules): Calls styleFromMatchedRulesForElement with AuthorCSSRules
+        | CrossOriginCSSRules to keep the original behavior.
+        (WebCore::EditingStyle::removeStyleFromRulesAndContext): Renamed from removeStyleFromRules; removes styles that
+        are present in context and not overridden by matched rules.
+        (WebCore::EditingStyle::removePropertiesInElementDefaultStyle): Added.
+        * editing/EditingStyle.h:
+        * editing/ReplaceSelectionCommand.cpp:
+        (WebCore::ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline): See the description above.
+
 2011-08-08  Dmitry Lomov  <[email protected]>
 
         https://bugs.webkit.org/show_bug.cgi?id=65778

Modified: trunk/Source/WebCore/css/CSSStyleSelector.cpp (92619 => 92620)


--- trunk/Source/WebCore/css/CSSStyleSelector.cpp	2011-08-08 19:11:33 UTC (rev 92619)
+++ trunk/Source/WebCore/css/CSSStyleSelector.cpp	2011-08-08 19:15:16 UTC (rev 92620)
@@ -2058,7 +2058,7 @@
         }
     }
 
-    if (m_matchAuthorAndUserStyles) {
+    if (m_matchAuthorAndUserStyles && (rulesToInclude & AuthorCSSRules)) {
         m_checker.m_sameOriginOnly = !(rulesToInclude & CrossOriginCSSRules);
 
         // Check the rules in author sheets.

Modified: trunk/Source/WebCore/editing/ApplyStyleCommand.cpp (92619 => 92620)


--- trunk/Source/WebCore/editing/ApplyStyleCommand.cpp	2011-08-08 19:11:33 UTC (rev 92619)
+++ trunk/Source/WebCore/editing/ApplyStyleCommand.cpp	2011-08-08 19:15:16 UTC (rev 92620)
@@ -70,6 +70,26 @@
     return elem->hasLocalName(spanAttr) && elem->getAttribute(classAttr) == styleSpanClassString();
 }
 
+bool isStyleSpanOrSpanWithOnlyStyleAttribute(const Element* element)
+{
+    if (!element || !element->hasTagName(spanTag))
+        return false;
+
+    const bool readonly = true;
+    NamedNodeMap* map = element->attributes(readonly);
+    if (!map || map->isEmpty())
+        return true;
+
+    unsigned matchedAttributes = 0;
+    if (element->fastGetAttribute(classAttr) == styleSpanClassString())
+        matchedAttributes++;
+    if (element->hasAttribute(styleAttr))
+        matchedAttributes++;
+
+    ASSERT(matchedAttributes <= map->length());
+    return matchedAttributes == map->length();
+}
+
 static bool isUnstyledStyleSpan(const Node* node)
 {
     if (!node || !node->isHTMLElement() || !node->hasTagName(spanTag))

Modified: trunk/Source/WebCore/editing/ApplyStyleCommand.h (92619 => 92620)


--- trunk/Source/WebCore/editing/ApplyStyleCommand.h	2011-08-08 19:11:33 UTC (rev 92619)
+++ trunk/Source/WebCore/editing/ApplyStyleCommand.h	2011-08-08 19:15:16 UTC (rev 92620)
@@ -130,6 +130,7 @@
 };
 
 bool isStyleSpan(const Node*);
+bool isStyleSpanOrSpanWithOnlyStyleAttribute(const Element*);
 PassRefPtr<HTMLElement> createStyleSpanElement(Document*);
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/editing/EditingStyle.cpp (92619 => 92620)


--- trunk/Source/WebCore/editing/EditingStyle.cpp	2011-08-08 19:11:33 UTC (rev 92619)
+++ trunk/Source/WebCore/editing/EditingStyle.cpp	2011-08-08 19:15:16 UTC (rev 92620)
@@ -818,11 +818,10 @@
     }
 }
 
-static PassRefPtr<CSSMutableStyleDeclaration> styleFromMatchedRulesForElement(Element* element)
+static PassRefPtr<CSSMutableStyleDeclaration> styleFromMatchedRulesForElement(Element* element, unsigned rulesToInclude)
 {
     RefPtr<CSSMutableStyleDeclaration> style = CSSMutableStyleDeclaration::create();
-    RefPtr<CSSRuleList> matchedRules = element->document()->styleSelector()->styleRulesForElement(element,
-        CSSStyleSelector::AuthorCSSRules | CSSStyleSelector::CrossOriginCSSRules);
+    RefPtr<CSSRuleList> matchedRules = element->document()->styleSelector()->styleRulesForElement(element, rulesToInclude);
     if (matchedRules) {
         for (unsigned i = 0; i < matchedRules->length(); i++) {
             if (matchedRules->item(i)->type() == CSSRule::STYLE_RULE) {
@@ -837,7 +836,8 @@
 
 void EditingStyle::mergeStyleFromRules(StyledElement* element)
 {
-    RefPtr<CSSMutableStyleDeclaration> styleFromMatchedRules = styleFromMatchedRulesForElement(element);
+    RefPtr<CSSMutableStyleDeclaration> styleFromMatchedRules = styleFromMatchedRulesForElement(element,
+        CSSStyleSelector::AuthorCSSRules | CSSStyleSelector::CrossOriginCSSRules);
     // Styles from the inline style declaration, held in the variable "style", take precedence 
     // over those from matched rules.
     if (m_mutableStyle)
@@ -870,17 +870,41 @@
     m_mutableStyle->merge(fromComputedStyle.get());
 }
 
-void EditingStyle::removeStyleFromRules(StyledElement* element)
+void EditingStyle::removeStyleFromRulesAndContext(StyledElement* element, Node* context)
 {
+    ASSERT(element);
     if (!m_mutableStyle)
         return;
 
-    RefPtr<CSSMutableStyleDeclaration> styleFromMatchedRules = styleFromMatchedRulesForElement(element);
-    if (!styleFromMatchedRules)
+    // 1. Remove style from matched rules because style remain without repeating it in inline style declaration
+    RefPtr<CSSMutableStyleDeclaration> styleFromMatchedRules = styleFromMatchedRulesForElement(element, CSSStyleSelector::AllButEmptyCSSRules);
+    if (styleFromMatchedRules && styleFromMatchedRules->length())
+        m_mutableStyle = getPropertiesNotIn(m_mutableStyle.get(), styleFromMatchedRules.get());
+
+    // 2. Remove style present in context and not overriden by matched rules.
+    RefPtr<EditingStyle> computedStyle = EditingStyle::create(context, EditingInheritablePropertiesAndBackgroundColorInEffect);
+    if (computedStyle->m_mutableStyle) {
+        computedStyle->removePropertiesInElementDefaultStyle(element);
+        m_mutableStyle = getPropertiesNotIn(m_mutableStyle.get(), computedStyle->m_mutableStyle.get());
+    }
+}
+
+void EditingStyle::removePropertiesInElementDefaultStyle(StyledElement* element)
+{
+    if (!m_mutableStyle || !m_mutableStyle->length())
         return;
 
-    m_mutableStyle = getPropertiesNotIn(m_mutableStyle.get(), styleFromMatchedRules.get());
+    RefPtr<CSSMutableStyleDeclaration> defaultStyle = styleFromMatchedRulesForElement(element, CSSStyleSelector::UAAndUserCSSRules);
+
+    Vector<int> propertiesToRemove(defaultStyle->length());
+    size_t i = 0;
+    CSSMutableStyleDeclaration::const_iterator end = defaultStyle->end();
+    for (CSSMutableStyleDeclaration::const_iterator it = defaultStyle->begin(); it != end; ++it, ++i)
+        propertiesToRemove[i] = it->id();
+
+    m_mutableStyle->removePropertiesInSet(propertiesToRemove.data(), propertiesToRemove.size());
 }
+    
 
 static void reconcileTextDecorationProperties(CSSMutableStyleDeclaration* style)
 {    

Modified: trunk/Source/WebCore/editing/EditingStyle.h (92619 => 92620)


--- trunk/Source/WebCore/editing/EditingStyle.h	2011-08-08 19:11:33 UTC (rev 92619)
+++ trunk/Source/WebCore/editing/EditingStyle.h	2011-08-08 19:15:16 UTC (rev 92620)
@@ -122,7 +122,7 @@
     void mergeInlineStyleOfElement(StyledElement*);
     void mergeStyleFromRules(StyledElement*);
     void mergeStyleFromRulesForSerialization(StyledElement*);
-    void removeStyleFromRules(StyledElement*);
+    void removeStyleFromRulesAndContext(StyledElement*, Node* context);
 
     float fontSizeDelta() const { return m_fontSizeDelta; }
     bool hasFontSizeDelta() const { return m_fontSizeDelta != NoFontDelta; }
@@ -141,6 +141,7 @@
     void extractFontSizeDelta();
     bool conflictsWithInlineStyleOfElement(StyledElement*, EditingStyle* extractedStyle, Vector<CSSPropertyID>* conflictingProperties) const;
     void mergeStyle(CSSMutableStyleDeclaration*);
+    void removePropertiesInElementDefaultStyle(StyledElement*);
 
     RefPtr<CSSMutableStyleDeclaration> m_mutableStyle;
     bool m_shouldUseFixedDefaultFontSize;

Modified: trunk/Source/WebCore/editing/ReplaceSelectionCommand.cpp (92619 => 92620)


--- trunk/Source/WebCore/editing/ReplaceSelectionCommand.cpp	2011-08-08 19:11:33 UTC (rev 92619)
+++ trunk/Source/WebCore/editing/ReplaceSelectionCommand.cpp	2011-08-08 19:15:16 UTC (rev 92620)
@@ -478,34 +478,55 @@
 // a div inserted into a document with div { display:inline; }.
 void ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline()
 {
-    for (RefPtr<Node> node = m_firstNodeInserted.get(); node; node = node->traverseNextNode()) {
+    RefPtr<Node> pastEndNode = m_lastLeafInserted ? m_lastLeafInserted->traverseNextNode() : 0;
+    RefPtr<Node> next;
+    for (RefPtr<Node> node = m_firstNodeInserted.get(); node && node != pastEndNode; node = next) {
         // FIXME: <rdar://problem/5371536> Style rules that match pasted content can change it's appearance
-        if (isStyleSpan(node.get())) {
-            HTMLElement* e = toHTMLElement(node.get());
+
+        next = node->traverseNextNode();
+        if (!node->isStyledElement())
+            continue;
+
+        StyledElement* element = static_cast<StyledElement*>(node.get());
+
+        CSSMutableStyleDeclaration* inlineStyle = element->inlineStyleDecl();
+        RefPtr<EditingStyle> newInlineStyle = EditingStyle::create(inlineStyle);
+        if (inlineStyle) {
+            ContainerNode* context = element->parentNode();
+
+            // If Mail wraps the fragment with a Paste as Quotation blockquote, or if you're pasting into a quoted region,
+            // styles from blockquoteNode are allowed to override those from the source document, see <rdar://problem/4930986> and <rdar://problem/5089327>.
+            Node* blockquoteNode = isMailPasteAsQuotationNode(context) ? context : enclosingNodeOfType(firstPositionInNode(context), isMailBlockquote, CanCrossEditingBoundary);
+            if (blockquoteNode)
+                newInlineStyle->removeStyleFromRulesAndContext(element, document()->documentElement());
+
+            newInlineStyle->removeStyleFromRulesAndContext(element, context);
+        }
+
+        if (!inlineStyle || newInlineStyle->isEmpty()) {
+            if (isStyleSpanOrSpanWithOnlyStyleAttribute(element))
+                removeNodePreservingChildren(element);
+            else
+                removeNodeAttribute(element, styleAttr);
+        } else if (newInlineStyle->style()->length() != inlineStyle->length())
+            setNodeAttribute(element, styleAttr, newInlineStyle->style()->cssText());
+
+        if (isStyleSpan(element)) {
+            if (!element->firstChild()) {
+                removeNodePreservingChildren(element);
+                continue;
+            }
             // There are other styles that style rules can give to style spans,
             // but these are the two important ones because they'll prevent
             // inserted content from appearing in the right paragraph.
             // FIXME: Hyatt is concerned that selectively using display:inline will give inconsistent
             // results. We already know one issue because td elements ignore their display property
             // in quirks mode (which Mail.app is always in). We should look for an alternative.
-            if (isBlock(e))
-                e->getInlineStyleDecl()->setProperty(CSSPropertyDisplay, CSSValueInline);
-            if (e->renderer() && e->renderer()->style()->isFloating())
-                e->getInlineStyleDecl()->setProperty(CSSPropertyFloat, CSSValueNone);
-        } else if (node->isStyledElement()) {
-            StyledElement* element = static_cast<StyledElement*>(node.get());
-            if (CSSMutableStyleDeclaration* inlineStyle = element->inlineStyleDecl()) {
-                RefPtr<EditingStyle> newInlineStyle = EditingStyle::create(inlineStyle);
-                newInlineStyle->removeStyleFromRules(element);
-                if (!newInlineStyle->style() || !newInlineStyle->style()->length())
-                    removeNodeAttribute(element, styleAttr);
-                else if (newInlineStyle->style()->length() < inlineStyle->length())
-                    setNodeAttribute(element, styleAttr, newInlineStyle->style()->cssText());                    
-            }
+            if (isBlock(element))
+                element->getInlineStyleDecl()->setProperty(CSSPropertyDisplay, CSSValueInline);
+            if (element->renderer() && element->renderer()->style()->isFloating())
+                element->getInlineStyleDecl()->setProperty(CSSPropertyFloat, CSSValueNone);
         }
-
-        if (node == m_lastLeafInserted)
-            break;
     }
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to