parse5 3.0.3 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -16
- package/lib/common/doctype.js +125 -108
- package/lib/common/error-codes.js +65 -0
- package/lib/common/foreign-content.js +265 -0
- package/lib/common/html.js +102 -102
- package/lib/common/unicode.js +81 -19
- package/lib/extensions/error-reporting/mixin-base.js +43 -0
- package/lib/extensions/error-reporting/parser-mixin.js +52 -0
- package/lib/extensions/error-reporting/preprocessor-mixin.js +24 -0
- package/lib/extensions/error-reporting/tokenizer-mixin.js +17 -0
- package/lib/extensions/location-info/open-element-stack-mixin.js +35 -0
- package/lib/extensions/location-info/parser-mixin.js +222 -0
- package/lib/extensions/location-info/tokenizer-mixin.js +146 -0
- package/lib/extensions/position-tracking/preprocessor-mixin.js +64 -0
- package/lib/index.js +6 -21
- package/lib/parser/formatting-element-list.js +181 -0
- package/lib/parser/index.js +1469 -1332
- package/lib/parser/open-element-stack.js +482 -0
- package/lib/serializer/index.js +136 -122
- package/lib/tokenizer/index.js +1856 -1804
- package/lib/tokenizer/{named_entity_data.js → named-entity-data.js} +1 -1
- package/lib/tokenizer/preprocessor.js +115 -103
- package/lib/tree-adapters/default.js +217 -0
- package/lib/utils/{merge_options.js → merge-options.js} +2 -2
- package/lib/utils/mixin.js +33 -12
- package/package.json +32 -61
- package/LICENSE +0 -19
- package/lib/common/foreign_content.js +0 -260
- package/lib/extensions/location_info/open_element_stack_mixin.js +0 -34
- package/lib/extensions/location_info/parser_mixin.js +0 -213
- package/lib/extensions/location_info/tokenizer_mixin.js +0 -117
- package/lib/extensions/position_tracking/preprocessor_mixin.js +0 -72
- package/lib/index.d.ts +0 -1077
- package/lib/parser/formatting_element_list.js +0 -167
- package/lib/parser/open_element_stack.js +0 -395
- package/lib/parser/parser_stream.js +0 -76
- package/lib/parser/plain_text_conversion_stream.js +0 -20
- package/lib/sax/dev_null_stream.js +0 -14
- package/lib/sax/index.js +0 -118
- package/lib/sax/parser_feedback_simulator.js +0 -153
- package/lib/serializer/serializer_stream.js +0 -28
- package/lib/tree_adapters/default.js +0 -209
- package/lib/tree_adapters/htmlparser2.js +0 -338
package/lib/sax/index.js
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var TransformStream = require('stream').Transform,
|
|
4
|
-
DevNullStream = require('./dev_null_stream'),
|
|
5
|
-
inherits = require('util').inherits,
|
|
6
|
-
Tokenizer = require('../tokenizer'),
|
|
7
|
-
LocationInfoTokenizerMixin = require('../extensions/location_info/tokenizer_mixin'),
|
|
8
|
-
ParserFeedbackSimulator = require('./parser_feedback_simulator'),
|
|
9
|
-
mergeOptions = require('../utils/merge_options');
|
|
10
|
-
|
|
11
|
-
var DEFAULT_OPTIONS = {
|
|
12
|
-
locationInfo: false
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
var SAXParser = module.exports = function (options) {
|
|
16
|
-
TransformStream.call(this);
|
|
17
|
-
|
|
18
|
-
this.options = mergeOptions(DEFAULT_OPTIONS, options);
|
|
19
|
-
|
|
20
|
-
this.tokenizer = new Tokenizer(options);
|
|
21
|
-
|
|
22
|
-
if (this.options.locationInfo)
|
|
23
|
-
new LocationInfoTokenizerMixin(this.tokenizer);
|
|
24
|
-
|
|
25
|
-
this.parserFeedbackSimulator = new ParserFeedbackSimulator(this.tokenizer);
|
|
26
|
-
|
|
27
|
-
this.pendingText = null;
|
|
28
|
-
this.currentTokenLocation = void 0;
|
|
29
|
-
|
|
30
|
-
this.lastChunkWritten = false;
|
|
31
|
-
this.stopped = false;
|
|
32
|
-
|
|
33
|
-
// NOTE: always pipe stream to the /dev/null stream to avoid
|
|
34
|
-
// `highWaterMark` hit even if we don't have consumers.
|
|
35
|
-
// (see: https://github.com/inikulin/parse5/issues/97#issuecomment-171940774)
|
|
36
|
-
this.pipe(new DevNullStream());
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
inherits(SAXParser, TransformStream);
|
|
40
|
-
|
|
41
|
-
//TransformStream implementation
|
|
42
|
-
SAXParser.prototype._transform = function (chunk, encoding, callback) {
|
|
43
|
-
if (!this.stopped) {
|
|
44
|
-
this.tokenizer.write(chunk.toString('utf8'), this.lastChunkWritten);
|
|
45
|
-
this._runParsingLoop();
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
this.push(chunk);
|
|
49
|
-
|
|
50
|
-
callback();
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
SAXParser.prototype._flush = function (callback) {
|
|
54
|
-
callback();
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
SAXParser.prototype.end = function (chunk, encoding, callback) {
|
|
58
|
-
this.lastChunkWritten = true;
|
|
59
|
-
TransformStream.prototype.end.call(this, chunk, encoding, callback);
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
SAXParser.prototype.stop = function () {
|
|
63
|
-
this.stopped = true;
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
//Internals
|
|
67
|
-
SAXParser.prototype._runParsingLoop = function () {
|
|
68
|
-
do {
|
|
69
|
-
var token = this.parserFeedbackSimulator.getNextToken();
|
|
70
|
-
|
|
71
|
-
if (token.type === Tokenizer.HIBERNATION_TOKEN)
|
|
72
|
-
break;
|
|
73
|
-
|
|
74
|
-
if (token.type === Tokenizer.CHARACTER_TOKEN ||
|
|
75
|
-
token.type === Tokenizer.WHITESPACE_CHARACTER_TOKEN ||
|
|
76
|
-
token.type === Tokenizer.NULL_CHARACTER_TOKEN) {
|
|
77
|
-
|
|
78
|
-
if (this.options.locationInfo) {
|
|
79
|
-
if (this.pendingText === null)
|
|
80
|
-
this.currentTokenLocation = token.location;
|
|
81
|
-
|
|
82
|
-
else
|
|
83
|
-
this.currentTokenLocation.endOffset = token.location.endOffset;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
this.pendingText = (this.pendingText || '') + token.chars;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
else {
|
|
90
|
-
this._emitPendingText();
|
|
91
|
-
this._handleToken(token);
|
|
92
|
-
}
|
|
93
|
-
} while (!this.stopped && token.type !== Tokenizer.EOF_TOKEN);
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
SAXParser.prototype._handleToken = function (token) {
|
|
97
|
-
if (this.options.locationInfo)
|
|
98
|
-
this.currentTokenLocation = token.location;
|
|
99
|
-
|
|
100
|
-
if (token.type === Tokenizer.START_TAG_TOKEN)
|
|
101
|
-
this.emit('startTag', token.tagName, token.attrs, token.selfClosing, this.currentTokenLocation);
|
|
102
|
-
|
|
103
|
-
else if (token.type === Tokenizer.END_TAG_TOKEN)
|
|
104
|
-
this.emit('endTag', token.tagName, this.currentTokenLocation);
|
|
105
|
-
|
|
106
|
-
else if (token.type === Tokenizer.COMMENT_TOKEN)
|
|
107
|
-
this.emit('comment', token.data, this.currentTokenLocation);
|
|
108
|
-
|
|
109
|
-
else if (token.type === Tokenizer.DOCTYPE_TOKEN)
|
|
110
|
-
this.emit('doctype', token.name, token.publicId, token.systemId, this.currentTokenLocation);
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
SAXParser.prototype._emitPendingText = function () {
|
|
114
|
-
if (this.pendingText !== null) {
|
|
115
|
-
this.emit('text', this.pendingText, this.currentTokenLocation);
|
|
116
|
-
this.pendingText = null;
|
|
117
|
-
}
|
|
118
|
-
};
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var Tokenizer = require('../tokenizer'),
|
|
4
|
-
foreignContent = require('../common/foreign_content'),
|
|
5
|
-
UNICODE = require('../common/unicode'),
|
|
6
|
-
HTML = require('../common/html');
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
//Aliases
|
|
10
|
-
var $ = HTML.TAG_NAMES,
|
|
11
|
-
NS = HTML.NAMESPACES;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
//ParserFeedbackSimulator
|
|
15
|
-
//Simulates adjustment of the Tokenizer which performed by standard parser during tree construction.
|
|
16
|
-
var ParserFeedbackSimulator = module.exports = function (tokenizer) {
|
|
17
|
-
this.tokenizer = tokenizer;
|
|
18
|
-
|
|
19
|
-
this.namespaceStack = [];
|
|
20
|
-
this.namespaceStackTop = -1;
|
|
21
|
-
this._enterNamespace(NS.HTML);
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
ParserFeedbackSimulator.prototype.getNextToken = function () {
|
|
25
|
-
var token = this.tokenizer.getNextToken();
|
|
26
|
-
|
|
27
|
-
if (token.type === Tokenizer.START_TAG_TOKEN)
|
|
28
|
-
this._handleStartTagToken(token);
|
|
29
|
-
|
|
30
|
-
else if (token.type === Tokenizer.END_TAG_TOKEN)
|
|
31
|
-
this._handleEndTagToken(token);
|
|
32
|
-
|
|
33
|
-
else if (token.type === Tokenizer.NULL_CHARACTER_TOKEN && this.inForeignContent) {
|
|
34
|
-
token.type = Tokenizer.CHARACTER_TOKEN;
|
|
35
|
-
token.chars = UNICODE.REPLACEMENT_CHARACTER;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
else if (this.skipNextNewLine) {
|
|
39
|
-
if (token.type !== Tokenizer.HIBERNATION_TOKEN)
|
|
40
|
-
this.skipNextNewLine = false;
|
|
41
|
-
|
|
42
|
-
if (token.type === Tokenizer.WHITESPACE_CHARACTER_TOKEN && token.chars[0] === '\n') {
|
|
43
|
-
if (token.chars.length === 1)
|
|
44
|
-
return this.getNextToken();
|
|
45
|
-
|
|
46
|
-
token.chars = token.chars.substr(1);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return token;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
//Namespace stack mutations
|
|
54
|
-
ParserFeedbackSimulator.prototype._enterNamespace = function (namespace) {
|
|
55
|
-
this.namespaceStackTop++;
|
|
56
|
-
this.namespaceStack.push(namespace);
|
|
57
|
-
|
|
58
|
-
this.inForeignContent = namespace !== NS.HTML;
|
|
59
|
-
this.currentNamespace = namespace;
|
|
60
|
-
this.tokenizer.allowCDATA = this.inForeignContent;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
ParserFeedbackSimulator.prototype._leaveCurrentNamespace = function () {
|
|
64
|
-
this.namespaceStackTop--;
|
|
65
|
-
this.namespaceStack.pop();
|
|
66
|
-
|
|
67
|
-
this.currentNamespace = this.namespaceStack[this.namespaceStackTop];
|
|
68
|
-
this.inForeignContent = this.currentNamespace !== NS.HTML;
|
|
69
|
-
this.tokenizer.allowCDATA = this.inForeignContent;
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
//Token handlers
|
|
73
|
-
ParserFeedbackSimulator.prototype._ensureTokenizerMode = function (tn) {
|
|
74
|
-
if (tn === $.TEXTAREA || tn === $.TITLE)
|
|
75
|
-
this.tokenizer.state = Tokenizer.MODE.RCDATA;
|
|
76
|
-
|
|
77
|
-
else if (tn === $.PLAINTEXT)
|
|
78
|
-
this.tokenizer.state = Tokenizer.MODE.PLAINTEXT;
|
|
79
|
-
|
|
80
|
-
else if (tn === $.SCRIPT)
|
|
81
|
-
this.tokenizer.state = Tokenizer.MODE.SCRIPT_DATA;
|
|
82
|
-
|
|
83
|
-
else if (tn === $.STYLE || tn === $.IFRAME || tn === $.XMP ||
|
|
84
|
-
tn === $.NOEMBED || tn === $.NOFRAMES || tn === $.NOSCRIPT)
|
|
85
|
-
this.tokenizer.state = Tokenizer.MODE.RAWTEXT;
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
ParserFeedbackSimulator.prototype._handleStartTagToken = function (token) {
|
|
89
|
-
var tn = token.tagName;
|
|
90
|
-
|
|
91
|
-
if (tn === $.SVG)
|
|
92
|
-
this._enterNamespace(NS.SVG);
|
|
93
|
-
|
|
94
|
-
else if (tn === $.MATH)
|
|
95
|
-
this._enterNamespace(NS.MATHML);
|
|
96
|
-
|
|
97
|
-
if (this.inForeignContent) {
|
|
98
|
-
if (foreignContent.causesExit(token)) {
|
|
99
|
-
this._leaveCurrentNamespace();
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
var currentNs = this.currentNamespace;
|
|
104
|
-
|
|
105
|
-
if (currentNs === NS.MATHML)
|
|
106
|
-
foreignContent.adjustTokenMathMLAttrs(token);
|
|
107
|
-
|
|
108
|
-
else if (currentNs === NS.SVG) {
|
|
109
|
-
foreignContent.adjustTokenSVGTagName(token);
|
|
110
|
-
foreignContent.adjustTokenSVGAttrs(token);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
foreignContent.adjustTokenXMLAttrs(token);
|
|
114
|
-
|
|
115
|
-
tn = token.tagName;
|
|
116
|
-
|
|
117
|
-
if (!token.selfClosing && foreignContent.isIntegrationPoint(tn, currentNs, token.attrs))
|
|
118
|
-
this._enterNamespace(NS.HTML);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
else {
|
|
122
|
-
if (tn === $.PRE || tn === $.TEXTAREA || tn === $.LISTING)
|
|
123
|
-
this.skipNextNewLine = true;
|
|
124
|
-
|
|
125
|
-
else if (tn === $.IMAGE)
|
|
126
|
-
token.tagName = $.IMG;
|
|
127
|
-
|
|
128
|
-
this._ensureTokenizerMode(tn);
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
ParserFeedbackSimulator.prototype._handleEndTagToken = function (token) {
|
|
133
|
-
var tn = token.tagName;
|
|
134
|
-
|
|
135
|
-
if (!this.inForeignContent) {
|
|
136
|
-
var previousNs = this.namespaceStack[this.namespaceStackTop - 1];
|
|
137
|
-
|
|
138
|
-
if (previousNs === NS.SVG && foreignContent.SVG_TAG_NAMES_ADJUSTMENT_MAP[tn])
|
|
139
|
-
tn = foreignContent.SVG_TAG_NAMES_ADJUSTMENT_MAP[tn];
|
|
140
|
-
|
|
141
|
-
//NOTE: check for exit from integration point
|
|
142
|
-
if (foreignContent.isIntegrationPoint(tn, previousNs, token.attrs))
|
|
143
|
-
this._leaveCurrentNamespace();
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
else if (tn === $.SVG && this.currentNamespace === NS.SVG ||
|
|
147
|
-
tn === $.MATH && this.currentNamespace === NS.MATHML)
|
|
148
|
-
this._leaveCurrentNamespace();
|
|
149
|
-
|
|
150
|
-
// NOTE: adjust end tag name as well for consistency
|
|
151
|
-
if (this.currentNamespace === NS.SVG)
|
|
152
|
-
foreignContent.adjustTokenSVGTagName(token);
|
|
153
|
-
};
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var ReadableStream = require('stream').Readable,
|
|
4
|
-
inherits = require('util').inherits,
|
|
5
|
-
Serializer = require('./index');
|
|
6
|
-
|
|
7
|
-
var SerializerStream = module.exports = function (node, options) {
|
|
8
|
-
ReadableStream.call(this);
|
|
9
|
-
|
|
10
|
-
this.serializer = new Serializer(node, options);
|
|
11
|
-
|
|
12
|
-
Object.defineProperty(this.serializer, 'html', {
|
|
13
|
-
//NOTE: To make `+=` concat operator work properly we define
|
|
14
|
-
//getter which always returns empty string
|
|
15
|
-
get: function () {
|
|
16
|
-
return '';
|
|
17
|
-
},
|
|
18
|
-
set: this.push.bind(this)
|
|
19
|
-
});
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
inherits(SerializerStream, ReadableStream);
|
|
23
|
-
|
|
24
|
-
//Readable stream implementation
|
|
25
|
-
SerializerStream.prototype._read = function () {
|
|
26
|
-
this.serializer.serialize();
|
|
27
|
-
this.push(null);
|
|
28
|
-
};
|
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var DOCUMENT_MODE = require('../common/html').DOCUMENT_MODE;
|
|
4
|
-
|
|
5
|
-
//Node construction
|
|
6
|
-
exports.createDocument = function () {
|
|
7
|
-
return {
|
|
8
|
-
nodeName: '#document',
|
|
9
|
-
mode: DOCUMENT_MODE.NO_QUIRKS,
|
|
10
|
-
childNodes: []
|
|
11
|
-
};
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
exports.createDocumentFragment = function () {
|
|
15
|
-
return {
|
|
16
|
-
nodeName: '#document-fragment',
|
|
17
|
-
childNodes: []
|
|
18
|
-
};
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
exports.createElement = function (tagName, namespaceURI, attrs) {
|
|
22
|
-
return {
|
|
23
|
-
nodeName: tagName,
|
|
24
|
-
tagName: tagName,
|
|
25
|
-
attrs: attrs,
|
|
26
|
-
namespaceURI: namespaceURI,
|
|
27
|
-
childNodes: [],
|
|
28
|
-
parentNode: null
|
|
29
|
-
};
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
exports.createCommentNode = function (data) {
|
|
33
|
-
return {
|
|
34
|
-
nodeName: '#comment',
|
|
35
|
-
data: data,
|
|
36
|
-
parentNode: null
|
|
37
|
-
};
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
var createTextNode = function (value) {
|
|
41
|
-
return {
|
|
42
|
-
nodeName: '#text',
|
|
43
|
-
value: value,
|
|
44
|
-
parentNode: null
|
|
45
|
-
};
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
//Tree mutation
|
|
50
|
-
var appendChild = exports.appendChild = function (parentNode, newNode) {
|
|
51
|
-
parentNode.childNodes.push(newNode);
|
|
52
|
-
newNode.parentNode = parentNode;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
var insertBefore = exports.insertBefore = function (parentNode, newNode, referenceNode) {
|
|
56
|
-
var insertionIdx = parentNode.childNodes.indexOf(referenceNode);
|
|
57
|
-
|
|
58
|
-
parentNode.childNodes.splice(insertionIdx, 0, newNode);
|
|
59
|
-
newNode.parentNode = parentNode;
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
exports.setTemplateContent = function (templateElement, contentElement) {
|
|
63
|
-
templateElement.content = contentElement;
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
exports.getTemplateContent = function (templateElement) {
|
|
67
|
-
return templateElement.content;
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
exports.setDocumentType = function (document, name, publicId, systemId) {
|
|
71
|
-
var doctypeNode = null;
|
|
72
|
-
|
|
73
|
-
for (var i = 0; i < document.childNodes.length; i++) {
|
|
74
|
-
if (document.childNodes[i].nodeName === '#documentType') {
|
|
75
|
-
doctypeNode = document.childNodes[i];
|
|
76
|
-
break;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (doctypeNode) {
|
|
81
|
-
doctypeNode.name = name;
|
|
82
|
-
doctypeNode.publicId = publicId;
|
|
83
|
-
doctypeNode.systemId = systemId;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
else {
|
|
87
|
-
appendChild(document, {
|
|
88
|
-
nodeName: '#documentType',
|
|
89
|
-
name: name,
|
|
90
|
-
publicId: publicId,
|
|
91
|
-
systemId: systemId
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
exports.setDocumentMode = function (document, mode) {
|
|
97
|
-
document.mode = mode;
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
exports.getDocumentMode = function (document) {
|
|
101
|
-
return document.mode;
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
exports.detachNode = function (node) {
|
|
105
|
-
if (node.parentNode) {
|
|
106
|
-
var idx = node.parentNode.childNodes.indexOf(node);
|
|
107
|
-
|
|
108
|
-
node.parentNode.childNodes.splice(idx, 1);
|
|
109
|
-
node.parentNode = null;
|
|
110
|
-
}
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
exports.insertText = function (parentNode, text) {
|
|
114
|
-
if (parentNode.childNodes.length) {
|
|
115
|
-
var prevNode = parentNode.childNodes[parentNode.childNodes.length - 1];
|
|
116
|
-
|
|
117
|
-
if (prevNode.nodeName === '#text') {
|
|
118
|
-
prevNode.value += text;
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
appendChild(parentNode, createTextNode(text));
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
exports.insertTextBefore = function (parentNode, text, referenceNode) {
|
|
127
|
-
var prevNode = parentNode.childNodes[parentNode.childNodes.indexOf(referenceNode) - 1];
|
|
128
|
-
|
|
129
|
-
if (prevNode && prevNode.nodeName === '#text')
|
|
130
|
-
prevNode.value += text;
|
|
131
|
-
else
|
|
132
|
-
insertBefore(parentNode, createTextNode(text), referenceNode);
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
exports.adoptAttributes = function (recipient, attrs) {
|
|
136
|
-
var recipientAttrsMap = [];
|
|
137
|
-
|
|
138
|
-
for (var i = 0; i < recipient.attrs.length; i++)
|
|
139
|
-
recipientAttrsMap.push(recipient.attrs[i].name);
|
|
140
|
-
|
|
141
|
-
for (var j = 0; j < attrs.length; j++) {
|
|
142
|
-
if (recipientAttrsMap.indexOf(attrs[j].name) === -1)
|
|
143
|
-
recipient.attrs.push(attrs[j]);
|
|
144
|
-
}
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
//Tree traversing
|
|
149
|
-
exports.getFirstChild = function (node) {
|
|
150
|
-
return node.childNodes[0];
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
exports.getChildNodes = function (node) {
|
|
154
|
-
return node.childNodes;
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
exports.getParentNode = function (node) {
|
|
158
|
-
return node.parentNode;
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
exports.getAttrList = function (element) {
|
|
162
|
-
return element.attrs;
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
//Node data
|
|
166
|
-
exports.getTagName = function (element) {
|
|
167
|
-
return element.tagName;
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
exports.getNamespaceURI = function (element) {
|
|
171
|
-
return element.namespaceURI;
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
exports.getTextNodeContent = function (textNode) {
|
|
175
|
-
return textNode.value;
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
exports.getCommentNodeContent = function (commentNode) {
|
|
179
|
-
return commentNode.data;
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
exports.getDocumentTypeNodeName = function (doctypeNode) {
|
|
183
|
-
return doctypeNode.name;
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
exports.getDocumentTypeNodePublicId = function (doctypeNode) {
|
|
187
|
-
return doctypeNode.publicId;
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
exports.getDocumentTypeNodeSystemId = function (doctypeNode) {
|
|
191
|
-
return doctypeNode.systemId;
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
//Node types
|
|
195
|
-
exports.isTextNode = function (node) {
|
|
196
|
-
return node.nodeName === '#text';
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
exports.isCommentNode = function (node) {
|
|
200
|
-
return node.nodeName === '#comment';
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
exports.isDocumentTypeNode = function (node) {
|
|
204
|
-
return node.nodeName === '#documentType';
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
exports.isElementNode = function (node) {
|
|
208
|
-
return !!node.tagName;
|
|
209
|
-
};
|