Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80684 views
1
//List from htmlparser2
2
var voidElements = {
3
area: true,
4
base: true,
5
basefont: true,
6
br: true,
7
col: true,
8
command: true,
9
embed: true,
10
frame: true,
11
hr: true,
12
img: true,
13
input: true,
14
isindex: true,
15
keygen: true,
16
link: true,
17
meta: true,
18
param: true,
19
source: true,
20
track: true,
21
wbr: true
22
};
23
24
var expr = {
25
upperCaseChars: /([A-Z])/g,
26
breakBetweenTags: /(<(\/?\w+).*?>)(?=<(?!\/\2))/gi,
27
voidElement: (function() {
28
var tags = [];
29
for (var i in voidElements) {
30
tags.push(i);
31
}
32
return new RegExp('<' + tags.join('|<'), 'i');
33
})()
34
};
35
36
var uncanon = function(str, letter) {
37
return '-' + letter.toLowerCase();
38
};
39
40
var HTMLEncode = require('./htmlencoding').HTMLEncode;
41
42
exports.stringifyElement = function stringifyElement(element) {
43
var tagName = element.tagName.toLowerCase(),
44
ret = {
45
start: "<" + tagName,
46
end:''
47
},
48
attributes = [],
49
i,
50
attribute = null;
51
52
if (element.attributes.length) {
53
ret.start += " ";
54
for (i = 0; i<element.attributes.length; i++) {
55
attribute = element.attributes.item(i);
56
attributes.push(attribute.name + '="' +
57
HTMLEncode(attribute.nodeValue, true) + '"');
58
}
59
}
60
ret.start += attributes.join(" ");
61
62
if (voidElements[tagName]) {
63
ret.start += ">";
64
ret.end = '';
65
} else {
66
ret.start += ">";
67
ret.end = "</" + tagName + ">";
68
}
69
70
return ret;
71
};
72
73
var rawTextElements = /SCRIPT|STYLE/i;
74
75
function stringifyDoctype (doctype) {
76
if (doctype.ownerDocument && doctype.ownerDocument._fullDT) {
77
return doctype.ownerDocument._fullDT;
78
}
79
80
var dt = '<!DOCTYPE ' + doctype.name;
81
if (doctype.publicId) {
82
// Public ID may never contain double quotes, so this is always safe.
83
dt += ' PUBLIC "' + doctype.publicId + '" ';
84
}
85
if (!doctype.publicId && doctype.systemId) {
86
dt += ' SYSTEM ';
87
}
88
if (doctype.systemId) {
89
// System ID may contain double quotes OR single quotes, not never both.
90
if (doctype.systemId.indexOf('"') > -1) {
91
dt += "'" + doctype.systemId + "'";
92
} else {
93
dt += '"' + doctype.systemId + '"';
94
}
95
}
96
dt += '>';
97
return dt;
98
}
99
100
exports.makeHtmlGenerator = function makeHtmlGenerator(indentUnit, eol) {
101
indentUnit = indentUnit || "";
102
eol = eol || "";
103
104
return function generateHtmlRecursive(node, rawText, curIndent) {
105
var ret = "", parent, current, i;
106
curIndent = curIndent || "";
107
if (node) {
108
if (node.nodeType &&
109
node.nodeType === node.ENTITY_REFERENCE_NODE) {
110
node = node._entity;
111
}
112
113
var childNodesRawText = rawText || rawTextElements.test(node.nodeName);
114
115
switch (node.nodeType) {
116
case node.ELEMENT_NODE:
117
current = exports.stringifyElement(node);
118
if (childNodesRawText) {
119
ret += curIndent + current.start;
120
} else {
121
ret += curIndent + current.start;
122
}
123
var len = node._childNodes.length;
124
if (len > 0) {
125
if (node._childNodes[0].nodeType !== node.TEXT_NODE) {
126
ret += eol;
127
}
128
for (i=0; i<len; i++) {
129
ret += generateHtmlRecursive(node._childNodes[i], childNodesRawText, curIndent + indentUnit);
130
}
131
if (node._childNodes[len - 1].nodeType !== node.TEXT_NODE) {
132
ret += curIndent;
133
}
134
ret += current.end + eol;
135
} else {
136
ret += ((rawText ? node.nodeValue : HTMLEncode(node.nodeValue, false)) || '') + current.end + eol;
137
}
138
break;
139
case node.TEXT_NODE:
140
// Skip pure whitespace nodes if we're indenting
141
if (!indentUnit || !/^[\s\n]*$/.test(node.nodeValue)) {
142
ret += (rawText ? node.nodeValue : HTMLEncode(node.nodeValue, false)) || '';
143
}
144
break;
145
case node.COMMENT_NODE:
146
ret += curIndent + '<!--' + node.nodeValue + '-->' + eol;
147
break;
148
case node.DOCUMENT_NODE:
149
for (i=0; i<node._childNodes.length; i++) {
150
ret += generateHtmlRecursive(node._childNodes[i], childNodesRawText, curIndent);
151
}
152
break;
153
case node.DOCUMENT_TYPE_NODE:
154
ret += stringifyDoctype(node);
155
break;
156
}
157
}
158
return ret;
159
};
160
};
161
162
exports.domToHtml = function(dom, noformat, raw) {
163
var htmlGenerator = exports.makeHtmlGenerator(noformat ? "" : " ",
164
noformat ? "" : "\n");
165
if (dom._toArray) {
166
// node list
167
dom = dom._toArray();
168
}
169
if (typeof dom.length !== 'undefined') {
170
var ret = "";
171
for (var i=0,len=dom.length; i<len; i++) {
172
ret += htmlGenerator(dom[i], raw);
173
}
174
return ret;
175
} else {
176
// single node
177
return htmlGenerator(dom, raw);
178
}
179
};
180
181