77 lines
2.2 KiB
JavaScript
77 lines
2.2 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
var WritableStream = require('stream').Writable,
|
||
|
inherits = require('util').inherits,
|
||
|
Parser = require('./index');
|
||
|
|
||
|
var ParserStream = module.exports = function (options) {
|
||
|
WritableStream.call(this);
|
||
|
|
||
|
this.parser = new Parser(options);
|
||
|
|
||
|
this.lastChunkWritten = false;
|
||
|
this.writeCallback = null;
|
||
|
this.pausedByScript = false;
|
||
|
|
||
|
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.runParsingLoopForCurrentChunk(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;
|
||
|
this.emit('script', scriptElement, this._documentWrite, this._resume);
|
||
|
}
|
||
|
else
|
||
|
this._runParsingLoop();
|
||
|
};
|
||
|
|