1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 /*
8  * nsIContentSerializer implementation that can be used with an
9  * nsIDocumentEncoder to convert an XHTML (not HTML!) DOM to an XHTML
10  * string that could be parsed into more or less the original DOM.
11  */
12 
13 #ifndef nsXHTMLContentSerializer_h__
14 #define nsXHTMLContentSerializer_h__
15 
16 #include "mozilla/Attributes.h"
17 #include "nsXMLContentSerializer.h"
18 #include "nsString.h"
19 #include "nsTArray.h"
20 
21 class nsIContent;
22 class nsAtom;
23 
24 namespace mozilla {
25 class Encoding;
26 }
27 
28 class nsXHTMLContentSerializer : public nsXMLContentSerializer {
29  public:
30   nsXHTMLContentSerializer();
31   virtual ~nsXHTMLContentSerializer();
32 
33   NS_IMETHOD Init(uint32_t flags, uint32_t aWrapColumn,
34                   const mozilla::Encoding* aEncoding, bool aIsCopying,
35                   bool aRewriteEncodingDeclaration,
36                   bool* aNeedsPreformatScanning, nsAString& aOutput) override;
37 
38   NS_IMETHOD AppendText(nsIContent* aText, int32_t aStartOffset,
39                         int32_t aEndOffset) override;
40 
41   NS_IMETHOD AppendDocumentStart(mozilla::dom::Document* aDocument) override;
42 
43  protected:
44   virtual bool CheckElementStart(mozilla::dom::Element* aElement,
45                                  bool& aForceFormat, nsAString& aStr,
46                                  nsresult& aResult) override;
47 
48   [[nodiscard]] virtual bool AfterElementStart(nsIContent* aContent,
49                                                nsIContent* aOriginalElement,
50                                                nsAString& aStr) override;
51 
52   virtual bool CheckElementEnd(mozilla::dom::Element* aContent,
53                                mozilla::dom::Element* aOriginalElement,
54                                bool& aForceFormat, nsAString& aStr) override;
55 
56   virtual void AfterElementEnd(nsIContent* aContent, nsAString& aStr) override;
57 
58   virtual bool LineBreakBeforeOpen(int32_t aNamespaceID,
59                                    nsAtom* aName) override;
60   virtual bool LineBreakAfterOpen(int32_t aNamespaceID, nsAtom* aName) override;
61   virtual bool LineBreakBeforeClose(int32_t aNamespaceID,
62                                     nsAtom* aName) override;
63   virtual bool LineBreakAfterClose(int32_t aNamespaceID,
64                                    nsAtom* aName) override;
65 
66   bool HasLongLines(const nsString& text, int32_t& aLastNewlineOffset);
67 
68   // functions to check if we enter in or leave from a preformated content
69   virtual void MaybeEnterInPreContent(nsIContent* aNode) override;
70   virtual void MaybeLeaveFromPreContent(nsIContent* aNode) override;
71 
72   [[nodiscard]] virtual bool SerializeAttributes(
73       mozilla::dom::Element* aContent, mozilla::dom::Element* aOriginalElement,
74       nsAString& aTagPrefix, const nsAString& aTagNamespaceURI,
75       nsAtom* aTagName, nsAString& aStr, uint32_t aSkipAttr,
76       bool aAddNSAttr) override;
77 
78   bool IsFirstChildOfOL(nsIContent* aElement);
79 
80   [[nodiscard]] bool SerializeLIValueAttribute(nsIContent* aElement,
81                                                nsAString& aStr);
82   bool IsShorthandAttr(const nsAtom* aAttrName, const nsAtom* aElementName);
83 
84   [[nodiscard]] virtual bool AppendAndTranslateEntities(
85       const nsAString& aStr, nsAString& aOutputStr) override;
86 
87  private:
88   bool IsElementPreformatted(nsIContent* aNode);
89 
90  protected:
91   /*
92    * isHTMLParser should be set to true by the HTML parser which inherits from
93    * this class. It avoids to redefine methods just for few changes.
94    */
95   bool mIsHTMLSerializer;
96 
97   bool mIsCopying;  // Set to true only while copying
98 
99   /*
100    * mDisableEntityEncoding is higher than 0 while the serializer is serializing
101    * the content of a element whose content is considerd CDATA by the
102    * serializer (such elements are 'script', 'style', 'noscript' and
103    * possibly others in XHTML) This doesn't have anything to do with if the
104    * element is defined as CDATA in the DTD, it simply means we'll
105    * output the content of the element without doing any entity encoding
106    * what so ever.
107    */
108   int32_t mDisableEntityEncoding;
109 
110   // This is to ensure that we only do meta tag fixups when dealing with
111   // whole documents.
112   bool mRewriteEncodingDeclaration;
113 
114   // To keep track of First LI child of OL in selected range
115   bool mIsFirstChildOfOL;
116 
117   // To keep track of startvalue of OL and first list item for nested lists
118   struct olState {
olStateolState119     olState(int32_t aStart, bool aIsFirst)
120         : startVal(aStart), isFirstListItem(aIsFirst) {}
121 
olStateolState122     olState(const olState& aOlState) {
123       startVal = aOlState.startVal;
124       isFirstListItem = aOlState.isFirstListItem;
125     }
126 
127     // the value of the start attribute in the OL
128     int32_t startVal;
129 
130     // is true only before the serialization of the first li of an ol
131     // should be false for other li in the list
132     bool isFirstListItem;
133   };
134 
135   // Stack to store one olState struct per <OL>.
136   AutoTArray<olState, 8> mOLStateStack;
137 
138   bool HasNoChildren(nsIContent* aContent);
139 };
140 
141 nsresult NS_NewXHTMLContentSerializer(nsIContentSerializer** aSerializer);
142 
143 #endif
144