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();
 | 
						|
};
 | 
						|
 |