<commit_before>#!/usr/bin/env node

'use strict';

var request = require('request');
var Promise = require('bluebird');
var express = require('express');
var level = require('level');
var through = require('through2');
var logger = require('./logger');
var levels = require('./levels');
var crypto = require('crypto');
module.exports = function (FAT_REMOTE, SKIM_REMOTE, port, pouchPort, urlBase, loglevel) {
  FAT_REMOTE = FAT_REMOTE || 'https://registry.npmjs.org';
  SKIM_REMOTE =  SKIM_REMOTE || 'https://skimdb.npmjs.com/registry';
  loglevel = levels(loglevel);
  var startingTimeout = 1000;
  logger.silly('\nWelcome!');
  logger.info('To start using local-npm, just run: ');
  logger.code('\n  $ npm set registry http://127.0.0.1:' + port);
  logger.info('\nTo switch back, you can run: ');
  logger.code('\n  $ npm set registry ' + FAT_REMOTE);
  logger.info('\nA simple npm-like UI is available here: http://127.0.0.1:' + port + '/_browse');

  var backoff = 1.1;
  var app = express();
  var PouchDB = require('./pouchdb-server-lite').PouchDB;
  var skimRemote = new PouchDB(SKIM_REMOTE);
  var skimLocal = new PouchDB('skimdb');
  var db = level('./binarydb');
  var base = urlBase + '/tarballs';

  if (loglevel > 1) {
    app.use(require('morgan')('dev'));
  }
  app.use(require('compression')());
  app.use(require('serve-favicon')(__dirname + '/favicon.ico'));

  //
  // rudimentary UI based on npm-browser
  //
  app.use('/_browse', express.static(__dirname + '/www'));
  function redirectToSkimdb(req, res) {
    var skimUrl = 'http://localhost:' + pouchPort + '/skimdb';
    var get = request.get(req.originalUrl.replace(/^\/_skimdb/, skimUrl));
    get.on('error', function (err) {
      console.error("couldn't proxy to skimdb");
      console.error(err);
    });
    get.pipe(res);
  }
  app.get('/_skimdb', redirectToSkimdb);
  app.get('/_skimdb*', redirectToSkimdb);

  //
  // actual server logic
  //
  app.get('/:name', function (req, res) {
    skimLocal.get(req.params.name).catch(function () {
      return skimRemote.get(req.params.name);
    }).then(function (doc) {
      var docs = changeTarballs(base, doc);
      res.json(docs);
    }).catch(function (e) {
      request.get(FAT_REMOTE + req.url).pipe(res);
    });
  });
  app.get('/:name/:version', function (req, res) {
    skimLocal.get(req.params.name).catch(function () {
      return skimRemote.get(req.params.name);
    }).then(function (doc) {
      res.json(changeTarballs(base, doc).versions[req.params.version]);
    }).catch(function (e) {
      request.get(FAT_REMOTE + req.url).pipe(res);
    });
  });
  app.get('/tarballs/:name/:version.tgz', function (req, res) {
    skimLocal.get(req.params.name).catch(function () {
      return skimRemote.get(req.params.name);
    }).catch(function (err) {
      res.send(500, "you are offline and skimdb isn\'t replicated yet");
      throw new Error('offline');
    }).then(function (doc) {
      var id = req.params.name + '-' + req.params.version;
      var dist = doc.versions[req.params.version].dist;
      db.get(id, {asBuffer: true, valueEncoding: 'binary'}, function (err, resp) {
        if (!err) {
          var hash = crypto.createHash('sha1');
          hash.update(resp);
          if (dist.shasum !== hash.digest('hex')) {
            // happens when we write garbage to disk somehow
            logger.warn('hashes don\'t match, not returning');
          } else {
            logger.hit(req.params.name, req.params.version);
            res.set('content-type', 'application/octet-stream');
            res.set('content-length', resp.length);
            return res.send(resp);
          }
        }
        logger.miss(req.params.name, req.params.version);
        var buffs = [];

        var get = request.get(dist.tarball);
        get.on('error', function (err) {
          logger.info(err);
          res.send(500, 'you are offline and this package isn\'t cached');
        });
        get.pipe(res);
        get.pipe(through(function (chunk, _, next) {
          buffs.push(chunk);
          next();
        }, function (next) {
          next();
          var buff = Buffer.concat(buffs);
          db.put(id, buff, function (err) {
            logger.cached(req.params.name, req.params.version);
            if (err) {
              logger.info(err);
            }
          });
        }));
      });
    }).catch(function (err) {
      logger.info(err);
    });
  });
  function changeTarballs(base, doc) {
    Object.keys(doc.versions).forEach(function (key) {
      doc.versions[key].dist.tarball = base + '/' + doc.name + '/' + key + '.tgz';
    });
    return doc;
  }
  app.all('/*', function (req, res) {
    res.send(500);
  });
  var sync;
  function replicateSkim() {
    skimRemote.info().then(function (info) {
      sync = skimLocal.replicate.from(skimRemote, {
        live: true,
        batch_size: 2000
      }).on('change', function (change) {
        var percent = Math.min(100,
          (Math.floor(change.last_seq / info.update_seq * 10000) / 100).toFixed(2));
        logger.status(change.last_seq, percent);
      }).on('uptodate', function () {
        logger.verbose('local skimdb is up to date');
      }).on('error', function (err) {
        logger.warn('error during replication with skimdb');
        logger.error(err);
        restartReplication();
      });
    }).catch(function (err) {
      logger.warn('error doing logger.info() on ' + SKIM_REMOTE);
      logger.error(err);
      restartReplication();
    });
  }
  function restartReplication() {
    // just keep going
    startingTimeout *= backoff;
    setTimeout(replicateSkim, Math.round(startingTimeout));
  }
  replicateSkim();

  app.listen(port);

  process.on('SIGINT', function () {
    // close gracefully
    sync.cancel();
    db.close(function () {
      skimLocal.close().then(function () {
        process.exit();
      }, function () {
        process.exit();
      });
    });
  });
};
<commit_msg>lower default batch size<commit_after>#!/usr/bin/env node

'use strict';

var request = require('request');
var Promise = require('bluebird');
var express = require('express');
var level = require('level');
var through = require('through2');
var logger = require('./logger');
var levels = require('./levels');
var crypto = require('crypto');
module.exports = function (FAT_REMOTE, SKIM_REMOTE, port, pouchPort, urlBase, loglevel) {
  FAT_REMOTE = FAT_REMOTE || 'https://registry.npmjs.org';
  SKIM_REMOTE =  SKIM_REMOTE || 'https://skimdb.npmjs.com/registry';
  loglevel = levels(loglevel);
  var startingTimeout = 1000;
  logger.silly('\nWelcome!');
  logger.info('To start using local-npm, just run: ');
  logger.code('\n  $ npm set registry http://127.0.0.1:' + port);
  logger.info('\nTo switch back, you can run: ');
  logger.code('\n  $ npm set registry ' + FAT_REMOTE);
  logger.info('\nA simple npm-like UI is available here: http://127.0.0.1:' + port + '/_browse');

  var backoff = 1.1;
  var app = express();
  var PouchDB = require('./pouchdb-server-lite').PouchDB;
  var skimRemote = new PouchDB(SKIM_REMOTE);
  var skimLocal = new PouchDB('skimdb');
  var db = level('./binarydb');
  var base = urlBase + '/tarballs';

  if (loglevel > 1) {
    app.use(require('morgan')('dev'));
  }
  app.use(require('compression')());
  app.use(require('serve-favicon')(__dirname + '/favicon.ico'));

  //
  // rudimentary UI based on npm-browser
  //
  app.use('/_browse', express.static(__dirname + '/www'));
  function redirectToSkimdb(req, res) {
    var skimUrl = 'http://localhost:' + pouchPort + '/skimdb';
    var get = request.get(req.originalUrl.replace(/^\/_skimdb/, skimUrl));
    get.on('error', function (err) {
      console.error("couldn't proxy to skimdb");
      console.error(err);
    });
    get.pipe(res);
  }
  app.get('/_skimdb', redirectToSkimdb);
  app.get('/_skimdb*', redirectToSkimdb);

  //
  // actual server logic
  //
  app.get('/:name', function (req, res) {
    skimLocal.get(req.params.name).catch(function () {
      return skimRemote.get(req.params.name);
    }).then(function (doc) {
      var docs = changeTarballs(base, doc);
      res.json(docs);
    }).catch(function (e) {
      request.get(FAT_REMOTE + req.url).pipe(res);
    });
  });
  app.get('/:name/:version', function (req, res) {
    skimLocal.get(req.params.name).catch(function () {
      return skimRemote.get(req.params.name);
    }).then(function (doc) {
      res.json(changeTarballs(base, doc).versions[req.params.version]);
    }).catch(function (e) {
      request.get(FAT_REMOTE + req.url).pipe(res);
    });
  });
  app.get('/tarballs/:name/:version.tgz', function (req, res) {
    skimLocal.get(req.params.name).catch(function () {
      return skimRemote.get(req.params.name);
    }).catch(function (err) {
      res.send(500, "you are offline and skimdb isn\'t replicated yet");
      throw new Error('offline');
    }).then(function (doc) {
      var id = req.params.name + '-' + req.params.version;
      var dist = doc.versions[req.params.version].dist;
      db.get(id, {asBuffer: true, valueEncoding: 'binary'}, function (err, resp) {
        if (!err) {
          var hash = crypto.createHash('sha1');
          hash.update(resp);
          if (dist.shasum !== hash.digest('hex')) {
            // happens when we write garbage to disk somehow
            logger.warn('hashes don\'t match, not returning');
          } else {
            logger.hit(req.params.name, req.params.version);
            res.set('content-type', 'application/octet-stream');
            res.set('content-length', resp.length);
            return res.send(resp);
          }
        }
        logger.miss(req.params.name, req.params.version);
        var buffs = [];

        var get = request.get(dist.tarball);
        get.on('error', function (err) {
          logger.info(err);
          res.send(500, 'you are offline and this package isn\'t cached');
        });
        get.pipe(res);
        get.pipe(through(function (chunk, _, next) {
          buffs.push(chunk);
          next();
        }, function (next) {
          next();
          var buff = Buffer.concat(buffs);
          db.put(id, buff, function (err) {
            logger.cached(req.params.name, req.params.version);
            if (err) {
              logger.info(err);
            }
          });
        }));
      });
    }).catch(function (err) {
      logger.info(err);
    });
  });
  function changeTarballs(base, doc) {
    Object.keys(doc.versions).forEach(function (key) {
      doc.versions[key].dist.tarball = base + '/' + doc.name + '/' + key + '.tgz';
    });
    return doc;
  }
  app.all('/*', function (req, res) {
    res.send(500);
  });
  var sync;
  function replicateSkim() {
    skimRemote.info().then(function (info) {
      sync = skimLocal.replicate.from(skimRemote, {
        live: true,
        batch_size: 200
      }).on('change', function (change) {
        var percent = Math.min(100,
          (Math.floor(change.last_seq / info.update_seq * 10000) / 100).toFixed(2));
        logger.status(change.last_seq, percent);
      }).on('uptodate', function () {
        logger.verbose('local skimdb is up to date');
      }).on('error', function (err) {
        logger.warn('error during replication with skimdb');
        logger.error(err);
        restartReplication();
      });
    }).catch(function (err) {
      logger.warn('error doing logger.info() on ' + SKIM_REMOTE);
      logger.error(err);
      restartReplication();
    });
  }
  function restartReplication() {
    // just keep going
    startingTimeout *= backoff;
    setTimeout(replicateSkim, Math.round(startingTimeout));
  }
  replicateSkim();

  app.listen(port);

  process.on('SIGINT', function () {
    // close gracefully
    sync.cancel();
    db.close(function () {
      skimLocal.close().then(function () {
        process.exit();
      }, function () {
        process.exit();
      });
    });
  });
};
<|endoftext|>


<commit_before>var fs = require('fs');
var http = require('http');
var https = require('https');
var keyfile = process.env.KEY_FILE;
var crtfile = process.env.CRT_FILE;

var privateKey = fs.readFileSync(keyfile, 'utf8');
var certificate = fs.readFileSync(crtfile, 'utf8');

var credentials = {key: privateKey, cert: certificate};

var express = require('express');
var app = express();

var port = 80;
var sllport = 443;

app.use('/assets', express.static(__dirname + '/public'));

app.get('/', function(req, res) {
	res.send('Moi EMMI!!!');
});

var httpServer = http.createServer(app);
var httpsServer = https.createServer(credentials, app);

httpServer.listen(port);
httpsServer.listen(443);
<commit_msg>Add condition for production environment.<commit_after>var fs = require('fs');
var http = require('http');
var https = require('https');

if(process.env.ENVIRONMENT === 'production') {
	var keyfile = process.env.KEY_FILE;
	var crtfile = process.env.CRT_FILE;

	var privateKey = fs.readFileSync(keyfile, 'utf8');
	var certificate = fs.readFileSync(crtfile, 'utf8');

	var credentials = {key: privateKey, cert: certificate};

};

var express = require('express');
var app = express();

var port = 80;
var sllport = 443;

app.use('/assets', express.static(__dirname + '/public'));

app.get('/', function(req, res) {
	res.send('Moi EMMI!!!');
});

var httpServer = http.createServer(app);
httpServer.listen(port);

if(process.env.ENVIRONMENT === 'production') {
	var httpsServer = https.createServer(credentials, app);
	httpsServer.listen(443);
};
<|endoftext|>


<commit_before>/**
 * Created by wangxin on 15/10/3.
 */

'use strict';

var fs = require('fs');
var PATH = require('path');
var iconv = require('iconv-lite');

var browserify = require('browserify');
var Imagemin = require('imagemin');

var distrbute = require('./lib/distrbute');
var trace = require('./lib/trace');
var outputHandle = require('./lib/output');
var listener = require('./lib/listener');
var util = require('./lib/util');

/*
 * @author wangxin
 * 获取执行任务的参数
 * file: 文件路径
 * return object;
 */
function getArgs(file) {
    var o = arguments[1] || {},
        type = arguments[2] || null,
        i = 0, len = file.length;

    if (len == 0) return o;
    for (; i < len; i++) {
        var path = PATH.resolve(file[i]);
        if (!type) {
            !o[path] && (o[path] = file[i]);
        } else if (type === 'remove') {
            delete o[path];
        }
    }
    return o;
}

/*
 * @author wangxin
 * 获取一个文件下所有文件路径
 * return arr ['dirPath','dirPath',...]
 */
function getLibraryMap(fileDir) {
    var files = fs.readdirSync(fileDir), arr = arguments[1] || [];
    files.forEach(function (fileName) {
        var baseDir = fileDir + fileName, lstat = fs.lstatSync(baseDir);
        if (lstat.isDirectory()) {
            getLibraryMap(baseDir + PATH.sep, arr);
        } else {
            var file = PATH.dirname(baseDir);
            arr.indexOf(file) === -1 && arr.push(PATH.normalize(file));
        }
    });
    return arr;
}

/*
 * @author wangxin
 * 进行browserify编译
 * content: 文件内容，string;
 * outputPath: 输出文件路径
 * return;
 */
function doBrowserify(basePath, libraryMap, config, index, cb) {
    var b = new browserify({
        entries: basePath,
        paths: libraryMap,
        debug: config.rjs.debug || false
    });
    b.bundle(function (err, code) {
        if (err) {
            trace.error(String(err));
        } else {
            //browserify编译完成，开始输出
            outputHandle(iconv.decode(code, 'utf8'), basePath, config, 'rjs');
            code = null;
        }
        cb && cb(index + 1);
    });
}

/*
 * @author wangxin
 * 处理加载模块文件内容为路径名
 * rjsMap: rjs文件map对象
 * libraryMap: 库文件map对象
 * return false;
 */
function walk(rjsMap, libraryMap, opt, cb) {

    var arr = [], go = function (i) {
        if (arr[i]) {
            doBrowserify(arr[i], libraryMap, opt, i, go);
        } else {
            cb && cb();
        }
        return false;
    };

    for (var i in rjsMap) {
        if (!i) {
            trace.error('file error');
            break;
        }
        if (rjsMap.hasOwnProperty(i))  arr.push(rjsMap[i]);
    }

    //开始编译
    return go(0);
}

/*
 * @author wangxin
 * 文件压缩==>js、css文件
 * opts: 输出路径：文件路径
 * retrun；
 */
function doMinify(map, opts, type) {
    for (var i in map) {
        var con = fs.readFileSync(map[i]), charset;
        //这里不建议用gbk编码格式
        if (iconv.decode(con, 'gbk').indexOf('�') != -1) {
            charset = 'utf8';
        } else {
            charset = 'gbk';
        }

        outputHandle(iconv.decode(con, charset), map[i], opts, type);
        con = null;
    }
}

/*
 * @author wangxin
 * 压缩图片
 * opts: 输出路径：文件路径
 * retrun；
 */
function imin(map, opts, cb) {
    var i, arr = [];
    for (i in map) arr.push(map[i]);

    function min(i) {
        new Imagemin().src(arr[i]).dest(PATH.normalize(opts.image.output.path)).run(function () {
            i += 1;
            arr[i] ? min(i) : (cb && cb());
        });
    }

    min(0);
}

/*
 * @author wangxin
 * 初始化方法
 * opts: 配置参数
 * 详情参考 ../test/test.js ==> config
 */
module.exports = function (config) {

    var opts = util.extendDeep(config);

    /**
     * 文件路径的初始化
     */
    var fileMap = distrbute(opts),
        rjsMap = fileMap.rjs,
        cssMap = fileMap.css,
        jsMap = fileMap.js,
        imageMap = fileMap.image,
        watchTask = function () {
            listener(opts, function (file, extname, type) {
                switch (extname) {
                    case 'rjs':
                        if (!type || type == 'remove') {
                            walk(getArgs(file, rjsMap, type), libraryMap, opts);
                        } else {
                            file = PATH.normalize(PATH.resolve(file));
                            if (type === 'resetLibA') {
                                libraryMap.indexOf(file) === -1 && libraryMap.push(file);
                            }
                            else if (type === 'resetLibD') {
                                libraryMap = util.removeEle.call(libraryMap, file);
                            }
                        }
                        break;
                    case 'css':
                        doMinify(getArgs(file, cssMap, type), opts, 'css');
                        break;
                    case 'js':
                        doMinify(getArgs(file), opts, 'js');
                        break;
                    case '' :
                        break;
                    default :
                        if (opts.image.patterns.indexOf('.' + extname) != -1) {
                            imin(getArgs(file), opts);
                        }
                }
            });
        },
        task_run = function () {
            //对CSS文件的处理
            if (cssMap) {
                doMinify(cssMap, opts, 'css');
                trace.ok('CSS file processing tasks completed\n');
            }

            if (jsMap) {
                doMinify(jsMap, opts, 'js');
                trace.ok('JS file processing tasks completed\n');
            }

            if (imageMap) {
                imin(imageMap, opts, function () {
                    trace.ok('image compress tasks completed\n');
                    //watch任务处理
                    opts.watch && watchTask();
                });
            } else {
                opts.watch && watchTask();
            }
        };

    /*
     * 因为rjs任务为异步操作
     * 所以放在最先执行的位置上
     */
    if (util.getLength(fileMap) !== 0) {
        if (util.getLength(rjsMap) !== 0) {
            //获取库文件的映射列表
            //arr: ['dirname']
            var libraryMap = getLibraryMap(PATH.resolve(opts.rjs.libraryPath) + PATH.sep, [PATH.resolve(opts.inputPath) + PATH.sep]);
            walk(rjsMap, libraryMap, opts, function () {
                trace.ok('RJS file processing tasks completed\n');
                task_run();
            });
        } else {
            task_run();
        }
    } else {
        trace.warn('no file to be processed , process end');
    }
};
<commit_msg>debug<commit_after>/**
 * Created by wangxin on 15/10/3.
 */

'use strict';

var fs = require('fs');
var PATH = require('path');
var iconv = require('iconv-lite');

var browserify = require('browserify');
var Imagemin = require('imagemin');

var distrbute = require('./lib/distrbute');
var trace = require('./lib/trace');
var outputHandle = require('./lib/output');
var listener = require('./lib/listener');
var util = require('./lib/util');

/*
 * @author wangxin
 * 获取执行任务的参数
 * file: 文件路径
 * return object;
 */
function getArgs(file) {
    var o = arguments[1] || {},
        type = arguments[2] || null,
        i = 0, len = file.length;

    if (len == 0) return o;
    for (; i < len; i++) {
        var path = PATH.resolve(file[i]);
        if (!type) {
            !o[path] && (o[path] = file[i]);
        } else if (type === 'remove') {
            delete o[path];
        }
    }
    return o;
}

/*
 * @author wangxin
 * 获取一个文件下所有文件路径
 * return arr ['dirPath','dirPath',...]
 */
function getLibraryMap(fileDir) {
    var files = fs.readdirSync(fileDir), arr = arguments[1] || [];
    files.forEach(function (fileName) {
        var baseDir = fileDir + fileName, lstat = fs.lstatSync(baseDir);
        if (lstat.isDirectory()) {
            getLibraryMap(baseDir + PATH.sep, arr);
        } else {
            var file = PATH.dirname(baseDir);
            arr.indexOf(file) === -1 && arr.push(PATH.normalize(file));
        }
    });
    return arr;
}

/*
 * @author wangxin
 * 进行browserify编译
 * content: 文件内容，string;
 * outputPath: 输出文件路径
 * return;
 */
function doBrowserify(basePath, libraryMap, config, index, cb) {
    var b = new browserify({
        entries: basePath,
        paths: libraryMap,
        debug: config.rjs.debug || false
    });
    b.bundle(function (err, code) {
        if (err) {
            trace.error(String(err));
        } else {
            //browserify编译完成，开始输出
            outputHandle(iconv.decode(code, 'utf8'), basePath, config, 'rjs');
            code = null;
        }
        cb && cb(index + 1);
    });
}

/*
 * @author wangxin
 * 处理加载模块文件内容为路径名
 * rjsMap: rjs文件map对象
 * libraryMap: 库文件map对象
 * return false;
 */
function walk(rjsMap, libraryMap, opt, cb) {

    var arr = [], go = function (i) {
        if (arr[i]) {
            doBrowserify(arr[i], libraryMap, opt, i, go);
        } else {
            cb && cb();
        }
        return false;
    };

    for (var i in rjsMap) {
        if (!i) {
            trace.error('file error');
            break;
        }
        if (rjsMap.hasOwnProperty(i))  arr.push(rjsMap[i]);
    }

    //开始编译
    return go(0);
}

/*
 * @author wangxin
 * 文件压缩==>js、css文件
 * opts: 输出路径：文件路径
 * retrun；
 */
function doMinify(map, opts, type) {
    for (var i in map) {
        var con = fs.readFileSync(map[i]), charset;
        //这里不建议用gbk编码格式
        if (iconv.decode(con, 'gbk').indexOf('�') != -1) {
            charset = 'utf8';
        } else {
            charset = 'gbk';
        }

        outputHandle(iconv.decode(con, charset), map[i], opts, type);
        con = null;
    }
}

/*
 * @author wangxin
 * 压缩图片
 * opts: 输出路径：文件路径
 * retrun；
 */
function imin(map, opts, cb) {
    var i, arr = [];
    for (i in map) arr.push(map[i]);

    function min(i) {
        new Imagemin().src(arr[i]).dest(PATH.normalize(opts.image.output.path)).run(function () {
            i += 1;
            arr[i] ? min(i) : (cb && cb());
        });
    }

    min(0);
}

/*
 * @author wangxin
 * 初始化方法
 * opts: 配置参数
 * 详情参考 ../test/test.js ==> config
 */
module.exports = function (config) {

    var opts = util.extendDeep(config);

    /**
     * 文件路径的初始化
     */
    var fileMap = distrbute(opts),
        rjsMap = fileMap.rjs,
        cssMap = fileMap.css,
        jsMap = fileMap.js,
        imageMap = fileMap.image,
        watchTask = function () {
            listener(opts, function (file, extname, type) {
                switch (extname) {
                    case 'rjs':
                        if (!type) {
                            walk(getArgs(file, rjsMap, type), libraryMap, opts);
                        } else if (type == 'remove') {
                            rjsMap = getArgs(file, rjsMap, type);
                        } else {
                            file = PATH.normalize(PATH.resolve(file));
                            if (type === 'resetLibA') {
                                libraryMap.indexOf(file) === -1 && libraryMap.push(file);
                            }
                            else if (type === 'resetLibD') {
                                libraryMap = util.removeEle.call(libraryMap, file);
                            }
                        }
                        break;
                    case 'css':
                        if (!type) {
                            doMinify(getArgs(file, cssMap, type), opts, 'css');
                        } else if (type == 'remove') {
                            cssMap = getArgs(file, cssMap, type);
                        }
                        break;
                    case 'js':
                        doMinify(getArgs(file), opts, 'js');
                        break;
                    case '' :
                        break;
                    default :
                        if (opts.image.patterns.indexOf('.' + extname) != -1) {
                            imin(getArgs(file), opts);
                        }
                }
            });
        },
        task_run = function () {
            //对CSS文件的处理
            if (cssMap) {
                doMinify(cssMap, opts, 'css');
                trace.ok('CSS file processing tasks completed\n');
            }

            if (jsMap) {
                doMinify(jsMap, opts, 'js');
                trace.ok('JS file processing tasks completed\n');
            }

            if (imageMap) {
                imin(imageMap, opts, function () {
                    trace.ok('image compress tasks completed\n');
                    //watch任务处理
                    opts.watch && watchTask();
                });
            } else {
                opts.watch && watchTask();
            }
        };

    /*
     * 因为rjs任务为异步操作
     * 所以放在最先执行的位置上
     */
    if (util.getLength(fileMap) !== 0) {
        if (util.getLength(rjsMap) !== 0) {
            //获取库文件的映射列表
            //arr: ['dirname']
            var libraryMap = getLibraryMap(PATH.resolve(opts.rjs.libraryPath) + PATH.sep, [PATH.resolve(opts.inputPath) + PATH.sep]);
            walk(rjsMap, libraryMap, opts, function () {
                trace.ok('RJS file processing tasks completed\n');
                task_run();
            });
        } else {
            task_run();
        }
    } else {
        trace.warn('no file to be processed , process end');
    }
};
<|endoftext|>


<commit_before>module.exports = {
  "env": {
    "browser": true,
    "mocha": true,
    "node": true,
    "es6": true
  },

  "parserOptions": {
    "ecmaVersion": 8 // or 2017
   },

  "extends": [
    "eslint:recommended"
   ],

  "rules": {

    // Separate the rules into blocks based on what plugin they come from.
    // Default rules are split up based on sections found on the eslint rules page.
    // Rules should be sorted alphabetically inside each section.

    "strict": 0,

    // Possible Errors
    "comma-dangle": [2, "always-multiline"], // disallow or enforce trailing commas
    "no-cond-assign": 2, // disallow assignment in conditional expressions
    "no-console": 0, // disallow use of console in the node environment
    "no-constant-condition": 2, // disallow use of constant expressions in conditions
    "no-control-regex": 2, // disallow control characters in regular expressions
    "no-debugger": 1, // disallow use of debugger
    "no-dupe-args": 2, // disallow duplicate arguments in functions
    "no-dupe-keys": 2, // disallow duplicate keys when creating object literals
    "no-duplicate-case": 2, // disallow a duplicate case label
    "no-empty": 2, // disallow empty statements
    "no-empty-character-class": 0, // disallow the use of empty character classes in regular expressions
    "no-ex-assign": 2, // disallow assigning to the exception in a catch block
    "no-extra-boolean-cast": 2, // disallow double-negation boolean casts in a boolean context
    "no-extra-parens": [2, "functions"], // disallow unnecessary parentheses
    "no-extra-semi": 2, // disallow unnecessary semicolons
    "no-func-assign": 2, // disallow overwriting functions written as function declarations
    "no-inner-declarations": [2, "functions"], // disallow function or variable declarations in nested blocks
    "no-invalid-regexp": 0, // disallow invalid regular expression strings in the RegExp constructor
    "no-irregular-whitespace": 0, // disallow irregular whitespace outside of strings and comments
    "no-negated-in-lhs": 0, // disallow negation of the left operand of an in expression
    "no-obj-calls": 2, // disallow the use of object properties of the global object (Math and JSON) as functions
    "no-regex-spaces": 0, // disallow multiple spaces in a regular expression literal
    "no-sparse-arrays": 1, // disallow sparse arrays
    "no-undef": 2, // disallow use of undeclared variables unless mentioned in a /*global */ block
    "no-unexpected-multiline": 2, // avoid code that looks like two expressions but is actually one
    "no-unreachable": 2, // disallow unreachable statements after a return, throw, continue, or break statement
    "no-unused-vars": 2, // disallow declaration of variables that are not used in the code
    "no-use-before-define": [2, "nofunc"], // disallow use of variables before they are defined
    "use-isnan": 2, // disallow comparisons with the value NaN
    "valid-jsdoc": [1, {
      "requireReturn": false,
      "requireReturnDescription": false,
      "requireReturnType": false
    }], // Ensure JSDoc comments are valid
    "valid-typeof": 2, // Ensure that the results of typeof are compared against a valid string

    // Best Practices
    "accessor-pairs": 2, // Enforces getter/setter pairs in objects
    "block-scoped-var": 0, // treat var statements as if they were block scoped
    "complexity": [2, 7], // specify the maximum cyclomatic complexity allowed in a program
    "consistent-return": 2, // require return statements to either always or never specify values
    "curly": 0, // specify curly brace conventions for all control statements
    "default-case": 2, // require default case in switch statements
    "dot-location": 0, // enforces consistent newlines before or after dots
    "dot-notation": 2, // encourages use of dot notation whenever possible
    "eqeqeq": [2, "smart"], // require the use of === and !==
    "guard-for-in": 0, // make sure for-in loops have an if statement
    "no-alert": 1, // disallow the use of alert, confirm, and prompt
    "no-caller": 1, // disallow use of arguments.caller or arguments.callee
    "no-case-declarations": 0, // disallow lexical declarations in case clauses
    "no-div-regex": 0, // disallow division operators explicitly at beginning of regular expression
    "no-else-return": 2, // disallow else after a return in an if
    "no-empty-label": 0, // disallow use of labels for anything other than loops and switches
    "no-empty-pattern": 0, // disallow use of empty destructuring patterns
    "no-eq-null": 0, // disallow comparisons to null without a type-checking operator
    "no-eval": 2, // disallow use of eval()
    "no-extend-native": 2, // disallow adding to native types
    "no-extra-bind": 2, // disallow unnecessary function binding
    "no-fallthrough": 2, // disallow fallthrough of case statements
    "no-floating-decimal": 0, // disallow the use of leading or trailing decimal points in numeric literals
    "no-implicit-coercion": 0, // disallow the type conversions with shorter notations
    "no-implied-eval": 2, // disallow use of eval()-like methods
    "no-invalid-this": 0, // disallow this keywords outside of classes or class-like objects
    "no-iterator": 1, // disallow usage of __iterator__ property
    "no-labels": 0, // disallow use of labeled statements
    "no-lone-blocks": 2, // disallow unnecessary nested blocks
    "no-loop-func": 2, // disallow creation of functions within loops
    "no-magic-numbers": 0, // isallow the use of magic numbers
    "no-multi-spaces": 0, // disallow use of multiple spaces
    "no-multi-str": 0, // disallow use of multiline strings
    "no-native-reassign": 2, // disallow reassignments of native objects
    "no-new": 1, // disallow use of the new operator when not part of an assignment or comparison
    "no-new-func": 1, // disallow use of new operator for Function object
    "no-new-wrappers": 1, // disallows creating new instances of String,Number, and Boolean
    "no-octal": 0, // disallow use of octal literals
    "no-octal-escape": 0, // disallow use of octal escape sequences in string literals, such as var foo = "Copyright \251";
    "no-param-reassign": 1, // disallow reassignment of function parameters
    "no-process-env": 0, // disallow use of process.env
    "no-proto": 2, // disallow usage of __proto__ property
    "no-redeclare": 2, // disallow declaring the same variable more than once
    "no-return-assign": 0, // disallow use of assignment in return statement
    "no-script-url": 0, // disallow use of javascript: urls.
    "no-self-compare": 2, // disallow comparisons where both sides are exactly the same
    "no-sequences": 2, // disallow use of the comma operator
    "no-throw-literal": 2, // restrict what can be thrown as an exception
    "no-useless-call": 2, // disallow unnecessary .call() and .apply()
    "no-useless-concat": 1, // disallow unnecessary concatenation of literals or template literals
    "no-void": 1, // disallow use of the void operator
    "no-warning-comments": 0, // disallow usage of configurable warning terms in comments - e.g. TODO or FIXME
    "no-with": 2, // disallow use of the with statement
    "radix": 2, // require use of the second argument for parseInt()
    "vars-on-top": 0, // require declaration of all vars at the top of their containing scope
    "wrap-iife": 0, // require immediate function invocation to be wrapped in parentheses
    "yoda": 0, // require or disallow Yoda conditions

    // Stylistic Issues
    "array-bracket-spacing": [2, "never"], // enforce spacing inside array brackets
    "block-spacing": 0, // disallow or enforce spaces inside of single line blocks
    "brace-style": [2, "1tbs"], // enforce one true brace style
    "camelcase": 2, // require camel case names
    "comma-spacing": 2, // enforce spacing before and after comma
    "comma-style": 2, // enforce one true comma style
    "computed-property-spacing": 0, // require or disallow padding inside computed properties
    "consistent-this": 0, // enforce consistent naming when capturing the current execution context
    "eol-last": 2, // enforce newline at the end of file, with no multiple empty lines
    "func-names": 0, // require function expressions to have a name
    "func-style": [2, "declaration",  {"allowArrowFunctions": true}], // enforce use of function declarations or expressions
    "id-length": 0, // this option enforces minimum and maximum identifier lengths (variable names, property names etc.)
    "id-match": 0, // require identifiers to match the provided regular expression
    "indent": [2, 2], // specify tab or space width for your code
    "jsx-quotes": [2, "prefer-double"], // specify whether double or single quotes should be used in JSX attributes
    "key-spacing": 2, // enforce spacing between keys and values in object literal properties
    "keyword-spacing": 2, // require a space after certain keywords
    "linebreak-style": [2, "unix"], // disallow mixed 'LF' and 'CRLF' as linebreaks
    "lines-around-comment": 2, // enforce empty lines around comments
    "max-depth": 0, // specify the maximum depth that blocks can be nested
    "max-len": 0, // specify the maximum length of a line in your program
    "max-nested-callbacks": [2, 3], // specify the maximum depth callbacks can be nested
    "max-params": [1, {max:4}], // limits the number of parameters that can be used in the function declaration.
    "max-statements": [1, {max:15}], // specify the maximum number of statement allowed in a function
    "new-cap": [2, { "capIsNew": false }], // require a capital letter for constructors
    "new-parens": 2, // disallow the omission of parentheses when invoking a constructor with no arguments
    "newline-after-var": 0, // require or disallow an empty newline after variable declarations
    "no-array-constructor": 1, // disallow use of the Array constructor
    "no-bitwise": 0, // disallow use of bitwise operators
    "no-continue": 0, // disallow use of the continue statement
    "no-inline-comments": 0, // disallow comments inline after code
    "no-lonely-if": 0, // disallow if as the only statement in an else block
    "no-mixed-spaces-and-tabs": 2, // disallow mixed spaces and tabs for indentation
    "no-multiple-empty-lines": [1, { "max": 3 }], // disallow multiple empty lines
    "no-negated-condition": 0, // disallow negated conditions
    "no-nested-ternary": 2, // disallow nested ternary expressions
    "no-new-object": 1, // disallow the use of the Object constructor
    "no-plusplus": 1, // disallow use of unary operators, ++ and --
    "no-restricted-syntax": 0, // disallow use of certain syntax in code
    "no-spaced-func": 0, // disallow space between function identifier and application
    "no-ternary": 0, // disallow the use of ternary operators
    "no-trailing-spaces": 2, // disallow trailing whitespace at the end of lines
    "no-underscore-dangle": 0, // disallow dangling underscores in identifiers
    "no-unneeded-ternary": 2, // disallow the use of ternary operators when a simpler alternative exists
    "no-useless-escape": 0,
    "object-curly-spacing": [2, "never"], // require or disallow padding inside curly braces
    "one-var": 0, // require or disallow one variable declaration per function
    "operator-assignment": 0, // require assignment operator shorthand where possible or prohibit it entirely
    "operator-linebreak": 0, // enforce operators to be placed before or after line breaks
    "padded-blocks": 0, // enforce padding within blocks
    "quote-props": 0, // require quotes around object literal property names
    "quotes": [2, "double"], // specify whether backticks, double or single quotes should be used
    "require-jsdoc": 0, // Require JSDoc comment
    "semi": [2, "never"], // require or disallow use of semicolons instead of ASI
    "semi-spacing": 0, // enforce spacing before and after semicolons
    "sort-vars": 2, // sort variables within the same declaration block
    "sort-keys": [0, "asc", {"caseSensitive": true, "natural": false}],
    "space-before-blocks": 2, // space-before-blocks
    "space-before-function-paren": [
      "error",
      {
        "anonymous": "never",
        "named": "never",
        "asyncArrow": "always"
      }
    ], // require or disallow a space before function opening parenthesis
    "space-before-keywords": 0, // require a space before certain keywords
    "space-in-parens": [2, "never"], // require or disallow spaces inside parentheses
    "space-infix-ops": 2, // require spaces around operators
    "space-return-throw-case": 0, // require a space after return, throw, and case
    "space-unary-ops": 0, // require or disallow spaces before/after unary operators
    "spaced-comment": 2, // require or disallow a space immediately following the // or /* in a comment
    "wrap-regex": 0, // require regex literals to be wrapped in parentheses

    // ECMAScript 6
    "arrow-body-style": 0, // require braces in arrow function body
    "arrow-parens": 0, // require parens in arrow function arguments
    "arrow-spacing": 0, // require space before/after arrow function's arrow
    "constructor-super": 2, // verify calls of super() in constructors
    "generator-star-spacing": 0, // enforce spacing around the * in generator functions
    "no-arrow-condition": 0, // disallow arrow functions where a condition is expected
    "no-class-assign": 0, // disallow modifying variables of class declarations
    "no-const-assign": 0, // disallow modifying variables that are declared using const
    "no-dupe-class-members": 0, // disallow duplicate name in class members
    "no-this-before-super": 2, // disallow use of this/super before calling super() in constructors.
    "no-var": 2, // require let or const instead of var
    "object-shorthand": 2, // require method and property shorthand syntax for object literals
    "prefer-arrow-callback": 0, // suggest using arrow functions as callbacks
    "prefer-const": 2, // uggest using const declaration for variables that are never modified after declared
    "prefer-reflect": 0, // suggest using Reflect methods where applicable
    "prefer-spread": 0, // suggest using the spread operator instead of .apply().
    "prefer-template": 0, // suggest using template literals instead of strings concatenation
    "require-yield": 0, // disallow generator functions that do not have yield
  }
}
<commit_msg>Relax max-params rule slightly<commit_after>module.exports = {
  "env": {
    "browser": true,
    "mocha": true,
    "node": true,
    "es6": true
  },

  "parserOptions": {
    "ecmaVersion": 8 // or 2017
   },

  "extends": [
    "eslint:recommended"
   ],

  "rules": {

    // Separate the rules into blocks based on what plugin they come from.
    // Default rules are split up based on sections found on the eslint rules page.
    // Rules should be sorted alphabetically inside each section.

    "strict": 0,

    // Possible Errors
    "comma-dangle": [2, "always-multiline"], // disallow or enforce trailing commas
    "no-cond-assign": 2, // disallow assignment in conditional expressions
    "no-console": 0, // disallow use of console in the node environment
    "no-constant-condition": 2, // disallow use of constant expressions in conditions
    "no-control-regex": 2, // disallow control characters in regular expressions
    "no-debugger": 1, // disallow use of debugger
    "no-dupe-args": 2, // disallow duplicate arguments in functions
    "no-dupe-keys": 2, // disallow duplicate keys when creating object literals
    "no-duplicate-case": 2, // disallow a duplicate case label
    "no-empty": 2, // disallow empty statements
    "no-empty-character-class": 0, // disallow the use of empty character classes in regular expressions
    "no-ex-assign": 2, // disallow assigning to the exception in a catch block
    "no-extra-boolean-cast": 2, // disallow double-negation boolean casts in a boolean context
    "no-extra-parens": [2, "functions"], // disallow unnecessary parentheses
    "no-extra-semi": 2, // disallow unnecessary semicolons
    "no-func-assign": 2, // disallow overwriting functions written as function declarations
    "no-inner-declarations": [2, "functions"], // disallow function or variable declarations in nested blocks
    "no-invalid-regexp": 0, // disallow invalid regular expression strings in the RegExp constructor
    "no-irregular-whitespace": 0, // disallow irregular whitespace outside of strings and comments
    "no-negated-in-lhs": 0, // disallow negation of the left operand of an in expression
    "no-obj-calls": 2, // disallow the use of object properties of the global object (Math and JSON) as functions
    "no-regex-spaces": 0, // disallow multiple spaces in a regular expression literal
    "no-sparse-arrays": 1, // disallow sparse arrays
    "no-undef": 2, // disallow use of undeclared variables unless mentioned in a /*global */ block
    "no-unexpected-multiline": 2, // avoid code that looks like two expressions but is actually one
    "no-unreachable": 2, // disallow unreachable statements after a return, throw, continue, or break statement
    "no-unused-vars": 2, // disallow declaration of variables that are not used in the code
    "no-use-before-define": [2, "nofunc"], // disallow use of variables before they are defined
    "use-isnan": 2, // disallow comparisons with the value NaN
    "valid-jsdoc": [1, {
      "requireReturn": false,
      "requireReturnDescription": false,
      "requireReturnType": false
    }], // Ensure JSDoc comments are valid
    "valid-typeof": 2, // Ensure that the results of typeof are compared against a valid string

    // Best Practices
    "accessor-pairs": 2, // Enforces getter/setter pairs in objects
    "block-scoped-var": 0, // treat var statements as if they were block scoped
    "complexity": [2, 7], // specify the maximum cyclomatic complexity allowed in a program
    "consistent-return": 2, // require return statements to either always or never specify values
    "curly": 0, // specify curly brace conventions for all control statements
    "default-case": 2, // require default case in switch statements
    "dot-location": 0, // enforces consistent newlines before or after dots
    "dot-notation": 2, // encourages use of dot notation whenever possible
    "eqeqeq": [2, "smart"], // require the use of === and !==
    "guard-for-in": 0, // make sure for-in loops have an if statement
    "no-alert": 1, // disallow the use of alert, confirm, and prompt
    "no-caller": 1, // disallow use of arguments.caller or arguments.callee
    "no-case-declarations": 0, // disallow lexical declarations in case clauses
    "no-div-regex": 0, // disallow division operators explicitly at beginning of regular expression
    "no-else-return": 2, // disallow else after a return in an if
    "no-empty-label": 0, // disallow use of labels for anything other than loops and switches
    "no-empty-pattern": 0, // disallow use of empty destructuring patterns
    "no-eq-null": 0, // disallow comparisons to null without a type-checking operator
    "no-eval": 2, // disallow use of eval()
    "no-extend-native": 2, // disallow adding to native types
    "no-extra-bind": 2, // disallow unnecessary function binding
    "no-fallthrough": 2, // disallow fallthrough of case statements
    "no-floating-decimal": 0, // disallow the use of leading or trailing decimal points in numeric literals
    "no-implicit-coercion": 0, // disallow the type conversions with shorter notations
    "no-implied-eval": 2, // disallow use of eval()-like methods
    "no-invalid-this": 0, // disallow this keywords outside of classes or class-like objects
    "no-iterator": 1, // disallow usage of __iterator__ property
    "no-labels": 0, // disallow use of labeled statements
    "no-lone-blocks": 2, // disallow unnecessary nested blocks
    "no-loop-func": 2, // disallow creation of functions within loops
    "no-magic-numbers": 0, // isallow the use of magic numbers
    "no-multi-spaces": 0, // disallow use of multiple spaces
    "no-multi-str": 0, // disallow use of multiline strings
    "no-native-reassign": 2, // disallow reassignments of native objects
    "no-new": 1, // disallow use of the new operator when not part of an assignment or comparison
    "no-new-func": 1, // disallow use of new operator for Function object
    "no-new-wrappers": 1, // disallows creating new instances of String,Number, and Boolean
    "no-octal": 0, // disallow use of octal literals
    "no-octal-escape": 0, // disallow use of octal escape sequences in string literals, such as var foo = "Copyright \251";
    "no-param-reassign": 1, // disallow reassignment of function parameters
    "no-process-env": 0, // disallow use of process.env
    "no-proto": 2, // disallow usage of __proto__ property
    "no-redeclare": 2, // disallow declaring the same variable more than once
    "no-return-assign": 0, // disallow use of assignment in return statement
    "no-script-url": 0, // disallow use of javascript: urls.
    "no-self-compare": 2, // disallow comparisons where both sides are exactly the same
    "no-sequences": 2, // disallow use of the comma operator
    "no-throw-literal": 2, // restrict what can be thrown as an exception
    "no-useless-call": 2, // disallow unnecessary .call() and .apply()
    "no-useless-concat": 1, // disallow unnecessary concatenation of literals or template literals
    "no-void": 1, // disallow use of the void operator
    "no-warning-comments": 0, // disallow usage of configurable warning terms in comments - e.g. TODO or FIXME
    "no-with": 2, // disallow use of the with statement
    "radix": 2, // require use of the second argument for parseInt()
    "vars-on-top": 0, // require declaration of all vars at the top of their containing scope
    "wrap-iife": 0, // require immediate function invocation to be wrapped in parentheses
    "yoda": 0, // require or disallow Yoda conditions

    // Stylistic Issues
    "array-bracket-spacing": [2, "never"], // enforce spacing inside array brackets
    "block-spacing": 0, // disallow or enforce spaces inside of single line blocks
    "brace-style": [2, "1tbs"], // enforce one true brace style
    "camelcase": 2, // require camel case names
    "comma-spacing": 2, // enforce spacing before and after comma
    "comma-style": 2, // enforce one true comma style
    "computed-property-spacing": 0, // require or disallow padding inside computed properties
    "consistent-this": 0, // enforce consistent naming when capturing the current execution context
    "eol-last": 2, // enforce newline at the end of file, with no multiple empty lines
    "func-names": 0, // require function expressions to have a name
    "func-style": [2, "declaration",  {"allowArrowFunctions": true}], // enforce use of function declarations or expressions
    "id-length": 0, // this option enforces minimum and maximum identifier lengths (variable names, property names etc.)
    "id-match": 0, // require identifiers to match the provided regular expression
    "indent": [2, 2], // specify tab or space width for your code
    "jsx-quotes": [2, "prefer-double"], // specify whether double or single quotes should be used in JSX attributes
    "key-spacing": 2, // enforce spacing between keys and values in object literal properties
    "keyword-spacing": 2, // require a space after certain keywords
    "linebreak-style": [2, "unix"], // disallow mixed 'LF' and 'CRLF' as linebreaks
    "lines-around-comment": 2, // enforce empty lines around comments
    "max-depth": 0, // specify the maximum depth that blocks can be nested
    "max-len": 0, // specify the maximum length of a line in your program
    "max-nested-callbacks": [2, 3], // specify the maximum depth callbacks can be nested
    "max-params": [1, {max:5}], // limits the number of parameters that can be used in the function declaration.
    "max-statements": [1, {max:15}], // specify the maximum number of statement allowed in a function
    "new-cap": [2, { "capIsNew": false }], // require a capital letter for constructors
    "new-parens": 2, // disallow the omission of parentheses when invoking a constructor with no arguments
    "newline-after-var": 0, // require or disallow an empty newline after variable declarations
    "no-array-constructor": 1, // disallow use of the Array constructor
    "no-bitwise": 0, // disallow use of bitwise operators
    "no-continue": 0, // disallow use of the continue statement
    "no-inline-comments": 0, // disallow comments inline after code
    "no-lonely-if": 0, // disallow if as the only statement in an else block
    "no-mixed-spaces-and-tabs": 2, // disallow mixed spaces and tabs for indentation
    "no-multiple-empty-lines": [1, { "max": 3 }], // disallow multiple empty lines
    "no-negated-condition": 0, // disallow negated conditions
    "no-nested-ternary": 2, // disallow nested ternary expressions
    "no-new-object": 1, // disallow the use of the Object constructor
    "no-plusplus": 1, // disallow use of unary operators, ++ and --
    "no-restricted-syntax": 0, // disallow use of certain syntax in code
    "no-spaced-func": 0, // disallow space between function identifier and application
    "no-ternary": 0, // disallow the use of ternary operators
    "no-trailing-spaces": 2, // disallow trailing whitespace at the end of lines
    "no-underscore-dangle": 0, // disallow dangling underscores in identifiers
    "no-unneeded-ternary": 2, // disallow the use of ternary operators when a simpler alternative exists
    "no-useless-escape": 0,
    "object-curly-spacing": [2, "never"], // require or disallow padding inside curly braces
    "one-var": 0, // require or disallow one variable declaration per function
    "operator-assignment": 0, // require assignment operator shorthand where possible or prohibit it entirely
    "operator-linebreak": 0, // enforce operators to be placed before or after line breaks
    "padded-blocks": 0, // enforce padding within blocks
    "quote-props": 0, // require quotes around object literal property names
    "quotes": [2, "double"], // specify whether backticks, double or single quotes should be used
    "require-jsdoc": 0, // Require JSDoc comment
    "semi": [2, "never"], // require or disallow use of semicolons instead of ASI
    "semi-spacing": 0, // enforce spacing before and after semicolons
    "sort-vars": 2, // sort variables within the same declaration block
    "sort-keys": [0, "asc", {"caseSensitive": true, "natural": false}],
    "space-before-blocks": 2, // space-before-blocks
    "space-before-function-paren": [
      "error",
      {
        "anonymous": "never",
        "named": "never",
        "asyncArrow": "always"
      }
    ], // require or disallow a space before function opening parenthesis
    "space-before-keywords": 0, // require a space before certain keywords
    "space-in-parens": [2, "never"], // require or disallow spaces inside parentheses
    "space-infix-ops": 2, // require spaces around operators
    "space-return-throw-case": 0, // require a space after return, throw, and case
    "space-unary-ops": 0, // require or disallow spaces before/after unary operators
    "spaced-comment": 2, // require or disallow a space immediately following the // or /* in a comment
    "wrap-regex": 0, // require regex literals to be wrapped in parentheses

    // ECMAScript 6
    "arrow-body-style": 0, // require braces in arrow function body
    "arrow-parens": 0, // require parens in arrow function arguments
    "arrow-spacing": 0, // require space before/after arrow function's arrow
    "constructor-super": 2, // verify calls of super() in constructors
    "generator-star-spacing": 0, // enforce spacing around the * in generator functions
    "no-arrow-condition": 0, // disallow arrow functions where a condition is expected
    "no-class-assign": 0, // disallow modifying variables of class declarations
    "no-const-assign": 0, // disallow modifying variables that are declared using const
    "no-dupe-class-members": 0, // disallow duplicate name in class members
    "no-this-before-super": 2, // disallow use of this/super before calling super() in constructors.
    "no-var": 2, // require let or const instead of var
    "object-shorthand": 2, // require method and property shorthand syntax for object literals
    "prefer-arrow-callback": 0, // suggest using arrow functions as callbacks
    "prefer-const": 2, // uggest using const declaration for variables that are never modified after declared
    "prefer-reflect": 0, // suggest using Reflect methods where applicable
    "prefer-spread": 0, // suggest using the spread operator instead of .apply().
    "prefer-template": 0, // suggest using template literals instead of strings concatenation
    "require-yield": 0, // disallow generator functions that do not have yield
  }
}
<|endoftext|>


<commit_before>/**
 * Created by dob on 19.11.13.
 */
var molecuel;

var i18next = require('i18next');
require('string.prototype.startswith');

var i18n = function() {
  this.config = molecuel.config.i18n;
  this.defaultlang = this.getDefaultLang();
  this.supportedlang = this.getSupportedLanguages();
  var handleConfig = {};
  if(this.config.detectLngFromPath === true) {
    handleConfig.detectLngFromPath = 0;
  }
  var self = this;
  handleConfig.useCookie = true;
  handleConfig.forceDetectLngFromPath = true;
  if(this.config.debug) {
    handleConfig.debug = true;
  }
  handleConfig.fallbackLng = this.defaultlang;
  handleConfig.supportedLngs = this.supportedlang;
  handleConfig.resGetPath = 'config/locales/__lng__/__ns__.json'
  i18next.init(handleConfig);
  this.i18next = i18next;

  /**
   * Add plugin to the created models
   */
  molecuel.on('mlcl::elements::registerSchema:post', function(elements, schemaname, modelRegistryElement) {
    self.elements = elements;
    var options = modelRegistryElement.options;
    var model =  modelRegistryElement.schema;
    // check if the schema configuration avoids url creation.
    if(options && !options.avoidTranslate) {
      model.plugin(self._schemaPlugin, {modelname: schemaname});
    }
  });

  /**
   * Register view helper
   */
  molecuel.on('mlcl::view::register:helper', function(view) {
    self.registerViewHelpers(view);
  });
};

/* ************************************************************************
 SINGLETON CLASS DEFINITION
 ************************************************************************ */
var instance = null;

/**
 * Singleton getInstance definition
 * @return singleton class
 */
var getInstance = function(){
  if(instance === null){
    instance = new i18n();
  }
  return instance;
};

function init(m) {
  molecuel = m;
  return getInstance();
}

/**
 * init module
 * @param app
 */
i18n.prototype.initApplication = function(app) {
  app.use(this.i18next.handle);
  app.use(function(req, res, next) {
    if(req.language) {
      req.prelangurl = req.url;
      var path = '/'+req.language;
      //var index = req.url.indexOf(path);
      if(req.url.startsWith(path)) {
        var str = req.url.substr(path.length);
        req.url = str;
        res.setHeader('x-mlcl-i18n-prelangurl', req.prelangurl);
        res.setHeader('x-mlcl-i18n-nolangurl', req.url);
      } else {
        if (req.url.charAt(0) !== '/') {
          req.url = req.url + '/';
        }
      }
      res.setHeader('X-mlcl-i18n-language', req.language);
    }
    next();
  });
};

/**
 * Get the default language
 * @returns {string}
 */
i18n.prototype.getDefaultLang = function getDefaultLang() {
  var target = this.config.languages;
  for (var k in target){
    if (target.hasOwnProperty(k)) {
      if(target[k].default) {
        return k;
      }
    }
  }
};

/**
 * Register the model
 * @param modelname
 * @param model
 * @param indexable
 */
/**
 * Return the definition of the plugin
 * @param schema
 * @param options
 */
i18n.prototype._schemaPlugin = function _schemaPlugin(schema, options) {
  var i18n = getInstance();
  if(options.modelname) {
    schema.add({
      lang: { type: String, enum: i18n.supportedlang, required: true},
      translations: [
        {
          lang: {type: String, enum: i18n.supportedlang, form: {hidden: true}},
          url: {type: String, form: {hidden: true}},
          element: {type: i18n.elements.ObjectId, ref: options.modelname, form: {hidden: true}},
          title: {type: String, form: {hidden: true}}
        }
      ]

    });
  }
};

/**
 * Get the languages supported by the system
 * @returns {Array}
 */
i18n.prototype.getSupportedLanguages = function getSupportedLanguages() {
  var target = this.config.languages;
  var supported = [];
  for (var k in target){
    if (target.hasOwnProperty(k)) {
      supported.push(k);
    }
  }
  return supported;
};

i18n.prototype.registerViewHelpers = function registerViewHelpers(view) {

  view.registerHelper('i18n:t', function(str, options) {
    return i18next.t(str);
  });

  view.registerRequestHelper('i18n:l', function(view, req, res) {
    return function() {
      return "the Language = " + req.language;
    }
  });
};

module.exports = init;
<commit_msg>Added list<commit_after>/**
 * Created by dob on 19.11.13.
 */
var molecuel;

var i18next = require('i18next');
require('string.prototype.startswith');

var i18n = function() {
  this.config = molecuel.config.i18n;
  this.defaultlang = this.getDefaultLang();
  this.supportedlang = this.getSupportedLanguages();
  var handleConfig = {};
  if(this.config.detectLngFromPath === true) {
    handleConfig.detectLngFromPath = 0;
  }
  var self = this;
  handleConfig.useCookie = true;
  handleConfig.forceDetectLngFromPath = true;
  if(this.config.debug) {
    handleConfig.debug = true;
  }
  handleConfig.fallbackLng = this.defaultlang;
  handleConfig.supportedLngs = this.supportedlang;
  handleConfig.resGetPath = 'config/locales/__lng__/__ns__.json'
  i18next.init(handleConfig);
  this.i18next = i18next;

  /**
   * Add plugin to the created models
   */
  molecuel.on('mlcl::elements::registerSchema:post', function(elements, schemaname, modelRegistryElement) {
    self.elements = elements;
    var options = modelRegistryElement.options;
    var model =  modelRegistryElement.schema;
    // check if the schema configuration avoids url creation.
    if(options && !options.avoidTranslate) {
      model.plugin(self._schemaPlugin, {modelname: schemaname});
    }
  });

  /**
   * Register view helper
   */
  molecuel.on('mlcl::view::register:helper', function(view) {
    self.registerViewHelpers(view);
  });
};

/* ************************************************************************
 SINGLETON CLASS DEFINITION
 ************************************************************************ */
var instance = null;

/**
 * Singleton getInstance definition
 * @return singleton class
 */
var getInstance = function(){
  if(instance === null){
    instance = new i18n();
  }
  return instance;
};

function init(m) {
  molecuel = m;
  return getInstance();
}

/**
 * init module
 * @param app
 */
i18n.prototype.initApplication = function(app) {
  app.use(this.i18next.handle);
  app.use(function(req, res, next) {
    if(req.language) {
      req.prelangurl = req.url;
      var path = '/'+req.language;
      //var index = req.url.indexOf(path);
      if(req.url.startsWith(path)) {
        var str = req.url.substr(path.length);
        req.url = str;
        res.setHeader('x-mlcl-i18n-prelangurl', req.prelangurl);
        res.setHeader('x-mlcl-i18n-nolangurl', req.url);
      } else {
        if (req.url.charAt(0) !== '/') {
          req.url = req.url + '/';
        }
      }
      res.setHeader('X-mlcl-i18n-language', req.language);
    }
    next();
  });
};

/**
 * Get the default language
 * @returns {string}
 */
i18n.prototype.getDefaultLang = function getDefaultLang() {
  var target = this.config.languages;
  for (var k in target){
    if (target.hasOwnProperty(k)) {
      if(target[k].default) {
        return k;
      }
    }
  }
};

/**
 * Register the model
 * @param modelname
 * @param model
 * @param indexable
 */
/**
 * Return the definition of the plugin
 * @param schema
 * @param options
 */
i18n.prototype._schemaPlugin = function _schemaPlugin(schema, options) {
  var i18n = getInstance();
  if(options.modelname) {
    schema.add({
      lang: { type: String, enum: i18n.supportedlang, required: true, list: true},
      translations: [
        {
          lang: {type: String, enum: i18n.supportedlang, form: {hidden: true}},
          url: {type: String, form: {hidden: true}},
          element: {type: i18n.elements.ObjectId, ref: options.modelname, form: {hidden: true}},
          title: {type: String, form: {hidden: true}}
        }
      ]

    });
  }
};

/**
 * Get the languages supported by the system
 * @returns {Array}
 */
i18n.prototype.getSupportedLanguages = function getSupportedLanguages() {
  var target = this.config.languages;
  var supported = [];
  for (var k in target){
    if (target.hasOwnProperty(k)) {
      supported.push(k);
    }
  }
  return supported;
};

i18n.prototype.registerViewHelpers = function registerViewHelpers(view) {

  view.registerHelper('i18n:t', function(str, options) {
    return i18next.t(str);
  });

  view.registerRequestHelper('i18n:l', function(view, req, res) {
    return function() {
      return "the Language = " + req.language;
    }
  });
};

module.exports = init;
<|endoftext|>


<commit_before>(function () {
    'use strict';

    var BSTNode = function (value) {
        this.key = value;
        this.right = null;
        this.left = null;
    };

    function basicCompare(a, b) {
        return a - b;
    }

    var BST = function (compareFn) {
        this.root = null;
        this.cmp = compareFn || basicCompare;
    };

    BST.prototype.add = function (value) {
        var newNode = new BSTNode(value);

        if (this.root === null) {
            this.root = newNode;
        } else {
            addNode(this.root, newNode, this.cmp);
        }
    };

    BST.prototype.contains = function (value) {
        return containsNode(this.root, value, this.cmp);
    };

    BST.prototype.inOrderTraversal = function (cb) {
        inOrderTraverseNode(this.root, cb);
    };

    BST.prototype.preOrderTraverseNode = function (cb) {
        preOrderTraverseNode(this.root, cb);
    };

    BST.prototype.postOrderTraverseNode = function (cb) {
        postOrderTraverseNode(this.root, cb);
    };

    BST.prototype.min = function () {
        return minNode(this.root);
    };

    BST.prototype.max = function () {
        return maxNode(this.root);
    };

    BST.prototype.remove = function (key) {
        var removeNode = this.root;
        var parent = this.root;
        var isLeftChild = true;

        while (removeNode.key !== key) {
            parent = removeNode;

            if (this.cmp(removeNode.key, key) > 0) {
                isLeftChild = true;
                removeNode = removeNode.left;
            } else {
                isLeftChild = false;
                removeNode = removeNode.right;
            }

            if (removeNode === null) {
                return false;
            }
        }

        // case 1: leaf node
        if (removeNode.left === null && removeNode.right === null) {

            if (removeNode === this.root) {
                this.root = null;
            }

            if (isLeftChild) {
                parent.left = null;

            } else {
                parent.right = null;
            }

        // case 2: one child node
        // case 2a: left child but no right child
        } else if (removeNode.right === null) {

            if (removeNode === this.root) {
                this.root = removeNode.left;

            } else if (isLeftChild) {
                parent.left = removeNode.left;

            } else {
                parent.right = removeNode.left;
            }

        // case 2b: right child but no left child
        } else if (removeNode.left === null) {

            if (removeNode === this.root) {
                this.root = removeNode.right;

            } else if (isLeftChild) {
                parent.left = removeNode.right;

            } else {
                parent.right = removeNode.right;
            }

        // case 3: both left and right nodes
        // this is where it gets a bit harder...need to determine the replacement
        // node.
        } else {

            var replacement = getReplacementNode(removeNode);

            if (removeNode === this.root) {
                this.root = replacement;

            } else if (isLeftChild) {
                parent.left = replacement;

            } else {
                parent.right = replacement;
            }

            replacement.left = removeNode.left;
        }

        return true;
    };

    module.exports = BST;

    if (module.parent === null) {
        main();
    }

    function main() {
    }

    /********** helper functions **********/
    function addNode(node, newNode, cmp) {
        if (cmp(node.key, newNode.key) > 0) {
            if (node.left === null) {
                node.left = newNode;
            } else {
                addNode(node.left, newNode, cmp);
            }

        } else {
            if (node.right === null) {
                node.right = newNode;
            } else {
                addNode(node.right, newNode, cmp);
            }

        }
    }

    function containsNode(node, value, cmp) {
        if (node === null) {
            return false;
        }

        if (cmp(node.key, value) > 0) {
            return containsNode(node.left, value, cmp);
        } else if (cmp(value, node.key) > 0) {
            return containsNode(node.right, value, cmp);
        } else {
            return true;
        }
    }

    function inOrderTraverseNode(node, cb) {
        if (node !== null) {
            inOrderTraverseNode(node.left, cb);
            cb(node.key);
            inOrderTraverseNode(node.right, cb);
        }
    }

    function preOrderTraverseNode(node, cb) {
        if (node !== null) {
            cb(node.key);
            preOrderTraverseNode(node.left, cb);
            preOrderTraverseNode(node.right, cb);
        }
    }

    function postOrderTraverseNode(node, cb) {
        if (node !== null) {
            postOrderTraverseNode(node.left, cb);
            postOrderTraverseNode(node.right, cb);
            cb(node.key);
        }
    }

    function minNode(node) {
        if (node) {
            while (node && node.left !== null) {
                node = node.left;
            }
            return node.key;
        }
        return null;
    }

    function maxNode(node) {
        if (node) {
            while (node && node.right !== null) {
                node = node.right;
            }
            return node.key;
        }
        return null;
    }

    function getReplacementNode(nodeToRemove) {
        var replacementParent = nodeToRemove;
        var replacementNode = nodeToRemove;

        var focusNode = nodeToRemove.right;

        while (focusNode !== null) {
            replacementParent = replacementNode;
            replacementNode = focusNode;

            focusNode = focusNode.left;
        }

        if (replacementNode !== nodeToRemove.right) {
            replacementParent.left = replacementNode.right;
            replacementNode.right = nodeToRemove.right;
        }

        return replacementNode;
    }

}());
<commit_msg>Rename traversal methods to fix issue<commit_after>(function () {
    'use strict';

    var BSTNode = function (value) {
        this.key = value;
        this.right = null;
        this.left = null;
    };

    function basicCompare(a, b) {
        return a - b;
    }

    var BST = function (compareFn) {
        this.root = null;
        this.cmp = compareFn || basicCompare;
    };

    BST.prototype.add = function (value) {
        var newNode = new BSTNode(value);

        if (this.root === null) {
            this.root = newNode;
        } else {
            addNode(this.root, newNode, this.cmp);
        }
    };

    BST.prototype.contains = function (value) {
        return containsNode(this.root, value, this.cmp);
    };

    BST.prototype.inOrderTraversal = function (cb) {
        inOrderTraverseNode(this.root, cb);
    };

    BST.prototype.preOrderTraversal = function (cb) {
        preOrderTraverseNode(this.root, cb);
    };

    BST.prototype.postOrderTraversal = function (cb) {
        postOrderTraverseNode(this.root, cb);
    };

    BST.prototype.min = function () {
        return minNode(this.root);
    };

    BST.prototype.max = function () {
        return maxNode(this.root);
    };

    BST.prototype.remove = function (key) {
        var removeNode = this.root;
        var parent = this.root;
        var isLeftChild = true;

        while (removeNode.key !== key) {
            parent = removeNode;

            if (this.cmp(removeNode.key, key) > 0) {
                isLeftChild = true;
                removeNode = removeNode.left;
            } else {
                isLeftChild = false;
                removeNode = removeNode.right;
            }

            if (removeNode === null) {
                return false;
            }
        }

        // case 1: leaf node
        if (removeNode.left === null && removeNode.right === null) {

            if (removeNode === this.root) {
                this.root = null;
            }

            if (isLeftChild) {
                parent.left = null;

            } else {
                parent.right = null;
            }

        // case 2: one child node
        // case 2a: left child but no right child
        } else if (removeNode.right === null) {

            if (removeNode === this.root) {
                this.root = removeNode.left;

            } else if (isLeftChild) {
                parent.left = removeNode.left;

            } else {
                parent.right = removeNode.left;
            }

        // case 2b: right child but no left child
        } else if (removeNode.left === null) {

            if (removeNode === this.root) {
                this.root = removeNode.right;

            } else if (isLeftChild) {
                parent.left = removeNode.right;

            } else {
                parent.right = removeNode.right;
            }

        // case 3: both left and right nodes
        // this is where it gets a bit harder...need to determine the replacement
        // node.
        } else {

            var replacement = getReplacementNode(removeNode);

            if (removeNode === this.root) {
                this.root = replacement;

            } else if (isLeftChild) {
                parent.left = replacement;

            } else {
                parent.right = replacement;
            }

            replacement.left = removeNode.left;
        }

        return true;
    };

    module.exports = BST;

    if (module.parent === null) {
        main();
    }

    function main() {
    }

    /********** helper functions **********/
    function addNode(node, newNode, cmp) {
        if (cmp(node.key, newNode.key) > 0) {
            if (node.left === null) {
                node.left = newNode;
            } else {
                addNode(node.left, newNode, cmp);
            }

        } else {
            if (node.right === null) {
                node.right = newNode;
            } else {
                addNode(node.right, newNode, cmp);
            }

        }
    }

    function containsNode(node, value, cmp) {
        if (node === null) {
            return false;
        }

        if (cmp(node.key, value) > 0) {
            return containsNode(node.left, value, cmp);
        } else if (cmp(value, node.key) > 0) {
            return containsNode(node.right, value, cmp);
        } else {
            return true;
        }
    }

    function inOrderTraverseNode(node, cb) {
        if (node !== null) {
            inOrderTraverseNode(node.left, cb);
            cb(node.key);
            inOrderTraverseNode(node.right, cb);
        }
    }

    function preOrderTraverseNode(node, cb) {
        if (node !== null) {
            cb(node.key);
            preOrderTraverseNode(node.left, cb);
            preOrderTraverseNode(node.right, cb);
        }
    }

    function postOrderTraverseNode(node, cb) {
        if (node !== null) {
            postOrderTraverseNode(node.left, cb);
            postOrderTraverseNode(node.right, cb);
            cb(node.key);
        }
    }

    function minNode(node) {
        if (node) {
            while (node && node.left !== null) {
                node = node.left;
            }
            return node.key;
        }
        return null;
    }

    function maxNode(node) {
        if (node) {
            while (node && node.right !== null) {
                node = node.right;
            }
            return node.key;
        }
        return null;
    }

    function getReplacementNode(nodeToRemove) {
        var replacementParent = nodeToRemove;
        var replacementNode = nodeToRemove;

        var focusNode = nodeToRemove.right;

        while (focusNode !== null) {
            replacementParent = replacementNode;
            replacementNode = focusNode;

            focusNode = focusNode.left;
        }

        if (replacementNode !== nodeToRemove.right) {
            replacementParent.left = replacementNode.right;
            replacementNode.right = nodeToRemove.right;
        }

        return replacementNode;
    }

}());
<|endoftext|>


<commit_before>var express = require('express'),
    fs = require('fs'),
    request = require('request'),
    config = require('./config'),
    types = require('./types');

exports.routes = function() {
    app = express();
    app.get("/:layer/*", function appGet (req, res) {
        var layerConfig = config.layers[req.param("layer")],
            cacheInfo;

        // Make sure the specified type is available
        if (layerConfig && types[layerConfig.type]) {
            cacheInfo = types[layerConfig.type].process(req, res, layerConfig);
        }

        if (cacheInfo) {

            // get the cache info if we can
            getCache(cacheInfo);
        } else {

            // If we can't get it, return an error
            res.status(404).send("Not Found");
        }
    });
    return app;
};

var getCache = function getCache(cacheInfo) {

    var createDirectories = function createDirectories(tilePath, cachePath, callback) {
        var testPaths = tilePath.split('/').concat(cachePath.split('/'));
        var checkDirectory = function checkDirectory(testPaths, innerCallback, index) {
            var testPath;
            index = index || 0;

            // Set this directory if the user adds './' as the root
            if (testPaths[0] === ".") {
                testPath = __dirname;
            } else {
                testPath = testPaths[0];
            }
            if (index > 0) {
                testPath = [testPath, testPaths.slice(1,index).join("/")].join("/");
            }

            if (index > testPaths.length - 1) {
                console.log("done loop");
                innerCallback(testPath);
            } else {
                fs.exists(testPath, function(exists) {
                    if (exists) {
                        checkDirectory(testPaths, innerCallback, index + 1);
                    } else {
                        fs.mkdir(testPath, 0777, function(err) {
                            if (!err) {
                                checkDirectory(testPaths, innerCallback, index + 1);
                            } else {
                                throw ("Error creating directory: " + err);
                            }
                        });
                    }
                });
            }
        };
        checkDirectory(testPaths, function(filename){
            console.log("fn: " + filename);
            callback(filename);
        });
    };

    var displayImage = function(filename) {

        // Write out the headers
        //cacheInfo.res.writeHead(200, {'Content-Type': 'image/jpeg'});

        // Check if the file exists
        fs.stat(filename, function(statErr) {
            if (!statErr) {

                // if so, open it and send it to the user
                var readStream = fs.createReadStream(filename);
                readStream.on('open', function() {
                    readStream.pipe(cacheInfo.stream);
                });
                readStream.on('error', function(readErr) {
                    cacheInfo.res.end(err);
                });
            } else {

                // Otherwise, download it and stream it to the user
                var writeStream = fs.createWriteStream(filename);
                writeStream.on('error', function(writeError) {
                    console.log("write error: " + writeErr);
                });
                console.log("opening write stream!");
                var saveImage = request(cacheInfo.url);

                // Stream to file
                saveImage.pipe(writeStream);

                // Stream to the browser
                saveImage.pipe(cacheInfo.stream);

                cacheInfo.stream.on('error', function(readErr) {
                    cacheInfo.res.end(err);
                });
            }
        });
    };

    createDirectories(config.tilePath, cacheInfo.cachePath, function(img){
        displayImage(img);
    });
};

// This is just for debugging really
var toHtml = function toHtml(inVal) {
    var inReq = [];
    for (var val in inVal) {
        inReq.push(["", val, "", ": ", inVal[val]].join(''));
    }
    return inReq.join("
");
};
<commit_msg>reworked some error handling<commit_after>var express = require('express'),
    fs = require('fs'),
    request = require('request'),
    config = require('./config'),
    types = require('./types');

exports.routes = function() {
    app = express();

    // leaflet test display
    app.get("/", function(req, res) {
        res.sendfile(__dirname + '/public/index.html');
    });

    //
    app.get("/:layer/*", function appGet (req, res) {
        var layerConfig = config.layers[req.param("layer")],
            cacheInfo;

        // Make sure the specified type is available
        if (layerConfig && types[layerConfig.type]) {
            cacheInfo = types[layerConfig.type].process(req, res, layerConfig);
        }

        if (cacheInfo) {

            // get the cache info if we can
            getCache(cacheInfo);
        } else {

            // If we can't get it, return an error
            sendError(404,res);
        }
    });
    return app;
};

var getCache = function getCache(cacheInfo) {

    var createDirectories = function createDirectories(tilePath, cachePath, callback) {
        var testPaths = tilePath.split('/').concat(cachePath.split('/'));
        var checkDirectory = function checkDirectory(testPaths, innerCallback, index) {
            var testPath;
            index = index || 0;

            // Set this directory if the user adds './' as the root
            if (testPaths[0] === ".") {
                testPath = __dirname;
            } else {
                testPath = testPaths[0];
            }
            if (index > 0) {
                testPath = [testPath, testPaths.slice(1,index).join("/")].join("/");
            }

            if (index > testPaths.length - 1) {
                console.log("done loop");
                innerCallback(testPath);
            } else {
                fs.exists(testPath, function(exists) {
                    var next = function next(){
                        checkDirectory(testPaths, innerCallback, index + 1);
                    };
                    console.log("testing path: " + testPath);
                    if (exists) {
                        next();
                    } else {
                        fs.mkdir(testPath, 0777, function(err) {
                            if (!err) {
                                next();
                            } else {
                                console.log("Error creating directory: " + err);
                                console.log(err);
                                if (err.errno === 47) {
                                    next();
                                } else {
                                    throw (err);
                                }
                            }
                        });
                    }
                });
            }
        };
        checkDirectory(testPaths, function(filename){
            console.log("fn: " + filename);
            callback(filename);
        });
    };

    var displayImage = function(filename) {

        // Write out the headers
        cacheInfo.res.writeHead(200, {'Content-Type': getContentType("png")});

        // Check if the file exists
        fs.stat(filename, function(statErr) {
            if (!statErr) {

                // if so, open it and send it to the user
                var readStream = fs.createReadStream(filename);
                readStream.on('open', function() {
                    readStream.pipe(cacheInfo.stream);
                });
                readStream.on('error', function(readErr) {
                    console.log(readErr);
                    //cacheInfo.res.end(readErr);
                });
            } else {

                // Otherwise, download it and stream it to the user
                var writeStream = fs.createWriteStream(filename);
                writeStream.on('error', function(writeError) {
                    console.log("write error: " + writeErr);
                });
                console.log("opening write stream!");
                var saveImage = request(cacheInfo.tileUrl);

                // Stream to file
                saveImage.pipe(writeStream);

                // Stream to the browser
                saveImage.pipe(cacheInfo.stream);

                cacheInfo.stream.on('error', function(readErr) {
                    cacheInfo.res.end(err);
                });
            }
        });
    };

    if (cacheInfo.cacheTile) {
        createDirectories(config.tilePath, cacheInfo.cachePath, function(img){
            displayImage(img);
        });
    } else {
        if (cacheInfo.tileUrl) {
            // do a 301 forward
            console.log(cacheInfo.tileUrl);
            cacheInfo.res.redirect(307, cacheInfo.tileUrl); //config.tileUrl);
        } else {
            //Tile Error
            /// PREDEFINED TILE ERROR PATH
            sendError(404,cacheInfo.res, cacheInfo.errorDescription);
        }
    }
};

// This is just for debugging really
var toHtml = function toHtml(inVal) {
    var inReq = [];
    for (var val in inVal) {
        inReq.push(["", val, "", ": ", inVal[val]].join(''));
    }
    return inReq.join("
");
};

// This should be a separate file?
var getContentType = function getContentType(ext) {
    var types = {
        "gif": "image/gif",
        "jpg": "image/jpeg",
        "jpeg": "image/jpeg",
        "png": "image/png",
        "tiff": "image/tiff"
    };
    return types[ext];
};
var sendError = function(errorType, res, description) {
    description = description ? "
" + description : "";
    res.status(errorType).send("Not Found" + description);
};
<|endoftext|>


<commit_before><commit_msg>fix for https://github.com/oliver-moran/jimp/issues/74<commit_after><|endoftext|>


<commit_before>/**
 * Module dependencies
 */

var
  Emitter   = require('emitter'),
  events    = require('event'),
  domify    = require('domify'),
  rotate    = require('rotate'),
  extend    = require('extend'),
  template  = require('./template');

/**
 * Expose `Dial`
 */

module.exports = Dial;

/**
 * A constructor for a Dial object,
 * creating a radial UI dial controlling
 * an input field
 *
 * Options
 *
 * - `min` minimum value
 * - `max` maximum value
 * - `float` boolean determing whether floats are allowed
 * - `increment` value to increment by
 * - `value` starting value
 *
 * @param {HTMLInputElement} input
 * @param {Object} options
 * @api public
 */

function Dial (input, options) {
  this.input = input;
  this.options = extend(false,
    Dial.defaults,
    optionsFromAttrs(this.input),
    options
  );

  this.value = this.options.value;

  this
    .setDefaultIncrement()
    .render()
    .bind()
    .hideInput();

  this.input.parentNode.appendChild(this.el);
  this.rotate();
}

/**
 * Inherits from `Emitter.prototype`
 */

Dial.prototype.__proto__ = Emitter.prototype;

/**
 * Defaults for each dial.
 * Increment is handled in setDefaultIncrement
 */

Dial.defaults = {
  min: 0,
  max: 10,
  value: 5,
  float: false,
  increment: null
};

/**
 * Creates the dial's `el` property
 *
 * @return {Dial}
 * @api public
 */

Dial.prototype.render = function () {
  this.el = domify(template)[0];
  return this;
};

/**
 * Binds mouse events for the dial element,
 * and on document if not already bound
 *
 * @return {Dial}
 * @api public
 */

Dial.prototype.bind = function () {
  var that = this;

  events.bind(this.el, 'mousedown', mouseDownHandler);
  events.bind(this.input, 'change', inputChangeHandler);

  // Bind mouseup and movemouse handlers
  // to document for better dragging
  if (!Dial.docEventsBound) {
    events.bind(document, 'mouseup', onMouseUp);
    events.bind(document, 'mousemove', onMouseMove);

    Dial.docEventsBound = true;
  }

  /**
   * Unbinds dial's events, not on prototype
   * due to unbinding event on input element in scope
   *
   * @return {Dial}
   * @api public
   */

  this.unbind = function () {
    events.unbind(this.el, 'mousedown');
    events.unbind(this.input, 'change', inputChangeHandler);
    return this;
  };

  function mouseDownHandler () {
    onMouseDown.apply(that, arguments);
  }

  function inputChangeHandler () {
    that.set(this.value);
  }

  return this;
};

/**
 * Removes dial element, reveals original input element,
 * unbinds dial events.
 *
 * @return {Dial}
 * @api public
 */

Dial.prototype.destroy = function () {
  var parent = this.el.parentElement;
  this.unbind();
  this.showInput();
  parent.removeChild(this.el);
  return this;
};

/**
 * Sets the dial's value if in allowed range,
 * rounds to integer if needed, updates the corresponding
 * input element, rotates dial and fires a change event
 *
 * @param {Number} val
 * @return {Dial}
 * @api public
 */

Dial.prototype.set = function (val) {
  if (val < this.options.min || val > this.options.max) {
    return;
  }
  if (!this.options.float) {
    val = ~~val;
  }
  this.input.value = val;
  this.value = val;
  this.emit('change', val);
  this.rotate();
  return this;
};

/**
 * Rotates the dial el based off of current
 * dial's value
 *
 * @return {Dial}
 * @api public
 */

Dial.prototype.rotate = function () {
  var MAX_DEG = 270;
  var shift = 405;
  var relative = (MAX_DEG / (this.options.max - this.options.min)) *
    (this.value - this.options.min);
  var degrees = relative - MAX_DEG + shift;

  rotate(this.el, degrees);

  return this;
};

/**
 * Hides original input element
 *
 * @return this;
 */

Dial.prototype.hideInput = function () {
  this.originalDisplay = this.originalDisplay || this.input.style.display;
  this.input.style.display = 'none';
  return this;
};

/**
 * Shows original input element
 *
 * @return this;
 */

Dial.prototype.showInput = function () {
  this.input.style.display = this.originalDisplay;
  return this;
};

/**
 * If no increment specific in config or attributes,
 * set an increment of a 1/25th of the allowable range.
 * Round to integer if necessary.
 *
 * @return this
 * @api public
 */

Dial.prototype.setDefaultIncrement = function () {
  var options = this.options;
  var increment;
  if (!options.increment) {
    increment = (options.max - options.min) / 25;
    if (!options.float) {
      increment = ~~increment || 1;
    }
    options.increment = increment;
  }

  return this;
};

/**
 * Takes an input element and parses attributes
 * and returns an object containing the attributes
 * if not empty.
 *
 * @param {HTMLInputElement} input
 * @return {Object}
 * @api private
 */

function optionsFromAttrs (input) {
  var options = {};
  var min = parseFloatAttr(input, 'min');
  var max = parseFloatAttr(input, 'max');
  var value = parseFloatAttr(input, 'value');
  var float = !!input.getAttribute('data-float');
  var inc = parseFloatAttr(input, 'increment');

  min   != undefined && (options.min       = min);
  max   != undefined && (options.max       = max);
  float != undefined && (options.float     = float);
  inc   != undefined && (options.increment = inc);
  value !== ''       && (options.value     = value);

  return options;
}

/**
 * Parses an attribute on an element
 * and returns as float if it exists
 *
 * @param {HTMLInputElement} el
 * @param {String} attr
 * @return {Mixed}
 * @api private
 */

function parseFloatAttr (el, attr) {
  var value = attr === 'value' ?
    el.value :
    el.getAttribute('data-' + attr);

  value = value && parseFloat(value);

  return value;
}

function onMouseMove (e) {
  var dial = Dial.activeDial;

  if (!dial) { return; }

  var curPos = e.x;
  var options = dial.options;
  var lastPos = dial.pos !== undefined ? dial.pos : curPos;

  // Increase
  if (curPos > lastPos) {
    dial.set(dial.value + options.increment);
  // Decrease
  } else if (curPos < lastPos) {
    dial.set(dial.value - options.increment);
  }

  dial.pos = curPos;
}

function onMouseDown (e) {
  Dial.activeDial = this;
  e.preventDefault();
}

function onMouseUp (e) {
  Dial.activeDial = null;
}
<commit_msg>Use Emitter's mixin method rather than inheritence to work in IE9<commit_after>/**
 * Module dependencies
 */

var
  Emitter   = require('emitter'),
  events    = require('event'),
  domify    = require('domify'),
  rotate    = require('rotate'),
  extend    = require('extend'),
  template  = require('./template');

/**
 * Expose `Dial`
 */

module.exports = Dial;

/**
 * A constructor for a Dial object,
 * creating a radial UI dial controlling
 * an input field
 *
 * Options
 *
 * - `min` minimum value
 * - `max` maximum value
 * - `float` boolean determing whether floats are allowed
 * - `increment` value to increment by
 * - `value` starting value
 *
 * @param {HTMLInputElement} input
 * @param {Object} options
 * @api public
 */

function Dial (input, options) {
  this.input = input;
  this.options = extend(false,
    Dial.defaults,
    optionsFromAttrs(this.input),
    options
  );

  Emitter(this);

  this.value = this.options.value;

  this
    .setDefaultIncrement()
    .render()
    .bind()
    .hideInput();

  this.input.parentNode.appendChild(this.el);
  this.rotate();
}

/**
 * Defaults for each dial.
 * Increment is handled in setDefaultIncrement
 */

Dial.defaults = {
  min: 0,
  max: 10,
  value: 5,
  float: false,
  increment: null
};

/**
 * Creates the dial's `el` property
 *
 * @return {Dial}
 * @api public
 */

Dial.prototype.render = function () {
  this.el = domify(template)[0];
  return this;
};

/**
 * Binds mouse events for the dial element,
 * and on document if not already bound
 *
 * @return {Dial}
 * @api public
 */

Dial.prototype.bind = function () {
  var that = this;

  events.bind(this.el, 'mousedown', mouseDownHandler);
  events.bind(this.input, 'change', inputChangeHandler);

  // Bind mouseup and movemouse handlers
  // to document for better dragging
  if (!Dial.docEventsBound) {
    events.bind(document, 'mouseup', onMouseUp);
    events.bind(document, 'mousemove', onMouseMove);

    Dial.docEventsBound = true;
  }

  /**
   * Unbinds dial's events, not on prototype
   * due to unbinding event on input element in scope
   *
   * @return {Dial}
   * @api public
   */

  this.unbind = function () {
    events.unbind(this.el, 'mousedown');
    events.unbind(this.input, 'change', inputChangeHandler);
    return this;
  };

  function mouseDownHandler () {
    onMouseDown.apply(that, arguments);
  }

  function inputChangeHandler () {
    that.set(this.value);
  }

  return this;
};

/**
 * Removes dial element, reveals original input element,
 * unbinds dial events.
 *
 * @return {Dial}
 * @api public
 */

Dial.prototype.destroy = function () {
  var parent = this.el.parentElement;
  this.unbind();
  this.showInput();
  parent.removeChild(this.el);
  return this;
};

/**
 * Sets the dial's value if in allowed range,
 * rounds to integer if needed, updates the corresponding
 * input element, rotates dial and fires a change event
 *
 * @param {Number} val
 * @return {Dial}
 * @api public
 */

Dial.prototype.set = function (val) {
  if (val < this.options.min || val > this.options.max) {
    return;
  }
  if (!this.options.float) {
    val = ~~val;
  }
  this.input.value = val;
  this.value = val;
  this.emit('change', val);
  this.rotate();
  return this;
};

/**
 * Rotates the dial el based off of current
 * dial's value
 *
 * @return {Dial}
 * @api public
 */

Dial.prototype.rotate = function () {
  var MAX_DEG = 270;
  var shift = 405;
  var relative = (MAX_DEG / (this.options.max - this.options.min)) *
    (this.value - this.options.min);
  var degrees = relative - MAX_DEG + shift;

  rotate(this.el, degrees);

  return this;
};

/**
 * Hides original input element
 *
 * @return this;
 */

Dial.prototype.hideInput = function () {
  this.originalDisplay = this.originalDisplay || this.input.style.display;
  this.input.style.display = 'none';
  return this;
};

/**
 * Shows original input element
 *
 * @return this;
 */

Dial.prototype.showInput = function () {
  this.input.style.display = this.originalDisplay;
  return this;
};

/**
 * If no increment specific in config or attributes,
 * set an increment of a 1/25th of the allowable range.
 * Round to integer if necessary.
 *
 * @return this
 * @api public
 */

Dial.prototype.setDefaultIncrement = function () {
  var options = this.options;
  var increment;
  if (!options.increment) {
    increment = (options.max - options.min) / 25;
    if (!options.float) {
      increment = ~~increment || 1;
    }
    options.increment = increment;
  }

  return this;
};

/**
 * Takes an input element and parses attributes
 * and returns an object containing the attributes
 * if not empty.
 *
 * @param {HTMLInputElement} input
 * @return {Object}
 * @api private
 */

function optionsFromAttrs (input) {
  var options = {};
  var min = parseFloatAttr(input, 'min');
  var max = parseFloatAttr(input, 'max');
  var value = parseFloatAttr(input, 'value');
  var float = !!input.getAttribute('data-float');
  var inc = parseFloatAttr(input, 'increment');

  min   != undefined && (options.min       = min);
  max   != undefined && (options.max       = max);
  float != undefined && (options.float     = float);
  inc   != undefined && (options.increment = inc);
  value !== ''       && (options.value     = value);

  return options;
}

/**
 * Parses an attribute on an element
 * and returns as float if it exists
 *
 * @param {HTMLInputElement} el
 * @param {String} attr
 * @return {Mixed}
 * @api private
 */

function parseFloatAttr (el, attr) {
  var value = attr === 'value' ?
    el.value :
    el.getAttribute('data-' + attr);

  value = value && parseFloat(value);

  return value;
}

function onMouseMove (e) {
  var dial = Dial.activeDial;

  if (!dial) { return; }

  var curPos = e.x;
  var options = dial.options;
  var lastPos = dial.pos !== undefined ? dial.pos : curPos;

  // Increase
  if (curPos > lastPos) {
    dial.set(dial.value + options.increment);
  // Decrease
  } else if (curPos < lastPos) {
    dial.set(dial.value - options.increment);
  }

  dial.pos = curPos;
}

function onMouseDown (e) {
  Dial.activeDial = this;
  e.preventDefault();
}

function onMouseUp (e) {
  Dial.activeDial = null;
}
<|endoftext|>