summaryrefslogtreecommitdiff
path: root/tools/eslint/node_modules/parse5/lib/parser/stream.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/eslint/node_modules/parse5/lib/parser/stream.js')
-rw-r--r--tools/eslint/node_modules/parse5/lib/parser/stream.js139
1 files changed, 139 insertions, 0 deletions
diff --git a/tools/eslint/node_modules/parse5/lib/parser/stream.js b/tools/eslint/node_modules/parse5/lib/parser/stream.js
new file mode 100644
index 0000000000..87b0447845
--- /dev/null
+++ b/tools/eslint/node_modules/parse5/lib/parser/stream.js
@@ -0,0 +1,139 @@
+'use strict';
+
+var WritableStream = require('stream').Writable,
+ inherits = require('util').inherits,
+ Parser = require('./index');
+
+/**
+ * Streaming HTML parser with scripting support.
+ * A [writable stream]{@link https://nodejs.org/api/stream.html#stream_class_stream_writable}.
+ * @class ParserStream
+ * @memberof parse5
+ * @instance
+ * @extends stream.Writable
+ * @param {ParserOptions} options - Parsing options.
+ * @example
+ * var parse5 = require('parse5');
+ * var http = require('http');
+ *
+ * // Fetch the google.com content and obtain it's <body> node
+ * http.get('http://google.com', function(res) {
+ * var parser = new parse5.ParserStream();
+ *
+ * parser.on('finish', function() {
+ * var body = parser.document.childNodes[0].childNodes[1];
+ * });
+ *
+ * res.pipe(parser);
+ * });
+ */
+var ParserStream = module.exports = function (options) {
+ WritableStream.call(this);
+
+ this.parser = new Parser(options);
+
+ this.lastChunkWritten = false;
+ this.writeCallback = null;
+ this.pausedByScript = false;
+
+ /**
+ * The resulting document node.
+ * @member {ASTNode<document>} document
+ * @memberof parse5#ParserStream
+ * @instance
+ */
+ this.document = this.parser.treeAdapter.createDocument();
+
+ this.pendingHtmlInsertions = [];
+
+ this._resume = this._resume.bind(this);
+ this._documentWrite = this._documentWrite.bind(this);
+ this._scriptHandler = this._scriptHandler.bind(this);
+
+ this.parser._bootstrap(this.document, null);
+};
+
+inherits(ParserStream, WritableStream);
+
+//WritableStream implementation
+ParserStream.prototype._write = function (chunk, encoding, callback) {
+ this.writeCallback = callback;
+ this.parser.tokenizer.write(chunk.toString('utf8'), this.lastChunkWritten);
+ this._runParsingLoop();
+};
+
+ParserStream.prototype.end = function (chunk, encoding, callback) {
+ this.lastChunkWritten = true;
+ WritableStream.prototype.end.call(this, chunk, encoding, callback);
+};
+
+//Scriptable parser implementation
+ParserStream.prototype._runParsingLoop = function () {
+ this.parser._runParsingLoop(this.writeCallback, this._scriptHandler);
+};
+
+ParserStream.prototype._resume = function () {
+ if (!this.pausedByScript)
+ throw new Error('Parser was already resumed');
+
+ while (this.pendingHtmlInsertions.length) {
+ var html = this.pendingHtmlInsertions.pop();
+
+ this.parser.tokenizer.insertHtmlAtCurrentPos(html);
+ }
+
+ this.pausedByScript = false;
+
+ //NOTE: keep parsing if we don't wait for the next input chunk
+ if (this.parser.tokenizer.active)
+ this._runParsingLoop();
+};
+
+ParserStream.prototype._documentWrite = function (html) {
+ if (!this.parser.stopped)
+ this.pendingHtmlInsertions.push(html);
+};
+
+ParserStream.prototype._scriptHandler = function (scriptElement) {
+ if (this.listeners('script').length) {
+ this.pausedByScript = true;
+
+ /**
+ * Raised then parser encounters a `<script>` element.
+ * If this event has listeners, parsing will be suspended once it is emitted.
+ * So, if `<script>` has the `src` attribute, you can fetch it, execute and then resume parsing just like browsers do.
+ * @event script
+ * @memberof parse5#ParserStream
+ * @instance
+ * @type {Function}
+ * @param {ASTNode} scriptElement - The script element that caused the event.
+ * @param {Function} documentWrite(html) - Write additional `html` at the current parsing position.
+ * Suitable for implementing the DOM `document.write` and `document.writeln` methods.
+ * @param {Function} resume - Resumes parsing.
+ * @example
+ * var parse = require('parse5');
+ * var http = require('http');
+ *
+ * var parser = new parse5.ParserStream();
+ *
+ * parser.on('script', function(scriptElement, documentWrite, resume) {
+ * var src = parse5.treeAdapters.default.getAttrList(scriptElement)[0].value;
+ *
+ * http.get(src, function(res) {
+ * // Fetch the script content, execute it with DOM built around `parser.document` and
+ * // `document.write` implemented using `documentWrite`.
+ * ...
+ * // Then resume parsing.
+ * resume();
+ * });
+ * });
+ *
+ * parser.end('<script src="example.com/script.js"></script>');
+ */
+
+
+ this.emit('script', scriptElement, this._documentWrite, this._resume);
+ }
+ else
+ this._runParsingLoop();
+};