OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2012 Apple Inc. All rights
reserved. | |
3 * Copyright (C) 2009, 2010 Google Inc. All rights reserved. | |
4 * | |
5 * Redistribution and use in source and binary forms, with or without | |
6 * modification, are permitted provided that the following conditions | |
7 * are met: | |
8 * 1. Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * 2. Redistributions in binary form must reproduce the above copyright | |
11 * notice, this list of conditions and the following disclaimer in the | |
12 * documentation and/or other materials provided with the distribution. | |
13 * | |
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
18 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
20 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
25 */ | |
26 | |
27 #include "config.h" | |
28 #include "core/editing/MarkupAccumulator.h" | |
29 | |
30 #include "core/HTMLNames.h" | |
31 #include "core/XLinkNames.h" | |
32 #include "core/XMLNSNames.h" | |
33 #include "core/XMLNames.h" | |
34 #include "core/dom/CDATASection.h" | |
35 #include "core/dom/Comment.h" | |
36 #include "core/dom/Document.h" | |
37 #include "core/dom/DocumentFragment.h" | |
38 #include "core/dom/DocumentType.h" | |
39 #include "core/dom/ProcessingInstruction.h" | |
40 #include "core/editing/Editor.h" | |
41 #include "core/html/HTMLElement.h" | |
42 #include "core/html/HTMLTemplateElement.h" | |
43 #include "platform/weborigin/KURL.h" | |
44 #include "wtf/text/CharacterNames.h" | |
45 | |
46 namespace blink { | |
47 | |
48 using namespace HTMLNames; | |
49 | |
50 MarkupAccumulator::MarkupAccumulator(EAbsoluteURLs resolveUrlsMethod, Serializat
ionType serializationType) | |
51 : m_formatter(resolveUrlsMethod, serializationType) | |
52 { | |
53 } | |
54 | |
55 MarkupAccumulator::~MarkupAccumulator() | |
56 { | |
57 } | |
58 | |
59 void MarkupAccumulator::appendString(const String& string) | |
60 { | |
61 m_markup.append(string); | |
62 } | |
63 | |
64 void MarkupAccumulator::appendStartTag(Node& node, Namespaces* namespaces) | |
65 { | |
66 appendStartMarkup(m_markup, node, namespaces); | |
67 } | |
68 | |
69 void MarkupAccumulator::appendEndTag(const Element& element) | |
70 { | |
71 appendEndMarkup(m_markup, element); | |
72 } | |
73 | |
74 void MarkupAccumulator::appendStartMarkup(StringBuilder& result, Node& node, Nam
espaces* namespaces) | |
75 { | |
76 switch (node.nodeType()) { | |
77 case Node::TEXT_NODE: | |
78 appendText(result, toText(node)); | |
79 break; | |
80 case Node::ELEMENT_NODE: | |
81 appendElement(result, toElement(node), namespaces); | |
82 break; | |
83 default: | |
84 m_formatter.appendStartMarkup(result, node, namespaces); | |
85 break; | |
86 } | |
87 } | |
88 | |
89 static bool elementCannotHaveEndTag(const Node& node) | |
90 { | |
91 if (!node.isHTMLElement()) | |
92 return false; | |
93 | |
94 // FIXME: ieForbidsInsertHTML may not be the right function to call here | |
95 // ieForbidsInsertHTML is used to disallow setting innerHTML/outerHTML | |
96 // or createContextualFragment. It does not necessarily align with | |
97 // which elements should be serialized w/o end tags. | |
98 return toHTMLElement(node).ieForbidsInsertHTML(); | |
99 } | |
100 | |
101 void MarkupAccumulator::appendEndMarkup(StringBuilder& result, const Element& el
ement) | |
102 { | |
103 m_formatter.appendEndMarkup(result, element); | |
104 } | |
105 | |
106 void MarkupAccumulator::appendCustomAttributes(StringBuilder&, const Element&, N
amespaces*) | |
107 { | |
108 } | |
109 | |
110 void MarkupAccumulator::appendText(StringBuilder& result, Text& text) | |
111 { | |
112 m_formatter.appendText(result, text); | |
113 } | |
114 | |
115 bool MarkupAccumulator::shouldIgnoreAttribute(const Attribute& attribute) | |
116 { | |
117 return false; | |
118 } | |
119 | |
120 void MarkupAccumulator::appendElement(StringBuilder& result, Element& element, N
amespaces* namespaces) | |
121 { | |
122 appendOpenTag(result, element, namespaces); | |
123 | |
124 AttributeCollection attributes = element.attributes(); | |
125 for (const auto& attribute : attributes) { | |
126 if (!shouldIgnoreAttribute(attribute)) | |
127 appendAttribute(result, element, attribute, namespaces); | |
128 } | |
129 | |
130 // Give an opportunity to subclasses to add their own attributes. | |
131 appendCustomAttributes(result, element, namespaces); | |
132 | |
133 appendCloseTag(result, element); | |
134 } | |
135 | |
136 void MarkupAccumulator::appendOpenTag(StringBuilder& result, const Element& elem
ent, Namespaces* namespaces) | |
137 { | |
138 m_formatter.appendOpenTag(result, element, namespaces); | |
139 } | |
140 | |
141 void MarkupAccumulator::appendCloseTag(StringBuilder& result, const Element& ele
ment) | |
142 { | |
143 m_formatter.appendCloseTag(result, element); | |
144 } | |
145 | |
146 void MarkupAccumulator::appendAttribute(StringBuilder& result, const Element& el
ement, const Attribute& attribute, Namespaces* namespaces) | |
147 { | |
148 m_formatter.appendAttribute(result, element, attribute, namespaces); | |
149 } | |
150 | |
151 EntityMask MarkupAccumulator::entityMaskForText(const Text& text) const | |
152 { | |
153 return m_formatter.entityMaskForText(text); | |
154 } | |
155 | |
156 bool MarkupAccumulator::serializeAsHTMLDocument(const Node& node) const | |
157 { | |
158 return m_formatter.serializeAsHTMLDocument(node); | |
159 } | |
160 | |
161 template<typename Strategy> | |
162 static void serializeNodesWithNamespaces(MarkupAccumulator& accumulator, Node& t
argetNode, EChildrenOnly childrenOnly, const Namespaces* namespaces) | |
163 { | |
164 Namespaces namespaceHash; | |
165 if (namespaces) | |
166 namespaceHash = *namespaces; | |
167 | |
168 if (!childrenOnly) | |
169 accumulator.appendStartTag(targetNode, &namespaceHash); | |
170 | |
171 if (!(accumulator.serializeAsHTMLDocument(targetNode) && elementCannotHaveEn
dTag(targetNode))) { | |
172 Node* current = isHTMLTemplateElement(targetNode) ? Strategy::firstChild
(*toHTMLTemplateElement(targetNode).content()) : Strategy::firstChild(targetNode
); | |
173 for ( ; current; current = Strategy::nextSibling(*current)) | |
174 serializeNodesWithNamespaces<Strategy>(accumulator, *current, Includ
eNode, &namespaceHash); | |
175 } | |
176 | |
177 if (!childrenOnly && targetNode.isElementNode()) | |
178 accumulator.appendEndTag(toElement(targetNode)); | |
179 } | |
180 | |
181 template<typename Strategy> | |
182 String serializeNodes(MarkupAccumulator& accumulator, Node& targetNode, EChildre
nOnly childrenOnly) | |
183 { | |
184 Namespaces* namespaces = nullptr; | |
185 Namespaces namespaceHash; | |
186 if (!accumulator.serializeAsHTMLDocument(targetNode)) { | |
187 // Add pre-bound namespaces for XML fragments. | |
188 namespaceHash.set(xmlAtom, XMLNames::xmlNamespaceURI); | |
189 namespaces = &namespaceHash; | |
190 } | |
191 | |
192 serializeNodesWithNamespaces<Strategy>(accumulator, targetNode, childrenOnly
, namespaces); | |
193 return accumulator.toString(); | |
194 } | |
195 | |
196 template String serializeNodes<EditingStrategy>(MarkupAccumulator&, Node&, EChil
drenOnly); | |
197 | |
198 } | |
OLD | NEW |