Changeset 69880 in webkit


Ignore:
Timestamp:
Oct 15, 2010 2:34:48 PM (13 years ago)
Author:
abarth@webkit.org
Message:

2010-10-15 Adam Barth <abarth@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.
Location:
trunk/WebCore
Files:
2 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/Android.mk

    r69594 r69880  
    221221        editing/InsertTextCommand.cpp \
    222222        editing/JoinTextNodesCommand.cpp \
     223        editing/MarkupAccumulator.cpp \
    223224        editing/MergeIdenticalElementsCommand.cpp \
    224225        editing/ModifySelectionListLevel.cpp \
  • trunk/WebCore/CMakeLists.txt

    r69844 r69880  
    905905    editing/InsertTextCommand.cpp
    906906    editing/JoinTextNodesCommand.cpp
     907    editing/MarkupAccumulator.cpp
    907908    editing/MergeIdenticalElementsCommand.cpp
    908909    editing/ModifySelectionListLevel.cpp
  • trunk/WebCore/ChangeLog

    r69876 r69880  
     12010-10-15  Adam Barth  <abarth@webkit.org>
     2
     3        Reviewed by Eric Seidel.
     4
     5        Move MarkupAccumulator from markup.cpp to its own file
     6        https://bugs.webkit.org/show_bug.cgi?id=47734
     7
     8        This patch moves the MarkupAccumulator class into its own file.
     9        There's a lot of clean up left to do, but this patch is a step in the
     10        right direction.
     11
     12        No behavior change.
     13
     14        * Android.mk:
     15        * CMakeLists.txt:
     16        * GNUmakefile.am:
     17        * WebCore.gypi:
     18        * WebCore.pro:
     19        * WebCore.vcproj/WebCore.vcproj:
     20        * WebCore.xcodeproj/project.pbxproj:
     21        * editing/markup.cpp:
     22        (WebCore::elementCannotHaveEndTag):
     23        * editing/markup.h:
     24        * editing/MarkupAccumulator.h: Added.
     25        * editing/MarkupAccumulator.cpp: Added.
     26
    1272010-10-15  Ryosuke Niwa  <rniwa@webkit.org>
    228
  • trunk/WebCore/GNUmakefile.am

    r69844 r69880  
    13151315        WebCore/editing/markup.cpp \
    13161316        WebCore/editing/markup.h \
     1317        WebCore/editing/MarkupAccumulator.cpp \
     1318        WebCore/editing/MarkupAccumulator.h \
    13171319        WebCore/editing/MergeIdenticalElementsCommand.cpp \
    13181320        WebCore/editing/MergeIdenticalElementsCommand.h \
  • trunk/WebCore/WebCore.gypi

    r69844 r69880  
    13971397            'editing/JoinTextNodesCommand.cpp',
    13981398            'editing/JoinTextNodesCommand.h',
     1399            'editing/MarkupAccumulator.cpp',
     1400            'editing/MarkupAccumulator.h',
    13991401            'editing/MergeIdenticalElementsCommand.cpp',
    14001402            'editing/MergeIdenticalElementsCommand.h',
  • trunk/WebCore/WebCore.pro

    r69844 r69880  
    796796    editing/JoinTextNodesCommand.cpp \
    797797    editing/markup.cpp \
     798    editing/MarkupAccumulator.cpp \
    798799    editing/MergeIdenticalElementsCommand.cpp \
    799800    editing/ModifySelectionListLevel.cpp \
  • trunk/WebCore/WebCore.vcproj/WebCore.vcproj

    r69844 r69880  
    4665646656                        </File>
    4665746657                        <File
     46658                                RelativePath="..\editing\MarkupAccumulator.cpp"
     46659                                >
     46660                                <FileConfiguration
     46661                                        Name="Debug|Win32"
     46662                                        ExcludedFromBuild="true"
     46663                                        >
     46664                                        <Tool
     46665                                                Name="VCCLCompilerTool"
     46666                                        />
     46667                                </FileConfiguration>
     46668                                <FileConfiguration
     46669                                        Name="Release|Win32"
     46670                                        ExcludedFromBuild="true"
     46671                                        >
     46672                                        <Tool
     46673                                                Name="VCCLCompilerTool"
     46674                                        />
     46675                                </FileConfiguration>
     46676                                <FileConfiguration
     46677                                        Name="Debug_Internal|Win32"
     46678                                        ExcludedFromBuild="true"
     46679                                        >
     46680                                        <Tool
     46681                                                Name="VCCLCompilerTool"
     46682                                        />
     46683                                </FileConfiguration>
     46684                                <FileConfiguration
     46685                                        Name="Debug_Cairo|Win32"
     46686                                        ExcludedFromBuild="true"
     46687                                        >
     46688                                        <Tool
     46689                                                Name="VCCLCompilerTool"
     46690                                        />
     46691                                </FileConfiguration>
     46692                                <FileConfiguration
     46693                                        Name="Release_Cairo|Win32"
     46694                                        ExcludedFromBuild="true"
     46695                                        >
     46696                                        <Tool
     46697                                                Name="VCCLCompilerTool"
     46698                                        />
     46699                                </FileConfiguration>
     46700                                <FileConfiguration
     46701                                        Name="Debug_All|Win32"
     46702                                        ExcludedFromBuild="true"
     46703                                        >
     46704                                        <Tool
     46705                                                Name="VCCLCompilerTool"
     46706                                        />
     46707                                </FileConfiguration>
     46708                        </File>
     46709                        <File
     46710                                RelativePath="..\editing\MarkupAccumulator.h"
     46711                                >
     46712                        </File>
     46713                        <File
    4665846714                                RelativePath="..\editing\MergeIdenticalElementsCommand.cpp"
    4665946715                                >
  • trunk/WebCore/WebCore.xcodeproj/project.pbxproj

    r69862 r69880  
    28622862                97205ABB1239292700B17380 /* PluginDocument.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 97205AB91239292700B17380 /* PluginDocument.cpp */; };
    28632863                97205ABC1239292700B17380 /* PluginDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = 97205ABA1239292700B17380 /* PluginDocument.h */; };
     2864                9728C3131268E4390041E89B /* MarkupAccumulator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9728C3111268E4390041E89B /* MarkupAccumulator.cpp */; };
     2865                9728C3141268E4390041E89B /* MarkupAccumulator.h in Headers */ = {isa = PBXBuildFile; fileRef = 9728C3121268E4390041E89B /* MarkupAccumulator.h */; };
    28642866                973889A0116EA9DC00ADF313 /* DocumentWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9738899E116EA9DC00ADF313 /* DocumentWriter.cpp */; };
    28652867                973889A1116EA9DC00ADF313 /* DocumentWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = 9738899F116EA9DC00ADF313 /* DocumentWriter.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    88978899                97205AB91239292700B17380 /* PluginDocument.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PluginDocument.cpp; sourceTree = "<group>"; };
    88988900                97205ABA1239292700B17380 /* PluginDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PluginDocument.h; sourceTree = "<group>"; };
     8901                9728C3111268E4390041E89B /* MarkupAccumulator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MarkupAccumulator.cpp; sourceTree = "<group>"; };
     8902                9728C3121268E4390041E89B /* MarkupAccumulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkupAccumulator.h; sourceTree = "<group>"; };
    88998903                9738899E116EA9DC00ADF313 /* DocumentWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentWriter.cpp; sourceTree = "<group>"; };
    89008904                9738899F116EA9DC00ADF313 /* DocumentWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentWriter.h; sourceTree = "<group>"; };
     
    1440714411                                93309DA8099E64910056E581 /* markup.cpp */,
    1440814412                                93309DA9099E64910056E581 /* markup.h */,
     14413                                9728C3111268E4390041E89B /* MarkupAccumulator.cpp */,
     14414                                9728C3121268E4390041E89B /* MarkupAccumulator.h */,
    1440914415                                93309DAA099E64910056E581 /* MergeIdenticalElementsCommand.cpp */,
    1441014416                                93309DAB099E64910056E581 /* MergeIdenticalElementsCommand.h */,
     
    2107721083                                97DD4D870FDF4D6E00ECF9A4 /* XSSAuditor.h in Headers */,
    2107821084                                4FA3B90B125CD12200300BAD /* InspectorState.h in Headers */,
     21085                                9728C3141268E4390041E89B /* MarkupAccumulator.h in Headers */,
    2107921086                        );
    2108021087                        runOnlyForDeploymentPostprocessing = 0;
     
    2113621143                        buildConfigurationList = 149C284308902B11008A9EFC /* Build configuration list for PBXProject "WebCore" */;
    2113721144                        compatibilityVersion = "Xcode 2.4";
    21138                         developmentRegion = English;
    2113921145                        hasScannedForEncodings = 1;
    2114021146                        knownRegions = (
     
    2362523631                                97DD4D860FDF4D6E00ECF9A4 /* XSSAuditor.cpp in Sources */,
    2362623632                                4FA3B90A125CD12200300BAD /* InspectorState.cpp in Sources */,
     23633                                9728C3131268E4390041E89B /* MarkupAccumulator.cpp in Sources */,
    2362723634                        );
    2362823635                        runOnlyForDeploymentPostprocessing = 0;
  • trunk/WebCore/editing/EditingAllInOne.cpp

    r68972 r69880  
    4949#include <InsertTextCommand.cpp>
    5050#include <JoinTextNodesCommand.cpp>
     51#include <MarkupAccumulator.cpp>
    5152#include <MergeIdenticalElementsCommand.cpp>
    5253#include <ModifySelectionListLevel.cpp>
  • trunk/WebCore/editing/markup.cpp

    r69868 r69880  
    5353#include "KURL.h"
    5454#include "Logging.h"
     55#include "MarkupAccumulator.h"
    5556#include "ProcessingInstruction.h"
    5657#include "Range.h"
     
    9293    String m_value;
    9394};
    94    
    95 enum EntityMask {
    96     EntityAmp = 0x0001,
    97     EntityLt = 0x0002,
    98     EntityGt = 0x0004,
    99     EntityQuot = 0x0008,
    100     EntityNbsp = 0x0010,
    101 
    102     // Non-breaking space needs to be escaped in innerHTML for compatibility reason. See http://trac.webkit.org/changeset/32879
    103     // However, we cannot do this in a XML document because it does not have the entity reference defined (See the bug 19215).
    104     EntityMaskInCDATA = 0,
    105     EntityMaskInPCDATA = EntityAmp | EntityLt | EntityGt,
    106     EntityMaskInHTMLPCDATA = EntityMaskInPCDATA | EntityNbsp,
    107     EntityMaskInAttributeValue = EntityAmp | EntityLt | EntityGt | EntityQuot,
    108     EntityMaskInHTMLAttributeValue = EntityMaskInAttributeValue | EntityNbsp,
    109 };
    110 
    111 struct EntityDescription {
    112     UChar entity;
    113     const String& reference;
    114     EntityMask mask;
    115 };
    116 
    117 static void appendCharactersReplacingEntities(Vector<UChar>& out, const UChar* content, size_t length, EntityMask entityMask)
    118 {
    119     DEFINE_STATIC_LOCAL(const String, ampReference, ("&amp;"));
    120     DEFINE_STATIC_LOCAL(const String, ltReference, ("&lt;"));
    121     DEFINE_STATIC_LOCAL(const String, gtReference, ("&gt;"));
    122     DEFINE_STATIC_LOCAL(const String, quotReference, ("&quot;"));
    123     DEFINE_STATIC_LOCAL(const String, nbspReference, ("&nbsp;"));
    124 
    125     static const EntityDescription entityMaps[] = {
    126         { '&', ampReference, EntityAmp },
    127         { '<', ltReference, EntityLt },
    128         { '>', gtReference, EntityGt },
    129         { '"', quotReference, EntityQuot },
    130         { noBreakSpace, nbspReference, EntityNbsp },
    131     };
    132 
    133     size_t positionAfterLastEntity = 0;
    134     for (size_t i = 0; i < length; i++) {
    135         for (size_t m = 0; m < sizeof(entityMaps) / sizeof(EntityDescription); m++) {
    136             if (content[i] == entityMaps[m].entity && entityMaps[m].mask & entityMask) {
    137                 out.append(content + positionAfterLastEntity, i - positionAfterLastEntity);
    138                 append(out, entityMaps[m].reference);
    139                 positionAfterLastEntity = i + 1;
    140                 break;
    141             }
    142         }
    143     }
    144     out.append(content + positionAfterLastEntity, length - positionAfterLastEntity);
    145 }
    146 
    147 typedef HashMap<AtomicStringImpl*, AtomicStringImpl*> Namespaces;
    148 
    149 class MarkupAccumulator {
    150 public:
    151     MarkupAccumulator(Vector<Node*>* nodes, EAbsoluteURLs shouldResolveURLs, const Range* range = 0)
    152         : m_nodes(nodes)
    153         , m_range(range)
    154         , m_shouldResolveURLs(shouldResolveURLs)
    155     {
    156     }
    157     virtual ~MarkupAccumulator() {}
    158     void appendString(const String&);
    159     void appendStartTag(Node*, Namespaces* = 0);
    160     void appendEndTag(Node*);
    161     virtual String takeResults();
    162 
    163 protected:
    164     void appendAttributeValue(Vector<UChar>& result, const String& attribute, bool documentIsHTML);
    165     void appendQuotedURLAttributeValue(Vector<UChar>& result, const String& urlString);
    166     void appendNodeValue(Vector<UChar>& out, const Node*, const Range*, EntityMask);
    167     bool shouldAddNamespaceElement(const Element*);
    168     bool shouldAddNamespaceAttribute(const Attribute&, Namespaces&);
    169     void appendNamespace(Vector<UChar>& result, const AtomicString& prefix, const AtomicString& namespaceURI, Namespaces&);
    170     EntityMask entityMaskForText(Text* text) const;
    171     virtual void appendText(Vector<UChar>& out, Text*);
    172     void appendComment(Vector<UChar>& out, const String& comment);
    173     void appendDocumentType(Vector<UChar>& result, const DocumentType*);
    174     void appendProcessingInstruction(Vector<UChar>& out, const String& target, const String& data);
    175     virtual void appendElement(Vector<UChar>& out, Element*, Namespaces*);
    176     void appendOpenTag(Vector<UChar>& out, Element* element, Namespaces*);
    177     void appendCloseTag(Vector<UChar>& out, Element* element);
    178     void appendAttribute(Vector<UChar>& out, Element* element, const Attribute&, Namespaces*);
    179     void appendCDATASection(Vector<UChar>& out, const String& section);
    180     void appendStartMarkup(Vector<UChar>& result, const Node*, Namespaces*);
    181     bool shouldSelfClose(const Node*);
    182     void appendEndMarkup(Vector<UChar>& result, const Node*);
    183 
    184     bool shouldResolveURLs() { return m_shouldResolveURLs == AbsoluteURLs; }
    185 
    186     Vector<Node*>* const m_nodes;
    187     const Range* const m_range;
    188     Vector<String> m_succeedingMarkup;
    189 
    190 private:
    191     const bool m_shouldResolveURLs;
    192 };
    193 
    194 void MarkupAccumulator::appendString(const String& string)
    195 {
    196     m_succeedingMarkup.append(string);
    197 }
    198 
    199 void MarkupAccumulator::appendStartTag(Node* node, Namespaces* namespaces)
    200 {
    201     Vector<UChar> markup;
    202     appendStartMarkup(markup, node, namespaces);
    203     m_succeedingMarkup.append(String::adopt(markup));
    204     if (m_nodes)
    205         m_nodes->append(node);
    206 }
    207 
    208 void MarkupAccumulator::appendEndTag(Node* node)
    209 {
    210     Vector<UChar> markup;
    211     appendEndMarkup(markup, node);
    212     m_succeedingMarkup.append(String::adopt(markup));
    213 }
    214 
    215 // FIXME: This is a very inefficient way of accumulating the markup.
    216 // We're converting results of appendStartMarkup and appendEndMarkup from Vector<UChar> to String
    217 // and then back to Vector<UChar> and again to String here.
    218 String MarkupAccumulator::takeResults()
    219 {
    220     size_t length = 0;
    221 
    222     size_t postCount = m_succeedingMarkup.size();
    223     for (size_t i = 0; i < postCount; ++i)
    224         length += m_succeedingMarkup[i].length();
    225 
    226     Vector<UChar> result;
    227     result.reserveInitialCapacity(length);
    228 
    229     for (size_t i = 0; i < postCount; ++i)
    230         append(result, m_succeedingMarkup[i]);
    231 
    232     return String::adopt(result);
    233 }
    234 
    235 void MarkupAccumulator::appendAttributeValue(Vector<UChar>& result, const String& attribute, bool documentIsHTML)
    236 {
    237     appendCharactersReplacingEntities(result, attribute.characters(), attribute.length(),
    238         documentIsHTML ? EntityMaskInHTMLAttributeValue : EntityMaskInAttributeValue);
    239 }
    240 
    241 void MarkupAccumulator::appendQuotedURLAttributeValue(Vector<UChar>& result, const String& urlString)
    242 {
    243     UChar quoteChar = '\"';
    244     String strippedURLString = urlString.stripWhiteSpace();
    245     if (protocolIsJavaScript(strippedURLString)) {
    246         // minimal escaping for javascript urls
    247         if (strippedURLString.contains('"')) {
    248             if (strippedURLString.contains('\''))
    249                 strippedURLString.replace('\"', "&quot;");
    250             else
    251                 quoteChar = '\'';
    252         }
    253         result.append(quoteChar);
    254         append(result, strippedURLString);
    255         result.append(quoteChar);
    256         return;
    257     }
    258 
    259     // FIXME: This does not fully match other browsers. Firefox percent-escapes non-ASCII characters for innerHTML.
    260     result.append(quoteChar);
    261     appendAttributeValue(result, urlString, false);
    262     result.append(quoteChar);
    263 }
    264 
    265 void MarkupAccumulator::appendNodeValue(Vector<UChar>& out, const Node* node, const Range* range, EntityMask entityMask)
    266 {
    267     String str = node->nodeValue();
    268     const UChar* characters = str.characters();
    269     size_t length = str.length();
    270 
    271     if (range) {
    272         ExceptionCode ec;
    273         if (node == range->endContainer(ec))
    274             length = range->endOffset(ec);
    275         if (node == range->startContainer(ec)) {
    276             size_t start = range->startOffset(ec);
    277             characters += start;
    278             length -= start;
    279         }
    280     }
    281 
    282     appendCharactersReplacingEntities(out, characters, length, entityMask);
    283 }
    284 
    285 bool MarkupAccumulator::shouldAddNamespaceElement(const Element* element)
    286 {
    287     // Don't add namespace attribute if it is already defined for this elem.
    288     const AtomicString& prefix = element->prefix();
    289     AtomicString attr = !prefix.isEmpty() ? "xmlns:" + prefix : "xmlns";
    290     return !element->hasAttribute(attr);
    291 }
    292 
    293 bool MarkupAccumulator::shouldAddNamespaceAttribute(const Attribute& attribute, Namespaces& namespaces)
    294 {
    295     namespaces.checkConsistency();
    296 
    297     // Don't add namespace attributes twice
    298     if (attribute.name() == XMLNSNames::xmlnsAttr) {
    299         namespaces.set(emptyAtom.impl(), attribute.value().impl());
    300         return false;
    301     }
    302    
    303     QualifiedName xmlnsPrefixAttr(xmlnsAtom, attribute.localName(), XMLNSNames::xmlnsNamespaceURI);
    304     if (attribute.name() == xmlnsPrefixAttr) {
    305         namespaces.set(attribute.localName().impl(), attribute.value().impl());
    306         return false;
    307     }
    308    
    309     return true;
    310 }
    311 
    312 void MarkupAccumulator::appendNamespace(Vector<UChar>& result, const AtomicString& prefix, const AtomicString& namespaceURI, Namespaces& namespaces)
    313 {
    314     namespaces.checkConsistency();
    315     if (namespaceURI.isEmpty())
    316         return;
    317        
    318     // Use emptyAtoms's impl() for both null and empty strings since the HashMap can't handle 0 as a key
    319     AtomicStringImpl* pre = prefix.isEmpty() ? emptyAtom.impl() : prefix.impl();
    320     AtomicStringImpl* foundNS = namespaces.get(pre);
    321     if (foundNS != namespaceURI.impl()) {
    322         namespaces.set(pre, namespaceURI.impl());
    323         result.append(' ');
    324         append(result, xmlnsAtom.string());
    325         if (!prefix.isEmpty()) {
    326             result.append(':');
    327             append(result, prefix);
    328         }
    329 
    330         result.append('=');
    331         result.append('"');
    332         appendAttributeValue(result, namespaceURI, false);
    333         result.append('"');
    334     }
    335 }
    336 
    337 EntityMask MarkupAccumulator::entityMaskForText(Text* text) const
    338 {
    339     const QualifiedName* parentName = 0;
    340     if (text->parentElement())
    341         parentName = &static_cast<Element*>(text->parentElement())->tagQName();
    342    
    343     if (parentName && (*parentName == scriptTag || *parentName == styleTag || *parentName == xmpTag))
    344         return EntityMaskInCDATA;
    345 
    346     return text->document()->isHTMLDocument() ? EntityMaskInHTMLPCDATA : EntityMaskInPCDATA;
    347 }
    348 
    349 void MarkupAccumulator::appendText(Vector<UChar>& out, Text* text)
    350 {
    351     appendNodeValue(out, text, m_range, entityMaskForText(text));
    352 }
    353 
    354 void MarkupAccumulator::appendComment(Vector<UChar>& out, const String& comment)
    355 {
    356     // FIXME: Comment content is not escaped, but XMLSerializer (and possibly other callers) should raise an exception if it includes "-->".
    357     append(out, "<!--");
    358     append(out, comment);
    359     append(out, "-->");
    360 }
    361 
    362 void MarkupAccumulator::appendDocumentType(Vector<UChar>& result, const DocumentType* n)
    363 {
    364     if (n->name().isEmpty())
    365         return;
    366 
    367     append(result, "<!DOCTYPE ");
    368     append(result, n->name());
    369     if (!n->publicId().isEmpty()) {
    370         append(result, " PUBLIC \"");
    371         append(result, n->publicId());
    372         append(result, "\"");
    373         if (!n->systemId().isEmpty()) {
    374             append(result, " \"");
    375             append(result, n->systemId());
    376             append(result, "\"");
    377         }
    378     } else if (!n->systemId().isEmpty()) {
    379         append(result, " SYSTEM \"");
    380         append(result, n->systemId());
    381         append(result, "\"");
    382     }
    383     if (!n->internalSubset().isEmpty()) {
    384         append(result, " [");
    385         append(result, n->internalSubset());
    386         append(result, "]");
    387     }
    388     append(result, ">");
    389 }
    390 
    391 void MarkupAccumulator::appendProcessingInstruction(Vector<UChar>& out, const String& target, const String& data)
    392 {
    393     // FIXME: PI data is not escaped, but XMLSerializer (and possibly other callers) this should raise an exception if it includes "?>".
    394     append(out, "<?");
    395     append(out, target);
    396     append(out, " ");
    397     append(out, data);
    398     append(out, "?>");
    399 }
    400 
    401 void MarkupAccumulator::appendElement(Vector<UChar>& out, Element* element, Namespaces* namespaces)
    402 {
    403     appendOpenTag(out, element, namespaces);
    404 
    405     NamedNodeMap* attributes = element->attributes();
    406     unsigned length = attributes->length();
    407     for (unsigned int i = 0; i < length; i++)
    408         appendAttribute(out, element, *attributes->attributeItem(i), namespaces);
    409 
    410     appendCloseTag(out, element);
    411 }
    412 
    413 void MarkupAccumulator::appendOpenTag(Vector<UChar>& out, Element* element, Namespaces* namespaces)
    414 {
    415     out.append('<');
    416     append(out, element->nodeNamePreservingCase());
    417     if (!element->document()->isHTMLDocument() && namespaces && shouldAddNamespaceElement(element))
    418         appendNamespace(out, element->prefix(), element->namespaceURI(), *namespaces);   
    419 }
    420 
    421 void MarkupAccumulator::appendCloseTag(Vector<UChar>& out, Element* element)
    422 {
    423     if (shouldSelfClose(element)) {
    424         if (element->isHTMLElement())
    425             out.append(' '); // XHTML 1.0 <-> HTML compatibility.
    426         out.append('/');
    427     }
    428     out.append('>');
    429 }
    430 
    431 void MarkupAccumulator::appendAttribute(Vector<UChar>& out, Element* element, const Attribute& attribute, Namespaces* namespaces)
    432 {
    433     bool documentIsHTML = element->document()->isHTMLDocument();
    434 
    435     out.append(' ');
    436 
    437     if (documentIsHTML)
    438         append(out, attribute.name().localName());
    439     else
    440         append(out, attribute.name().toString());
    441 
    442     out.append('=');
    443 
    444     if (element->isURLAttribute(const_cast<Attribute*>(&attribute))) {
    445         // We don't want to complete file:/// URLs because it may contain sensitive information
    446         // about the user's system.
    447         if (shouldResolveURLs() && !element->document()->url().isLocalFile())
    448             appendQuotedURLAttributeValue(out, element->document()->completeURL(attribute.value()).string());
    449         else
    450             appendQuotedURLAttributeValue(out, attribute.value());
    451     } else {
    452         out.append('\"');
    453         appendAttributeValue(out, attribute.value(), documentIsHTML);
    454         out.append('\"');
    455     }
    456 
    457     if (!documentIsHTML && namespaces && shouldAddNamespaceAttribute(attribute, *namespaces))
    458         appendNamespace(out, attribute.prefix(), attribute.namespaceURI(), *namespaces);
    459 }
    460 
    461 void MarkupAccumulator::appendCDATASection(Vector<UChar>& out, const String& section)
    462 {
    463     // FIXME: CDATA content is not escaped, but XMLSerializer (and possibly other callers) should raise an exception if it includes "]]>".
    464     append(out, "<![CDATA[");
    465     append(out, section);
    466     append(out, "]]>");
    467 }
    468 
    469 void MarkupAccumulator::appendStartMarkup(Vector<UChar>& result, const Node* node, Namespaces* namespaces)
    470 {
    471     if (namespaces)
    472         namespaces->checkConsistency();
    473 
    474     switch (node->nodeType()) {
    475     case Node::TEXT_NODE:
    476         appendText(result, static_cast<Text*>(const_cast<Node*>(node)));
    477         break;
    478     case Node::COMMENT_NODE:
    479         appendComment(result, static_cast<const Comment*>(node)->data());
    480         break;
    481     case Node::DOCUMENT_NODE:
    482     case Node::DOCUMENT_FRAGMENT_NODE:
    483         break;
    484     case Node::DOCUMENT_TYPE_NODE:
    485         appendDocumentType(result, static_cast<const DocumentType*>(node));
    486         break;
    487     case Node::PROCESSING_INSTRUCTION_NODE:
    488         appendProcessingInstruction(result, static_cast<const ProcessingInstruction*>(node)->target(), static_cast<const ProcessingInstruction*>(node)->data());
    489         break;
    490     case Node::ELEMENT_NODE:
    491         appendElement(result, static_cast<Element*>(const_cast<Node*>(node)), namespaces);
    492         break;
    493     case Node::CDATA_SECTION_NODE:
    494         appendCDATASection(result, static_cast<const CDATASection*>(node)->data());
    495         break;
    496     case Node::ATTRIBUTE_NODE:
    497     case Node::ENTITY_NODE:
    498     case Node::ENTITY_REFERENCE_NODE:
    499     case Node::NOTATION_NODE:
    500     case Node::XPATH_NAMESPACE_NODE:
    501         ASSERT_NOT_REACHED();
    502         break;
    503     }
    504 }
    505 
    506 static inline bool elementCannotHaveEndTag(const Node *node)
     95
     96bool elementCannotHaveEndTag(const Node* node)
    50797{
    50898    if (!node->isHTMLElement())
     
    514104    // which elements should be serialized w/o end tags.
    515105    return static_cast<const HTMLElement*>(node)->ieForbidsInsertHTML();
    516 }
    517 
    518 // Rules of self-closure
    519 // 1. No elements in HTML documents use the self-closing syntax.
    520 // 2. Elements w/ children never self-close because they use a separate end tag.
    521 // 3. HTML elements which do not have a "forbidden" end tag will close with a separate end tag.
    522 // 4. Other elements self-close.
    523 bool MarkupAccumulator::shouldSelfClose(const Node* node)
    524 {
    525     if (node->document()->isHTMLDocument())
    526         return false;
    527     if (node->hasChildNodes())
    528         return false;
    529     if (node->isHTMLElement() && !elementCannotHaveEndTag(node))
    530         return false;
    531     return true;
    532 }
    533 
    534 void MarkupAccumulator::appendEndMarkup(Vector<UChar>& result, const Node* node)
    535 {
    536     if (!node->isElementNode() || shouldSelfClose(node) || (!node->hasChildNodes() && elementCannotHaveEndTag(node)))
    537         return;
    538 
    539     result.append('<');
    540     result.append('/');
    541     append(result, static_cast<const Element*>(node)->nodeNamePreservingCase());
    542     result.append('>');
    543106}
    544107
  • trunk/WebCore/editing/markup.h

    r65021 r69880  
    5757
    5858    String urlToMarkup(const KURL&, const String& title);
     59
     60    // FIXME: Should this be better encapulated somewhere?
     61    bool elementCannotHaveEndTag(const Node*);
    5962}
    6063
Note: See TracChangeset for help on using the changeset viewer.