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