1/*
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef MarkupAccumulator_h
27#define MarkupAccumulator_h
28
29#include "PlatformString.h"
30#include "markup.h"
31#include <wtf/HashMap.h>
32#include <wtf/Vector.h>
33
34namespace WebCore {
35
36class Attribute;
37class DocumentType;
38class Element;
39class Node;
40class Range;
41
42typedef HashMap<AtomicStringImpl*, AtomicStringImpl*> Namespaces;
43
44enum EntityMask {
45    EntityAmp = 0x0001,
46    EntityLt = 0x0002,
47    EntityGt = 0x0004,
48    EntityQuot = 0x0008,
49    EntityNbsp = 0x0010,
50
51    // Non-breaking space needs to be escaped in innerHTML for compatibility reason. See http://trac.webkit.org/changeset/32879
52    // However, we cannot do this in a XML document because it does not have the entity reference defined (See the bug 19215).
53    EntityMaskInCDATA = 0,
54    EntityMaskInPCDATA = EntityAmp | EntityLt | EntityGt,
55    EntityMaskInHTMLPCDATA = EntityMaskInPCDATA | EntityNbsp,
56    EntityMaskInAttributeValue = EntityAmp | EntityLt | EntityGt | EntityQuot,
57    EntityMaskInHTMLAttributeValue = EntityMaskInAttributeValue | EntityNbsp,
58};
59
60struct EntityDescription {
61    UChar entity;
62    const String& reference;
63    EntityMask mask;
64};
65
66// FIXME: Noncopyable?
67class MarkupAccumulator {
68public:
69    MarkupAccumulator(Vector<Node*>* nodes, EAbsoluteURLs shouldResolveURLs, const Range* range = 0);
70    virtual ~MarkupAccumulator();
71
72    String serializeNodes(Node* node, Node* nodeToSkip, EChildrenOnly childrenOnly);
73
74protected:
75    virtual void appendString(const String&);
76    void appendStartTag(Node*, Namespaces* = 0);
77    void appendEndTag(Node*);
78    static size_t totalLength(const Vector<String>&);
79    size_t length() const { return totalLength(m_succeedingMarkup); }
80    void concatenateMarkup(Vector<UChar>& out);
81    void appendAttributeValue(Vector<UChar>& result, const String& attribute, bool documentIsHTML);
82    void appendQuotedURLAttributeValue(Vector<UChar>& result, const String& urlString);
83    void appendNodeValue(Vector<UChar>& out, const Node*, const Range*, EntityMask);
84    bool shouldAddNamespaceElement(const Element*);
85    bool shouldAddNamespaceAttribute(const Attribute&, Namespaces&);
86    void appendNamespace(Vector<UChar>& result, const AtomicString& prefix, const AtomicString& namespaceURI, Namespaces&);
87    EntityMask entityMaskForText(Text* text) const;
88    virtual void appendText(Vector<UChar>& out, Text*);
89    void appendComment(Vector<UChar>& out, const String& comment);
90    void appendDocumentType(Vector<UChar>& result, const DocumentType*);
91    void appendProcessingInstruction(Vector<UChar>& out, const String& target, const String& data);
92    virtual void appendElement(Vector<UChar>& out, Element*, Namespaces*);
93    void appendOpenTag(Vector<UChar>& out, Element* element, Namespaces*);
94    void appendCloseTag(Vector<UChar>& out, Element* element);
95    void appendAttribute(Vector<UChar>& out, Element* element, const Attribute&, Namespaces*);
96    void appendCDATASection(Vector<UChar>& out, const String& section);
97    void appendStartMarkup(Vector<UChar>& result, const Node*, Namespaces*);
98    bool shouldSelfClose(const Node*);
99    bool elementCannotHaveEndTag(const Node* node);
100    void appendEndMarkup(Vector<UChar>& result, const Node*);
101
102    bool shouldResolveURLs() { return m_shouldResolveURLs == AbsoluteURLs; }
103
104    Vector<Node*>* const m_nodes;
105    const Range* const m_range;
106
107private:
108    void serializeNodesWithNamespaces(Node*, Node* nodeToSkip, EChildrenOnly, const Namespaces*);
109
110    Vector<String> m_succeedingMarkup;
111    const bool m_shouldResolveURLs;
112};
113
114// FIXME: This method should be integrated with MarkupAccumulator.
115void appendCharactersReplacingEntities(Vector<UChar>& out, const UChar* content, size_t length, EntityMask entityMask);
116
117}
118
119#endif
120