<commit_before>/**
 * @module Mediator
 * @requires NodeContext
 * @requires BrowserContext
 */
;(function (root, Mediator) {
  if(typeof define === "function" && define.amd) {
    define(["Mediator"], function(Context){
      return (root.Mediator = Mediator(Context));
    });
  } else if(typeof module === "object" && module.exports) {
    if (typeof process === 'object' && process.hasOwnProperty('versions') && process.versions.node) {
      module.exports = Mediator(require('./lib/nodeContext'))
    } else {
      module.exports = (root.Mediator = Mediator(require('./lib/browserContext')));
    }
  } else {
    root.Mediator = Mediator(root.Context);
  }
}(this, function(Context) {
  'use strict'

  var contextList = {}
  var defaultNamespace = 'default'

  /**
   * Instantiate context based on namespace
   * @member instantiateContext
   * @function instantiateContext
   * @private
   * @param [namespace='default'] {String=} Context namespace
   * @returns {Mediator.Context} Context instance
   */
  function instantiateContext (namespace) {
    contextList[namespace || defaultNamespace] = new Context(namespace || defaultNamespace)
    return contextList[namespace]
  }

  /**
   * Get mediator context based on namespace
   * @member getContext
   * @static
   * @function getContext
   * @param [namespace='default' {String=} Context namespace
   * @returns {Mediator.Context|Error} Context instance
   */
  function getContext (namespace) {
    namespace = namespace || defaultNamespace
    if (typeof namespace !== 'string') return new Error('Namespace MUST BE A String')
    return contextList.hasOwnProperty(namespace)
      ? contextList[namespace]
      : instantiateContext(namespace)
  }

  /**
   * Get context name list
   * @member getContextList
   * @static
   * @function getContextList
   * @returns {Array} Context list names
   */
  function getContextList () {
    return Object.keys(contextList)
  }

  /**
   * Destroy mediator context based on namespace
   * @member destroyContext
   * @static
   * @function destroyContext
   * @param [namespace='default'] {String=} Context namespace
   * @returns {Boolean|Error}
   */
  function destroyContext (namespace) {
    namespace = namespace || defaultNamespace
    if (typeof namespace !== 'string') return new Error('Namespace MUST BE A String')
    if (!contextList.hasOwnProperty(namespace)) return false

    contextList[namespace].removeAll()
    return delete contextList[namespace]
  }

  /**
   * Destroy all contexts
   * @member destroyAllContexts
   * @static
   * @function destroyAllContexts
   */
  function destroyAllContexts () {
    return Object.keys(contextList).forEach(function (namespace) {
      destroyContext(namespace)
    })
  }

  return {
    getContext: getContext,
    getContextList: getContextList,
    destroyContext: destroyContext,
    destroyAllContexts: destroyAllContexts
  }
}))<commit_msg>Added lib/Mediator<commit_after>'use strict'
module.exports = require('./lib/Mediator')
<|endoftext|>


<commit_before>"use strict";

require("dotenv").config();
module.exports = require('./src/server.js');
<commit_msg>update index for main class<commit_after>"use strict";

require("dotenv").config();
module.exports = require('./src/botstack.js');
<|endoftext|>


<commit_before>#!/usr/bin/env node
'use strict';

var
  request   = require('request'),
  clipboard = require('copy-paste');

var options = {
  url: 'http://www.lgtm.in/g',
  method: 'GET'
};

request(options, function (error, response, body) {
  console.log('Error:', error);
  console.log('Response:', response);
  console.log('Body:', body);
});
<commit_msg>Add copy method.<commit_after>#!/usr/bin/env node
'use strict';

var
  clipboard = require('copy-paste'),
  request   = require('request');

var
  FAILURE_EXIT = 1,
  SUCCESS_EXIT = 1;

var options = {
  url: 'http://www.lgtm.in/g',
  method: 'GET',
  json: true
};

request(options, function (error, response, json) {
  if (error) {
    console.log("Error:", error);
    return 1;
  }
  var lgtm = "![LGTM]("+ json.imageUrl +")";
  return clipboard.copy(lgtm);
});
<|endoftext|>


<commit_before>var postcss = require('postcss');
var Q = require('q');
var lodash = require('lodash');
var url = require('url');
var path = require('path');
var async = require('async');
var spritesmith = require('spritesmith');
var mkdirp = require('mkdirp');
var fs = require('fs');
var md5 = require('md5');
var gutil = require('gulp-util');

// cache objects;
var cache = {};
var cacheIndex = {};

// for debug
function debug() {
  var data = [gutil.colors.red('debug'), ':']
    .concat(Array.prototype.slice.call(arguments));
  gutil.log.apply(false, data);
}
function log() {
  var data = Array.prototype.slice.call(arguments);
  gutil.log.apply(false, data);
}

/**
 * Constants.
 *
 * @type {String}
 */
var GROUP_DELIMITER   = '.';
var GROUP_MASK        = '*';
var BACKGROUND        = 'background';
var BACKGROUND_IMAGE  = 'background-image';

module.exports = postcss.plugin('postcss-easysprite', function (opts) {
    opts = opts || {};
    debug();

    // opts
    opts = opts || {};
    opts.groupBy = opts.groupBy || [];
    opts.padding = opts.padding ? opts.padding : 20;

    // paths
    opts.imagePath = path.resolve(process.cwd(), opts.imagePath||'');
    opts.spritePath = path.resolve(process.cwd(), opts.spritePath||'');

    // Group retina images
    opts.groupBy.unshift(function(image) {
      if (image.ratio>1) { return '@' + image.ratio + 'x'; }
      return null;
    });

    return function (css) {
      // if file path

      return Q
        // prepare part
        .all([collectImages(css, opts), opts])
        .spread(applyGroupBy)
        .spread(function(images, opts){
          return setTokens(images, opts, css);
        })
        // compilation part
        .spread(runSpriteSmith)
        .spread(saveSprites)
        .spread(mapSpritesProperties)
        .spread(function(images, opts, sprites) {
          return updateReferences(images, opts, sprites, css);
        });
    };
});

function collectImages(css, opts) {
  var images = [];
  var stylesheetPath = opts.stylesheetPath || path.dirname(css.source.input.file);
  if (!stylesheetPath) {
    throw 'Stylesheets path is undefined, please use option stylesheetPath!';
  }

  css.eachRule(function(rule) {
    var image = {
      path    : null,
      url     : null,
      stylesheetPath : stylesheetPath,
      ratio   : 1,
      groups  : [],
      token   : ''
    };

    if (hasImageInRule(rule.toString())) {
      image.url = getImageUrl(rule.toString());
      var imageUrl = url.parse(image.url);

      // only locals, hashed paths
      if (imageUrl.host ||
          !imageUrl.hash ||
          imageUrl.pathname.indexOf('//') === 0 ||
          imageUrl.pathname.indexOf(';base64') !== -1) {
        return;
      }

      image.groups = [imageUrl.hash.replace('#','')];

      // Perform search for retina
      if (isRetinaImage(image.url)) {
        image.ratio  = getRetinaRatio(image.url);
      }

      // Get the path to the image.
      image.path = resolveUrl(image, opts);

      images.push(image);
    }
  });

  return images;
}

function applyGroupBy(images, opts) {
  return Q.Promise(function(resolve, reject) {
    async.reduce(opts.groupBy, images, function(images, group, next) {
      async.map(images, function(image, done) {
        new Q(group(image))
          .then(function(group) {
            if (group) {
              image.groups.push(group);
            }

            done(null, image);
          })
          .catch(done);
      }, next);
    }, function(err, images) {
      if (err) {
        return reject(err);
      }

      resolve([images, opts]);
    });
  });
}

function setTokens(images, opts, css) {
  return Q.Promise(function(resolve) {
    css.eachDecl(/^background(-image)?$/, function(decl) {
      var rule = decl.parent;
      var url, image, color;

      // Manipulate only rules with background image
      // in them.
      if (hasImageInRule(rule.toString())) {
        url   = getImageUrl(rule.toString());
        image = lodash.find(images, { url: url });

        if (image) {
          // We remove these declarations since
          // our plugin will insert them when
          // they are necessary.
          rule.eachDecl(/^background-(repeat|size|position)$/, function(decl) {
            decl.removeSelf();
          });

          if (decl.prop === BACKGROUND) {
            color = getColor(decl);

            // Extract color to background-color propery
            if (color && color.length === 1) {
              rule.append({
                prop: 'background-color',
                value: color[0],
                before: ' '
              });
            }
          }

          if (decl.prop === BACKGROUND || decl.prop === BACKGROUND_IMAGE) {
            image.token = postcss.comment({
              text: image.url,
              before: ' ',
              left: '@replace|',
              right: ''
            });

            // Replace the declaration with a comment token
            // which will be used later for reference.
            decl.replaceWith(image.token);
          }
        }
      }
    });

    resolve([images, opts]);
  });
}

function runSpriteSmith(images, opts) {
  return Q.Promise(function(resolve, reject) {
    var all = lodash
      .chain(images)
      .groupBy(function (image) {
        var temp;

        temp = image.groups.map(mask(true));
        temp.unshift('_');

        return temp.join(GROUP_DELIMITER);
      })
      .map(function(images, temp) {
        var config = lodash.merge({}, opts, {
          src: lodash.pluck(images, 'path')
        });
        var ratio;

        // Enlarge padding for retina images
        if (areAllRetina(images)) {
          ratio = lodash
            .chain(images)
            .flatten('ratio')
            .unique()
            .value();

          if (ratio.length === 1) {
            config.padding = config.padding * ratio[0];
          }
        }

        var checkstring = [];
        // collect images datechanged
        config.spriteName = temp.replace(/^_./,'').replace(/.@/,'@');
        lodash.each(config.src, function(image){
          checkstring.push(image+'='+md5(fs.readFileSync(image).toString()));
        });
        checkstring = md5(checkstring.join('&'));

        // get data from cache (avoid spritesmith)
        if (cache[checkstring]) {
          var deferred = Q.defer();
          var results = cache[checkstring];
          results.isFromCache = true;
          deferred.resolve(results);
          return deferred.promise;
        }

        return Q.nfcall(spritesmith, config)
          .then(function(result) {
            temp = temp.split(GROUP_DELIMITER);
            temp.shift();

            // Append info about sprite group
            result.groups = temp.map(mask(false));

            // cache - clean old
            var oldCheckstring = cacheIndex[config.spriteName];
            if (oldCheckstring && cache[oldCheckstring]) {
              delete cache[oldCheckstring];
            }
            // cache - add brand new data
            cacheIndex[config.spriteName] = checkstring;
            cache[checkstring] = result;

            return result;
          });
      })
      .value();

    Q.all(all)
      .then(function(results) {
        resolve([images, opts, results]);
      })
      .catch(function(err) {
        if (err) {
          reject(err);
        }
      });
  });
}

function saveSprites(images, opts, sprites) {
  return Q.Promise(function(resolve, reject) {

    if (!fs.existsSync(opts.spritePath)) {
      mkdirp.sync(opts.spritePath);
    }
    var all = lodash
      .chain(sprites)
      .map(function(sprite) {
        sprite.path = makeSpritePath(opts, sprite.groups);

        // if this file is up to date
        if (sprite.isFromCache) {
          var deferred = Q.defer();
          log('Easysprite:', gutil.colors.green(sprite.path), 'unchanged.');
          deferred.resolve(sprite);
          return deferred.promise;
        }

        // save new file version
        return Q.nfcall(fs.writeFile, sprite.path, new Buffer(sprite.image, 'binary'))
          .then(function() {
            log('Easysprite:', gutil.colors.yellow(sprite.path), 'generated.');
            return sprite;
          });
      })
      .value();

    Q.all(all)
      .then(function(sprites) {
        resolve([images, opts, sprites]);      })
      .catch(function(err) {
        if (err) {
          reject(err);
        }
      });
  });
}

/**
 * Map properties for every image.
 *
 * @param  {Array}  images
 * @param  {Object} opts
 * @param  {Array}  sprites
 * @return {Promise}
 */
function mapSpritesProperties(images, opts, sprites) {
  return Q.Promise(function(resolve) {
    sprites = lodash.map(sprites, function(sprite) {
      return lodash.map(sprite.coordinates, function (coordinates, imagePath) {

        return lodash.merge(lodash.find(images, { path: imagePath }), {
          coordinates: coordinates,
          spritePath: sprite.path,
          properties: sprite.properties
        });
      });
    });

    resolve([images, opts, sprites]);
  });
}

function updateReferences(images, opts, sprites, css) {
  return Q.Promise(function(resolve) {
    css.eachComment(function(comment) {
      var rule, image, backgroundImage, backgroundPosition, backgroundSize;

      // Manipulate only token comments
      if (isToken(comment)) {
        image = lodash.find(images, { url: comment.text });

        if (image) {
          // Generate correct ref to the sprite
          image.spriteRef = path.relative(image.stylesheetPath, image.spritePath);
          image.spriteRef = image.spriteRef.split(path.sep).join('/');

          backgroundImage = postcss.decl({
            prop: 'background-image',
            value: getBackgroundImageUrl(image)
          });

          backgroundPosition = postcss.decl({
            prop: 'background-position',
            value: getBackgroundPosition(image)
          });

          // Replace the comment and append necessary properties.
          comment.replaceWith(backgroundImage);

          // Output the dimensions
          rule = backgroundImage.parent;
          if (opts.outputDimensions) {
            ['height', 'width'].forEach(function(prop) {
              rule.insertAfter(backgroundImage, postcss.decl({
                prop: prop,
                value: (image.ratio>1 ? image.coordinates[prop] / image.ratio : image.coordinates[prop]) + 'px'
              }));
            });
          }

          rule.insertAfter(backgroundImage, backgroundPosition);

          if (image.ratio>1) {
            backgroundSize = postcss.decl({
              prop: 'background-size',
              value: getBackgroundSize(image)
            });

            backgroundPosition.parent.insertAfter(backgroundPosition, backgroundSize);
          }
        }
      }
    });

    resolve([images, opts, sprites, css]);
  });
}

function makeSpritePath(opts, groups) {
  var base = opts.spritePath;
  var file = path.resolve(base, groups.join('.')+'.png');
  return file.replace('.@', '@');
}

function mask(toggle) {
  var input  = new RegExp('[' + (toggle ? GROUP_DELIMITER : GROUP_MASK) + ']', 'gi');
  var output = toggle ? GROUP_MASK : GROUP_DELIMITER;

  return function(value) {
    return value.replace(input, output);
  };
}

function resolveUrl(image, opts) {
  var results;
  if (/^\//.test(image.url)) {
    results = path.resolve(opts.imagePath, image.url.replace(/^\//,''));
  } else {
    results = path.resolve(image.stylesheetPath, image.url);
  }

  // get rid of get params and hash;
  return results.split('#')[0].split('?')[0];
}

/**
 * Check that the declaration is background.
 * E.g. background-image, background, etc.
 *
 * @param  {Object}  decl
 * @return {Boolean}
 */
function isBackgroundDecl(decl) {
  return /^background/gi.test(decl.prop);
}

/**
 * Check for url in the given rule.
 *
 * @param  {String}  rule
 * @return {Boolean}
 */
function hasImageInRule(rule) {
  return /background[^:]*.*url[^;]+;/gi.test(rule);
}

/**
 * Extract the path to image from the url in given rule.
 *
 * @param  {String} rule
 * @return {String}
 */
function getImageUrl(rule) {
  var match = /background[^:]*:.*url\(([\S]+)\)/gi.exec(rule);

  return match ? match[1].replace(/['"]/gi, '') : '';
}

/**
 * Extract the background color from declaration.
 *
 * @param  {Object} decl
 * @return {String|null}
 */
function getColor(decl) {
  var regexes = ['(#([0-9a-f]{3}){1,2})', 'rgba?\\([^\\)]+\\)'];
  var matches = null;

  lodash.forEach(regexes, function(regex) {
    regex = new RegExp(regex, 'gi');

    if (regex.test(decl.value)) {
      matches = decl.value.match(regex);
    }
  });

  return matches;
}

/**
 * Check whether the comment is token that
 * should be replaced with CSS declarations.
 *
 * @param  {Object}  comment
 * @return {Boolean}
 */
function isToken(comment) {
  return /@replace/gi.test(comment.toString());
}

/**
 * Return the value for background-image property.
 *
 * @param  {Object} image
 * @return {String}
 */
function getBackgroundImageUrl(image) {
  var template = lodash.template('url(<%= image.spriteRef %>)');

  return template({ image: image });
}

/**
 * Return the value for background-position property.
 *
 * @param  {Object} image
 * @return {String}
 */
function getBackgroundPosition(image) {
  var x        = -1 * (image.ratio>1 ? image.coordinates.x / image.ratio : image.coordinates.x);
  var y        = -1 * (image.ratio>1 ? image.coordinates.y / image.ratio : image.coordinates.y);
  var template = lodash.template('<%= (x ? x + "px" : x) %> <%= (y ? y + "px" : y) %>');

  return template({ x: x, y: y });
}

/**
 * Return the value for background-size property.
 *
 * @param  {Object} image
 * @return {String}
 */
function getBackgroundSize(image) {
  var x        = image.properties.width / image.ratio;
  var y        = image.properties.height / image.ratio;
  var template = lodash.template('<%= x %>px <%= y %>px');

  return template({ x: x, y: y });
}

/**
 * Check whether the image is retina.
 * @param  {String}  url
 * @return {Boolean}
 */
function isRetinaImage(url) {
  return /@(\d)x\.[a-z]{3,4}$/gi.test(url.split('#')[0]);
}

/**
 * Return the retina ratio.
 *
 * @param  {String} url
 * @return {Number}
 */
function getRetinaRatio(url) {
  var matches = /@(\d)x\.[a-z]{3,4}$/gi.exec(url.split('#')[0]);
  var ratio   = lodash.parseInt(matches[1]);

  return ratio;
}

/**
 * Check whether all images are retina.
 *
 * @param  {Array}  images
 * @return {Boolean}
 */
function areAllRetina(images) {
  return lodash.every(images, function(image) {
    return image.ratio>1;
  });
}<commit_msg>clean console output<commit_after>var postcss = require('postcss');
var Q = require('q');
var lodash = require('lodash');
var url = require('url');
var path = require('path');
var async = require('async');
var spritesmith = require('spritesmith');
var mkdirp = require('mkdirp');
var fs = require('fs');
var md5 = require('md5');
var gutil = require('gulp-util');

// cache objects;
var cache = {};
var cacheIndex = {};

// for debug
function debug() {
  var data = [gutil.colors.red('debug'), ':']
    .concat(Array.prototype.slice.call(arguments));
  gutil.log.apply(false, data);
}
function log() {
  var data = Array.prototype.slice.call(arguments);
  gutil.log.apply(false, data);
}

/**
 * Constants.
 *
 * @type {String}
 */
var GROUP_DELIMITER   = '.';
var GROUP_MASK        = '*';
var BACKGROUND        = 'background';
var BACKGROUND_IMAGE  = 'background-image';

module.exports = postcss.plugin('postcss-easysprite', function (opts) {
    opts = opts || {};

    // opts
    opts = opts || {};
    opts.groupBy = opts.groupBy || [];
    opts.padding = opts.padding ? opts.padding : 20;

    // paths
    opts.imagePath = path.resolve(process.cwd(), opts.imagePath||'');
    opts.spritePath = path.resolve(process.cwd(), opts.spritePath||'');

    // Group retina images
    opts.groupBy.unshift(function(image) {
      if (image.ratio>1) { return '@' + image.ratio + 'x'; }
      return null;
    });

    return function (css) {
      // if file path

      return Q
        // prepare part
        .all([collectImages(css, opts), opts])
        .spread(applyGroupBy)
        .spread(function(images, opts){
          return setTokens(images, opts, css);
        })
        // compilation part
        .spread(runSpriteSmith)
        .spread(saveSprites)
        .spread(mapSpritesProperties)
        .spread(function(images, opts, sprites) {
          return updateReferences(images, opts, sprites, css);
        });
    };
});

function collectImages(css, opts) {
  var images = [];
  var stylesheetPath = opts.stylesheetPath || path.dirname(css.source.input.file);
  if (!stylesheetPath) {
    throw 'Stylesheets path is undefined, please use option stylesheetPath!';
  }

  css.eachRule(function(rule) {
    var image = {
      path    : null,
      url     : null,
      stylesheetPath : stylesheetPath,
      ratio   : 1,
      groups  : [],
      token   : ''
    };

    if (hasImageInRule(rule.toString())) {
      image.url = getImageUrl(rule.toString());
      var imageUrl = url.parse(image.url);

      // only locals, hashed paths
      if (imageUrl.host ||
          !imageUrl.hash ||
          imageUrl.pathname.indexOf('//') === 0 ||
          imageUrl.pathname.indexOf(';base64') !== -1) {
        return;
      }

      image.groups = [imageUrl.hash.replace('#','')];

      // Perform search for retina
      if (isRetinaImage(image.url)) {
        image.ratio  = getRetinaRatio(image.url);
      }

      // Get the path to the image.
      image.path = resolveUrl(image, opts);

      images.push(image);
    }
  });

  return images;
}

function applyGroupBy(images, opts) {
  return Q.Promise(function(resolve, reject) {
    async.reduce(opts.groupBy, images, function(images, group, next) {
      async.map(images, function(image, done) {
        new Q(group(image))
          .then(function(group) {
            if (group) {
              image.groups.push(group);
            }

            done(null, image);
          })
          .catch(done);
      }, next);
    }, function(err, images) {
      if (err) {
        return reject(err);
      }

      resolve([images, opts]);
    });
  });
}

function setTokens(images, opts, css) {
  return Q.Promise(function(resolve) {
    css.eachDecl(/^background(-image)?$/, function(decl) {
      var rule = decl.parent;
      var url, image, color;

      // Manipulate only rules with background image
      // in them.
      if (hasImageInRule(rule.toString())) {
        url   = getImageUrl(rule.toString());
        image = lodash.find(images, { url: url });

        if (image) {
          // We remove these declarations since
          // our plugin will insert them when
          // they are necessary.
          rule.eachDecl(/^background-(repeat|size|position)$/, function(decl) {
            decl.removeSelf();
          });

          if (decl.prop === BACKGROUND) {
            color = getColor(decl);

            // Extract color to background-color propery
            if (color && color.length === 1) {
              rule.append({
                prop: 'background-color',
                value: color[0],
                before: ' '
              });
            }
          }

          if (decl.prop === BACKGROUND || decl.prop === BACKGROUND_IMAGE) {
            image.token = postcss.comment({
              text: image.url,
              before: ' ',
              left: '@replace|',
              right: ''
            });

            // Replace the declaration with a comment token
            // which will be used later for reference.
            decl.replaceWith(image.token);
          }
        }
      }
    });

    resolve([images, opts]);
  });
}

function runSpriteSmith(images, opts) {
  return Q.Promise(function(resolve, reject) {
    var all = lodash
      .chain(images)
      .groupBy(function (image) {
        var temp;

        temp = image.groups.map(mask(true));
        temp.unshift('_');

        return temp.join(GROUP_DELIMITER);
      })
      .map(function(images, temp) {
        var config = lodash.merge({}, opts, {
          src: lodash.pluck(images, 'path')
        });
        var ratio;

        // Enlarge padding for retina images
        if (areAllRetina(images)) {
          ratio = lodash
            .chain(images)
            .flatten('ratio')
            .unique()
            .value();

          if (ratio.length === 1) {
            config.padding = config.padding * ratio[0];
          }
        }

        var checkstring = [];
        // collect images datechanged
        config.spriteName = temp.replace(/^_./,'').replace(/.@/,'@');
        lodash.each(config.src, function(image){
          checkstring.push(image+'='+md5(fs.readFileSync(image).toString()));
        });
        checkstring = md5(checkstring.join('&'));

        // get data from cache (avoid spritesmith)
        if (cache[checkstring]) {
          var deferred = Q.defer();
          var results = cache[checkstring];
          results.isFromCache = true;
          deferred.resolve(results);
          return deferred.promise;
        }

        return Q.nfcall(spritesmith, config)
          .then(function(result) {
            temp = temp.split(GROUP_DELIMITER);
            temp.shift();

            // Append info about sprite group
            result.groups = temp.map(mask(false));

            // cache - clean old
            var oldCheckstring = cacheIndex[config.spriteName];
            if (oldCheckstring && cache[oldCheckstring]) {
              delete cache[oldCheckstring];
            }
            // cache - add brand new data
            cacheIndex[config.spriteName] = checkstring;
            cache[checkstring] = result;

            return result;
          });
      })
      .value();

    Q.all(all)
      .then(function(results) {
        resolve([images, opts, results]);
      })
      .catch(function(err) {
        if (err) {
          reject(err);
        }
      });
  });
}

function saveSprites(images, opts, sprites) {
  return Q.Promise(function(resolve, reject) {

    if (!fs.existsSync(opts.spritePath)) {
      mkdirp.sync(opts.spritePath);
    }
    var all = lodash
      .chain(sprites)
      .map(function(sprite) {
        sprite.path = makeSpritePath(opts, sprite.groups);

        // if this file is up to date
        if (sprite.isFromCache) {
          var deferred = Q.defer();
          log('Easysprite:', gutil.colors.green(sprite.path), 'unchanged.');
          deferred.resolve(sprite);
          return deferred.promise;
        }

        // save new file version
        return Q.nfcall(fs.writeFile, sprite.path, new Buffer(sprite.image, 'binary'))
          .then(function() {
            log('Easysprite:', gutil.colors.yellow(sprite.path), 'generated.');
            return sprite;
          });
      })
      .value();

    Q.all(all)
      .then(function(sprites) {
        resolve([images, opts, sprites]);      })
      .catch(function(err) {
        if (err) {
          reject(err);
        }
      });
  });
}

/**
 * Map properties for every image.
 *
 * @param  {Array}  images
 * @param  {Object} opts
 * @param  {Array}  sprites
 * @return {Promise}
 */
function mapSpritesProperties(images, opts, sprites) {
  return Q.Promise(function(resolve) {
    sprites = lodash.map(sprites, function(sprite) {
      return lodash.map(sprite.coordinates, function (coordinates, imagePath) {

        return lodash.merge(lodash.find(images, { path: imagePath }), {
          coordinates: coordinates,
          spritePath: sprite.path,
          properties: sprite.properties
        });
      });
    });

    resolve([images, opts, sprites]);
  });
}

function updateReferences(images, opts, sprites, css) {
  return Q.Promise(function(resolve) {
    css.eachComment(function(comment) {
      var rule, image, backgroundImage, backgroundPosition, backgroundSize;

      // Manipulate only token comments
      if (isToken(comment)) {
        image = lodash.find(images, { url: comment.text });

        if (image) {
          // Generate correct ref to the sprite
          image.spriteRef = path.relative(image.stylesheetPath, image.spritePath);
          image.spriteRef = image.spriteRef.split(path.sep).join('/');

          backgroundImage = postcss.decl({
            prop: 'background-image',
            value: getBackgroundImageUrl(image)
          });

          backgroundPosition = postcss.decl({
            prop: 'background-position',
            value: getBackgroundPosition(image)
          });

          // Replace the comment and append necessary properties.
          comment.replaceWith(backgroundImage);

          // Output the dimensions
          rule = backgroundImage.parent;
          if (opts.outputDimensions) {
            ['height', 'width'].forEach(function(prop) {
              rule.insertAfter(backgroundImage, postcss.decl({
                prop: prop,
                value: (image.ratio>1 ? image.coordinates[prop] / image.ratio : image.coordinates[prop]) + 'px'
              }));
            });
          }

          rule.insertAfter(backgroundImage, backgroundPosition);

          if (image.ratio>1) {
            backgroundSize = postcss.decl({
              prop: 'background-size',
              value: getBackgroundSize(image)
            });

            backgroundPosition.parent.insertAfter(backgroundPosition, backgroundSize);
          }
        }
      }
    });

    resolve([images, opts, sprites, css]);
  });
}

function makeSpritePath(opts, groups) {
  var base = opts.spritePath;
  var file = path.resolve(base, groups.join('.')+'.png');
  return file.replace('.@', '@');
}

function mask(toggle) {
  var input  = new RegExp('[' + (toggle ? GROUP_DELIMITER : GROUP_MASK) + ']', 'gi');
  var output = toggle ? GROUP_MASK : GROUP_DELIMITER;

  return function(value) {
    return value.replace(input, output);
  };
}

function resolveUrl(image, opts) {
  var results;
  if (/^\//.test(image.url)) {
    results = path.resolve(opts.imagePath, image.url.replace(/^\//,''));
  } else {
    results = path.resolve(image.stylesheetPath, image.url);
  }

  // get rid of get params and hash;
  return results.split('#')[0].split('?')[0];
}

/**
 * Check that the declaration is background.
 * E.g. background-image, background, etc.
 *
 * @param  {Object}  decl
 * @return {Boolean}
 */
function isBackgroundDecl(decl) {
  return /^background/gi.test(decl.prop);
}

/**
 * Check for url in the given rule.
 *
 * @param  {String}  rule
 * @return {Boolean}
 */
function hasImageInRule(rule) {
  return /background[^:]*.*url[^;]+;/gi.test(rule);
}

/**
 * Extract the path to image from the url in given rule.
 *
 * @param  {String} rule
 * @return {String}
 */
function getImageUrl(rule) {
  var match = /background[^:]*:.*url\(([\S]+)\)/gi.exec(rule);

  return match ? match[1].replace(/['"]/gi, '') : '';
}

/**
 * Extract the background color from declaration.
 *
 * @param  {Object} decl
 * @return {String|null}
 */
function getColor(decl) {
  var regexes = ['(#([0-9a-f]{3}){1,2})', 'rgba?\\([^\\)]+\\)'];
  var matches = null;

  lodash.forEach(regexes, function(regex) {
    regex = new RegExp(regex, 'gi');

    if (regex.test(decl.value)) {
      matches = decl.value.match(regex);
    }
  });

  return matches;
}

/**
 * Check whether the comment is token that
 * should be replaced with CSS declarations.
 *
 * @param  {Object}  comment
 * @return {Boolean}
 */
function isToken(comment) {
  return /@replace/gi.test(comment.toString());
}

/**
 * Return the value for background-image property.
 *
 * @param  {Object} image
 * @return {String}
 */
function getBackgroundImageUrl(image) {
  var template = lodash.template('url(<%= image.spriteRef %>)');

  return template({ image: image });
}

/**
 * Return the value for background-position property.
 *
 * @param  {Object} image
 * @return {String}
 */
function getBackgroundPosition(image) {
  var x        = -1 * (image.ratio>1 ? image.coordinates.x / image.ratio : image.coordinates.x);
  var y        = -1 * (image.ratio>1 ? image.coordinates.y / image.ratio : image.coordinates.y);
  var template = lodash.template('<%= (x ? x + "px" : x) %> <%= (y ? y + "px" : y) %>');

  return template({ x: x, y: y });
}

/**
 * Return the value for background-size property.
 *
 * @param  {Object} image
 * @return {String}
 */
function getBackgroundSize(image) {
  var x        = image.properties.width / image.ratio;
  var y        = image.properties.height / image.ratio;
  var template = lodash.template('<%= x %>px <%= y %>px');

  return template({ x: x, y: y });
}

/**
 * Check whether the image is retina.
 * @param  {String}  url
 * @return {Boolean}
 */
function isRetinaImage(url) {
  return /@(\d)x\.[a-z]{3,4}$/gi.test(url.split('#')[0]);
}

/**
 * Return the retina ratio.
 *
 * @param  {String} url
 * @return {Number}
 */
function getRetinaRatio(url) {
  var matches = /@(\d)x\.[a-z]{3,4}$/gi.exec(url.split('#')[0]);
  var ratio   = lodash.parseInt(matches[1]);

  return ratio;
}

/**
 * Check whether all images are retina.
 *
 * @param  {Array}  images
 * @return {Boolean}
 */
function areAllRetina(images) {
  return lodash.every(images, function(image) {
    return image.ratio>1;
  });
}<|endoftext|>


<commit_before>var path = require('path'),
    fs = require('fs'),
    Step = require('step'),
    resolved = {};

var resolve = function(m) {
    if (resolved[m] === undefined) {
        try {
            require(m);
            for (var key in module.parent.moduleCache) {
                var cache = module.parent.moduleCache[key];
                if (cache.id === m) {
                    resolved[m] = path.dirname(cache.filename);
                    break;
                }
            }
        } catch(e) {
            throw new Error('Require ' + m + 'failed.');
        }
    }
    return resolved[m];
};

var assets = function(assets, headers) {
    (typeof assets === 'string') && (assets = [assets]);
    headers = headers || {'Content-Type': 'text/javascript'};
    return function(req, res, next) {
        Step(
            function() {
                var group = this.group();
                for (var i = 0; i < assets.length; i++) {
                    var split = assets[i].split('/'),
                        module = split.shift(),
                        basepath = resolve(module),
                        filepath = split.join('/');
                    fs.readFile(path.join(basepath, filepath), 'utf8', group());
                }
            },
            function(err, data) {
                if (err) next(new Error('Failed to load assets.'));
                res.send(data.join('\n'), headers);
            }
        );
    };
};

var file = function(asset) {
    var split = asset.split('/'),
        module = split.shift(),
        filename = split.join('/');
    return function(req, res, next) {
        res.sendfile(path.join(resolve(module), filename));
    };
};

module.exports = {
    assets: assets,
    file: file,
    resolve: resolve
};

<commit_msg>Fix error handling.<commit_after>var path = require('path'),
    fs = require('fs'),
    Step = require('step'),
    resolved = {};

var resolve = function(m) {
    if (resolved[m] === undefined) {
        try {
            require(m);
            for (var key in module.parent.moduleCache) {
                var cache = module.parent.moduleCache[key];
                if (cache.id === m) {
                    resolved[m] = path.dirname(cache.filename);
                    break;
                }
            }
        } catch(e) {
            throw new Error('Require ' + m + ' failed.');
        }
    }
    return resolved[m];
};

var assets = function(assets, headers) {
    (typeof assets === 'string') && (assets = [assets]);
    headers = headers || {'Content-Type': 'text/javascript'};
    return function(req, res, next) {
        Step(
            function() {
                var group = this.group();
                for (var i = 0; i < assets.length; i++) {
                    var split = assets[i].split('/'),
                        module = split.shift(),
                        basepath = resolve(module),
                        filepath = split.join('/');
                    fs.readFile(path.join(basepath, filepath), 'utf8', group());
                }
            },
            function(err, data) {
                if (err) return next(err);
                res.send(data.join('\n'), headers);
            }
        );
    };
};

var file = function(asset) {
    var split = asset.split('/'),
        module = split.shift(),
        filename = split.join('/');
    return function(req, res, next) {
        res.sendfile(path.join(resolve(module), filename));
    };
};

module.exports = {
    assets: assets,
    file: file,
    resolve: resolve
};

<|endoftext|>


<commit_before>'use strict';

/**
 * module dependencies
 */

var path = require('path');
var async = require('async');
var runtimes = require('composer-runtimes');
var Boilerplate = require('boilerplate');
var Templates = require('templates');
var Scaffold = require('scaffold');
var Composer = require('composer');
var proto = Composer.prototype;
var utils = require('./lib/utils');

/**
 * Create an `assemble` application. This is the main function exported
 * by the assemble module.
 *
 * ```js
 * var assemble = require('assemble');
 * var app = assemble();
 * ```
 * @param {Object} `options` Optionally pass default options to use.
 * @api public
 */

function Assemble(options) {
  if (!(this instanceof Assemble)) {
    return new Assemble(options);
  }

  Templates.apply(this, arguments);
  Composer.apply(this, arguments);
  this.set('Boilerplate', this.options.Boilerplate || Boilerplate);
  this.set('Scaffold', this.options.Scaffold || Scaffold);
  this.boilerplates = {};
  this.scaffolds = {};
  this.init();
}

Templates.inherit(Assemble, Composer);

/**
 * `Assemble` prototype methods
 */

Templates.extend(Assemble, {
  constructor: Assemble,

  /**
   * Initialize Assemble defaults
   */

  init: function() {
    this.defaultEngine();
    this.defaultMiddleware();
    this.defaultViewTypes();
  },

  /**
   * Default template engine and related extensions.
   */

  defaultEngine: function () {
    this.engine(['hbs', 'html', 'md'], require('engine-handlebars'));
  },

  /**
   * Default middleware
   *  | Ensure user-defined layout is recognized
   *  | Parse front-matter
   */

  defaultMiddleware: function () {
    this.preLayout(/\.(hbs|md|html)$/, function (view, next) {
      if (!view.layout) view.layout = view.locals.layout || view.data.layout;
      next();
    });
    this.onLoad(/\.(hbs|md|html)$/, function (view, next) {
      utils.matter.parse(view, next);
    });
  },

  /**
   * Default `viewTypes`
   *  | partials
   *  | layouts
   *  | pages
   *  | files
   */

  defaultViewTypes: function () {
    this.create('partials', {
      viewType: 'partial',
      renameKey: function (fp) {
        return path.basename(fp, path.extname(fp));
      }
    });

    this.create('layouts', {
      viewType: 'layout',
      renameKey: function (fp) {
        return path.basename(fp, path.extname(fp));
      }
    });

    this.create('pages', {
      renameKey: function (fp) {
        return fp;
      }
    });

    this.create('files', {
      renameKey: function (fp) {
        return fp;
      }
    });
  },

  /**
   * Copy a file from `src` to `dest` and process any templates in
   * `file.contents`.
   *
   * @name .process
   * @param {Object} `file` [Vinyl][] file object.
   * @param {Object} `options`
   * @return {Stream} Returns a stream to continue processing if needed.
   * @api public
   */

  process: function (file, options) {
    options = options || {};
    var pre = options.preprocess || options.pipeline || utils.identity;
    var post = options.postprocess || utils.identity;
    var stream = this.src(file.src);

    stream = pre(stream, this).pipe(this.renderFile(file.data || {}));
    return post(stream, this).pipe(this.dest(file.dest));
  },

  /**
   * Generate all of the `src`/`dest` definitions in the given
   * `config` object. Used for generating [boilerplates][] and
   * [scaffolds][].
   *
   * @name .generate
   * @param {Object} `config` The configuration object to use.
   * @param {Function} `cb` Callback function, exposes `err` on the callback.
   * @return {Object} Returns the `Assemble` instance for chaining.
   * @api public
   */

  generate: function (config, cb) {
    var opts = {};
    opts.preprocess = config.preprocess;
    opts.postprocess = config.postprocess;
    async.each(config.files, function (file, next) {
      utils.parallel(this.process(file, opts), next);
    }.bind(this), cb);
    return this;
  },

  /**
   * Register and/or generate a boilerplate from the given `config`.
   *
   * @name .boilerplate
   * @param {String} `name` The name of the boilerplate to register
   * @param {Object} `config` The configuration object to use.
   * @return {Object} Returns the `Boilerplate` instance for chaining.
   * @api public
   */

  boilerplate: function (name, config) {
    if (!config && typeof name === 'string') {
      return this.boilerplates[name];
    }

    var Boilerplate = this.get('Boilerplate');
    var boilerplate = !(config instanceof Boilerplate)
      ? new Boilerplate(config)
      : config;

    var app = this;
    boilerplate.generate = function (options, cb) {
      var targets = Object.keys(boilerplate.targets);
      async.each(targets, function (target, next) {
        app.generate(target, options, next);
      }, cb);
    };

    this.boilerplates[name] = boilerplate;
    return boilerplate;
  },

  /**
   * Generate a scaffold from the given `config`.
   *
   * @name .scaffold
   * @param {String} `name`
   * @param {Object} `config`
   * @return {Object} Returns the `Assemble` instance for chaining
   * @api public
   */

  scaffold: function (name, config) {
    if (!config && typeof name === 'string') {
      return this.scaffolds[name];
    }

    var Scaffold = this.get('Scaffold');
    var scaffold = !(config instanceof Scaffold)
      ? new Scaffold(config)
      : config;

    var app = this;
    scaffold.generate = function (cb) {
      var args = [].slice.call(arguments);
      args.unshift(this);
      return app.generate.apply(app, args);
    };

    this.scaffolds[name] = scaffold;
    return this;
  },

  /**
   * Glob patterns or filepaths to source files.
   *
   * ```js
   * app.src('src/*.hbs', {layout: 'default'});
   * ```
   * @name .src
   * @param {String|Array} `glob` Glob patterns or file paths to source files.
   * @param {Object} `options` Options or locals to merge into the context and/or pass to `src` plugins
   * @api public
   */

  src: function () {
    return utils.vfs.src.apply(utils.vfs, arguments);
  },

  /**
   * Glob patterns or paths for symlinks.
   *
   * ```js
   * app.symlink('src/**');
   * ```
   * @name .symlink
   * @param {String|Array} `glob`
   * @api public
   */

  symlink: function () {
    return utils.vfs.symlink.apply(utils.vfs, arguments);
  },

  /**
   * Specify a destination for processed files.
   *
   * ```js
   * app.dest('dist/');
   * ```
   * @name .dest
   * @param {String|Function} `dest` File path or rename function.
   * @param {Object} `options` Options and locals to pass to `dest` plugins
   * @api public
   */

  dest: function () {
    return utils.vfs.dest.apply(utils.vfs, arguments)
      .on('data', function () {}); // TODO: fix this
  },

  /**
   * Copy files with the given glob `patterns` to the specified `destDir`.
   *
   * ```js
   * app.task('assets', function() {
   *   app.copy('assets/**', 'dist/');
   * });
   * ```
   * @name .copy
   * @param {String|Array} `patterns` Glob patterns of files to copy.
   * @param  {String|Function} `dest` Desination directory.
   * @return {Stream} Stream, to continue processing if necessary.
   * @api public
   */

  copy: function(patterns, dest, options) {
    return utils.vfs.src(patterns, options)
      .pipe(utils.vfs.dest(dest, options));
  },

  /**
   * Push a view collection into a vinyl stream.
   *
   * ```js
   * app.toStream('posts', function(file) {
   *   return file.path !== 'index.hbs';
   * })
   * ```
   * @name .toStream
   * @param {String} `collection` The name of the view collection to push into the stream.
   * @param {Function} Optionally pass a filter function to use for filtering views.
   * @return {Stream}
   * @api public
   */

  toStream: function (collection, fn) {
    var views = this.getViews(collection) || {};
    var stream = utils.through.obj();
    return utils.srcStream(function () {
      setImmediate(function () {
        Object.keys(views).forEach(function (key) {
          var view = views[key];
          var file = utils.toVinyl(view);
          stream.write(file);
        });
        stream.end();
      });
      return stream;
    });
  },

  /**
   * Render a vinyl file.
   *
   * ```js
   * app.src('*.hbs')
   *   .pipe(app.renderFile());
   * ```
   *
   * @name .renderFile
   * @param  {Object} `locals` Optionally locals to pass to the template engine for rendering.
   * @return {Object}
   * @api public
   */

  renderFile: function (locals) {
    var app = this;
    var collection = this.collection();
    return utils.through.obj(function (file, enc, cb) {
      if (typeof locals === 'function') {
        cb = locals;
        locals = {};
      }
      var view = collection.view(file);
      app.handleView('onLoad', view)
      app.render(view, locals, function (err, res) {
        if (err) return cb(err);
        res.contents = new Buffer(res.content);
        file = new utils.Vinyl(res);
        cb(null, file);
      });
    });
  },

  /**
   * Define an Assemble task.
   *
   * ```js
   * app.task('default', function() {
   *   app.src('templates/*.hbs')
   *     .pipe(app.dest('dist/'));
   * });
   * ```
   *
   * @name .task
   * @param {String} `name` Task name
   * @param {Function} `fn` function that is called when the task is run.
   * @api public
   */

  task: function (name) {
    runtimes(this);
    return proto.task.apply(this, arguments);
  },

  /**
   * Run one or more tasks.
   *
   * ```js
   * app.run(['foo', 'bar'], function(err) {
   *   if (err) console.error('ERROR:', err);
   * });
   * ```
   * @name .run
   * @param {Array|String} `tasks` Task name or array of task names.
   * @param {Function} `cb` callback function that exposes `err`
   * @api public
   */

  run: function (tasks, cb) {
    return proto.run.apply(this, arguments);
  },

  /**
   * Re-run the specified task(s) when a file changes.
   *
   * ```js
   * app.task('watch', function() {
   *   app.watch('docs/*.md', ['docs']);
   * });
   * ```
   *
   * @param  {String|Array} `glob` Filepaths or glob patterns.
   * @param  {Array} `tasks` Task(s) to watch.
   * @api public
   */

  watch: function (glob, tasks) {
    return proto.watch.apply(this, arguments);
  }
});

/**
 * Expose the `Assemble` constructor
 */

module.exports = Assemble;
<commit_msg>need to pass an actual stream to src-stream<commit_after>'use strict';

/**
 * module dependencies
 */

var path = require('path');
var async = require('async');
var runtimes = require('composer-runtimes');
var Boilerplate = require('boilerplate');
var Templates = require('templates');
var Scaffold = require('scaffold');
var Composer = require('composer');
var proto = Composer.prototype;
var utils = require('./lib/utils');

/**
 * Create an `assemble` application. This is the main function exported
 * by the assemble module.
 *
 * ```js
 * var assemble = require('assemble');
 * var app = assemble();
 * ```
 * @param {Object} `options` Optionally pass default options to use.
 * @api public
 */

function Assemble(options) {
  if (!(this instanceof Assemble)) {
    return new Assemble(options);
  }

  Templates.apply(this, arguments);
  Composer.apply(this, arguments);
  this.set('Boilerplate', this.options.Boilerplate || Boilerplate);
  this.set('Scaffold', this.options.Scaffold || Scaffold);
  this.boilerplates = {};
  this.scaffolds = {};
  this.init();
}

Templates.inherit(Assemble, Composer);

/**
 * `Assemble` prototype methods
 */

Templates.extend(Assemble, {
  constructor: Assemble,

  /**
   * Initialize Assemble defaults
   */

  init: function() {
    this.defaultEngine();
    this.defaultMiddleware();
    this.defaultViewTypes();
  },

  /**
   * Default template engine and related extensions.
   */

  defaultEngine: function () {
    this.engine(['hbs', 'html', 'md'], require('engine-handlebars'));
  },

  /**
   * Default middleware
   *  | Ensure user-defined layout is recognized
   *  | Parse front-matter
   */

  defaultMiddleware: function () {
    this.preLayout(/\.(hbs|md|html)$/, function (view, next) {
      if (!view.layout) view.layout = view.locals.layout || view.data.layout;
      next();
    });
    this.onLoad(/\.(hbs|md|html)$/, function (view, next) {
      utils.matter.parse(view, next);
    });
  },

  /**
   * Default `viewTypes`
   *  | partials
   *  | layouts
   *  | pages
   *  | files
   */

  defaultViewTypes: function () {
    this.create('partials', {
      viewType: 'partial',
      renameKey: function (fp) {
        return path.basename(fp, path.extname(fp));
      }
    });

    this.create('layouts', {
      viewType: 'layout',
      renameKey: function (fp) {
        return path.basename(fp, path.extname(fp));
      }
    });

    this.create('pages', {
      renameKey: function (fp) {
        return fp;
      }
    });

    this.create('files', {
      renameKey: function (fp) {
        return fp;
      }
    });
  },

  /**
   * Copy a file from `src` to `dest` and process any templates in
   * `file.contents`.
   *
   * @name .process
   * @param {Object} `file` [Vinyl][] file object.
   * @param {Object} `options`
   * @return {Stream} Returns a stream to continue processing if needed.
   * @api public
   */

  process: function (file, options) {
    options = options || {};
    var pre = options.preprocess || options.pipeline || utils.identity;
    var post = options.postprocess || utils.identity;
    var stream = this.src(file.src);

    stream = pre(stream, this).pipe(this.renderFile(file.data || {}));
    return post(stream, this).pipe(this.dest(file.dest));
  },

  /**
   * Generate all of the `src`/`dest` definitions in the given
   * `config` object. Used for generating [boilerplates][] and
   * [scaffolds][].
   *
   * @name .generate
   * @param {Object} `config` The configuration object to use.
   * @param {Function} `cb` Callback function, exposes `err` on the callback.
   * @return {Object} Returns the `Assemble` instance for chaining.
   * @api public
   */

  generate: function (config, cb) {
    var opts = {};
    opts.preprocess = config.preprocess;
    opts.postprocess = config.postprocess;
    async.each(config.files, function (file, next) {
      utils.parallel(this.process(file, opts), next);
    }.bind(this), cb);
    return this;
  },

  /**
   * Register and/or generate a boilerplate from the given `config`.
   *
   * @name .boilerplate
   * @param {String} `name` The name of the boilerplate to register
   * @param {Object} `config` The configuration object to use.
   * @return {Object} Returns the `Boilerplate` instance for chaining.
   * @api public
   */

  boilerplate: function (name, config) {
    if (!config && typeof name === 'string') {
      return this.boilerplates[name];
    }

    var Boilerplate = this.get('Boilerplate');
    var boilerplate = !(config instanceof Boilerplate)
      ? new Boilerplate(config)
      : config;

    var app = this;
    boilerplate.generate = function (options, cb) {
      var targets = Object.keys(boilerplate.targets);
      async.each(targets, function (target, next) {
        app.generate(target, options, next);
      }, cb);
    };

    this.boilerplates[name] = boilerplate;
    return boilerplate;
  },

  /**
   * Generate a scaffold from the given `config`.
   *
   * @name .scaffold
   * @param {String} `name`
   * @param {Object} `config`
   * @return {Object} Returns the `Assemble` instance for chaining
   * @api public
   */

  scaffold: function (name, config) {
    if (!config && typeof name === 'string') {
      return this.scaffolds[name];
    }

    var Scaffold = this.get('Scaffold');
    var scaffold = !(config instanceof Scaffold)
      ? new Scaffold(config)
      : config;

    var app = this;
    scaffold.generate = function (cb) {
      var args = [].slice.call(arguments);
      args.unshift(this);
      return app.generate.apply(app, args);
    };

    this.scaffolds[name] = scaffold;
    return this;
  },

  /**
   * Glob patterns or filepaths to source files.
   *
   * ```js
   * app.src('src/*.hbs', {layout: 'default'});
   * ```
   * @name .src
   * @param {String|Array} `glob` Glob patterns or file paths to source files.
   * @param {Object} `options` Options or locals to merge into the context and/or pass to `src` plugins
   * @api public
   */

  src: function () {
    return utils.vfs.src.apply(utils.vfs, arguments);
  },

  /**
   * Glob patterns or paths for symlinks.
   *
   * ```js
   * app.symlink('src/**');
   * ```
   * @name .symlink
   * @param {String|Array} `glob`
   * @api public
   */

  symlink: function () {
    return utils.vfs.symlink.apply(utils.vfs, arguments);
  },

  /**
   * Specify a destination for processed files.
   *
   * ```js
   * app.dest('dist/');
   * ```
   * @name .dest
   * @param {String|Function} `dest` File path or rename function.
   * @param {Object} `options` Options and locals to pass to `dest` plugins
   * @api public
   */

  dest: function () {
    return utils.vfs.dest.apply(utils.vfs, arguments)
      .on('data', function () {}); // TODO: fix this
  },

  /**
   * Copy files with the given glob `patterns` to the specified `destDir`.
   *
   * ```js
   * app.task('assets', function() {
   *   app.copy('assets/**', 'dist/');
   * });
   * ```
   * @name .copy
   * @param {String|Array} `patterns` Glob patterns of files to copy.
   * @param  {String|Function} `dest` Desination directory.
   * @return {Stream} Stream, to continue processing if necessary.
   * @api public
   */

  copy: function(patterns, dest, options) {
    return utils.vfs.src(patterns, options)
      .pipe(utils.vfs.dest(dest, options));
  },

  /**
   * Push a view collection into a vinyl stream.
   *
   * ```js
   * app.toStream('posts', function(file) {
   *   return file.path !== 'index.hbs';
   * })
   * ```
   * @name .toStream
   * @param {String} `collection` The name of the view collection to push into the stream.
   * @param {Function} Optionally pass a filter function to use for filtering views.
   * @return {Stream}
   * @api public
   */

  toStream: function (collection, fn) {
    var views = this.getViews(collection) || {};
    var stream = utils.through.obj();
    return utils.srcStream(function () {
      setImmediate(function () {
        Object.keys(views).forEach(function (key) {
          var view = views[key];
          var file = utils.toVinyl(view);
          stream.write(file);
        });
        stream.end();
      }());
      return stream;
    });
  },

  /**
   * Render a vinyl file.
   *
   * ```js
   * app.src('*.hbs')
   *   .pipe(app.renderFile());
   * ```
   *
   * @name .renderFile
   * @param  {Object} `locals` Optionally locals to pass to the template engine for rendering.
   * @return {Object}
   * @api public
   */

  renderFile: function (locals) {
    var app = this;
    var collection = this.collection();
    return utils.through.obj(function (file, enc, cb) {
      if (typeof locals === 'function') {
        cb = locals;
        locals = {};
      }
      var view = collection.view(file);
      app.handleView('onLoad', view)
      app.render(view, locals, function (err, res) {
        if (err) return cb(err);
        res.contents = new Buffer(res.content);
        file = new utils.Vinyl(res);
        cb(null, file);
      });
    });
  },

  /**
   * Define an Assemble task.
   *
   * ```js
   * app.task('default', function() {
   *   app.src('templates/*.hbs')
   *     .pipe(app.dest('dist/'));
   * });
   * ```
   *
   * @name .task
   * @param {String} `name` Task name
   * @param {Function} `fn` function that is called when the task is run.
   * @api public
   */

  task: function (name) {
    runtimes(this);
    return proto.task.apply(this, arguments);
  },

  /**
   * Run one or more tasks.
   *
   * ```js
   * app.run(['foo', 'bar'], function(err) {
   *   if (err) console.error('ERROR:', err);
   * });
   * ```
   * @name .run
   * @param {Array|String} `tasks` Task name or array of task names.
   * @param {Function} `cb` callback function that exposes `err`
   * @api public
   */

  run: function (tasks, cb) {
    return proto.run.apply(this, arguments);
  },

  /**
   * Re-run the specified task(s) when a file changes.
   *
   * ```js
   * app.task('watch', function() {
   *   app.watch('docs/*.md', ['docs']);
   * });
   * ```
   *
   * @param  {String|Array} `glob` Filepaths or glob patterns.
   * @param  {Array} `tasks` Task(s) to watch.
   * @api public
   */

  watch: function (glob, tasks) {
    return proto.watch.apply(this, arguments);
  }
});

/**
 * Expose the `Assemble` constructor
 */

module.exports = Assemble;
<|endoftext|>


<commit_before>// Generated by CoffeeScript 1.9.3
var $, MathSwipeController, Tuple, Two, game;

$ = require('jquery');

MathSwipeController = require('./app/controllers/MathSwipeController');

Tuple = require('./app/models/Tuple');

Two = require('two.js');

game = new MathSwipeController;
<commit_msg>remove index.js<commit_after><|endoftext|>


<commit_before>'use strict';

var util = require('util'),
    assert = require('assert'),
    retryFn = require('retry-fn'),
    FlushWritable = require('flushwritable'),
    _ = require('lodash');

util.inherits(KinesisWritable, FlushWritable);

/**
 * A simple stream wrapper around Kinesis putRecords
 *
 * @param {AWS.Kinesis} client AWS Kinesis client
 * @param {string} streamName Kinesis stream name
 * @param {Object} options Options
 * @param {number} [options.highWaterMark=16] Number of items to buffer before writing.
 * Also the size of the underlying stream buffer.
 * @param {Number} [options.maxRetries=3] How many times to retry failed data before
 * rasing an error
 * @param {Number} [options.retryTimeout=100] How long to wait initially before
 * retrying failed records
 * @param {Object} [options.logger] Instance of a logger like bunyan or winston
 */
function KinesisWritable(client, streamName, options) {
    assert(client, 'client is required');
    assert(streamName, 'streamName is required');

    options = options || {};
    options.objectMode = true;

    FlushWritable.call(this, options);

    this.client = client;
    this.streamName = streamName;
    this.logger = options.logger || null;
    this.highWaterMark = options.highWaterMark || 16;
    this.maxRetries = options.maxRetries || 3;

    // The maximum number of items that can be written to Kinesis in
    // one request is 500
    assert(this.highWaterMark <= 500, 'Max highWaterMark is 500');

    this.queue = [];
}

/* eslint-disable no-unused-vars */

/**
 * Get partition key for given record
 *
 * @param {Object} [record] Record
 * @return {string}
 */
KinesisWritable.prototype.getPartitionKey = function getPartitionKey(record) {
    return _.padLeft(_.random(0, 1000), 4, '0');
};

/* eslint-enable no-unused-vars */

/**
 * Transform record into one accepted by Kinesis
 *
 * @private
 * @param {Object} record
 * @return {Object}
 */
KinesisWritable.prototype.transformRecord = function transformRecord(record) {
    return {
        Data: JSON.stringify(record),
        PartitionKey: this.getPartitionKey()
    };
};

/**
 * Write records in queue to Kinesis
 *
 * @private
 * @param {Function} callback
 */
KinesisWritable.prototype.writeRecords = function writeRecords(callback) {
    if (this.logger) {
        this.logger.debug('Writing %d records to Kinesis', this.queue.length);
    }

    var records = this.queue.map(this.transformRecord.bind(this));

    this.client.putRecords({
        Records: records,
        StreamName: this.streamName
    }, function(err, response) {
        if (err) {
            return callback(err);
        }

        if (this.logger) {
            this.logger.info('Wrote %d records to Kinesis',
                records.length - response.FailedRecordCount);
        }

        if (response.FailedRecordCount !== 0) {
            if (this.logger) {
                this.logger.warning('Failed writing %d records to Kinesis',
                    response.FailedRecordCount);
            }

            var failedRecords = [];

            response.Records.forEach(function(record, index) {
                if (record.ErrorCode) {
                    if (this.logger) {
                        this.logger.warning('Failed record with message: %s', record.ErrorMessage);
                    }

                    failedRecords.push(this.queue[index]);
                }
            }.bind(this));

            this.queue = failedRecords;

            return callback(new Error('Failed to write ' + failedRecords.length + ' records'));
        }

        this.queue = [];

        callback();
    }.bind(this));
};

/**
 * Flush method needed by the underlying stream implementation
 *
 * @private
 * @param {Function} callback
 * @return {undefined}
 */
KinesisWritable.prototype._flush = function _flush(callback) {
    if (this.queue.length === 0) {
        return callback();
    }

    var retry = retryFn.bind(null, {
        retries: this.maxRetries,
        timeout: retryFn.fib(this.retryTimeout)
    });

    retry(this.writeRecords.bind(this), callback);
};

/**
 * Write method needed by the underlying stream implementation
 *
 * @private
 * @param {Object} record
 * @param {string} enc
 * @param {Function} callback
 * @returns {undefined}
 */
KinesisWritable.prototype._write = function _write(record, enc, callback) {
    if (this.logger) {
        this.logger.debug('Adding to Kinesis queue', { record: record });
    }

    this.queue.push(record);

    if (this.queue.length >= this.highWaterMark) {
        return this._flush(callback);
    }

    callback();
};

module.exports = KinesisWritable;
<commit_msg>Call warn instead of warning method on logger<commit_after>'use strict';

var util = require('util'),
    assert = require('assert'),
    retryFn = require('retry-fn'),
    FlushWritable = require('flushwritable'),
    _ = require('lodash');

util.inherits(KinesisWritable, FlushWritable);

/**
 * A simple stream wrapper around Kinesis putRecords
 *
 * @param {AWS.Kinesis} client AWS Kinesis client
 * @param {string} streamName Kinesis stream name
 * @param {Object} options Options
 * @param {number} [options.highWaterMark=16] Number of items to buffer before writing.
 * Also the size of the underlying stream buffer.
 * @param {Number} [options.maxRetries=3] How many times to retry failed data before
 * rasing an error
 * @param {Number} [options.retryTimeout=100] How long to wait initially before
 * retrying failed records
 * @param {Object} [options.logger] Instance of a logger like bunyan or winston
 */
function KinesisWritable(client, streamName, options) {
    assert(client, 'client is required');
    assert(streamName, 'streamName is required');

    options = options || {};
    options.objectMode = true;

    FlushWritable.call(this, options);

    this.client = client;
    this.streamName = streamName;
    this.logger = options.logger || null;
    this.highWaterMark = options.highWaterMark || 16;
    this.maxRetries = options.maxRetries || 3;

    // The maximum number of items that can be written to Kinesis in
    // one request is 500
    assert(this.highWaterMark <= 500, 'Max highWaterMark is 500');

    this.queue = [];
}

/* eslint-disable no-unused-vars */

/**
 * Get partition key for given record
 *
 * @param {Object} [record] Record
 * @return {string}
 */
KinesisWritable.prototype.getPartitionKey = function getPartitionKey(record) {
    return _.padLeft(_.random(0, 1000), 4, '0');
};

/* eslint-enable no-unused-vars */

/**
 * Transform record into one accepted by Kinesis
 *
 * @private
 * @param {Object} record
 * @return {Object}
 */
KinesisWritable.prototype.transformRecord = function transformRecord(record) {
    return {
        Data: JSON.stringify(record),
        PartitionKey: this.getPartitionKey()
    };
};

/**
 * Write records in queue to Kinesis
 *
 * @private
 * @param {Function} callback
 */
KinesisWritable.prototype.writeRecords = function writeRecords(callback) {
    if (this.logger) {
        this.logger.debug('Writing %d records to Kinesis', this.queue.length);
    }

    var records = this.queue.map(this.transformRecord.bind(this));

    this.client.putRecords({
        Records: records,
        StreamName: this.streamName
    }, function(err, response) {
        if (err) {
            return callback(err);
        }

        if (this.logger) {
            this.logger.info('Wrote %d records to Kinesis',
                records.length - response.FailedRecordCount);
        }

        if (response.FailedRecordCount !== 0) {
            if (this.logger) {
                this.logger.warn('Failed writing %d records to Kinesis',
                    response.FailedRecordCount);
            }

            var failedRecords = [];

            response.Records.forEach(function(record, index) {
                if (record.ErrorCode) {
                    if (this.logger) {
                        this.logger.warn('Failed record with message: %s', record.ErrorMessage);
                    }

                    failedRecords.push(this.queue[index]);
                }
            }.bind(this));

            this.queue = failedRecords;

            return callback(new Error('Failed to write ' + failedRecords.length + ' records'));
        }

        this.queue = [];

        callback();
    }.bind(this));
};

/**
 * Flush method needed by the underlying stream implementation
 *
 * @private
 * @param {Function} callback
 * @return {undefined}
 */
KinesisWritable.prototype._flush = function _flush(callback) {
    if (this.queue.length === 0) {
        return callback();
    }

    var retry = retryFn.bind(null, {
        retries: this.maxRetries,
        timeout: retryFn.fib(this.retryTimeout)
    });

    retry(this.writeRecords.bind(this), callback);
};

/**
 * Write method needed by the underlying stream implementation
 *
 * @private
 * @param {Object} record
 * @param {string} enc
 * @param {Function} callback
 * @returns {undefined}
 */
KinesisWritable.prototype._write = function _write(record, enc, callback) {
    if (this.logger) {
        this.logger.debug('Adding to Kinesis queue', { record: record });
    }

    this.queue.push(record);

    if (this.queue.length >= this.highWaterMark) {
        return this._flush(callback);
    }

    callback();
};

module.exports = KinesisWritable;
<|endoftext|>


<commit_before>'use strict';

var tty = require('tty');
var util = require('util');
var WritableStream = require('stream').Writable;

var auto = 'auto';
var never = 'never';
var always = 'always';

var COLOR_OPTION = '--color';
var NO_COLOR_OPTION = '--no-color';
var OPTION = {always: COLOR_OPTION, never: NO_COLOR_OPTION};

var cache = {}, stash = {
  log: console.log,
  info: console.info,
  error: console.error,
  warn: console.warn
}

var styles = {
  log: {format: ['normal'], parameters: ['normal', 'bright']},
  info: {format: ['cyan'], parameters: ['cyan', 'bright']},
  warn: {format: ['magenta'], parameters: ['magenta', 'bright']},
  error: {format: ['red'], parameters: ['red', 'bright']}
}

var definition = {
  colors: {
    normal          : 39,
    white           : 37,
    black           : 30,
    blue            : 34,
    cyan            : 36,
    green           : 32,
    yellow          : 33,
    magenta         : 35,
    red             : 31
  },
  bg: {
    colors: {
      normal        : 49,
      white         : 47,
      black         : 40,
      blue          : 44,
      cyan          : 46,
      green         : 42,
      yellow        : 43,
      magenta       : 45,
      red           : 41
    }
  },
  attrs: {
    bright          : 1,
    dim             : 2,
    italic          : 3,
    underline       : 4,
    blink           : 5,
    reverse         : 7
  }
}

var ANSI_OPEN = '\u001b[';
var ANSI_FINAL = 'm';
var ANSI_CLOSE_CODE = '0';
var ANSI_CLOSE = ANSI_OPEN + ANSI_CLOSE_CODE + ANSI_FINAL;

/**
 *  Open an escape sequence.
 *
 *  @param code The color code.
 *  @param attr An optional attribute code.
 */
function open(code, attr) {
  return  attr ? ANSI_OPEN + attr + ';' + code + ANSI_FINAL
    : ANSI_OPEN + code + ANSI_FINAL;
}

/**
 *  Concatenate a close sequence.
 *
 *  @param value The value to close.
 */
function close(value, tag) {
  return value + (tag ? tag : ANSI_CLOSE);
}

/**
 *  Low-level method for creating escaped string sequences.
 *
 *  @param value The value to escape.
 *  @param code The color code.
 *  @param attr An optional attribute code.
 *  @param tag A specific closing tag to use.
 */
function stringify(value, code, attr, tag) {
  var s = open(code, attr);
  s +=  close(value, tag);
  return s;
}

/**
 *  Escapes replacement values.
 *
 *  @param options.tty A boolean indicating whether the output is a tty.
 *  @param options.method A method to proxy to.
 *  @param options.stream A writable stream to write to.
 *
 *  @param options Write options.
 *  @param format The format string.
 *  @param ... The format string arguments.
 */
function proxy(options, format) {
  var tty = options.tty, method = options.method, re = /(%[sdj])+/g;
  if(arguments.length == 1) return method.apply(console, []);
  var arg, i, replacing, replacements, matches, tag;
  replacing = (typeof format == 'string')
    && re.test(format) && arguments.length > 2;
  replacements = [].slice.call(arguments, 2);
  if(format instanceof AnsiColor) {
    replacing = true;
    if(!replacements.length) {
      replacements.unshift(format); format = '%s';
    }
  }
  if(!replacing) {
    replacements.unshift(format);
    return method.apply(console, replacements);
  }
  matches = (format && (typeof format.match == 'function')) ?
    format.match(re) : [];
  if(format instanceof AnsiColor) {
    if(!tty) {
      format = format.v;
    }else{
      tag = format.start(tty);
      format = format.valueOf(tty);
    }
  }
  for(i = 0;i < replacements.length;i++) {
    arg = replacements[i];
    if(arg instanceof AnsiColor) {
      if(tty) {
        // we will coerce to strings
        format = format.replace(/%[jds]/, '%s');
        if(matches[i] == '%j') {
          arg.v = JSON.stringify(arg.v);
        }
      }
      replacements[i] = arg.valueOf(tty, tag);
    }
  }
  replacements.unshift(format);
  return method.apply(options.scope ? options.scope : console, replacements);
}

/**
 *  Chainable color builder.
 *
 *  @param value The underlying value to be escaped.
 *  @param key The key for the code lookup.
 *  @param parent A parent color instance.
 */
var AnsiColor = function(value, key, parent){
  this.t = definition.colors;
  this.v = value;
  this.k = key;
  this.p = parent;
  this.a = null;
}

/**
 *  Retrieve list of parent instances.
 */
AnsiColor.prototype.parents = function() {
  var list = [this], p = this.p;
  while(p) {
    if(p) {
      list.push(p);
    }
    p = p.p;
  }
  list.reverse();
  return list;
}

/**
 *  Retrieve a start escape sequence.
 *
 *  @param tty Whether the output stream is a terminal.
 */
AnsiColor.prototype.start = function(tty) {
  if(!tty) return '';
  var list = this.parents(), i, p;
  var o = ANSI_CLOSE;
  for(i = 0;i < list.length;i++){
    p = list[i];
    if(!p.k) continue;
    o += open(p.t[p.k], p.a);
  }
  return o;
}

/**
 *  Retrieve an escape sequence from the chain.
 *
 *  @param tty Whether the output stream is a terminal.
 *  @param tag A specific closing tag to use.
 */
AnsiColor.prototype.valueOf = function(tty, tag) {
  if(!tty) return this.v;
  var list = this.parents(), i, p;
  for(i = 0;i < list.length;i++){
    p = list[i];
    if(!p.k) continue;
    this.v = stringify(this.v, p.t[p.k], p.a, tag);
  }
  return this.v;
}

AnsiColor.prototype.__defineGetter__('bg', function() {
  var ansi = new AnsiColor(this.v, this.k, this);
  ansi.t = definition.bg.colors;
  return ansi;
});

// attributes
Object.keys(definition.attrs).forEach(function (k) {
  AnsiColor.prototype.__defineGetter__(k, function () {
    if(this.a) {
      var ansi = new AnsiColor(this.v, this.k || 'normal', this);
      ansi.a = definition.attrs[k];
      return ansi;
    }
    this.a = definition.attrs[k];
    this.k = this.k || 'normal';
    return this;
  });
});

// colors
Object.keys(definition.colors).forEach(function (k) {
  AnsiColor.prototype.__defineGetter__(k, function () {
    // reset the background color chain after color method invocation
    // allows invoking foreground colors after background colors
    if(this.k && this.t == definition.bg.colors && this.p && !this.p.k) {
      return new AnsiColor(this.v, k, this);
    }
    this.k = k;
    // allow color functions after multiple attribute chains
    if(this.p && this.p.a && this.p.k == 'normal') {
      this.p.k = this.k;
    }
    return this;
  });
});

function isatty(tty, mode) {
  if(mode == always) return true;
  if(mode == never) return false;
  return tty;
}

function initialize(mode) {
  /**
   *  Write a writable stream.
   *
   *  @param options.stream A writable stream.
   *  @param options.callback A callback to invoke once the data is written.
   *  @param format The format string.
   *  @param ...  The format string arguments.
   */
  console.write = function(options) {
    var stream = options.stream;
    if(stream instanceof WritableStream) {
      if(stream.fd == null) {
        throw new Error('Cannot write to stream, file descriptor not open');
      }
      var args = [
        {
          scope: util, method: util.format,
          tty: isatty(tty.isatty(stream.fd), mode)
        }
      ];
      args = args.concat([].slice.call(arguments, 1));
      var value = proxy.apply(null, args);
      stream.write(value, function() {
        if(typeof options.callback == 'function') options.callback(value);
      });
    }else{
      throw new Error('Stream option must be writable');
    }
  }

  // console functions
  Object.keys(stash).forEach(function (k) {
    var stream = (k == 'info' || k == 'log') ?
      process.stdout : process.stderr;
    console[k] = function(format) {
      var tty = isatty(stream.isTTY, mode);
      var args = [{tty: tty, method: stash[k]}];
      var rest = [].slice.call(arguments, 0);
      args = args.concat(rest);
      proxy.apply(null, args);
    }
  });
}

function ansi(v) {
  return new AnsiColor(v);
}

function defaults(custom) {
  var props = custom || styles;
  var keys = Object.keys(styles);
  function convert(arg, names) {
    var prop;
    names = Array.isArray(names) ? names : [];
    names = names.slice(0);
    if(!(arg instanceof AnsiColor) && names.length) {
      arg = ansi(arg);
      while(prop = names.shift()) {
        arg = arg[prop];
      }
    }
    return arg;
  }
  keys.forEach(function(name) {
    cache[name] = console[name];
    console[name] = function() {
      var format = arguments[0];
      format = convert(format, props[name].format);
      var args = [].slice.call(arguments, 1), i;
      for(i = 0;i < args.length;i++) {
        args[i] = convert(args[i], props[name].parameters);
      }
      args.unshift(format);
      return cache[name].apply(null, args);
    }
  });
  function revert() {
    keys.forEach(function(name) {
      console[name] = cache[name];
    });
  }
  return revert;
}

function debug() {
  var args = [{scope: util, method: util.format, tty: true}];
  args = args.concat([].slice.call(arguments, 0));
  return proxy.apply(null, args);
}

function parse(option, argv) {
  option = option || {};
  argv = argv || process.argv.slice(2);
  option.always = option.always || COLOR_OPTION;
  option.never = option.never || NO_COLOR_OPTION;
  var i, arg;
  // default *auto* with no arguments
  if(!argv.length) {
    return auto;
  }else{
    for(i = 0;i < argv.length;i++) {
      arg = argv[i];
      if(arg == option.always) {
        return always;
      }else if(arg == option.never) {
        return never;
      }
    }
  }
  return auto;
}

module.exports = function(parser, option) {
  option = option || OPTION;
  parser = parser !== false ? (parser || parse) : false;
  var mode = auto;
  if(typeof parser == 'function') {
    mode = parser(option);
  }
  initialize(mode);
  return module.exports;
}

module.exports.console = stash;
module.exports.cache = cache;
module.exports.ansi = ansi;
module.exports.colors = Object.keys(definition.colors);
module.exports.attributes = definition.attrs;
module.exports.foreground = definition.colors;
module.exports.background = definition.bg.colors;
module.exports.stringify = stringify;
module.exports.debug = debug;
module.exports.defaults = defaults;
module.exports.styles = styles;
<commit_msg>Allow arguments with an = delimiter.<commit_after>'use strict';

var tty = require('tty');
var util = require('util');
var WritableStream = require('stream').Writable;

var auto = 'auto';
var never = 'never';
var always = 'always';
var modes = [auto, always, never];

var COLOR_OPTION = '--color';
var NO_COLOR_OPTION = '--no-color';
var OPTION = {always: COLOR_OPTION, never: NO_COLOR_OPTION};

var cache = {}, stash = {
  log: console.log,
  info: console.info,
  error: console.error,
  warn: console.warn
}

var styles = {
  log: {format: ['normal'], parameters: ['normal', 'bright']},
  info: {format: ['cyan'], parameters: ['cyan', 'bright']},
  warn: {format: ['magenta'], parameters: ['magenta', 'bright']},
  error: {format: ['red'], parameters: ['red', 'bright']}
}

var definition = {
  colors: {
    normal          : 39,
    white           : 37,
    black           : 30,
    blue            : 34,
    cyan            : 36,
    green           : 32,
    yellow          : 33,
    magenta         : 35,
    red             : 31
  },
  bg: {
    colors: {
      normal        : 49,
      white         : 47,
      black         : 40,
      blue          : 44,
      cyan          : 46,
      green         : 42,
      yellow        : 43,
      magenta       : 45,
      red           : 41
    }
  },
  attrs: {
    bright          : 1,
    dim             : 2,
    italic          : 3,
    underline       : 4,
    blink           : 5,
    reverse         : 7
  }
}

var ANSI_OPEN = '\u001b[';
var ANSI_FINAL = 'm';
var ANSI_CLOSE_CODE = '0';
var ANSI_CLOSE = ANSI_OPEN + ANSI_CLOSE_CODE + ANSI_FINAL;

/**
 *  Open an escape sequence.
 *
 *  @param code The color code.
 *  @param attr An optional attribute code.
 */
function open(code, attr) {
  return  attr ? ANSI_OPEN + attr + ';' + code + ANSI_FINAL
    : ANSI_OPEN + code + ANSI_FINAL;
}

/**
 *  Concatenate a close sequence.
 *
 *  @param value The value to close.
 */
function close(value, tag) {
  return value + (tag ? tag : ANSI_CLOSE);
}

/**
 *  Low-level method for creating escaped string sequences.
 *
 *  @param value The value to escape.
 *  @param code The color code.
 *  @param attr An optional attribute code.
 *  @param tag A specific closing tag to use.
 */
function stringify(value, code, attr, tag) {
  var s = open(code, attr);
  s +=  close(value, tag);
  return s;
}

/**
 *  Escapes replacement values.
 *
 *  @param options.tty A boolean indicating whether the output is a tty.
 *  @param options.method A method to proxy to.
 *  @param options.stream A writable stream to write to.
 *
 *  @param options Write options.
 *  @param format The format string.
 *  @param ... The format string arguments.
 */
function proxy(options, format) {
  var tty = options.tty, method = options.method, re = /(%[sdj])+/g;
  if(arguments.length == 1) return method.apply(console, []);
  var arg, i, replacing, replacements, matches, tag;
  replacing = (typeof format == 'string')
    && re.test(format) && arguments.length > 2;
  replacements = [].slice.call(arguments, 2);
  if(format instanceof AnsiColor) {
    replacing = true;
    if(!replacements.length) {
      replacements.unshift(format); format = '%s';
    }
  }
  if(!replacing) {
    replacements.unshift(format);
    return method.apply(console, replacements);
  }
  matches = (format && (typeof format.match == 'function')) ?
    format.match(re) : [];
  if(format instanceof AnsiColor) {
    if(!tty) {
      format = format.v;
    }else{
      tag = format.start(tty);
      format = format.valueOf(tty);
    }
  }
  for(i = 0;i < replacements.length;i++) {
    arg = replacements[i];
    if(arg instanceof AnsiColor) {
      if(tty) {
        // we will coerce to strings
        format = format.replace(/%[jds]/, '%s');
        if(matches[i] == '%j') {
          arg.v = JSON.stringify(arg.v);
        }
      }
      replacements[i] = arg.valueOf(tty, tag);
    }
  }
  replacements.unshift(format);
  return method.apply(options.scope ? options.scope : console, replacements);
}

/**
 *  Chainable color builder.
 *
 *  @param value The underlying value to be escaped.
 *  @param key The key for the code lookup.
 *  @param parent A parent color instance.
 */
var AnsiColor = function(value, key, parent){
  this.t = definition.colors;
  this.v = value;
  this.k = key;
  this.p = parent;
  this.a = null;
}

/**
 *  Retrieve list of parent instances.
 */
AnsiColor.prototype.parents = function() {
  var list = [this], p = this.p;
  while(p) {
    if(p) {
      list.push(p);
    }
    p = p.p;
  }
  list.reverse();
  return list;
}

/**
 *  Retrieve a start escape sequence.
 *
 *  @param tty Whether the output stream is a terminal.
 */
AnsiColor.prototype.start = function(tty) {
  if(!tty) return '';
  var list = this.parents(), i, p;
  var o = ANSI_CLOSE;
  for(i = 0;i < list.length;i++){
    p = list[i];
    if(!p.k) continue;
    o += open(p.t[p.k], p.a);
  }
  return o;
}

/**
 *  Retrieve an escape sequence from the chain.
 *
 *  @param tty Whether the output stream is a terminal.
 *  @param tag A specific closing tag to use.
 */
AnsiColor.prototype.valueOf = function(tty, tag) {
  if(!tty) return this.v;
  var list = this.parents(), i, p;
  for(i = 0;i < list.length;i++){
    p = list[i];
    if(!p.k) continue;
    this.v = stringify(this.v, p.t[p.k], p.a, tag);
  }
  return this.v;
}

AnsiColor.prototype.__defineGetter__('bg', function() {
  var ansi = new AnsiColor(this.v, this.k, this);
  ansi.t = definition.bg.colors;
  return ansi;
});

// attributes
Object.keys(definition.attrs).forEach(function (k) {
  AnsiColor.prototype.__defineGetter__(k, function () {
    if(this.a) {
      var ansi = new AnsiColor(this.v, this.k || 'normal', this);
      ansi.a = definition.attrs[k];
      return ansi;
    }
    this.a = definition.attrs[k];
    this.k = this.k || 'normal';
    return this;
  });
});

// colors
Object.keys(definition.colors).forEach(function (k) {
  AnsiColor.prototype.__defineGetter__(k, function () {
    // reset the background color chain after color method invocation
    // allows invoking foreground colors after background colors
    if(this.k && this.t == definition.bg.colors && this.p && !this.p.k) {
      return new AnsiColor(this.v, k, this);
    }
    this.k = k;
    // allow color functions after multiple attribute chains
    if(this.p && this.p.a && this.p.k == 'normal') {
      this.p.k = this.k;
    }
    return this;
  });
});

function isatty(tty, mode) {
  if(mode == always) return true;
  if(mode == never) return false;
  return tty;
}

function initialize(mode) {
  /**
   *  Write a writable stream.
   *
   *  @param options.stream A writable stream.
   *  @param options.callback A callback to invoke once the data is written.
   *  @param format The format string.
   *  @param ...  The format string arguments.
   */
  console.write = function(options) {
    var stream = options.stream;
    if(stream instanceof WritableStream) {
      if(stream.fd == null) {
        throw new Error('Cannot write to stream, file descriptor not open');
      }
      var args = [
        {
          scope: util, method: util.format,
          tty: isatty(tty.isatty(stream.fd), mode)
        }
      ];
      args = args.concat([].slice.call(arguments, 1));
      var value = proxy.apply(null, args);
      stream.write(value, function() {
        if(typeof options.callback == 'function') options.callback(value);
      });
    }else{
      throw new Error('Stream option must be writable');
    }
  }

  // console functions
  Object.keys(stash).forEach(function (k) {
    var stream = (k == 'info' || k == 'log') ?
      process.stdout : process.stderr;
    console[k] = function(format) {
      var tty = isatty(stream.isTTY, mode);
      var args = [{tty: tty, method: stash[k]}];
      var rest = [].slice.call(arguments, 0);
      args = args.concat(rest);
      proxy.apply(null, args);
    }
  });
}

function ansi(v) {
  return new AnsiColor(v);
}

function defaults(custom) {
  var props = custom || styles;
  var keys = Object.keys(styles);
  function convert(arg, names) {
    var prop;
    names = Array.isArray(names) ? names : [];
    names = names.slice(0);
    if(!(arg instanceof AnsiColor) && names.length) {
      arg = ansi(arg);
      while(prop = names.shift()) {
        arg = arg[prop];
      }
    }
    return arg;
  }
  keys.forEach(function(name) {
    cache[name] = console[name];
    console[name] = function() {
      var format = arguments[0];
      format = convert(format, props[name].format);
      var args = [].slice.call(arguments, 1), i;
      for(i = 0;i < args.length;i++) {
        args[i] = convert(args[i], props[name].parameters);
      }
      args.unshift(format);
      return cache[name].apply(null, args);
    }
  });
  function revert() {
    keys.forEach(function(name) {
      console[name] = cache[name];
    });
  }
  return revert;
}

function debug() {
  var args = [{scope: util, method: util.format, tty: true}];
  args = args.concat([].slice.call(arguments, 0));
  return proxy.apply(null, args);
}

function parse(option, argv) {
  option = option || {};
  argv = argv || process.argv.slice(2);
  option.always = option.always || COLOR_OPTION;
  option.never = option.never;
  var i, arg, equals, value;
  // default *auto* with no arguments
  if(!argv.length) {
    return auto;
  }else{
    for(i = 0;i < argv.length;i++) {
      arg = argv[i];
      if(arg.indexOf(option.always) == 0) {
        value = argv[i + 1], equals = arg.indexOf('=');
        if(equals > -1) value = arg.substr(equals + 1);
        if(value && (modes.indexOf(value) > -1)) {
          return value;
        }
        if(arg == option.always) return always;
      }else if(option.never && arg == option.never) {
        return never;
      }
    }
  }
  return auto;
}

module.exports = function(parser, option) {
  option = option || OPTION;
  parser = parser !== false ? (parser || parse) : false;
  var mode = auto;
  if(typeof parser == 'function') {
    mode = parser(option);
  }
  initialize(mode);
  return module.exports;
}

module.exports.console = stash;
module.exports.cache = cache;
module.exports.ansi = ansi;
module.exports.colors = Object.keys(definition.colors);
module.exports.attributes = definition.attrs;
module.exports.foreground = definition.colors;
module.exports.background = definition.bg.colors;
module.exports.stringify = stringify;
module.exports.debug = debug;
module.exports.defaults = defaults;
module.exports.styles = styles;
<|endoftext|>