.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / domhandler / index.js
1 var ElementType = require("domelementtype");
2
3 var re_whitespace = /\s+/g;
4 var NodePrototype = require("./lib/node");
5 var ElementPrototype = require("./lib/element");
6
7 function DomHandler(callback, options, elementCB){
8         if(typeof callback === "object"){
9                 elementCB = options;
10                 options = callback;
11                 callback = null;
12         } else if(typeof options === "function"){
13                 elementCB = options;
14                 options = defaultOpts;
15         }
16         this._callback = callback;
17         this._options = options || defaultOpts;
18         this._elementCB = elementCB;
19         this.dom = [];
20         this._done = false;
21         this._tagStack = [];
22         this._parser = this._parser || null;
23 }
24
25 //default options
26 var defaultOpts = {
27         normalizeWhitespace: false, //Replace all whitespace with single spaces
28         withStartIndices: false, //Add startIndex properties to nodes
29         withEndIndices: false, //Add endIndex properties to nodes
30 };
31
32 DomHandler.prototype.onparserinit = function(parser){
33         this._parser = parser;
34 };
35
36 //Resets the handler back to starting state
37 DomHandler.prototype.onreset = function(){
38         DomHandler.call(this, this._callback, this._options, this._elementCB);
39 };
40
41 //Signals the handler that parsing is done
42 DomHandler.prototype.onend = function(){
43         if(this._done) return;
44         this._done = true;
45         this._parser = null;
46         this._handleCallback(null);
47 };
48
49 DomHandler.prototype._handleCallback =
50 DomHandler.prototype.onerror = function(error){
51         if(typeof this._callback === "function"){
52                 this._callback(error, this.dom);
53         } else {
54                 if(error) throw error;
55         }
56 };
57
58 DomHandler.prototype.onclosetag = function(){
59         //if(this._tagStack.pop().name !== name) this._handleCallback(Error("Tagname didn't match!"));
60         
61         var elem = this._tagStack.pop();
62
63         if(this._options.withEndIndices && elem){
64                 elem.endIndex = this._parser.endIndex;
65         }
66
67         if(this._elementCB) this._elementCB(elem);
68 };
69
70 DomHandler.prototype._createDomElement = function(properties){
71         if (!this._options.withDomLvl1) return properties;
72
73         var element;
74         if (properties.type === "tag") {
75                 element = Object.create(ElementPrototype);
76         } else {
77                 element = Object.create(NodePrototype);
78         }
79
80         for (var key in properties) {
81                 if (properties.hasOwnProperty(key)) {
82                         element[key] = properties[key];
83                 }
84         }
85
86         return element;
87 };
88
89 DomHandler.prototype._addDomElement = function(element){
90         var parent = this._tagStack[this._tagStack.length - 1];
91         var siblings = parent ? parent.children : this.dom;
92         var previousSibling = siblings[siblings.length - 1];
93
94         element.next = null;
95
96         if(this._options.withStartIndices){
97                 element.startIndex = this._parser.startIndex;
98         }
99         if(this._options.withEndIndices){
100                 element.endIndex = this._parser.endIndex;
101         }
102
103         if(previousSibling){
104                 element.prev = previousSibling;
105                 previousSibling.next = element;
106         } else {
107                 element.prev = null;
108         }
109
110         siblings.push(element);
111         element.parent = parent || null;
112 };
113
114 DomHandler.prototype.onopentag = function(name, attribs){
115         var properties = {
116                 type: name === "script" ? ElementType.Script : name === "style" ? ElementType.Style : ElementType.Tag,
117                 name: name,
118                 attribs: attribs,
119                 children: []
120         };
121
122         var element = this._createDomElement(properties);
123
124         this._addDomElement(element);
125
126         this._tagStack.push(element);
127 };
128
129 DomHandler.prototype.ontext = function(data){
130         //the ignoreWhitespace is officially dropped, but for now,
131         //it's an alias for normalizeWhitespace
132         var normalize = this._options.normalizeWhitespace || this._options.ignoreWhitespace;
133
134         var lastTag;
135
136         if(!this._tagStack.length && this.dom.length && (lastTag = this.dom[this.dom.length-1]).type === ElementType.Text){
137                 if(normalize){
138                         lastTag.data = (lastTag.data + data).replace(re_whitespace, " ");
139                 } else {
140                         lastTag.data += data;
141                 }
142         } else {
143                 if(
144                         this._tagStack.length &&
145                         (lastTag = this._tagStack[this._tagStack.length - 1]) &&
146                         (lastTag = lastTag.children[lastTag.children.length - 1]) &&
147                         lastTag.type === ElementType.Text
148                 ){
149                         if(normalize){
150                                 lastTag.data = (lastTag.data + data).replace(re_whitespace, " ");
151                         } else {
152                                 lastTag.data += data;
153                         }
154                 } else {
155                         if(normalize){
156                                 data = data.replace(re_whitespace, " ");
157                         }
158
159                         var element = this._createDomElement({
160                                 data: data,
161                                 type: ElementType.Text
162                         });
163
164                         this._addDomElement(element);
165                 }
166         }
167 };
168
169 DomHandler.prototype.oncomment = function(data){
170         var lastTag = this._tagStack[this._tagStack.length - 1];
171
172         if(lastTag && lastTag.type === ElementType.Comment){
173                 lastTag.data += data;
174                 return;
175         }
176
177         var properties = {
178                 data: data,
179                 type: ElementType.Comment
180         };
181
182         var element = this._createDomElement(properties);
183
184         this._addDomElement(element);
185         this._tagStack.push(element);
186 };
187
188 DomHandler.prototype.oncdatastart = function(){
189         var properties = {
190                 children: [{
191                         data: "",
192                         type: ElementType.Text
193                 }],
194                 type: ElementType.CDATA
195         };
196
197         var element = this._createDomElement(properties);
198
199         this._addDomElement(element);
200         this._tagStack.push(element);
201 };
202
203 DomHandler.prototype.oncommentend = DomHandler.prototype.oncdataend = function(){
204         this._tagStack.pop();
205 };
206
207 DomHandler.prototype.onprocessinginstruction = function(name, data){
208         var element = this._createDomElement({
209                 name: name,
210                 data: data,
211                 type: ElementType.Directive
212         });
213
214         this._addDomElement(element);
215 };
216
217 module.exports = DomHandler;