UNPKG

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