parse5 1.0.1 → 1.1.3

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.
@@ -0,0 +1,68 @@
1
+ var Tokenizer = require('../tokenization/tokenizer'),
2
+ TokenizerProxy = require('./tokenizer_proxy');
3
+
4
+ //Skipping handler
5
+ function skip() {
6
+ //NOTE: do nothing =)
7
+ }
8
+
9
+ //SimpleApiParser
10
+ var SimpleApiParser = module.exports = function (handlers) {
11
+ this.handlers = {
12
+ doctype: handlers.doctype || skip,
13
+ startTag: handlers.startTag || skip,
14
+ endTag: handlers.endTag || skip,
15
+ text: handlers.text || skip,
16
+ comment: handlers.comment || skip
17
+ };
18
+ };
19
+
20
+ //API
21
+ SimpleApiParser.prototype.parse = function (html) {
22
+ var token = null;
23
+
24
+ this._reset(html);
25
+
26
+ do {
27
+ token = this.tokenizerProxy.getNextToken();
28
+
29
+ if (token.type === Tokenizer.CHARACTER_TOKEN ||
30
+ token.type === Tokenizer.WHITESPACE_CHARACTER_TOKEN ||
31
+ token.type === Tokenizer.NULL_CHARACTER_TOKEN) {
32
+ this.pendingText = (this.pendingText || '') + token.chars;
33
+ }
34
+
35
+ else {
36
+ this._emitPendingText();
37
+ this._handleToken(token);
38
+ }
39
+ } while (token.type !== Tokenizer.EOF_TOKEN)
40
+ };
41
+
42
+ //Internals
43
+ SimpleApiParser.prototype._handleToken = function (token) {
44
+ if (token.type === Tokenizer.START_TAG_TOKEN)
45
+ this.handlers.startTag(token.tagName, token.attrs, token.selfClosing);
46
+
47
+ else if (token.type === Tokenizer.END_TAG_TOKEN)
48
+ this.handlers.endTag(token.tagName);
49
+
50
+ else if (token.type === Tokenizer.COMMENT_TOKEN)
51
+ this.handlers.comment(token.data);
52
+
53
+ else if (token.type === Tokenizer.DOCTYPE_TOKEN)
54
+ this.handlers.doctype(token.name, token.publicId, token.systemId);
55
+
56
+ };
57
+
58
+ SimpleApiParser.prototype._reset = function (html) {
59
+ this.tokenizerProxy = new TokenizerProxy(html);
60
+ this.pendingText = null;
61
+ };
62
+
63
+ SimpleApiParser.prototype._emitPendingText = function () {
64
+ if (this.pendingText !== null) {
65
+ this.handlers.text(this.pendingText);
66
+ this.pendingText = null;
67
+ }
68
+ };
@@ -0,0 +1,119 @@
1
+ var Tokenizer = require('../tokenization/tokenizer'),
2
+ ForeignContent = require('../common/foreign_content'),
3
+ UNICODE = require('../common/unicode'),
4
+ HTML = require('../common/html');
5
+
6
+ //Aliases
7
+ var $ = HTML.TAG_NAMES,
8
+ NS = HTML.NAMESPACES;
9
+
10
+
11
+ //Tokenizer proxy
12
+ //NOTE: this proxy simulates adjustment of the Tokenizer which performed by standard parser during tree construction.
13
+ var TokenizerProxy = module.exports = function (html) {
14
+ this.tokenizer = new Tokenizer(html);
15
+
16
+ this.namespaceStack = [];
17
+ this.namespaceStackTop = -1;
18
+ this.currentNamespace = null;
19
+ this.inForeignContent = false;
20
+ };
21
+
22
+ //API
23
+ TokenizerProxy.prototype.getNextToken = function () {
24
+ var token = this.tokenizer.getNextToken();
25
+
26
+ if (token.type === Tokenizer.START_TAG_TOKEN)
27
+ this._handleStartTagToken(token);
28
+
29
+ else if (token.type === Tokenizer.END_TAG_TOKEN)
30
+ this._handleEndTagToken(token);
31
+
32
+ else if (token.type === Tokenizer.NULL_CHARACTER_TOKEN && this.inForeignContent) {
33
+ token.type = Tokenizer.CHARACTER_TOKEN;
34
+ token.chars = UNICODE.REPLACEMENT_CHARACTER;
35
+ }
36
+
37
+ return token;
38
+ };
39
+
40
+ //Namespace stack mutations
41
+ TokenizerProxy.prototype._enterNamespace = function (namespace) {
42
+ this.namespaceStackTop++;
43
+ this.namespaceStack.push(namespace);
44
+
45
+ this.inForeignContent = namespace !== NS.HTML;
46
+ this.currentNamespace = namespace;
47
+ this.tokenizer.allowCDATA = this.inForeignContent;
48
+ };
49
+
50
+ TokenizerProxy.prototype._leaveCurrentNamespace = function () {
51
+ this.namespaceStackTop--;
52
+ this.namespaceStack.pop();
53
+
54
+ this.currentNamespace = this.namespaceStack[this.namespaceStackTop];
55
+ this.inForeignContent = this.currentNamespace !== NS.HTML;
56
+ this.tokenizer.allowCDATA = this.inForeignContent;
57
+ };
58
+
59
+ //Token handlers
60
+ TokenizerProxy.prototype._ensureTokenizerState = function (tn) {
61
+ if (tn === $.TEXTAREA || tn === $.TITLE)
62
+ this.tokenizer.state = Tokenizer.RCDATA_STATE;
63
+
64
+ else if (tn === $.PLAINTEXT)
65
+ this.tokenizer.state = Tokenizer.PLAINTEXT_STATE;
66
+
67
+ else if (tn === $.SCRIPT)
68
+ this.tokenizer.state = Tokenizer.SCRIPT_DATA_STATE;
69
+
70
+ else if (tn === $.STYLE || tn === $.IFRAME || tn === $.XMP ||
71
+ tn === $.NOEMBED || tn === $.NOFRAMES || tn === $.NOSCRIPT) {
72
+ this.tokenizer.state = Tokenizer.RAWTEXT_STATE;
73
+ }
74
+ };
75
+
76
+ TokenizerProxy.prototype._handleStartTagToken = function (token) {
77
+ var tn = token.tagName;
78
+
79
+ if (tn === $.SVG)
80
+ this._enterNamespace(NS.SVG);
81
+
82
+ else if (tn === $.MATH)
83
+ this._enterNamespace(NS.MATHML);
84
+
85
+ else {
86
+ if (this.inForeignContent) {
87
+ if (ForeignContent.causesExit(token))
88
+ this._leaveCurrentNamespace();
89
+
90
+ else if (ForeignContent.isMathMLTextIntegrationPoint(tn, this.currentNamespace) ||
91
+ ForeignContent.isHtmlIntegrationPoint(tn, this.currentNamespace, token.attrs)) {
92
+ this._enterNamespace(NS.HTML);
93
+ }
94
+ }
95
+
96
+ else
97
+ this._ensureTokenizerState(tn);
98
+ }
99
+ };
100
+
101
+ TokenizerProxy.prototype._handleEndTagToken = function (token) {
102
+ var tn = token.tagName;
103
+
104
+ if (!this.inForeignContent) {
105
+ var previousNs = this.namespaceStack[this.namespaceStackTop - 1];
106
+
107
+ //NOTE: check for exit from integration point
108
+ if (ForeignContent.isMathMLTextIntegrationPoint(tn, previousNs) ||
109
+ ForeignContent.isHtmlIntegrationPoint(tn, previousNs, token.attrs)) {
110
+ this._leaveCurrentNamespace();
111
+ }
112
+
113
+ else if (tn === $.SCRIPT)
114
+ this.tokenizer.state = Tokenizer.DATA_STATE;
115
+ }
116
+
117
+ else if ((tn === $.SVG && this.currentNamespace === NS.SVG) || (tn === $.MATH && this.currentNamespace === NS.MATHML))
118
+ this._leaveCurrentNamespace();
119
+ };
@@ -1,4 +1,4 @@
1
- var UNICODE = require('../const/unicode');
1
+ var UNICODE = require('../common/unicode');
2
2
 
3
3
  //Aliases
4
4
  var $ = UNICODE.CODE_POINTS;
@@ -80,4 +80,4 @@ Preprocessor.prototype.retreat = function () {
80
80
  }
81
81
 
82
82
  this.pos--;
83
- };
83
+ };
@@ -1,5 +1,5 @@
1
1
  var Preprocessor = require('./preprocessor'),
2
- UNICODE = require('../const/unicode'),
2
+ UNICODE = require('../common/unicode'),
3
3
  NAMED_ENTITY_TRIE = require('./named_entity_trie');
4
4
 
5
5
  //Aliases
@@ -171,11 +171,22 @@ Tokenizer.DOCTYPE_TOKEN = 'DOCTYPE_TOKEN';
171
171
  Tokenizer.EOF_TOKEN = 'EOF_TOKEN';
172
172
 
173
173
  //States export
174
+ Tokenizer.DATA_STATE = DATA_STATE;
174
175
  Tokenizer.RCDATA_STATE = RCDATA_STATE;
175
176
  Tokenizer.RAWTEXT_STATE = RAWTEXT_STATE;
176
177
  Tokenizer.SCRIPT_DATA_STATE = SCRIPT_DATA_STATE;
177
178
  Tokenizer.PLAINTEXT_STATE = PLAINTEXT_STATE;
178
179
 
180
+ //Static
181
+ Tokenizer.getTokenAttr = function (token, attrName) {
182
+ for (var i = token.attrs.length - 1; i >= 0; i--) {
183
+ if (token.attrs[i].name === attrName)
184
+ return token.attrs[i].value;
185
+ }
186
+
187
+ return null;
188
+ };
189
+
179
190
  //Get token
180
191
  Tokenizer.prototype.getNextToken = function () {
181
192
  while (!this.tokenQueue.length)
@@ -310,14 +321,7 @@ Tokenizer.prototype._createAttr = function (attrNameFirstCh) {
310
321
  };
311
322
 
312
323
  Tokenizer.prototype._isDuplicateAttr = function () {
313
- var attrs = this.currentToken.attrs;
314
-
315
- for (var i = 0; i < attrs.length; i++) {
316
- if (attrs[i].name === this.currentAttr.name)
317
- return true;
318
- }
319
-
320
- return false;
324
+ return Tokenizer.getTokenAttr(this.currentToken, this.currentAttr.name) !== null;
321
325
  };
322
326
 
323
327
  Tokenizer.prototype._leaveAttrName = function (toState) {
@@ -2293,4 +2297,4 @@ _[CDATA_SECTION_STATE] = function cdataSectionState(cp) {
2293
2297
  cp = this._consume();
2294
2298
  }
2295
2299
  }
2296
- };
2300
+ };
@@ -195,4 +195,4 @@ exports.isDocumentTypeNode = function (node) {
195
195
 
196
196
  exports.isElementNode = function (node) {
197
197
  return !!node.tagName;
198
- };
198
+ };
@@ -264,4 +264,4 @@ exports.isDocumentTypeNode = function (node) {
264
264
 
265
265
  exports.isElementNode = function (node) {
266
266
  return !!node.attribs;
267
- };
267
+ };
@@ -0,0 +1,107 @@
1
+ //Const
2
+ var VALID_DOCTYPE_NAME = 'html',
3
+ QUIRKS_MODE_SYSTEM_ID = 'http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd',
4
+ QUIRKS_MODE_PUBLIC_ID_PREFIXES = [
5
+ "+//silmaril//dtd html pro v0r11 19970101//en",
6
+ "-//advasoft ltd//dtd html 3.0 aswedit + extensions//en",
7
+ "-//as//dtd html 3.0 aswedit + extensions//en",
8
+ "-//ietf//dtd html 2.0 level 1//en",
9
+ "-//ietf//dtd html 2.0 level 2//en",
10
+ "-//ietf//dtd html 2.0 strict level 1//en",
11
+ "-//ietf//dtd html 2.0 strict level 2//en",
12
+ "-//ietf//dtd html 2.0 strict//en",
13
+ "-//ietf//dtd html 2.0//en",
14
+ "-//ietf//dtd html 2.1e//en",
15
+ "-//ietf//dtd html 3.0//en",
16
+ "-//ietf//dtd html 3.0//en//",
17
+ "-//ietf//dtd html 3.2 final//en",
18
+ "-//ietf//dtd html 3.2//en",
19
+ "-//ietf//dtd html 3//en",
20
+ "-//ietf//dtd html level 0//en",
21
+ "-//ietf//dtd html level 0//en//2.0",
22
+ "-//ietf//dtd html level 1//en",
23
+ "-//ietf//dtd html level 1//en//2.0",
24
+ "-//ietf//dtd html level 2//en",
25
+ "-//ietf//dtd html level 2//en//2.0",
26
+ "-//ietf//dtd html level 3//en",
27
+ "-//ietf//dtd html level 3//en//3.0",
28
+ "-//ietf//dtd html strict level 0//en",
29
+ "-//ietf//dtd html strict level 0//en//2.0",
30
+ "-//ietf//dtd html strict level 1//en",
31
+ "-//ietf//dtd html strict level 1//en//2.0",
32
+ "-//ietf//dtd html strict level 2//en",
33
+ "-//ietf//dtd html strict level 2//en//2.0",
34
+ "-//ietf//dtd html strict level 3//en",
35
+ "-//ietf//dtd html strict level 3//en//3.0",
36
+ "-//ietf//dtd html strict//en",
37
+ "-//ietf//dtd html strict//en//2.0",
38
+ "-//ietf//dtd html strict//en//3.0",
39
+ "-//ietf//dtd html//en",
40
+ "-//ietf//dtd html//en//2.0",
41
+ "-//ietf//dtd html//en//3.0",
42
+ "-//metrius//dtd metrius presentational//en",
43
+ "-//microsoft//dtd internet explorer 2.0 html strict//en",
44
+ "-//microsoft//dtd internet explorer 2.0 html//en",
45
+ "-//microsoft//dtd internet explorer 2.0 tables//en",
46
+ "-//microsoft//dtd internet explorer 3.0 html strict//en",
47
+ "-//microsoft//dtd internet explorer 3.0 html//en",
48
+ "-//microsoft//dtd internet explorer 3.0 tables//en",
49
+ "-//netscape comm. corp.//dtd html//en",
50
+ "-//netscape comm. corp.//dtd strict html//en",
51
+ "-//o'reilly and associates//dtd html 2.0//en",
52
+ "-//o'reilly and associates//dtd html extended 1.0//en",
53
+ "-//spyglass//dtd html 2.0 extended//en",
54
+ "-//sq//dtd html 2.0 hotmetal + extensions//en",
55
+ "-//sun microsystems corp.//dtd hotjava html//en",
56
+ "-//sun microsystems corp.//dtd hotjava strict html//en",
57
+ "-//w3c//dtd html 3 1995-03-24//en",
58
+ "-//w3c//dtd html 3.2 draft//en",
59
+ "-//w3c//dtd html 3.2 final//en",
60
+ "-//w3c//dtd html 3.2//en",
61
+ "-//w3c//dtd html 3.2s draft//en",
62
+ "-//w3c//dtd html 4.0 frameset//en",
63
+ "-//w3c//dtd html 4.0 transitional//en",
64
+ "-//w3c//dtd html experimental 19960712//en",
65
+ "-//w3c//dtd html experimental 970421//en",
66
+ "-//w3c//dtd w3 html//en",
67
+ "-//w3o//dtd w3 html 3.0//en",
68
+ "-//w3o//dtd w3 html 3.0//en//",
69
+ "-//webtechs//dtd mozilla html 2.0//en",
70
+ "-//webtechs//dtd mozilla html//en"
71
+ ],
72
+ QUIRKS_MODE_NO_SYSTEM_ID_PUBLIC_ID_PREFIXES = [
73
+ '-//w3c//dtd html 4.01 frameset//',
74
+ '-//w3c//dtd html 4.01 transitional//'
75
+ ],
76
+ QUIRKS_MODE_PUBLIC_IDS = [
77
+ '-//w3o//dtd w3 html strict 3.0//en//',
78
+ '-/w3c/dtd html 4.0 transitional/en',
79
+ 'html'
80
+ ];
81
+
82
+ exports.isQuirks = function (name, publicId, systemId) {
83
+ if (name !== VALID_DOCTYPE_NAME)
84
+ return true;
85
+
86
+ if (systemId && systemId.toLowerCase() === QUIRKS_MODE_SYSTEM_ID)
87
+ return true;
88
+
89
+ if (publicId !== null) {
90
+ publicId = publicId.toLowerCase();
91
+
92
+ if (QUIRKS_MODE_PUBLIC_IDS.indexOf(publicId) > -1)
93
+ return true;
94
+
95
+ var prefixes = QUIRKS_MODE_PUBLIC_ID_PREFIXES;
96
+
97
+ if (systemId === null)
98
+ prefixes = prefixes.concat(QUIRKS_MODE_NO_SYSTEM_ID_PUBLIC_ID_PREFIXES);
99
+
100
+ for (var i = 0; i < prefixes.length; i++) {
101
+ if (publicId.indexOf(prefixes[i]) === 0)
102
+ return true;
103
+ }
104
+ }
105
+
106
+ return false;
107
+ };
@@ -1,4 +1,4 @@
1
- var HTML = require('../const/html');
1
+ var HTML = require('../common/html');
2
2
 
3
3
  //Aliases
4
4
  var $ = HTML.TAG_NAMES,