parse5 6.0.1 → 7.3.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 +2 -2
- package/dist/cjs/common/doctype.d.ts +4 -0
- package/dist/cjs/common/doctype.js +118 -0
- package/dist/cjs/common/error-codes.d.ts +67 -0
- package/dist/cjs/common/error-codes.js +66 -0
- package/dist/cjs/common/foreign-content.d.ts +9 -0
- package/dist/cjs/common/foreign-content.js +237 -0
- package/dist/cjs/common/html.d.ts +289 -0
- package/dist/cjs/common/html.js +528 -0
- package/dist/cjs/common/token.d.ts +84 -0
- package/dist/cjs/common/token.js +24 -0
- package/dist/cjs/common/unicode.d.ts +42 -0
- package/dist/cjs/common/unicode.js +70 -0
- package/dist/cjs/index.d.ts +71 -0
- package/dist/cjs/index.js +54 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/parser/formatting-element-list.d.ts +36 -0
- package/dist/cjs/parser/formatting-element-list.js +114 -0
- package/dist/cjs/parser/index.d.ts +221 -0
- package/dist/cjs/parser/index.js +3240 -0
- package/dist/cjs/parser/open-element-stack.d.ts +53 -0
- package/dist/cjs/parser/open-element-stack.js +328 -0
- package/dist/cjs/serializer/index.d.ts +60 -0
- package/dist/cjs/serializer/index.js +172 -0
- package/dist/cjs/tokenizer/index.d.ts +247 -0
- package/dist/cjs/tokenizer/index.js +2714 -0
- package/dist/cjs/tokenizer/preprocessor.d.ts +36 -0
- package/dist/cjs/tokenizer/preprocessor.js +200 -0
- package/dist/cjs/tree-adapters/default.d.ts +84 -0
- package/dist/cjs/tree-adapters/default.js +176 -0
- package/dist/cjs/tree-adapters/interface.d.ts +255 -0
- package/dist/cjs/tree-adapters/interface.js +2 -0
- package/dist/common/doctype.d.ts +4 -0
- package/{lib → dist}/common/doctype.js +24 -72
- package/dist/common/error-codes.d.ts +67 -0
- package/dist/common/error-codes.js +63 -0
- package/dist/common/foreign-content.d.ts +9 -0
- package/dist/common/foreign-content.js +228 -0
- package/dist/common/html.d.ts +289 -0
- package/dist/common/html.js +523 -0
- package/dist/common/token.d.ts +84 -0
- package/dist/common/token.js +20 -0
- package/dist/common/unicode.d.ts +42 -0
- package/dist/common/unicode.js +62 -0
- package/dist/index.d.ts +71 -0
- package/dist/index.js +42 -0
- package/dist/parser/formatting-element-list.d.ts +36 -0
- package/dist/parser/formatting-element-list.js +110 -0
- package/dist/parser/index.d.ts +221 -0
- package/dist/parser/index.js +3245 -0
- package/dist/parser/open-element-stack.d.ts +53 -0
- package/dist/parser/open-element-stack.js +324 -0
- package/dist/serializer/index.d.ts +60 -0
- package/dist/serializer/index.js +168 -0
- package/dist/tokenizer/index.d.ts +247 -0
- package/dist/tokenizer/index.js +2710 -0
- package/dist/tokenizer/preprocessor.d.ts +36 -0
- package/dist/tokenizer/preprocessor.js +196 -0
- package/dist/tree-adapters/default.d.ts +84 -0
- package/dist/tree-adapters/default.js +173 -0
- package/dist/tree-adapters/interface.d.ts +255 -0
- package/dist/tree-adapters/interface.js +1 -0
- package/package.json +21 -6
- package/lib/common/error-codes.js +0 -65
- package/lib/common/foreign-content.js +0 -265
- package/lib/common/html.js +0 -272
- package/lib/common/unicode.js +0 -109
- package/lib/extensions/error-reporting/mixin-base.js +0 -43
- package/lib/extensions/error-reporting/parser-mixin.js +0 -52
- package/lib/extensions/error-reporting/preprocessor-mixin.js +0 -24
- package/lib/extensions/error-reporting/tokenizer-mixin.js +0 -17
- package/lib/extensions/location-info/open-element-stack-mixin.js +0 -35
- package/lib/extensions/location-info/parser-mixin.js +0 -223
- package/lib/extensions/location-info/tokenizer-mixin.js +0 -146
- package/lib/extensions/position-tracking/preprocessor-mixin.js +0 -64
- package/lib/index.js +0 -29
- package/lib/parser/formatting-element-list.js +0 -181
- package/lib/parser/index.js +0 -2956
- package/lib/parser/open-element-stack.js +0 -482
- package/lib/serializer/index.js +0 -176
- package/lib/tokenizer/index.js +0 -2196
- package/lib/tokenizer/named-entity-data.js +0 -5
- package/lib/tokenizer/preprocessor.js +0 -159
- package/lib/tree-adapters/default.js +0 -221
- package/lib/utils/merge-options.js +0 -13
- package/lib/utils/mixin.js +0 -39
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const Mixin = require('../../utils/mixin');
|
|
4
|
-
const Tokenizer = require('../../tokenizer');
|
|
5
|
-
const LocationInfoTokenizerMixin = require('./tokenizer-mixin');
|
|
6
|
-
const LocationInfoOpenElementStackMixin = require('./open-element-stack-mixin');
|
|
7
|
-
const HTML = require('../../common/html');
|
|
8
|
-
|
|
9
|
-
//Aliases
|
|
10
|
-
const $ = HTML.TAG_NAMES;
|
|
11
|
-
|
|
12
|
-
class LocationInfoParserMixin extends Mixin {
|
|
13
|
-
constructor(parser) {
|
|
14
|
-
super(parser);
|
|
15
|
-
|
|
16
|
-
this.parser = parser;
|
|
17
|
-
this.treeAdapter = this.parser.treeAdapter;
|
|
18
|
-
this.posTracker = null;
|
|
19
|
-
this.lastStartTagToken = null;
|
|
20
|
-
this.lastFosterParentingLocation = null;
|
|
21
|
-
this.currentToken = null;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
_setStartLocation(element) {
|
|
25
|
-
let loc = null;
|
|
26
|
-
|
|
27
|
-
if (this.lastStartTagToken) {
|
|
28
|
-
loc = Object.assign({}, this.lastStartTagToken.location);
|
|
29
|
-
loc.startTag = this.lastStartTagToken.location;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
this.treeAdapter.setNodeSourceCodeLocation(element, loc);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
_setEndLocation(element, closingToken) {
|
|
36
|
-
const loc = this.treeAdapter.getNodeSourceCodeLocation(element);
|
|
37
|
-
|
|
38
|
-
if (loc) {
|
|
39
|
-
if (closingToken.location) {
|
|
40
|
-
const ctLoc = closingToken.location;
|
|
41
|
-
const tn = this.treeAdapter.getTagName(element);
|
|
42
|
-
|
|
43
|
-
// NOTE: For cases like <p> <p> </p> - First 'p' closes without a closing
|
|
44
|
-
// tag and for cases like <td> <p> </td> - 'p' closes without a closing tag.
|
|
45
|
-
const isClosingEndTag = closingToken.type === Tokenizer.END_TAG_TOKEN && tn === closingToken.tagName;
|
|
46
|
-
const endLoc = {};
|
|
47
|
-
if (isClosingEndTag) {
|
|
48
|
-
endLoc.endTag = Object.assign({}, ctLoc);
|
|
49
|
-
endLoc.endLine = ctLoc.endLine;
|
|
50
|
-
endLoc.endCol = ctLoc.endCol;
|
|
51
|
-
endLoc.endOffset = ctLoc.endOffset;
|
|
52
|
-
} else {
|
|
53
|
-
endLoc.endLine = ctLoc.startLine;
|
|
54
|
-
endLoc.endCol = ctLoc.startCol;
|
|
55
|
-
endLoc.endOffset = ctLoc.startOffset;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
this.treeAdapter.updateNodeSourceCodeLocation(element, endLoc);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
_getOverriddenMethods(mxn, orig) {
|
|
64
|
-
return {
|
|
65
|
-
_bootstrap(document, fragmentContext) {
|
|
66
|
-
orig._bootstrap.call(this, document, fragmentContext);
|
|
67
|
-
|
|
68
|
-
mxn.lastStartTagToken = null;
|
|
69
|
-
mxn.lastFosterParentingLocation = null;
|
|
70
|
-
mxn.currentToken = null;
|
|
71
|
-
|
|
72
|
-
const tokenizerMixin = Mixin.install(this.tokenizer, LocationInfoTokenizerMixin);
|
|
73
|
-
|
|
74
|
-
mxn.posTracker = tokenizerMixin.posTracker;
|
|
75
|
-
|
|
76
|
-
Mixin.install(this.openElements, LocationInfoOpenElementStackMixin, {
|
|
77
|
-
onItemPop: function(element) {
|
|
78
|
-
mxn._setEndLocation(element, mxn.currentToken);
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
},
|
|
82
|
-
|
|
83
|
-
_runParsingLoop(scriptHandler) {
|
|
84
|
-
orig._runParsingLoop.call(this, scriptHandler);
|
|
85
|
-
|
|
86
|
-
// NOTE: generate location info for elements
|
|
87
|
-
// that remains on open element stack
|
|
88
|
-
for (let i = this.openElements.stackTop; i >= 0; i--) {
|
|
89
|
-
mxn._setEndLocation(this.openElements.items[i], mxn.currentToken);
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
|
|
93
|
-
//Token processing
|
|
94
|
-
_processTokenInForeignContent(token) {
|
|
95
|
-
mxn.currentToken = token;
|
|
96
|
-
orig._processTokenInForeignContent.call(this, token);
|
|
97
|
-
},
|
|
98
|
-
|
|
99
|
-
_processToken(token) {
|
|
100
|
-
mxn.currentToken = token;
|
|
101
|
-
orig._processToken.call(this, token);
|
|
102
|
-
|
|
103
|
-
//NOTE: <body> and <html> are never popped from the stack, so we need to updated
|
|
104
|
-
//their end location explicitly.
|
|
105
|
-
const requireExplicitUpdate =
|
|
106
|
-
token.type === Tokenizer.END_TAG_TOKEN &&
|
|
107
|
-
(token.tagName === $.HTML || (token.tagName === $.BODY && this.openElements.hasInScope($.BODY)));
|
|
108
|
-
|
|
109
|
-
if (requireExplicitUpdate) {
|
|
110
|
-
for (let i = this.openElements.stackTop; i >= 0; i--) {
|
|
111
|
-
const element = this.openElements.items[i];
|
|
112
|
-
|
|
113
|
-
if (this.treeAdapter.getTagName(element) === token.tagName) {
|
|
114
|
-
mxn._setEndLocation(element, token);
|
|
115
|
-
break;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
},
|
|
120
|
-
|
|
121
|
-
//Doctype
|
|
122
|
-
_setDocumentType(token) {
|
|
123
|
-
orig._setDocumentType.call(this, token);
|
|
124
|
-
|
|
125
|
-
const documentChildren = this.treeAdapter.getChildNodes(this.document);
|
|
126
|
-
const cnLength = documentChildren.length;
|
|
127
|
-
|
|
128
|
-
for (let i = 0; i < cnLength; i++) {
|
|
129
|
-
const node = documentChildren[i];
|
|
130
|
-
|
|
131
|
-
if (this.treeAdapter.isDocumentTypeNode(node)) {
|
|
132
|
-
this.treeAdapter.setNodeSourceCodeLocation(node, token.location);
|
|
133
|
-
break;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
},
|
|
137
|
-
|
|
138
|
-
//Elements
|
|
139
|
-
_attachElementToTree(element) {
|
|
140
|
-
//NOTE: _attachElementToTree is called from _appendElement, _insertElement and _insertTemplate methods.
|
|
141
|
-
//So we will use token location stored in this methods for the element.
|
|
142
|
-
mxn._setStartLocation(element);
|
|
143
|
-
mxn.lastStartTagToken = null;
|
|
144
|
-
orig._attachElementToTree.call(this, element);
|
|
145
|
-
},
|
|
146
|
-
|
|
147
|
-
_appendElement(token, namespaceURI) {
|
|
148
|
-
mxn.lastStartTagToken = token;
|
|
149
|
-
orig._appendElement.call(this, token, namespaceURI);
|
|
150
|
-
},
|
|
151
|
-
|
|
152
|
-
_insertElement(token, namespaceURI) {
|
|
153
|
-
mxn.lastStartTagToken = token;
|
|
154
|
-
orig._insertElement.call(this, token, namespaceURI);
|
|
155
|
-
},
|
|
156
|
-
|
|
157
|
-
_insertTemplate(token) {
|
|
158
|
-
mxn.lastStartTagToken = token;
|
|
159
|
-
orig._insertTemplate.call(this, token);
|
|
160
|
-
|
|
161
|
-
const tmplContent = this.treeAdapter.getTemplateContent(this.openElements.current);
|
|
162
|
-
|
|
163
|
-
this.treeAdapter.setNodeSourceCodeLocation(tmplContent, null);
|
|
164
|
-
},
|
|
165
|
-
|
|
166
|
-
_insertFakeRootElement() {
|
|
167
|
-
orig._insertFakeRootElement.call(this);
|
|
168
|
-
this.treeAdapter.setNodeSourceCodeLocation(this.openElements.current, null);
|
|
169
|
-
},
|
|
170
|
-
|
|
171
|
-
//Comments
|
|
172
|
-
_appendCommentNode(token, parent) {
|
|
173
|
-
orig._appendCommentNode.call(this, token, parent);
|
|
174
|
-
|
|
175
|
-
const children = this.treeAdapter.getChildNodes(parent);
|
|
176
|
-
const commentNode = children[children.length - 1];
|
|
177
|
-
|
|
178
|
-
this.treeAdapter.setNodeSourceCodeLocation(commentNode, token.location);
|
|
179
|
-
},
|
|
180
|
-
|
|
181
|
-
//Text
|
|
182
|
-
_findFosterParentingLocation() {
|
|
183
|
-
//NOTE: store last foster parenting location, so we will be able to find inserted text
|
|
184
|
-
//in case of foster parenting
|
|
185
|
-
mxn.lastFosterParentingLocation = orig._findFosterParentingLocation.call(this);
|
|
186
|
-
|
|
187
|
-
return mxn.lastFosterParentingLocation;
|
|
188
|
-
},
|
|
189
|
-
|
|
190
|
-
_insertCharacters(token) {
|
|
191
|
-
orig._insertCharacters.call(this, token);
|
|
192
|
-
|
|
193
|
-
const hasFosterParent = this._shouldFosterParentOnInsertion();
|
|
194
|
-
|
|
195
|
-
const parent =
|
|
196
|
-
(hasFosterParent && mxn.lastFosterParentingLocation.parent) ||
|
|
197
|
-
this.openElements.currentTmplContent ||
|
|
198
|
-
this.openElements.current;
|
|
199
|
-
|
|
200
|
-
const siblings = this.treeAdapter.getChildNodes(parent);
|
|
201
|
-
|
|
202
|
-
const textNodeIdx =
|
|
203
|
-
hasFosterParent && mxn.lastFosterParentingLocation.beforeElement
|
|
204
|
-
? siblings.indexOf(mxn.lastFosterParentingLocation.beforeElement) - 1
|
|
205
|
-
: siblings.length - 1;
|
|
206
|
-
|
|
207
|
-
const textNode = siblings[textNodeIdx];
|
|
208
|
-
|
|
209
|
-
//NOTE: if we have location assigned by another token, then just update end position
|
|
210
|
-
const tnLoc = this.treeAdapter.getNodeSourceCodeLocation(textNode);
|
|
211
|
-
|
|
212
|
-
if (tnLoc) {
|
|
213
|
-
const { endLine, endCol, endOffset } = token.location;
|
|
214
|
-
this.treeAdapter.updateNodeSourceCodeLocation(textNode, { endLine, endCol, endOffset });
|
|
215
|
-
} else {
|
|
216
|
-
this.treeAdapter.setNodeSourceCodeLocation(textNode, token.location);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
module.exports = LocationInfoParserMixin;
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const Mixin = require('../../utils/mixin');
|
|
4
|
-
const Tokenizer = require('../../tokenizer');
|
|
5
|
-
const PositionTrackingPreprocessorMixin = require('../position-tracking/preprocessor-mixin');
|
|
6
|
-
|
|
7
|
-
class LocationInfoTokenizerMixin extends Mixin {
|
|
8
|
-
constructor(tokenizer) {
|
|
9
|
-
super(tokenizer);
|
|
10
|
-
|
|
11
|
-
this.tokenizer = tokenizer;
|
|
12
|
-
this.posTracker = Mixin.install(tokenizer.preprocessor, PositionTrackingPreprocessorMixin);
|
|
13
|
-
this.currentAttrLocation = null;
|
|
14
|
-
this.ctLoc = null;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
_getCurrentLocation() {
|
|
18
|
-
return {
|
|
19
|
-
startLine: this.posTracker.line,
|
|
20
|
-
startCol: this.posTracker.col,
|
|
21
|
-
startOffset: this.posTracker.offset,
|
|
22
|
-
endLine: -1,
|
|
23
|
-
endCol: -1,
|
|
24
|
-
endOffset: -1
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
_attachCurrentAttrLocationInfo() {
|
|
29
|
-
this.currentAttrLocation.endLine = this.posTracker.line;
|
|
30
|
-
this.currentAttrLocation.endCol = this.posTracker.col;
|
|
31
|
-
this.currentAttrLocation.endOffset = this.posTracker.offset;
|
|
32
|
-
|
|
33
|
-
const currentToken = this.tokenizer.currentToken;
|
|
34
|
-
const currentAttr = this.tokenizer.currentAttr;
|
|
35
|
-
|
|
36
|
-
if (!currentToken.location.attrs) {
|
|
37
|
-
currentToken.location.attrs = Object.create(null);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
currentToken.location.attrs[currentAttr.name] = this.currentAttrLocation;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
_getOverriddenMethods(mxn, orig) {
|
|
44
|
-
const methods = {
|
|
45
|
-
_createStartTagToken() {
|
|
46
|
-
orig._createStartTagToken.call(this);
|
|
47
|
-
this.currentToken.location = mxn.ctLoc;
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
_createEndTagToken() {
|
|
51
|
-
orig._createEndTagToken.call(this);
|
|
52
|
-
this.currentToken.location = mxn.ctLoc;
|
|
53
|
-
},
|
|
54
|
-
|
|
55
|
-
_createCommentToken() {
|
|
56
|
-
orig._createCommentToken.call(this);
|
|
57
|
-
this.currentToken.location = mxn.ctLoc;
|
|
58
|
-
},
|
|
59
|
-
|
|
60
|
-
_createDoctypeToken(initialName) {
|
|
61
|
-
orig._createDoctypeToken.call(this, initialName);
|
|
62
|
-
this.currentToken.location = mxn.ctLoc;
|
|
63
|
-
},
|
|
64
|
-
|
|
65
|
-
_createCharacterToken(type, ch) {
|
|
66
|
-
orig._createCharacterToken.call(this, type, ch);
|
|
67
|
-
this.currentCharacterToken.location = mxn.ctLoc;
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
_createEOFToken() {
|
|
71
|
-
orig._createEOFToken.call(this);
|
|
72
|
-
this.currentToken.location = mxn._getCurrentLocation();
|
|
73
|
-
},
|
|
74
|
-
|
|
75
|
-
_createAttr(attrNameFirstCh) {
|
|
76
|
-
orig._createAttr.call(this, attrNameFirstCh);
|
|
77
|
-
mxn.currentAttrLocation = mxn._getCurrentLocation();
|
|
78
|
-
},
|
|
79
|
-
|
|
80
|
-
_leaveAttrName(toState) {
|
|
81
|
-
orig._leaveAttrName.call(this, toState);
|
|
82
|
-
mxn._attachCurrentAttrLocationInfo();
|
|
83
|
-
},
|
|
84
|
-
|
|
85
|
-
_leaveAttrValue(toState) {
|
|
86
|
-
orig._leaveAttrValue.call(this, toState);
|
|
87
|
-
mxn._attachCurrentAttrLocationInfo();
|
|
88
|
-
},
|
|
89
|
-
|
|
90
|
-
_emitCurrentToken() {
|
|
91
|
-
const ctLoc = this.currentToken.location;
|
|
92
|
-
|
|
93
|
-
//NOTE: if we have pending character token make it's end location equal to the
|
|
94
|
-
//current token's start location.
|
|
95
|
-
if (this.currentCharacterToken) {
|
|
96
|
-
this.currentCharacterToken.location.endLine = ctLoc.startLine;
|
|
97
|
-
this.currentCharacterToken.location.endCol = ctLoc.startCol;
|
|
98
|
-
this.currentCharacterToken.location.endOffset = ctLoc.startOffset;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (this.currentToken.type === Tokenizer.EOF_TOKEN) {
|
|
102
|
-
ctLoc.endLine = ctLoc.startLine;
|
|
103
|
-
ctLoc.endCol = ctLoc.startCol;
|
|
104
|
-
ctLoc.endOffset = ctLoc.startOffset;
|
|
105
|
-
} else {
|
|
106
|
-
ctLoc.endLine = mxn.posTracker.line;
|
|
107
|
-
ctLoc.endCol = mxn.posTracker.col + 1;
|
|
108
|
-
ctLoc.endOffset = mxn.posTracker.offset + 1;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
orig._emitCurrentToken.call(this);
|
|
112
|
-
},
|
|
113
|
-
|
|
114
|
-
_emitCurrentCharacterToken() {
|
|
115
|
-
const ctLoc = this.currentCharacterToken && this.currentCharacterToken.location;
|
|
116
|
-
|
|
117
|
-
//NOTE: if we have character token and it's location wasn't set in the _emitCurrentToken(),
|
|
118
|
-
//then set it's location at the current preprocessor position.
|
|
119
|
-
//We don't need to increment preprocessor position, since character token
|
|
120
|
-
//emission is always forced by the start of the next character token here.
|
|
121
|
-
//So, we already have advanced position.
|
|
122
|
-
if (ctLoc && ctLoc.endOffset === -1) {
|
|
123
|
-
ctLoc.endLine = mxn.posTracker.line;
|
|
124
|
-
ctLoc.endCol = mxn.posTracker.col;
|
|
125
|
-
ctLoc.endOffset = mxn.posTracker.offset;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
orig._emitCurrentCharacterToken.call(this);
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
//NOTE: patch initial states for each mode to obtain token start position
|
|
133
|
-
Object.keys(Tokenizer.MODE).forEach(modeName => {
|
|
134
|
-
const state = Tokenizer.MODE[modeName];
|
|
135
|
-
|
|
136
|
-
methods[state] = function(cp) {
|
|
137
|
-
mxn.ctLoc = mxn._getCurrentLocation();
|
|
138
|
-
orig[state].call(this, cp);
|
|
139
|
-
};
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
return methods;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
module.exports = LocationInfoTokenizerMixin;
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const Mixin = require('../../utils/mixin');
|
|
4
|
-
|
|
5
|
-
class PositionTrackingPreprocessorMixin extends Mixin {
|
|
6
|
-
constructor(preprocessor) {
|
|
7
|
-
super(preprocessor);
|
|
8
|
-
|
|
9
|
-
this.preprocessor = preprocessor;
|
|
10
|
-
this.isEol = false;
|
|
11
|
-
this.lineStartPos = 0;
|
|
12
|
-
this.droppedBufferSize = 0;
|
|
13
|
-
|
|
14
|
-
this.offset = 0;
|
|
15
|
-
this.col = 0;
|
|
16
|
-
this.line = 1;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
_getOverriddenMethods(mxn, orig) {
|
|
20
|
-
return {
|
|
21
|
-
advance() {
|
|
22
|
-
const pos = this.pos + 1;
|
|
23
|
-
const ch = this.html[pos];
|
|
24
|
-
|
|
25
|
-
//NOTE: LF should be in the last column of the line
|
|
26
|
-
if (mxn.isEol) {
|
|
27
|
-
mxn.isEol = false;
|
|
28
|
-
mxn.line++;
|
|
29
|
-
mxn.lineStartPos = pos;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (ch === '\n' || (ch === '\r' && this.html[pos + 1] !== '\n')) {
|
|
33
|
-
mxn.isEol = true;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
mxn.col = pos - mxn.lineStartPos + 1;
|
|
37
|
-
mxn.offset = mxn.droppedBufferSize + pos;
|
|
38
|
-
|
|
39
|
-
return orig.advance.call(this);
|
|
40
|
-
},
|
|
41
|
-
|
|
42
|
-
retreat() {
|
|
43
|
-
orig.retreat.call(this);
|
|
44
|
-
|
|
45
|
-
mxn.isEol = false;
|
|
46
|
-
mxn.col = this.pos - mxn.lineStartPos + 1;
|
|
47
|
-
},
|
|
48
|
-
|
|
49
|
-
dropParsedChunk() {
|
|
50
|
-
const prevPos = this.pos;
|
|
51
|
-
|
|
52
|
-
orig.dropParsedChunk.call(this);
|
|
53
|
-
|
|
54
|
-
const reduction = prevPos - this.pos;
|
|
55
|
-
|
|
56
|
-
mxn.lineStartPos -= reduction;
|
|
57
|
-
mxn.droppedBufferSize += reduction;
|
|
58
|
-
mxn.offset = mxn.droppedBufferSize + this.pos;
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
module.exports = PositionTrackingPreprocessorMixin;
|
package/lib/index.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const Parser = require('./parser');
|
|
4
|
-
const Serializer = require('./serializer');
|
|
5
|
-
|
|
6
|
-
// Shorthands
|
|
7
|
-
exports.parse = function parse(html, options) {
|
|
8
|
-
const parser = new Parser(options);
|
|
9
|
-
|
|
10
|
-
return parser.parse(html);
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
exports.parseFragment = function parseFragment(fragmentContext, html, options) {
|
|
14
|
-
if (typeof fragmentContext === 'string') {
|
|
15
|
-
options = html;
|
|
16
|
-
html = fragmentContext;
|
|
17
|
-
fragmentContext = null;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const parser = new Parser(options);
|
|
21
|
-
|
|
22
|
-
return parser.parseFragment(html, fragmentContext);
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
exports.serialize = function(node, options) {
|
|
26
|
-
const serializer = new Serializer(node, options);
|
|
27
|
-
|
|
28
|
-
return serializer.serialize();
|
|
29
|
-
};
|
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
//Const
|
|
4
|
-
const NOAH_ARK_CAPACITY = 3;
|
|
5
|
-
|
|
6
|
-
//List of formatting elements
|
|
7
|
-
class FormattingElementList {
|
|
8
|
-
constructor(treeAdapter) {
|
|
9
|
-
this.length = 0;
|
|
10
|
-
this.entries = [];
|
|
11
|
-
this.treeAdapter = treeAdapter;
|
|
12
|
-
this.bookmark = null;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
//Noah Ark's condition
|
|
16
|
-
//OPTIMIZATION: at first we try to find possible candidates for exclusion using
|
|
17
|
-
//lightweight heuristics without thorough attributes check.
|
|
18
|
-
_getNoahArkConditionCandidates(newElement) {
|
|
19
|
-
const candidates = [];
|
|
20
|
-
|
|
21
|
-
if (this.length >= NOAH_ARK_CAPACITY) {
|
|
22
|
-
const neAttrsLength = this.treeAdapter.getAttrList(newElement).length;
|
|
23
|
-
const neTagName = this.treeAdapter.getTagName(newElement);
|
|
24
|
-
const neNamespaceURI = this.treeAdapter.getNamespaceURI(newElement);
|
|
25
|
-
|
|
26
|
-
for (let i = this.length - 1; i >= 0; i--) {
|
|
27
|
-
const entry = this.entries[i];
|
|
28
|
-
|
|
29
|
-
if (entry.type === FormattingElementList.MARKER_ENTRY) {
|
|
30
|
-
break;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const element = entry.element;
|
|
34
|
-
const elementAttrs = this.treeAdapter.getAttrList(element);
|
|
35
|
-
|
|
36
|
-
const isCandidate =
|
|
37
|
-
this.treeAdapter.getTagName(element) === neTagName &&
|
|
38
|
-
this.treeAdapter.getNamespaceURI(element) === neNamespaceURI &&
|
|
39
|
-
elementAttrs.length === neAttrsLength;
|
|
40
|
-
|
|
41
|
-
if (isCandidate) {
|
|
42
|
-
candidates.push({ idx: i, attrs: elementAttrs });
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return candidates.length < NOAH_ARK_CAPACITY ? [] : candidates;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
_ensureNoahArkCondition(newElement) {
|
|
51
|
-
const candidates = this._getNoahArkConditionCandidates(newElement);
|
|
52
|
-
let cLength = candidates.length;
|
|
53
|
-
|
|
54
|
-
if (cLength) {
|
|
55
|
-
const neAttrs = this.treeAdapter.getAttrList(newElement);
|
|
56
|
-
const neAttrsLength = neAttrs.length;
|
|
57
|
-
const neAttrsMap = Object.create(null);
|
|
58
|
-
|
|
59
|
-
//NOTE: build attrs map for the new element so we can perform fast lookups
|
|
60
|
-
for (let i = 0; i < neAttrsLength; i++) {
|
|
61
|
-
const neAttr = neAttrs[i];
|
|
62
|
-
|
|
63
|
-
neAttrsMap[neAttr.name] = neAttr.value;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
for (let i = 0; i < neAttrsLength; i++) {
|
|
67
|
-
for (let j = 0; j < cLength; j++) {
|
|
68
|
-
const cAttr = candidates[j].attrs[i];
|
|
69
|
-
|
|
70
|
-
if (neAttrsMap[cAttr.name] !== cAttr.value) {
|
|
71
|
-
candidates.splice(j, 1);
|
|
72
|
-
cLength--;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (candidates.length < NOAH_ARK_CAPACITY) {
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
//NOTE: remove bottommost candidates until Noah's Ark condition will not be met
|
|
82
|
-
for (let i = cLength - 1; i >= NOAH_ARK_CAPACITY - 1; i--) {
|
|
83
|
-
this.entries.splice(candidates[i].idx, 1);
|
|
84
|
-
this.length--;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
//Mutations
|
|
90
|
-
insertMarker() {
|
|
91
|
-
this.entries.push({ type: FormattingElementList.MARKER_ENTRY });
|
|
92
|
-
this.length++;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
pushElement(element, token) {
|
|
96
|
-
this._ensureNoahArkCondition(element);
|
|
97
|
-
|
|
98
|
-
this.entries.push({
|
|
99
|
-
type: FormattingElementList.ELEMENT_ENTRY,
|
|
100
|
-
element: element,
|
|
101
|
-
token: token
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
this.length++;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
insertElementAfterBookmark(element, token) {
|
|
108
|
-
let bookmarkIdx = this.length - 1;
|
|
109
|
-
|
|
110
|
-
for (; bookmarkIdx >= 0; bookmarkIdx--) {
|
|
111
|
-
if (this.entries[bookmarkIdx] === this.bookmark) {
|
|
112
|
-
break;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
this.entries.splice(bookmarkIdx + 1, 0, {
|
|
117
|
-
type: FormattingElementList.ELEMENT_ENTRY,
|
|
118
|
-
element: element,
|
|
119
|
-
token: token
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
this.length++;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
removeEntry(entry) {
|
|
126
|
-
for (let i = this.length - 1; i >= 0; i--) {
|
|
127
|
-
if (this.entries[i] === entry) {
|
|
128
|
-
this.entries.splice(i, 1);
|
|
129
|
-
this.length--;
|
|
130
|
-
break;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
clearToLastMarker() {
|
|
136
|
-
while (this.length) {
|
|
137
|
-
const entry = this.entries.pop();
|
|
138
|
-
|
|
139
|
-
this.length--;
|
|
140
|
-
|
|
141
|
-
if (entry.type === FormattingElementList.MARKER_ENTRY) {
|
|
142
|
-
break;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
//Search
|
|
148
|
-
getElementEntryInScopeWithTagName(tagName) {
|
|
149
|
-
for (let i = this.length - 1; i >= 0; i--) {
|
|
150
|
-
const entry = this.entries[i];
|
|
151
|
-
|
|
152
|
-
if (entry.type === FormattingElementList.MARKER_ENTRY) {
|
|
153
|
-
return null;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
if (this.treeAdapter.getTagName(entry.element) === tagName) {
|
|
157
|
-
return entry;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
return null;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
getElementEntry(element) {
|
|
165
|
-
for (let i = this.length - 1; i >= 0; i--) {
|
|
166
|
-
const entry = this.entries[i];
|
|
167
|
-
|
|
168
|
-
if (entry.type === FormattingElementList.ELEMENT_ENTRY && entry.element === element) {
|
|
169
|
-
return entry;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
return null;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
//Entry types
|
|
178
|
-
FormattingElementList.MARKER_ENTRY = 'MARKER_ENTRY';
|
|
179
|
-
FormattingElementList.ELEMENT_ENTRY = 'ELEMENT_ENTRY';
|
|
180
|
-
|
|
181
|
-
module.exports = FormattingElementList;
|