| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 | 
							- var ElementType = require("domelementtype");
 
- var re_whitespace = /\s+/g;
 
- var NodePrototype = require("./lib/node");
 
- var ElementPrototype = require("./lib/element");
 
- function DomHandler(callback, options, elementCB){
 
- 	if(typeof callback === "object"){
 
- 		elementCB = options;
 
- 		options = callback;
 
- 		callback = null;
 
- 	} else if(typeof options === "function"){
 
- 		elementCB = options;
 
- 		options = defaultOpts;
 
- 	}
 
- 	this._callback = callback;
 
- 	this._options = options || defaultOpts;
 
- 	this._elementCB = elementCB;
 
- 	this.dom = [];
 
- 	this._done = false;
 
- 	this._tagStack = [];
 
- 	this._parser = this._parser || null;
 
- }
 
- //default options
 
- var defaultOpts = {
 
- 	normalizeWhitespace: false, //Replace all whitespace with single spaces
 
- 	withStartIndices: false, //Add startIndex properties to nodes
 
- 	withEndIndices: false, //Add endIndex properties to nodes
 
- };
 
- DomHandler.prototype.onparserinit = function(parser){
 
- 	this._parser = parser;
 
- };
 
- //Resets the handler back to starting state
 
- DomHandler.prototype.onreset = function(){
 
- 	DomHandler.call(this, this._callback, this._options, this._elementCB);
 
- };
 
- //Signals the handler that parsing is done
 
- DomHandler.prototype.onend = function(){
 
- 	if(this._done) return;
 
- 	this._done = true;
 
- 	this._parser = null;
 
- 	this._handleCallback(null);
 
- };
 
- DomHandler.prototype._handleCallback =
 
- DomHandler.prototype.onerror = function(error){
 
- 	if(typeof this._callback === "function"){
 
- 		this._callback(error, this.dom);
 
- 	} else {
 
- 		if(error) throw error;
 
- 	}
 
- };
 
- DomHandler.prototype.onclosetag = function(){
 
- 	//if(this._tagStack.pop().name !== name) this._handleCallback(Error("Tagname didn't match!"));
 
- 	
 
- 	var elem = this._tagStack.pop();
 
- 	if(this._options.withEndIndices && elem){
 
- 		elem.endIndex = this._parser.endIndex;
 
- 	}
 
- 	if(this._elementCB) this._elementCB(elem);
 
- };
 
- DomHandler.prototype._createDomElement = function(properties){
 
- 	if (!this._options.withDomLvl1) return properties;
 
- 	var element;
 
- 	if (properties.type === "tag") {
 
- 		element = Object.create(ElementPrototype);
 
- 	} else {
 
- 		element = Object.create(NodePrototype);
 
- 	}
 
- 	for (var key in properties) {
 
- 		if (properties.hasOwnProperty(key)) {
 
- 			element[key] = properties[key];
 
- 		}
 
- 	}
 
- 	return element;
 
- };
 
- DomHandler.prototype._addDomElement = function(element){
 
- 	var parent = this._tagStack[this._tagStack.length - 1];
 
- 	var siblings = parent ? parent.children : this.dom;
 
- 	var previousSibling = siblings[siblings.length - 1];
 
- 	element.next = null;
 
- 	if(this._options.withStartIndices){
 
- 		element.startIndex = this._parser.startIndex;
 
- 	}
 
- 	if(this._options.withEndIndices){
 
- 		element.endIndex = this._parser.endIndex;
 
- 	}
 
- 	if(previousSibling){
 
- 		element.prev = previousSibling;
 
- 		previousSibling.next = element;
 
- 	} else {
 
- 		element.prev = null;
 
- 	}
 
- 	siblings.push(element);
 
- 	element.parent = parent || null;
 
- };
 
- DomHandler.prototype.onopentag = function(name, attribs){
 
- 	var properties = {
 
- 		type: name === "script" ? ElementType.Script : name === "style" ? ElementType.Style : ElementType.Tag,
 
- 		name: name,
 
- 		attribs: attribs,
 
- 		children: []
 
- 	};
 
- 	var element = this._createDomElement(properties);
 
- 	this._addDomElement(element);
 
- 	this._tagStack.push(element);
 
- };
 
- DomHandler.prototype.ontext = function(data){
 
- 	//the ignoreWhitespace is officially dropped, but for now,
 
- 	//it's an alias for normalizeWhitespace
 
- 	var normalize = this._options.normalizeWhitespace || this._options.ignoreWhitespace;
 
- 	var lastTag;
 
- 	if(!this._tagStack.length && this.dom.length && (lastTag = this.dom[this.dom.length-1]).type === ElementType.Text){
 
- 		if(normalize){
 
- 			lastTag.data = (lastTag.data + data).replace(re_whitespace, " ");
 
- 		} else {
 
- 			lastTag.data += data;
 
- 		}
 
- 	} else {
 
- 		if(
 
- 			this._tagStack.length &&
 
- 			(lastTag = this._tagStack[this._tagStack.length - 1]) &&
 
- 			(lastTag = lastTag.children[lastTag.children.length - 1]) &&
 
- 			lastTag.type === ElementType.Text
 
- 		){
 
- 			if(normalize){
 
- 				lastTag.data = (lastTag.data + data).replace(re_whitespace, " ");
 
- 			} else {
 
- 				lastTag.data += data;
 
- 			}
 
- 		} else {
 
- 			if(normalize){
 
- 				data = data.replace(re_whitespace, " ");
 
- 			}
 
- 			var element = this._createDomElement({
 
- 				data: data,
 
- 				type: ElementType.Text
 
- 			});
 
- 			this._addDomElement(element);
 
- 		}
 
- 	}
 
- };
 
- DomHandler.prototype.oncomment = function(data){
 
- 	var lastTag = this._tagStack[this._tagStack.length - 1];
 
- 	if(lastTag && lastTag.type === ElementType.Comment){
 
- 		lastTag.data += data;
 
- 		return;
 
- 	}
 
- 	var properties = {
 
- 		data: data,
 
- 		type: ElementType.Comment
 
- 	};
 
- 	var element = this._createDomElement(properties);
 
- 	this._addDomElement(element);
 
- 	this._tagStack.push(element);
 
- };
 
- DomHandler.prototype.oncdatastart = function(){
 
- 	var properties = {
 
- 		children: [{
 
- 			data: "",
 
- 			type: ElementType.Text
 
- 		}],
 
- 		type: ElementType.CDATA
 
- 	};
 
- 	var element = this._createDomElement(properties);
 
- 	this._addDomElement(element);
 
- 	this._tagStack.push(element);
 
- };
 
- DomHandler.prototype.oncommentend = DomHandler.prototype.oncdataend = function(){
 
- 	this._tagStack.pop();
 
- };
 
- DomHandler.prototype.onprocessinginstruction = function(name, data){
 
- 	var element = this._createDomElement({
 
- 		name: name,
 
- 		data: data,
 
- 		type: ElementType.Directive
 
- 	});
 
- 	this._addDomElement(element);
 
- };
 
- module.exports = DomHandler;
 
 
  |