218 lines
5.1 KiB
JavaScript
218 lines
5.1 KiB
JavaScript
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;
|
|
};
|
|
|