<commit_before>'use strict';

var UserModel = require('./models/user');
var TradeModel = require('./models/trade');

var config = require('../config/config');

var TradeController = require('./tradeController');
var tradeController = new TradeController();

module.exports = function() {

  this.ranking = function(mainCallback){

    // Get all sells
    TradeModel.aggregate(
      { $match: { 'type' : 'Sell', active : true }},
      { $group: {
        _id: "$owner",
        balance: { $sum: { $multiply: [ "$price", "$amount" ] } }
      }},
      function (sellErr, sellRes) {
        if (sellErr)
          return console.log(sellErr);

        // Get all purchases
        TradeModel.aggregate(
          { $match: { 'type' : 'Buy', active : true }},
          { $group: {
            _id: "$owner",
            balance: { $sum: { $multiply: [ "$price", "$amount", -1 ] } }
          }},
          function (buyErr, buyRes) {
            if (buyErr)
              return console.log(buyErr);

            // Join purchases with sells
            var transactionsSum = sellRes.concat(buyRes);

            // Group purchases and sells (sells - purchases)
            // Sort results by balance
            // Get Top results
            var result = transactionsSum.reduce(function(res, obj) {
                if (!(obj._id in res))
                    res.__array.push(res[obj._id] = obj);
                else
                    res[obj._id].balance += obj.balance;
                return res;
            }, {__array:[]}).__array
              .sort(function(a,b) { return b.balance - a.balance; })
              .slice(0, config.usersOnRanking);

            // Fetch users data (async loop)
            var asyncLoop = function(o){
                var i=-1;
                var loop = function(){
                    i++;
                    if(i==o.length){o.callback(); return;}
                    o.functionToLoop(loop, i);
                }
                loop();//init
            }
            asyncLoop({
                length : result.length,
                functionToLoop : function(loop, i){
                  UserModel.findById(result[i]._id, function(err, userDoc){
                    delete result[i]._id;
                    result[i].user = userDoc;
                    loop();
                  });
                },
                callback : function(){
                    mainCallback(result);
                }
            });

        });

      });

  };

  this.rankingPosition = function(user, mainCallback){

    // Get all sells
    TradeModel.aggregate(
      { $match: { 'type' : 'Sell', active : true }},
      { $group: {
        _id: "$owner",
        balance: { $sum: { $multiply: [ "$price", "$amount" ] } }
      }},
      function (sellErr, sellRes) {
        if (sellErr)
          return console.log(sellErr);

        // Get all purchases
        TradeModel.aggregate(
          { $match: { 'type' : 'Buy', active : true }},
          { $group: {
            _id: "$owner",
            balance: { $sum: { $multiply: [ "$price", "$amount", -1 ] } }
          }},
          function (buyErr, buyRes) {
            if (buyErr)
              return console.log(buyErr);

            // Join purchases with sells
            var transactionsSum = sellRes.concat(buyRes);

            // Group purchases and sells (sells - purchases)
            // Sort results by balance
            var result = transactionsSum.reduce(function(res, obj) {
                if (!(obj._id in res))
                    res.__array.push(res[obj._id] = obj);
                else
                    res[obj._id].balance += obj.balance;
                return res;
            }, {__array:[]}).__array
              .sort(function(a,b) { return b.balance - a.balance; });

            // Get user position
            var position = null;
            for (var i = 0; i < result.length; i++) {
                 if (result[i]._id.equals(user._id)) {
                    position = i+1;
                    break;
                 }
             }
             mainCallback(position);

        });

      });

  };

  this.portfolio = function(user, callback){

    var portfolioArray = [];

    TradeModel.find({ 'owner' : user, 'type' : 'Buy', active : true }, function(err, trades) {

      if (err)
        callback(portfolioArray);

      if (!trades || trades.length === 0)
        callback(portfolioArray);

      var itemsProcessed = 0;
      trades.forEach((trade, index, array) => {

          findStockPrice(trade, function(portfolioItem){

            portfolioArray.push(portfolioItem);
            itemsProcessed++;
            if(itemsProcessed === trades.length)
              callback(portfolioArray);

          });

      });

    });

    var findStockPrice = function(trade, callback){

      tradeController.findStockHistory(trade.stock, function(history){

        var portfolioItem = {
          'tradeId' : trade._id,
          'stock' : trade.stock,
          'amount' : trade.amount,
          'purchasePrice' : trade.price,
          'currentPrice' : history[0].price || 0,
          'created' : trade.created,
          'history' : history
        };
        callback(portfolioItem);

      });

    };

  };

  this.stats = function(user, callback){

    var thisController = this;
    tradeController.totalSells(user, function(totalSell){
        tradeController.totalPurchases(user, function(totalBuy){
              callback({
                'totalSells': totalSell,
                'totalPurchases': totalBuy
              });
          });
      });

  };

  this.statement = function(user, callback){

    TradeModel.find({ 'owner' : user }, function(err, trades) {
      callback(trades);
    });

  };

  this.restart = function(user, mainCallback){

    // Need to get user again so it will not be affected by manipulated requests
    UserModel.findById(user._id, function(err, docUser){

      if (err)
        return mainCallback({ success: false, message: err });

      if (!docUser)
        return mainCallback({ success: false, message: 'User not found' });

      removeTrades(docUser, processReset);
    });

    var removeTrades = function(docUser, callback){
        TradeModel.remove({ 'owner' : docUser }, function(){
          callback(docUser);
        });
    }

    var processReset = function(docUser){

      // Trades removed. Add reset trade.
      var trade = new TradeModel({
        stock: '_RESET',
        price: config.startingPoints,
        amount: 1,
        owner: docUser,
        type: 'Sell',
      });

      trade.save(function(err) {
        if (err)
          return mainCallback({ success: false, message: err });

        return mainCallback({
          success: true,
          message: 'You reset your account'
        });

      });

    }

  };

};
<commit_msg>ranking fix<commit_after>'use strict';

var UserModel = require('./models/user');
var TradeModel = require('./models/trade');

var config = require('../config/config');

var TradeController = require('./tradeController');
var tradeController = new TradeController();

module.exports = function() {

  this.ranking = function(mainCallback){

    // Get all sells
    TradeModel.aggregate(
      { $match: { 'type' : 'Sell' }},
      { $group: {
        _id: "$owner",
        balance: { $sum: { $multiply: [ "$price", "$amount" ] } }
      }},
      function (sellErr, sellRes) {
        if (sellErr)
          return console.log(sellErr);

        // Get all purchases
        TradeModel.aggregate(
          { $match: { 'type' : 'Buy' }},
          { $group: {
            _id: "$owner",
            balance: { $sum: { $multiply: [ "$price", "$amount", -1 ] } }
          }},
          function (buyErr, buyRes) {
            if (buyErr)
              return console.log(buyErr);

            // Join purchases with sells
            var transactionsSum = sellRes.concat(buyRes);

            // Group purchases and sells (sells - purchases)
            // Sort results by balance
            // Get Top results
            var result = transactionsSum.reduce(function(res, obj) {
                if (!(obj._id in res))
                    res.__array.push(res[obj._id] = obj);
                else
                    res[obj._id].balance += obj.balance;
                return res;
            }, {__array:[]}).__array
              .sort(function(a,b) { return b.balance - a.balance; })
              .slice(0, config.usersOnRanking);

            // Fetch users data (async loop)
            var asyncLoop = function(o){
                var i=-1;
                var loop = function(){
                    i++;
                    if(i==o.length){o.callback(); return;}
                    o.functionToLoop(loop, i);
                }
                loop();//init
            }
            asyncLoop({
                length : result.length,
                functionToLoop : function(loop, i){
                  UserModel.findById(result[i]._id, function(err, userDoc){
                    delete result[i]._id;
                    result[i].user = userDoc;
                    loop();
                  });
                },
                callback : function(){
                    mainCallback(result);
                }
            });

        });

      });

  };

  this.rankingPosition = function(user, mainCallback){

    // Get all sells
    TradeModel.aggregate(
      { $match: { 'type' : 'Sell', active : true }},
      { $group: {
        _id: "$owner",
        balance: { $sum: { $multiply: [ "$price", "$amount" ] } }
      }},
      function (sellErr, sellRes) {
        if (sellErr)
          return console.log(sellErr);

        // Get all purchases
        TradeModel.aggregate(
          { $match: { 'type' : 'Buy', active : true }},
          { $group: {
            _id: "$owner",
            balance: { $sum: { $multiply: [ "$price", "$amount", -1 ] } }
          }},
          function (buyErr, buyRes) {
            if (buyErr)
              return console.log(buyErr);

            // Join purchases with sells
            var transactionsSum = sellRes.concat(buyRes);

            // Group purchases and sells (sells - purchases)
            // Sort results by balance
            var result = transactionsSum.reduce(function(res, obj) {
                if (!(obj._id in res))
                    res.__array.push(res[obj._id] = obj);
                else
                    res[obj._id].balance += obj.balance;
                return res;
            }, {__array:[]}).__array
              .sort(function(a,b) { return b.balance - a.balance; });

            // Get user position
            var position = null;
            for (var i = 0; i < result.length; i++) {
                 if (result[i]._id.equals(user._id)) {
                    position = i+1;
                    break;
                 }
             }
             mainCallback(position);

        });

      });

  };

  this.portfolio = function(user, callback){

    var portfolioArray = [];

    TradeModel.find({ 'owner' : user, 'type' : 'Buy', active : true }, function(err, trades) {

      if (err)
        callback(portfolioArray);

      if (!trades || trades.length === 0)
        callback(portfolioArray);

      var itemsProcessed = 0;
      trades.forEach((trade, index, array) => {

          findStockPrice(trade, function(portfolioItem){

            portfolioArray.push(portfolioItem);
            itemsProcessed++;
            if(itemsProcessed === trades.length)
              callback(portfolioArray);

          });

      });

    });

    var findStockPrice = function(trade, callback){

      tradeController.findStockHistory(trade.stock, function(history){

        var portfolioItem = {
          'tradeId' : trade._id,
          'stock' : trade.stock,
          'amount' : trade.amount,
          'purchasePrice' : trade.price,
          'currentPrice' : history[0].price || 0,
          'created' : trade.created,
          'history' : history
        };
        callback(portfolioItem);

      });

    };

  };

  this.stats = function(user, callback){

    var thisController = this;
    tradeController.totalSells(user, function(totalSell){
        tradeController.totalPurchases(user, function(totalBuy){
              callback({
                'totalSells': totalSell,
                'totalPurchases': totalBuy
              });
          });
      });

  };

  this.statement = function(user, callback){

    TradeModel.find({ 'owner' : user }, function(err, trades) {
      callback(trades);
    });

  };

  this.restart = function(user, mainCallback){

    // Need to get user again so it will not be affected by manipulated requests
    UserModel.findById(user._id, function(err, docUser){

      if (err)
        return mainCallback({ success: false, message: err });

      if (!docUser)
        return mainCallback({ success: false, message: 'User not found' });

      removeTrades(docUser, processReset);
    });

    var removeTrades = function(docUser, callback){
        TradeModel.remove({ 'owner' : docUser }, function(){
          callback(docUser);
        });
    }

    var processReset = function(docUser){

      // Trades removed. Add reset trade.
      var trade = new TradeModel({
        stock: '_RESET',
        price: config.startingPoints,
        amount: 1,
        owner: docUser,
        type: 'Sell',
      });

      trade.save(function(err) {
        if (err)
          return mainCallback({ success: false, message: err });

        return mainCallback({
          success: true,
          message: 'You reset your account'
        });

      });

    }

  };

};
<|endoftext|>


<commit_before>'use strict';

angular.module('utils.services', [])

.service('dataService', function($http) {
    var apiURL = "https://api.xmrpool.net";

    // delete $http.defaults.headers.common['X-Requested-With'];
    this.getData = function(url, callbackFunc, errCallback) {
        $http({
            method: 'GET',
            url: apiURL + url,
            // params: 'limit=10, sort_by=created:desc',
            // headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
        }).then(function successCallback(response) {
          // With the data succesfully returned, call our callback
          callbackFunc(response.data);
        }, function errorCallback(response) {
          if (errCallback && response != undefined) errCallback(response); else console.log("Network Error", response);
          // called asynchronously if an error occurs
          // or server returns response with an error status.
        }).$promise;
     }
})

.service('timerService', function($interval) {
    var timer;
    var listeners = {};

    this.startTimer = function(ms) {
        timer = $interval(function() {
            _.each(listeners, function(listener) {
                listener();
            });
        }, ms);
    }

    this.stopTimer = function(){
        $interval.cancel(timer);
    }

    this.register = function(callback, key){
        // console.log("Registering requests for", key);
        return listeners[key] = callback;
    }

    this.remove = function(key){
        // console.log("Destroying requests for", key);
        delete listeners[key];
    }
})

.service('addressService', function(dataService, timerService, $localStorage, ngAudio) {
  var addrStats = {};
  var callback;
  var storage = $localStorage;

  this.trackAddress = function (addr) {
    addrStats[addr] = {};
    track();
  }

  this.deleteAddress = function (key) {
    delete addrStats[key];
  };

  this.getData = function (){
    return addrStats;
  }

  this.setAlarm = function(addr, bool){
    addrStats[addr].alarm = bool;
    storage.addrStats[addr].alarm = bool;
  }

  var track = function(){
    _.each(addrStats, function(addr, key) {
      // Get Miner stats
      dataService.getData("/miner/"+key+"/stats", function(data){
        addrStats[key] = Object.assign(addr, data);

        // check and inject alarm var
        if (addr.alarm == undefined) {
          addr.alarm = false;
        }

        // Set default miner name address
        if (addr.name === undefined) {
          addr.name = key;
        }

        // update
        storage.addrStats = addrStats;
        callback(addrStats);
      });

      // Get miner worker ids
      dataService.getData("/miner/"+key+"/identifiers", function(minerIDs){
        addrStats[key].ids = minerIDs;
      });

    });

  }

  this.start = function (cb){
    timerService.register(track, 'minerStats');
    addrStats = storage.addrStats || {} ;
    callback = cb;
    track(); // also run immediately
  }
})

.service('minerService', function($filter, dataService) {
  var minerStats = {};
  var callback;
  var status = true; // check pause

  this.runService = function (bool) {
    status = bool;
  }

  this.updateStats = function (addrs, callback) {

    // initalise addrs
    if(!status) return 0;

    _.each(addrs, function (data, addr) {

      if (minerStats[addr] === undefined) minerStats[addr] = {
        dataset : {},
        options : {
          series: [],
          axes: {
            x: {
              key: "ts",
              type: "date"
            }
          }
        }
      };

      // get all ids from adds
      minerStats[addr].ids = data.ids;

      dataService.getData("/miner/"+addr+"/chart/hashrate/allWorkers", function(allWorkersData){
          // Convert all dates to object

          _.each(allWorkersData, function (workerData, mid) {
            for(var i = 0 ; i < workerData.length; i++){
              allWorkersData[mid][i].ts = new Date(allWorkersData[mid][i].ts);
            }

            minerStats[addr].dataset[mid] = workerData;

            minerStats[addr].options.series = _.unionBy(minerStats[addr].options.series, [{
                axis: "y",
                id: mid,
                dataset: mid,
                label: mid,
                key: "hs",
                color: (minerStats[addr].options.series[mid]===undefined) ? randomColor() : minerStats[addr].options.series[mid].color,
                type: ['line', 'area'],
                interpolation: { mode: "bundle", tension: 0.6 },
                defined: function (value){
                  //console.log(value);
                  return (value !== undefined || value.x !== undefined || value.y !== undefined) ;
                }
              }], 'id');
          });

      });

    //   _.each(minerStats[addr].ids, function (val, mid) {
    //     // request

    // });

    callback(minerStats);

    });
  };
});<commit_msg>cleanup<commit_after>'use strict';

angular.module('utils.services', [])

.service('dataService', function($http) {
    var apiURL = "https://api.xmrpool.net";

    // delete $http.defaults.headers.common['X-Requested-With'];
    this.getData = function(url, callbackFunc, errCallback) {
        $http({
            method: 'GET',
            url: apiURL + url,
            // params: 'limit=10, sort_by=created:desc',
            // headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
        }).then(function successCallback(response) {
          // With the data succesfully returned, call our callback
          callbackFunc(response.data);
        }, function errorCallback(response) {
          if (errCallback && response != undefined) errCallback(response); else console.log("Network Error", response);
          // called asynchronously if an error occurs
          // or server returns response with an error status.
        }).$promise;
     }
})

.service('timerService', function($interval) {
    var timer;
    var listeners = {};

    this.startTimer = function(ms) {
        timer = $interval(function() {
            _.each(listeners, function(listener) {
                listener();
            });
        }, ms);
    }

    this.stopTimer = function(){
        $interval.cancel(timer);
    }

    this.register = function(callback, key){
        // console.log("Registering requests for", key);
        return listeners[key] = callback;
    }

    this.remove = function(key){
        // console.log("Destroying requests for", key);
        delete listeners[key];
    }
})

.service('addressService', function(dataService, timerService, $localStorage, ngAudio) {
  var addrStats = {};
  var callback;
  var storage = $localStorage;

  this.trackAddress = function (addr) {
    addrStats[addr] = {};
    track();
  }

  this.deleteAddress = function (key) {
    delete addrStats[key];
  };

  this.getData = function (){
    return addrStats;
  }

  this.setAlarm = function(addr, bool){
    addrStats[addr].alarm = bool;
    storage.addrStats[addr].alarm = bool;
  }

  var track = function(){
    _.each(addrStats, function(addr, key) {
      // Get Miner stats
      dataService.getData("/miner/"+key+"/stats", function(data){
        addrStats[key] = Object.assign(addr, data);

        // check and inject alarm var
        if (addr.alarm == undefined) {
          addr.alarm = false;
        }

        // Set default miner name address
        if (addr.name === undefined) {
          addr.name = key;
        }

        // update
        storage.addrStats = addrStats;
        callback(addrStats);
      });

      // Get miner worker ids
      dataService.getData("/miner/"+key+"/identifiers", function(minerIDs){
        addrStats[key].ids = minerIDs;
      });

    });

  }

  this.start = function (cb){
    timerService.register(track, 'minerStats');
    addrStats = storage.addrStats || {} ;
    callback = cb;
    track(); // also run immediately
  }
})

.service('minerService', function($filter, dataService) {
  var minerStats = {};
  var callback;
  var status = true; // check pause

  this.runService = function (bool) {
    status = bool;
  }

  this.updateStats = function (addrs, callback) {

    // initalise addrs
    if(!status) return 0;

    _.each(addrs, function (data, addr) {

      if (minerStats[addr] === undefined) minerStats[addr] = {
        dataset : {},
        options : {
          series: [],
          axes: {
            x: {
              key: "ts",
              type: "date"
            }
          }
        }
      };

      // get all ids from adds
      minerStats[addr].ids = data.ids;

      dataService.getData("/miner/"+addr+"/chart/hashrate/allWorkers", function(allWorkersData){
          // Convert all dates to object

          _.each(allWorkersData, function (workerData, mid) {
            for(var i = 0 ; i < workerData.length; i++){
              allWorkersData[mid][i].ts = new Date(allWorkersData[mid][i].ts);
            }

            minerStats[addr].dataset[mid] = workerData;

            minerStats[addr].options.series = _.unionBy(minerStats[addr].options.series, [{
                axis: "y",
                id: mid,
                dataset: mid,
                label: mid,
                key: "hs",
                color: (minerStats[addr].options.series[mid]===undefined) ? randomColor() : minerStats[addr].options.series[mid].color,
                type: ['line', 'area'],
                interpolation: { mode: "bundle", tension: 0.6 },
                defined: function (value){
                  //console.log(value);
                  return (value !== undefined || value.x !== undefined || value.y !== undefined) ;
                }
              }], 'id');
          });

      });

    callback(minerStats);

    });
  };
});<|endoftext|>


<commit_before>module.exports = function(grunt) {

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        config: grunt.file.readYAML('../config/config.yml'),

        watch: {
            options: {
                spawn: false,
                livereload: true
            },
            scripts: {
                files: ['sass/*.scss', 'sass/nav/*.scss'],
                tasks: ['sass'],
            },
            js: {
                files: ['js/*.js', 'js/src/*.js'],
                tasks: ['concat:js'],
            }
        },

        sass: {
            dist: {
                options: {
                    style: 'compressed',
                    loadPath: [
                        'node_modules/bootstrap-sass/assets/stylesheets/',
                        'node_modules/font-awesome/scss/'
                    ],
                    lineNumbers: false,
                    unixNewlines: true,
                    banner: "/**\n * These are Bolt's COMPILED CSS files! \n * Do not edit these files, because all changes will be lost. \n * You can edit ../scss/app.scss & ../scss/app-old-ie.scss, and run 'grunt' to generate this file. \n */"
                },
                files: {
                    'css/bolt-old-ie.css': 'sass/app-old-ie.scss',
                    'css/bolt.css': 'sass/app.scss'
                }
            }

        },

        copy: {
            main: {
                files: [
                    // includes files within path
                    {expand: true, flatten: true, src: ['node_modules/font-awesome/fonts/*'], dest: 'fonts/', filter: 'isFile'}
                ]
            }
        },

        // concat: {
        //     bootstrap: {
        //         src: [
        //             'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/alert.js',
        //             'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/button.js',
        //             'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/dropdown.js',
        //             'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/tab.js',
        //             'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/transition.js',
        //             'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/modal.js',
        //             'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/tooltip.js',
        //             'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/popover.js',
        //         ],
        //         dest: 'js/bootstrap-concat.js',
        //     },
        //     bolt: {
        //         // TODO: configure this.
        //         //src: ['src/main.js', 'src/extras.js'],
        //         //dest: 'dist/with_extras.js',
        //     },
        // },

        concat: {
            js: {
                src: [
                    'js/src/console.js',
                    'js/src/start.js',
                    'js/src/fnc-helpers.js',
                    'js/src/init-keyboard-shortcuts.js',
                    'js/src/init-ckeditor.js',
                    'js/src/activity.js',
                    'js/src/bind-fileupload.js',
                    'js/src/make-uri-slug.js',
                    'js/src/video-embed.js',
                    'js/src/geolocation.js',
                    'js/src/upload-files.js',
                    'js/src/upload-images.js',
                    'js/src/obj-sidebar.js',
                    'js/src/obj-files.js',
                    'js/src/obj-stack.js',
                    'js/src/obj-folders.js',
                ],
                dest: 'js/bolt.js',
            },
        },

        uglify: {
            bootstrap: {
                files: {
                    'js/bootstrap.js': [
                        'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/alert.js',
                        'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/button.js',
                        'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/dropdown.js',
                        'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/tab.js',
                        'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/transition.js',
                        'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/modal.js',
                        'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/tooltip.js',
                        'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/popover.js'
                    ]
                }
            }
        }

    });

    require('load-grunt-tasks')(grunt);

    grunt.registerTask('default', ['sass', 'concat:js', 'watch']);

};
<commit_msg>Moved start code to the end of bolt.js<commit_after>module.exports = function(grunt) {

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        config: grunt.file.readYAML('../config/config.yml'),

        watch: {
            options: {
                spawn: false,
                livereload: true
            },
            scripts: {
                files: ['sass/*.scss', 'sass/nav/*.scss'],
                tasks: ['sass'],
            },
            js: {
                files: ['js/*.js', 'js/src/*.js'],
                tasks: ['concat:js'],
            }
        },

        sass: {
            dist: {
                options: {
                    style: 'compressed',
                    loadPath: [
                        'node_modules/bootstrap-sass/assets/stylesheets/',
                        'node_modules/font-awesome/scss/'
                    ],
                    lineNumbers: false,
                    unixNewlines: true,
                    banner: "/**\n * These are Bolt's COMPILED CSS files! \n * Do not edit these files, because all changes will be lost. \n * You can edit ../scss/app.scss & ../scss/app-old-ie.scss, and run 'grunt' to generate this file. \n */"
                },
                files: {
                    'css/bolt-old-ie.css': 'sass/app-old-ie.scss',
                    'css/bolt.css': 'sass/app.scss'
                }
            }

        },

        copy: {
            main: {
                files: [
                    // includes files within path
                    {expand: true, flatten: true, src: ['node_modules/font-awesome/fonts/*'], dest: 'fonts/', filter: 'isFile'}
                ]
            }
        },

        // concat: {
        //     bootstrap: {
        //         src: [
        //             'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/alert.js',
        //             'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/button.js',
        //             'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/dropdown.js',
        //             'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/tab.js',
        //             'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/transition.js',
        //             'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/modal.js',
        //             'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/tooltip.js',
        //             'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/popover.js',
        //         ],
        //         dest: 'js/bootstrap-concat.js',
        //     },
        //     bolt: {
        //         // TODO: configure this.
        //         //src: ['src/main.js', 'src/extras.js'],
        //         //dest: 'dist/with_extras.js',
        //     },
        // },

        concat: {
            js: {
                src: [
                    'js/src/console.js',
                    'js/src/fnc-helpers.js',
                    'js/src/init-keyboard-shortcuts.js',
                    'js/src/init-ckeditor.js',
                    'js/src/activity.js',
                    'js/src/bind-fileupload.js',
                    'js/src/make-uri-slug.js',
                    'js/src/video-embed.js',
                    'js/src/geolocation.js',
                    'js/src/upload-files.js',
                    'js/src/upload-images.js',
                    'js/src/obj-sidebar.js',
                    'js/src/obj-files.js',
                    'js/src/obj-stack.js',
                    'js/src/obj-folders.js',
                    'js/src/start.js',
                ],
                dest: 'js/bolt.js',
            },
        },

        uglify: {
            bootstrap: {
                files: {
                    'js/bootstrap.js': [
                        'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/alert.js',
                        'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/button.js',
                        'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/dropdown.js',
                        'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/tab.js',
                        'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/transition.js',
                        'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/modal.js',
                        'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/tooltip.js',
                        'node_modules/bootstrap-sass/vendor/assets/javascripts/bootstrap/popover.js'
                    ]
                }
            }
        }

    });

    require('load-grunt-tasks')(grunt);

    grunt.registerTask('default', ['sass', 'concat:js', 'watch']);

};
<|endoftext|>


<commit_before>/**
 * This file shows an example of how to import data into a textus instance,
 * including setting up searchable bibliographic metadata. The data and metadata
 * are hard-coded into the file itself, obviously in a real case you'd be
 * loading these in from some external source.
 */
var conf = require('../js/textusConfiguration.js').conf();
var ds = require('../js/datastore/dataStore-elastic.js')(conf);
var markers = require('../public/js/markers.js');

/**
 * This is the data type required by the datastore's import operation
 */
var data = {
	text : [ {
		/*
		 * You can chunk the text at this point using the sequence property to
		 * determine in which order the chunks should be combined. They must be
		 * contiguous or nothing will work properly!
		 */
		text : "This is the text to be imported",
		sequence : 0
	} ],
	typography : [ {
		/*
		 * Each typography annotation consists of a start and end point and a
		 * css class name which will be applied to the resultant span. These may
		 * nest but may not partially overlap.
		 */
		start : 0,
		end : 9,
		css : "styleName"
	} ],
	semantics : [ {
		/*
		 * Semantic annotations carry common metadata plus a payload dependent
		 * on the type of the annotation. This one is a free text comment which
		 * is probably the simplest type of semantic annotation we can have.
		 */
		user : "tomoinn@gmail.com",
		type : "textus:comment",
		payload : {
			text : "This is a comment"
		},
		start : 31,
		end : 39,
		visibility : "private"
	}, {
		/* This is a tag, the other type textus knows about at the moment. */
		user : "tomoinn@gmail.com",
		type : "textus:tag",
		payload : {
			name : "name",
			value : "value"
		},
		start : 31,
		end : 39,
		visibility : "private"
	} ],
	/*
	 * This is an example of a metadata document. The metadata document has
	 * three roles: It determines the owners of the upload, those who will see
	 * it in their upload list and who can modify the bibliographic information.
	 * It defines a set of markers which contribute either or both of index
	 * information and BibJSON markup.
	 */
	metadata : {
		title : 'The title used in the upload list',
		markers : {
			// This marker applies at index 0
			marker0 : {
				label : 'start of the text',
				indexLevel : 0,
				discoverable : true,
				bibJson : {
					"title" : "Example import title",
					"author" : [ {
						"firstname" : "Firstname",
						"lastname" : "Lastname"
					} ],
					"year" : "Some year",
					"pages" : "1"
				}
			},
			// ...and this one at index 10
			marker10 : {
				// Label used in the index dropdown
				label : 'marker 2',
				// Value is >= 0 to appear in the index
				indexLevel : 1,
				// Discoverable set to false, marker doesn't appear in all texts
				// search view.
				disoverable : false,
				bibJson : {
				// Some BibJSON can go here
				}
			}
		},
		owners : [ 'someone@somewhere.com' ]
	}
};

ds.init(function() {
	ds.importData(data, function(err, textId) {
		if (err) {
			console.log("Failed to import!", err);
		} else {
			console.log("Imported text with id", textId);
		}
	});
});

<commit_msg>Removed redundant import<commit_after>/**
 * This file shows an example of how to import data into a textus instance,
 * including setting up searchable bibliographic metadata. The data and metadata
 * are hard-coded into the file itself, obviously in a real case you'd be
 * loading these in from some external source.
 */
var conf = require('../js/textusConfiguration.js').conf();
var ds = require('../js/datastore/dataStore-elastic.js')(conf);

/**
 * This is the data type required by the datastore's import operation
 */
var data = {
	text : [ {
		/*
		 * You can chunk the text at this point using the sequence property to
		 * determine in which order the chunks should be combined. They must be
		 * contiguous or nothing will work properly!
		 */
		text : "This is the text to be imported",
		sequence : 0
	} ],
	typography : [ {
		/*
		 * Each typography annotation consists of a start and end point and a
		 * css class name which will be applied to the resultant span. These may
		 * nest but may not partially overlap.
		 */
		start : 0,
		end : 9,
		css : "styleName"
	} ],
	semantics : [ {
		/*
		 * Semantic annotations carry common metadata plus a payload dependent
		 * on the type of the annotation. This one is a free text comment which
		 * is probably the simplest type of semantic annotation we can have.
		 */
		user : "tomoinn@gmail.com",
		type : "textus:comment",
		payload : {
			text : "This is a comment"
		},
		start : 31,
		end : 39,
		visibility : "private"
	}, {
		/* This is a tag, the other type textus knows about at the moment. */
		user : "tomoinn@gmail.com",
		type : "textus:tag",
		payload : {
			name : "name",
			value : "value"
		},
		start : 31,
		end : 39,
		visibility : "private"
	} ],
	/*
	 * This is an example of a metadata document. The metadata document has
	 * three roles: It determines the owners of the upload, those who will see
	 * it in their upload list and who can modify the bibliographic information.
	 * It defines a set of markers which contribute either or both of index
	 * information and BibJSON markup.
	 */
	metadata : {
		title : 'The title used in the upload list',
		markers : {
			// This marker applies at index 0
			marker0 : {
				label : 'start of the text',
				indexLevel : 0,
				discoverable : true,
				bibJson : {
					"title" : "Example import title",
					"author" : [ {
						"firstname" : "Firstname",
						"lastname" : "Lastname"
					} ],
					"year" : "Some year",
					"pages" : "1"
				}
			},
			// ...and this one at index 10
			marker10 : {
				// Label used in the index dropdown
				label : 'marker 2',
				// Value is >= 0 to appear in the index
				indexLevel : 1,
				// Discoverable set to false, marker doesn't appear in all texts
				// search view.
				disoverable : false,
				bibJson : {
				// Some BibJSON can go here
				}
			}
		},
		owners : [ 'someone@somewhere.com' ]
	}
};

ds.init(function() {
	ds.importData(data, function(err, textId) {
		if (err) {
			console.log("Failed to import!", err);
		} else {
			console.log("Imported text with id", textId);
		}
	});
});

<|endoftext|>


<commit_before>// Requires: crafty.js
// Requires: utils.js
// Requires: kongregate.js

var Game = {
	cols: 25,
	rows: 15,
	statusLines: 3,
	tileSize: 20,
	borderSize: 5,
	cellDelay: 500,
	speedDelta: 0.2,
}

Game.offset = Game.tileSize + Game.borderSize;
Game.w = Game.cols * Game.offset + Game.borderSize;
Game.h = (Game.rows + Game.statusLines) * Game.offset + Game.borderSize;

window.onload = function() {
	console.log("Starting Snake On A Slow Display...");
	Crafty.init(Game.w, Game.h);
	Kongregate.init();
	Crafty.background("#000000");
	Crafty.paths({"audio": "assets/", "images": "assets/"});
	Crafty.load({
		"audio": {
			"blip": ["blip.wav"],
			"tik": ["tik.wav"],
			"bloop": ["bloop.wav"],
		},
	}, function() {
		Crafty.bind("SceneChange", function(data) {console.log(data.newScene)});
		Crafty.scene("SetUp");
	});
};
<commit_msg>Prevent keys from moving the window<commit_after>// Requires: crafty.js
// Requires: utils.js
// Requires: kongregate.js

var Game = {
	cols: 25,
	rows: 15,
	statusLines: 3,
	tileSize: 20,
	borderSize: 5,
	cellDelay: 500,
	speedDelta: 0.2,
}

Game.offset = Game.tileSize + Game.borderSize;
Game.w = Game.cols * Game.offset + Game.borderSize;
Game.h = (Game.rows + Game.statusLines) * Game.offset + Game.borderSize;

window.addEventListener("keydown", function(e) {
    // ESC, SPACE and ARROW KEYS
    if([27, 32, 37, 38, 39, 40].indexOf(e.keyCode) > -1) {
        e.preventDefault();
    }
}, false);

window.onload = function() {
	console.log("Starting Snake On A Slow Display...");
	Crafty.init(Game.w, Game.h);
	Kongregate.init();
	Crafty.background("#000000");
	Crafty.paths({"audio": "assets/", "images": "assets/"});
	Crafty.load({
		"audio": {
			"blip": ["blip.wav"],
			"tik": ["tik.wav"],
			"bloop": ["bloop.wav"],
		},
	}, function() {
		Crafty.bind("SceneChange", function(data) {console.log(data.newScene)});
		Crafty.scene("SetUp");
	});
};
<|endoftext|>


<commit_before>var _ = require('underscore');
var async = require('async');
var stream = require('stream');

var Client = require('./client');

/**
 * Stack Class
 *
 * Manages a set of middlewares.
 *
 * @param {Function} errorHandler - function that handles all errors
 */
var Stack = function(errorHandler){
  this.middlewares = [];
  this.errorHandler = errorHandler;
};

/**
 * Add a middleware to the stack.
 *
 * @param middleware - and already instantiated middleware or object
 */
Stack.prototype.use = function(middleware) {
  middleware.stack = this;
  this.middlewares.push(middleware);
};

/**
 * Generates handler that takes streams as an input.
 *
 * @returns {Function}
 */
Stack.prototype.handler = function(){
  var self = this;

  return function(stream) {
    new Client(self, stream);
  }
};

/**
 * Install a client on all middlewares.
 *
 * @param client - the client that should be installed
 */
Stack.prototype.install = function(client) {
  _.each(this.middlewares, function(m){
    if(m.install) {
      m.install(client);
    }
  });
};

/**
 * Run the stack against a client and a single packet. This will be
 * automatically called with data from the underlying stream.
 *
 * @param client - the stream emitted the packet
 * @param packet - the packet that should be handled
 * @param done - to be called on finish
 */
Stack.prototype.process = function(client, packet, done) {
  var self = this;
  var l = this.middlewares.length;
  var i = -1;
  function next(err) {
    if(err) {
      return self.errorHandler(err, client, packet);
    } else {
      i++;
      if(i < l) {
        if(self.middlewares[i].handle) {
          return self.middlewares[i].handle(client, packet, next, done);
        } else {
          return next();
        }
      }
    }
  }
  next();
};

/**
 * Execute a function on all middlewares.
 *
 * @param fn - the name of the function
 * @param [data] - object passed as first argument
 * @param [store] - object passes as second argument (usefull to collect data)
 * @param [callback] - function to be called after finish
 */
Stack.prototype.execute = function(fn, data, store, callback){
  if(typeof store === 'function') {
    callback = store;
    store = null;
  }

  async.mapSeries(this.middlewares, function(m, cb){
    if(m[fn]) {
      if(store) {
        return m[fn](data, store, cb);
      } else {
        return m[fn](data, cb);
      }
    } else {
      return cb();
    }
  }, callback);
};

module.exports = Stack;
<commit_msg>no anonymous function = faster execution<commit_after>var _ = require('underscore');
var async = require('async');
var stream = require('stream');

var Client = require('./client');

/**
 * Stack Class
 *
 * Manages a set of middlewares.
 *
 * @param {Function} errorHandler - function that handles all errors
 */
var Stack = function(errorHandler){
  this.middlewares = [];
  this.errorHandler = errorHandler;
};

/**
 * Add a middleware to the stack.
 *
 * @param middleware - and already instantiated middleware or object
 */
Stack.prototype.use = function(middleware) {
  middleware.stack = this;
  this.middlewares.push(middleware);
};

/**
 * Generates handler that takes streams as an input.
 *
 * @returns {Function}
 */
Stack.prototype.handler = function(){
  var self = this;

  return function(stream) {
    new Client(self, stream);
  }
};

/**
 * Install a client on all middlewares.
 *
 * @param client - the client that should be installed
 */
Stack.prototype.install = function(client) {
  _.each(this.middlewares, function(m){
    if(m.install) {
      m.install(client);
    }
  });
};

/**
 * Run the stack against a client and a single packet. This will be
 * automatically called with data from the underlying stream.
 *
 * @param client - the stream emitted the packet
 * @param packet - the packet that should be handled
 * @param done - to be called on finish
 */
Stack.prototype.process = function(client, packet, done) {
  var self = this;
  var l = this.middlewares.length;
  var i = -1;
  function next(err) {
    if(err) {
      return self.errorHandler(err, client, packet);
    } else {
      i++;
      if(i < l) {
        if(self.middlewares[i].handle) {
          return self.middlewares[i].handle(client, packet, next, done);
        } else {
          return next();
        }
      }
    }
  }
  next();
};

/**
 * Execute a function on all middlewares.
 *
 * @param fn - the name of the function
 * @param [data] - object passed as first argument
 * @param [store] - object passes as second argument (usefull to collect data)
 * @param [callback] - function to be called after finish
 */
Stack.prototype.execute = function(fn, data, store, callback){
  if(typeof store === 'function') {
    callback = store;
    store = null;
  }

  this._execute_fn = fn;
  this._execute_data = data;
  this._execute_store = store;

  async.mapSeries(this.middlewares, this._execute.bind(this), callback);
};

/**
 * Exeucte a single task on a middleware
 *
 * @param m
 * @param cb
 * @private
 */
Stack.prototype._execute = function(m, cb) {
  if(m[this._execute_fn]) {
    if(this._execute_store) {
      return m[this._execute_fn](this._execute_data, this._execute_store, cb);
    } else {
      return m[this._execute_fn](this._execute_data, cb);
    }
  } else {
    return cb();
  }
};

module.exports = Stack;
<|endoftext|>


<commit_before>// adopted from: ilog <https://github.com/teambition/ilog>
// Copyright (c) 2015 Teambition (License: MIT)

'use strict'

const format = require('util').format
const jlog   = require('../util/jcolorz')
const ccase  = require('../string/sentenceCase')
const map    = require('../array/map')
const slice  = require('../array/slice')

const levels = [
  'FATAL',    // level 0
  'CRITICAL', // level 1
  'ERROR',    // level 2
  'WARNING',  // level 3
  'ALERT',    // level 4
  'NOTICE',   // level 5
  'INFO',     // level 6
  'DEBUG'     // level 7
]

const clrs = {
  black   : [30, 39],
  gray    : [90, 39],
  grey    : [90, 39],
  red     : [31, 39],
  green   : [32, 39],
  yellow  : [33, 39],
  blue    : [34, 39],
  magenta : [35, 39],
  cyan    : [36, 39],
  white   : [37, 39]
}

// Original version
function ilog () {
  if (arguments.length) {
    ilog._stdout.write(ilog._assembleLog(format.apply(null, arguments)))
  }
}

// Own version: meant for raw string output to log
ilog.log = function () {
  if (arguments.length) {
    ilog._stdout.write(ilog._assembleLog(slice(arguments).join(' ')))
  }
}

// options for display, preserving the original functionality by reversing values.
ilog.display = {
  colors: true,
  dates: false
}

// ilog.level === -1 turns off all levels
// ilog.level === -2 turns on debug logging only
// ilog.level === -3 turns on debug and trace logging
ilog.level = 7
ilog.levels = levels.slice()

// ilog.fatal, ilog.critical, ilog.error, ilog.warning, ilog.alert
map(levels.slice(0, 5), (level, index) => {
  ilog[level.toLowerCase()] = function (error, stack) {
    if (error != null && index <= ilog.level) {
      // allow the ability to pass debugging messages as strings
      if (typeof error === 'string') error = {message: error}
      if (stack) error.stack = ilog._errorify(stack)

      error.name = ccase(level)

      let color = ilog.display.colors ? ilog._color(level, 'red') : level
      let label = ilog.display.dates ? ilog._label(new Date()) : ilog._label()

      error = ilog.display.colors
        ? ilog._errorify(error)
        : ilog._stringify(ilog._errorify(error))

      let type = function (obj) {
        return typeof obj === 'string'
          ? obj
          : obj.message
      }

      ilog._stderr.write(ilog._assembleLog(type(error), color, label))
      if (ilog.display.colors) jlog(error)
    }
  }
})

// ilog.notice, ilog.info
map(levels.slice(5, 7), (level, index) => {
  index += 5
  ilog[level.toLowerCase()] = function (message) {
    if (message != null && index <= ilog.level) {
      message = ilog._stringify(message)

      let color = ilog.display.colors ? ilog._color(level, 'grey') : level
      let label = ilog.display.dates ? ilog._label(new Date()) : ilog._label()

      ilog._stdout.write(ilog._assembleLog(message, color, label))
    }
  }
})

ilog.debug = function () {
  if (arguments.length && (ilog.level >= 7 || ilog.level <= -2)) {
    let messages

    if (arguments.length === 1) {
      messages = ilog._stringify(arguments[0])
    }

    else if (arguments.length === 2
      && typeof arguments[1] === 'object'
      && 'name' in arguments[1]
      && 'message' in arguments[1]
    ) {
      messages = arguments[0]
      var stack = {
        name: 'Debug',
        message: arguments[0],
        stack: ilog._errorify(arguments[1])
      }
    }

    else messages = format.apply(null, arguments)

    let color = ilog.display.colors
      ? ilog._color('DEBUG', 'blue')
      : 'DEBUG'

    let label = ilog.display.dates
      ? ilog._label(new Date())
      : ilog._label()

    ilog._stdout.write(ilog._assembleLog(messages, color, label))
    if (ilog.display.colors && stack) jlog(stack)
  }
}

ilog.trace = function () {
  if (arguments.length && (ilog.level >= 8 || ilog.level <= -3)) {
    // contruct components
    let messages = format.apply(null, arguments)
    let color = ilog.display.colors ? ilog._color('LOGR', 'yellow') : 'LOGR'
    let label = ilog.display.dates ? ilog._label(new Date()) : ilog._label()

    // compose message
    let assemble = ilog._assembleLog(messages, color, label)

    // log message
    ilog._stdout.write(assemble)
  }
}

ilog.assert = function (expression, label) {
  let title = 'Assertion expression'
  let stack = {
    name: 'Assert',
    message: label,
    result: !!expression
  }

  ilog.debug(title, stack)
}

ilog.auto = function (error) {
  if (error instanceof Error) return ilog.error(error)
  let args = slice(arguments, +(error == null))
  if (args.length === 1) ilog.info(args[0])
  else if (args.length > 1) ilog.debug.apply(null, args)
}

// expose json-colorz
ilog.jclr = function () {
  map(slice(arguments), (arg) => {
    jlog(arg)
  })
}

ilog._stdout = process.stdout
ilog._stderr = process.stderr
ilog._procname = process.argv[1].split('/').pop()
ilog._pointer = {
  tick: '✔',
  check: '√',
  cross: '✖',
  star: '★',
  bullet: '*',
  info: 'i',
  info2: 'ℹ',
  warning: '‼',
  warning2: '⚠',
  clip: '❯',
  single: '›',
  double: '»',
  arrowUp: '↑',
  arrowDown: '↓',
  arrowLeft: '←',
  arrowRight: '→',
  radioOn: '◉',
  radioOff: '◯',
}

ilog._color = function (label, color) {
  return `\u001b[${clrs[color][0]}m${label}\u001b[${clrs[color][1]}m`
}

ilog._label = function (label) {
  return `${ilog._procname} ${ilog._pointer.double}`
}

ilog._assembleLog = function (log, level, label) {
  if (level) log = `${level} ${log}`
  if (label) log = `${label} ${log}\n`
  else log = `${ilog._label()} ${log}\n`

  return log
}

ilog._stringify = function (obj) {
  try {
    return JSON.stringify(obj)
  } catch (e) {
    return format(obj)
  }
}

ilog._errorify = function (error) {
  return new Errorify(error)
}

function Errorify (error) {
  this.name = error.name || 'Error'
  this.message = error.message || format(error)

  if (error.code) this.code = error.code
  if (error.errno) this.errno = error.errno
  if (error.status) this.status = error.status
  if (error.syscall) this.syscall = error.syscall
  if (!Array.isArray(error)) {
    Object.keys(error).map((key) => {
      if (!this[key]) this[key] = error[key]
    })
  }
  if (error.stack) this.stack = error.stack
}

module.exports = ilog
<commit_msg>update debug/ilog -- argument check for ilog.log()<commit_after>// adopted from: ilog <https://github.com/teambition/ilog>
// Copyright (c) 2015 Teambition (License: MIT)

'use strict'

const format = require('util').format
const jlog   = require('../util/jcolorz')
const ccase  = require('../string/sentenceCase')
const map    = require('../array/map')
const slice  = require('../array/slice')

const levels = [
  'FATAL',    // level 0
  'CRITICAL', // level 1
  'ERROR',    // level 2
  'WARNING',  // level 3
  'ALERT',    // level 4
  'NOTICE',   // level 5
  'INFO',     // level 6
  'DEBUG'     // level 7
]

const clrs = {
  black   : [30, 39],
  gray    : [90, 39],
  grey    : [90, 39],
  red     : [31, 39],
  green   : [32, 39],
  yellow  : [33, 39],
  blue    : [34, 39],
  magenta : [35, 39],
  cyan    : [36, 39],
  white   : [37, 39]
}

// Original version
function ilog () {
  if (arguments.length) {
    ilog._stdout.write(ilog._assembleLog(format.apply(null, arguments)))
  }
}

// Own version: meant for raw string output to log
ilog.log = function () {
  // don't penalize a single string/template being passed as a param
  arguments.length > 1
    ? ilog._stdout.write(ilog._assembleLog(slice(arguments).join(' ')))
    : ilog._stdout.write(ilog._assembleLog(arguments[0]))
}

// options for display, preserving the original functionality by reversing values.
ilog.display = {
  colors: true,
  dates: false
}

// ilog.level === -1 turns off all levels
// ilog.level === -2 turns on debug logging only
// ilog.level === -3 turns on debug and trace logging
ilog.level = 7
ilog.levels = levels.slice()

// ilog.fatal, ilog.critical, ilog.error, ilog.warning, ilog.alert
map(levels.slice(0, 5), (level, index) => {
  ilog[level.toLowerCase()] = function (error, stack) {
    if (error != null && index <= ilog.level) {
      // allow the ability to pass debugging messages as strings
      if (typeof error === 'string') error = {message: error}
      if (stack) error.stack = ilog._errorify(stack)

      error.name = ccase(level)

      let color = ilog.display.colors ? ilog._color(level, 'red') : level
      let label = ilog.display.dates ? ilog._label(new Date()) : ilog._label()

      error = ilog.display.colors
        ? ilog._errorify(error)
        : ilog._stringify(ilog._errorify(error))

      let type = function (obj) {
        return typeof obj === 'string'
          ? obj
          : obj.message
      }

      ilog._stderr.write(ilog._assembleLog(type(error), color, label))
      if (ilog.display.colors) jlog(error)
    }
  }
})

// ilog.notice, ilog.info
map(levels.slice(5, 7), (level, index) => {
  index += 5
  ilog[level.toLowerCase()] = function (message) {
    if (message != null && index <= ilog.level) {
      message = ilog._stringify(message)

      let color = ilog.display.colors ? ilog._color(level, 'grey') : level
      let label = ilog.display.dates ? ilog._label(new Date()) : ilog._label()

      ilog._stdout.write(ilog._assembleLog(message, color, label))
    }
  }
})

ilog.debug = function () {
  if (arguments.length && (ilog.level >= 7 || ilog.level <= -2)) {
    let messages

    if (arguments.length === 1) {
      messages = ilog._stringify(arguments[0])
    }

    else if (arguments.length === 2
      && typeof arguments[1] === 'object'
      && 'name' in arguments[1]
      && 'message' in arguments[1]
    ) {
      messages = arguments[0]
      var stack = {
        name: 'Debug',
        message: arguments[0],
        stack: ilog._errorify(arguments[1])
      }
    }

    else messages = format.apply(null, arguments)

    let color = ilog.display.colors
      ? ilog._color('DEBUG', 'blue')
      : 'DEBUG'

    let label = ilog.display.dates
      ? ilog._label(new Date())
      : ilog._label()

    ilog._stdout.write(ilog._assembleLog(messages, color, label))
    if (ilog.display.colors && stack) jlog(stack)
  }
}

ilog.trace = function () {
  if (arguments.length && (ilog.level >= 8 || ilog.level <= -3)) {
    // contruct components
    let messages = format.apply(null, arguments)
    let color = ilog.display.colors ? ilog._color('LOGR', 'yellow') : 'LOGR'
    let label = ilog.display.dates ? ilog._label(new Date()) : ilog._label()

    // compose message
    let assemble = ilog._assembleLog(messages, color, label)

    // log message
    ilog._stdout.write(assemble)
  }
}

ilog.assert = function (expression, label) {
  let title = 'Assertion expression'
  let stack = {
    name: 'Assert',
    message: label,
    result: !!expression
  }

  ilog.debug(title, stack)
}

ilog.auto = function (error) {
  if (error instanceof Error) return ilog.error(error)
  let args = slice(arguments, +(error == null))
  if (args.length === 1) ilog.info(args[0])
  else if (args.length > 1) ilog.debug.apply(null, args)
}

// expose json-colorz
ilog.jclr = function () {
  map(slice(arguments), (arg) => {
    jlog(arg)
  })
}

ilog._stdout = process.stdout
ilog._stderr = process.stderr
ilog._procname = process.argv[1].split('/').pop()
ilog._pointer = {
  tick: '✔',
  check: '√',
  cross: '✖',
  star: '★',
  bullet: '*',
  info: 'i',
  info2: 'ℹ',
  warning: '‼',
  warning2: '⚠',
  clip: '❯',
  single: '›',
  double: '»',
  arrowUp: '↑',
  arrowDown: '↓',
  arrowLeft: '←',
  arrowRight: '→',
  radioOn: '◉',
  radioOff: '◯',
}

ilog._color = function (label, color) {
  return `\u001b[${clrs[color][0]}m${label}\u001b[${clrs[color][1]}m`
}

ilog._label = function (label) {
  return `${ilog._procname} ${ilog._pointer.double}`
}

ilog._assembleLog = function (log, level, label) {
  if (level) log = `${level} ${log}`
  if (label) log = `${label} ${log}\n`
  else log = `${ilog._label()} ${log}\n`

  return log
}

ilog._stringify = function (obj) {
  try {
    return JSON.stringify(obj)
  } catch (e) {
    return format(obj)
  }
}

ilog._errorify = function (error) {
  return new Errorify(error)
}

function Errorify (error) {
  this.name = error.name || 'Error'
  this.message = error.message || format(error)

  if (error.code) this.code = error.code
  if (error.errno) this.errno = error.errno
  if (error.status) this.status = error.status
  if (error.syscall) this.syscall = error.syscall
  if (!Array.isArray(error)) {
    Object.keys(error).map((key) => {
      if (!this[key]) this[key] = error[key]
    })
  }
  if (error.stack) this.stack = error.stack
}

module.exports = ilog
<|endoftext|>


<commit_before>var color = require('cli-color');

var spawn = require('child_process').spawn;
var logging = require('../logging');

// gitClient errors and functions
var errors = require('./errors');
var gitFunctions = require('./functions');

/**
 * @reexport UnknownGitOption
 */

var UnknownGitOption = exports.UnknownGitOption = errors.UnknownGitOption;

/**
 * @reexport UnknownGitRevision
 */

var UnknownGitRevision = exports.UnknownGitRevision = errors.UnknownGitRevision;

/**
 * @reexport FatalGitError
 */

var FatalGitError = exports.FatalGitError = errors.FatalGitError;

/**
 * Spawn a git process with a logger. Reject non zero exit codes with
 * appropriate error types.
 *
 * @return {Promise}
 */

function spawnWithLogger(args, opts, cb) {

  // defaults
  opts = merge(opts, {silent: true, buffer: true});

  var name = 'git';
  var buffers;
  if (opts.buffer || opts.silent) {
    buffers = {stdout: [], stderr: []};
  }

  if (!args[0]) {
    throw new Error('no git command provided');
  }

  var logger = logging.get(name, opts.silent, buffers);

  if (!opts.extraSilent) {
    logger.log(color.yellow('-> ' + args.join(' ')));
  }

  if (!opts.stdio) {
    opts.stdio = [process.stdin, 'pipe', 'pipe'];
  }

  var logErrorContext = function () {
    logger.error('[child process error]', name, args.join(' '));
  };

  var ranCallback = false;
  var child = spawn(name, args, {stdio: opts.stdio, cwd: opts.cwd});
  child.stdout && child.stdout.pipe(logger.stdout, {end: false});
  child.stderr && child.stderr.pipe(logger.stderr, {end: false});

  return new Promise(function (resolve, reject) {
    child.on('close', function (code) {
      var stdout = buffers && buffers.stdout.join('');
      var stderr = buffers && buffers.stderr.join('');

      if (!ranCallback) {
        ranCallback = true;
        if (code === 0) {
          return resolve(stdout);
        }

        var cmd = name + ' ' + args.join(' ');
        if (code === 128) {
          reject(new FatalGitError('during `' + cmd + '`: ' + stderr));
        } else if (code === 129) {
          reject(new UnknownGitOption('during `' + cmd + '`: ' + stderr));
        } else {
          reject({code: code, stderr: stderr});
        }
      }
    });

    child.on('error', function (err) {
      logErrorContext();
      if (!ranCallback) {
        ranCallback = true;
        if (!(err instanceof Error)) {
          err = new Error(err);
        }
        reject(err);
      }
    });
  }).nodeify(cb);
}

/**
 * opts:
 *   - buffer: capture stdout to an array
 *   - silent: don't print to screen
 *   - stdio: custom io handling forwarded to child_process.spawn
 */
exports.get = function (dir, opts) {
  opts = merge(opts, {cwd: dir});

  var client = function () {
    var last = arguments.length - 1;
    var singleOpts = arguments[last - 1];
    var cb = arguments[last];

    if (typeof cb !== 'function') {
      singleOpts = cb;
      cb = void 0;
      last++;
    }

    if (typeof singleOpts === 'object') {
      singleOpts = merge({}, singleOpts, opts);
      --last;
    } else {
      singleOpts = merge({}, opts);
    }

    // TODO fix arguments allocation
    var args = Array.prototype.slice.call(arguments, 0, last);
    return spawnWithLogger(args, singleOpts, cb);
  };

  for (var functionName in gitFunctions) {
    client[functionName] = gitFunctions[functionName];
  }

  return client;
};

<commit_msg>log cwd in FatalGitError case for easier debugging<commit_after>var color = require('cli-color');

var spawn = require('child_process').spawn;
var logging = require('../logging');

// gitClient errors and functions
var errors = require('./errors');
var gitFunctions = require('./functions');

/**
 * @reexport UnknownGitOption
 */

var UnknownGitOption = exports.UnknownGitOption = errors.UnknownGitOption;

/**
 * @reexport UnknownGitRevision
 */

var UnknownGitRevision = exports.UnknownGitRevision = errors.UnknownGitRevision;

/**
 * @reexport FatalGitError
 */

var FatalGitError = exports.FatalGitError = errors.FatalGitError;

/**
 * Spawn a git process with a logger. Reject non zero exit codes with
 * appropriate error types.
 *
 * @return {Promise}
 */

function spawnWithLogger(args, opts, cb) {

  // defaults
  opts = merge(opts, {silent: true, buffer: true});

  var name = 'git';
  var buffers;
  if (opts.buffer || opts.silent) {
    buffers = {stdout: [], stderr: []};
  }

  if (!args[0]) {
    throw new Error('no git command provided');
  }

  var logger = logging.get(name, opts.silent, buffers);

  if (!opts.extraSilent) {
    logger.log(color.yellow('-> ' + args.join(' ')));
  }

  if (!opts.stdio) {
    opts.stdio = [process.stdin, 'pipe', 'pipe'];
  }

  var logErrorContext = function () {
    logger.error('[child process error]', name, args.join(' '));
  };

  var ranCallback = false;
  var child = spawn(name, args, {stdio: opts.stdio, cwd: opts.cwd});
  child.stdout && child.stdout.pipe(logger.stdout, {end: false});
  child.stderr && child.stderr.pipe(logger.stderr, {end: false});

  return new Promise(function (resolve, reject) {
    child.on('close', function (code) {
      var stdout = buffers && buffers.stdout.join('');
      var stderr = buffers && buffers.stderr.join('');

      if (!ranCallback) {
        ranCallback = true;
        if (code === 0) {
          return resolve(stdout);
        }

        var cmd = name + ' ' + args.join(' ');
        if (code === 128) {
          var msg = 'during `' + cmd + ' (' + opts.cwd + ')`: ' + stderr;
          reject(new FatalGitError(msg));
        } else if (code === 129) {
          reject(new UnknownGitOption('during `' + cmd + '`: ' + stderr));
        } else {
          reject({code: code, stderr: stderr});
        }
      }
    });

    child.on('error', function (err) {
      logErrorContext();
      if (!ranCallback) {
        ranCallback = true;
        if (!(err instanceof Error)) {
          err = new Error(err);
        }
        reject(err);
      }
    });
  }).nodeify(cb);
}

/**
 * opts:
 *   - buffer: capture stdout to an array
 *   - silent: don't print to screen
 *   - stdio: custom io handling forwarded to child_process.spawn
 */
exports.get = function (dir, opts) {
  opts = merge(opts, {cwd: dir});

  var client = function () {
    var last = arguments.length - 1;
    var singleOpts = arguments[last - 1];
    var cb = arguments[last];

    if (typeof cb !== 'function') {
      singleOpts = cb;
      cb = void 0;
      last++;
    }

    if (typeof singleOpts === 'object') {
      singleOpts = merge({}, singleOpts, opts);
      --last;
    } else {
      singleOpts = merge({}, opts);
    }

    // TODO fix arguments allocation
    var args = Array.prototype.slice.call(arguments, 0, last);
    return spawnWithLogger(args, singleOpts, cb);
  };

  for (var functionName in gitFunctions) {
    client[functionName] = gitFunctions[functionName];
  }

  return client;
};

<|endoftext|>


<commit_before>const util = require('./util')
const time = require('./time')
const fs = require('fs')
const path = require('path')
const Updater = require('./updater')
const Display = require("./display")
const idGenerator = require('./id-generator')
const child_process = require('child_process')

const config = require('./updater-config').loadConfig()

let errorMessage = null

if (config.simulate) {
  console.log("simulate == true, so I will only pretend to execute local update scripts.")
}

function checkForUpdate() {
  display.showNetworkConnecting()
  updater.checkForUpdateAndTellHubHowItWorkedOut()
    .then((result) => {
      display.showNetworkOk()
      console.log("Update check completed. ", result)
      checkUpdateInterval(result.newUpdateInterval)

      console.log("Waiting " + config.updateIntervalSeconds + " seconds until next update check...")
      setTimeout(checkForUpdate, config.updateIntervalSeconds * 1000)

    })
    .catch((err) => {
      if (err.networkError) {
        display.showNetworkError(err)
      }
      if (err.updateError) {
        display.showUpdateError(err)
      }

      console.log("Waiting " + config.updateIntervalSeconds + " seconds until next update check...")
      setTimeout(checkForUpdate, config.updateIntervalSeconds * 1000)
    })
}

/**
 * Notifies me that updating is currently in progress.
 * So I'll show a progress bar.
 */
function onUpdating(updating) {
  if (updating) {
    display.showUpdating()
  } else {
    display.showUpdateDone()
  }
}

function truncate(string, toLength) {
  return string.substring(0, toLength)
}

function displayStatus(statusRow1, statusRow2, errorMessage) {
  const row = 9
  const col = 0

  if (statusRow1) {
    display.call("writeText", [statusRow1 + "        ", row, col, false, config.mainDisplayTab])
  }
  if (statusRow2) {
    display.call("writeText", [statusRow2 + "        ", row + 1, col, false, config.mainDisplayTab])
  }
}

function displayError(errorMessage) {
  display.call("writeText", [errorMessage])
}

function checkUpdateInterval(newUpdateInterval) {
  if (newUpdateInterval) {
    try {
      newUpdateInterval = parseInt(newUpdateInterval)
      if (newUpdateInterval < config.minUpdateIntervalSeconds) {
        newUpdateInterval = config.minUpdateIntervalSeconds
      }
      if (newUpdateInterval > config.maxUpdateIntervalSeconds) {
        newUpdateInterval = config.maxUpdateIntervalSeconds
      }
      config.updateIntervalSeconds = newUpdateInterval
      console.log("Setting update interval to " + config.updateIntervalSeconds + " seconds")
    } catch (err) {
      console.log("Something went wrong while parsing newUpdateInterval (ignoring it and moving on)", newUpdateInterval, err)
    }

  }

}

function readDeviceId() {
  const deviceIdFile = path.join(config.rootDir, "device-id")
  let deviceId
  if (fs.existsSync(deviceIdFile)) {
    deviceId = fs.readFileSync(deviceIdFile).toString()
  } else {
    deviceId = generateDeviceIdAndSave()
  }
  return deviceId
}

function generateDeviceIdAndSave() {
  const deviceIdFile = path.join(config.rootDir, "device-id")
  const deviceId = idGenerator.generateRandomId(config.deviceIdLength)
  fs.writeFileSync(deviceIdFile, deviceId)
  console.log("Created " + deviceIdFile + " with ID " + deviceId)
  if (config.scriptToCallWhenDeviceIdHasBeenSet) {
    console.log("Will execute script: ", config.scriptToCallWhenDeviceIdHasBeenSet)
    try {
      const scriptWithArgument = config.scriptToCallWhenDeviceIdHasBeenSet + " " + deviceId
      child_process.exec(scriptWithArgument)
      console.log("Sucessfully executed script " + scriptWithArgument)
    } catch (err) {
      console.log("Failed to execute script " + scriptWithArgument, err)
    }

  }

  return deviceId
}

function createRootDirIfMissing() {
  if (!fs.existsSync(config.rootDir)) {
    fs.mkdirSync(config.rootDir)
    console.log("Created root dir: " + config.rootDir)
  }
}

function startDisplayResendLoop(display) {
  if (config.displayResendIntervalSeconds && config.displayRpcPort) {
    setInterval(function() {
      display.resendStatusToDisplayIfLastAttemptFailed()
    }, config.displayResendIntervalSeconds * 1000)
  }
}

function setSystemClock() {
  time.syncSystemClockWithServer(config.hubUrl)
}

createRootDirIfMissing()

const deviceId = readDeviceId()

const options = {
  updateScriptTimeoutSeconds: config.updateScriptTimeoutSeconds,
  simulate: config.simulate,
  sshTunnelCommand: config.sshTunnelCommand,
  onUpdating: onUpdating
}
const updater = new Updater(config.rootDir, config.hubUrl, options)

const display = new Display(deviceId, config.displayRpcPort, config.mainDisplayTab, config.networkInfoDisplayTab, config.logDisplayCalls)
startDisplayResendLoop(display)

display.showDeviceId()

setSystemClock()

checkForUpdate()

<commit_msg>Removed unused code<commit_after>const util = require('./util')
const time = require('./time')
const fs = require('fs')
const path = require('path')
const Updater = require('./updater')
const Display = require("./display")
const idGenerator = require('./id-generator')
const child_process = require('child_process')

const config = require('./updater-config').loadConfig()

let errorMessage = null

if (config.simulate) {
  console.log("simulate == true, so I will only pretend to execute local update scripts.")
}

function checkForUpdate() {
  display.showNetworkConnecting()
  updater.checkForUpdateAndTellHubHowItWorkedOut()
    .then((result) => {
      display.showNetworkOk()
      console.log("Update check completed. ", result)
      checkUpdateInterval(result.newUpdateInterval)

      console.log("Waiting " + config.updateIntervalSeconds + " seconds until next update check...")
      setTimeout(checkForUpdate, config.updateIntervalSeconds * 1000)

    })
    .catch((err) => {
      if (err.networkError) {
        display.showNetworkError(err)
      }
      if (err.updateError) {
        display.showUpdateError(err)
      }

      console.log("Waiting " + config.updateIntervalSeconds + " seconds until next update check...")
      setTimeout(checkForUpdate, config.updateIntervalSeconds * 1000)
    })
}

/**
 * Notifies me that updating is currently in progress.
 * So I'll show a progress bar.
 */
function onUpdating(updating) {
  if (updating) {
    display.showUpdating()
  } else {
    display.showUpdateDone()
  }
}

function checkUpdateInterval(newUpdateInterval) {
  if (newUpdateInterval) {
    try {
      newUpdateInterval = parseInt(newUpdateInterval)
      if (newUpdateInterval < config.minUpdateIntervalSeconds) {
        newUpdateInterval = config.minUpdateIntervalSeconds
      }
      if (newUpdateInterval > config.maxUpdateIntervalSeconds) {
        newUpdateInterval = config.maxUpdateIntervalSeconds
      }
      config.updateIntervalSeconds = newUpdateInterval
      console.log("Setting update interval to " + config.updateIntervalSeconds + " seconds")
    } catch (err) {
      console.log("Something went wrong while parsing newUpdateInterval (ignoring it and moving on)", newUpdateInterval, err)
    }

  }

}

function readDeviceId() {
  const deviceIdFile = path.join(config.rootDir, "device-id")
  let deviceId
  if (fs.existsSync(deviceIdFile)) {
    deviceId = fs.readFileSync(deviceIdFile).toString()
  } else {
    deviceId = generateDeviceIdAndSave()
  }
  return deviceId
}

function generateDeviceIdAndSave() {
  const deviceIdFile = path.join(config.rootDir, "device-id")
  const deviceId = idGenerator.generateRandomId(config.deviceIdLength)
  fs.writeFileSync(deviceIdFile, deviceId)
  console.log("Created " + deviceIdFile + " with ID " + deviceId)
  if (config.scriptToCallWhenDeviceIdHasBeenSet) {
    console.log("Will execute script: ", config.scriptToCallWhenDeviceIdHasBeenSet)
    try {
      const scriptWithArgument = config.scriptToCallWhenDeviceIdHasBeenSet + " " + deviceId
      child_process.exec(scriptWithArgument)
      console.log("Sucessfully executed script " + scriptWithArgument)
    } catch (err) {
      console.log("Failed to execute script " + scriptWithArgument, err)
    }

  }

  return deviceId
}

function createRootDirIfMissing() {
  if (!fs.existsSync(config.rootDir)) {
    fs.mkdirSync(config.rootDir)
    console.log("Created root dir: " + config.rootDir)
  }
}

function startDisplayResendLoop(display) {
  if (config.displayResendIntervalSeconds && config.displayRpcPort) {
    setInterval(function() {
      display.resendStatusToDisplayIfLastAttemptFailed()
    }, config.displayResendIntervalSeconds * 1000)
  }
}

function setSystemClock() {
  time.syncSystemClockWithServer(config.hubUrl)
}

createRootDirIfMissing()

const deviceId = readDeviceId()

const options = {
  updateScriptTimeoutSeconds: config.updateScriptTimeoutSeconds,
  simulate: config.simulate,
  sshTunnelCommand: config.sshTunnelCommand,
  onUpdating: onUpdating
}
const updater = new Updater(config.rootDir, config.hubUrl, options)

const display = new Display(deviceId, config.displayRpcPort, config.mainDisplayTab, config.networkInfoDisplayTab, config.logDisplayCalls)
startDisplayResendLoop(display)

display.showDeviceId()

setSystemClock()

checkForUpdate()

<|endoftext|>


<commit_before>const {EditorState, Plugin} = require("prosemirror-state")
const {Decoration, DecorationSet} = require("prosemirror-view")
const {MenuBarEditorView} = require("prosemirror-menu")
const {Mapping} = require("prosemirror-transform")
const {schema} = require("prosemirror-schema-basic")
const {exampleSetup} = require("prosemirror-example-setup")
const crel = require("crel")

const trackPlugin = new Plugin({
  state: {
    init(_, instance) {
      return new TrackState([new Span(0, instance.doc.content.size, null)], [], [], [])
    },
    applyAction(action, tracked) {
      if (action.type == "transform")
        return tracked.applyTransform(action.transform)
      if (action.type == "commit")
        return tracked.applyCommit(action.message, action.time)
      else
        return tracked
    }
  }
})

const highlightPlugin = new Plugin({
  state: {
    init() { return {deco: DecorationSet.empty, commit: null} },
    applyAction(action, prev, state) {
      if (action.type == "highlightCommit" && prev.commit != action.commit) {
        let tState = trackPlugin.getState(state)
        let decos = tState.blameMap
            .filter(span => tState.commits[span.commit] == action.commit)
            .map(span => Decoration.inline(span.from, span.to, {class: "blame-marker"}))
        return {deco: DecorationSet.create(state.doc, decos), commit: action.commit}
      } else if (action.type == "clearHighlight" && prev.commit == action.commit) {
        return {deco: DecorationSet.empty, commit: null}
      } else if (action.type == "transform" && prev.commit) {
        return {deco: prev.deco.map(action.transform.mapping, action.transform.doc), commit: prev.commit}
      } else {
        return prev
      }
    }
  },
  props: {
    decorations(state) { return this.getState(state).deco }
  }
})

class Span {
  constructor(from, to, commit) {
    this.from = from; this.to = to; this.commit = commit
  }
}

class Commit {
  constructor(message, time, steps, maps, hidden) {
    this.message = message
    this.time = time
    this.steps = steps
    this.maps = maps
    this.hidden = hidden
  }
}

class TrackState {
  constructor(blameMap, commits, uncommittedSteps, uncommittedMaps) {
    this.blameMap = blameMap
    this.commits = commits
    this.uncommittedSteps = uncommittedSteps
    this.uncommittedMaps = uncommittedMaps
  }

  applyTransform(transform) {
    let inverted = transform.steps.map((step, i) => step.invert(transform.docs[i]))
    return new TrackState(updateBlameMap(this.blameMap, transform, this.commits.length),
                          this.commits,
                          this.uncommittedSteps.concat(inverted),
                          this.uncommittedMaps.concat(transform.mapping.maps))
  }

  applyCommit(message, time) {
    if (this.uncommittedSteps.length == 0) return this
    let commit = new Commit(message, time, this.uncommittedSteps, this.uncommittedMaps)
    return new TrackState(this.blameMap, this.commits.concat(commit), [], [])
  }
}

function updateBlameMap(map, transform, id) {
  let result = [], mapping = transform.mapping
  for (let i = 0; i < map.length; i++) {
    let span = map[i]
    let from = mapping.map(span.from, 1), to = mapping.map(span.to, -1)
    if (from < to) result.push(new Span(from, to, span.commit))
  }

  for (let i = 0; i < mapping.maps.length; i++) {
    let map = mapping.maps[i], after = mapping.slice(i + 1)
    map.forEach((_s, _e, start, end) => {
      insertIntoBlameMap(result, after.map(start, 1), after.map(end, -1), id)
    })
  }

  return result
}

function insertIntoBlameMap(map, from, to, commit) {
  if (from >= to) return
  let pos = 0, next
  for (; pos < map.length; pos++) {
    next = map[pos]
    if (next.commit == commit) {
      if (next.to >= from) break
    } else if (next.to > from) { // Different commit, not before
      if (next.from < from) { // Sticks out to the left (loop below will handle right side)
        let left = new Span(next.from, from, next.commit)
        if (next.to > to) map.splice(pos++, 0, left)
        else map[pos++] = left
      }
      break
    }
  }

  while (next = map[pos]) {
    if (next.commit == commit) {
      if (next.from > to) break
      from = Math.min(from, next.from)
      to = Math.max(to, next.to)
      map.splice(pos, 1)
    } else {
      if (next.from >= to) break
      if (next.to > to) {
        map[pos] = new Span(to, next.to, next.commit)
        break
      } else {
        map.splice(pos, 1)
      }
    }
  }

  map.splice(pos, 0, new Span(from, to, commit))
}

let state = EditorState.create({
  schema,
  plugins: exampleSetup({schema}).concat(trackPlugin, highlightPlugin)
}), view

let lastRendered = null

function onAction(action) {
  state = state.applyAction(action)
  view.updateState(state)
  setDisabled(state)
  renderCommits(state, onAction)
}

view = new MenuBarEditorView(document.querySelector("#editor"), {state, onAction})
window.view = view.editor

function commitAction(message) {
  return {type: "commit", message, time: new Date}
}

onAction(state.tr.insertText("Type something, and then commit it.").action())
onAction(commitAction("Initial commit"))

function setDisabled(state) {
  let input = document.querySelector("#message")
  let button = document.querySelector("#commitbutton")
  input.disabled = button.disabled = trackPlugin.getState(state).uncommittedSteps.length == 0
}

function doCommit(message) {
  onAction(commitAction(message))
}

function renderCommits(state, onAction) {
  let curState = trackPlugin.getState(state)
  if (lastRendered == curState) return
  lastRendered = curState

  let out = document.querySelector("#commits")
  out.textContent = ""
  let commits = curState.commits
  commits.forEach(commit => {
    let node = crel("div", {class: "commit"},
                    crel("span", {class: "commit-time"},
                         commit.time.getHours() + ":" + (commit.time.getMinutes() < 10 ? "0" : "")
                         + commit.time.getMinutes()),
                    "\u00a0 " + commit.message + "\u00a0 ",
                    crel("button", {class: "commit-revert"}, "revert"))
    node.lastChild.addEventListener("click", () => revertCommit(commit))
    node.addEventListener("mouseover", e => {
      if (!node.contains(e.relatedTarget)) onAction({type: "highlightCommit", commit})
    })
    node.addEventListener("mouseout", e => {
      if (!node.contains(e.relatedTarget)) onAction({type: "clearHighlight", commit})
    })
    out.appendChild(node)
  })
}

function revertCommit(commit) {
  let tState = trackPlugin.getState(state)
  let found = tState.commits.indexOf(commit)
  if (found == -1) return

  if (tState.uncommittedSteps.length) return alert("Commit your changes first!")

  let remap = new Mapping(tState.commits.slice(found).reduce((maps, c) => maps.concat(c.maps), []))
  let tr = state.tr
  for (let i = commit.steps.length - 1; i >= 0; i--) {
    let remapped = commit.steps[i].map(remap.slice(i + 1))
    let result = remapped && tr.maybeStep(remapped)
    if (result && result.doc) remap.appendMap(remapped.getMap(), i)
  }
  if (tr.steps.length) {
    onAction(tr.action())
    onAction(commitAction(`Revert '${commit.message}'`))
  }
}

document.querySelector("#commit").addEventListener("submit", e => {
  e.preventDefault()
  doCommit(e.target.elements.message.value || "Unnamed")
  e.target.elements.message.value = ""
  view.editor.focus()
})

function findInBlameMap(pos, state) {
  let map = trackPlugin.getState(state).blameMap
  for (let i = 0; i < map.length; i++)
    if (map[i].to >= pos && map[i].commit != null)
      return map[i].commit
}

document.querySelector("#blame").addEventListener("mousedown", e => {
  e.preventDefault()
  let pos = e.target.getBoundingClientRect()
  let commitID = findInBlameMap(state.selection.head, state)
  let commit = commitID != null && trackPlugin.getState(state).commits[commitID]
  let node = crel("div", {class: "blame-info"},
                  commitID != null ? ["It was: ", crel("strong", null, commit ? commit.message : "Uncommitted")]
                  : "No commit found")
  node.style.right = (document.body.clientWidth - pos.right) + "px"
  node.style.top = (pos.bottom + 2) + "px"
  document.body.appendChild(node)
  setTimeout(() => document.body.removeChild(node), 2000)
})
<commit_msg>Update highlight plugin interface<commit_after>const {EditorState, Plugin} = require("prosemirror-state")
const {Decoration, DecorationSet} = require("prosemirror-view")
const {MenuBarEditorView} = require("prosemirror-menu")
const {Mapping} = require("prosemirror-transform")
const {schema} = require("prosemirror-schema-basic")
const {exampleSetup} = require("prosemirror-example-setup")
const crel = require("crel")

const trackPlugin = new Plugin({
  state: {
    init(_, instance) {
      return new TrackState([new Span(0, instance.doc.content.size, null)], [], [], [])
    },
    applyAction(action, tracked) {
      if (action.type == "transform")
        return tracked.applyTransform(action.transform)
      if (action.type == "commit")
        return tracked.applyCommit(action.message, action.time)
      else
        return tracked
    }
  }
})

const highlightPlugin = new Plugin({
  state: {
    init() { return {deco: DecorationSet.empty, commit: null} },
    applyAction(action, prev, oldState, state) {
      if (action.type == "highlightCommit" && prev.commit != action.commit) {
        let tState = trackPlugin.getState(state)
        let decos = tState.blameMap
            .filter(span => tState.commits[span.commit] == action.commit)
            .map(span => Decoration.inline(span.from, span.to, {class: "blame-marker"}))
        return {deco: DecorationSet.create(state.doc, decos), commit: action.commit}
      } else if (action.type == "clearHighlight" && prev.commit == action.commit) {
        return {deco: DecorationSet.empty, commit: null}
      } else if (action.type == "transform" && prev.commit) {
        return {deco: prev.deco.map(action.transform.mapping, action.transform.doc), commit: prev.commit}
      } else {
        return prev
      }
    }
  },
  props: {
    decorations(state) { return this.getState(state).deco }
  }
})

class Span {
  constructor(from, to, commit) {
    this.from = from; this.to = to; this.commit = commit
  }
}

class Commit {
  constructor(message, time, steps, maps, hidden) {
    this.message = message
    this.time = time
    this.steps = steps
    this.maps = maps
    this.hidden = hidden
  }
}

class TrackState {
  constructor(blameMap, commits, uncommittedSteps, uncommittedMaps) {
    this.blameMap = blameMap
    this.commits = commits
    this.uncommittedSteps = uncommittedSteps
    this.uncommittedMaps = uncommittedMaps
  }

  applyTransform(transform) {
    let inverted = transform.steps.map((step, i) => step.invert(transform.docs[i]))
    return new TrackState(updateBlameMap(this.blameMap, transform, this.commits.length),
                          this.commits,
                          this.uncommittedSteps.concat(inverted),
                          this.uncommittedMaps.concat(transform.mapping.maps))
  }

  applyCommit(message, time) {
    if (this.uncommittedSteps.length == 0) return this
    let commit = new Commit(message, time, this.uncommittedSteps, this.uncommittedMaps)
    return new TrackState(this.blameMap, this.commits.concat(commit), [], [])
  }
}

function updateBlameMap(map, transform, id) {
  let result = [], mapping = transform.mapping
  for (let i = 0; i < map.length; i++) {
    let span = map[i]
    let from = mapping.map(span.from, 1), to = mapping.map(span.to, -1)
    if (from < to) result.push(new Span(from, to, span.commit))
  }

  for (let i = 0; i < mapping.maps.length; i++) {
    let map = mapping.maps[i], after = mapping.slice(i + 1)
    map.forEach((_s, _e, start, end) => {
      insertIntoBlameMap(result, after.map(start, 1), after.map(end, -1), id)
    })
  }

  return result
}

function insertIntoBlameMap(map, from, to, commit) {
  if (from >= to) return
  let pos = 0, next
  for (; pos < map.length; pos++) {
    next = map[pos]
    if (next.commit == commit) {
      if (next.to >= from) break
    } else if (next.to > from) { // Different commit, not before
      if (next.from < from) { // Sticks out to the left (loop below will handle right side)
        let left = new Span(next.from, from, next.commit)
        if (next.to > to) map.splice(pos++, 0, left)
        else map[pos++] = left
      }
      break
    }
  }

  while (next = map[pos]) {
    if (next.commit == commit) {
      if (next.from > to) break
      from = Math.min(from, next.from)
      to = Math.max(to, next.to)
      map.splice(pos, 1)
    } else {
      if (next.from >= to) break
      if (next.to > to) {
        map[pos] = new Span(to, next.to, next.commit)
        break
      } else {
        map.splice(pos, 1)
      }
    }
  }

  map.splice(pos, 0, new Span(from, to, commit))
}

let state = EditorState.create({
  schema,
  plugins: exampleSetup({schema}).concat(trackPlugin, highlightPlugin)
}), view

let lastRendered = null

function onAction(action) {
  state = state.applyAction(action)
  view.updateState(state)
  setDisabled(state)
  renderCommits(state, onAction)
}

view = new MenuBarEditorView(document.querySelector("#editor"), {state, onAction})
window.view = view.editor

function commitAction(message) {
  return {type: "commit", message, time: new Date}
}

onAction(state.tr.insertText("Type something, and then commit it.").action())
onAction(commitAction("Initial commit"))

function setDisabled(state) {
  let input = document.querySelector("#message")
  let button = document.querySelector("#commitbutton")
  input.disabled = button.disabled = trackPlugin.getState(state).uncommittedSteps.length == 0
}

function doCommit(message) {
  onAction(commitAction(message))
}

function renderCommits(state, onAction) {
  let curState = trackPlugin.getState(state)
  if (lastRendered == curState) return
  lastRendered = curState

  let out = document.querySelector("#commits")
  out.textContent = ""
  let commits = curState.commits
  commits.forEach(commit => {
    let node = crel("div", {class: "commit"},
                    crel("span", {class: "commit-time"},
                         commit.time.getHours() + ":" + (commit.time.getMinutes() < 10 ? "0" : "")
                         + commit.time.getMinutes()),
                    "\u00a0 " + commit.message + "\u00a0 ",
                    crel("button", {class: "commit-revert"}, "revert"))
    node.lastChild.addEventListener("click", () => revertCommit(commit))
    node.addEventListener("mouseover", e => {
      if (!node.contains(e.relatedTarget)) onAction({type: "highlightCommit", commit})
    })
    node.addEventListener("mouseout", e => {
      if (!node.contains(e.relatedTarget)) onAction({type: "clearHighlight", commit})
    })
    out.appendChild(node)
  })
}

function revertCommit(commit) {
  let tState = trackPlugin.getState(state)
  let found = tState.commits.indexOf(commit)
  if (found == -1) return

  if (tState.uncommittedSteps.length) return alert("Commit your changes first!")

  let remap = new Mapping(tState.commits.slice(found).reduce((maps, c) => maps.concat(c.maps), []))
  let tr = state.tr
  for (let i = commit.steps.length - 1; i >= 0; i--) {
    let remapped = commit.steps[i].map(remap.slice(i + 1))
    let result = remapped && tr.maybeStep(remapped)
    if (result && result.doc) remap.appendMap(remapped.getMap(), i)
  }
  if (tr.steps.length) {
    onAction(tr.action())
    onAction(commitAction(`Revert '${commit.message}'`))
  }
}

document.querySelector("#commit").addEventListener("submit", e => {
  e.preventDefault()
  doCommit(e.target.elements.message.value || "Unnamed")
  e.target.elements.message.value = ""
  view.editor.focus()
})

function findInBlameMap(pos, state) {
  let map = trackPlugin.getState(state).blameMap
  for (let i = 0; i < map.length; i++)
    if (map[i].to >= pos && map[i].commit != null)
      return map[i].commit
}

document.querySelector("#blame").addEventListener("mousedown", e => {
  e.preventDefault()
  let pos = e.target.getBoundingClientRect()
  let commitID = findInBlameMap(state.selection.head, state)
  let commit = commitID != null && trackPlugin.getState(state).commits[commitID]
  let node = crel("div", {class: "blame-info"},
                  commitID != null ? ["It was: ", crel("strong", null, commit ? commit.message : "Uncommitted")]
                  : "No commit found")
  node.style.right = (document.body.clientWidth - pos.right) + "px"
  node.style.top = (pos.bottom + 2) + "px"
  document.body.appendChild(node)
  setTimeout(() => document.body.removeChild(node), 2000)
})
<|endoftext|>


<commit_before>/**
 * Created by Manuel on 24/08/16.
 */

export class KeyboardHelper {

    hasKeyboard = false;

    constructor(options = {
        hideKeyboardAccessoryBar: true,
        disableScroll: true
    }) {

        this.hasKeyboard = cordova && cordova.plugins.Keyboard;

        if (this.hasKeyboard && options.disableScroll) {
            cordova.plugins.Keyboard.hideKeyboardAccessoryBar && cordova.plugins.Keyboard.hideKeyboardAccessoryBar(options.hideKeyboardAccessoryBar);
            cordova.plugins.Keyboard.hideKeyboardAccessoryBar && cordova.plugins.Keyboard.disableScroll(options.disableScroll);

            /**
             * Change the size of the famous-container to shrink the famous-context once the keyboard shows/hides. DisableScroll should be enabled for this to work
             */
            window.addEventListener('native.keyboardshow', ()=> {
                document.getElementsByClassName('famous-container')[0].style.height = window.innerHeight + "px";
                this._dispatchResizeEvent();
            });

            window.addEventListener('native.keyboardhide', ()=> {
                document.getElementsByClassName('famous-container')[0].style.height = window.innerHeight + "px";
                this._dispatchResizeEvent();
            });

            window.addEventListener("orientationchange", ()=> {
                document.getElementsByClassName('famous-container')[0].style.height = "";
                document.getElementsByClassName('famous-container')[0].style.width = "";
                this._dispatchResizeEvent();
            });
        }
    }

    _dispatchResizeEvent() {
        let resizeEvent = new Event('resize');
        window.dispatchEvent(resizeEvent);
    }

    setKeyboardAccessoryBar(boolean = false) {
        if (this.hasKeyboard) {
            cordova.plugins.Keyboard.hideKeyboardAccessoryBar(boolean);
        } else {
            this._warn();
        }
    }

    setDisableScroll(boolean = false) {
        if (this.hasKeyboard) {
            cordova.plugins.Keyboard.disableScroll(boolean);
        } else {
            this._warn();
        }
    }

    show() {
        if (this.hasKeyboard) {
            cordova.plugins.Keyboard.show();
        } else {
            this._warn();
        }
    }

    hide() {
        if (this.hasKeyboard) {
            cordova.plugins.Keyboard.hide();
        } else {
            this._warn();
        }
    }

    _warn() {
        console.warn('KeyboardHelper is not supported on this platform, probably not a native (iOS/Android) platform');
    }
}<commit_msg>Made keyboard check more rubout since it threw an exception otherwise<commit_after>/**
 * Created by Manuel on 24/08/16.
 */

export class KeyboardHelper {

    hasKeyboard = false;

    constructor(options = {
        hideKeyboardAccessoryBar: true,
        disableScroll: true
    }) {

        this.hasKeyboard = cordova && cordova.plugins && cordova.plugins.Keyboard;

        if (this.hasKeyboard && options.disableScroll) {
            cordova.plugins.Keyboard.hideKeyboardAccessoryBar && cordova.plugins.Keyboard.hideKeyboardAccessoryBar(options.hideKeyboardAccessoryBar);
            cordova.plugins.Keyboard.hideKeyboardAccessoryBar && cordova.plugins.Keyboard.disableScroll(options.disableScroll);

            /**
             * Change the size of the famous-container to shrink the famous-context once the keyboard shows/hides. DisableScroll should be enabled for this to work
             */
            window.addEventListener('native.keyboardshow', ()=> {
                document.getElementsByClassName('famous-container')[0].style.height = window.innerHeight + "px";
                this._dispatchResizeEvent();
            });

            window.addEventListener('native.keyboardhide', ()=> {
                document.getElementsByClassName('famous-container')[0].style.height = window.innerHeight + "px";
                this._dispatchResizeEvent();
            });

            window.addEventListener("orientationchange", ()=> {
                document.getElementsByClassName('famous-container')[0].style.height = "";
                document.getElementsByClassName('famous-container')[0].style.width = "";
                this._dispatchResizeEvent();
            });
        }
    }

    _dispatchResizeEvent() {
        let resizeEvent = new Event('resize');
        window.dispatchEvent(resizeEvent);
    }

    setKeyboardAccessoryBar(boolean = false) {
        if (this.hasKeyboard) {
            cordova.plugins.Keyboard.hideKeyboardAccessoryBar(boolean);
        } else {
            this._warn();
        }
    }

    setDisableScroll(boolean = false) {
        if (this.hasKeyboard) {
            cordova.plugins.Keyboard.disableScroll(boolean);
        } else {
            this._warn();
        }
    }

    show() {
        if (this.hasKeyboard) {
            cordova.plugins.Keyboard.show();
        } else {
            this._warn();
        }
    }

    hide() {
        if (this.hasKeyboard) {
            cordova.plugins.Keyboard.hide();
        } else {
            this._warn();
        }
    }

    _warn() {
        console.warn('KeyboardHelper is not supported on this platform, probably not a native (iOS/Android) platform');
    }
}<|endoftext|>