[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, ("&"));
+ DEFINE_STATIC_LOCAL(const String, ltReference, ("<"));
+ DEFINE_STATIC_LOCAL(const String, gtReference, (">"));
+ DEFINE_STATIC_LOCAL(const String, quotReference, ("""));
+ DEFINE_STATIC_LOCAL(const String, nbspReference, (" "));
+
+ 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('\"', """);
+ 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, ("&"));
- DEFINE_STATIC_LOCAL(const String, ltReference, ("<"));
- DEFINE_STATIC_LOCAL(const String, gtReference, (">"));
- DEFINE_STATIC_LOCAL(const String, quotReference, ("""));
- DEFINE_STATIC_LOCAL(const String, nbspReference, (" "));
-
- 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('\"', """);
- 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