UNPKG

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