.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / use / index.js
1 /*!
2  * use <https://github.com/jonschlinkert/use>
3  *
4  * Copyright (c) 2015-2017, Jon Schlinkert.
5  * Released under the MIT License.
6  */
7
8 'use strict';
9
10 module.exports = function base(app, options) {
11   if (!isObject(app) && typeof app !== 'function') {
12     throw new TypeError('expected an object or function');
13   }
14
15   var opts = isObject(options) ? options : {};
16   var prop = typeof opts.prop === 'string' ? opts.prop : 'fns';
17   if (!Array.isArray(app[prop])) {
18     define(app, prop, []);
19   }
20
21   /**
22    * Define a plugin function to be passed to use. The only
23    * parameter exposed to the plugin is `app`, the object or function.
24    * passed to `use(app)`. `app` is also exposed as `this` in plugins.
25    *
26    * Additionally, **if a plugin returns a function, the function will
27    * be pushed onto the `fns` array**, allowing the plugin to be
28    * called at a later point by the `run` method.
29    *
30    * ```js
31    * var use = require('use');
32    *
33    * // define a plugin
34    * function foo(app) {
35    *   // do stuff
36    * }
37    *
38    * var app = function(){};
39    * use(app);
40    *
41    * // register plugins
42    * app.use(foo);
43    * app.use(bar);
44    * app.use(baz);
45    * ```
46    * @name .use
47    * @param {Function} `fn` plugin function to call
48    * @api public
49    */
50
51   define(app, 'use', use);
52
53   /**
54    * Run all plugins on `fns`. Any plugin that returns a function
55    * when called by `use` is pushed onto the `fns` array.
56    *
57    * ```js
58    * var config = {};
59    * app.run(config);
60    * ```
61    * @name .run
62    * @param {Object} `value` Object to be modified by plugins.
63    * @return {Object} Returns the object passed to `run`
64    * @api public
65    */
66
67   define(app, 'run', function(val) {
68     if (!isObject(val)) return;
69
70     if (!val.use || !val.run) {
71       define(val, prop, val[prop] || []);
72       define(val, 'use', use);
73     }
74
75     if (!val[prop] || val[prop].indexOf(base) === -1) {
76       val.use(base);
77     }
78
79     var self = this || app;
80     var fns = self[prop];
81     var len = fns.length;
82     var idx = -1;
83
84     while (++idx < len) {
85       val.use(fns[idx]);
86     }
87     return val;
88   });
89
90   /**
91    * Call plugin `fn`. If a function is returned push it into the
92    * `fns` array to be called by the `run` method.
93    */
94
95   function use(type, fn, options) {
96     var offset = 1;
97
98     if (typeof type === 'string' || Array.isArray(type)) {
99       fn = wrap(type, fn);
100       offset++;
101     } else {
102       options = fn;
103       fn = type;
104     }
105
106     if (typeof fn !== 'function') {
107       throw new TypeError('expected a function');
108     }
109
110     var self = this || app;
111     var fns = self[prop];
112
113     var args = [].slice.call(arguments, offset);
114     args.unshift(self);
115
116     if (typeof opts.hook === 'function') {
117       opts.hook.apply(self, args);
118     }
119
120     var val = fn.apply(self, args);
121     if (typeof val === 'function' && fns.indexOf(val) === -1) {
122       fns.push(val);
123     }
124     return self;
125   }
126
127   /**
128    * Wrap a named plugin function so that it's only called on objects of the
129    * given `type`
130    *
131    * @param {String} `type`
132    * @param {Function} `fn` Plugin function
133    * @return {Function}
134    */
135
136   function wrap(type, fn) {
137     return function plugin() {
138       return this.type === type ? fn.apply(this, arguments) : plugin;
139     };
140   }
141
142   return app;
143 };
144
145 function isObject(val) {
146   return val && typeof val === 'object' && !Array.isArray(val);
147 }
148
149 function define(obj, key, val) {
150   Object.defineProperty(obj, key, {
151     configurable: true,
152     writable: true,
153     value: val
154   });
155 }