.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / unified / index.js
1 'use strict'
2
3 /* Dependencies. */
4 var extend = require('extend')
5 var bail = require('bail')
6 var vfile = require('vfile')
7 var trough = require('trough')
8 var string = require('x-is-string')
9 var plain = require('is-plain-obj')
10
11 /* Expose a frozen processor. */
12 module.exports = unified().freeze()
13
14 var slice = [].slice
15 var own = {}.hasOwnProperty
16
17 /* Process pipeline. */
18 var pipeline = trough()
19   .use(pipelineParse)
20   .use(pipelineRun)
21   .use(pipelineStringify)
22
23 function pipelineParse(p, ctx) {
24   ctx.tree = p.parse(ctx.file)
25 }
26
27 function pipelineRun(p, ctx, next) {
28   p.run(ctx.tree, ctx.file, done)
29
30   function done(err, tree, file) {
31     if (err) {
32       next(err)
33     } else {
34       ctx.tree = tree
35       ctx.file = file
36       next()
37     }
38   }
39 }
40
41 function pipelineStringify(p, ctx) {
42   ctx.file.contents = p.stringify(ctx.tree, ctx.file)
43 }
44
45 /* Function to create the first processor. */
46 function unified() {
47   var attachers = []
48   var transformers = trough()
49   var namespace = {}
50   var frozen = false
51   var freezeIndex = -1
52
53   /* Data management. */
54   processor.data = data
55
56   /* Lock. */
57   processor.freeze = freeze
58
59   /* Plug-ins. */
60   processor.attachers = attachers
61   processor.use = use
62
63   /* API. */
64   processor.parse = parse
65   processor.stringify = stringify
66   processor.run = run
67   processor.runSync = runSync
68   processor.process = process
69   processor.processSync = processSync
70
71   /* Expose. */
72   return processor
73
74   /* Create a new processor based on the processor
75    * in the current scope. */
76   function processor() {
77     var destination = unified()
78     var length = attachers.length
79     var index = -1
80
81     while (++index < length) {
82       destination.use.apply(null, attachers[index])
83     }
84
85     destination.data(extend(true, {}, namespace))
86
87     return destination
88   }
89
90   /* Freeze: used to signal a processor that has finished
91    * configuration.
92    *
93    * For example, take unified itself.  It’s frozen.
94    * Plug-ins should not be added to it.  Rather, it should
95    * be extended, by invoking it, before modifying it.
96    *
97    * In essence, always invoke this when exporting a
98    * processor. */
99   function freeze() {
100     var values
101     var plugin
102     var options
103     var transformer
104
105     if (frozen) {
106       return processor
107     }
108
109     while (++freezeIndex < attachers.length) {
110       values = attachers[freezeIndex]
111       plugin = values[0]
112       options = values[1]
113       transformer = null
114
115       if (options === false) {
116         continue
117       }
118
119       if (options === true) {
120         values[1] = undefined
121       }
122
123       transformer = plugin.apply(processor, values.slice(1))
124
125       if (typeof transformer === 'function') {
126         transformers.use(transformer)
127       }
128     }
129
130     frozen = true
131     freezeIndex = Infinity
132
133     return processor
134   }
135
136   /* Data management.
137    * Getter / setter for processor-specific informtion. */
138   function data(key, value) {
139     if (string(key)) {
140       /* Set `key`. */
141       if (arguments.length === 2) {
142         assertUnfrozen('data', frozen)
143
144         namespace[key] = value
145
146         return processor
147       }
148
149       /* Get `key`. */
150       return (own.call(namespace, key) && namespace[key]) || null
151     }
152
153     /* Set space. */
154     if (key) {
155       assertUnfrozen('data', frozen)
156       namespace = key
157       return processor
158     }
159
160     /* Get space. */
161     return namespace
162   }
163
164   /* Plug-in management.
165    *
166    * Pass it:
167    * *   an attacher and options,
168    * *   a preset,
169    * *   a list of presets, attachers, and arguments (list
170    *     of attachers and options). */
171   function use(value) {
172     var settings
173
174     assertUnfrozen('use', frozen)
175
176     if (value === null || value === undefined) {
177       /* Empty */
178     } else if (typeof value === 'function') {
179       addPlugin.apply(null, arguments)
180     } else if (typeof value === 'object') {
181       if ('length' in value) {
182         addList(value)
183       } else {
184         addPreset(value)
185       }
186     } else {
187       throw new Error('Expected usable value, not `' + value + '`')
188     }
189
190     if (settings) {
191       namespace.settings = extend(namespace.settings || {}, settings)
192     }
193
194     return processor
195
196     function addPreset(result) {
197       addList(result.plugins)
198
199       if (result.settings) {
200         settings = extend(settings || {}, result.settings)
201       }
202     }
203
204     function add(value) {
205       if (typeof value === 'function') {
206         addPlugin(value)
207       } else if (typeof value === 'object') {
208         if ('length' in value) {
209           addPlugin.apply(null, value)
210         } else {
211           addPreset(value)
212         }
213       } else {
214         throw new Error('Expected usable value, not `' + value + '`')
215       }
216     }
217
218     function addList(plugins) {
219       var length
220       var index
221
222       if (plugins === null || plugins === undefined) {
223         /* Empty */
224       } else if (typeof plugins === 'object' && 'length' in plugins) {
225         length = plugins.length
226         index = -1
227
228         while (++index < length) {
229           add(plugins[index])
230         }
231       } else {
232         throw new Error('Expected a list of plugins, not `' + plugins + '`')
233       }
234     }
235
236     function addPlugin(plugin, value) {
237       var entry = find(plugin)
238
239       if (entry) {
240         if (plain(entry[1]) && plain(value)) {
241           value = extend(entry[1], value)
242         }
243
244         entry[1] = value
245       } else {
246         attachers.push(slice.call(arguments))
247       }
248     }
249   }
250
251   function find(plugin) {
252     var length = attachers.length
253     var index = -1
254     var entry
255
256     while (++index < length) {
257       entry = attachers[index]
258
259       if (entry[0] === plugin) {
260         return entry
261       }
262     }
263   }
264
265   /* Parse a file (in string or VFile representation)
266    * into a Unist node using the `Parser` on the
267    * processor. */
268   function parse(doc) {
269     var file = vfile(doc)
270     var Parser
271
272     freeze()
273     Parser = processor.Parser
274     assertParser('parse', Parser)
275
276     if (newable(Parser)) {
277       return new Parser(String(file), file).parse()
278     }
279
280     return Parser(String(file), file) // eslint-disable-line new-cap
281   }
282
283   /* Run transforms on a Unist node representation of a file
284    * (in string or VFile representation), async. */
285   function run(node, file, cb) {
286     assertNode(node)
287     freeze()
288
289     if (!cb && typeof file === 'function') {
290       cb = file
291       file = null
292     }
293
294     if (!cb) {
295       return new Promise(executor)
296     }
297
298     executor(null, cb)
299
300     function executor(resolve, reject) {
301       transformers.run(node, vfile(file), done)
302
303       function done(err, tree, file) {
304         tree = tree || node
305         if (err) {
306           reject(err)
307         } else if (resolve) {
308           resolve(tree)
309         } else {
310           cb(null, tree, file)
311         }
312       }
313     }
314   }
315
316   /* Run transforms on a Unist node representation of a file
317    * (in string or VFile representation), sync. */
318   function runSync(node, file) {
319     var complete = false
320     var result
321
322     run(node, file, done)
323
324     assertDone('runSync', 'run', complete)
325
326     return result
327
328     function done(err, tree) {
329       complete = true
330       bail(err)
331       result = tree
332     }
333   }
334
335   /* Stringify a Unist node representation of a file
336    * (in string or VFile representation) into a string
337    * using the `Compiler` on the processor. */
338   function stringify(node, doc) {
339     var file = vfile(doc)
340     var Compiler
341
342     freeze()
343     Compiler = processor.Compiler
344     assertCompiler('stringify', Compiler)
345     assertNode(node)
346
347     if (newable(Compiler)) {
348       return new Compiler(node, file).compile()
349     }
350
351     return Compiler(node, file) // eslint-disable-line new-cap
352   }
353
354   /* Parse a file (in string or VFile representation)
355    * into a Unist node using the `Parser` on the processor,
356    * then run transforms on that node, and compile the
357    * resulting node using the `Compiler` on the processor,
358    * and store that result on the VFile. */
359   function process(doc, cb) {
360     freeze()
361     assertParser('process', processor.Parser)
362     assertCompiler('process', processor.Compiler)
363
364     if (!cb) {
365       return new Promise(executor)
366     }
367
368     executor(null, cb)
369
370     function executor(resolve, reject) {
371       var file = vfile(doc)
372
373       pipeline.run(processor, {file: file}, done)
374
375       function done(err) {
376         if (err) {
377           reject(err)
378         } else if (resolve) {
379           resolve(file)
380         } else {
381           cb(null, file)
382         }
383       }
384     }
385   }
386
387   /* Process the given document (in string or VFile
388    * representation), sync. */
389   function processSync(doc) {
390     var complete = false
391     var file
392
393     freeze()
394     assertParser('processSync', processor.Parser)
395     assertCompiler('processSync', processor.Compiler)
396     file = vfile(doc)
397
398     process(file, done)
399
400     assertDone('processSync', 'process', complete)
401
402     return file
403
404     function done(err) {
405       complete = true
406       bail(err)
407     }
408   }
409 }
410
411 /* Check if `func` is a constructor. */
412 function newable(value) {
413   return typeof value === 'function' && keys(value.prototype)
414 }
415
416 /* Check if `value` is an object with keys. */
417 function keys(value) {
418   var key
419   for (key in value) {
420     return true
421   }
422   return false
423 }
424
425 /* Assert a parser is available. */
426 function assertParser(name, Parser) {
427   if (typeof Parser !== 'function') {
428     throw new Error('Cannot `' + name + '` without `Parser`')
429   }
430 }
431
432 /* Assert a compiler is available. */
433 function assertCompiler(name, Compiler) {
434   if (typeof Compiler !== 'function') {
435     throw new Error('Cannot `' + name + '` without `Compiler`')
436   }
437 }
438
439 /* Assert the processor is not frozen. */
440 function assertUnfrozen(name, frozen) {
441   if (frozen) {
442     throw new Error(
443       [
444         'Cannot invoke `' + name + '` on a frozen processor.\nCreate a new ',
445         'processor first, by invoking it: use `processor()` instead of ',
446         '`processor`.'
447       ].join('')
448     )
449   }
450 }
451
452 /* Assert `node` is a Unist node. */
453 function assertNode(node) {
454   if (!node || !string(node.type)) {
455     throw new Error('Expected node, got `' + node + '`')
456   }
457 }
458
459 /* Assert that `complete` is `true`. */
460 function assertDone(name, asyncName, complete) {
461   if (!complete) {
462     throw new Error(
463       '`' + name + '` finished async. Use `' + asyncName + '` instead'
464     )
465   }
466 }