UNPKG

3.07 kBJavaScriptView Raw
1var ElementType = require("./ElementType.js");
2
3function DomHandler(callback, options){
4 this._options = typeof callback === "object" ? callback : options || defaultOpts;
5 this._callback = typeof callback === "object" ? null : callback;
6 this.dom = [];
7 this._done = false;
8 this._tagStack = [];
9}
10
11//default options
12var defaultOpts = {
13 ignoreWhitespace: false, //Keep whitespace-only text nodes
14 refParent: false //add a reference to the elements parent node
15};
16
17//Resets the handler back to starting state
18DomHandler.prototype.onreset = function(){
19 DomHandler.call(this, this._callback, this._options);
20};
21
22//Signals the handler that parsing is done
23DomHandler.prototype.onend = function(){
24 if(this._done) return;
25 this._done = true;
26 this._handleCallback(null);
27};
28
29DomHandler.prototype._handleCallback =
30DomHandler.prototype.onerror = function(error){
31 if(typeof this._callback === "function"){
32 this._callback(error, this.dom);
33 } else {
34 if(error) throw error;
35 }
36};
37
38DomHandler.prototype.onclosetag = function(name){
39 //if(this._tagStack.pop().name !== name) this._handleCallback(Error("Tagname didn't match!"));
40 this._tagStack.pop();
41};
42
43DomHandler.prototype._addDomElement = function(element){
44 var lastChild,
45 lastTag = this._tagStack[this._tagStack.length - 1];
46
47 if(lastTag){ //There are parent elements
48 if(this._options.refParent){
49 element.parent = lastTag;
50 }
51 if(!lastTag.children){
52 lastTag.children = [element];
53 return;
54 }
55 lastChild = lastTag.children[lastTag.children.length - 1];
56 if(element.type === ElementType.Text && lastChild.type === ElementType.Text){
57 lastChild.data += element.data;
58 } else {
59 lastTag.children.push(element);
60 }
61 }
62 else {
63 this.dom.push(element);
64 }
65};
66
67DomHandler.prototype.onopentagname = function(name){
68 var element = {
69 type: name === "script" ? ElementType.Script : name === "style" ? ElementType.Style : ElementType.Tag,
70 name: name
71 };
72 this._addDomElement(element);
73 this._tagStack.push(element);
74};
75
76DomHandler.prototype.onattribute = function(name, value){
77 var element = this._tagStack[this._tagStack.length-1];
78 if(!("attribs" in element)) element.attribs = {};
79 element.attribs[name] = value;
80};
81
82DomHandler.prototype.ontext = function(data){
83 if(this._options.ignoreWhitespace && data.trim() === "") return;
84 this._addDomElement({
85 data: data,
86 type: ElementType.Text
87 });
88};
89
90DomHandler.prototype.oncomment = function(data){
91 var lastTag = this._tagStack[this._tagStack.length - 1];
92
93 if(lastTag && lastTag.type === ElementType.Comment){
94 lastTag.data += data;
95 return;
96 }
97
98 var element = {
99 data: data,
100 type: ElementType.Comment
101 };
102
103 if(!lastTag) this.dom.push(element);
104 else if(!lastTag.children) lastTag.children = [element];
105 else lastTag.children.push(element);
106
107 this._tagStack.push(element);
108};
109
110DomHandler.prototype.oncommentend = function(){
111 this._tagStack.pop();
112};
113
114DomHandler.prototype.onprocessinginstruction = function(name, data){
115 this._addDomElement({
116 name: name,
117 data: data,
118 type: ElementType.Directive
119 });
120};
121
122module.exports = DomHandler;
\No newline at end of file