summaryrefslogtreecommitdiff
path: root/tools/eslint/node_modules/unified/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/eslint/node_modules/unified/index.js')
-rw-r--r--tools/eslint/node_modules/unified/index.js637
1 files changed, 637 insertions, 0 deletions
diff --git a/tools/eslint/node_modules/unified/index.js b/tools/eslint/node_modules/unified/index.js
new file mode 100644
index 0000000000..051383e98a
--- /dev/null
+++ b/tools/eslint/node_modules/unified/index.js
@@ -0,0 +1,637 @@
+/**
+ * @author Titus Wormer
+ * @copyright 2015 Titus Wormer
+ * @license MIT
+ * @module unified
+ * @fileoverview Pluggable text processing interface.
+ */
+
+'use strict';
+
+/* Dependencies. */
+var events = require('events');
+var has = require('has');
+var once = require('once');
+var extend = require('extend');
+var bail = require('bail');
+var vfile = require('vfile');
+var trough = require('trough');
+
+/* Expose an abstract processor. */
+module.exports = unified().abstract();
+
+/* Methods. */
+var slice = [].slice;
+
+/* Process pipeline. */
+var pipeline = trough()
+ .use(function (p, ctx) {
+ ctx.tree = p.parse(ctx.file, ctx.options);
+ })
+ .use(function (p, ctx, next) {
+ p.run(ctx.tree, ctx.file, function (err, tree, file) {
+ if (err) {
+ next(err);
+ } else {
+ ctx.tree = tree;
+ ctx.file = file;
+ next();
+ }
+ });
+ })
+ .use(function (p, ctx) {
+ ctx.file.contents = p.stringify(ctx.tree, ctx.file, ctx.options);
+ });
+
+/**
+ * Function to create the first processor.
+ *
+ * @return {Function} - First processor.
+ */
+function unified() {
+ var attachers = [];
+ var transformers = trough();
+ var namespace = {};
+ var chunks = [];
+ var emitter = new events.EventEmitter();
+ var ended = false;
+ var concrete = true;
+ var settings;
+ var key;
+
+ /**
+ * Create a new processor based on the processor
+ * in the current scope.
+ *
+ * @return {Processor} - New concrete processor based
+ * on the descendant processor.
+ */
+ 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;
+ }
+
+ /* Mix in methods. */
+ for (key in emitter) {
+ processor[key] = emitter[key];
+ }
+
+ /* Helpers. */
+
+ /**
+ * Assert a parser is available.
+ *
+ * @param {string} name - Name of callee.
+ */
+ function assertParser(name) {
+ if (!isParser(processor.Parser)) {
+ throw new Error('Cannot `' + name + '` without `Parser`');
+ }
+ }
+
+ /**
+ * Assert a compiler is available.
+ *
+ * @param {string} name - Name of callee.
+ */
+ function assertCompiler(name) {
+ if (!isCompiler(processor.Compiler)) {
+ throw new Error('Cannot `' + name + '` without `Compiler`');
+ }
+ }
+
+ /**
+ * Assert the processor is concrete.
+ *
+ * @param {string} name - Name of callee.
+ */
+ function assertConcrete(name) {
+ if (!concrete) {
+ throw new Error(
+ 'Cannot ' +
+ (name ? 'invoke `' + name + '` on' : 'pipe into') +
+ ' abstract processor.\n' +
+ 'To make the processor concrete, invoke it: ' +
+ 'use `processor()` instead of `processor`.'
+ );
+ }
+ }
+
+ /**
+ * Assert `node` is a Unist node.
+ *
+ * @param {*} node - Value to check.
+ */
+ function assertNode(node) {
+ if (!isNode(node)) {
+ throw new Error('Expected node, got `' + node + '`');
+ }
+ }
+
+ /**
+ * Assert, if no `done` is given, that `complete` is
+ * `true`.
+ *
+ * @param {string} name - Name of callee.
+ * @param {boolean} complete - Whether an async process
+ * is complete.
+ * @param {Function?} done - Optional handler of async
+ * results.
+ */
+ function assertDone(name, complete, done) {
+ if (!complete && !done) {
+ throw new Error(
+ 'Expected `done` to be given to `' + name + '` ' +
+ 'as async plug-ins are used'
+ );
+ }
+ }
+
+ /* Throw as early as possible.
+ * As events are triggered synchroneously, the stack
+ * is preserved. */
+ processor.on('pipe', function () {
+ assertConcrete();
+ });
+
+ /**
+ * Abstract: used to signal an abstract processor which
+ * should made concrete before using.
+ *
+ * For example, take unified itself. It’s abstract.
+ * Plug-ins should not be added to it. Rather, it should
+ * be made concrete (by invoking it) before modifying it.
+ *
+ * In essence, always invoke this when exporting a
+ * processor.
+ *
+ * @return {Processor} - The operated on processor.
+ */
+ function abstract() {
+ concrete = false;
+
+ return processor;
+ }
+
+ /**
+ * Data management.
+ *
+ * Getter / setter for processor-specific informtion.
+ *
+ * @param {string} key - Key to get or set.
+ * @param {*} value - Value to set.
+ * @return {*} - Either the operator on processor in
+ * setter mode; or the value stored as `key` in
+ * getter mode.
+ */
+ function data(key, value) {
+ assertConcrete('data');
+
+ if (typeof key === 'string') {
+ /* Set `key`. */
+ if (arguments.length === 2) {
+ namespace[key] = value;
+
+ return processor;
+ }
+
+ /* Get `key`. */
+ return (has(namespace, key) && namespace[key]) || null;
+ }
+
+ /* Get space. */
+ if (!key) {
+ return namespace;
+ }
+
+ /* Set space. */
+ namespace = key;
+
+ return processor;
+ }
+
+ /**
+ * Plug-in management.
+ *
+ * Pass it:
+ * * an attacher and options,
+ * * a list of attachers and options for all of them;
+ * * a tuple of one attacher and options.
+ * * a matrix: list containing any of the above and
+ * matrices.
+ *
+ * @param {...*} value - See description.
+ * @return {Processor} - The operated on processor.
+ */
+ function use(value) {
+ var args = slice.call(arguments, 0);
+ var params = args.slice(1);
+ var index;
+ var length;
+ var transformer;
+
+ assertConcrete('use');
+
+ /* Multiple attachers. */
+ if ('length' in value && !isFunction(value)) {
+ index = -1;
+ length = value.length;
+
+ if (!isFunction(value[0])) {
+ /* Matrix of things. */
+ while (++index < length) {
+ use(value[index]);
+ }
+ } else if (isFunction(value[1])) {
+ /* List of things. */
+ while (++index < length) {
+ use.apply(null, [value[index]].concat(params));
+ }
+ } else {
+ /* Arguments. */
+ use.apply(null, value);
+ }
+
+ return processor;
+ }
+
+ /* Store attacher. */
+ attachers.push(args);
+
+ /* Single attacher. */
+ transformer = value.apply(null, [processor].concat(params));
+
+ if (isFunction(transformer)) {
+ transformers.use(transformer);
+ }
+
+ return processor;
+ }
+
+ /**
+ * Parse a file (in string or VFile representation)
+ * into a Unist node using the `Parser` on the
+ * processor.
+ *
+ * @param {(string|VFile)?} [file] - File to process.
+ * @param {Object?} [options] - Configuration.
+ * @return {Node} - Unist node.
+ */
+ function parse(file, options) {
+ assertConcrete('parse');
+ assertParser('parse');
+
+ return new processor.Parser(vfile(file), options, processor).parse();
+ }
+
+ /**
+ * Run transforms on a Unist node representation of a file
+ * (in string or VFile representation).
+ *
+ * @param {Node} node - Unist node.
+ * @param {(string|VFile)?} [file] - File representation.
+ * @param {Function?} [done] - Callback.
+ * @return {Node} - The given or resulting Unist node.
+ */
+ function run(node, file, done) {
+ var complete = false;
+ var result;
+
+ assertConcrete('run');
+ assertNode(node);
+
+ result = node;
+
+ if (!done && file && !isFile(file)) {
+ done = file;
+ file = null;
+ }
+
+ transformers.run(node, vfile(file), function (err, tree, file) {
+ complete = true;
+ result = tree || node;
+
+ (done || bail)(err, tree, file);
+ });
+
+ assertDone('run', complete, done);
+
+ return result;
+ }
+
+ /**
+ * Stringify a Unist node representation of a file
+ * (in string or VFile representation) into a string
+ * using the `Compiler` on the processor.
+ *
+ * @param {Node} node - Unist node.
+ * @param {(string|VFile)?} [file] - File representation.
+ * @param {Object?} [options] - Configuration.
+ * @return {string} - String representation.
+ */
+ function stringify(node, file, options) {
+ assertConcrete('stringify');
+ assertCompiler('stringify');
+ assertNode(node);
+
+ if (!options && file && !isFile(file)) {
+ options = file;
+ file = null;
+ }
+
+ return new processor.Compiler(vfile(file), options, processor).compile(node);
+ }
+
+ /**
+ * 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.
+ *
+ * @param {(string|VFile)?} file - File representation.
+ * @param {Object?} [options] - Configuration.
+ * @param {Function?} [done] - Callback.
+ * @return {VFile} - The given or resulting VFile.
+ */
+ function process(file, options, done) {
+ var complete = false;
+
+ assertConcrete('process');
+ assertParser('process');
+ assertCompiler('process');
+
+ if (!done && isFunction(options)) {
+ done = options;
+ options = null;
+ }
+
+ file = vfile(file);
+
+ pipeline.run(processor, {
+ file: file,
+ options: options || {}
+ }, function (err) {
+ complete = true;
+
+ if (done) {
+ done(err, file);
+ } else {
+ bail(err);
+ }
+ });
+
+ assertDone('process', complete, done);
+
+ return file;
+ }
+
+ /* Streams. */
+
+ /**
+ * Write a chunk into memory.
+ *
+ * @param {(Buffer|string)?} chunk - Value to write.
+ * @param {string?} [encoding] - Encoding.
+ * @param {Function?} [callback] - Callback.
+ * @return {boolean} - Whether the write was succesful.
+ */
+ function write(chunk, encoding, callback) {
+ assertConcrete('write');
+
+ if (isFunction(encoding)) {
+ callback = encoding;
+ encoding = null;
+ }
+
+ if (ended) {
+ throw new Error('Did not expect `write` after `end`');
+ }
+
+ chunks.push((chunk || '').toString(encoding || 'utf8'));
+
+ if (callback) {
+ callback();
+ }
+
+ /* Signal succesful write. */
+ return true;
+ }
+
+ /**
+ * End the writing. Passes all arguments to a final
+ * `write`. Starts the process, which will trigger
+ * `error`, with a fatal error, if any; `data`, with
+ * the generated document in `string` form, if
+ * succesful. If messages are triggered during the
+ * process, those are triggerd as `warning`s.
+ *
+ * @return {boolean} - Whether the last write was
+ * succesful.
+ */
+ function end() {
+ assertConcrete('end');
+ assertParser('end');
+ assertCompiler('end');
+
+ write.apply(null, arguments);
+
+ ended = true;
+
+ process(chunks.join(''), settings, function (err, file) {
+ var messages = file.messages;
+ var length = messages.length;
+ var index = -1;
+
+ chunks = settings = null;
+
+ /* Trigger messages as warnings, except for fatal error. */
+ while (++index < length) {
+ if (messages[index] !== err) {
+ processor.emit('warning', messages[index]);
+ }
+ }
+
+ if (err) {
+ /* Don’t enter an infinite error throwing loop. */
+ global.setTimeout(function () {
+ processor.emit('error', err);
+ }, 4);
+ } else {
+ processor.emit('data', file.contents);
+ processor.emit('end');
+ }
+ });
+
+ return true;
+ }
+
+ /**
+ * Pipe the processor into a writable stream.
+ *
+ * Basically `Stream#pipe`, but inlined and
+ * simplified to keep the bundled size down.
+ *
+ * @see https://github.com/nodejs/node/blob/master/lib/stream.js#L26
+ *
+ * @param {Stream} dest - Writable stream.
+ * @param {Object?} [options] - Processing
+ * configuration.
+ * @return {Stream} - The destination stream.
+ */
+ function pipe(dest, options) {
+ var onend = once(function () {
+ if (dest.end) {
+ dest.end();
+ }
+ });
+
+ assertConcrete('pipe');
+
+ settings = options || {};
+
+ /**
+ * Handle data.
+ *
+ * @param {*} chunk - Data to pass through.
+ */
+ function ondata(chunk) {
+ if (dest.writable) {
+ dest.write(chunk);
+ }
+ }
+
+ /**
+ * Clean listeners.
+ */
+ function cleanup() {
+ processor.removeListener('data', ondata);
+ processor.removeListener('end', onend);
+ processor.removeListener('error', onerror);
+ processor.removeListener('end', cleanup);
+ processor.removeListener('close', cleanup);
+
+ dest.removeListener('error', onerror);
+ dest.removeListener('close', cleanup);
+ }
+
+ /**
+ * Close dangling pipes and handle unheard errors.
+ *
+ * @param {Error} err - Exception.
+ */
+ function onerror(err) {
+ var handlers = processor._events.error;
+
+ cleanup();
+
+ /* Cannot use `listenerCount` in node <= 0.12. */
+ if (!handlers || !handlers.length || handlers === onerror) {
+ throw err; /* Unhandled stream error in pipe. */
+ }
+ }
+
+ processor.on('data', ondata);
+ processor.on('error', onerror);
+ processor.on('end', cleanup);
+ processor.on('close', cleanup);
+
+ /* If the 'end' option is not supplied, dest.end() will be
+ * called when the 'end' or 'close' events are received.
+ * Only dest.end() once. */
+ if (!dest._isStdio && settings.end !== false) {
+ processor.on('end', onend);
+ }
+
+ dest.on('error', onerror);
+ dest.on('close', cleanup);
+
+ dest.emit('pipe', processor);
+
+ return dest;
+ }
+
+ /* Data management. */
+ processor.data = data;
+
+ /* Lock. */
+ processor.abstract = abstract;
+
+ /* Plug-ins. */
+ processor.use = use;
+
+ /* Streaming. */
+ processor.writable = true;
+ processor.readable = true;
+ processor.write = write;
+ processor.end = end;
+ processor.pipe = pipe;
+
+ /* API. */
+ processor.parse = parse;
+ processor.stringify = stringify;
+ processor.run = run;
+ processor.process = process;
+
+ /* Expose. */
+ return processor;
+}
+
+/**
+ * Check if `node` is a Unist node.
+ *
+ * @param {*} node - Value.
+ * @return {boolean} - Whether `node` is a Unist node.
+ */
+function isNode(node) {
+ return node && typeof node.type === 'string' && node.type.length !== 0;
+}
+
+/**
+ * Check if `file` is a VFile.
+ *
+ * @param {*} file - Value.
+ * @return {boolean} - Whether `file` is a VFile.
+ */
+function isFile(file) {
+ return file && typeof file.contents === 'string';
+}
+
+/**
+ * Check if `fn` is a function.
+ *
+ * @param {*} fn - Value.
+ * @return {boolean} - Whether `fn` is a function.
+ */
+function isFunction(fn) {
+ return typeof fn === 'function';
+}
+
+/**
+ * Check if `compiler` is a Compiler.
+ *
+ * @param {*} compiler - Value.
+ * @return {boolean} - Whether `compiler` is a Compiler.
+ */
+function isCompiler(compiler) {
+ return isFunction(compiler) && compiler.prototype && isFunction(compiler.prototype.compile);
+}
+
+/**
+ * Check if `parser` is a Parser.
+ *
+ * @param {*} parser - Value.
+ * @return {boolean} - Whether `parser` is a Parser.
+ */
+function isParser(parser) {
+ return isFunction(parser) && parser.prototype && isFunction(parser.prototype.parse);
+}