Changeset 69880 in webkit
- Timestamp:
- Oct 15, 2010 2:34:48 PM (13 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 2 added
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/Android.mk
r69594 r69880 221 221 editing/InsertTextCommand.cpp \ 222 222 editing/JoinTextNodesCommand.cpp \ 223 editing/MarkupAccumulator.cpp \ 223 224 editing/MergeIdenticalElementsCommand.cpp \ 224 225 editing/ModifySelectionListLevel.cpp \ -
trunk/WebCore/CMakeLists.txt
r69844 r69880 905 905 editing/InsertTextCommand.cpp 906 906 editing/JoinTextNodesCommand.cpp 907 editing/MarkupAccumulator.cpp 907 908 editing/MergeIdenticalElementsCommand.cpp 908 909 editing/ModifySelectionListLevel.cpp -
trunk/WebCore/ChangeLog
r69876 r69880 1 2010-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 1 27 2010-10-15 Ryosuke Niwa <rniwa@webkit.org> 2 28 -
trunk/WebCore/GNUmakefile.am
r69844 r69880 1315 1315 WebCore/editing/markup.cpp \ 1316 1316 WebCore/editing/markup.h \ 1317 WebCore/editing/MarkupAccumulator.cpp \ 1318 WebCore/editing/MarkupAccumulator.h \ 1317 1319 WebCore/editing/MergeIdenticalElementsCommand.cpp \ 1318 1320 WebCore/editing/MergeIdenticalElementsCommand.h \ -
trunk/WebCore/WebCore.gypi
r69844 r69880 1397 1397 'editing/JoinTextNodesCommand.cpp', 1398 1398 'editing/JoinTextNodesCommand.h', 1399 'editing/MarkupAccumulator.cpp', 1400 'editing/MarkupAccumulator.h', 1399 1401 'editing/MergeIdenticalElementsCommand.cpp', 1400 1402 'editing/MergeIdenticalElementsCommand.h', -
trunk/WebCore/WebCore.pro
r69844 r69880 796 796 editing/JoinTextNodesCommand.cpp \ 797 797 editing/markup.cpp \ 798 editing/MarkupAccumulator.cpp \ 798 799 editing/MergeIdenticalElementsCommand.cpp \ 799 800 editing/ModifySelectionListLevel.cpp \ -
trunk/WebCore/WebCore.vcproj/WebCore.vcproj
r69844 r69880 46656 46656 </File> 46657 46657 <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 46658 46714 RelativePath="..\editing\MergeIdenticalElementsCommand.cpp" 46659 46715 > -
trunk/WebCore/WebCore.xcodeproj/project.pbxproj
r69862 r69880 2862 2862 97205ABB1239292700B17380 /* PluginDocument.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 97205AB91239292700B17380 /* PluginDocument.cpp */; }; 2863 2863 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 */; }; 2864 2866 973889A0116EA9DC00ADF313 /* DocumentWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9738899E116EA9DC00ADF313 /* DocumentWriter.cpp */; }; 2865 2867 973889A1116EA9DC00ADF313 /* DocumentWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = 9738899F116EA9DC00ADF313 /* DocumentWriter.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 8897 8899 97205AB91239292700B17380 /* PluginDocument.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PluginDocument.cpp; sourceTree = "<group>"; }; 8898 8900 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>"; }; 8899 8903 9738899E116EA9DC00ADF313 /* DocumentWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentWriter.cpp; sourceTree = "<group>"; }; 8900 8904 9738899F116EA9DC00ADF313 /* DocumentWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentWriter.h; sourceTree = "<group>"; }; … … 14407 14411 93309DA8099E64910056E581 /* markup.cpp */, 14408 14412 93309DA9099E64910056E581 /* markup.h */, 14413 9728C3111268E4390041E89B /* MarkupAccumulator.cpp */, 14414 9728C3121268E4390041E89B /* MarkupAccumulator.h */, 14409 14415 93309DAA099E64910056E581 /* MergeIdenticalElementsCommand.cpp */, 14410 14416 93309DAB099E64910056E581 /* MergeIdenticalElementsCommand.h */, … … 21077 21083 97DD4D870FDF4D6E00ECF9A4 /* XSSAuditor.h in Headers */, 21078 21084 4FA3B90B125CD12200300BAD /* InspectorState.h in Headers */, 21085 9728C3141268E4390041E89B /* MarkupAccumulator.h in Headers */, 21079 21086 ); 21080 21087 runOnlyForDeploymentPostprocessing = 0; … … 21136 21143 buildConfigurationList = 149C284308902B11008A9EFC /* Build configuration list for PBXProject "WebCore" */; 21137 21144 compatibilityVersion = "Xcode 2.4"; 21138 developmentRegion = English;21139 21145 hasScannedForEncodings = 1; 21140 21146 knownRegions = ( … … 23625 23631 97DD4D860FDF4D6E00ECF9A4 /* XSSAuditor.cpp in Sources */, 23626 23632 4FA3B90A125CD12200300BAD /* InspectorState.cpp in Sources */, 23633 9728C3131268E4390041E89B /* MarkupAccumulator.cpp in Sources */, 23627 23634 ); 23628 23635 runOnlyForDeploymentPostprocessing = 0; -
trunk/WebCore/editing/EditingAllInOne.cpp
r68972 r69880 49 49 #include <InsertTextCommand.cpp> 50 50 #include <JoinTextNodesCommand.cpp> 51 #include <MarkupAccumulator.cpp> 51 52 #include <MergeIdenticalElementsCommand.cpp> 52 53 #include <ModifySelectionListLevel.cpp> -
trunk/WebCore/editing/markup.cpp
r69868 r69880 53 53 #include "KURL.h" 54 54 #include "Logging.h" 55 #include "MarkupAccumulator.h" 55 56 #include "ProcessingInstruction.h" 56 57 #include "Range.h" … … 92 93 String m_value; 93 94 }; 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, ("&")); 120 DEFINE_STATIC_LOCAL(const String, ltReference, ("<")); 121 DEFINE_STATIC_LOCAL(const String, gtReference, (">")); 122 DEFINE_STATIC_LOCAL(const String, quotReference, (""")); 123 DEFINE_STATIC_LOCAL(const String, nbspReference, (" ")); 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('\"', """); 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 96 bool elementCannotHaveEndTag(const Node* node) 507 97 { 508 98 if (!node->isHTMLElement()) … … 514 104 // which elements should be serialized w/o end tags. 515 105 return static_cast<const HTMLElement*>(node)->ieForbidsInsertHTML(); 516 }517 518 // Rules of self-closure519 // 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('>');543 106 } 544 107 -
trunk/WebCore/editing/markup.h
r65021 r69880 57 57 58 58 String urlToMarkup(const KURL&, const String& title); 59 60 // FIXME: Should this be better encapulated somewhere? 61 bool elementCannotHaveEndTag(const Node*); 59 62 } 60 63
Note: See TracChangeset
for help on using the changeset viewer.