.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / snapdragon-node / index.js
1 'use strict';
2
3 var isObject = require('isobject');
4 var define = require('define-property');
5 var utils = require('snapdragon-util');
6 var ownNames;
7
8 /**
9  * Create a new AST `Node` with the given `val` and `type`.
10  *
11  * ```js
12  * var node = new Node('*', 'Star');
13  * var node = new Node({type: 'star', val: '*'});
14  * ```
15  * @name Node
16  * @param {String|Object} `val` Pass a matched substring, or an object to merge onto the node.
17  * @param {String} `type` The node type to use when `val` is a string.
18  * @return {Object} node instance
19  * @api public
20  */
21
22 function Node(val, type, parent) {
23   if (typeof type !== 'string') {
24     parent = type;
25     type = null;
26   }
27
28   define(this, 'parent', parent);
29   define(this, 'isNode', true);
30   define(this, 'expect', null);
31
32   if (typeof type !== 'string' && isObject(val)) {
33     lazyKeys();
34     var keys = Object.keys(val);
35     for (var i = 0; i < keys.length; i++) {
36       var key = keys[i];
37       if (ownNames.indexOf(key) === -1) {
38         this[key] = val[key];
39       }
40     }
41   } else {
42     this.type = type;
43     this.val = val;
44   }
45 }
46
47 /**
48  * Returns true if the given value is a node.
49  *
50  * ```js
51  * var Node = require('snapdragon-node');
52  * var node = new Node({type: 'foo'});
53  * console.log(Node.isNode(node)); //=> true
54  * console.log(Node.isNode({})); //=> false
55  * ```
56  * @param {Object} `node`
57  * @returns {Boolean}
58  * @api public
59  */
60
61 Node.isNode = function(node) {
62   return utils.isNode(node);
63 };
64
65 /**
66  * Define a non-enumberable property on the node instance.
67  * Useful for adding properties that shouldn't be extended
68  * or visible during debugging.
69  *
70  * ```js
71  * var node = new Node();
72  * node.define('foo', 'something non-enumerable');
73  * ```
74  * @param {String} `name`
75  * @param {any} `val`
76  * @return {Object} returns the node instance
77  * @api public
78  */
79
80 Node.prototype.define = function(name, val) {
81   define(this, name, val);
82   return this;
83 };
84
85 /**
86  * Returns true if `node.val` is an empty string, or `node.nodes` does
87  * not contain any non-empty text nodes.
88  *
89  * ```js
90  * var node = new Node({type: 'text'});
91  * node.isEmpty(); //=> true
92  * node.val = 'foo';
93  * node.isEmpty(); //=> false
94  * ```
95  * @param {Function} `fn` (optional) Filter function that is called on `node` and/or child nodes. `isEmpty` will return false immediately when the filter function returns false on any nodes.
96  * @return {Boolean}
97  * @api public
98  */
99
100 Node.prototype.isEmpty = function(fn) {
101   return utils.isEmpty(this, fn);
102 };
103
104 /**
105  * Given node `foo` and node `bar`, push node `bar` onto `foo.nodes`, and
106  * set `foo` as `bar.parent`.
107  *
108  * ```js
109  * var foo = new Node({type: 'foo'});
110  * var bar = new Node({type: 'bar'});
111  * foo.push(bar);
112  * ```
113  * @param {Object} `node`
114  * @return {Number} Returns the length of `node.nodes`
115  * @api public
116  */
117
118 Node.prototype.push = function(node) {
119   assert(Node.isNode(node), 'expected node to be an instance of Node');
120   define(node, 'parent', this);
121
122   this.nodes = this.nodes || [];
123   return this.nodes.push(node);
124 };
125
126 /**
127  * Given node `foo` and node `bar`, unshift node `bar` onto `foo.nodes`, and
128  * set `foo` as `bar.parent`.
129  *
130  * ```js
131  * var foo = new Node({type: 'foo'});
132  * var bar = new Node({type: 'bar'});
133  * foo.unshift(bar);
134  * ```
135  * @param {Object} `node`
136  * @return {Number} Returns the length of `node.nodes`
137  * @api public
138  */
139
140 Node.prototype.unshift = function(node) {
141   assert(Node.isNode(node), 'expected node to be an instance of Node');
142   define(node, 'parent', this);
143
144   this.nodes = this.nodes || [];
145   return this.nodes.unshift(node);
146 };
147
148 /**
149  * Pop a node from `node.nodes`.
150  *
151  * ```js
152  * var node = new Node({type: 'foo'});
153  * node.push(new Node({type: 'a'}));
154  * node.push(new Node({type: 'b'}));
155  * node.push(new Node({type: 'c'}));
156  * node.push(new Node({type: 'd'}));
157  * console.log(node.nodes.length);
158  * //=> 4
159  * node.pop();
160  * console.log(node.nodes.length);
161  * //=> 3
162  * ```
163  * @return {Number} Returns the popped `node`
164  * @api public
165  */
166
167 Node.prototype.pop = function() {
168   return this.nodes && this.nodes.pop();
169 };
170
171 /**
172  * Shift a node from `node.nodes`.
173  *
174  * ```js
175  * var node = new Node({type: 'foo'});
176  * node.push(new Node({type: 'a'}));
177  * node.push(new Node({type: 'b'}));
178  * node.push(new Node({type: 'c'}));
179  * node.push(new Node({type: 'd'}));
180  * console.log(node.nodes.length);
181  * //=> 4
182  * node.shift();
183  * console.log(node.nodes.length);
184  * //=> 3
185  * ```
186  * @return {Object} Returns the shifted `node`
187  * @api public
188  */
189
190 Node.prototype.shift = function() {
191   return this.nodes && this.nodes.shift();
192 };
193
194 /**
195  * Remove `node` from `node.nodes`.
196  *
197  * ```js
198  * node.remove(childNode);
199  * ```
200  * @param {Object} `node`
201  * @return {Object} Returns the removed node.
202  * @api public
203  */
204
205 Node.prototype.remove = function(node) {
206   assert(Node.isNode(node), 'expected node to be an instance of Node');
207   this.nodes = this.nodes || [];
208   var idx = node.index;
209   if (idx !== -1) {
210     node.index = -1;
211     return this.nodes.splice(idx, 1);
212   }
213   return null;
214 };
215
216 /**
217  * Get the first child node from `node.nodes` that matches the given `type`.
218  * If `type` is a number, the child node at that index is returned.
219  *
220  * ```js
221  * var child = node.find(1); //<= index of the node to get
222  * var child = node.find('foo'); //<= node.type of a child node
223  * var child = node.find(/^(foo|bar)$/); //<= regex to match node.type
224  * var child = node.find(['foo', 'bar']); //<= array of node.type(s)
225  * ```
226  * @param {String} `type`
227  * @return {Object} Returns a child node or undefined.
228  * @api public
229  */
230
231 Node.prototype.find = function(type) {
232   return utils.findNode(this.nodes, type);
233 };
234
235 /**
236  * Return true if the node is the given `type`.
237  *
238  * ```js
239  * var node = new Node({type: 'bar'});
240  * cosole.log(node.isType('foo'));          // false
241  * cosole.log(node.isType(/^(foo|bar)$/));  // true
242  * cosole.log(node.isType(['foo', 'bar'])); // true
243  * ```
244  * @param {String} `type`
245  * @return {Boolean}
246  * @api public
247  */
248
249 Node.prototype.isType = function(type) {
250   return utils.isType(this, type);
251 };
252
253 /**
254  * Return true if the `node.nodes` has the given `type`.
255  *
256  * ```js
257  * var foo = new Node({type: 'foo'});
258  * var bar = new Node({type: 'bar'});
259  * foo.push(bar);
260  *
261  * cosole.log(foo.hasType('qux'));          // false
262  * cosole.log(foo.hasType(/^(qux|bar)$/));  // true
263  * cosole.log(foo.hasType(['qux', 'bar'])); // true
264  * ```
265  * @param {String} `type`
266  * @return {Boolean}
267  * @api public
268  */
269
270 Node.prototype.hasType = function(type) {
271   return utils.hasType(this, type);
272 };
273
274 /**
275  * Get the siblings array, or `null` if it doesn't exist.
276  *
277  * ```js
278  * var foo = new Node({type: 'foo'});
279  * var bar = new Node({type: 'bar'});
280  * var baz = new Node({type: 'baz'});
281  * foo.push(bar);
282  * foo.push(baz);
283  *
284  * console.log(bar.siblings.length) // 2
285  * console.log(baz.siblings.length) // 2
286  * ```
287  * @return {Array}
288  * @api public
289  */
290
291 Object.defineProperty(Node.prototype, 'siblings', {
292   set: function() {
293     throw new Error('node.siblings is a getter and cannot be defined');
294   },
295   get: function() {
296     return this.parent ? this.parent.nodes : null;
297   }
298 });
299
300 /**
301  * Get the node's current index from `node.parent.nodes`.
302  * This should always be correct, even when the parent adds nodes.
303  *
304  * ```js
305  * var foo = new Node({type: 'foo'});
306  * var bar = new Node({type: 'bar'});
307  * var baz = new Node({type: 'baz'});
308  * var qux = new Node({type: 'qux'});
309  * foo.push(bar);
310  * foo.push(baz);
311  * foo.unshift(qux);
312  *
313  * console.log(bar.index) // 1
314  * console.log(baz.index) // 2
315  * console.log(qux.index) // 0
316  * ```
317  * @return {Number}
318  * @api public
319  */
320
321 Object.defineProperty(Node.prototype, 'index', {
322   set: function(index) {
323     define(this, 'idx', index);
324   },
325   get: function() {
326     if (!Array.isArray(this.siblings)) {
327       return -1;
328     }
329     var tok = this.idx !== -1 ? this.siblings[this.idx] : null;
330     if (tok !== this) {
331       this.idx = this.siblings.indexOf(this);
332     }
333     return this.idx;
334   }
335 });
336
337 /**
338  * Get the previous node from the siblings array or `null`.
339  *
340  * ```js
341  * var foo = new Node({type: 'foo'});
342  * var bar = new Node({type: 'bar'});
343  * var baz = new Node({type: 'baz'});
344  * foo.push(bar);
345  * foo.push(baz);
346  *
347  * console.log(baz.prev.type) // 'bar'
348  * ```
349  * @return {Object}
350  * @api public
351  */
352
353 Object.defineProperty(Node.prototype, 'prev', {
354   set: function() {
355     throw new Error('node.prev is a getter and cannot be defined');
356   },
357   get: function() {
358     if (Array.isArray(this.siblings)) {
359       return this.siblings[this.index - 1] || this.parent.prev;
360     }
361     return null;
362   }
363 });
364
365 /**
366  * Get the siblings array, or `null` if it doesn't exist.
367  *
368  * ```js
369  * var foo = new Node({type: 'foo'});
370  * var bar = new Node({type: 'bar'});
371  * var baz = new Node({type: 'baz'});
372  * foo.push(bar);
373  * foo.push(baz);
374  *
375  * console.log(bar.siblings.length) // 2
376  * console.log(baz.siblings.length) // 2
377  * ```
378  * @return {Object}
379  * @api public
380  */
381
382 Object.defineProperty(Node.prototype, 'next', {
383   set: function() {
384     throw new Error('node.next is a getter and cannot be defined');
385   },
386   get: function() {
387     if (Array.isArray(this.siblings)) {
388       return this.siblings[this.index + 1] || this.parent.next;
389     }
390     return null;
391   }
392 });
393
394 /**
395  * Get the first node from `node.nodes`.
396  *
397  * ```js
398  * var foo = new Node({type: 'foo'});
399  * var bar = new Node({type: 'bar'});
400  * var baz = new Node({type: 'baz'});
401  * var qux = new Node({type: 'qux'});
402  * foo.push(bar);
403  * foo.push(baz);
404  * foo.push(qux);
405  *
406  * console.log(foo.first.type) // 'bar'
407  * ```
408  * @return {Object} The first node, or undefiend
409  * @api public
410  */
411
412 Object.defineProperty(Node.prototype, 'first', {
413   get: function() {
414     return this.nodes ? this.nodes[0] : null;
415   }
416 });
417
418 /**
419  * Get the last node from `node.nodes`.
420  *
421  * ```js
422  * var foo = new Node({type: 'foo'});
423  * var bar = new Node({type: 'bar'});
424  * var baz = new Node({type: 'baz'});
425  * var qux = new Node({type: 'qux'});
426  * foo.push(bar);
427  * foo.push(baz);
428  * foo.push(qux);
429  *
430  * console.log(foo.last.type) // 'qux'
431  * ```
432  * @return {Object} The last node, or undefiend
433  * @api public
434  */
435
436 Object.defineProperty(Node.prototype, 'last', {
437   get: function() {
438     return this.nodes ? utils.last(this.nodes) : null;
439   }
440 });
441
442 /**
443  * Get the last node from `node.nodes`.
444  *
445  * ```js
446  * var foo = new Node({type: 'foo'});
447  * var bar = new Node({type: 'bar'});
448  * var baz = new Node({type: 'baz'});
449  * var qux = new Node({type: 'qux'});
450  * foo.push(bar);
451  * foo.push(baz);
452  * foo.push(qux);
453  *
454  * console.log(foo.last.type) // 'qux'
455  * ```
456  * @return {Object} The last node, or undefiend
457  * @api public
458  */
459
460 Object.defineProperty(Node.prototype, 'scope', {
461   get: function() {
462     if (this.isScope !== true) {
463       return this.parent ? this.parent.scope : this;
464     }
465     return this;
466   }
467 });
468
469 /**
470  * Get own property names from Node prototype, but only the
471  * first time `Node` is instantiated
472  */
473
474 function lazyKeys() {
475   if (!ownNames) {
476     ownNames = Object.getOwnPropertyNames(Node.prototype);
477   }
478 }
479
480 /**
481  * Simplified assertion. Throws an error is `val` is falsey.
482  */
483
484 function assert(val, message) {
485   if (!val) throw new Error(message);
486 }
487
488 /**
489  * Expose `Node`
490  */
491
492 exports = module.exports = Node;