diff options
Diffstat (limited to 'tools/node_modules/eslint/node_modules/unified/index.js')
-rw-r--r-- | tools/node_modules/eslint/node_modules/unified/index.js | 460 |
1 files changed, 460 insertions, 0 deletions
diff --git a/tools/node_modules/eslint/node_modules/unified/index.js b/tools/node_modules/eslint/node_modules/unified/index.js new file mode 100644 index 0000000000..2bc872ee8d --- /dev/null +++ b/tools/node_modules/eslint/node_modules/unified/index.js @@ -0,0 +1,460 @@ +'use strict'; + +/* Dependencies. */ +var extend = require('extend'); +var bail = require('bail'); +var vfile = require('vfile'); +var trough = require('trough'); +var string = require('x-is-string'); +var func = require('x-is-function'); +var plain = require('is-plain-obj'); + +/* Expose a frozen processor. */ +module.exports = unified().freeze(); + +var slice = [].slice; +var own = {}.hasOwnProperty; + +/* Process pipeline. */ +var pipeline = trough().use(pipelineParse).use(pipelineRun).use(pipelineStringify); + +function pipelineParse(p, ctx) { + ctx.tree = p.parse(ctx.file); +} + +function pipelineRun(p, ctx, next) { + p.run(ctx.tree, ctx.file, done); + + function done(err, tree, file) { + if (err) { + next(err); + } else { + ctx.tree = tree; + ctx.file = file; + next(); + } + } +} + +function pipelineStringify(p, ctx) { + ctx.file.contents = p.stringify(ctx.tree, ctx.file); +} + +/* Function to create the first processor. */ +function unified() { + var attachers = []; + var transformers = trough(); + var namespace = {}; + var frozen = false; + var freezeIndex = -1; + + /* Data management. */ + processor.data = data; + + /* Lock. */ + processor.freeze = freeze; + + /* Plug-ins. */ + processor.attachers = attachers; + processor.use = use; + + /* API. */ + processor.parse = parse; + processor.stringify = stringify; + processor.run = run; + processor.runSync = runSync; + processor.process = process; + processor.processSync = processSync; + + /* Expose. */ + return processor; + + /* Create a new processor based on the processor + * in the current scope. */ + function processor() { + var destination = unified(); + var length = attachers.length; + var index = -1; + + while (++index < length) { + destination.use.apply(null, attachers[index]); + } + + destination.data(extend(true, {}, namespace)); + + return destination; + } + + /* Freeze: used to signal a processor that has finished + * configuration. + * + * For example, take unified itself. It’s frozen. + * Plug-ins should not be added to it. Rather, it should + * be extended, by invoking it, before modifying it. + * + * In essence, always invoke this when exporting a + * processor. */ + function freeze() { + var values; + var plugin; + var options; + var transformer; + + if (frozen) { + return processor; + } + + while (++freezeIndex < attachers.length) { + values = attachers[freezeIndex]; + plugin = values[0]; + options = values[1]; + transformer = null; + + if (options === false) { + continue; + } + + if (options === true) { + values[1] = undefined; + } + + transformer = plugin.apply(processor, values.slice(1)); + + if (func(transformer)) { + transformers.use(transformer); + } + } + + frozen = true; + freezeIndex = Infinity; + + return processor; + } + + /* Data management. + * Getter / setter for processor-specific informtion. */ + function data(key, value) { + if (string(key)) { + /* Set `key`. */ + if (arguments.length === 2) { + assertUnfrozen('data', frozen); + + namespace[key] = value; + + return processor; + } + + /* Get `key`. */ + return (own.call(namespace, key) && namespace[key]) || null; + } + + /* Set space. */ + if (key) { + assertUnfrozen('data', frozen); + namespace = key; + return processor; + } + + /* Get space. */ + return namespace; + } + + /* Plug-in management. + * + * Pass it: + * * an attacher and options, + * * a preset, + * * a list of presets, attachers, and arguments (list + * of attachers and options). */ + function use(value) { + var settings; + + assertUnfrozen('use', frozen); + + if (value === null || value === undefined) { + /* Empty */ + } else if (func(value)) { + addPlugin.apply(null, arguments); + } else if (typeof value === 'object') { + if ('length' in value) { + addList(value); + } else { + addPreset(value); + } + } else { + throw new Error('Expected usable value, not `' + value + '`'); + } + + if (settings) { + namespace.settings = extend(namespace.settings || {}, settings); + } + + return processor; + + function addPreset(result) { + addList(result.plugins); + + if (result.settings) { + settings = extend(settings || {}, result.settings); + } + } + + function add(value) { + if (func(value)) { + addPlugin(value); + } else if (typeof value === 'object') { + if ('length' in value) { + addPlugin.apply(null, value); + } else { + addPreset(value); + } + } else { + throw new Error('Expected usable value, not `' + value + '`'); + } + } + + function addList(plugins) { + var length; + var index; + + if (plugins === null || plugins === undefined) { + /* Empty */ + } else if (typeof plugins === 'object' && 'length' in plugins) { + length = plugins.length; + index = -1; + + while (++index < length) { + add(plugins[index]); + } + } else { + throw new Error('Expected a list of plugins, not `' + plugins + '`'); + } + } + + function addPlugin(plugin, value) { + var entry = find(plugin); + + if (entry) { + if (plain(entry[1]) && plain(value)) { + value = extend(entry[1], value); + } + + entry[1] = value; + } else { + attachers.push(slice.call(arguments)); + } + } + } + + function find(plugin) { + var length = attachers.length; + var index = -1; + var entry; + + while (++index < length) { + entry = attachers[index]; + + if (entry[0] === plugin) { + return entry; + } + } + } + + /* Parse a file (in string or VFile representation) + * into a Unist node using the `Parser` on the + * processor. */ + function parse(doc) { + var file = vfile(doc); + var Parser; + + freeze(); + Parser = processor.Parser; + assertParser('parse', Parser); + + if (newable(Parser)) { + return new Parser(String(file), file).parse(); + } + + return Parser(String(file), file); // eslint-disable-line new-cap + } + + /* Run transforms on a Unist node representation of a file + * (in string or VFile representation), async. */ + function run(node, file, cb) { + assertNode(node); + freeze(); + + if (!cb && func(file)) { + cb = file; + file = null; + } + + if (!cb) { + return new Promise(executor); + } + + executor(null, cb); + + function executor(resolve, reject) { + transformers.run(node, vfile(file), done); + + function done(err, tree, file) { + tree = tree || node; + if (err) { + reject(err); + } else if (resolve) { + resolve(tree); + } else { + cb(null, tree, file); + } + } + } + } + + /* Run transforms on a Unist node representation of a file + * (in string or VFile representation), sync. */ + function runSync(node, file) { + var complete = false; + var result; + + run(node, file, done); + + assertDone('runSync', 'run', complete); + + return result; + + function done(err, tree) { + complete = true; + bail(err); + result = tree; + } + } + + /* Stringify a Unist node representation of a file + * (in string or VFile representation) into a string + * using the `Compiler` on the processor. */ + function stringify(node, doc) { + var file = vfile(doc); + var Compiler; + + freeze(); + Compiler = processor.Compiler; + assertCompiler('stringify', Compiler); + assertNode(node); + + if (newable(Compiler)) { + return new Compiler(node, file).compile(); + } + + return Compiler(node, file); // eslint-disable-line new-cap + } + + /* Parse a file (in string or VFile representation) + * into a Unist node using the `Parser` on the processor, + * then run transforms on that node, and compile the + * resulting node using the `Compiler` on the processor, + * and store that result on the VFile. */ + function process(doc, cb) { + freeze(); + assertParser('process', processor.Parser); + assertCompiler('process', processor.Compiler); + + if (!cb) { + return new Promise(executor); + } + + executor(null, cb); + + function executor(resolve, reject) { + var file = vfile(doc); + + pipeline.run(processor, {file: file}, done); + + function done(err) { + if (err) { + reject(err); + } else if (resolve) { + resolve(file); + } else { + cb(null, file); + } + } + } + } + + /* Process the given document (in string or VFile + * representation), sync. */ + function processSync(doc) { + var complete = false; + var file; + + freeze(); + assertParser('processSync', processor.Parser); + assertCompiler('processSync', processor.Compiler); + file = vfile(doc); + + process(file, done); + + assertDone('processSync', 'process', complete); + + return file; + + function done(err) { + complete = true; + bail(err); + } + } +} + +/* Check if `func` is a constructor. */ +function newable(value) { + return func(value) && keys(value.prototype); +} + +/* Check if `value` is an object with keys. */ +function keys(value) { + var key; + for (key in value) { + return true; + } + return false; +} + +/* Assert a parser is available. */ +function assertParser(name, Parser) { + if (!func(Parser)) { + throw new Error('Cannot `' + name + '` without `Parser`'); + } +} + +/* Assert a compiler is available. */ +function assertCompiler(name, Compiler) { + if (!func(Compiler)) { + throw new Error('Cannot `' + name + '` without `Compiler`'); + } +} + +/* Assert the processor is not frozen. */ +function assertUnfrozen(name, frozen) { + if (frozen) { + throw new Error( + 'Cannot invoke `' + name + '` on a frozen processor.\n' + + 'Create a new processor first, by invoking it: ' + + 'use `processor()` instead of `processor`.' + ); + } +} + +/* Assert `node` is a Unist node. */ +function assertNode(node) { + if (!node || !string(node.type)) { + throw new Error('Expected node, got `' + node + '`'); + } +} + +/* Assert that `complete` is `true`. */ +function assertDone(name, asyncName, complete) { + if (!complete) { + throw new Error('`' + name + '` finished async. Use `' + asyncName + '` instead'); + } +} |