[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

abarth at webkit.org abarth at webkit.org
Wed Dec 22 14:41:04 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 409e717f19a80726c89a04ea9d9e9de12ea92894
Author: abarth at webkit.org <abarth at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Fri Oct 15 21:34:48 2010 +0000

    2010-10-15  Adam Barth  <abarth at webkit.org>
    
            Reviewed by Eric Seidel.
    
            Move MarkupAccumulator from markup.cpp to its own file
            https://bugs.webkit.org/show_bug.cgi?id=47734
    
            This patch moves the MarkupAccumulator class into its own file.
            There's a lot of clean up left to do, but this patch is a step in the
            right direction.
    
            No behavior change.
    
            * Android.mk:
            * CMakeLists.txt:
            * GNUmakefile.am:
            * WebCore.gypi:
            * WebCore.pro:
            * WebCore.vcproj/WebCore.vcproj:
            * WebCore.xcodeproj/project.pbxproj:
            * editing/markup.cpp:
            (WebCore::elementCannotHaveEndTag):
            * editing/markup.h:
            * editing/MarkupAccumulator.h: Added.
            * editing/MarkupAccumulator.cpp: Added.
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@69880 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/Android.mk b/WebCore/Android.mk
index f14d0e1..8cccc96 100644
--- a/WebCore/Android.mk
+++ b/WebCore/Android.mk
@@ -220,6 +220,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
 	editing/InsertParagraphSeparatorCommand.cpp \
 	editing/InsertTextCommand.cpp \
 	editing/JoinTextNodesCommand.cpp \
+	editing/MarkupAccumulator.cpp \
 	editing/MergeIdenticalElementsCommand.cpp \
 	editing/ModifySelectionListLevel.cpp \
 	editing/MoveSelectionCommand.cpp \
diff --git a/WebCore/CMakeLists.txt b/WebCore/CMakeLists.txt
index 96a634d..2e1bac7 100644
--- a/WebCore/CMakeLists.txt
+++ b/WebCore/CMakeLists.txt
@@ -904,6 +904,7 @@ SET(WebCore_SOURCES
     editing/InsertParagraphSeparatorCommand.cpp
     editing/InsertTextCommand.cpp
     editing/JoinTextNodesCommand.cpp
+    editing/MarkupAccumulator.cpp
     editing/MergeIdenticalElementsCommand.cpp
     editing/ModifySelectionListLevel.cpp
     editing/MoveSelectionCommand.cpp
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index c306598..55e8059 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,29 @@
+2010-10-15  Adam Barth  <abarth at webkit.org>
+
+        Reviewed by Eric Seidel.
+
+        Move MarkupAccumulator from markup.cpp to its own file
+        https://bugs.webkit.org/show_bug.cgi?id=47734
+
+        This patch moves the MarkupAccumulator class into its own file.
+        There's a lot of clean up left to do, but this patch is a step in the
+        right direction.
+
+        No behavior change.
+
+        * Android.mk:
+        * CMakeLists.txt:
+        * GNUmakefile.am:
+        * WebCore.gypi:
+        * WebCore.pro:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * editing/markup.cpp:
+        (WebCore::elementCannotHaveEndTag):
+        * editing/markup.h:
+        * editing/MarkupAccumulator.h: Added.
+        * editing/MarkupAccumulator.cpp: Added.
+
 2010-10-15  Ryosuke Niwa  <rniwa at webkit.org>
 
         Reviewed by Darin Adler.
diff --git a/WebCore/GNUmakefile.am b/WebCore/GNUmakefile.am
index c4eb1c2..7b8c161 100644
--- a/WebCore/GNUmakefile.am
+++ b/WebCore/GNUmakefile.am
@@ -1314,6 +1314,8 @@ webcore_sources += \
 	WebCore/editing/JoinTextNodesCommand.h \
 	WebCore/editing/markup.cpp \
 	WebCore/editing/markup.h \
+	WebCore/editing/MarkupAccumulator.cpp \
+	WebCore/editing/MarkupAccumulator.h \
 	WebCore/editing/MergeIdenticalElementsCommand.cpp \
 	WebCore/editing/MergeIdenticalElementsCommand.h \
 	WebCore/editing/ModifySelectionListLevel.cpp \
diff --git a/WebCore/WebCore.gypi b/WebCore/WebCore.gypi
index 7d3cb27..8d70283 100644
--- a/WebCore/WebCore.gypi
+++ b/WebCore/WebCore.gypi
@@ -1396,6 +1396,8 @@
             'editing/InsertTextCommand.h',
             'editing/JoinTextNodesCommand.cpp',
             'editing/JoinTextNodesCommand.h',
+            'editing/MarkupAccumulator.cpp',
+            'editing/MarkupAccumulator.h',
             'editing/MergeIdenticalElementsCommand.cpp',
             'editing/MergeIdenticalElementsCommand.h',
             'editing/ModifySelectionListLevel.cpp',
diff --git a/WebCore/WebCore.pro b/WebCore/WebCore.pro
index d479180..fa73450 100644
--- a/WebCore/WebCore.pro
+++ b/WebCore/WebCore.pro
@@ -795,6 +795,7 @@ SOURCES += \
     editing/InsertTextCommand.cpp \
     editing/JoinTextNodesCommand.cpp \
     editing/markup.cpp \
+    editing/MarkupAccumulator.cpp \
     editing/MergeIdenticalElementsCommand.cpp \
     editing/ModifySelectionListLevel.cpp \
     editing/MoveSelectionCommand.cpp \
diff --git a/WebCore/WebCore.vcproj/WebCore.vcproj b/WebCore/WebCore.vcproj/WebCore.vcproj
index 0771072..ec20aff 100644
--- a/WebCore/WebCore.vcproj/WebCore.vcproj
+++ b/WebCore/WebCore.vcproj/WebCore.vcproj
@@ -46655,6 +46655,62 @@
 				>
 			</File>
 			<File
+				RelativePath="..\editing\MarkupAccumulator.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug_Internal|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug_Cairo|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release_Cairo|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug_All|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\editing\MarkupAccumulator.h"
+				>
+			</File>
+			<File
 				RelativePath="..\editing\MergeIdenticalElementsCommand.cpp"
 				>
 				<FileConfiguration
diff --git a/WebCore/WebCore.xcodeproj/project.pbxproj b/WebCore/WebCore.xcodeproj/project.pbxproj
index 65aad7d..c323c94 100644
--- a/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -2861,6 +2861,8 @@
 		97205AB81239291000B17380 /* MediaDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = 97205AB41239291000B17380 /* MediaDocument.h */; };
 		97205ABB1239292700B17380 /* PluginDocument.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 97205AB91239292700B17380 /* PluginDocument.cpp */; };
 		97205ABC1239292700B17380 /* PluginDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = 97205ABA1239292700B17380 /* PluginDocument.h */; };
+		9728C3131268E4390041E89B /* MarkupAccumulator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9728C3111268E4390041E89B /* MarkupAccumulator.cpp */; };
+		9728C3141268E4390041E89B /* MarkupAccumulator.h in Headers */ = {isa = PBXBuildFile; fileRef = 9728C3121268E4390041E89B /* MarkupAccumulator.h */; };
 		973889A0116EA9DC00ADF313 /* DocumentWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9738899E116EA9DC00ADF313 /* DocumentWriter.cpp */; };
 		973889A1116EA9DC00ADF313 /* DocumentWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = 9738899F116EA9DC00ADF313 /* DocumentWriter.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		973E325610883B7C005BC493 /* ResourceLoadNotifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 973E325410883B7C005BC493 /* ResourceLoadNotifier.cpp */; };
@@ -8896,6 +8898,8 @@
 		97205AB41239291000B17380 /* MediaDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaDocument.h; sourceTree = "<group>"; };
 		97205AB91239292700B17380 /* PluginDocument.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PluginDocument.cpp; sourceTree = "<group>"; };
 		97205ABA1239292700B17380 /* PluginDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PluginDocument.h; sourceTree = "<group>"; };
+		9728C3111268E4390041E89B /* MarkupAccumulator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MarkupAccumulator.cpp; sourceTree = "<group>"; };
+		9728C3121268E4390041E89B /* MarkupAccumulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkupAccumulator.h; sourceTree = "<group>"; };
 		9738899E116EA9DC00ADF313 /* DocumentWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentWriter.cpp; sourceTree = "<group>"; };
 		9738899F116EA9DC00ADF313 /* DocumentWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentWriter.h; sourceTree = "<group>"; };
 		973E325410883B7C005BC493 /* ResourceLoadNotifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ResourceLoadNotifier.cpp; sourceTree = "<group>"; };
@@ -14406,6 +14410,8 @@
 				93309DA5099E64910056E581 /* JoinTextNodesCommand.h */,
 				93309DA8099E64910056E581 /* markup.cpp */,
 				93309DA9099E64910056E581 /* markup.h */,
+				9728C3111268E4390041E89B /* MarkupAccumulator.cpp */,
+				9728C3121268E4390041E89B /* MarkupAccumulator.h */,
 				93309DAA099E64910056E581 /* MergeIdenticalElementsCommand.cpp */,
 				93309DAB099E64910056E581 /* MergeIdenticalElementsCommand.h */,
 				C6D74AE309AA290A000B0A52 /* ModifySelectionListLevel.cpp */,
@@ -21076,6 +21082,7 @@
 				E1BE512E0CF6C512002EA959 /* XSLTUnicodeSort.h in Headers */,
 				97DD4D870FDF4D6E00ECF9A4 /* XSSAuditor.h in Headers */,
 				4FA3B90B125CD12200300BAD /* InspectorState.h in Headers */,
+				9728C3141268E4390041E89B /* MarkupAccumulator.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -21135,7 +21142,6 @@
 			isa = PBXProject;
 			buildConfigurationList = 149C284308902B11008A9EFC /* Build configuration list for PBXProject "WebCore" */;
 			compatibilityVersion = "Xcode 2.4";
-			developmentRegion = English;
 			hasScannedForEncodings = 1;
 			knownRegions = (
 				English,
@@ -23624,6 +23630,7 @@
 				E1BE512D0CF6C512002EA959 /* XSLTUnicodeSort.cpp in Sources */,
 				97DD4D860FDF4D6E00ECF9A4 /* XSSAuditor.cpp in Sources */,
 				4FA3B90A125CD12200300BAD /* InspectorState.cpp in Sources */,
+				9728C3131268E4390041E89B /* MarkupAccumulator.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/WebCore/editing/EditingAllInOne.cpp b/WebCore/editing/EditingAllInOne.cpp
index d8b504e..ba484be 100644
--- a/WebCore/editing/EditingAllInOne.cpp
+++ b/WebCore/editing/EditingAllInOne.cpp
@@ -48,6 +48,7 @@
 #include <InsertParagraphSeparatorCommand.cpp>
 #include <InsertTextCommand.cpp>
 #include <JoinTextNodesCommand.cpp>
+#include <MarkupAccumulator.cpp>
 #include <MergeIdenticalElementsCommand.cpp>
 #include <ModifySelectionListLevel.cpp>
 #include <MoveSelectionCommand.cpp>
diff --git a/WebCore/editing/MarkupAccumulator.cpp b/WebCore/editing/MarkupAccumulator.cpp
new file mode 100644
index 0000000..aa6e5cf
--- /dev/null
+++ b/WebCore/editing/MarkupAccumulator.cpp
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "MarkupAccumulator.h"
+
+#include "CDATASection.h"
+#include "CharacterNames.h"
+#include "Comment.h"
+#include "DocumentFragment.h"
+#include "DocumentType.h"
+#include "Editor.h"
+#include "HTMLElement.h"
+#include "HTMLNames.h"
+#include "KURL.h"
+#include "ProcessingInstruction.h"
+#include "XMLNSNames.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+void appendCharactersReplacingEntities(Vector<UChar>& out, const UChar* content, size_t length, EntityMask entityMask)
+{
+    DEFINE_STATIC_LOCAL(const String, ampReference, ("&amp;"));
+    DEFINE_STATIC_LOCAL(const String, ltReference, ("&lt;"));
+    DEFINE_STATIC_LOCAL(const String, gtReference, ("&gt;"));
+    DEFINE_STATIC_LOCAL(const String, quotReference, ("&quot;"));
+    DEFINE_STATIC_LOCAL(const String, nbspReference, ("&nbsp;"));
+
+    static const EntityDescription entityMaps[] = {
+        { '&', ampReference, EntityAmp },
+        { '<', ltReference, EntityLt },
+        { '>', gtReference, EntityGt },
+        { '"', quotReference, EntityQuot },
+        { noBreakSpace, nbspReference, EntityNbsp },
+    };
+
+    size_t positionAfterLastEntity = 0;
+    for (size_t i = 0; i < length; i++) {
+        for (size_t m = 0; m < sizeof(entityMaps) / sizeof(EntityDescription); m++) {
+            if (content[i] == entityMaps[m].entity && entityMaps[m].mask & entityMask) {
+                out.append(content + positionAfterLastEntity, i - positionAfterLastEntity);
+                append(out, entityMaps[m].reference);
+                positionAfterLastEntity = i + 1;
+                break;
+            }
+        }
+    }
+    out.append(content + positionAfterLastEntity, length - positionAfterLastEntity);
+}
+
+MarkupAccumulator::MarkupAccumulator(Vector<Node*>* nodes, EAbsoluteURLs shouldResolveURLs, const Range* range)
+    : m_nodes(nodes)
+    , m_range(range)
+    , m_shouldResolveURLs(shouldResolveURLs)
+{
+}
+
+MarkupAccumulator::~MarkupAccumulator()
+{
+}
+
+void MarkupAccumulator::appendString(const String& string)
+{
+    m_succeedingMarkup.append(string);
+}
+
+void MarkupAccumulator::appendStartTag(Node* node, Namespaces* namespaces)
+{
+    Vector<UChar> markup;
+    appendStartMarkup(markup, node, namespaces);
+    m_succeedingMarkup.append(String::adopt(markup));
+    if (m_nodes)
+        m_nodes->append(node);
+}
+
+void MarkupAccumulator::appendEndTag(Node* node)
+{
+    Vector<UChar> markup;
+    appendEndMarkup(markup, node);
+    m_succeedingMarkup.append(String::adopt(markup));
+}
+
+// FIXME: This is a very inefficient way of accumulating the markup.
+// We're converting results of appendStartMarkup and appendEndMarkup from Vector<UChar> to String
+// and then back to Vector<UChar> and again to String here.
+String MarkupAccumulator::takeResults()
+{
+    size_t length = 0;
+
+    size_t postCount = m_succeedingMarkup.size();
+    for (size_t i = 0; i < postCount; ++i)
+        length += m_succeedingMarkup[i].length();
+
+    Vector<UChar> result;
+    result.reserveInitialCapacity(length);
+
+    for (size_t i = 0; i < postCount; ++i)
+        append(result, m_succeedingMarkup[i]);
+
+    return String::adopt(result);
+}
+
+void MarkupAccumulator::appendAttributeValue(Vector<UChar>& result, const String& attribute, bool documentIsHTML)
+{
+    appendCharactersReplacingEntities(result, attribute.characters(), attribute.length(),
+        documentIsHTML ? EntityMaskInHTMLAttributeValue : EntityMaskInAttributeValue);
+}
+
+void MarkupAccumulator::appendQuotedURLAttributeValue(Vector<UChar>& result, const String& urlString)
+{
+    UChar quoteChar = '\"';
+    String strippedURLString = urlString.stripWhiteSpace();
+    if (protocolIsJavaScript(strippedURLString)) {
+        // minimal escaping for javascript urls
+        if (strippedURLString.contains('"')) {
+            if (strippedURLString.contains('\''))
+                strippedURLString.replace('\"', "&quot;");
+            else
+                quoteChar = '\'';
+        }
+        result.append(quoteChar);
+        append(result, strippedURLString);
+        result.append(quoteChar);
+        return;
+    }
+
+    // FIXME: This does not fully match other browsers. Firefox percent-escapes non-ASCII characters for innerHTML.
+    result.append(quoteChar);
+    appendAttributeValue(result, urlString, false);
+    result.append(quoteChar);
+}
+
+void MarkupAccumulator::appendNodeValue(Vector<UChar>& out, const Node* node, const Range* range, EntityMask entityMask)
+{
+    String str = node->nodeValue();
+    const UChar* characters = str.characters();
+    size_t length = str.length();
+
+    if (range) {
+        ExceptionCode ec;
+        if (node == range->endContainer(ec))
+            length = range->endOffset(ec);
+        if (node == range->startContainer(ec)) {
+            size_t start = range->startOffset(ec);
+            characters += start;
+            length -= start;
+        }
+    }
+
+    appendCharactersReplacingEntities(out, characters, length, entityMask);
+}
+
+bool MarkupAccumulator::shouldAddNamespaceElement(const Element* element)
+{
+    // Don't add namespace attribute if it is already defined for this elem.
+    const AtomicString& prefix = element->prefix();
+    AtomicString attr = !prefix.isEmpty() ? "xmlns:" + prefix : "xmlns";
+    return !element->hasAttribute(attr);
+}
+
+bool MarkupAccumulator::shouldAddNamespaceAttribute(const Attribute& attribute, Namespaces& namespaces)
+{
+    namespaces.checkConsistency();
+
+    // Don't add namespace attributes twice
+    if (attribute.name() == XMLNSNames::xmlnsAttr) {
+        namespaces.set(emptyAtom.impl(), attribute.value().impl());
+        return false;
+    }
+    
+    QualifiedName xmlnsPrefixAttr(xmlnsAtom, attribute.localName(), XMLNSNames::xmlnsNamespaceURI);
+    if (attribute.name() == xmlnsPrefixAttr) {
+        namespaces.set(attribute.localName().impl(), attribute.value().impl());
+        return false;
+    }
+    
+    return true;
+}
+
+void MarkupAccumulator::appendNamespace(Vector<UChar>& result, const AtomicString& prefix, const AtomicString& namespaceURI, Namespaces& namespaces)
+{
+    namespaces.checkConsistency();
+    if (namespaceURI.isEmpty())
+        return;
+        
+    // Use emptyAtoms's impl() for both null and empty strings since the HashMap can't handle 0 as a key
+    AtomicStringImpl* pre = prefix.isEmpty() ? emptyAtom.impl() : prefix.impl();
+    AtomicStringImpl* foundNS = namespaces.get(pre);
+    if (foundNS != namespaceURI.impl()) {
+        namespaces.set(pre, namespaceURI.impl());
+        result.append(' ');
+        append(result, xmlnsAtom.string());
+        if (!prefix.isEmpty()) {
+            result.append(':');
+            append(result, prefix);
+        }
+
+        result.append('=');
+        result.append('"');
+        appendAttributeValue(result, namespaceURI, false);
+        result.append('"');
+    }
+}
+
+EntityMask MarkupAccumulator::entityMaskForText(Text* text) const
+{
+    const QualifiedName* parentName = 0;
+    if (text->parentElement())
+        parentName = &static_cast<Element*>(text->parentElement())->tagQName();
+    
+    if (parentName && (*parentName == scriptTag || *parentName == styleTag || *parentName == xmpTag))
+        return EntityMaskInCDATA;
+
+    return text->document()->isHTMLDocument() ? EntityMaskInHTMLPCDATA : EntityMaskInPCDATA;
+}
+
+void MarkupAccumulator::appendText(Vector<UChar>& out, Text* text)
+{
+    appendNodeValue(out, text, m_range, entityMaskForText(text));
+}
+
+void MarkupAccumulator::appendComment(Vector<UChar>& out, const String& comment)
+{
+    // FIXME: Comment content is not escaped, but XMLSerializer (and possibly other callers) should raise an exception if it includes "-->".
+    append(out, "<!--");
+    append(out, comment);
+    append(out, "-->");
+}
+
+void MarkupAccumulator::appendDocumentType(Vector<UChar>& result, const DocumentType* n)
+{
+    if (n->name().isEmpty())
+        return;
+
+    append(result, "<!DOCTYPE ");
+    append(result, n->name());
+    if (!n->publicId().isEmpty()) {
+        append(result, " PUBLIC \"");
+        append(result, n->publicId());
+        append(result, "\"");
+        if (!n->systemId().isEmpty()) {
+            append(result, " \"");
+            append(result, n->systemId());
+            append(result, "\"");
+        }
+    } else if (!n->systemId().isEmpty()) {
+        append(result, " SYSTEM \"");
+        append(result, n->systemId());
+        append(result, "\"");
+    }
+    if (!n->internalSubset().isEmpty()) {
+        append(result, " [");
+        append(result, n->internalSubset());
+        append(result, "]");
+    }
+    append(result, ">");
+}
+
+void MarkupAccumulator::appendProcessingInstruction(Vector<UChar>& out, const String& target, const String& data)
+{
+    // FIXME: PI data is not escaped, but XMLSerializer (and possibly other callers) this should raise an exception if it includes "?>".
+    append(out, "<?");
+    append(out, target);
+    append(out, " ");
+    append(out, data);
+    append(out, "?>");
+}
+
+void MarkupAccumulator::appendElement(Vector<UChar>& out, Element* element, Namespaces* namespaces)
+{
+    appendOpenTag(out, element, namespaces);
+
+    NamedNodeMap* attributes = element->attributes();
+    unsigned length = attributes->length();
+    for (unsigned int i = 0; i < length; i++)
+        appendAttribute(out, element, *attributes->attributeItem(i), namespaces);
+
+    appendCloseTag(out, element);
+}
+
+void MarkupAccumulator::appendOpenTag(Vector<UChar>& out, Element* element, Namespaces* namespaces)
+{
+    out.append('<');
+    append(out, element->nodeNamePreservingCase());
+    if (!element->document()->isHTMLDocument() && namespaces && shouldAddNamespaceElement(element))
+        appendNamespace(out, element->prefix(), element->namespaceURI(), *namespaces);    
+}
+
+void MarkupAccumulator::appendCloseTag(Vector<UChar>& out, Element* element)
+{
+    if (shouldSelfClose(element)) {
+        if (element->isHTMLElement())
+            out.append(' '); // XHTML 1.0 <-> HTML compatibility.
+        out.append('/');
+    }
+    out.append('>');
+}
+
+void MarkupAccumulator::appendAttribute(Vector<UChar>& out, Element* element, const Attribute& attribute, Namespaces* namespaces)
+{
+    bool documentIsHTML = element->document()->isHTMLDocument();
+
+    out.append(' ');
+
+    if (documentIsHTML)
+        append(out, attribute.name().localName());
+    else
+        append(out, attribute.name().toString());
+
+    out.append('=');
+
+    if (element->isURLAttribute(const_cast<Attribute*>(&attribute))) {
+        // We don't want to complete file:/// URLs because it may contain sensitive information
+        // about the user's system.
+        if (shouldResolveURLs() && !element->document()->url().isLocalFile())
+            appendQuotedURLAttributeValue(out, element->document()->completeURL(attribute.value()).string());
+        else
+            appendQuotedURLAttributeValue(out, attribute.value()); 
+    } else {
+        out.append('\"');
+        appendAttributeValue(out, attribute.value(), documentIsHTML);
+        out.append('\"');
+    }
+
+    if (!documentIsHTML && namespaces && shouldAddNamespaceAttribute(attribute, *namespaces))
+        appendNamespace(out, attribute.prefix(), attribute.namespaceURI(), *namespaces);
+}
+
+void MarkupAccumulator::appendCDATASection(Vector<UChar>& out, const String& section)
+{
+    // FIXME: CDATA content is not escaped, but XMLSerializer (and possibly other callers) should raise an exception if it includes "]]>".
+    append(out, "<![CDATA[");
+    append(out, section);
+    append(out, "]]>");
+}
+
+void MarkupAccumulator::appendStartMarkup(Vector<UChar>& result, const Node* node, Namespaces* namespaces)
+{
+    if (namespaces)
+        namespaces->checkConsistency();
+
+    switch (node->nodeType()) {
+    case Node::TEXT_NODE:
+        appendText(result, static_cast<Text*>(const_cast<Node*>(node)));
+        break;
+    case Node::COMMENT_NODE:
+        appendComment(result, static_cast<const Comment*>(node)->data());
+        break;
+    case Node::DOCUMENT_NODE:
+    case Node::DOCUMENT_FRAGMENT_NODE:
+        break;
+    case Node::DOCUMENT_TYPE_NODE:
+        appendDocumentType(result, static_cast<const DocumentType*>(node));
+        break;
+    case Node::PROCESSING_INSTRUCTION_NODE:
+        appendProcessingInstruction(result, static_cast<const ProcessingInstruction*>(node)->target(), static_cast<const ProcessingInstruction*>(node)->data());
+        break;
+    case Node::ELEMENT_NODE:
+        appendElement(result, static_cast<Element*>(const_cast<Node*>(node)), namespaces);
+        break;
+    case Node::CDATA_SECTION_NODE:
+        appendCDATASection(result, static_cast<const CDATASection*>(node)->data());
+        break;
+    case Node::ATTRIBUTE_NODE:
+    case Node::ENTITY_NODE:
+    case Node::ENTITY_REFERENCE_NODE:
+    case Node::NOTATION_NODE:
+    case Node::XPATH_NAMESPACE_NODE:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+}
+
+// Rules of self-closure
+// 1. No elements in HTML documents use the self-closing syntax.
+// 2. Elements w/ children never self-close because they use a separate end tag.
+// 3. HTML elements which do not have a "forbidden" end tag will close with a separate end tag.
+// 4. Other elements self-close.
+bool MarkupAccumulator::shouldSelfClose(const Node* node)
+{
+    if (node->document()->isHTMLDocument())
+        return false;
+    if (node->hasChildNodes())
+        return false;
+    if (node->isHTMLElement() && !elementCannotHaveEndTag(node))
+        return false;
+    return true;
+}
+
+void MarkupAccumulator::appendEndMarkup(Vector<UChar>& result, const Node* node)
+{
+    if (!node->isElementNode() || shouldSelfClose(node) || (!node->hasChildNodes() && elementCannotHaveEndTag(node)))
+        return;
+
+    result.append('<');
+    result.append('/');
+    append(result, static_cast<const Element*>(node)->nodeNamePreservingCase());
+    result.append('>');
+}
+
+}
diff --git a/WebCore/editing/MarkupAccumulator.h b/WebCore/editing/MarkupAccumulator.h
new file mode 100644
index 0000000..3741259
--- /dev/null
+++ b/WebCore/editing/MarkupAccumulator.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef MarkupAccumulator_h
+#define MarkupAccumulator_h
+
+#include "PlatformString.h"
+#include "markup.h"
+#include <wtf/HashMap.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class Attribute;
+class DocumentType;
+class Element;
+class Node;
+class Range;
+
+typedef HashMap<AtomicStringImpl*, AtomicStringImpl*> Namespaces;
+
+enum EntityMask {
+    EntityAmp = 0x0001,
+    EntityLt = 0x0002,
+    EntityGt = 0x0004,
+    EntityQuot = 0x0008,
+    EntityNbsp = 0x0010,
+
+    // Non-breaking space needs to be escaped in innerHTML for compatibility reason. See http://trac.webkit.org/changeset/32879
+    // However, we cannot do this in a XML document because it does not have the entity reference defined (See the bug 19215).
+    EntityMaskInCDATA = 0,
+    EntityMaskInPCDATA = EntityAmp | EntityLt | EntityGt,
+    EntityMaskInHTMLPCDATA = EntityMaskInPCDATA | EntityNbsp,
+    EntityMaskInAttributeValue = EntityAmp | EntityLt | EntityGt | EntityQuot,
+    EntityMaskInHTMLAttributeValue = EntityMaskInAttributeValue | EntityNbsp,
+};
+
+struct EntityDescription {
+    UChar entity;
+    const String& reference;
+    EntityMask mask;
+};
+
+// FIXME: Noncopyable?
+class MarkupAccumulator {
+public:
+    MarkupAccumulator(Vector<Node*>* nodes, EAbsoluteURLs shouldResolveURLs, const Range* range = 0);
+    virtual ~MarkupAccumulator();
+
+    void appendString(const String&);
+    void appendStartTag(Node*, Namespaces* = 0);
+    void appendEndTag(Node*);
+    virtual String takeResults();
+
+protected:
+    void appendAttributeValue(Vector<UChar>& result, const String& attribute, bool documentIsHTML);
+    void appendQuotedURLAttributeValue(Vector<UChar>& result, const String& urlString);
+    void appendNodeValue(Vector<UChar>& out, const Node*, const Range*, EntityMask);
+    bool shouldAddNamespaceElement(const Element*);
+    bool shouldAddNamespaceAttribute(const Attribute&, Namespaces&);
+    void appendNamespace(Vector<UChar>& result, const AtomicString& prefix, const AtomicString& namespaceURI, Namespaces&);
+    EntityMask entityMaskForText(Text* text) const;
+    virtual void appendText(Vector<UChar>& out, Text*);
+    void appendComment(Vector<UChar>& out, const String& comment);
+    void appendDocumentType(Vector<UChar>& result, const DocumentType*);
+    void appendProcessingInstruction(Vector<UChar>& out, const String& target, const String& data);
+    virtual void appendElement(Vector<UChar>& out, Element*, Namespaces*);
+    void appendOpenTag(Vector<UChar>& out, Element* element, Namespaces*);
+    void appendCloseTag(Vector<UChar>& out, Element* element);
+    void appendAttribute(Vector<UChar>& out, Element* element, const Attribute&, Namespaces*);
+    void appendCDATASection(Vector<UChar>& out, const String& section);
+    void appendStartMarkup(Vector<UChar>& result, const Node*, Namespaces*);
+    bool shouldSelfClose(const Node*);
+    void appendEndMarkup(Vector<UChar>& result, const Node*);
+
+    bool shouldResolveURLs() { return m_shouldResolveURLs == AbsoluteURLs; }
+
+    Vector<Node*>* const m_nodes;
+    const Range* const m_range;
+    Vector<String> m_succeedingMarkup;
+
+private:
+    const bool m_shouldResolveURLs;
+};
+
+// FIXME: This method should be integrated with MarkupAccumulator.
+void appendCharactersReplacingEntities(Vector<UChar>& out, const UChar* content, size_t length, EntityMask entityMask);
+
+}
+
+#endif
diff --git a/WebCore/editing/markup.cpp b/WebCore/editing/markup.cpp
index 308fded..bf5bbdb 100644
--- a/WebCore/editing/markup.cpp
+++ b/WebCore/editing/markup.cpp
@@ -52,6 +52,7 @@
 #include "InlineTextBox.h"
 #include "KURL.h"
 #include "Logging.h"
+#include "MarkupAccumulator.h"
 #include "ProcessingInstruction.h"
 #include "Range.h"
 #include "TextIterator.h"
@@ -91,419 +92,8 @@ private:
     QualifiedName m_name;
     String m_value;
 };
-    
-enum EntityMask {
-    EntityAmp = 0x0001,
-    EntityLt = 0x0002,
-    EntityGt = 0x0004,
-    EntityQuot = 0x0008,
-    EntityNbsp = 0x0010,
-
-    // Non-breaking space needs to be escaped in innerHTML for compatibility reason. See http://trac.webkit.org/changeset/32879
-    // However, we cannot do this in a XML document because it does not have the entity reference defined (See the bug 19215).
-    EntityMaskInCDATA = 0,
-    EntityMaskInPCDATA = EntityAmp | EntityLt | EntityGt,
-    EntityMaskInHTMLPCDATA = EntityMaskInPCDATA | EntityNbsp,
-    EntityMaskInAttributeValue = EntityAmp | EntityLt | EntityGt | EntityQuot,
-    EntityMaskInHTMLAttributeValue = EntityMaskInAttributeValue | EntityNbsp,
-};
-
-struct EntityDescription {
-    UChar entity;
-    const String& reference;
-    EntityMask mask;
-};
-
-static void appendCharactersReplacingEntities(Vector<UChar>& out, const UChar* content, size_t length, EntityMask entityMask)
-{
-    DEFINE_STATIC_LOCAL(const String, ampReference, ("&amp;"));
-    DEFINE_STATIC_LOCAL(const String, ltReference, ("&lt;"));
-    DEFINE_STATIC_LOCAL(const String, gtReference, ("&gt;"));
-    DEFINE_STATIC_LOCAL(const String, quotReference, ("&quot;"));
-    DEFINE_STATIC_LOCAL(const String, nbspReference, ("&nbsp;"));
-
-    static const EntityDescription entityMaps[] = {
-        { '&', ampReference, EntityAmp },
-        { '<', ltReference, EntityLt },
-        { '>', gtReference, EntityGt },
-        { '"', quotReference, EntityQuot },
-        { noBreakSpace, nbspReference, EntityNbsp },
-    };
-
-    size_t positionAfterLastEntity = 0;
-    for (size_t i = 0; i < length; i++) {
-        for (size_t m = 0; m < sizeof(entityMaps) / sizeof(EntityDescription); m++) {
-            if (content[i] == entityMaps[m].entity && entityMaps[m].mask & entityMask) {
-                out.append(content + positionAfterLastEntity, i - positionAfterLastEntity);
-                append(out, entityMaps[m].reference);
-                positionAfterLastEntity = i + 1;
-                break;
-            }
-        }
-    }
-    out.append(content + positionAfterLastEntity, length - positionAfterLastEntity);
-}
-
-typedef HashMap<AtomicStringImpl*, AtomicStringImpl*> Namespaces;
-
-class MarkupAccumulator {
-public:
-    MarkupAccumulator(Vector<Node*>* nodes, EAbsoluteURLs shouldResolveURLs, const Range* range = 0)
-        : m_nodes(nodes)
-        , m_range(range)
-        , m_shouldResolveURLs(shouldResolveURLs)
-    {
-    }
-    virtual ~MarkupAccumulator() {}
-    void appendString(const String&);
-    void appendStartTag(Node*, Namespaces* = 0);
-    void appendEndTag(Node*);
-    virtual String takeResults();
-
-protected:
-    void appendAttributeValue(Vector<UChar>& result, const String& attribute, bool documentIsHTML);
-    void appendQuotedURLAttributeValue(Vector<UChar>& result, const String& urlString);
-    void appendNodeValue(Vector<UChar>& out, const Node*, const Range*, EntityMask);
-    bool shouldAddNamespaceElement(const Element*);
-    bool shouldAddNamespaceAttribute(const Attribute&, Namespaces&);
-    void appendNamespace(Vector<UChar>& result, const AtomicString& prefix, const AtomicString& namespaceURI, Namespaces&);
-    EntityMask entityMaskForText(Text* text) const;
-    virtual void appendText(Vector<UChar>& out, Text*);
-    void appendComment(Vector<UChar>& out, const String& comment);
-    void appendDocumentType(Vector<UChar>& result, const DocumentType*);
-    void appendProcessingInstruction(Vector<UChar>& out, const String& target, const String& data);
-    virtual void appendElement(Vector<UChar>& out, Element*, Namespaces*);
-    void appendOpenTag(Vector<UChar>& out, Element* element, Namespaces*);
-    void appendCloseTag(Vector<UChar>& out, Element* element);
-    void appendAttribute(Vector<UChar>& out, Element* element, const Attribute&, Namespaces*);
-    void appendCDATASection(Vector<UChar>& out, const String& section);
-    void appendStartMarkup(Vector<UChar>& result, const Node*, Namespaces*);
-    bool shouldSelfClose(const Node*);
-    void appendEndMarkup(Vector<UChar>& result, const Node*);
-
-    bool shouldResolveURLs() { return m_shouldResolveURLs == AbsoluteURLs; }
-
-    Vector<Node*>* const m_nodes;
-    const Range* const m_range;
-    Vector<String> m_succeedingMarkup;
-
-private:
-    const bool m_shouldResolveURLs;
-};
-
-void MarkupAccumulator::appendString(const String& string)
-{
-    m_succeedingMarkup.append(string);
-}
-
-void MarkupAccumulator::appendStartTag(Node* node, Namespaces* namespaces)
-{
-    Vector<UChar> markup;
-    appendStartMarkup(markup, node, namespaces);
-    m_succeedingMarkup.append(String::adopt(markup));
-    if (m_nodes)
-        m_nodes->append(node);
-}
-
-void MarkupAccumulator::appendEndTag(Node* node)
-{
-    Vector<UChar> markup;
-    appendEndMarkup(markup, node);
-    m_succeedingMarkup.append(String::adopt(markup));
-}
-
-// FIXME: This is a very inefficient way of accumulating the markup.
-// We're converting results of appendStartMarkup and appendEndMarkup from Vector<UChar> to String
-// and then back to Vector<UChar> and again to String here.
-String MarkupAccumulator::takeResults()
-{
-    size_t length = 0;
-
-    size_t postCount = m_succeedingMarkup.size();
-    for (size_t i = 0; i < postCount; ++i)
-        length += m_succeedingMarkup[i].length();
-
-    Vector<UChar> result;
-    result.reserveInitialCapacity(length);
-
-    for (size_t i = 0; i < postCount; ++i)
-        append(result, m_succeedingMarkup[i]);
-
-    return String::adopt(result);
-}
-
-void MarkupAccumulator::appendAttributeValue(Vector<UChar>& result, const String& attribute, bool documentIsHTML)
-{
-    appendCharactersReplacingEntities(result, attribute.characters(), attribute.length(),
-        documentIsHTML ? EntityMaskInHTMLAttributeValue : EntityMaskInAttributeValue);
-}
 
-void MarkupAccumulator::appendQuotedURLAttributeValue(Vector<UChar>& result, const String& urlString)
-{
-    UChar quoteChar = '\"';
-    String strippedURLString = urlString.stripWhiteSpace();
-    if (protocolIsJavaScript(strippedURLString)) {
-        // minimal escaping for javascript urls
-        if (strippedURLString.contains('"')) {
-            if (strippedURLString.contains('\''))
-                strippedURLString.replace('\"', "&quot;");
-            else
-                quoteChar = '\'';
-        }
-        result.append(quoteChar);
-        append(result, strippedURLString);
-        result.append(quoteChar);
-        return;
-    }
-
-    // FIXME: This does not fully match other browsers. Firefox percent-escapes non-ASCII characters for innerHTML.
-    result.append(quoteChar);
-    appendAttributeValue(result, urlString, false);
-    result.append(quoteChar);
-}
-
-void MarkupAccumulator::appendNodeValue(Vector<UChar>& out, const Node* node, const Range* range, EntityMask entityMask)
-{
-    String str = node->nodeValue();
-    const UChar* characters = str.characters();
-    size_t length = str.length();
-
-    if (range) {
-        ExceptionCode ec;
-        if (node == range->endContainer(ec))
-            length = range->endOffset(ec);
-        if (node == range->startContainer(ec)) {
-            size_t start = range->startOffset(ec);
-            characters += start;
-            length -= start;
-        }
-    }
-
-    appendCharactersReplacingEntities(out, characters, length, entityMask);
-}
-
-bool MarkupAccumulator::shouldAddNamespaceElement(const Element* element)
-{
-    // Don't add namespace attribute if it is already defined for this elem.
-    const AtomicString& prefix = element->prefix();
-    AtomicString attr = !prefix.isEmpty() ? "xmlns:" + prefix : "xmlns";
-    return !element->hasAttribute(attr);
-}
-
-bool MarkupAccumulator::shouldAddNamespaceAttribute(const Attribute& attribute, Namespaces& namespaces)
-{
-    namespaces.checkConsistency();
-
-    // Don't add namespace attributes twice
-    if (attribute.name() == XMLNSNames::xmlnsAttr) {
-        namespaces.set(emptyAtom.impl(), attribute.value().impl());
-        return false;
-    }
-    
-    QualifiedName xmlnsPrefixAttr(xmlnsAtom, attribute.localName(), XMLNSNames::xmlnsNamespaceURI);
-    if (attribute.name() == xmlnsPrefixAttr) {
-        namespaces.set(attribute.localName().impl(), attribute.value().impl());
-        return false;
-    }
-    
-    return true;
-}
-
-void MarkupAccumulator::appendNamespace(Vector<UChar>& result, const AtomicString& prefix, const AtomicString& namespaceURI, Namespaces& namespaces)
-{
-    namespaces.checkConsistency();
-    if (namespaceURI.isEmpty())
-        return;
-        
-    // Use emptyAtoms's impl() for both null and empty strings since the HashMap can't handle 0 as a key
-    AtomicStringImpl* pre = prefix.isEmpty() ? emptyAtom.impl() : prefix.impl();
-    AtomicStringImpl* foundNS = namespaces.get(pre);
-    if (foundNS != namespaceURI.impl()) {
-        namespaces.set(pre, namespaceURI.impl());
-        result.append(' ');
-        append(result, xmlnsAtom.string());
-        if (!prefix.isEmpty()) {
-            result.append(':');
-            append(result, prefix);
-        }
-
-        result.append('=');
-        result.append('"');
-        appendAttributeValue(result, namespaceURI, false);
-        result.append('"');
-    }
-}
-
-EntityMask MarkupAccumulator::entityMaskForText(Text* text) const
-{
-    const QualifiedName* parentName = 0;
-    if (text->parentElement())
-        parentName = &static_cast<Element*>(text->parentElement())->tagQName();
-    
-    if (parentName && (*parentName == scriptTag || *parentName == styleTag || *parentName == xmpTag))
-        return EntityMaskInCDATA;
-
-    return text->document()->isHTMLDocument() ? EntityMaskInHTMLPCDATA : EntityMaskInPCDATA;
-}
-
-void MarkupAccumulator::appendText(Vector<UChar>& out, Text* text)
-{
-    appendNodeValue(out, text, m_range, entityMaskForText(text));
-}
-
-void MarkupAccumulator::appendComment(Vector<UChar>& out, const String& comment)
-{
-    // FIXME: Comment content is not escaped, but XMLSerializer (and possibly other callers) should raise an exception if it includes "-->".
-    append(out, "<!--");
-    append(out, comment);
-    append(out, "-->");
-}
-
-void MarkupAccumulator::appendDocumentType(Vector<UChar>& result, const DocumentType* n)
-{
-    if (n->name().isEmpty())
-        return;
-
-    append(result, "<!DOCTYPE ");
-    append(result, n->name());
-    if (!n->publicId().isEmpty()) {
-        append(result, " PUBLIC \"");
-        append(result, n->publicId());
-        append(result, "\"");
-        if (!n->systemId().isEmpty()) {
-            append(result, " \"");
-            append(result, n->systemId());
-            append(result, "\"");
-        }
-    } else if (!n->systemId().isEmpty()) {
-        append(result, " SYSTEM \"");
-        append(result, n->systemId());
-        append(result, "\"");
-    }
-    if (!n->internalSubset().isEmpty()) {
-        append(result, " [");
-        append(result, n->internalSubset());
-        append(result, "]");
-    }
-    append(result, ">");
-}
-
-void MarkupAccumulator::appendProcessingInstruction(Vector<UChar>& out, const String& target, const String& data)
-{
-    // FIXME: PI data is not escaped, but XMLSerializer (and possibly other callers) this should raise an exception if it includes "?>".
-    append(out, "<?");
-    append(out, target);
-    append(out, " ");
-    append(out, data);
-    append(out, "?>");
-}
-
-void MarkupAccumulator::appendElement(Vector<UChar>& out, Element* element, Namespaces* namespaces)
-{
-    appendOpenTag(out, element, namespaces);
-
-    NamedNodeMap* attributes = element->attributes();
-    unsigned length = attributes->length();
-    for (unsigned int i = 0; i < length; i++)
-        appendAttribute(out, element, *attributes->attributeItem(i), namespaces);
-
-    appendCloseTag(out, element);
-}
-
-void MarkupAccumulator::appendOpenTag(Vector<UChar>& out, Element* element, Namespaces* namespaces)
-{
-    out.append('<');
-    append(out, element->nodeNamePreservingCase());
-    if (!element->document()->isHTMLDocument() && namespaces && shouldAddNamespaceElement(element))
-        appendNamespace(out, element->prefix(), element->namespaceURI(), *namespaces);    
-}
-
-void MarkupAccumulator::appendCloseTag(Vector<UChar>& out, Element* element)
-{
-    if (shouldSelfClose(element)) {
-        if (element->isHTMLElement())
-            out.append(' '); // XHTML 1.0 <-> HTML compatibility.
-        out.append('/');
-    }
-    out.append('>');
-}
-
-void MarkupAccumulator::appendAttribute(Vector<UChar>& out, Element* element, const Attribute& attribute, Namespaces* namespaces)
-{
-    bool documentIsHTML = element->document()->isHTMLDocument();
-
-    out.append(' ');
-
-    if (documentIsHTML)
-        append(out, attribute.name().localName());
-    else
-        append(out, attribute.name().toString());
-
-    out.append('=');
-
-    if (element->isURLAttribute(const_cast<Attribute*>(&attribute))) {
-        // We don't want to complete file:/// URLs because it may contain sensitive information
-        // about the user's system.
-        if (shouldResolveURLs() && !element->document()->url().isLocalFile())
-            appendQuotedURLAttributeValue(out, element->document()->completeURL(attribute.value()).string());
-        else
-            appendQuotedURLAttributeValue(out, attribute.value()); 
-    } else {
-        out.append('\"');
-        appendAttributeValue(out, attribute.value(), documentIsHTML);
-        out.append('\"');
-    }
-
-    if (!documentIsHTML && namespaces && shouldAddNamespaceAttribute(attribute, *namespaces))
-        appendNamespace(out, attribute.prefix(), attribute.namespaceURI(), *namespaces);
-}
-
-void MarkupAccumulator::appendCDATASection(Vector<UChar>& out, const String& section)
-{
-    // FIXME: CDATA content is not escaped, but XMLSerializer (and possibly other callers) should raise an exception if it includes "]]>".
-    append(out, "<![CDATA[");
-    append(out, section);
-    append(out, "]]>");
-}
-
-void MarkupAccumulator::appendStartMarkup(Vector<UChar>& result, const Node* node, Namespaces* namespaces)
-{
-    if (namespaces)
-        namespaces->checkConsistency();
-
-    switch (node->nodeType()) {
-    case Node::TEXT_NODE:
-        appendText(result, static_cast<Text*>(const_cast<Node*>(node)));
-        break;
-    case Node::COMMENT_NODE:
-        appendComment(result, static_cast<const Comment*>(node)->data());
-        break;
-    case Node::DOCUMENT_NODE:
-    case Node::DOCUMENT_FRAGMENT_NODE:
-        break;
-    case Node::DOCUMENT_TYPE_NODE:
-        appendDocumentType(result, static_cast<const DocumentType*>(node));
-        break;
-    case Node::PROCESSING_INSTRUCTION_NODE:
-        appendProcessingInstruction(result, static_cast<const ProcessingInstruction*>(node)->target(), static_cast<const ProcessingInstruction*>(node)->data());
-        break;
-    case Node::ELEMENT_NODE:
-        appendElement(result, static_cast<Element*>(const_cast<Node*>(node)), namespaces);
-        break;
-    case Node::CDATA_SECTION_NODE:
-        appendCDATASection(result, static_cast<const CDATASection*>(node)->data());
-        break;
-    case Node::ATTRIBUTE_NODE:
-    case Node::ENTITY_NODE:
-    case Node::ENTITY_REFERENCE_NODE:
-    case Node::NOTATION_NODE:
-    case Node::XPATH_NAMESPACE_NODE:
-        ASSERT_NOT_REACHED();
-        break;
-    }
-}
-
-static inline bool elementCannotHaveEndTag(const Node *node)
+bool elementCannotHaveEndTag(const Node* node)
 {
     if (!node->isHTMLElement())
         return false;
@@ -515,33 +105,6 @@ static inline bool elementCannotHaveEndTag(const Node *node)
     return static_cast<const HTMLElement*>(node)->ieForbidsInsertHTML();
 }
 
-// Rules of self-closure
-// 1. No elements in HTML documents use the self-closing syntax.
-// 2. Elements w/ children never self-close because they use a separate end tag.
-// 3. HTML elements which do not have a "forbidden" end tag will close with a separate end tag.
-// 4. Other elements self-close.
-bool MarkupAccumulator::shouldSelfClose(const Node* node)
-{
-    if (node->document()->isHTMLDocument())
-        return false;
-    if (node->hasChildNodes())
-        return false;
-    if (node->isHTMLElement() && !elementCannotHaveEndTag(node))
-        return false;
-    return true;
-}
-
-void MarkupAccumulator::appendEndMarkup(Vector<UChar>& result, const Node* node)
-{
-    if (!node->isElementNode() || shouldSelfClose(node) || (!node->hasChildNodes() && elementCannotHaveEndTag(node)))
-        return;
-
-    result.append('<');
-    result.append('/');
-    append(result, static_cast<const Element*>(node)->nodeNamePreservingCase());
-    result.append('>');
-}
-
 static void completeURLs(Node* node, const String& baseURL)
 {
     Vector<AttributeChange> changes;
diff --git a/WebCore/editing/markup.h b/WebCore/editing/markup.h
index dbf8b80..fc8e431 100644
--- a/WebCore/editing/markup.h
+++ b/WebCore/editing/markup.h
@@ -56,6 +56,9 @@ namespace WebCore {
     String createFullMarkup(const Range*);
 
     String urlToMarkup(const KURL&, const String& title);
+
+    // FIXME: Should this be better encapulated somewhere?
+    bool elementCannotHaveEndTag(const Node*);
 }
 
 #endif // markup_h

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list