<commit_before>/******************************************************************************
   Password strength analyzer

   Use analyze(text) to analyze and get a score of how strong, or
   unguessable, the password or passphrase is. A zero-length input
   will yield a score of 0, which is the worst, and the higher the
   score the stronger the password. In addition a word is also
   attributed including a color.

   It uses two metrics to calculate a score: Basic16 and Comprehensive8
   The one producing the largest score is the result.

   Basic16 yields 4 points for each of the first 7 characters after
   which 8 points are awarded subsequent characters. A score of 100 is
   awarded 16 characters, which is why it's called Basic16.

   Comprehensive8 yields 4 points for each character and an additional
   17 points for each uppercase character, digit or symbol. Inputting
   a second unique uppercase character, digit or symbol yields an
   additional 8 points, and a third adds extra 4 points. If no
   lowercse characters are found then 17 points are deducted, and if
   the text does not appear in the word list then 17 points are added.

   The word lists used were provided by Open Wall:
     http://download.openwall.net/pub/wordlists/passwords/

   Deps: jQuery, XRegExp
 ******************************************************************************/
"use strict";
function Psw(path) {
  this.loadPath = path || "wordlist.json";
  this.wordlist = [];
  this.wordObject = {};
  var self = this;

  if (localStorage["wordlist"] != null) {
     self.wordObject = JSON.parse(localStorage["wordlist"]);
     self.wordlist = self.wordObject.wordlist;
     console.log("Loaded wordlist from local storage!");
  } else {
     $.ajax({
       "type" : "GET",
       "url" : self.loadPath,
       "success" : function(data, status, xhr) {
          console.log("Loaded wordlist from \"" + self.loadPath + "\"");
          if (typeof data === "string") {
            var data = JSON.parse(data);
          }
          localStorage["wordlist"] = JSON.stringify(data);
          self.wordObject = JSON.parse(localStorage["wordlist"]);
          self.wordlist = self.wordObject.wordlist;
         },
       "error" : function(xhr, status, error) {
          console.log("Error" + error);
       }
    });
 }
}
window["Psw"] = Psw;

Psw.prototype.analyze = function(text) {
  var score = this.calcScore(text);
  var meaning = this.scoreMeaning(score);
  return {
    "score": score,
    "meaning": meaning[0],
    "color": meaning[1]
  };
};
Psw.prototype["analyze"] = Psw.prototype.analyze;

/**************************************/

Psw.prototype.calcScore = function(text) {
  if (text == undefined || text.length == 0) {
    return 0;
  }
  return Math.max(this.calcBasic16(text), this.calcComp8(text));
};
Psw.prototype["calcScore"] = Psw.prototype.calcScore;

/**
 * 8 segments: dreadful (1-16), bad (17-33), poor (34-50), fair
 * (51-67), good (68-84), great (85-99), excellent (100-115), fantastic (116+)
 */
Psw.prototype.scoreMeaning = function(score) {
  if (score > 0 && score <= 16) {
    return ["Dreadful", "#FF0000"];
  }
  else if (score > 16 && score <= 33) {
    return ["Bad", "#FF6600"];
  }
  else if (score > 33 && score <= 50) {
    return ["Poor", "#FF9900"];
  }
  else if (score > 50 && score <= 67) {
    return ["Fair", "#FFCC00"];
  }
  else if (score > 67 && score <= 84) {
    return ["Good", "#FFFF00"];
  }
  else if (score > 84 && score <= 99) {
    return ["Great", "#CCFF00"];
  }
  else if (score > 99 && score <= 115) {
    return ["Excellent", "#99FF00"];
  }
  else if (score > 115) {
    return ["Fantastic", "#00FF00"];
  }
  else {
    return ["", ""];
  }
};
Psw.prototype["scoreMeaning"] = Psw.prototype.scoreMeaning;

Psw.prototype.calcBasic16 = function(text) {
  var score = 0, len = text.length;
  score = Math.min(len, 7) * 4;
  if (len > 7) {
    score += (len - 7) * 8;
  }
  return score;
};
Psw.prototype["calcBasic16"] = Psw.prototype.calcBasic16;

Psw.prototype.calcComp8 = function(text) {
  var score = 0, len = text.length;
  var upsq = this.countCmp(text, this.isUpper, true);
  var digsq = this.countCmp(text, this.isDigit, true);
  var symsq = this.countCmp(text, this.isSymbol, true);
  var los = this.countCmp(text, this.isLower);

  score = len * 4;

  function unqPoints(num) {
    return (num >= 1 ? 17 : 0) + (num >= 2 ? 8 : 0) + (num >= 3 ? 4 : 0);
  }
  score += unqPoints(upsq) + unqPoints(digsq) + unqPoints(symsq);

  if (los == 0) score -= 17;

  if (this.checkWordList(text)) {
    score += 17;
  }

  return score;
};
Psw.prototype["calcComp8"] = Psw.prototype.calcComp8;

/**
 * Note that XRegExp is used because we want to be able to check for
 * Unicode uppercase characters, not only ASCII, and toUpperCase() is
 * not useful since it lets non-uppercase characters pass through..
 */
Psw.prototype.isUpper = function(text) {
  return XRegExp("^\\p{Lu}$").test(text);
};
Psw.prototype["isUpper"] = Psw.prototype.isUpper;

Psw.prototype.isLower = function(text) {
  return XRegExp("^\\p{Ll}$").test(text);
};
Psw.prototype["isLower"] = Psw.prototype.isLower;

Psw.prototype.isDigit = function(text) {
  return /^\d$/.test(text);
};
Psw.prototype["isDigit"] = Psw.prototype.isDigit;

Psw.prototype.isSymbol = function(text) {
  return /^[!=\?\"\'#%\$§\/\\\(\)\[\]{}+\-\.,;:_<>\*`´\^~|]$/.test(text);
};
Psw.prototype["isSymbol"] = Psw.prototype.isSymbol;

Psw.prototype.countCmp = function(text, cmp, unique) {
  if (unique == undefined) {
    unique = false;
  }
  var cnt = 0;
  var txt = text.split("");
  if (unique) {
    txt = $.unique(txt.sort());
  }
  $.each(txt, function(index, value) {
    if (cmp(txt[index])) {
      cnt++;
    }
  });
  return cnt;
};
Psw.prototype["countCmp"] = Psw.prototype.countCmp;

/**
 * Returns false if found in the word list.
 */
Psw.prototype.checkWordList = function(text) {
  return this.wordlist.indexOf(text.toLowerCase()) == -1;
};
Psw.prototype["checkWordList"] = Psw.prototype.checkWordList
<commit_msg>Don't save wordObject to "self", just keep it as a temp.<commit_after>/******************************************************************************
   Password strength analyzer

   Use analyze(text) to analyze and get a score of how strong, or
   unguessable, the password or passphrase is. A zero-length input
   will yield a score of 0, which is the worst, and the higher the
   score the stronger the password. In addition a word is also
   attributed including a color.

   It uses two metrics to calculate a score: Basic16 and Comprehensive8
   The one producing the largest score is the result.

   Basic16 yields 4 points for each of the first 7 characters after
   which 8 points are awarded subsequent characters. A score of 100 is
   awarded 16 characters, which is why it's called Basic16.

   Comprehensive8 yields 4 points for each character and an additional
   17 points for each uppercase character, digit or symbol. Inputting
   a second unique uppercase character, digit or symbol yields an
   additional 8 points, and a third adds extra 4 points. If no
   lowercse characters are found then 17 points are deducted, and if
   the text does not appear in the word list then 17 points are added.

   The word lists used were provided by Open Wall:
     http://download.openwall.net/pub/wordlists/passwords/

   Deps: jQuery, XRegExp
 ******************************************************************************/
"use strict";
function Psw(path) {
  this.loadPath = path || "wordlist.json";
  this.wordlist = [];

  var self = this;
  if (localStorage["wordlist"] != null) {
    var wordObject = JSON.parse(localStorage["wordlist"]);
    self.wordlist = wordObject.wordlist;
    console.log("Loaded wordlist from local storage!");
  }
  else {
    $.ajax({
      "type": "GET",
      "url": self.loadPath,
      "success": function(data, status, xhr) {
        console.log("Loaded wordlist from \"" + self.loadPath + "\"");
        if (typeof data === "string") {
          data = JSON.parse(data);
        }
        localStorage["wordlist"] = JSON.stringify(data);
        var wordObject = JSON.parse(localStorage["wordlist"]);
        self.wordlist = wordObject.wordlist;
      },
      "error": function(xhr, status, error) {
        console.log("Error" + error);
      }
    });
  }
}
window["Psw"] = Psw;

Psw.prototype.analyze = function(text) {
  var score = this.calcScore(text);
  var meaning = this.scoreMeaning(score);
  return {
    "score": score,
    "meaning": meaning[0],
    "color": meaning[1]
  };
};
Psw.prototype["analyze"] = Psw.prototype.analyze;

/**************************************/

Psw.prototype.calcScore = function(text) {
  if (text == undefined || text.length == 0) {
    return 0;
  }
  return Math.max(this.calcBasic16(text), this.calcComp8(text));
};
Psw.prototype["calcScore"] = Psw.prototype.calcScore;

/**
 * 8 segments: dreadful (1-16), bad (17-33), poor (34-50), fair
 * (51-67), good (68-84), great (85-99), excellent (100-115), fantastic (116+)
 */
Psw.prototype.scoreMeaning = function(score) {
  if (score > 0 && score <= 16) {
    return ["Dreadful", "#FF0000"];
  }
  else if (score > 16 && score <= 33) {
    return ["Bad", "#FF6600"];
  }
  else if (score > 33 && score <= 50) {
    return ["Poor", "#FF9900"];
  }
  else if (score > 50 && score <= 67) {
    return ["Fair", "#FFCC00"];
  }
  else if (score > 67 && score <= 84) {
    return ["Good", "#FFFF00"];
  }
  else if (score > 84 && score <= 99) {
    return ["Great", "#CCFF00"];
  }
  else if (score > 99 && score <= 115) {
    return ["Excellent", "#99FF00"];
  }
  else if (score > 115) {
    return ["Fantastic", "#00FF00"];
  }
  else {
    return ["", ""];
  }
};
Psw.prototype["scoreMeaning"] = Psw.prototype.scoreMeaning;

Psw.prototype.calcBasic16 = function(text) {
  var score = 0, len = text.length;
  score = Math.min(len, 7) * 4;
  if (len > 7) {
    score += (len - 7) * 8;
  }
  return score;
};
Psw.prototype["calcBasic16"] = Psw.prototype.calcBasic16;

Psw.prototype.calcComp8 = function(text) {
  var score = 0, len = text.length;
  var upsq = this.countCmp(text, this.isUpper, true);
  var digsq = this.countCmp(text, this.isDigit, true);
  var symsq = this.countCmp(text, this.isSymbol, true);
  var los = this.countCmp(text, this.isLower);

  score = len * 4;

  function unqPoints(num) {
    return (num >= 1 ? 17 : 0) + (num >= 2 ? 8 : 0) + (num >= 3 ? 4 : 0);
  }
  score += unqPoints(upsq) + unqPoints(digsq) + unqPoints(symsq);

  if (los == 0) score -= 17;

  if (this.checkWordList(text)) {
    score += 17;
  }

  return score;
};
Psw.prototype["calcComp8"] = Psw.prototype.calcComp8;

/**
 * Note that XRegExp is used because we want to be able to check for
 * Unicode uppercase characters, not only ASCII, and toUpperCase() is
 * not useful since it lets non-uppercase characters pass through..
 */
Psw.prototype.isUpper = function(text) {
  return XRegExp("^\\p{Lu}$").test(text);
};
Psw.prototype["isUpper"] = Psw.prototype.isUpper;

Psw.prototype.isLower = function(text) {
  return XRegExp("^\\p{Ll}$").test(text);
};
Psw.prototype["isLower"] = Psw.prototype.isLower;

Psw.prototype.isDigit = function(text) {
  return /^\d$/.test(text);
};
Psw.prototype["isDigit"] = Psw.prototype.isDigit;

Psw.prototype.isSymbol = function(text) {
  return /^[!=\?\"\'#%\$§\/\\\(\)\[\]{}+\-\.,;:_<>\*`´\^~|]$/.test(text);
};
Psw.prototype["isSymbol"] = Psw.prototype.isSymbol;

Psw.prototype.countCmp = function(text, cmp, unique) {
  if (unique == undefined) {
    unique = false;
  }
  var cnt = 0;
  var txt = text.split("");
  if (unique) {
    txt = $.unique(txt.sort());
  }
  $.each(txt, function(index, value) {
    if (cmp(txt[index])) {
      cnt++;
    }
  });
  return cnt;
};
Psw.prototype["countCmp"] = Psw.prototype.countCmp;

/**
 * Returns false if found in the word list.
 */
Psw.prototype.checkWordList = function(text) {
  return this.wordlist.indexOf(text.toLowerCase()) == -1;
};
Psw.prototype["checkWordList"] = Psw.prototype.checkWordList
<|endoftext|>


<commit_before>(() => {
  const isURLAvailable = url => {
    const req = new Request(url, {
      method: "HEAD",
      redirect: "follow"
    });

    return fetch(req).then(resp => resp.ok).catch(() => false);
  };

  const getHostname = () => {
    const u = new URL(document.URL);
    return `${u.protocol}//${u.hostname}`;
  };

  const reportCouldNotConnect = url => {
    /* eslint-disable no-console */
    console.error(`livereloaded: could not find livereload script at ${url}`);
    console.error(`livereloaded: check that livereload server is running`);
    /* eslint-enable no-console */
  };

  const injectLivereload = port => {
    const host = getHostname();
    const url = `${host}:${port}/livereload.js`;

    return isURLAvailable(url).then(isAvailable => {
      if (!isAvailable) {
        reportCouldNotConnect(url);
        return false;
      }

      const script = document.createElement("script");
      script.setAttribute("src", url);
      document.head.appendChild(script);

      return true;
    });
  };

  browser.runtime.onMessage.addListener(msg => {
    switch (msg.command) {
      case "inject":
        return injectLivereload(msg.port);
      default:
        return false;
    }
  });
})();
<commit_msg>Remove closure wrapping around script injector<commit_after>const isURLAvailable = url => {
  const req = new Request(url, {
    method: "HEAD",
    redirect: "follow"
  });

  return fetch(req).then(resp => resp.ok).catch(() => false);
};

const getHostname = () => {
  const u = new URL(document.URL);
  return `${u.protocol}//${u.hostname}`;
};

const reportCouldNotConnect = url => {
  /* eslint-disable no-console */
  console.error(`livereloaded: could not find livereload script at ${url}`);
  console.error(`livereloaded: check that livereload server is running`);
  /* eslint-enable no-console */
};

const injectLivereload = port => {
  const host = getHostname();
  const url = `${host}:${port}/livereload.js`;

  return isURLAvailable(url).then(isAvailable => {
    if (!isAvailable) {
      reportCouldNotConnect(url);
      return false;
    }

    const script = document.createElement("script");
    script.setAttribute("src", url);
    document.head.appendChild(script);

    return true;
  });
};

browser.runtime.onMessage.addListener(msg => {
  switch (msg.command) {
    case "inject":
      return injectLivereload(msg.port);
    default:
      return false;
  }
});
<|endoftext|>


<commit_before>const gulp = require('gulp');
const gutil = require('gulp-util');
const nodemon = require('gulp-nodemon');

gulp.task('nodemon', () => {
  return nodemon({
    script: 'server',
    ext: 'js',
    env: {
      'DEBUG': 'app*,jefferson*,mountie*',
    },
    tasks: ['lint-src', 'test-src'],
  })
    .on('error', (err) => gutil.log('nodemon error', err))
    .on('restart', () => gutil.log('restarting server'));
});
gulp.task('develop', ['watch-client', 'nodemon']);
<commit_msg>Added sass to build chain for gulp develop<commit_after>const gulp = require('gulp');
const gutil = require('gulp-util');
const nodemon = require('gulp-nodemon');

gulp.task('nodemon', () => {
  return nodemon({
    script: 'server',
    ext: 'js',
    env: {
      'DEBUG': 'app*,jefferson*,mountie*',
    },
    tasks: ['lint-src', 'test-src'],
  })
    .on('error', (err) => gutil.log('nodemon error', err))
    .on('restart', () => gutil.log('restarting server'));
});
gulp.task('develop', ['sass', 'watch-client', 'nodemon']);
<|endoftext|>


<commit_before>var global = this;
//
// Define these primitive methods used by drone.js (and potentially others)
//
//  getPlayerPos
//    returns the player's x,y,z and yaw (direction)
//
//  getMousePos
//    returns the x,y,z of the current block being targeted.
//
//  putBlock(x,y,z,blockId,metadata)
//    puts a block at a location in current world
//
//  getBlock(x,y,z)
//    gets the block and metadata (returned as a string in form '35:15')
//
//  putSign(texts,x,y,z,blockId,metadata)
//    puts a sign at the given location
//
//  notifyAdministrators(msg)
//    sends a message to all admins/ops.
//
//  echo(msg)
//    prints a message on screen to current user.
//
(function(){

    //
    // only execute once
    //
    if (typeof getPlayerPos != "undefined"){
        return;
    }

    var _getPlayerPos = function(){
        if (typeof self == "undefined")
            return;
        return self.location;
    };

    var _getMousePos = function(){
        if (typeof self == "undefined")
            return;
        // self might be CONSOLE or a CommandBlock
        if (!self.getTargetBlock)
            return;
        var targetedBlock = self.getTargetBlock(null,5);
        if (targetedBlock == null || targetedBlock.isEmpty()){
            return null;
        }
        return targetedBlock.location;
    };

    var _putBlock = function(x,y,z,blockId,metadata){

        if (typeof metadata == "undefined")
            metadata = 0;
        var pl = org.bukkit.entity.Player;
        var cs = org.bukkit.command.BlockCommandSender;
        var world = (self instanceof pl)?self.location.world:(self instanceof cs)?self.block.location.world:null;
        var block = world.getBlockAt(x,y,z);
        if (block.typeId != blockId || block.data != metadata)
            block.setTypeIdAndData(blockId,metadata,false);

    };

    var _putSign = function(texts, x, y, z, blockId, meta){
        if (blockId != 63 && blockId != 68)
            throw new Error("Invalid Parameter: blockId must be 63 or 68");
        putBlock(x,y,z,blockId,meta);
        var block = _getBlockObject(x,y,z);
        var state = block.state;
        if (state instanceof org.bukkit.block.Sign){
            for (var i = 0;i < texts.length; i++)
                state.setLine(i%4,texts[i]);
            state.update(true);
        }
    };

    var _getBlock = function(x,y,z){
        var block = _getBlockObject(x,y,z);
        if (block)
            return "" + block.typeId + ":" + block.data;

    };

    var _getBlockObject = function(x,y,z){
        var world = _getWorld();
        if (world){
            if (typeof z == "undefined"){
                var loc = _getMousePos()
                if (loc)
                    return world.getBlockAt(loc);
            }else{
                return world.getBlockAt(x,y,z);
            }
        }
    };

    var _getWorld = function(){
        if (self instanceof org.bukkit.entity.Player)
            return self.location.world;
        if (typeof self == "undefined")
            return;
        if (self instanceof org.bukkit.command.BlockCommandSender)
            return self.block.location.world;
    };

    var _notifyAdministrators = function(msg){
        var ops = __plugin.server.operators;
        for (var i = 0; i < ops.size();i++){
            if (ops[i].isOnline())
                ops[i].player.chat(msg);
        }
        __plugin.logger.info(msg);
    };
    var _echo = function(msg){
        __plugin.logger.info(msg);
        if (typeof self == "undefined"){
            java.lang.System.out.println(msg);
            return;
        }
        self.sendMessage(msg);
    };

    global.getPlayerPos = _getPlayerPos;
    global.getMousePos = _getMousePos;
    global.putBlock = _putBlock;
    global.getBlock = _getBlock;
    global.putSign = _putSign;
    global.notifyAdministrators = _notifyAdministrators;
    global.echo = _echo;

}());
<commit_msg>Fix bug in notifyAdmins<commit_after>var global = this;
//
// Define these primitive methods used by drone.js (and potentially others)
//
//  getPlayerPos
//    returns the player's x,y,z and yaw (direction)
//
//  getMousePos
//    returns the x,y,z of the current block being targeted.
//
//  putBlock(x,y,z,blockId,metadata)
//    puts a block at a location in current world
//
//  getBlock(x,y,z)
//    gets the block and metadata (returned as a string in form '35:15')
//
//  putSign(texts,x,y,z,blockId,metadata)
//    puts a sign at the given location
//
//  notifyAdministrators(msg)
//    sends a message to all admins/ops.
//
//  echo(msg)
//    prints a message on screen to current user.
//
(function(){

    //
    // only execute once
    //
    if (typeof getPlayerPos != "undefined"){
        return;
    }

    var _getPlayerPos = function(){
        if (typeof self == "undefined")
            return;
        return self.location;
    };

    var _getMousePos = function(){
        if (typeof self == "undefined")
            return;
        // self might be CONSOLE or a CommandBlock
        if (!self.getTargetBlock)
            return;
        var targetedBlock = self.getTargetBlock(null,5);
        if (targetedBlock == null || targetedBlock.isEmpty()){
            return null;
        }
        return targetedBlock.location;
    };

    var _putBlock = function(x,y,z,blockId,metadata){

        if (typeof metadata == "undefined")
            metadata = 0;
        var pl = org.bukkit.entity.Player;
        var cs = org.bukkit.command.BlockCommandSender;
        var world = (self instanceof pl)?self.location.world:(self instanceof cs)?self.block.location.world:null;
        var block = world.getBlockAt(x,y,z);
        if (block.typeId != blockId || block.data != metadata)
            block.setTypeIdAndData(blockId,metadata,false);

    };

    var _putSign = function(texts, x, y, z, blockId, meta){
        if (blockId != 63 && blockId != 68)
            throw new Error("Invalid Parameter: blockId must be 63 or 68");
        putBlock(x,y,z,blockId,meta);
        var block = _getBlockObject(x,y,z);
        var state = block.state;
        if (state instanceof org.bukkit.block.Sign){
            for (var i = 0;i < texts.length; i++)
                state.setLine(i%4,texts[i]);
            state.update(true);
        }
    };

    var _getBlock = function(x,y,z){
        var block = _getBlockObject(x,y,z);
        if (block)
            return "" + block.typeId + ":" + block.data;

    };

    var _getBlockObject = function(x,y,z){
        var world = _getWorld();
        if (world){
            if (typeof z == "undefined"){
                var loc = _getMousePos()
                if (loc)
                    return world.getBlockAt(loc);
            }else{
                return world.getBlockAt(x,y,z);
            }
        }
    };

    var _getWorld = function(){
        if (self instanceof org.bukkit.entity.Player)
            return self.location.world;
        if (typeof self == "undefined")
            return;
        if (self instanceof org.bukkit.command.BlockCommandSender)
            return self.block.location.world;
    };

    var _notifyAdministrators = function(msg){
        var ops = __plugin.server.operators.toArray();
        for (var i = 0; i < ops.length;i++){
            var op = ops[i];
            if (op.isOnline())
                op.chat(msg);
        }
        __plugin.logger.info(msg);
    };
    var _echo = function(msg){
        __plugin.logger.info(msg);
        if (typeof self == "undefined"){
            java.lang.System.out.println(msg);
            return;
        }
        self.sendMessage(msg);
    };

    global.getPlayerPos = _getPlayerPos;
    global.getMousePos = _getMousePos;
    global.putBlock = _putBlock;
    global.getBlock = _getBlock;
    global.putSign = _putSign;
    global.notifyAdministrators = _notifyAdministrators;
    global.echo = _echo;

}());
<|endoftext|>


<commit_before>import gulp from 'gulp';
import { argv } from 'yargs';
import gulpif from 'gulp-if';
import rename from 'gulp-rename';
import sourcemaps from 'gulp-sourcemaps';
import sass from 'gulp-sass';
import postcss from 'gulp-postcss';
import autoprefixer from 'autoprefixer';
import cssnano from 'cssnano';
import cssGlobbing from 'gulp-css-globbing';
import browserSync from 'browser-sync';
import config from '../config';

const { src, dist } = config.paths;
const isDev = argv.dev || false;

gulp.task('styles', () => {
    const postcssPlugins = [
        autoprefixer({ browsers: ['last 2 versions'] })
    ];
    const postcssDistPlugins = [
        cssnano()
    ];

    return gulp.src(src.styles.entry)
        .pipe(cssGlobbing({ extensions: ['.css', '.scss'] }))
        .pipe(sourcemaps.init())
        .pipe(sass().on('error', sass.logError))
        .pipe(postcss(postcssPlugins))
        .pipe(gulpif(isDev, sourcemaps.write()))
        .pipe(gulp.dest(isDev ? src.styles.dest : dist.css))
        .pipe(gulpif(isDev, browserSync.stream()))
        .pipe(gulpif(!isDev, postcss(postcssDistPlugins)))
        .pipe(gulpif(!isDev, rename(path => path.basename += '.min')))
        .pipe(gulpif(!isDev, gulp.dest(dist.css)));
});
<commit_msg>close #37 perform only safe css optimizations with cssnano<commit_after>import gulp from 'gulp';
import { argv } from 'yargs';
import gulpif from 'gulp-if';
import rename from 'gulp-rename';
import sourcemaps from 'gulp-sourcemaps';
import sass from 'gulp-sass';
import postcss from 'gulp-postcss';
import autoprefixer from 'autoprefixer';
import cssnano from 'cssnano';
import cssGlobbing from 'gulp-css-globbing';
import browserSync from 'browser-sync';
import config from '../config';

const { src, dist } = config.paths;
const isDev = argv.dev || false;

gulp.task('styles', () => {
    const postcssPlugins = [
        autoprefixer({ browsers: ['last 2 versions'] })
    ];
    const postcssDistPlugins = [
        cssnano({ safe: true })
    ];

    return gulp.src(src.styles.entry)
        .pipe(cssGlobbing({ extensions: ['.css', '.scss'] }))
        .pipe(sourcemaps.init())
        .pipe(sass().on('error', sass.logError))
        .pipe(postcss(postcssPlugins))
        .pipe(gulpif(isDev, sourcemaps.write()))
        .pipe(gulp.dest(isDev ? src.styles.dest : dist.css))
        .pipe(gulpif(isDev, browserSync.stream()))
        .pipe(gulpif(!isDev, postcss(postcssDistPlugins)))
        .pipe(gulpif(!isDev, rename(path => path.basename += '.min')))
        .pipe(gulpif(!isDev, gulp.dest(dist.css)));
});
<|endoftext|>


<commit_before>import Utils from './utils';
import Color from './color';
import Cmy   from './cmy';
import Hsl   from './hsl';
import Hsv   from './hsv';
import Xyz   from './xyz';
import Yiq   from './yiq';
import Yuv   from './yuv';

const NAME = Symbol.for('RGB');
const KEYS = Object.freeze({
  R: Symbol.for('r'),
  G: Symbol.for('g'),
  B: Symbol.for('b'),
});

const HEX_PATTERN = /^#([0-9a-f]{6}|[0-9a-f]{3})$/i;
const INT_PATTERN = /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/i;
const PCT_PATTERN = /^rgb\(\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,\s*(\d{1,3}|\d{1,2}\.\d+)%\s*\)$/i;

export default class Rgb extends Color {
  constructor(r, g, b) {
    super(NAME, [[KEYS.R, r], [KEYS.G, g], [KEYS.B, b]]);
  }

  clone() {
    return new Rgb(...this.values());
  }

  isValid() {
    return this.values().every(value => {
      if (!Number.isInteger(value)) {
        return false;
      }
      return 0x00 <= value && value <= 0xFF;
    });
  }

  cmy() {
    let [c, m, y] = this.values().map(value => {
      return 1 - value / 0xFF;
    });
    return new Cmy(c, m, y);
  }

  cmyk() {
    return this.cmy().cmyk();
  }

  hsl() {
    let [r, g, b] = this.values().map(value => value / 0xFF);

    let max   = Math.max(r, g, b);
    let min   = Math.min(r, g, b);
    let delta = max - min;
    if (delta === 0) {
      return new Hsl(0, 0, max);
    }

    let h = 0;
    if (max === r) {
      h = 60 * ((g - b) / delta % 360);
    } else if (max === g) {
      h = 60 * ((b - r) / delta + 2);
    } else if (max === b) {
      h = 60 * ((r - g) / delta + 4);
    }
    let l = (max + min) / 2;
    let s = delta / (1 - Math.abs(2 * l - 1));
    return new Hsl(h, s, l);
  }

  hsv() {
    let [r, g, b] = this.values().map(value => value / 0xFF);

    let max   = Math.max(r, g, b);
    let min   = Math.min(r, g, b);
    let delta = max - min;
    if (delta === 0) {
      return new Hsv(0, 0, max);
    }

    let h = 0;
    if (max === r) {
      h = 60 * ((g - b) / delta % 6);
    } else if (max === g) {
      h = 60 * ((b - r) / delta + 2);
    } else if (max === b) {
      h = 60 * ((r - g) / delta + 4);
    }

    let s = 0;
    if (max !== 0) {
      s = delta / max;
    }

    let v = max;
    return new Hsv(h, s, v);
  }

  rgb() {
    return this;
  }

  xyz() {
    let [r, g, b] = this.values().map(value => {
      value /= 0xFF;
      if (value > 0.04045) {
        value = Math.pow((value + 0.055) / 1.055, 2.4);
      } else {
        value /= 12.92;
      }
      return value * 100;
    });

    let x = r * 0.4124 + g * 0.3576 + b * 0.1805;
    let y = r * 0.2126 + g * 0.7152 + b * 0.0722;
    let z = r * 0.0193 + g * 0.1192 + b * 0.9505;
    return new Xyz(x, y, z);
  }

  yiq() {
    let [r, g, b] = this.values().map(value => value /= 0xFF);

    let y = 0.299 * r + 0.587 * g + 0.114 * b;
    let i = 0.596 * r - 0.274 * g - 0.322 * b;
    let q = 0.211 * r - 0.523 * g + 0.312 * b;
    return new Yiq(y, i, q);
  }

  yuv() {
    let [r, g, b] = this.values().map(value => value /= 0xFF);

    let y =  0.29900 * r + 0.58700 * g + 0.11400 * b;
    let u = -0.14713 * r - 0.28886 * g + 0.43600 * b;
    let v =  0.61500 * r - 0.51499 * g - 0.10001 * b;
    return new Yuv(y, u, v);
  }

  yxy() {
    return this.xyz().yxy();
  }

  static from(value) {
    if (Utils.isObject(value)) {
      return Rgb.fromObject(value);
    }
    if (Utils.isString(value)) {
      return Rgb.fromString(value);
    }
    return null;
  }

  static fromObject(object) {
    let keysA = Object.keys(object).sort();
    let keysB = Object.keys(KEYS).sort();
    if (keysA.join('').toLowerCase() === keysB.join('').toLowerCase()) {
      return new Rgb(object.r, object.g, object.b);
    }
    return null;
  }

  static fromString(string) {
    let matches = string.match(HEX_PATTERN);
    if (matches) {
      let matched = matches[1];
      let integer = Number.parseInt(matched, 16);
      if (matched.length === 6) {
        return new Rgb(integer >> 16 & 0xFF, integer >>  8 & 0xFF, integer >>  0 & 0xFF);
      }
      return new Rgb((integer >> 8 & 0xF) * 17, (integer >> 4 & 0xF) * 17, (integer >> 0 & 0xF) * 17);
    }
  }
}
<commit_msg>Implemented a method that converts color space from RGB to HSI<commit_after>import Utils from './utils';
import Color from './color';
import Cmy   from './cmy';
import Hsi   from './hsi';
import Hsl   from './hsl';
import Hsv   from './hsv';
import Xyz   from './xyz';
import Yiq   from './yiq';
import Yuv   from './yuv';

const NAME = Symbol.for('RGB');
const KEYS = Object.freeze({
  R: Symbol.for('r'),
  G: Symbol.for('g'),
  B: Symbol.for('b'),
});

const HEX_PATTERN = /^#([0-9a-f]{6}|[0-9a-f]{3})$/i;
const INT_PATTERN = /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/i;
const PCT_PATTERN = /^rgb\(\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,\s*(\d{1,3}|\d{1,2}\.\d+)%\s*\)$/i;

export default class Rgb extends Color {
  constructor(r, g, b) {
    super(NAME, [[KEYS.R, r], [KEYS.G, g], [KEYS.B, b]]);
  }

  clone() {
    return new Rgb(...this.values());
  }

  isValid() {
    return this.values().every(value => {
      if (!Number.isInteger(value)) {
        return false;
      }
      return 0x00 <= value && value <= 0xFF;
    });
  }

  cmy() {
    let [c, m, y] = this.values().map(value => {
      return 1 - value / 0xFF;
    });
    return new Cmy(c, m, y);
  }

  cmyk() {
    return this.cmy().cmyk();
  }

  hsi() {
    let [r, g, b] = this.values();

    let i = (r + g + b) / 3;
    let s = 1 - (3 / (r + g + b)) * Math.min(r, g, b);
    let h = Math.acos((0.5 * (r - g) + (r - b)) / Math.pow(r - g, 2) + (r - b) * Math.pow(g - b, 0.5));

    if (b > g) {
      h = 360 - h;
    }
    return new Hsi(h, s, i);
  }

  hsl() {
    let [r, g, b] = this.values().map(value => value / 0xFF);

    let max   = Math.max(r, g, b);
    let min   = Math.min(r, g, b);
    let delta = max - min;
    if (delta === 0) {
      return new Hsl(0, 0, max);
    }

    let h = 0;
    if (max === r) {
      h = 60 * ((g - b) / delta % 360);
    } else if (max === g) {
      h = 60 * ((b - r) / delta + 2);
    } else if (max === b) {
      h = 60 * ((r - g) / delta + 4);
    }
    let l = (max + min) / 2;
    let s = delta / (1 - Math.abs(2 * l - 1));
    return new Hsl(h, s, l);
  }

  hsv() {
    let [r, g, b] = this.values().map(value => value / 0xFF);

    let max   = Math.max(r, g, b);
    let min   = Math.min(r, g, b);
    let delta = max - min;
    if (delta === 0) {
      return new Hsv(0, 0, max);
    }

    let h = 0;
    if (max === r) {
      h = 60 * ((g - b) / delta % 6);
    } else if (max === g) {
      h = 60 * ((b - r) / delta + 2);
    } else if (max === b) {
      h = 60 * ((r - g) / delta + 4);
    }

    let s = 0;
    if (max !== 0) {
      s = delta / max;
    }

    let v = max;
    return new Hsv(h, s, v);
  }

  rgb() {
    return this;
  }

  xyz() {
    let [r, g, b] = this.values().map(value => {
      value /= 0xFF;
      if (value > 0.04045) {
        value = Math.pow((value + 0.055) / 1.055, 2.4);
      } else {
        value /= 12.92;
      }
      return value * 100;
    });

    let x = r * 0.4124 + g * 0.3576 + b * 0.1805;
    let y = r * 0.2126 + g * 0.7152 + b * 0.0722;
    let z = r * 0.0193 + g * 0.1192 + b * 0.9505;
    return new Xyz(x, y, z);
  }

  yiq() {
    let [r, g, b] = this.values().map(value => value /= 0xFF);

    let y = 0.299 * r + 0.587 * g + 0.114 * b;
    let i = 0.596 * r - 0.274 * g - 0.322 * b;
    let q = 0.211 * r - 0.523 * g + 0.312 * b;
    return new Yiq(y, i, q);
  }

  yuv() {
    let [r, g, b] = this.values().map(value => value /= 0xFF);

    let y =  0.29900 * r + 0.58700 * g + 0.11400 * b;
    let u = -0.14713 * r - 0.28886 * g + 0.43600 * b;
    let v =  0.61500 * r - 0.51499 * g - 0.10001 * b;
    return new Yuv(y, u, v);
  }

  yxy() {
    return this.xyz().yxy();
  }

  static from(value) {
    if (Utils.isObject(value)) {
      return Rgb.fromObject(value);
    }
    if (Utils.isString(value)) {
      return Rgb.fromString(value);
    }
    return null;
  }

  static fromObject(object) {
    let keysA = Object.keys(object).sort();
    let keysB = Object.keys(KEYS).sort();
    if (keysA.join('').toLowerCase() === keysB.join('').toLowerCase()) {
      return new Rgb(object.r, object.g, object.b);
    }
    return null;
  }

  static fromString(string) {
    let matches = string.match(HEX_PATTERN);
    if (matches) {
      let matched = matches[1];
      let integer = Number.parseInt(matched, 16);
      if (matched.length === 6) {
        return new Rgb(integer >> 16 & 0xFF, integer >>  8 & 0xFF, integer >>  0 & 0xFF);
      }
      return new Rgb((integer >> 8 & 0xF) * 17, (integer >> 4 & 0xF) * 17, (integer >> 0 & 0xF) * 17);
    }
  }
}
<|endoftext|>


<commit_before>/*
 * (C) Copyright 2014 Kurento (http://kurento.org/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

var ws = new WebSocket('wss://' + location.host + '/call');
var video;
var webRtcPeer;
var recording;

window.onload = function() {
	console = new Console();
	video = document.getElementById('video');
	recording = false;
	disableStopButton();
	disableRecordButton();
}

window.onbeforeunload = function() {
	ws.close();
}

ws.onmessage = function(message) {
	var parsedMessage = JSON.parse(message.data);
	console.info('Received message: ' + message.data);

	switch (parsedMessage.id) {
	case 'presenterResponse':
		presenterResponse(parsedMessage);
		break;
	case 'viewerResponse':
		viewerResponse(parsedMessage);
		break;
	case 'addViewerReturn':
		addViewerReturn(parsedMessage);
		break;
	case 'viewerResponseRet':
		viewerResponseRet(parsedMessage);
		break;
	case 'iceCandidate':
		webRtcPeer.addIceCandidate(parsedMessage.candidate, function(error) {
			if (error)
				return console.error('Error adding candidate: ' + error);
		});
		break;
	case 'stopCommunication':
		dispose();
		break;
	case 'stopParticipantStream':
		removeParticipant(parsedMessage);
		break;
	default:
		console.error('Unrecognized message', parsedMessage);
	}
}

function presenterResponse(message) {
	if (message.response != 'accepted') {
		var errorMsg = message.message ? message.message : 'Unknow error';
		console.info('Call not accepted for the following reason: ' + errorMsg);
		dispose();
	} else {
		webRtcPeer.processAnswer(message.sdpAnswer, function(error) {
			if (error)
				return console.error(error);
		});
	}
}

function viewerResponse(message) {
	if (message.response != 'accepted') {
		var errorMsg = message.message ? message.message : 'Unknow error';
		console.info('Call not accepted for the following reason: ' + errorMsg);
		dispose();
	} else {
		webRtcPeer.processAnswer(message.sdpAnswer, function(error) {
			if (error)
				return console.error(error);
		});
	}
}

function presenter() {
	if (!webRtcPeer) {
		showSpinner(video);

		var options = {
			localVideo : video,
			onicecandidate : onIceCandidate
		}
		webRtcPeer = new kurentoUtils.WebRtcPeer.WebRtcPeerSendonly(options,
				function(error) {
					if (error) {
						return console.error(error);
					}
					webRtcPeer.generateOffer(onOfferPresenter);
				});

		enableStopButton();
		//enableButton('#record', 'record()');
	}
}

function onOfferPresenter(error, offerSdp) {
	if (error)
		return console.error('Error generating the offer');
	console.info('Invoking SDP offer callback function ' + location.host);
	var message = {
		id : 'presenter',
		sdpOffer : offerSdp
	}
	sendMessage(message);
}

function viewer() {
	if (!webRtcPeer) {
		showSpinner(video);

		var options = {
			remoteVideo : video,
			onicecandidate : onIceCandidate
		}
		webRtcPeer = new kurentoUtils.WebRtcPeer.WebRtcPeerRecvonly(options,
				function(error) {
					if (error) {
						return console.error(error);
					}
					this.generateOffer(onOfferViewer);
				});

		enableStopButton();
	}
}

function onOfferViewer(error, offerSdp) {
	if (error)
		return console.error('Error generating the offer');
	console.info('Invoking SDP offer callback function ' + location.host);
	var message = {
		id : 'viewer',
		sdpOffer : offerSdp
	}
	sendMessage(message);
}

function onIceCandidate(candidate) {
	console.log("Local candidate" + JSON.stringify(candidate));

	var message = {
		id : 'onIceCandidate',
		candidate : candidate
	};
	sendMessage(message);
}

function stop() {
	var message = {
		id : 'stop'
	}
	sendMessage(message);
	dispose();
}

function dispose() {
	if (webRtcPeer) {
		webRtcPeer.dispose();
		webRtcPeer = null;
	}
	hideSpinner(video);

	disableStopButton();
}

function disableStopButton() {
	enableButton('#presenter', 'presenter()');
	enableButton('#viewer', 'viewer()');
	disableButton('#stop');
}

function disableRecordButton() {
	disableButton('#record');
}

function enableStopButton() {
	disableButton('#presenter');
	disableButton('#viewer');
	enableButton('#stop', 'stop()');
}

function disableButton(id) {
	$(id).attr('disabled', true);
	$(id).removeAttr('onclick');
}

function enableButton(id, functionName) {
	$(id).attr('disabled', false);
	$(id).attr('onclick', functionName);
}

function sendMessage(message) {
	var jsonMessage = JSON.stringify(message);
	console.log('Senging message: ' + jsonMessage);
	ws.send(jsonMessage);
}

function showSpinner() {
	for (var i = 0; i < arguments.length; i++) {
		arguments[i].poster = './img/transparent-1px.png';
		arguments[i].style.background = 'center transparent url("./img/spinner.gif") no-repeat';
	}
}

function hideSpinner() {
	for (var i = 0; i < arguments.length; i++) {
		arguments[i].src = '';
		arguments[i].poster = './img/webrtc.png';
		arguments[i].style.background = '';
	}
}

/**
 * Lightbox utility (to display media pipeline image in a modal dialog)
 */
$(document).delegate('*[data-toggle="lightbox"]', 'click', function(event) {
	event.preventDefault();
	$(this).ekkoLightbox();
});
<commit_msg>add send video from viewer to front end<commit_after>/*
 * (C) Copyright 2014 Kurento (http://kurento.org/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

var ws = new WebSocket('wss://' + location.host + '/call');
var video;
var webRtcPeer;
var recording;

window.onload = function() {
	console = new Console();
	video = document.getElementById('video');
	recording = false;
	disableStopButton();
	disableRecordButton();
}

window.onbeforeunload = function() {
	ws.close();
}

ws.onmessage = function(message) {
	var parsedMessage = JSON.parse(message.data);
	console.info('Received message: ' + message.data);

	switch (parsedMessage.id) {
	case 'presenterResponse':
		presenterResponse(parsedMessage);
		break;
	case 'viewerResponse':
		viewerResponse(parsedMessage);
		break;
	case 'addViewerReturn':
		addViewerReturn(parsedMessage);
		break;
	case 'viewerResponseRet':
		viewerResponseRet(parsedMessage);
		break;
	case 'iceCandidate':
		webRtcPeer.addIceCandidate(parsedMessage.candidate, function(error) {
			if (error)
				return console.error('Error adding candidate: ' + error);
		});
		break;
	case 'stopCommunication':
		dispose();
		break;
	case 'stopParticipantStream':
		removeParticipant(parsedMessage);
		break;
	default:
		console.error('Unrecognized message', parsedMessage);
	}
}

function presenterResponse(message) {
	if (message.response != 'accepted') {
		var errorMsg = message.message ? message.message : 'Unknow error';
		console.info('Call not accepted for the following reason: ' + errorMsg);
		dispose();
	} else {
		webRtcPeer.processAnswer(message.sdpAnswer, function(error) {
			if (error)
				return console.error(error);
		});
	}
}

function viewerResponse(message) {
	if (message.response != 'accepted') {
		var errorMsg = message.message ? message.message : 'Unknow error';
		console.info('Call not accepted for the following reason: ' + errorMsg);
		dispose();
	} else {
		webRtcPeer.processAnswer(message.sdpAnswer, function(error) {
			if (error)
				return console.error(error);
		});
	}
}

function presenter() {
	if (!webRtcPeer) {
		showSpinner(video);

		var options = {
			localVideo : video,
			onicecandidate : onIceCandidate
		}
		webRtcPeer = new kurentoUtils.WebRtcPeer.WebRtcPeerSendonly(options,
				function(error) {
					if (error) {
						return console.error(error);
					}
					webRtcPeer.generateOffer(onOfferPresenter);
				});

		enableStopButton();
		//enableButton('#record', 'record()');
	}
}

function onOfferPresenter(error, offerSdp) {
	if (error)
		return console.error('Error generating the offer');
	console.info('Invoking SDP offer callback function ' + location.host);
	var message = {
		id : 'presenter',
		sdpOffer : offerSdp
	}
	sendMessage(message);
}

function viewer() {
	if (!webRtcPeer) {
		showSpinner(video);

		var options = {
			remoteVideo : video,
			onicecandidate : onIceCandidate
		}
		webRtcPeer = new kurentoUtils.WebRtcPeer.WebRtcPeerRecvonly(options,
				function(error) {
					if (error) {
						return console.error(error);
					}
					this.generateOffer(onOfferViewer);
				});
		webRtcPeer = new kurentoUtils.WebRtcPeer.WebRtcPeerSendonly(options,
				function(error) {
					if (error) {
						return console.error(error);
					}
					webRtcPeer.generateOffer(onOfferPresenter);
				});
		enableStopButton();
	}
}

function onOfferViewer(error, offerSdp) {
	if (error)
		return console.error('Error generating the offer');
	console.info('Invoking SDP offer callback function ' + location.host);
	var message = {
		id : 'viewer',
		sdpOffer : offerSdp
	}
	sendMessage(message);
}

function onIceCandidate(candidate) {
	console.log("Local candidate" + JSON.stringify(candidate));

	var message = {
		id : 'onIceCandidate',
		candidate : candidate
	};
	sendMessage(message);
}

function stop() {
	var message = {
		id : 'stop'
	}
	sendMessage(message);
	dispose();
}

function dispose() {
	if (webRtcPeer) {
		webRtcPeer.dispose();
		webRtcPeer = null;
	}
	hideSpinner(video);

	disableStopButton();
}

function disableStopButton() {
	enableButton('#presenter', 'presenter()');
	enableButton('#viewer', 'viewer()');
	disableButton('#stop');
}

function disableRecordButton() {
	disableButton('#record');
}

function enableStopButton() {
	disableButton('#presenter');
	disableButton('#viewer');
	enableButton('#stop', 'stop()');
}

function disableButton(id) {
	$(id).attr('disabled', true);
	$(id).removeAttr('onclick');
}

function enableButton(id, functionName) {
	$(id).attr('disabled', false);
	$(id).attr('onclick', functionName);
}

function sendMessage(message) {
	var jsonMessage = JSON.stringify(message);
	console.log('Senging message: ' + jsonMessage);
	ws.send(jsonMessage);
}

function showSpinner() {
	for (var i = 0; i < arguments.length; i++) {
		arguments[i].poster = './img/transparent-1px.png';
		arguments[i].style.background = 'center transparent url("./img/spinner.gif") no-repeat';
	}
}

function hideSpinner() {
	for (var i = 0; i < arguments.length; i++) {
		arguments[i].src = '';
		arguments[i].poster = './img/webrtc.png';
		arguments[i].style.background = '';
	}
}

/**
 * Lightbox utility (to display media pipeline image in a modal dialog)
 */
$(document).delegate('*[data-toggle="lightbox"]', 'click', function(event) {
	event.preventDefault();
	$(this).ekkoLightbox();
});
<|endoftext|>


<commit_before>'use strict'

var _ = require('lodash')
var asar = require('asar')
var async = require('async')
var child = require('child_process')
var debug = require('debug')
var fs = require('fs-extra')
var fsize = require('get-folder-size')
var glob = require('glob')
var path = require('path')
var temp = require('temp').track()
var wrap = require('word-wrap')

var pkg = require('../package.json')

var defaultLogger = debug(pkg.name)

var defaultRename = function (dest, src) {
  return path.join(dest, '<%= name %>_<%= version %>_<%= arch %>.deb')
}

/**
 * Spawn a child process.
 */
var spawn = function (options, command, args, callback) {
  var spawnedProcess = null
  var error = null
  var stderr = ''

  options.logger('Executing command ' + command + ' ' + args.join(' '))

  try {
    spawnedProcess = child.spawn(command, args)
  } catch (err) {
    process.nextTick(function () {
      callback(err, stderr)
    })
    return
  }

  spawnedProcess.stderr.on('data', function (data) {
    stderr += data
  })

  spawnedProcess.on('error', function (err) {
    if (err.name === 'ENOENT') {
      var isFakeroot = err.syscall === 'spawn fakeroot'
      var isDpkg = !isFakeroot && err.syscall === 'spawn dpkg'

      if (isFakeroot || isDpkg) {
        var installer = process.platform === 'darwin' ? 'brew' : 'apt-get'
        var pkg = isFakeroot ? 'fakeroot' : 'dpkg'

        err.message = 'Your system is missing the fakeroot package. Try  e.g. `' + installer + ' install ' + pkg + '`'
      }
    }

    error = error || err
  })

  spawnedProcess.on('close', function (code, signal) {
    if (code !== 0) {
      error = error || signal || code
    }

    callback(error && new Error('Error executing command (' + (error.message || error) + '): ' +
      '\n' + command + ' ' + args.join(' ') + '\n' + stderr))
  })
}

/**
 * Read `package.json` either from `resources.app.asar` (if the app is packaged)
 * or from `resources/app/package.json` (if it is not).
 */
var readMeta = function (options, callback) {
  var withAsar = path.join(options.src, 'resources/app.asar')
  var withoutAsar = path.join(options.src, 'resources/app/package.json')

  try {
    fs.accessSync(withAsar)
    options.logger('Reading package metadata from ' + withAsar)
    callback(null, JSON.parse(asar.extractFile(withAsar, 'package.json')))
    return
  } catch (err) {
  }

  try {
    options.logger('Reading package metadata from ' + withoutAsar)
    callback(null, fs.readJsonSync(withoutAsar))
  } catch (err) {
    callback(new Error('Error reading package metadata: ' + (err.message || err)))
  }
}

/**
 * Read `LICENSE` from the root of the app.
 */
var readLicense = function (options, callback) {
  var licenseSrc = path.join(options.src, 'LICENSE')
  options.logger('Reading license file from ' + licenseSrc)

  fs.readFile(licenseSrc, callback)
}

/**
 * Get the size of the app.
 */
var getSize = function (options, callback) {
  fsize(options.src, callback)
}

/**
 * Get the hash of default options for the installer. Some come from the info
 * read from `package.json`, and some are hardcoded.
 */
var getDefaults = function (data, callback) {
  async.parallel([
    async.apply(readMeta, data),
    async.apply(getSize, {src: data.src})
  ], function (err, results) {
    var pkg = results[0] || {}
    var size = results[1] || 0

    var defaults = {
      name: pkg.name || 'electron',
      productName: pkg.productName || pkg.name,
      genericName: pkg.genericName || pkg.productName || pkg.name,
      description: pkg.description,
      productDescription: pkg.productDescription || pkg.description,
      // Use '~' on pre-releases for proper Debian version ordering.
      // See https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version
      version: (pkg.version || '0.0.0').replace(/(\d)[_.+-]?((RC|rc|pre|dev|beta|alpha)[_.+-]?\d*)$/, '$1~$2'),
      revision: pkg.revision || '1',

      section: 'utils',
      priority: 'optional',
      arch: undefined,
      size: Math.ceil(size / 1024),

      depends: [
        'gconf-service',
        'gconf2',
        'gvfs-bin',
        'libc6',
        'libcap2',
        'libgcrypt11 | libgcrypt20',
        'libgtk2.0-0',
        'libnotify4',
        'libnss3',
        'libudev0 | libudev1',
        'libxtst6',
        'xdg-utils'
      ],
      recommends: [
        'lsb-release'
      ],
      suggests: [
        'gir1.2-gnomekeyring-1.0',
        'libgnome-keyring0'
      ],
      enhances: [
      ],
      preDepends: [
      ],

      maintainer: pkg.author && (typeof pkg.author === 'string'
        ? pkg.author.replace(/\s+\([^)]+\)/, '')
        : pkg.author.name +
          (pkg.author.email != null ? ' <' + pkg.author.email + '>' : '')
      ),

      homepage: pkg.homepage || (pkg.author && (typeof pkg.author === 'string'
        ? pkg.author.replace(/.*\(([^)]+)\).*/, '$1')
        : pkg.author.url
      )),

      bin: pkg.name || 'electron',
      icon: path.resolve(__dirname, '../resources/icon.png'),

      categories: [
        'GNOME',
        'GTK',
        'Utility'
      ],

      mimeType: [],

      lintianOverrides: []
    }

    callback(err, defaults)
  })
}

/**
 * Get the hash of options for the installer.
 */
var getOptions = function (data, defaults, callback) {
  // Flatten everything for ease of use.
  var options = _.defaults({}, data, data.options, defaults)

  // Replace all newlines in the description with spaces, since it's supposed
  // to be one line.
  options.description = options.description.replace(/[\r\n]+/g, ' ')

  // Ensure blank lines have the "." that denotes a blank line in the control file.
  options.productDescription = options.productDescription.replace(/^$/m, '.')
  // Wrap the extended description to avoid lintian warning about
  // `extended-description-line-too-long`.
  options.productDescription = wrap(options.productDescription, {width: 80, indent: ' '})

  callback(null, options)
}

/**
 * Fill in a template with the hash of options.
 */
var generateTemplate = function (options, file, callback) {
  options.logger('Generating template from ' + file)

  async.waterfall([
    async.apply(fs.readFile, file),
    function (template, callback) {
      var result = _.template(template)(options)
      options.logger('Generated template from ' + file + '\n' + result)
      callback(null, result)
    }
  ], callback)
}

/**
 * Create the control file for the package.
 *
 * See: https://www.debian.org/doc/debian-policy/ch-controlfields.html
 */
var createControl = function (options, dir, callback) {
  var controlSrc = path.resolve(__dirname, '../resources/control.ejs')
  var controlDest = path.join(dir, 'DEBIAN/control')
  options.logger('Creating control file at ' + controlDest)

  async.waterfall([
    async.apply(generateTemplate, options, controlSrc),
    async.apply(fs.outputFile, controlDest)
  ], function (err) {
    callback(err && new Error('Error creating control file: ' + (err.message || err)))
  })
}

/**
 * Copy debian scripts.
 */
var copyScripts = function (options, dir, callback) {
  const scriptNames = ['preinst', 'postinst', 'prerm', 'postrm']

  async.forEachOf(options.scripts, function (item, key, callback) {
    if (_.includes(scriptNames, key)) {
      var scriptFile = path.join(dir, 'DEBIAN', key)
      options.logger('Creating script file at ' + scriptFile)

      fs.copy(item, scriptFile, callback)
    } else {
      callback(new Error('Wrong executable script name: ' + key))
    }
  }, function (err) {
    callback(err && new Error('Error creating script files: ' + (err.message || err)))
  })
}

/**
 * Create the binary for the package.
 */
var createBinary = function (options, dir, callback) {
  var binDir = path.join(dir, 'usr/bin')
  var binSrc = path.join('../lib', options.name, options.bin)
  var binDest = path.join(binDir, options.name)
  options.logger('Symlinking binary from ' + binSrc + ' to ' + binDest)

  async.waterfall([
    async.apply(fs.ensureDir, binDir),
    async.apply(fs.symlink, binSrc, binDest, 'file')
  ], function (err) {
    callback(err && new Error('Error creating binary file: ' + (err.message || err)))
  })
}

/**
 * Create the desktop file for the package.
 *
 * See: http://standards.freedesktop.org/desktop-entry-spec/latest/
 */
var createDesktop = function (options, dir, callback) {
  var desktopSrc = path.resolve(__dirname, '../resources/desktop.ejs')
  var desktopDest = path.join(dir, 'usr/share/applications', options.name + '.desktop')
  options.logger('Creating desktop file at ' + desktopDest)

  async.waterfall([
    async.apply(generateTemplate, options, desktopSrc),
    async.apply(fs.outputFile, desktopDest)
  ], function (err) {
    callback(err && new Error('Error creating desktop file: ' + (err.message || err)))
  })
}

/**
 * Create pixmap icon for the package.
 */
var createPixmapIcon = function (options, dir, callback) {
  var iconFile = path.join(dir, 'usr/share/pixmaps', options.name + '.png')
  options.logger('Creating icon file at ' + iconFile)

  fs.copy(options.icon, iconFile, function (err) {
    callback(err && new Error('Error creating icon file: ' + (err.message || err)))
  })
}

/**
 * Create hicolor icon for the package.
 */
var createHicolorIcon = function (options, dir, callback) {
  async.forEachOf(options.icon, function (icon, resolution, callback) {
    var iconFile = path.join(dir, 'usr/share/icons/hicolor', resolution, 'apps', options.name + '.png')
    options.logger('Creating icon file at ' + iconFile)

    fs.copy(icon, iconFile, callback)
  }, function (err) {
    callback(err && new Error('Error creating icon file: ' + (err.message || err)))
  })
}

/**
 * Create icon for the package.
 */
var createIcon = function (options, dir, callback) {
  if (_.isObject(options.icon)) {
    createHicolorIcon(options, dir, callback)
  } else {
    createPixmapIcon(options, dir, callback)
  }
}

/**
 * Create copyright for the package.
 */
var createCopyright = function (options, dir, callback) {
  var copyrightFile = path.join(dir, 'usr/share/doc', options.name, 'copyright')
  options.logger('Creating copyright file at ' + copyrightFile)

  async.waterfall([
    async.apply(readLicense, options),
    async.apply(fs.outputFile, copyrightFile)
  ], function (err) {
    callback(err && new Error('Error creating copyright file: ' + (err.message || err)))
  })
}

/**
 * Create lintian overrides for the package.
 */
var createOverrides = function (options, dir, callback) {
  var overridesSrc = path.resolve(__dirname, '../resources/overrides.ejs')
  var overridesDest = path.join(dir, 'usr/share/lintian/overrides', options.name)
  options.logger('Creating lintian overrides at ' + overridesDest)

  async.waterfall([
    async.apply(generateTemplate, options, overridesSrc),
    async.apply(fs.outputFile, overridesDest)
  ], function (err) {
    callback(err && new Error('Error creating lintian overrides file: ' + (err.message || err)))
  })
}

/**
 * Copy the application into the package.
 */
var createApplication = function (options, dir, callback) {
  var applicationDir = path.join(dir, 'usr/lib', options.name)
  options.logger('Copying application to ' + applicationDir)

  async.waterfall([
    async.apply(fs.ensureDir, applicationDir),
    async.apply(fs.copy, options.src, applicationDir)
  ], function (err) {
    callback(err && new Error('Error copying application directory: ' + (err.message || err)))
  })
}

/**
 * Create temporary directory where the contents of the package will live.
 */
var createDir = function (options, callback) {
  options.logger('Creating temporary directory')

  async.waterfall([
    async.apply(temp.mkdir, 'electron-'),
    function (dir, callback) {
      dir = path.join(dir, options.name + '_' + options.version + '_' + options.arch)
      fs.ensureDir(dir, callback)
    }
  ], function (err, dir) {
    callback(err && new Error('Error creating temporary directory: ' + (err.message || err)), dir)
  })
}

/**
 * Create the contents of the package.
 */
var createContents = function (options, dir, callback) {
  options.logger('Creating contents of package')

  async.parallel([
    async.apply(createControl, options, dir),
    async.apply(copyScripts, options, dir),
    async.apply(createBinary, options, dir),
    async.apply(createDesktop, options, dir),
    async.apply(createIcon, options, dir),
    async.apply(createCopyright, options, dir),
    async.apply(createOverrides, options, dir),
    async.apply(createApplication, options, dir)
  ], function (err) {
    callback(err, dir)
  })
}

/**
 * Package everything using `dpkg` and `fakeroot`.
 */
var createPackage = function (options, dir, callback) {
  options.logger('Creating package at ' + dir)

  spawn(options, 'fakeroot', ['dpkg-deb', '--build', dir], function (err) {
    callback(err, dir)
  })
}

/**
 * Move the package to the specified destination.
 */
var movePackage = function (options, dir, callback) {
  options.logger('Moving package to destination')

  var packagePattern = path.join(dir, '../*.deb')
  async.waterfall([
    async.apply(glob, packagePattern),
    function (files, callback) {
      async.each(files, function (file) {
        var dest = options.rename(options.dest, path.basename(file))
        dest = _.template(dest)(options)
        options.logger('Moving file ' + file + ' to ' + dest)
        fs.move(file, dest, {clobber: true}, callback)
      }, callback)
    }
  ], function (err) {
    callback(err && new Error('Error moving package files: ' + (err.message || err)), dir)
  })
}

/* ************************************************************************** */

module.exports = function (data, callback) {
  data.rename = data.rename || defaultRename
  data.logger = data.logger || defaultLogger

  async.waterfall([
    async.apply(getDefaults, data),
    async.apply(getOptions, data),
    function (options, callback) {
      data.logger('Creating package with options\n' + JSON.stringify(options, null, 2))
      async.waterfall([
        async.apply(createDir, options),
        async.apply(createContents, options),
        async.apply(createPackage, options),
        async.apply(movePackage, options)
      ], function (err) {
        callback(err, options)
      })
    }
  ], function (err, options) {
    if (!err) {
      data.logger('Successfully created package at ' + options.dest)
    } else {
      data.logger('Error creating package: ' + (err.message || err))
    }

    callback(err, options)
  })
}
<commit_msg>Fix typo in docs<commit_after>'use strict'

var _ = require('lodash')
var asar = require('asar')
var async = require('async')
var child = require('child_process')
var debug = require('debug')
var fs = require('fs-extra')
var fsize = require('get-folder-size')
var glob = require('glob')
var path = require('path')
var temp = require('temp').track()
var wrap = require('word-wrap')

var pkg = require('../package.json')

var defaultLogger = debug(pkg.name)

var defaultRename = function (dest, src) {
  return path.join(dest, '<%= name %>_<%= version %>_<%= arch %>.deb')
}

/**
 * Spawn a child process.
 */
var spawn = function (options, command, args, callback) {
  var spawnedProcess = null
  var error = null
  var stderr = ''

  options.logger('Executing command ' + command + ' ' + args.join(' '))

  try {
    spawnedProcess = child.spawn(command, args)
  } catch (err) {
    process.nextTick(function () {
      callback(err, stderr)
    })
    return
  }

  spawnedProcess.stderr.on('data', function (data) {
    stderr += data
  })

  spawnedProcess.on('error', function (err) {
    if (err.name === 'ENOENT') {
      var isFakeroot = err.syscall === 'spawn fakeroot'
      var isDpkg = !isFakeroot && err.syscall === 'spawn dpkg'

      if (isFakeroot || isDpkg) {
        var installer = process.platform === 'darwin' ? 'brew' : 'apt-get'
        var pkg = isFakeroot ? 'fakeroot' : 'dpkg'

        err.message = 'Your system is missing the fakeroot package. Try  e.g. `' + installer + ' install ' + pkg + '`'
      }
    }

    error = error || err
  })

  spawnedProcess.on('close', function (code, signal) {
    if (code !== 0) {
      error = error || signal || code
    }

    callback(error && new Error('Error executing command (' + (error.message || error) + '): ' +
      '\n' + command + ' ' + args.join(' ') + '\n' + stderr))
  })
}

/**
 * Read `package.json` either from `resources/app.asar` (if the app is packaged)
 * or from `resources/app/package.json` (if it is not).
 */
var readMeta = function (options, callback) {
  var withAsar = path.join(options.src, 'resources/app.asar')
  var withoutAsar = path.join(options.src, 'resources/app/package.json')

  try {
    fs.accessSync(withAsar)
    options.logger('Reading package metadata from ' + withAsar)
    callback(null, JSON.parse(asar.extractFile(withAsar, 'package.json')))
    return
  } catch (err) {
  }

  try {
    options.logger('Reading package metadata from ' + withoutAsar)
    callback(null, fs.readJsonSync(withoutAsar))
  } catch (err) {
    callback(new Error('Error reading package metadata: ' + (err.message || err)))
  }
}

/**
 * Read `LICENSE` from the root of the app.
 */
var readLicense = function (options, callback) {
  var licenseSrc = path.join(options.src, 'LICENSE')
  options.logger('Reading license file from ' + licenseSrc)

  fs.readFile(licenseSrc, callback)
}

/**
 * Get the size of the app.
 */
var getSize = function (options, callback) {
  fsize(options.src, callback)
}

/**
 * Get the hash of default options for the installer. Some come from the info
 * read from `package.json`, and some are hardcoded.
 */
var getDefaults = function (data, callback) {
  async.parallel([
    async.apply(readMeta, data),
    async.apply(getSize, {src: data.src})
  ], function (err, results) {
    var pkg = results[0] || {}
    var size = results[1] || 0

    var defaults = {
      name: pkg.name || 'electron',
      productName: pkg.productName || pkg.name,
      genericName: pkg.genericName || pkg.productName || pkg.name,
      description: pkg.description,
      productDescription: pkg.productDescription || pkg.description,
      // Use '~' on pre-releases for proper Debian version ordering.
      // See https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version
      version: (pkg.version || '0.0.0').replace(/(\d)[_.+-]?((RC|rc|pre|dev|beta|alpha)[_.+-]?\d*)$/, '$1~$2'),
      revision: pkg.revision || '1',

      section: 'utils',
      priority: 'optional',
      arch: undefined,
      size: Math.ceil(size / 1024),

      depends: [
        'gconf-service',
        'gconf2',
        'gvfs-bin',
        'libc6',
        'libcap2',
        'libgcrypt11 | libgcrypt20',
        'libgtk2.0-0',
        'libnotify4',
        'libnss3',
        'libudev0 | libudev1',
        'libxtst6',
        'xdg-utils'
      ],
      recommends: [
        'lsb-release'
      ],
      suggests: [
        'gir1.2-gnomekeyring-1.0',
        'libgnome-keyring0'
      ],
      enhances: [
      ],
      preDepends: [
      ],

      maintainer: pkg.author && (typeof pkg.author === 'string'
        ? pkg.author.replace(/\s+\([^)]+\)/, '')
        : pkg.author.name +
          (pkg.author.email != null ? ' <' + pkg.author.email + '>' : '')
      ),

      homepage: pkg.homepage || (pkg.author && (typeof pkg.author === 'string'
        ? pkg.author.replace(/.*\(([^)]+)\).*/, '$1')
        : pkg.author.url
      )),

      bin: pkg.name || 'electron',
      icon: path.resolve(__dirname, '../resources/icon.png'),

      categories: [
        'GNOME',
        'GTK',
        'Utility'
      ],

      mimeType: [],

      lintianOverrides: []
    }

    callback(err, defaults)
  })
}

/**
 * Get the hash of options for the installer.
 */
var getOptions = function (data, defaults, callback) {
  // Flatten everything for ease of use.
  var options = _.defaults({}, data, data.options, defaults)

  // Replace all newlines in the description with spaces, since it's supposed
  // to be one line.
  options.description = options.description.replace(/[\r\n]+/g, ' ')

  // Ensure blank lines have the "." that denotes a blank line in the control file.
  options.productDescription = options.productDescription.replace(/^$/m, '.')
  // Wrap the extended description to avoid lintian warning about
  // `extended-description-line-too-long`.
  options.productDescription = wrap(options.productDescription, {width: 80, indent: ' '})

  callback(null, options)
}

/**
 * Fill in a template with the hash of options.
 */
var generateTemplate = function (options, file, callback) {
  options.logger('Generating template from ' + file)

  async.waterfall([
    async.apply(fs.readFile, file),
    function (template, callback) {
      var result = _.template(template)(options)
      options.logger('Generated template from ' + file + '\n' + result)
      callback(null, result)
    }
  ], callback)
}

/**
 * Create the control file for the package.
 *
 * See: https://www.debian.org/doc/debian-policy/ch-controlfields.html
 */
var createControl = function (options, dir, callback) {
  var controlSrc = path.resolve(__dirname, '../resources/control.ejs')
  var controlDest = path.join(dir, 'DEBIAN/control')
  options.logger('Creating control file at ' + controlDest)

  async.waterfall([
    async.apply(generateTemplate, options, controlSrc),
    async.apply(fs.outputFile, controlDest)
  ], function (err) {
    callback(err && new Error('Error creating control file: ' + (err.message || err)))
  })
}

/**
 * Copy debian scripts.
 */
var copyScripts = function (options, dir, callback) {
  const scriptNames = ['preinst', 'postinst', 'prerm', 'postrm']

  async.forEachOf(options.scripts, function (item, key, callback) {
    if (_.includes(scriptNames, key)) {
      var scriptFile = path.join(dir, 'DEBIAN', key)
      options.logger('Creating script file at ' + scriptFile)

      fs.copy(item, scriptFile, callback)
    } else {
      callback(new Error('Wrong executable script name: ' + key))
    }
  }, function (err) {
    callback(err && new Error('Error creating script files: ' + (err.message || err)))
  })
}

/**
 * Create the binary for the package.
 */
var createBinary = function (options, dir, callback) {
  var binDir = path.join(dir, 'usr/bin')
  var binSrc = path.join('../lib', options.name, options.bin)
  var binDest = path.join(binDir, options.name)
  options.logger('Symlinking binary from ' + binSrc + ' to ' + binDest)

  async.waterfall([
    async.apply(fs.ensureDir, binDir),
    async.apply(fs.symlink, binSrc, binDest, 'file')
  ], function (err) {
    callback(err && new Error('Error creating binary file: ' + (err.message || err)))
  })
}

/**
 * Create the desktop file for the package.
 *
 * See: http://standards.freedesktop.org/desktop-entry-spec/latest/
 */
var createDesktop = function (options, dir, callback) {
  var desktopSrc = path.resolve(__dirname, '../resources/desktop.ejs')
  var desktopDest = path.join(dir, 'usr/share/applications', options.name + '.desktop')
  options.logger('Creating desktop file at ' + desktopDest)

  async.waterfall([
    async.apply(generateTemplate, options, desktopSrc),
    async.apply(fs.outputFile, desktopDest)
  ], function (err) {
    callback(err && new Error('Error creating desktop file: ' + (err.message || err)))
  })
}

/**
 * Create pixmap icon for the package.
 */
var createPixmapIcon = function (options, dir, callback) {
  var iconFile = path.join(dir, 'usr/share/pixmaps', options.name + '.png')
  options.logger('Creating icon file at ' + iconFile)

  fs.copy(options.icon, iconFile, function (err) {
    callback(err && new Error('Error creating icon file: ' + (err.message || err)))
  })
}

/**
 * Create hicolor icon for the package.
 */
var createHicolorIcon = function (options, dir, callback) {
  async.forEachOf(options.icon, function (icon, resolution, callback) {
    var iconFile = path.join(dir, 'usr/share/icons/hicolor', resolution, 'apps', options.name + '.png')
    options.logger('Creating icon file at ' + iconFile)

    fs.copy(icon, iconFile, callback)
  }, function (err) {
    callback(err && new Error('Error creating icon file: ' + (err.message || err)))
  })
}

/**
 * Create icon for the package.
 */
var createIcon = function (options, dir, callback) {
  if (_.isObject(options.icon)) {
    createHicolorIcon(options, dir, callback)
  } else {
    createPixmapIcon(options, dir, callback)
  }
}

/**
 * Create copyright for the package.
 */
var createCopyright = function (options, dir, callback) {
  var copyrightFile = path.join(dir, 'usr/share/doc', options.name, 'copyright')
  options.logger('Creating copyright file at ' + copyrightFile)

  async.waterfall([
    async.apply(readLicense, options),
    async.apply(fs.outputFile, copyrightFile)
  ], function (err) {
    callback(err && new Error('Error creating copyright file: ' + (err.message || err)))
  })
}

/**
 * Create lintian overrides for the package.
 */
var createOverrides = function (options, dir, callback) {
  var overridesSrc = path.resolve(__dirname, '../resources/overrides.ejs')
  var overridesDest = path.join(dir, 'usr/share/lintian/overrides', options.name)
  options.logger('Creating lintian overrides at ' + overridesDest)

  async.waterfall([
    async.apply(generateTemplate, options, overridesSrc),
    async.apply(fs.outputFile, overridesDest)
  ], function (err) {
    callback(err && new Error('Error creating lintian overrides file: ' + (err.message || err)))
  })
}

/**
 * Copy the application into the package.
 */
var createApplication = function (options, dir, callback) {
  var applicationDir = path.join(dir, 'usr/lib', options.name)
  options.logger('Copying application to ' + applicationDir)

  async.waterfall([
    async.apply(fs.ensureDir, applicationDir),
    async.apply(fs.copy, options.src, applicationDir)
  ], function (err) {
    callback(err && new Error('Error copying application directory: ' + (err.message || err)))
  })
}

/**
 * Create temporary directory where the contents of the package will live.
 */
var createDir = function (options, callback) {
  options.logger('Creating temporary directory')

  async.waterfall([
    async.apply(temp.mkdir, 'electron-'),
    function (dir, callback) {
      dir = path.join(dir, options.name + '_' + options.version + '_' + options.arch)
      fs.ensureDir(dir, callback)
    }
  ], function (err, dir) {
    callback(err && new Error('Error creating temporary directory: ' + (err.message || err)), dir)
  })
}

/**
 * Create the contents of the package.
 */
var createContents = function (options, dir, callback) {
  options.logger('Creating contents of package')

  async.parallel([
    async.apply(createControl, options, dir),
    async.apply(copyScripts, options, dir),
    async.apply(createBinary, options, dir),
    async.apply(createDesktop, options, dir),
    async.apply(createIcon, options, dir),
    async.apply(createCopyright, options, dir),
    async.apply(createOverrides, options, dir),
    async.apply(createApplication, options, dir)
  ], function (err) {
    callback(err, dir)
  })
}

/**
 * Package everything using `dpkg` and `fakeroot`.
 */
var createPackage = function (options, dir, callback) {
  options.logger('Creating package at ' + dir)

  spawn(options, 'fakeroot', ['dpkg-deb', '--build', dir], function (err) {
    callback(err, dir)
  })
}

/**
 * Move the package to the specified destination.
 */
var movePackage = function (options, dir, callback) {
  options.logger('Moving package to destination')

  var packagePattern = path.join(dir, '../*.deb')
  async.waterfall([
    async.apply(glob, packagePattern),
    function (files, callback) {
      async.each(files, function (file) {
        var dest = options.rename(options.dest, path.basename(file))
        dest = _.template(dest)(options)
        options.logger('Moving file ' + file + ' to ' + dest)
        fs.move(file, dest, {clobber: true}, callback)
      }, callback)
    }
  ], function (err) {
    callback(err && new Error('Error moving package files: ' + (err.message || err)), dir)
  })
}

/* ************************************************************************** */

module.exports = function (data, callback) {
  data.rename = data.rename || defaultRename
  data.logger = data.logger || defaultLogger

  async.waterfall([
    async.apply(getDefaults, data),
    async.apply(getOptions, data),
    function (options, callback) {
      data.logger('Creating package with options\n' + JSON.stringify(options, null, 2))
      async.waterfall([
        async.apply(createDir, options),
        async.apply(createContents, options),
        async.apply(createPackage, options),
        async.apply(movePackage, options)
      ], function (err) {
        callback(err, options)
      })
    }
  ], function (err, options) {
    if (!err) {
      data.logger('Successfully created package at ' + options.dest)
    } else {
      data.logger('Error creating package: ' + (err.message || err))
    }

    callback(err, options)
  })
}
<|endoftext|>


<commit_before>mapbox.markers.layer = function() {

    var m = {},
        // external list of geojson features
        features = [],
        // internal list of markers
        markers = [],
        // internal list of callbacks
        callbackManager = new MM.CallbackManager(m, ['drawn', 'markeradded']),
        // the absolute position of the parent element
        position = null,
        // a factory function for creating DOM elements out of
        // GeoJSON objects
        factory = mapbox.markers.simplestyle_factory,
        // a sorter function for sorting GeoJSON objects
        // in the DOM
        sorter = function(a, b) {
            return b.geometry.coordinates[1] -
              a.geometry.coordinates[1];
        },
        // a list of urls from which features can be loaded.
        // these can be templated with {z}, {x}, and {y}
        urls,
        // map bounds
        left = null,
        right = null,
        // a function that filters points
        filter = function() {
            return true;
        },
        _seq = 0,
        keyfn = function() {
            return ++_seq;
        },
        index = {};

    // The parent DOM element
    m.parent = document.createElement('div');
    m.parent.style.cssText = 'position: absolute; top: 0px;' +
        'left:0px; width:100%; height:100%; margin:0; padding:0; z-index:0;pointer-events:none;';
    m.name = 'markers';

    // reposition a single marker element
    function reposition(marker) {
        // remember the tile coordinate so we don't have to reproject every time
        if (!marker.coord) marker.coord = m.map.locationCoordinate(marker.location);
        var pos = m.map.coordinatePoint(marker.coord);
        var pos_loc, new_pos;

        // If this point has wound around the world, adjust its position
        // to the new, onscreen location
        if (pos.x < 0) {
            pos_loc = new MM.Location(marker.location.lat, marker.location.lon);
            pos_loc.lon += Math.ceil((left.lon - marker.location.lon) / 360) * 360;
            new_pos = m.map.locationPoint(pos_loc);
            if (new_pos.x < m.map.dimensions.x) {
                pos = new_pos;
                marker.coord = m.map.locationCoordinate(pos_loc);
            }
        } else if (pos.x > m.map.dimensions.x) {
            pos_loc = new MM.Location(marker.location.lat, marker.location.lon);
            pos_loc.lon -= Math.ceil((marker.location.lon - right.lon) / 360) * 360;
            new_pos = m.map.locationPoint(pos_loc);
            if (new_pos.x > 0) {
                pos = new_pos;
                marker.coord = m.map.locationCoordinate(pos_loc);
            }
        }

        pos.scale = 1;
        pos.width = pos.height = 0;
        MM.moveElement(marker.element, pos);
    }

    // Adding and removing callbacks is mainly a way to enable mmg_interaction to operate.
    // I think there are better ways to do this, by, for instance, having mmg be able to
    // register 'binders' to markers, but this is backwards-compatible and equivalent
    // externally.
    m.addCallback = function(event, callback) {
        callbackManager.addCallback(event, callback);
        return m;
    };

    m.removeCallback = function(event, callback) {
        callbackManager.removeCallback(event, callback);
        return m;
    };

    // Draw this layer - reposition all markers on the div. This requires
    // the markers library to be attached to a map, and will noop otherwise.
    m.draw = function() {
        if (!m.map) return;
        left = m.map.pointLocation(new MM.Point(0, 0));
        right = m.map.pointLocation(new MM.Point(m.map.dimensions.x, 0));
        callbackManager.dispatchCallback('drawn', m);
        for (var i = 0; i < markers.length; i++) {
            reposition(markers[i]);
        }
    };

    // Add a fully-formed marker to the layer. This fires a `markeradded` event.
    // This does not require the map element t be attached.
    m.add = function(marker) {
        if (!marker || !marker.element) return null;
        m.parent.appendChild(marker.element);
        markers.push(marker);
        callbackManager.dispatchCallback('markeradded', marker);
        return marker;
    };

    // Remove a fully-formed marker - which must be the same exact marker
    // object as in the markers array - from the layer.
    m.remove = function(marker) {
        if (!marker) return null;
        m.parent.removeChild(marker.element);
        for (var i = 0; i < markers.length; i++) {
            if (markers[i] === marker) {
                markers.splice(i, 1);
                return marker;
            }
        }
        return marker;
    };

    m.markers = function(x) {
        if (!arguments.length) return markers;
    };

    // Add a GeoJSON feature to the markers layer.
    m.add_feature = function(x) {
        return m.features(m.features().concat([x]));
    };

    m.sort = function(x) {
        if (!arguments.length) return sorter;
        sorter = x;
        return m;
    };

    // Public data interface
    m.features = function(x) {
        // Return features
        if (!arguments.length) return features;

        // Set features
        if (!x) x = [];
        features = x.slice();

        features.sort(sorter);

        for (var j = 0; j < markers.length; j++) {
            markers[j].touch = false;
        }

        for (var i = 0; i < features.length; i++) {
            if (filter(features[i])) {
                var id = keyfn(features[i]);
                if (index[id]) {
                    // marker is already on the map, needs to be moved or rebuilt
                    index[id].location = new MM.Location(
                        features[i].geometry.coordinates[1],
                        features[i].geometry.coordinates[0]);
                    index[id].coord = null;
                    reposition(index[id]);
                } else {
                    // marker needs to be added to the map
                    index[id] = m.add({
                        element: factory(features[i]),
                        location: new MM.Location(
                            features[i].geometry.coordinates[1],
                            features[i].geometry.coordinates[0]),
                        data: features[i]
                    });
                }
                if (index[id]) index[id].touch = true;
            }
        }

        for (var k = markers.length - 1; k >= 0; k--) {
            if (markers[k].touch === false) {
                m.remove(markers[k]);
            }
        }

        if (m.map && m.map.coordinate) m.map.draw();

        return m;
    };

    // Request features from a URL - either a local URL or a JSONP call.
    // Expects GeoJSON-formatted features.
    m.url = function(x, callback) {
        if (!arguments.length) return urls;
        if (typeof reqwest === 'undefined') throw 'reqwest is required for url loading';
        if (typeof x === 'string') x = [x];

        urls = x;
        function add_features(err, x) {
            if (err && callback) return callback(err);
            var features = x && x.features ? x.features : null;
            if (features) m.features(features);
            if (callback) callback(err, features, m);
        }

        reqwest((urls[0].match(/geojsonp$/)) ? {
            url: urls[0] + (~urls[0].indexOf('?') ? '&' : '?') + 'callback=grid',
            type: 'jsonp',
            jsonpCallback: 'callback',
            success: function(resp) { add_features(null, resp); },
            error: add_features
        } : {
            url: urls[0],
            type: 'json',
            success: function(resp) { add_features(null, resp); },
            error: add_features
        });
        return m;
    };

    m.id = function(x, callback) {
        return m.url('http://a.tiles.mapbox.com/v3/' + x + '/markers.geojsonp', callback);
    };

    m.csv = function(x) {
        return m.features(mapbox.markers.csv_to_geojson(x));
    };

    m.extent = function() {
        var ext = [{
            lat: Infinity,
            lon: Infinity
        }, {
            lat: -Infinity,
            lon: -Infinity
        }];
        var ft = m.features();
        for (var i = 0; i < ft.length; i++) {
            var coords = ft[i].geometry.coordinates;
            if (coords[0] < ext[0].lon) ext[0].lon = coords[0];
            if (coords[1] < ext[0].lat) ext[0].lat = coords[1];
            if (coords[0] > ext[1].lon) ext[1].lon = coords[0];
            if (coords[1] > ext[1].lat) ext[1].lat = coords[1];
        }
        return ext;
    };

    m.key = function(x) {
        if (!arguments.length) return keyfn;
        if (x === null) {
            keyfn = function() { return ++_seq; };
        } else {
            keyfn = x;
        }
        return m;
    };

    // Factory interface
    m.factory = function(x) {
        if (!arguments.length) return factory;
        factory = x;
        // re-render all features
        m.features(m.features());
        return m;
    };

    m.filter = function(x) {
        if (!arguments.length) return filter;
        filter = x;
        // Setting a filter re-sets the features into a new array.
        // This does _not_ change the actual output of .features()
        m.features(m.features());
        return m;
    };

    m.destroy = function() {
        if (m.parent.parentNode) {
            m.parent.parentNode.removeChild(m.parent);
        }
    };

    // Get or set this layer's name
    m.named = function(x) {
        if (!arguments.length) return m.name;
        m.name = x;
        return m;
    };

    m.enabled = true;

    m.enable = function() {
        this.enabled = true;
        this.parent.style.display = '';
        return m;
    };

    m.disable = function() {
        this.enabled = false;
        this.parent.style.display = 'none';
        return m;
    };

    return m;
};

mmg = mapbox.markers.layer; // Backwards compatibility
<commit_msg>Fix check for x.<commit_after>mapbox.markers.layer = function() {

    var m = {},
        // external list of geojson features
        features = [],
        // internal list of markers
        markers = [],
        // internal list of callbacks
        callbackManager = new MM.CallbackManager(m, ['drawn', 'markeradded']),
        // the absolute position of the parent element
        position = null,
        // a factory function for creating DOM elements out of
        // GeoJSON objects
        factory = mapbox.markers.simplestyle_factory,
        // a sorter function for sorting GeoJSON objects
        // in the DOM
        sorter = function(a, b) {
            return b.geometry.coordinates[1] -
              a.geometry.coordinates[1];
        },
        // a list of urls from which features can be loaded.
        // these can be templated with {z}, {x}, and {y}
        urls,
        // map bounds
        left = null,
        right = null,
        // a function that filters points
        filter = function() {
            return true;
        },
        _seq = 0,
        keyfn = function() {
            return ++_seq;
        },
        index = {};

    // The parent DOM element
    m.parent = document.createElement('div');
    m.parent.style.cssText = 'position: absolute; top: 0px;' +
        'left:0px; width:100%; height:100%; margin:0; padding:0; z-index:0;pointer-events:none;';
    m.name = 'markers';

    // reposition a single marker element
    function reposition(marker) {
        // remember the tile coordinate so we don't have to reproject every time
        if (!marker.coord) marker.coord = m.map.locationCoordinate(marker.location);
        var pos = m.map.coordinatePoint(marker.coord);
        var pos_loc, new_pos;

        // If this point has wound around the world, adjust its position
        // to the new, onscreen location
        if (pos.x < 0) {
            pos_loc = new MM.Location(marker.location.lat, marker.location.lon);
            pos_loc.lon += Math.ceil((left.lon - marker.location.lon) / 360) * 360;
            new_pos = m.map.locationPoint(pos_loc);
            if (new_pos.x < m.map.dimensions.x) {
                pos = new_pos;
                marker.coord = m.map.locationCoordinate(pos_loc);
            }
        } else if (pos.x > m.map.dimensions.x) {
            pos_loc = new MM.Location(marker.location.lat, marker.location.lon);
            pos_loc.lon -= Math.ceil((marker.location.lon - right.lon) / 360) * 360;
            new_pos = m.map.locationPoint(pos_loc);
            if (new_pos.x > 0) {
                pos = new_pos;
                marker.coord = m.map.locationCoordinate(pos_loc);
            }
        }

        pos.scale = 1;
        pos.width = pos.height = 0;
        MM.moveElement(marker.element, pos);
    }

    // Adding and removing callbacks is mainly a way to enable mmg_interaction to operate.
    // I think there are better ways to do this, by, for instance, having mmg be able to
    // register 'binders' to markers, but this is backwards-compatible and equivalent
    // externally.
    m.addCallback = function(event, callback) {
        callbackManager.addCallback(event, callback);
        return m;
    };

    m.removeCallback = function(event, callback) {
        callbackManager.removeCallback(event, callback);
        return m;
    };

    // Draw this layer - reposition all markers on the div. This requires
    // the markers library to be attached to a map, and will noop otherwise.
    m.draw = function() {
        if (!m.map) return;
        left = m.map.pointLocation(new MM.Point(0, 0));
        right = m.map.pointLocation(new MM.Point(m.map.dimensions.x, 0));
        callbackManager.dispatchCallback('drawn', m);
        for (var i = 0; i < markers.length; i++) {
            reposition(markers[i]);
        }
    };

    // Add a fully-formed marker to the layer. This fires a `markeradded` event.
    // This does not require the map element t be attached.
    m.add = function(marker) {
        if (!marker || !marker.element) return null;
        m.parent.appendChild(marker.element);
        markers.push(marker);
        callbackManager.dispatchCallback('markeradded', marker);
        return marker;
    };

    // Remove a fully-formed marker - which must be the same exact marker
    // object as in the markers array - from the layer.
    m.remove = function(marker) {
        if (!marker) return null;
        m.parent.removeChild(marker.element);
        for (var i = 0; i < markers.length; i++) {
            if (markers[i] === marker) {
                markers.splice(i, 1);
                return marker;
            }
        }
        return marker;
    };

    m.markers = function(x) {
        if (!arguments.length) return markers;
    };

    // Add a GeoJSON feature to the markers layer.
    m.add_feature = function(x) {
        return m.features(m.features().concat([x]));
    };

    m.sort = function(x) {
        if (!arguments.length) return sorter;
        sorter = x;
        return m;
    };

    // Public data interface
    m.features = function(x) {
        // Return features
        if (!arguments.length) return features;

        // Set features
        if (!x) x = [];
        features = x.slice();

        features.sort(sorter);

        for (var j = 0; j < markers.length; j++) {
            markers[j].touch = false;
        }

        for (var i = 0; i < features.length; i++) {
            if (filter(features[i])) {
                var id = keyfn(features[i]);
                if (index[id]) {
                    // marker is already on the map, needs to be moved or rebuilt
                    index[id].location = new MM.Location(
                        features[i].geometry.coordinates[1],
                        features[i].geometry.coordinates[0]);
                    index[id].coord = null;
                    reposition(index[id]);
                } else {
                    // marker needs to be added to the map
                    index[id] = m.add({
                        element: factory(features[i]),
                        location: new MM.Location(
                            features[i].geometry.coordinates[1],
                            features[i].geometry.coordinates[0]),
                        data: features[i]
                    });
                }
                if (index[id]) index[id].touch = true;
            }
        }

        for (var k = markers.length - 1; k >= 0; k--) {
            if (markers[k].touch === false) {
                m.remove(markers[k]);
            }
        }

        if (m.map && m.map.coordinate) m.map.draw();

        return m;
    };

    // Request features from a URL - either a local URL or a JSONP call.
    // Expects GeoJSON-formatted features.
    m.url = function(x, callback) {
        if (!arguments.length) return urls;
        if (typeof reqwest === 'undefined') throw 'reqwest is required for url loading';
        if (typeof x === 'string') x = [x];

        urls = x;
        function add_features(err, x) {
            if (err && callback) return callback(err);
            var features = typeof x !== 'undefined' && x.features ? x.features : null;
            if (features) m.features(features);
            if (callback) callback(err, features, m);
        }

        reqwest((urls[0].match(/geojsonp$/)) ? {
            url: urls[0] + (~urls[0].indexOf('?') ? '&' : '?') + 'callback=grid',
            type: 'jsonp',
            jsonpCallback: 'callback',
            success: function(resp) { add_features(null, resp); },
            error: add_features
        } : {
            url: urls[0],
            type: 'json',
            success: function(resp) { add_features(null, resp); },
            error: add_features
        });
        return m;
    };

    m.id = function(x, callback) {
        return m.url('http://a.tiles.mapbox.com/v3/' + x + '/markers.geojsonp', callback);
    };

    m.csv = function(x) {
        return m.features(mapbox.markers.csv_to_geojson(x));
    };

    m.extent = function() {
        var ext = [{
            lat: Infinity,
            lon: Infinity
        }, {
            lat: -Infinity,
            lon: -Infinity
        }];
        var ft = m.features();
        for (var i = 0; i < ft.length; i++) {
            var coords = ft[i].geometry.coordinates;
            if (coords[0] < ext[0].lon) ext[0].lon = coords[0];
            if (coords[1] < ext[0].lat) ext[0].lat = coords[1];
            if (coords[0] > ext[1].lon) ext[1].lon = coords[0];
            if (coords[1] > ext[1].lat) ext[1].lat = coords[1];
        }
        return ext;
    };

    m.key = function(x) {
        if (!arguments.length) return keyfn;
        if (x === null) {
            keyfn = function() { return ++_seq; };
        } else {
            keyfn = x;
        }
        return m;
    };

    // Factory interface
    m.factory = function(x) {
        if (!arguments.length) return factory;
        factory = x;
        // re-render all features
        m.features(m.features());
        return m;
    };

    m.filter = function(x) {
        if (!arguments.length) return filter;
        filter = x;
        // Setting a filter re-sets the features into a new array.
        // This does _not_ change the actual output of .features()
        m.features(m.features());
        return m;
    };

    m.destroy = function() {
        if (m.parent.parentNode) {
            m.parent.parentNode.removeChild(m.parent);
        }
    };

    // Get or set this layer's name
    m.named = function(x) {
        if (!arguments.length) return m.name;
        m.name = x;
        return m;
    };

    m.enabled = true;

    m.enable = function() {
        this.enabled = true;
        this.parent.style.display = '';
        return m;
    };

    m.disable = function() {
        this.enabled = false;
        this.parent.style.display = 'none';
        return m;
    };

    return m;
};

mmg = mapbox.markers.layer; // Backwards compatibility
<|endoftext|>


<commit_before>var lineReader = require('line-reader');
var fs = require('fs');

var output = "";
var i = 1;
var trkOpenTagFound = false;

NAMEOPENTAG = "<name>";
NAMECLOSETAG = "</name>";
TRACKOPENTAG = "<trk>";
TRACKCLOSETAG = "</trk>";

// read all lines:
lineReader.eachLine('./passit/passit_2014.gpx', function(line) {
	var nameOpenTag = line.search(NAMEOPENTAG);
	var nameCloseTag = line.search(NAMECLOSETAG);
	var trackOpenTag = line.search(TRACKOPENTAG);
	var trackCloseTag = line.search(TRACKCLOSETAG);

	if (trackOpenTag >= 0) {
		trkOpenTagFound = true;
	}

	// If track is not found yet, check the line content
	// If track is found then skip the line
	if (trkOpenTagFound === false) {
		if (nameOpenTag >= 0) {
			var nameOrig = line.slice(nameOpenTag + NAMEOPENTAG.length, nameCloseTag);
			var tmp = nameOrig.replace(/[,:.]/gi, "");
			var newLine = line.replace(nameOrig, tmp);
			output += newLine;
			i++;
		} else {
			output += line;
		}
	}
	// Track closed
	if ((trackCloseTag >= 0) && (trkOpenTagFound === true)) {
		trkOpenTagFound = false;
	}
}).then(function () {
	console.log("I'm done!!");
    // All lines are read, file is closed now.
	fs.writeFile('./passit/passit_2014-mod.gpx', output, function (err) {
		if (err) throw err;
		console.log('It\'s saved!');
	});
});
<commit_msg>Remove <extension> fields.<commit_after>var lineReader = require('line-reader');
var fs = require('fs');

var output = "";
var i = 1;
var skipLine = false;

NAMEOPENTAG = "<name>";
NAMECLOSETAG = "</name>";
TRACKOPENTAG = "<trk>";
TRACKCLOSETAG = "</trk>";
EXTOPENTAG = "<extensions>";
EXTCLOSETAG = "</extensions>";

// read all lines:
lineReader.eachLine('./passit/passit_2014.gpx', function(line) {
	var nameOpenTag = line.search(NAMEOPENTAG);
	var nameCloseTag = line.search(NAMECLOSETAG);
	var trackOpenTag = line.search(TRACKOPENTAG);
	var trackCloseTag = line.search(TRACKCLOSETAG);
	var extOpenTag = line.search(EXTOPENTAG);
	var extCloseTag = line.search(EXTCLOSETAG);

	if ((trackOpenTag >= 0) || (extOpenTag >= 0)) {
		skipLine = true;
	}

	// If track is not found yet, check the line content
	// If track is found then skip the line
	if (skipLine === false) {
		if (nameOpenTag >= 0) {
			var nameOrig = line.slice(nameOpenTag + NAMEOPENTAG.length, nameCloseTag);
			var tmp = nameOrig.replace(/[,:.]/gi, "");
			var newLine = line.replace(nameOrig, tmp);
			output += newLine;
			i++;
		} else {
			output += line;
		}
	}
	// Track closed
	if (((trackCloseTag >= 0) || (extCloseTag >= 0)) && (skipLine === true)) {
		skipLine = false;
	}
}).then(function () {
	console.log("I'm done!!");
    // All lines are read, file is closed now.
	fs.writeFile('./passit/passit_2014-mod.gpx', output, function (err) {
		if (err) throw err;
		console.log('It\'s saved!');
	});
});
<|endoftext|>