1
2
3
4
5
6 #include <gendoc/html/HtmlSourceCodeWriter.hpp>
7 #include <sngxml/dom/CharacterData.hpp>
8
9 namespace gendoc { namespace html {
10
11 HtmlSourceCodeWriter::HtmlSourceCodeWriter() : lineElement(nullptr), inlineLineElement(nullptr), currentPos(0), inlineCurrentPos(0)
12 {
13 }
14
15 void HtmlSourceCodeWriter::WriteToElement(sngxml::dom::Element* element, const std::u32string& text)
16 {
17 for (char32_t c : text)
18 {
19 if (c == ' ')
20 {
21 element->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::EntityReference(U"nbsp")));
22 }
23 else
24 {
25 element->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::Text(std::u32string(1, c))));
26 }
27 }
28 }
29
30 void HtmlSourceCodeWriter::MoveTo(const Span& span)
31 {
32 if (currentPos < span.start)
33 {
34 int length = span.start - currentPos;
35 WriteSpaceKind(length, WriteKind::line);
36 }
37 if (inlineCurrentPos < span.start)
38 {
39 int length = span.start - inlineCurrentPos;
40 WriteSpaceKind(length, WriteKind::inlineLine);
41 }
42 }
43
44 void HtmlSourceCodeWriter::WriteLineNumberKind(const std::u32string& lineNumber, WriteKind kind)
45 {
46 std::unique_ptr<sngxml::dom::Element> lineNumberElement(new sngxml::dom::Element(U"span"));
47 lineNumberElement->SetAttribute(U"class", U"lineNumber");
48 WriteToElement(lineNumberElement.get(), lineNumber);
49 if ((kind & WriteKind::inlineLine) != WriteKind::none)
50 {
51 if (inlineLineElement)
52 {
53 inlineLineElement->AppendChild(lineNumberElement->CloneNode(true));
54 inlineCurrentPos += lineNumber.length();
55 }
56 }
57 if ((kind & WriteKind::line) != WriteKind::none)
58 {
59 lineElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(lineNumberElement.release()));
60 currentPos += lineNumber.length();
61 }
62 }
63 void HtmlSourceCodeWriter::WriteLineNumber(const std::u32string& lineNumber)
64 {
65 WriteLineNumberKind(lineNumber, WriteKind::both);
66 }
67
68 void HtmlSourceCodeWriter::WriteLineComment(const std::u32string& comment)
69 {
70 std::u32string line;
71 for (char32_t c : comment)
72 {
73 if (c != '\r' && c != '\n')
74 {
75 line.append(1, c);
76 }
77 }
78 std::unique_ptr<sngxml::dom::Element> commentElement(new sngxml::dom::Element(U"span"));
79 commentElement->SetAttribute(U"class", U"comment");
80 WriteToElement(commentElement.get(), line);
81 if (inlineLineElement)
82 {
83 inlineLineElement->AppendChild(commentElement->CloneNode(true));
84 inlineCurrentPos += comment.length();
85 }
86 lineElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(commentElement.release()));
87 currentPos += line.length();
88 }
89
90 void HtmlSourceCodeWriter::WriteBlockComment(const std::u32string& comment)
91 {
92 std::unique_ptr<sngxml::dom::Element> commentElement(new sngxml::dom::Element(U"span"));
93 commentElement->SetAttribute(U"class", U"comment");
94 WriteToElement(commentElement.get(), comment);
95 if (inlineLineElement)
96 {
97 inlineLineElement->AppendChild(commentElement->CloneNode(true));
98 inlineCurrentPos += comment.length();
99 }
100 lineElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(commentElement.release()));
101 currentPos += comment.length();
102 }
103
104 void HtmlSourceCodeWriter::WriteKeyword(const std::u32string& keyword)
105 {
106 std::unique_ptr<sngxml::dom::Element> keywordElement(new sngxml::dom::Element(U"span"));
107 keywordElement->SetAttribute(U"class", U"kw");
108 WriteToElement(keywordElement.get(), keyword);
109 if (inlineLineElement)
110 {
111 inlineLineElement->AppendChild(keywordElement->CloneNode(true));
112 inlineCurrentPos += keyword.length();
113 }
114 lineElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(keywordElement.release()));
115 currentPos += keyword.length();
116 }
117
118 void HtmlSourceCodeWriter::WriteIdentifier(const std::u32string& identifier)
119 {
120 std::unique_ptr<sngxml::dom::Element> identifierElement(new sngxml::dom::Element(U"span"));
121 identifierElement->SetAttribute(U"class", U"identifier");
122 WriteToElement(identifierElement.get(), identifier);
123 if (inlineLineElement)
124 {
125 inlineLineElement->AppendChild(identifierElement->CloneNode(true));
126 inlineCurrentPos += identifier.length();
127 }
128 lineElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(identifierElement.release()));
129 currentPos += identifier.length();
130 }
131
132 void HtmlSourceCodeWriter::WriteLink(const std::u32string& identifier, const std::u32string& ref)
133 {
134 if (ref.empty())
135 {
136 std::unique_ptr<sngxml::dom::Element> identifierElement(new sngxml::dom::Element(U"span"));
137 identifierElement->SetAttribute(U"class", U"identifier");
138 WriteToElement(identifierElement.get(), identifier);
139 lineElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(identifierElement.release()));
140 currentPos += identifier.length();
141 }
142 else
143 {
144 std::unique_ptr<sngxml::dom::Element> linkElement(new sngxml::dom::Element(U"a"));
145 linkElement->SetAttribute(U"href", ref);
146 WriteToElement(linkElement.get(), identifier);
147 lineElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(linkElement.release()));
148 currentPos += identifier.length();
149 }
150 }
151
152 void HtmlSourceCodeWriter::WriteInlineLink(const std::u32string& identifier, const std::u32string& ref)
153 {
154 if (inlineLineElement)
155 {
156 if (ref.empty())
157 {
158 std::unique_ptr<sngxml::dom::Element> identifierElement(new sngxml::dom::Element(U"span"));
159 identifierElement->SetAttribute(U"class", U"identifier");
160 WriteToElement(identifierElement.get(), identifier);
161 inlineLineElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(identifierElement.release()));
162 inlineCurrentPos += identifier.length();
163 }
164 else
165 {
166 std::unique_ptr<sngxml::dom::Element> linkElement(new sngxml::dom::Element(U"a"));
167 linkElement->SetAttribute(U"href", ref);
168 WriteToElement(linkElement.get(), identifier);
169 inlineLineElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(linkElement.release()));
170 inlineCurrentPos += identifier.length();
171 }
172 }
173 }
174
175 void HtmlSourceCodeWriter::WriteType(const std::u32string& type)
176 {
177 std::unique_ptr<sngxml::dom::Element> typeElement(new sngxml::dom::Element(U"span"));
178 typeElement->SetAttribute(U"class", U"type");
179 WriteToElement(typeElement.get(), type);
180 if (inlineLineElement)
181 {
182 inlineLineElement->AppendChild(typeElement->CloneNode(true));
183 inlineCurrentPos += type.length();
184 }
185 lineElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(typeElement.release()));
186 currentPos += type.length();
187 }
188
189 void HtmlSourceCodeWriter::WritePP(const std::u32string& pp)
190 {
191 std::unique_ptr<sngxml::dom::Element> ppElement(new sngxml::dom::Element(U"span"));
192 ppElement->SetAttribute(U"class", U"pp");
193 WriteToElement(ppElement.get(), pp);
194 if (inlineLineElement)
195 {
196 inlineLineElement->AppendChild(ppElement->CloneNode(true));
197 inlineCurrentPos += pp.length();
198 }
199 lineElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(ppElement.release()));
200 currentPos += pp.length();
201 }
202
203 void HtmlSourceCodeWriter::WriteChar(const std::u32string& chars)
204 {
205 WriteString(chars);
206 }
207
208 void HtmlSourceCodeWriter::WriteString(const std::u32string& string)
209 {
210 std::unique_ptr<sngxml::dom::Element> stringElement(new sngxml::dom::Element(U"span"));
211 stringElement->SetAttribute(U"class", U"string");
212 WriteToElement(stringElement.get(), string);
213 if (inlineLineElement)
214 {
215 inlineLineElement->AppendChild(stringElement->CloneNode(true));
216 inlineCurrentPos += string.length();
217 }
218 lineElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(stringElement.release()));
219 currentPos += string.length();
220 }
221
222 void HtmlSourceCodeWriter::WriteSpaceKind(int numSpaces, WriteKind kind)
223 {
224 if ((kind & WriteKind::line) != WriteKind::none)
225 {
226 for (int i = 0; i < numSpaces; ++i)
227 {
228 lineElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::EntityReference(U"nbsp")));
229 }
230 currentPos += numSpaces;
231 }
232 if (inlineLineElement)
233 {
234 if ((kind & WriteKind::inlineLine) != WriteKind::none)
235 {
236 for (int i = 0; i < numSpaces; ++i)
237 {
238 inlineLineElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(new sngxml::dom::EntityReference(U"nbsp")));
239 }
240 inlineCurrentPos += numSpaces;
241 }
242 }
243 }
244
245 void HtmlSourceCodeWriter::WriteSpace(int numSpaces)
246 {
247 WriteSpaceKind(numSpaces, WriteKind::both);
248 }
249
250 void HtmlSourceCodeWriter::WriteSpaces(const std::u32string& spaces)
251 {
252 int numSpaces = 0;
253 for (char32_t c : spaces)
254 {
255 if (c == '\t')
256 {
257 numSpaces += 4;
258 }
259 else if (c == ' ')
260 {
261 ++numSpaces;
262 }
263 }
264 WriteSpace(numSpaces);
265 }
266
267 void HtmlSourceCodeWriter::WriteNumber(const std::u32string& number)
268 {
269 WriteOther(number);
270 }
271
272 void HtmlSourceCodeWriter::WriteOther(const std::u32string& other)
273 {
274 std::unique_ptr<sngxml::dom::Element> otherElement(new sngxml::dom::Element(U"span"));
275 otherElement->SetAttribute(U"class", U"other");
276 WriteToElement(otherElement.get(), other);
277 if (inlineLineElement)
278 {
279 inlineLineElement->AppendChild(otherElement->CloneNode(true));
280 inlineCurrentPos += other.length();
281 }
282 lineElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(otherElement.release()));
283 currentPos += other.length();
284 }
285
286 } }