<commit_before>/*!
* jQuery Text Counter Plugin v0.3.6
* https://github.com/ractoon/jQuery-Text-Counter
*
* Copyright 2014 ractoon
* Released under the MIT license
*/
;(function($) {
  $.textcounter = function(el, options) {
    // To avoid scope issues, use 'base' instead of 'this'
    // to reference this class from internal events and functions.
    var base = this;

    // Access to jQuery and DOM versions of element
    base.$el = $(el);
    base.el = el;

    // Add a reverse reference to the DOM object
    base.$el.data("textcounter", base);

    base.init = function() {
      base.options = $.extend({}, $.textcounter.defaultOptions, options);

      // append the count element
      var counterText = base.options.countDown ? base.options.countDownText : base.options.counterText,
          counterNum = base.options.countDown ? base.options.max : 0;

      base.$el.after('<' + base.options.countContainerElement + ' class="' + base.options.countContainerClass + '">' + counterText + '' + counterNum + '</' + base.options.countContainerElement + '>');

      // bind input events
      base.$el.bind('keyup.textcounter click.textcounter blur.textcounter focus.textcounter change.textcounter paste.textcounter', base.checkLimits).trigger('click.textcounter');

      // TextCounter: init(el) Callback
      base.options.init(base.el);
    };

    base.checkLimits = function(e) {
      var $this = base.$el,
          $countEl = $this.nextAll('.' + base.options.countContainerClass),
          $text = $this.val(),
          textCount = 0,
          textTotalCount = 0,
          eventTriggered =  e.originalEvent === undefined ? false : true;

      if (!$.isEmptyObject($text)) {
        if (base.options.type == "word") {  // word count
          textCount = $text.trim().replace(/\s+/gi, ' ').split(' ').length;
        }
        else {  // character count
          if (base.options.countSpaces) { // if need to count spaces
            textCount = $text.replace(/[^\S\n|\r|\r\n]/g, ' ').length;
          }
          else {
            textCount = $text.replace(/\s/g, '').length;
          }

          if (base.options.countExtendedCharacters) {
            var extended = $text.match(/[^\x00-\xff]/gi);

            if (extended == null) {
              textCount = $text.length;
            } else {
              textCount = $text.length + extended.length;
            }
          }
        }
      }

      // if max is auto retrieve value
      if (base.options.max == 'auto') {
        var max = base.$el.attr('maxlength');

        if (typeof max !== 'undefined' && max !== false) {
          base.options.max = max;
        }
        else {
          base.$el.nextAll('.' + base.options.countContainerClass).text('error: [maxlength] attribute not set');
        }
      }

      // if this is a countdown counter deduct from the max characters/words
      textTotalCount = base.options.countDown ? base.options.max - textCount : textCount;

      // set the current text count
      base.setCount(textTotalCount);

      if (base.options.min > 0 && eventTriggered) {   // if a minimum value has been set
        if (textCount < base.options.min) {
          base.setErrors('min');

          // TextCounter: minunder(el) Callback
          base.options.minunder(base.el);
        }
        else if (textCount >= base.options.min) {
          // TextCounter: mincount(el) Callback
          base.options.mincount(base.el);

          base.clearErrors('min');
        }
      }

      if (base.options.max !== -1) {  // if a maximum value has been set
        if (textCount >= base.options.max && base.options.max != 0) {
          // TextCounter: maxcount(el) Callback
          base.options.maxcount(base.el);

          if (base.options.stopInputAtMaximum) {  // if the string should be trimmed at the maximum length
            var trimmedString = '';

            if (base.options.type == "word") {  // word type
              var wordArray = $text.split(/[^\S\n]/g);
              var i = 0;

              // iterate over individual words
              while (i < wordArray.length) {
                // if over the maximum words allowed break;
                if (i >= base.options.max - 1) break;

                if (wordArray[i] !== undefined) {
                  trimmedString += wordArray[i] + ' ';
                  i++;
                }
              }
            }
            else {  // character type
              if (base.options.countSpaces) {     // if spaces should be counted
                trimmedString = $text.substring(0, base.options.max);
              }
              else {
                var charArray = $text.split(''),
                    totalCharacters = charArray.length,
                    charCount = 0,
                    i = 0;

                while (charCount < base.options.max && i < totalCharacters) {
                  if (charArray[i] !== ' ') charCount++;
                  trimmedString += charArray[i++];
                }
              }
            }

            $this.val(trimmedString.trim());

            textTotalCount = base.options.countDown ? 0 : base.options.max;
            base.setCount(textTotalCount);
          } else {
            base.setErrors('max');
          }
        }
        else {
          // TextCounter: maxunder(el) Callback
          base.options.maxunder(base.el);
          base.clearErrors('max');
        }
      }
    };

    base.setCount = function(count) {
      var $this = base.$el,
          $countEl = $this.nextAll('.' + base.options.countContainerClass);

      $countEl.children('.' + base.options.textCountClass).text(count);
    };

    base.setErrors = function(type) {
      var $this = base.$el,
          $countEl = $this.nextAll('.' + base.options.countContainerClass);

      $this.addClass(base.options.inputErrorClass);
      $countEl.addClass(base.options.counterErrorClass);

      if (base.options.displayErrorText) {
        switch(type) {
          case 'min':
            errorText = base.options.minimumErrorText;
            break;
          case 'max':
            errorText = base.options.maximumErrorText;
            break;
        }

        if (!$countEl.children('.error-text-' + type).length) {
          $countEl.append('<' + base.options.errorTextElement + ' class="error-text error-text-' + type + '">' + errorText + '</' + base.options.errorTextElement + '>');
        }
      }
    };

    base.clearErrors = function(type) {
      var $this = base.$el,
          $countEl = $this.nextAll('.' + base.options.countContainerClass);

      $countEl.children('.error-text-' + type).remove();

      if ($countEl.children('.error-text').length == 0) {
        $this.removeClass(base.options.inputErrorClass);
        $countEl.removeClass(base.options.counterErrorClass);
      }
    };

    // kick it off
    base.init();
  };

  $.textcounter.defaultOptions = {
    'type'                      : "character",              // "character" or "word"
    'min'                       : 0,                        // minimum number of characters/words
    'max'                       : 200,                      // maximum number of characters/words, -1 for unlimited, 'auto' to use maxlength attribute
    'countContainerElement'     : "div",                    // HTML element to wrap the text count in
    'countContainerClass'       : "text-count-wrapper",     // class applied to the countContainerElement
    'textCountClass'            : "text-count",             // class applied to the counter length
    'inputErrorClass'           : "error",                  // error class appended to the input element if error occurs
    'counterErrorClass'         : "error",                  // error class appended to the countContainerElement if error occurs
    'counterText'               : "Total Count: ",          // counter text
    'errorTextElement'          : "div",                    // error text element
    'minimumErrorText'          : "Minimum not met",        // error message for minimum not met,
    'maximumErrorText'          : "Maximum exceeded",       // error message for maximum range exceeded,
    'displayErrorText'          : true,                     // display error text messages for minimum/maximum values
    'stopInputAtMaximum'        : true,                     // stop further text input if maximum reached
    'countSpaces'               : false,                    // count spaces as character (only for "character" type)
    'countDown'                 : false,                    // if the counter should deduct from maximum characters/words rather than counting up
    'countDownText'             : "Remaining: ",            // count down text
    'countExtendedCharacters'   : false,                    // count extended UTF-8 characters as 2 bytes (such as Chinese characters)

    // Callback API
    maxunder                     : function(el){},          //  Callback: function(element) - Fires when counter under max limit
    minunder                     : function(el){},          //  Callback: function(element) - Fires when counter under min limit
    maxcount                    : function(el){},           // Callback: function(element) - Fires when the counter hits the maximum word/character count
    mincount                    : function(el){},           // Callback: function(element) - Fires when the counter hits the minimum word/character count
    init                        : function(el){}            // Callback: function(element) - Fires after the counter is initially setup
  };

  $.fn.textcounter = function(options) {
    return this.each(function() {
      new $.textcounter(this, options);
    });
  };

})(jQuery);<commit_msg>Text alignment<commit_after>/*!
* jQuery Text Counter Plugin v0.3.6
* https://github.com/ractoon/jQuery-Text-Counter
*
* Copyright 2014 ractoon
* Released under the MIT license
*/
;(function($) {
  $.textcounter = function(el, options) {
    // To avoid scope issues, use 'base' instead of 'this'
    // to reference this class from internal events and functions.
    var base = this;

    // Access to jQuery and DOM versions of element
    base.$el = $(el);
    base.el = el;

    // Add a reverse reference to the DOM object
    base.$el.data("textcounter", base);

    base.init = function() {
      base.options = $.extend({}, $.textcounter.defaultOptions, options);

      // append the count element
      var counterText = base.options.countDown ? base.options.countDownText : base.options.counterText,
          counterNum = base.options.countDown ? base.options.max : 0;

      base.$el.after('<' + base.options.countContainerElement + ' class="' + base.options.countContainerClass + '">' + counterText + '' + counterNum + '</' + base.options.countContainerElement + '>');

      // bind input events
      base.$el.bind('keyup.textcounter click.textcounter blur.textcounter focus.textcounter change.textcounter paste.textcounter', base.checkLimits).trigger('click.textcounter');

      // TextCounter: init(el) Callback
      base.options.init(base.el);
    };

    base.checkLimits = function(e) {
      var $this = base.$el,
          $countEl = $this.nextAll('.' + base.options.countContainerClass),
          $text = $this.val(),
          textCount = 0,
          textTotalCount = 0,
          eventTriggered =  e.originalEvent === undefined ? false : true;

      if (!$.isEmptyObject($text)) {
        if (base.options.type == "word") {  // word count
          textCount = $text.trim().replace(/\s+/gi, ' ').split(' ').length;
        }
        else {  // character count
          if (base.options.countSpaces) { // if need to count spaces
            textCount = $text.replace(/[^\S\n|\r|\r\n]/g, ' ').length;
          }
          else {
            textCount = $text.replace(/\s/g, '').length;
          }

          if (base.options.countExtendedCharacters) {
            var extended = $text.match(/[^\x00-\xff]/gi);

            if (extended == null) {
              textCount = $text.length;
            } else {
              textCount = $text.length + extended.length;
            }
          }
        }
      }

      // if max is auto retrieve value
      if (base.options.max == 'auto') {
        var max = base.$el.attr('maxlength');

        if (typeof max !== 'undefined' && max !== false) {
          base.options.max = max;
        }
        else {
          base.$el.nextAll('.' + base.options.countContainerClass).text('error: [maxlength] attribute not set');
        }
      }

      // if this is a countdown counter deduct from the max characters/words
      textTotalCount = base.options.countDown ? base.options.max - textCount : textCount;

      // set the current text count
      base.setCount(textTotalCount);

      if (base.options.min > 0 && eventTriggered) {   // if a minimum value has been set
        if (textCount < base.options.min) {
          base.setErrors('min');

          // TextCounter: minunder(el) Callback
          base.options.minunder(base.el);
        }
        else if (textCount >= base.options.min) {
          // TextCounter: mincount(el) Callback
          base.options.mincount(base.el);

          base.clearErrors('min');
        }
      }

      if (base.options.max !== -1) {  // if a maximum value has been set
        if (textCount >= base.options.max && base.options.max != 0) {
          // TextCounter: maxcount(el) Callback
          base.options.maxcount(base.el);

          if (base.options.stopInputAtMaximum) {  // if the string should be trimmed at the maximum length
            var trimmedString = '';

            if (base.options.type == "word") {  // word type
              var wordArray = $text.split(/[^\S\n]/g);
              var i = 0;

              // iterate over individual words
              while (i < wordArray.length) {
                // if over the maximum words allowed break;
                if (i >= base.options.max - 1) break;

                if (wordArray[i] !== undefined) {
                  trimmedString += wordArray[i] + ' ';
                  i++;
                }
              }
            }
            else {  // character type
              if (base.options.countSpaces) {     // if spaces should be counted
                trimmedString = $text.substring(0, base.options.max);
              }
              else {
                var charArray = $text.split(''),
                    totalCharacters = charArray.length,
                    charCount = 0,
                    i = 0;

                while (charCount < base.options.max && i < totalCharacters) {
                  if (charArray[i] !== ' ') charCount++;
                  trimmedString += charArray[i++];
                }
              }
            }

            $this.val(trimmedString.trim());

            textTotalCount = base.options.countDown ? 0 : base.options.max;
            base.setCount(textTotalCount);
          } else {
            base.setErrors('max');
          }
        }
        else {
          // TextCounter: maxunder(el) Callback
          base.options.maxunder(base.el);
          base.clearErrors('max');
        }
      }
    };

    base.setCount = function(count) {
      var $this = base.$el,
          $countEl = $this.nextAll('.' + base.options.countContainerClass);

      $countEl.children('.' + base.options.textCountClass).text(count);
    };

    base.setErrors = function(type) {
      var $this = base.$el,
          $countEl = $this.nextAll('.' + base.options.countContainerClass);

      $this.addClass(base.options.inputErrorClass);
      $countEl.addClass(base.options.counterErrorClass);

      if (base.options.displayErrorText) {
        switch(type) {
          case 'min':
            errorText = base.options.minimumErrorText;
            break;
          case 'max':
            errorText = base.options.maximumErrorText;
            break;
        }

        if (!$countEl.children('.error-text-' + type).length) {
          $countEl.append('<' + base.options.errorTextElement + ' class="error-text error-text-' + type + '">' + errorText + '</' + base.options.errorTextElement + '>');
        }
      }
    };

    base.clearErrors = function(type) {
      var $this = base.$el,
          $countEl = $this.nextAll('.' + base.options.countContainerClass);

      $countEl.children('.error-text-' + type).remove();

      if ($countEl.children('.error-text').length == 0) {
        $this.removeClass(base.options.inputErrorClass);
        $countEl.removeClass(base.options.counterErrorClass);
      }
    };

    // kick it off
    base.init();
  };

  $.textcounter.defaultOptions = {
    'type'                      : "character",              // "character" or "word"
    'min'                       : 0,                        // minimum number of characters/words
    'max'                       : 200,                      // maximum number of characters/words, -1 for unlimited, 'auto' to use maxlength attribute
    'countContainerElement'     : "div",                    // HTML element to wrap the text count in
    'countContainerClass'       : "text-count-wrapper",     // class applied to the countContainerElement
    'textCountClass'            : "text-count",             // class applied to the counter length
    'inputErrorClass'           : "error",                  // error class appended to the input element if error occurs
    'counterErrorClass'         : "error",                  // error class appended to the countContainerElement if error occurs
    'counterText'               : "Total Count: ",          // counter text
    'errorTextElement'          : "div",                    // error text element
    'minimumErrorText'          : "Minimum not met",        // error message for minimum not met,
    'maximumErrorText'          : "Maximum exceeded",       // error message for maximum range exceeded,
    'displayErrorText'          : true,                     // display error text messages for minimum/maximum values
    'stopInputAtMaximum'        : true,                     // stop further text input if maximum reached
    'countSpaces'               : false,                    // count spaces as character (only for "character" type)
    'countDown'                 : false,                    // if the counter should deduct from maximum characters/words rather than counting up
    'countDownText'             : "Remaining: ",            // count down text
    'countExtendedCharacters'   : false,                    // count extended UTF-8 characters as 2 bytes (such as Chinese characters)

    // Callback API
    maxunder                    : function(el){},           //  Callback: function(element) - Fires when counter under max limit
    minunder                    : function(el){},           //  Callback: function(element) - Fires when counter under min limit
    maxcount                    : function(el){},           // Callback: function(element) - Fires when the counter hits the maximum word/character count
    mincount                    : function(el){},           // Callback: function(element) - Fires when the counter hits the minimum word/character count
    init                        : function(el){}            // Callback: function(element) - Fires after the counter is initially setup
  };

  $.fn.textcounter = function(options) {
    return this.each(function() {
      new $.textcounter(this, options);
    });
  };

})(jQuery);<|endoftext|>


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

/* Copyright 2012, Jonathan Cheung Licensed and released under the MIT
   license. Refer to MIT-LICENSE.txt.

   A nodejs script that allows you to watch a folder for changes and
   compile the less css files into another folder.

   Always give credit where it's due. Parts of this script is modified
   from Mikeal Rogers's watch script (https://github.com/mikeal/watch)

   Usage:     node less-watch-compiler.js FOLDER_TO_WATCH FOLDER_TO_OUTPUT
   Example:   "node less-watch-compiler.js less css" will watch ./less folder
              and compile the less css files into ./css when they are added/changed
*/
var allowedExtensions = ["less"];
var sys = require('util')
  , fs = require('fs')
  , path = require('path')
  , events = require('events')
  , exec = require('child_process').exec;

// Check to see if we have the correct number of arguments
var argvs = process.argv.slice(2);
if (!argvs[0] || !argvs[1]){
  console.log("Missing arguements");
  console.log("\tnode less-watch-compiler.js FOLDER_TO_WATCH FOLDER_TO_OUTPUT");
  console.log("\tExample:");
  process.exit(1);
}

// Walk the directory tree
function walk (dir, options, callback, initCallback) {
  if (!callback) {callback = options; options = {}}
  if (!callback.files) callback.files = {};
  if (!callback.pending) callback.pending = 0;
  callback.pending += 1;
  fs.stat(dir, function (err, stat) {
    if (err) return callback(err);
    callback.files[dir] = stat;
    fs.readdir(dir, function (err, files) {
      if (err) return callback(err);
      callback.pending -= 1;
      files.forEach(function (f, index) {
        f = path.join(dir, f);
        callback.pending += 1;
        fs.stat(f, function (err, stat) {
          var enoent = false
            , done = false;

          if (err) {
            if (err.code !== 'ENOENT') {
              return callback(err);
            } else {
              enoent = true;
            }
          }
          callback.pending -= 1;
          done = callback.pending === 0;
          if (!enoent) {
            if (options.ignoreDotFiles && path.basename(f)[0] === '.') return done && callback(null, callback.files);
            if (options.filter && options.filter(f, stat)) return done && callback(null, callback.files);
            callback.files[f] = stat;
            if (stat.isDirectory()) {
              walk(f, options, callback);
            }else{
              initCallback&&initCallback(f);
            }

            if (done) callback(null, callback.files);
          }
        })
      })
      if (callback.pending === 0) callback(null, callback.files);
    })
    if (callback.pending === 0) callback(null, callback.files);
  })

}

//Setup fs.watchFile() for each file.
var watchTree = function ( root, options, watchCallback, initCallback ) {
  if (!watchCallback) {watchCallback = options; options = {}}
  walk(root, options, function (err, files) {
    if (err) throw err;
    var fileWatcher = function (f) {
      fs.watchFile(f, options, function (c, p) {
        // Check if anything actually changed in stat
        if (files[f] && !files[f].isDirectory() && c.nlink !== 0 && files[f].mtime.getTime() == c.mtime.getTime()) return;
        files[f] = c;
        if (!files[f].isDirectory()) {
          if(options.ignoreDotFiles && (path.basename(f)[0] === '.')) return;
          if(options.filter&& options.filter(f, files[f])) return;
          watchCallback(f, c, p);
        }else {
          fs.readdir(f, function (err, nfiles) {
            if (err) return;
            nfiles.forEach(function (b) {
              var file = path.join(f, b);
              if (!files[file]) {
                fs.stat(file, function (err, stat) {
                  if(options.ignoreDotFiles && (path.basename(b)[0] === '.')) return;
                  if(options.filter&& options.filter(b, files[b])) return;
                  watchCallback(file, stat, null);
                  files[file] = stat;
                  fileWatcher(file);
                })
              }
            })
          })
        }
        if (c.nlink === 0) {
          // unwatch removed files.
          delete files[f]
          fs.unwatchFile(f);
        }
      })
    }

    fileWatcher(root);
    for (var i in files) {
      fileWatcher(i);
    }
    watchCallback(files, null, null);
  },
  initCallback);
}

// String function to retrieve the filename without the extension
function getFilenameWithoutExtention(string){
  //extract filename (xxx.less)
  //strip out the extension
  var filename = string.replace(/^.*[\\\/]/, '').split(".")[0];
  return filename
}

// String function to retrieve the file's extension
function getFileExtension(string){
  var extension = string.split(".").pop();
  if (extension == string) return ""
  else
  return extension;
}

// Here's where we run the less compiler
function compileCSS(file){
	  var filename = getFilenameWithoutExtention(file);
    var command = "lessc "+file.replace(/\s+/g,"\\ ")+" "+argvs[1]+"/"+filename.replace(/\s+/g,"\\ ")+".css";
	  console.log("Command: '"+command+"'");
    // Run the command
	  exec(command, function (error, stdout, stderr){
	  if (error !== null) {
	    console.log('exec error: ' + error);
      console.log("stdout : "+stdout)
      console.log("stderr : "+stderr)
	  }
  });
}

// This is the function we use to filter the files to watch.
function filterFiles(f, stat){
  var filename = getFilenameWithoutExtention(f);
  var extension = getFileExtension(f);
  if (filename.substr(0,1) == "_" ||
      filename.substr(0,1) == "." ||
      filename == "" ||
      allowedExtensions.indexOf(extension) == -1
      )
    return true;
  else{
    return false;
  }
}

// Here's where we setup the watch function
watchTree(
  argvs[0],
  {interval: 500, ignoreDotFiles:true,filter:filterFiles},
  function (f, curr, prev) {
    if (typeof f == "object" && prev === null && curr === null) {
      // Finished walking the tree
      return;
    } else if (curr.nlink === 0) {
      // f was removed
      console.log(f +" was removed.")
    }else {
      // f is a new file or changed
      console.log("The file: "+f+ " was changed.")
      console.log("Recompiling CSS.. "+Date());
      compileCSS(f);
    }
  },
  function(f){
  compileCSS(f);
  }
);
<commit_msg>Removed whitespace, added date function (For nice date output), corrected typos and outputted css is now fully compressed<commit_after>#!/usr/bin/env node

/* Copyright 2012, Jonathan Cheung Licensed and released under the MIT
   license. Refer to MIT-LICENSE.txt.

   A nodejs script that allows you to watch a folder for changes and
   compile the less css files into another folder.

   Always give credit where it's due. Parts of this script is modified
   from Mikeal Rogers's watch script (https://github.com/mikeal/watch)

   Usage:     node less-watch-compiler.js FOLDER_TO_WATCH FOLDER_TO_OUTPUT
   Example:   'node less-watch-compiler.js less css' will watch ./less folder
              and compile the less css files into ./css when they are added/changed
*/
var allowedExtensions = ['less'];
var sys = require('util')
  , fs = require('fs')
  , path = require('path')
  , events = require('events')
  , exec = require('child_process').exec;

// Check to see if we have the correct number of arguments
var argvs = process.argv.slice(2);
if (!argvs[0] || !argvs[1]){
  console.log('Missing arguments. Example:');
    console.log('\tnode less-watch-compiler.js FOLDER_TO_WATCH FOLDER_TO_OUTPUT');
  process.exit(1);
}

// Walk the directory tree
function walk (dir, options, callback, initCallback) {
  if (!callback) {callback = options; options = {}}
  if (!callback.files) callback.files = {};
  if (!callback.pending) callback.pending = 0;
  callback.pending += 1;
  fs.stat(dir, function (err, stat) {
    if (err) return callback(err);
    callback.files[dir] = stat;
    fs.readdir(dir, function (err, files) {
      if (err) return callback(err);
      callback.pending -= 1;
      files.forEach(function (f, index) {
        f = path.join(dir, f);
        callback.pending += 1;
        fs.stat(f, function (err, stat) {
          var enoent = false
            , done = false;

          if (err) {
            if (err.code !== 'ENOENT') {
              return callback(err);
            } else {
              enoent = true;
            }
          }
          callback.pending -= 1;
          done = callback.pending === 0;
          if (!enoent) {
            if (options.ignoreDotFiles && path.basename(f)[0] === '.') return done && callback(null, callback.files);
            if (options.filter && options.filter(f, stat)) return done && callback(null, callback.files);
            callback.files[f] = stat;
            if (stat.isDirectory()) {
              walk(f, options, callback);
            }else{
              initCallback&&initCallback(f);
            }

            if (done) callback(null, callback.files);
          }
        })
      })
      if (callback.pending === 0) callback(null, callback.files);
    })
    if (callback.pending === 0) callback(null, callback.files);
  })

}

//Setup fs.watchFile() for each file.
var watchTree = function ( root, options, watchCallback, initCallback ) {
  if (!watchCallback) {watchCallback = options; options = {}}
  walk(root, options, function (err, files) {
    if (err) throw err;
    var fileWatcher = function (f) {
      fs.watchFile(f, options, function (c, p) {
        // Check if anything actually changed in stat
        if (files[f] && !files[f].isDirectory() && c.nlink !== 0 && files[f].mtime.getTime() == c.mtime.getTime()) return;
        files[f] = c;
        if (!files[f].isDirectory()) {
          if(options.ignoreDotFiles && (path.basename(f)[0] === '.')) return;
          if(options.filter&& options.filter(f, files[f])) return;
          watchCallback(f, c, p);
        }else {
          fs.readdir(f, function (err, nfiles) {
            if (err) return;
            nfiles.forEach(function (b) {
              var file = path.join(f, b);
              if (!files[file]) {
                fs.stat(file, function (err, stat) {
                  if(options.ignoreDotFiles && (path.basename(b)[0] === '.')) return;
                  if(options.filter&& options.filter(b, files[b])) return;
                  watchCallback(file, stat, null);
                  files[file] = stat;
                  fileWatcher(file);
                })
              }
            })
          })
        }
        if (c.nlink === 0) {
          // unwatch removed files.
          delete files[f]
          fs.unwatchFile(f);
        }
      })
    }

    fileWatcher(root);
    for (var i in files) {
      fileWatcher(i);
    }
    watchCallback(files, null, null);
  },
  initCallback);
}

// String function to retrieve the filename without the extension
function getFilenameWithoutExtention(string){
  //extract filename (xxx.less)
  //strip out the extension
  var filename = string.replace(/^.*[\\\/]/, '').split('.')[0];
  return filename
}

// String function to retrieve the file's extension
function getFileExtension(string){
  var extension = string.split('.').pop();
  if (extension == string) return ''
  else
  return extension;
}

// Here's where we run the less compiler
function compileCSS(file){
    var filename = getFilenameWithoutExtention(file);
    var command = 'lessc --yui-compress '+file.replace(/\s+/g,'\\ ')+' '+argvs[1]+'/'+filename.replace(/\s+/g,'\\ ')+'.css';
    // Run the command
    exec(command, function (error, stdout, stderr){
      if (error !== null)
        console.log(error);
      if(stdout)
          console.error(stdout);
  });
}

// This is the function we use to filter the files to watch.
function filterFiles(f, stat){
  var filename = getFilenameWithoutExtention(f);
  var extension = getFileExtension(f);
  if (filename.substr(0,1) == '_' ||
      filename.substr(0,1) == '.' ||
      filename == '' ||
      allowedExtensions.indexOf(extension) == -1
      )
    return true;
  else{
    return false;
  }
}

function getDateTime() {

    var date = new Date();
    var hour = date.getHours();
    hour = (hour < 10 ? "0" : "") + hour;
    var min  = date.getMinutes();
    min = (min < 10 ? "0" : "") + min;
    var sec  = date.getSeconds();
    sec = (sec < 10 ? "0" : "") + sec;
    var year = date.getFullYear();
    var month = date.getMonth() + 1;
    month = (month < 10 ? "0" : "") + month;
    var day  = date.getDate();
    day = (day < 10 ? "0" : "") + day;
    return hour + ":" + min + ":" + sec + " on " + day + '/' + month + "/" + year;

}

// Here's where we setup the watch function
console.log('Watching directory for file changes.');
console.log('');
watchTree(
  argvs[0],
  {interval: 200, ignoreDotFiles: true, filter:filterFiles},
  function (f, curr, prev) {
    if (typeof f == 'object' && prev === null && curr === null) {
      // Finished walking the tree
      return;
    } else if (curr.nlink === 0) {
      // f was removed
      console.log(f +' was removed.')
    } else {
      // f is a new file or changed
      console.log('The file: ' + f + ' was changed. Recompiling CSS at ' + getDateTime());
      compileCSS(f);
    }
  },
  function(f){
     compileCSS(f);
  }
);
<|endoftext|>


<commit_before>'use strict';
const promise = require('request-promise');
const Anesidora = require("anesidora");
const Fuse = require('fuse.js');

let settings = {};

try {
  settings = require('../../settings.json');
} catch (e) {}

function getPandoraMetadata(id, title, auth) {
  return `<DIDL-Lite xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/"
        xmlns:r="urn:schemas-rinconnetworks-com:metadata-1-0/" xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/">
        <item id="OOOX${id}" parentID="0" restricted="true"><dc:title>${title}</dc:title><upnp:class>object.item.audioItem.audioBroadcast</upnp:class>
        <desc id="cdudn" nameSpace="urn:schemas-rinconnetworks-com:metadata-1-0/">SA_RINCON3_${auth}</desc></item></DIDL-Lite>`;
}

function getPandoraUri(id, title, albumart) {
  if (albumart == undefined) {
    return `pndrradio:${id}?sn=2`;
  } else {
    return `pndrradio:${id}?sn=2,"title":"${title}","albumArtUri":"${albumart}"`;
  }
}

function pandora(player, values) {
  const cmd = values[0];

  function userLogin() {
    return new Promise(function(resolve, reject) {
      pAPI.login(function(err) {
        if (!err) {
          resolve();
        } else {
          reject(err);
        }
      });
    });
  }

  function pandoraAPI(command, parameters) {
    return new Promise(function(resolve, reject) {
      pAPI.request(command, parameters, function(err, result) {
        if (!err) {
          resolve(result);
        } else {
          console.log("pandoraAPI " + command + " " + JSON.stringify(parameters));
          console.log("ERROR: " + JSON.stringify(err));
          reject(err);
        }
      });
    });
  }

  function playPandora(player, name) {
    var uri = '';
    var metadata = '';

    return userLogin()
      .then(() => pandoraAPI("user.getStationList", {"includeStationArtUrl" : true}))
      .then((stationList) => {
        return pandoraAPI("music.search", {"searchText": name})
          .then((result) => {
            if (result.artists != undefined) {
              result.artists.map(function(artist) {
                if (artist.score > 90) {
                  stationList.stations.push({"stationId":artist.musicToken,"stationName":artist.artistName,"type":"artist"});
                }
              });
            }
            if (result.songs != undefined) {
              result.songs.map(function(song) {
                if (song.score > 90) {
                  stationList.stations.push({"stationId":song.musicToken,"stationName":song.songName,"type":"song"});
                }
              });
            }
            return pandoraAPI("station.getGenreStations", {});
          })
          .then((result) => {
            result.categories.map(function(category) {
              category.stations.map(function(genreStation) {
                stationList.stations.push({"stationId":genreStation.stationToken,"stationName":genreStation.stationName,"type":"song"});
              });
            });
            var fuzzy = new Fuse(stationList.stations, { keys: ["stationName"] });

            const results = fuzzy.search(name);
            if (results.length > 0) {
              const station = results[0];
              if (station.type == undefined) {
                uri = getPandoraUri(station.stationId, station.stationName, station.artUrl);
                metadata = getPandoraMetadata(station.stationId, station.stationName, settings.pandora.username);
                return Promise.resolve();
              } else {
                return pandoraAPI("station.createStation", {"musicToken":station.stationId, "musicType":station.type})
                  .then((stationInfo) => {
                  	 uri = getPandoraUri(stationInfo.stationId);
                     metadata = getPandoraMetadata(stationInfo.stationId, stationInfo.stationName, settings.pandora.username);
                     return Promise.resolve();
                  });
              }
            } else {
              return Promise.reject("No match was found");
            }
          })
          .then(() => player.coordinator.setAVTransport(uri, metadata))
          .then(() => player.coordinator.play());
      });
  }

  if (settings && settings.pandora) {
    var pAPI = new Anesidora(settings.pandora.username, settings.pandora.password);

    if (cmd == 'play') {
      return playPandora(player, values[1]);
    } if ((cmd == 'thumbsup')||(cmd == 'thumbsdown')) {
      const uri = player.state.currentTrack.uri;

      if (uri.startsWith('pndrradio-http')) {
        const stationToken = uri.substring(uri.search('&x=') + 3);
        const trackToken = uri.substring(uri.search('&m=') + 3,uri.search('&f='));
        const up = (cmd == 'thumbsup');

        return pandoraAPI("station.addFeedback", {"stationToken" : stationToken, "trackToken" : trackToken, "isPositive" : up})
          .then(() => {
            if (cmd == 'thumbsdown') {
              return player.coordinator.nextTrack();
            }
          });
      } else {
        return Promise.reject('The music that is playing is not a Pandora station');
      }
    }
  } else {
    console.log('Missing Pandora settings');
    return Promise.reject('Missing Pandora settings');
  }

}

module.exports = function (api) {
  api.registerAction('pandora', pandora);
}

<commit_msg>Update pandora.js<commit_after>'use strict';
const promise = require('request-promise');
const Anesidora = require("anesidora");
const Fuse = require('fuse.js');

let settings = {};

try {
  settings = require('../../settings.json');
} catch (e) {}

function getPandoraMetadata(id, title, auth) {
  return `<DIDL-Lite xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/"
        xmlns:r="urn:schemas-rinconnetworks-com:metadata-1-0/" xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/">
        <item id="OOOX${id}" parentID="0" restricted="true"><dc:title>${title}</dc:title><upnp:class>object.item.audioItem.audioBroadcast</upnp:class>
        <desc id="cdudn" nameSpace="urn:schemas-rinconnetworks-com:metadata-1-0/">SA_RINCON3_${auth}</desc></item></DIDL-Lite>`;
}

function getPandoraUri(id, title, albumart) {
  if (albumart == undefined) {
    return `pndrradio:${id}?sn=2`;
  } else {
    return `pndrradio:${id}?sn=2,"title":"${title}","albumArtUri":"${albumart}"`;
  }
}

function pandora(player, values) {
  const cmd = values[0];

  function userLogin() {
    return new Promise(function(resolve, reject) {
      pAPI.login(function(err) {
        if (!err) {
          resolve();
        } else {
          reject(err);
        }
      });
    });
  }

  function pandoraAPI(command, parameters) {
    return new Promise(function(resolve, reject) {
      pAPI.request(command, parameters, function(err, result) {
        if (!err) {
          resolve(result);
        } else {
          console.log("pandoraAPI " + command + " " + JSON.stringify(parameters));
          console.log("ERROR: " + JSON.stringify(err));
          reject(err);
        }
      });
    });
  }

  function playPandora(player, name) {
    var uri = '';
    var metadata = '';

    return userLogin()
      .then(() => pandoraAPI("user.getStationList", {"includeStationArtUrl" : true}))
      .then((stationList) => {
        return pandoraAPI("music.search", {"searchText": name})
          .then((result) => {
            if (result.artists != undefined) {
              result.artists.map(function(artist) {
                if (artist.score > 90) {
                  stationList.stations.push({"stationId":artist.musicToken,"stationName":artist.artistName,"type":"artist"});
                }
              });
            }
            if (result.songs != undefined) {
              result.songs.map(function(song) {
                if (song.score > 90) {
                  stationList.stations.push({"stationId":song.musicToken,"stationName":song.songName,"type":"song"});
                }
              });
            }
            return pandoraAPI("station.getGenreStations", {});
          })
          .then((result) => {
            result.categories.map(function(category) {
              category.stations.map(function(genreStation) {
                stationList.stations.push({"stationId":genreStation.stationToken,"stationName":genreStation.stationName,"type":"song"});
              });
            });
            var fuzzy = new Fuse(stationList.stations, { keys: ["stationName"] });

            const results = fuzzy.search(name);
            if (results.length > 0) {
              const station = results[0];
              if (station.type == undefined) {
                uri = getPandoraUri(station.stationId, station.stationName, station.artUrl);
                metadata = getPandoraMetadata(station.stationId, station.stationName, settings.pandora.username);
                return Promise.resolve();
              } else {
                return pandoraAPI("station.createStation", {"musicToken":station.stationId, "musicType":station.type})
                  .then((stationInfo) => {
                  	 uri = getPandoraUri(stationInfo.stationId);
                     metadata = getPandoraMetadata(stationInfo.stationId, stationInfo.stationName, settings.pandora.username);
                     return Promise.resolve();
                  });
              }
            } else {
              return Promise.reject("No match was found");
            }
          })
          .then(() => player.coordinator.setAVTransport(uri, metadata))
          .then(() => player.coordinator.play());
      });
  }

  if (settings && settings.pandora) {
    var pAPI = new Anesidora(settings.pandora.username, settings.pandora.password);

    if (cmd == 'play') {
      return playPandora(player, values[1]);
    } if ((cmd == 'thumbsup')||(cmd == 'thumbsdown')) {
      const uri = player.state.currentTrack.uri;

      if (uri.startsWith('pndrradio-http')) {
        const stationToken = uri.substring(uri.search('&x=') + 3);
        const trackToken = uri.substring(uri.search('&m=') + 3,uri.search('&f='));
        const up = (cmd == 'thumbsup');

        return userLogin()
          .then(() => pandoraAPI("station.addFeedback", {"stationToken" : stationToken, "trackToken" : trackToken, "isPositive" : up}))
          .then(() => {
            if (cmd == 'thumbsdown') {
              return player.coordinator.nextTrack();
            }
          });
      } else {
        return Promise.reject('The music that is playing is not a Pandora station');
      }
    }
  } else {
    console.log('Missing Pandora settings');
    return Promise.reject('Missing Pandora settings');
  }

}

module.exports = function (api) {
  api.registerAction('pandora', pandora);
}

<|endoftext|>


<commit_before>var util = require('util');
var crypto = require('crypto');

function Command(options) {
  this._options = options || {};
}
Command.commandTypes = [];
Command.extend = function(targetClass) {
  if (targetClass.commandTypes)
    return;
  targetClass.commandTypes = [this];
  targetClass.prototype.isInstanceOf = function(commandType) {
    return (
      commandType &&
      this._commandTypes.indexOf(commandType) > -1
    );
  };
  Object.defineProperty(targetClass.prototype, 'dataset', {
    get: function() { return this._options.dataset; }
  });
  targetClass.isInstance = function(modelInstance) {
    return (
      modelInstance &&
      modelInstance.constructor.commandTypes &&
      modelInstance.constructor.commandTypes.indexOf(this) > -1
    );
  };
};
Command.extend(Command);

function RequestResponse(options) {
  Command.apply(this, arguments);
}
RequestResponse.extend = function(targetClass) {
  Command.extend(targetClass);
  if (targetClass.commandTypes.indexOf(this) > -1)
    return;
  targetClass.commandTypes.push(this);
  Object.defineProperty(targetClass.prototype, 'onRequest', {
    get: function() { return this._options.onRequest; }
  });
  Object.defineProperty(targetClass.prototype, 'onResponse', {
    get: function() { return this._options.onResponse; }
  });
};
RequestResponse.extend(RequestResponse);
exports.RequestResponse = RequestResponse;

function PublishSubscribe(options) {
  Command.apply(this, arguments);
}
PublishSubscribe.extend = function(targetClass) {
  Command.extend(targetClass);
  if (targetClass.commandTypes.indexOf(this) > -1)
    return;
  targetClass.commandTypes.push(this);
  Object.defineProperty(targetClass.prototype, 'onSubscribe', {
    get: function() { return this._options.onSubscribe; }
  });
  Object.defineProperty(targetClass.prototype, 'onSubscribed', {
    get: function() { return this._options.onSubscribed; }
  });
  Object.defineProperty(targetClass.prototype, 'onUnsubscribe', {
    get: function() { return this._options.onUnsubscribe; }
  });
  Object.defineProperty(targetClass.prototype, 'onUnsubscribed', {
    get: function() { return this._options.onUnsubscribed; }
  });
  Object.defineProperty(targetClass.prototype, 'notification', {
    get: function() { return this._options.notification; }
  });
  Object.defineProperty(targetClass.prototype, 'onNotify', {
    get: function() { return this._options.onNotify; }
  });
};
PublishSubscribe.extend(PublishSubscribe);
exports.PublishSubscribe = PublishSubscribe;

function HTTPCommand(options) {
  Command.apply(this, arguments);
}
HTTPCommand.extend = function(targetClass) {
  Command.extend(targetClass);
  if (targetClass.commandTypes.indexOf(this) > -1)
    return;
  targetClass.commandTypes.push(this);
  Object.defineProperty(targetClass.prototype, 'path', {
    get: function() { return this._options.path; }
  });
  Object.defineProperty(targetClass.prototype, 'method', {
    get: function() { return this._options.method || 'GET'; }
  });
};
HTTPCommand.extend(HTTPCommand);
exports.HTTPCommand = HTTPCommand;

function HTTPRequestResponse(options) {
  Command.apply(this, arguments);
}
HTTPRequestResponse.extend = function(targetClass) {
  HTTPCommand.extend(targetClass);
  RequestResponse.extend(targetClass);
  if (targetClass.commandTypes.indexOf(this) > -1)
    return;
  targetClass.commandTypes.push(this);
};
HTTPRequestResponse.extend(HTTPRequestResponse);
exports.HTTPRequestResponse = HTTPRequestResponse;

function HTTPStreaming(options) {
  Command.apply(this, arguments);
}
HTTPStreaming.extend = function(targetClass) {
  HTTPCommand.extend(targetClass);
  if (targetClass.commandTypes.indexOf(this) > -1)
    return;
  targetClass.commandTypes.push(this);

  Object.defineProperty(targetClass.prototype, 'subscription', {
    get: function() { return this._options.subscription; }
  });
  Object.defineProperty(targetClass.prototype, 'unsubscription', {
    get: function() { return this._options.unsubscription; }
  });
  Object.defineProperty(targetClass.prototype, 'notification', {
    get: function() { return this._options.notification; }
  });
  Object.defineProperty(targetClass.prototype, 'delimiter', {
    get: function() { return this._options.delimiter || targetClass.defaultDelimiter; }
  });
  if (!targetClass.defaultDelimiter)
    targetClass.defaultDelimiter = '\n';

  Object.defineProperty(targetClass.prototype, 'createSubscription', {
    get: function() { return this._options.createSubscription; }
  });

  var connectionsCount = 0;
  targetClass.prototype.onHandle = function(request, response, connection) {
    connectionsCount++;

    response.writeHead(200, {
      'Content-Type':      'application/json',
      'Transfer-Encoding': 'chunked'
    });

    var delimiter = this.delimiter;
    connection.on(this.notification, function(data) {
      response.write(JSON.stringify(data) + delimiter);
    });

    var subscriptionMessage = this.createSubscription(request);
    if (!subscriptionMessage.route) {
      var route = connection.routeToSelf;
      subscriptionMessage.route = route;
    }
    if (!subscriptionMessage.subscriber) {
      var subscriberID = sha1sum(route + '#type=' + this.notification + '&id=' + connectionsCount);
      subscriptionMessage.subscriber = subscriberID;
    }
    connection.emit(this.subscription, subscriptionMessage);

// XXX How we handle the disconnection?
//    var self = this;
//    request.on('???', function() {
//      connection.emit(self.unsubscription, subscriptionMessage);
//    });
  };
};
HTTPStreaming.extend(HTTPStreaming);
exports.HTTPStreaming = HTTPStreaming;

function SocketCommand() {
  Command.apply(this, arguments);
}
SocketCommand.extend = function(targetClass) {
  Command.extend(targetClass);
  if (targetClass.commandTypes.indexOf(this) > -1)
    return;
  targetClass.commandTypes.push(this);
};
SocketCommand.extend(SocketCommand);
exports.SocketCommand = SocketCommand;

function SocketRequestResponse(options) {
  Command.apply(this, arguments);
}
SocketRequestResponse.extend = function(targetClass) {
  SocketCommand.extend(targetClass);
  RequestResponse.extend(targetClass);
  if (targetClass.commandTypes.indexOf(this) > -1)
    return;
  targetClass.commandTypes.push(this);
};
SocketRequestResponse.extend(SocketRequestResponse);
exports.SocketRequestResponse = SocketRequestResponse;

function SocketPublishSubscribe(options) {
  Command.apply(this, arguments);
}
SocketPublishSubscribe.extend = function(targetClass) {
  SocketCommand.extend(targetClass);
  PublishSubscribe.extend(targetClass);
  if (targetClass.commandTypes.indexOf(this) > -1)
    return;
  targetClass.commandTypes.push(this);
};
SocketPublishSubscribe.extend(SocketPublishSubscribe);
exports.SocketPublishSubscribe = SocketPublishSubscribe;

function sha1sum(source) {
  var hash = crypto.createHash('sha1');
  hash = hash.update(source);
  return hash.digest('hex');
}
exports.sha1sum = sha1sum;
<commit_msg>Return response as application/json"s"<commit_after>var util = require('util');
var crypto = require('crypto');

function Command(options) {
  this._options = options || {};
}
Command.commandTypes = [];
Command.extend = function(targetClass) {
  if (targetClass.commandTypes)
    return;
  targetClass.commandTypes = [this];
  targetClass.prototype.isInstanceOf = function(commandType) {
    return (
      commandType &&
      this._commandTypes.indexOf(commandType) > -1
    );
  };
  Object.defineProperty(targetClass.prototype, 'dataset', {
    get: function() { return this._options.dataset; }
  });
  targetClass.isInstance = function(modelInstance) {
    return (
      modelInstance &&
      modelInstance.constructor.commandTypes &&
      modelInstance.constructor.commandTypes.indexOf(this) > -1
    );
  };
};
Command.extend(Command);

function RequestResponse(options) {
  Command.apply(this, arguments);
}
RequestResponse.extend = function(targetClass) {
  Command.extend(targetClass);
  if (targetClass.commandTypes.indexOf(this) > -1)
    return;
  targetClass.commandTypes.push(this);
  Object.defineProperty(targetClass.prototype, 'onRequest', {
    get: function() { return this._options.onRequest; }
  });
  Object.defineProperty(targetClass.prototype, 'onResponse', {
    get: function() { return this._options.onResponse; }
  });
};
RequestResponse.extend(RequestResponse);
exports.RequestResponse = RequestResponse;

function PublishSubscribe(options) {
  Command.apply(this, arguments);
}
PublishSubscribe.extend = function(targetClass) {
  Command.extend(targetClass);
  if (targetClass.commandTypes.indexOf(this) > -1)
    return;
  targetClass.commandTypes.push(this);
  Object.defineProperty(targetClass.prototype, 'onSubscribe', {
    get: function() { return this._options.onSubscribe; }
  });
  Object.defineProperty(targetClass.prototype, 'onSubscribed', {
    get: function() { return this._options.onSubscribed; }
  });
  Object.defineProperty(targetClass.prototype, 'onUnsubscribe', {
    get: function() { return this._options.onUnsubscribe; }
  });
  Object.defineProperty(targetClass.prototype, 'onUnsubscribed', {
    get: function() { return this._options.onUnsubscribed; }
  });
  Object.defineProperty(targetClass.prototype, 'notification', {
    get: function() { return this._options.notification; }
  });
  Object.defineProperty(targetClass.prototype, 'onNotify', {
    get: function() { return this._options.onNotify; }
  });
};
PublishSubscribe.extend(PublishSubscribe);
exports.PublishSubscribe = PublishSubscribe;

function HTTPCommand(options) {
  Command.apply(this, arguments);
}
HTTPCommand.extend = function(targetClass) {
  Command.extend(targetClass);
  if (targetClass.commandTypes.indexOf(this) > -1)
    return;
  targetClass.commandTypes.push(this);
  Object.defineProperty(targetClass.prototype, 'path', {
    get: function() { return this._options.path; }
  });
  Object.defineProperty(targetClass.prototype, 'method', {
    get: function() { return this._options.method || 'GET'; }
  });
};
HTTPCommand.extend(HTTPCommand);
exports.HTTPCommand = HTTPCommand;

function HTTPRequestResponse(options) {
  Command.apply(this, arguments);
}
HTTPRequestResponse.extend = function(targetClass) {
  HTTPCommand.extend(targetClass);
  RequestResponse.extend(targetClass);
  if (targetClass.commandTypes.indexOf(this) > -1)
    return;
  targetClass.commandTypes.push(this);
};
HTTPRequestResponse.extend(HTTPRequestResponse);
exports.HTTPRequestResponse = HTTPRequestResponse;

function HTTPStreaming(options) {
  Command.apply(this, arguments);
}
HTTPStreaming.extend = function(targetClass) {
  HTTPCommand.extend(targetClass);
  if (targetClass.commandTypes.indexOf(this) > -1)
    return;
  targetClass.commandTypes.push(this);

  Object.defineProperty(targetClass.prototype, 'subscription', {
    get: function() { return this._options.subscription; }
  });
  Object.defineProperty(targetClass.prototype, 'unsubscription', {
    get: function() { return this._options.unsubscription; }
  });
  Object.defineProperty(targetClass.prototype, 'notification', {
    get: function() { return this._options.notification; }
  });
  Object.defineProperty(targetClass.prototype, 'delimiter', {
    get: function() { return this._options.delimiter || targetClass.defaultDelimiter; }
  });
  if (!targetClass.defaultDelimiter)
    targetClass.defaultDelimiter = '\n';

  Object.defineProperty(targetClass.prototype, 'createSubscription', {
    get: function() { return this._options.createSubscription; }
  });

  var connectionsCount = 0;
  targetClass.prototype.onHandle = function(request, response, connection) {
    connectionsCount++;

    response.writeHead(200, {
      'Content-Type':      'application/jsons',
      'Transfer-Encoding': 'chunked'
    });

    var delimiter = this.delimiter;
    connection.on(this.notification, function(data) {
      response.write(JSON.stringify(data) + delimiter);
    });

    var subscriptionMessage = this.createSubscription(request);
    if (!subscriptionMessage.route) {
      var route = connection.routeToSelf;
      subscriptionMessage.route = route;
    }
    if (!subscriptionMessage.subscriber) {
      var subscriberID = sha1sum(route + '#type=' + this.notification + '&id=' + connectionsCount);
      subscriptionMessage.subscriber = subscriberID;
    }
    connection.emit(this.subscription, subscriptionMessage);

// XXX How we handle the disconnection?
//    var self = this;
//    request.on('???', function() {
//      connection.emit(self.unsubscription, subscriptionMessage);
//    });
  };
};
HTTPStreaming.extend(HTTPStreaming);
exports.HTTPStreaming = HTTPStreaming;

function SocketCommand() {
  Command.apply(this, arguments);
}
SocketCommand.extend = function(targetClass) {
  Command.extend(targetClass);
  if (targetClass.commandTypes.indexOf(this) > -1)
    return;
  targetClass.commandTypes.push(this);
};
SocketCommand.extend(SocketCommand);
exports.SocketCommand = SocketCommand;

function SocketRequestResponse(options) {
  Command.apply(this, arguments);
}
SocketRequestResponse.extend = function(targetClass) {
  SocketCommand.extend(targetClass);
  RequestResponse.extend(targetClass);
  if (targetClass.commandTypes.indexOf(this) > -1)
    return;
  targetClass.commandTypes.push(this);
};
SocketRequestResponse.extend(SocketRequestResponse);
exports.SocketRequestResponse = SocketRequestResponse;

function SocketPublishSubscribe(options) {
  Command.apply(this, arguments);
}
SocketPublishSubscribe.extend = function(targetClass) {
  SocketCommand.extend(targetClass);
  PublishSubscribe.extend(targetClass);
  if (targetClass.commandTypes.indexOf(this) > -1)
    return;
  targetClass.commandTypes.push(this);
};
SocketPublishSubscribe.extend(SocketPublishSubscribe);
exports.SocketPublishSubscribe = SocketPublishSubscribe;

function sha1sum(source) {
  var hash = crypto.createHash('sha1');
  hash = hash.update(source);
  return hash.digest('hex');
}
exports.sha1sum = sha1sum;
<|endoftext|>


<commit_before>const Boom = require('boom');
const Controller = require('../controller');
// const {Issuer} = require('openid-client');
const User = require('./user');
const {hash_verify, jwt_sign} = require('../helpers/security');
const Sharp = require('../../vendor/sharp/index');
const {upload} = require('../../vendor/minio');

class AuthController extends Controller {

    constructor(auth_options) {
        super({
            prefix: '/api/auth',
            routes: {
                profile_post: {
                    auth: {mode: 'required'},
                    payload: {
                        maxBytes: 1048576 * 16,
                    }
                },
                profile: {
                    auth: {mode: 'required'}
                }
            }
        });

        this.auth_options = auth_options;

        // this._init_oauth_client();
    }

    async login_post(request, reply, _user) {
        let {username, password} = request.payload;

        // Prefix username
        if (this.auth_options.username_prefix &&
            username.indexOf(this.auth_options.username_prefix) === -1)
            username += this.auth_options.username_prefix;

        // Find user
        let user = await User.findOne({email: username});
        if (!user) return reply(Boom.unauthorized("User not found"));

        // Check password
        let verified = await hash_verify(password, user.get('password'));
        if (verified !== true) return reply(Boom.unauthorized("Invalid credentials"));

        // Create new session
        let session = user.sessions.create({
            agent: request.headers['user-agent'],
            ip: request.info['remoteAddress']
        });

        // Revoke any older sessions of user with same user-agent
        user.sessions = user.sessions.filter(s => (s.agent != session.agent));

        // Add new session
        user.sessions.push(session);
        await user.save();

        // Sign session token
        let id_token = await jwt_sign({u: user._id, s: session._id}, this.auth_options.secret);

        return reply({id_token});
    }

    profile(request, reply, user) {
        reply({user});
    }

    async profile_post(request, reply, user) {
        // Upload profile photo
        let avatar = request.payload.avatar;

        if (avatar instanceof Buffer) {
            try {
                let img = await Sharp(avatar).resize(128, 128).webp({quality: 100}).toBuffer();
                user.avatar_etag = await upload('avatar', user._id + '.webp', img);
                await user.save();
            } catch (e) {
                return reply(Boom.badRequest("Error while uploading avatar"));
            }
        }

        reply({user});
    }

    // ==============================
    // OpenId Client functionality
    // ==============================
    // init_oauth_client() {
    //     // if (this.auth_options.client) {
    //     // const issuer = await Issuer.discover(this.auth_options.client.discover_url);
    //     // this.client = new issuer.Client(this.auth_options.client);
    //     // }
    // }
    //
    // oauth_login(request, reply, user) {
    //     if (!this.client) return reply(Boom.serverUnavailable("oauth"));
    //
    //     let opts = {
    //         redirect_uri: this.auth_options.redirect_uri,
    //         scope: 'profile email phone'
    //     };
    //
    //     reply(this.client.authorizationPost(opts));
    // }
    //
    // async oauth_callback(request, reply, user) {
    //     if (!this.client) return reply(Boom.serverUnavailable("oauth"));
    //
    //     console.log("Callback");
    //     let tokenSet = await this.client.authorizationCallback(this.auth_options.redirect_uri, request.query);
    //     console.log('received and validated tokens %j', tokenSet);
    //     console.log('validated id_token claims %j', tokenSet.claims);
    //
    //     reply(this.client.authorizationPost(opts));
    // }

}

module.exports = AuthController;<commit_msg>/auth/profile ~> /auth/user<commit_after>const Boom = require('boom');
const Controller = require('../controller');
// const {Issuer} = require('openid-client');
const User = require('./user');
const {hash_verify, jwt_sign} = require('../helpers/security');
const Sharp = require('../../vendor/sharp/index');
const {upload} = require('../../vendor/minio');

class AuthController extends Controller {

    constructor(auth_options) {
        super({
            prefix: '/api/auth',
            routes: {
                profile_post: {
                    auth: {mode: 'required'},
                    payload: {
                        maxBytes: 1048576 * 16,
                    }
                },
                profile: {
                    auth: {mode: 'required'}
                }
            }
        });

        this.auth_options = auth_options;

        // this._init_oauth_client();
    }

    async login_post(request, reply, _user) {
        let {username, password} = request.payload;

        // Prefix username
        if (this.auth_options.username_prefix &&
            username.indexOf(this.auth_options.username_prefix) === -1)
            username += this.auth_options.username_prefix;

        // Find user
        let user = await User.findOne({email: username});
        if (!user) return reply(Boom.unauthorized("User not found"));

        // Check password
        let verified = await hash_verify(password, user.get('password'));
        if (verified !== true) return reply(Boom.unauthorized("Invalid credentials"));

        // Create new session
        let session = user.sessions.create({
            agent: request.headers['user-agent'],
            ip: request.info['remoteAddress']
        });

        // Revoke any older sessions of user with same user-agent
        user.sessions = user.sessions.filter(s => (s.agent != session.agent));

        // Add new session
        user.sessions.push(session);
        await user.save();

        // Sign session token
        let id_token = await jwt_sign({u: user._id, s: session._id}, this.auth_options.secret);

        return reply({id_token});
    }

    user(request, reply, user) {
        reply({user});
    }

    async user_post(request, reply, user) {
        // Upload profile photo
        let avatar = request.payload.avatar;

        if (avatar instanceof Buffer) {
            try {
                let img = await Sharp(avatar).resize(128, 128).webp({quality: 100}).toBuffer();
                user.avatar_etag = await upload('avatar', user._id + '.webp', img);
                await user.save();
            } catch (e) {
                return reply(Boom.badRequest("Error while uploading avatar"));
            }
        }

        reply({user});
    }

    // ==============================
    // OpenId Client functionality
    // ==============================
    // init_oauth_client() {
    //     // if (this.auth_options.client) {
    //     // const issuer = await Issuer.discover(this.auth_options.client.discover_url);
    //     // this.client = new issuer.Client(this.auth_options.client);
    //     // }
    // }
    //
    // oauth_login(request, reply, user) {
    //     if (!this.client) return reply(Boom.serverUnavailable("oauth"));
    //
    //     let opts = {
    //         redirect_uri: this.auth_options.redirect_uri,
    //         scope: 'profile email phone'
    //     };
    //
    //     reply(this.client.authorizationPost(opts));
    // }
    //
    // async oauth_callback(request, reply, user) {
    //     if (!this.client) return reply(Boom.serverUnavailable("oauth"));
    //
    //     console.log("Callback");
    //     let tokenSet = await this.client.authorizationCallback(this.auth_options.redirect_uri, request.query);
    //     console.log('received and validated tokens %j', tokenSet);
    //     console.log('validated id_token claims %j', tokenSet.claims);
    //
    //     reply(this.client.authorizationPost(opts));
    // }

}

module.exports = AuthController;<|endoftext|>


<commit_before>var cleanError = require('../tools').cleanError;

module.exports = {};

module.exports.execute = function (code, args) {
  "use strict";

  var self =  this;

  if (args === undefined) {
    args = [];
  }

  if (typeof code !== 'string' && typeof code !== 'function') {
    throw new Error('`code` has to be either string or a function')
  }

  if (!Array.isArray(args)) {
    throw new Error('`args` has to be an array');
  }

  return self.__custom__(function (operand, done) {
    var closure  = operand.closure ? operand.closure() : {};

    code = wrapSourceCode(codeToString(code), args, closure);

    operand.browser.execute("return (" + code + ").apply(null, arguments)",
        values(closure), feedbackProcessor(operand.closure.bind(operand), done));
  });
};

module.exports.timeout = function (ms) {
  this._timeout = ms;
  return this;
};

module.exports.promise = function (code, args) {
  "use strict";

  var self = this;

  if (args === undefined) {
    args = [];
  }

  if (typeof code !== 'string' && typeof code !== 'function') {
    throw new Error('`code` has to be either string or a function')
  }

  if (!Array.isArray(args)) {
    throw new Error('`args` has to be an array');
  }

  // we could set this 5000 globally, right?

  return self.__custom__(function (operand, done) {

    operand.browser.setAsyncScriptTimeout(self._timeout || 5000, done);

  }).__custom__(function (operand, done) {

    var closure = operand.closure ? operand.closure() : {};
    var chunks  = [];

    var keys = Object.keys(closure).map(function (key) {
      return stringify(key) + ": " + key;
    }).join(',');

    // stringify arguments
    args = args.map(stringify);

    args.unshift("(function (cb) {\n    return function ($) {\n      setTimeout( function () { cb({ error : ($ && typeof $ === 'object') ? $.message : $.toString()," +
      " closure: {" + keys + "}}); });\n    };\n  })(arguments[arguments.length-1])");

    args.unshift("(function (cb) {\n    return function ($) {\n      setTimeout( function () { cb({ value : $, closure: {" +
      keys + "}}); });\n    };\n  })(arguments[arguments.length-1])");

    chunks.push(
      "function (" + Object.keys(closure).join(', ') + ") {",
      "  'use strict';",
      "  var either = function (first) {",
      "    return {",
      "      or: function (second) {",
      "        return function (arg1, arg2) {",
      "          return arg1 ? first(arg1) : second(arg2);",
      "        };",
      "      }",
      "    };",
      "  };",
      "  try {",
      "    (" + codeToString(code) + ")(",
      "    " + args.join(', ') + ");",
      "  } catch ($) {",
      "    arguments[arguments.length-1]({",
      "      error   : $.message,",
      "      closure : { " + keys + " }",
      "    });",
      "  }",
      "}"
    );

    //console.log(chunks.join('\n'))

    code = chunks.join('\n');

    // TODO: how come "args" instead of values(closure) was passing as well?
    operand.browser.executeAsync("(" + code + ").apply(null, arguments)",
      values(closure), feedbackProcessor(operand.closure.bind(operand), done));
  });

};

module.exports.wait = function (timeout, message, code, args) {
  "use strict";

  if (args === undefined) {
    args = [];
  }

  if (typeof timeout !== 'number') {
    throw new Error('`timeout` has to be a number');
  }

  if (typeof message !== 'string') {
    throw new Error('`message` has to be a string');
  }

  if (typeof code !== 'string' && typeof code !== 'function') {
    throw new Error('`code` has to be either string or a function')
  }

  if (!Array.isArray(args)) {
    throw new Error('`args` has to be an array');
  }

  var self = this;

  return self.__custom__(function (operand, done) {

    operand.browser.setAsyncScriptTimeout(2 * timeout, done);

  }).__custom__(function (operand, done) {

    var closure = operand.closure ? operand.closure() : {};
    var chunks  = [];

    var keys = Object.keys(closure).map(function (key) {
      return stringify(key) + ": " + key;
    }).join(',');

    args = args.map(stringify);

    chunks.push("function (" + Object.keys(closure).join(', ') + ") {");

    chunks.push(
      '  "use strict";',
      '  var cb = arguments[arguments.length - 1];',
      '  var handle1 = null;',
      '  var handle2 = window.setTimeout(function () {',
      '    window.clearTimeout(handle1);',
      '    cb({ closure: {' + keys + '}, error: ' + JSON.stringify('I have been waiting for ' + timeout + ' ms ' + message + ', but it did not happen.') + ' });',
      '  }, ' + JSON.stringify(timeout) + ');',
      '  (function test() {',
      '    var value;',
      '    try {',
      '      value = (' + codeToString(code) + ')(' + args.join(', ') + ');',
      '      if (value) {',
      '        window.clearTimeout(handle2);',
      '        cb({ value: value, closure: {' + keys + '} });',
      '      } else {',
      '        handle1 = window.setTimeout(test, 50);', // repeat after 1/20 sec.
      '      }',
      '    } catch (err) {',
      '      window.clearTimeout(handle2);',
      '      cb({ error: err.message, closure: {' + keys + '} });',
      '    }',
      '  }());'
    );

    chunks.push('}');

    code = chunks.join('\n');

    operand.browser.executeAsync("(" + code + ").apply(null, arguments)", values(closure),
      feedbackProcessor(operand.closure.bind(operand), done));
  });

};

function values(closure) {
  "use strict";

  var values = Object.keys(closure).map(function (key) {
    return closure[key];
  });
  if (arguments.length > 1) {
    values.push.apply(values, Array.prototype.slice.call(arguments, 1));
  }
  return values;
}

function stringify(value) {
  "use strict";

  if (typeof value === 'function') {
    return value.toString();
  }
  return value !== undefined ? JSON.stringify(value) : "undefined";
}

function codeToString(code) {
  "use strict";

  var test;

  if (typeof code === 'string' && !/^function\s+\(/.test(code)) {
    return 'function () {\n' + code + '\n}';
  }
  if (typeof code === 'function') {
    return code.toString();
  }

  eval("test = " + code); // XXX it may throw on syntax error

  return code;
}

function feedbackProcessor(closure, cb) {
  "use strict";

  return function (err, feedback) {
    if (err) {
      return cb(err);
    }
    if (feedback.closure) {
      closure(feedback.closure);
    }
    if (feedback.error) {
      return cb(cleanError(feedback.error));
    }
    cb(null, feedback.value);
  }
}

function wrapSourceCode(code, args, closure) {
  "use strict";

  var chunks = [];

  chunks.push("function (" + Object.keys(closure).join(', ') + ") {");

  //addSyncChunks(chunks, closure, accessor);

  chunks.push(
    "  try {",
    "    return (function ($) {",
    "      return {",
    "        closure: {"
  );

  Object.keys(closure).forEach(function (key) {
    chunks.push("          " + stringify(key) + ": " + key + ",");
  });

  chunks.push(
    "        },",
    "        value: $,",
    "      };",
    "    })( (" + code + ")(" + args.map(stringify).join(',') + ") );",
    "  } catch (err) {",
    "    return {",
    "      closure: {"
  );

  Object.keys(closure).forEach(function (key) {
    chunks.push("        " + stringify(key) + ": " + key + ",");
  });

  chunks.push(
    "      },",
    "      error: err.message",
    "    };",
    "  }",
    "}"
  );

  return chunks.join('\n');
}
<commit_msg>Retry when there's no chai<commit_after>var cleanError = require('../tools').cleanError;
var either     = require('../tools').either;

module.exports = {};

module.exports.execute = function (code, args) {
  "use strict";

  var self =  this;

  if (args === undefined) {
    args = [];
  }

  if (typeof code !== 'string' && typeof code !== 'function') {
    throw new Error('`code` has to be either string or a function')
  }

  if (!Array.isArray(args)) {
    throw new Error('`args` has to be an array');
  }

  return self.__custom__(function (operand, done) {

    if (this.lastError) {
      if (this.retryCount <= 1 && /chai not found/.test(this.lastError.message)) {
        operand.browser.execute("window.chai = {}", either(done).or(doAction));
      } else {
        done(this.lastError);
      }
    } else {
      doAction();
    }

    function doAction() {
      var closure  = operand.closure ? operand.closure() : {};

      operand.browser.execute("return (" + wrapSourceCode(codeToString(code), args, closure) + ").apply(null, arguments)",
          values(closure), feedbackProcessor(operand.closure.bind(operand), done));
    }

    return true; // retry on first attempt
  });
};

module.exports.timeout = function (ms) {
  this._timeout = ms;
  return this;
};

module.exports.promise = function (code, args) {
  "use strict";

  var self = this;

  if (args === undefined) {
    args = [];
  }

  if (typeof code !== 'string' && typeof code !== 'function') {
    throw new Error('`code` has to be either string or a function')
  }

  if (!Array.isArray(args)) {
    throw new Error('`args` has to be an array');
  }

  // we could set this 5000 globally, right?

  return self.__custom__(function (operand, done) {

    operand.browser.setAsyncScriptTimeout(self._timeout || 5000, done);

  }).__custom__(function (operand, done) {

    var closure = operand.closure ? operand.closure() : {};
    var chunks  = [];

    var keys = Object.keys(closure).map(function (key) {
      return stringify(key) + ": " + key;
    }).join(',');

    // stringify arguments
    args = args.map(stringify);

    args.unshift("(function (cb) {\n    return function ($) {\n      setTimeout( function () { cb({ error : ($ && typeof $ === 'object') ? $.message : $.toString()," +
      " closure: {" + keys + "}}); });\n    };\n  })(arguments[arguments.length-1])");

    args.unshift("(function (cb) {\n    return function ($) {\n      setTimeout( function () { cb({ value : $, closure: {" +
      keys + "}}); });\n    };\n  })(arguments[arguments.length-1])");

    chunks.push(
      "function (" + Object.keys(closure).join(', ') + ") {",
      "  'use strict';",
      "  var either = function (first) {",
      "    return {",
      "      or: function (second) {",
      "        return function (arg1, arg2) {",
      "          return arg1 ? first(arg1) : second(arg2);",
      "        };",
      "      }",
      "    };",
      "  };",
      "  try {",
      "    (" + codeToString(code) + ")(",
      "    " + args.join(', ') + ");",
      "  } catch ($) {",
      "    arguments[arguments.length-1]({",
      "      error   : $.message,",
      "      closure : { " + keys + " }",
      "    });",
      "  }",
      "}"
    );

    //console.log(chunks.join('\n'))

    code = chunks.join('\n');

    // TODO: how come "args" instead of values(closure) was passing as well?
    operand.browser.executeAsync("(" + code + ").apply(null, arguments)",
      values(closure), feedbackProcessor(operand.closure.bind(operand), done));
  });

};

module.exports.wait = function (timeout, message, code, args) {
  "use strict";

  if (args === undefined) {
    args = [];
  }

  if (typeof timeout !== 'number') {
    throw new Error('`timeout` has to be a number');
  }

  if (typeof message !== 'string') {
    throw new Error('`message` has to be a string');
  }

  if (typeof code !== 'string' && typeof code !== 'function') {
    throw new Error('`code` has to be either string or a function')
  }

  if (!Array.isArray(args)) {
    throw new Error('`args` has to be an array');
  }

  var self = this;

  return self.__custom__(function (operand, done) {

    operand.browser.setAsyncScriptTimeout(2 * timeout, done);

  }).__custom__(function (operand, done) {

    var closure = operand.closure ? operand.closure() : {};
    var chunks  = [];

    var keys = Object.keys(closure).map(function (key) {
      return stringify(key) + ": " + key;
    }).join(',');

    args = args.map(stringify);

    chunks.push("function (" + Object.keys(closure).join(', ') + ") {");

    chunks.push(
      '  "use strict";',
      '  var cb = arguments[arguments.length - 1];',
      '  var handle1 = null;',
      '  var handle2 = window.setTimeout(function () {',
      '    window.clearTimeout(handle1);',
      '    cb({ closure: {' + keys + '}, error: ' + JSON.stringify('I have been waiting for ' + timeout + ' ms ' + message + ', but it did not happen.') + ' });',
      '  }, ' + JSON.stringify(timeout) + ');',
      '  (function test() {',
      '    var value;',
      '    try {',
      '      value = (' + codeToString(code) + ')(' + args.join(', ') + ');',
      '      if (value) {',
      '        window.clearTimeout(handle2);',
      '        cb({ value: value, closure: {' + keys + '} });',
      '      } else {',
      '        handle1 = window.setTimeout(test, 50);', // repeat after 1/20 sec.
      '      }',
      '    } catch (err) {',
      '      window.clearTimeout(handle2);',
      '      cb({ error: err.message, closure: {' + keys + '} });',
      '    }',
      '  }());'
    );

    chunks.push('}');

    code = chunks.join('\n');

    operand.browser.executeAsync("(" + code + ").apply(null, arguments)", values(closure),
      feedbackProcessor(operand.closure.bind(operand), done));
  });

};

function values(closure) {
  "use strict";

  var values = Object.keys(closure).map(function (key) {
    return closure[key];
  });
  if (arguments.length > 1) {
    values.push.apply(values, Array.prototype.slice.call(arguments, 1));
  }
  return values;
}

function stringify(value) {
  "use strict";

  if (typeof value === 'function') {
    return value.toString();
  }
  return value !== undefined ? JSON.stringify(value) : "undefined";
}

function codeToString(code) {
  "use strict";

  var test;

  if (typeof code === 'string' && !/^function\s+\(/.test(code)) {
    return 'function () {\n' + code + '\n}';
  }
  if (typeof code === 'function') {
    return code.toString();
  }

  eval("test = " + code); // XXX it may throw on syntax error

  return code;
}

function feedbackProcessor(closure, cb) {
  "use strict";

  return function (err, feedback) {
    if (err) {
      return cb(err);
    }
    if (feedback.closure) {
      closure(feedback.closure);
    }
    if (feedback.error) {
      return cb(cleanError(feedback.error));
    }
    cb(null, feedback.value);
  }
}

function wrapSourceCode(code, args, closure) {
  "use strict";

  var chunks = [];

  chunks.push("function (" + Object.keys(closure).join(', ') + ") {");

  //addSyncChunks(chunks, closure, accessor);
  chunks.push("  var expect = null;");

  chunks.push(
    "  var expect = null;",
    "  try {",
    "    if (window.chai) {",
    "      expect = window.chai.expect;",
    "    } else {",
    "      throw new Error('chai not found');",
    "    }",
    "    return (function ($) {",
    "      return {",
    "        closure: {"
  );

  Object.keys(closure).forEach(function (key) {
    chunks.push("          " + stringify(key) + ": " + key + ",");
  });

  chunks.push(
    "        },",
    "        value: $,",
    "      };",
    "    })( (" + code + ")(" + args.map(stringify).join(',') + ") );",
    "  } catch (err) {",
    "    return {",
    "      closure: {"
  );

  Object.keys(closure).forEach(function (key) {
    chunks.push("        " + stringify(key) + ": " + key + ",");
  });

  chunks.push(
    "      },",
    "      error: err.message",
    "    };",
    "  }",
    "}"
  );

  return chunks.join('\n');
}
<|endoftext|>


<commit_before>"use babel";

import child_process from "child_process";
import path from "path";
import Builder from "../builder";

export default class TexifyBuilder extends Builder {
  constructor() {
    super();
    this.executable = "texify";
  }

  run(filePath) {
    const args = this.constructArgs(filePath);
    const command = `${this.executable} ${args.join(" ")}`;
    const options = this.constructChildProcessOptions();

    options.cwd = path.dirname(filePath); // Run process with sensible CWD.
    options.maxBuffer = 52428800; // Set process' max buffer size to 50 MB.

    return new Promise((resolve) => {
      // TODO: Add support for killing the process.
      child_process.exec(command, options, (error) => {
        resolve((error) ? error.code : 0);
      });
    });
  }

  constructArgs(filePath) {
    const args = [
      "--batch",
      "--pdf",
      "--tex-option=--synctex=1",
      "--tex-option=--max-print-line=1000", // Max log file line length
    ];

    const enableShellEscape = atom.config.get("latex.enableShellEscape");
    if (enableShellEscape) {
      args.push("--tex-option=--enable-write18");
    }

    const customEngine = atom.config.get("latex.customEngine");
    const engine = atom.config.get("latex.engine");
    if (customEngine || engine !== "pdflatex") {
      atom.notifications.addWarning(
        "Engine customization is not supported by texify, " +
        "so this functionality is disabled when using the texify builder."
      );
    }

    let outdir = this.getOutputDirectory(filePath);
    if (outdir) {
      atom.notifications.addWarning(
        "Output directory functionality is poorly supported by texify, " +
        "so this functionality is disabled (for the foreseeable future) " +
        "when using the texify builder."
      );
    }

    args.push(`\"${filePath}\"`);
    return args;
  }
}
<commit_msg>:shirt: Move comment to work around linter bug<commit_after>"use babel";

import child_process from "child_process";
import path from "path";
import Builder from "../builder";

export default class TexifyBuilder extends Builder {
  constructor() {
    super();
    this.executable = "texify";
  }

  run(filePath) {
    const args = this.constructArgs(filePath);
    const command = `${this.executable} ${args.join(" ")}`;
    const options = this.constructChildProcessOptions();

    options.cwd = path.dirname(filePath); // Run process with sensible CWD.
    options.maxBuffer = 52428800; // Set process' max buffer size to 50 MB.

    return new Promise((resolve) => {
      // TODO: Add support for killing the process.
      child_process.exec(command, options, (error) => {
        resolve((error) ? error.code : 0);
      });
    });
  }

  constructArgs(filePath) {
    const args = [
      "--batch",
      "--pdf",
      "--tex-option=--synctex=1",
      // Set logfile max line length.
      "--tex-option=--max-print-line=1000",
    ];

    const enableShellEscape = atom.config.get("latex.enableShellEscape");
    if (enableShellEscape) {
      args.push("--tex-option=--enable-write18");
    }

    const customEngine = atom.config.get("latex.customEngine");
    const engine = atom.config.get("latex.engine");
    if (customEngine || engine !== "pdflatex") {
      atom.notifications.addWarning(
        "Engine customization is not supported by texify, " +
        "so this functionality is disabled when using the texify builder."
      );
    }

    let outdir = this.getOutputDirectory(filePath);
    if (outdir) {
      atom.notifications.addWarning(
        "Output directory functionality is poorly supported by texify, " +
        "so this functionality is disabled (for the foreseeable future) " +
        "when using the texify builder."
      );
    }

    args.push(`\"${filePath}\"`);
    return args;
  }
}
<|endoftext|>


<commit_before>'use strict';

var gaze = require('gaze'),
    path = require('path'),
    util = require('util'),
    log = require('../logger')('nodecg/lib/bundles/watcher'),
    EventEmitter = require('events').EventEmitter,
    emitter = new EventEmitter();

require('string.prototype.endswith');

function Watcher() {
    EventEmitter.call(this);
    var self = this;

    // Patterns for gaze to watch or ignore
    var watchPatterns = [
        'bundles/**',         // Watch bundles folder
        '!**/*___jb_*___',    // Ignore temp files created by JetBrains IDEs
        '!bundles/*/view/**', // Ignore view folders. Might watch them in a later NodeCG version, but not now.
        '!node_modules'       // Ignore node_modules folders
    ];

    gaze(watchPatterns, function(err, watcher) {
        // On changed/added/deleted
        this.on('all', function(event, filepath) {
            // TODO: Check if index.js was changed, and prompt to restart NodeCG. index.js can't be hot-reloaded

            //extract the bundle name from the filepath
            var bundleName = '';
            var res = filepath.split(path.sep);
            var prevPart = '';

            //walk up the path in reverse, once we find "bundles" we know the previous dir was the bundle
            res.reverse().forEach(function(part) {
                if(part === 'bundles') {
                    bundleName = prevPart;
                }
                prevPart = part;
            });

            log.debug("Change detected in " + bundleName + ": " + filepath + " " + event);
            emitter.emit("bundleChanged", bundleName);
        });

        this.on('error', function(error) {
            log.error('Gaze error:', error.stack);
        });
    });
}

module.exports = emitter;
<commit_msg>remove old "TODO" comment<commit_after>'use strict';

var gaze = require('gaze'),
    path = require('path'),
    util = require('util'),
    log = require('../logger')('nodecg/lib/bundles/watcher'),
    EventEmitter = require('events').EventEmitter,
    emitter = new EventEmitter();

require('string.prototype.endswith');

function Watcher() {
    EventEmitter.call(this);
    var self = this;

    // Patterns for gaze to watch or ignore
    var watchPatterns = [
        'bundles/**',         // Watch bundles folder
        '!**/*___jb_*___',    // Ignore temp files created by JetBrains IDEs
        '!bundles/*/view/**', // Ignore view folders. Might watch them in a later NodeCG version, but not now.
        '!node_modules'       // Ignore node_modules folders
    ];

    gaze(watchPatterns, function(err, watcher) {
        // On changed/added/deleted
        this.on('all', function(event, filepath) {
            //extract the bundle name from the filepath
            var bundleName = '';
            var res = filepath.split(path.sep);
            var prevPart = '';

            //walk up the path in reverse, once we find "bundles" we know the previous dir was the bundle
            res.reverse().forEach(function(part) {
                if(part === 'bundles') {
                    bundleName = prevPart;
                }
                prevPart = part;
            });

            log.debug("Change detected in " + bundleName + ": " + filepath + " " + event);
            emitter.emit("bundleChanged", bundleName);
        });

        this.on('error', function(error) {
            log.error('Gaze error:', error.stack);
        });
    });
}

module.exports = emitter;
<|endoftext|>


<commit_before><commit_msg>Adding updateRecords and updateRecordsWithWait<commit_after><|endoftext|>


<commit_before>'use strict';

var node_path     	= require('path');
var async           = require('async');
var fs              = require('fs-sync');
var Installer       = require('cortex-install');

// used by ctx.commands.build
var argv_parser     = require('../util/parse-argv');
var command_build   = require('./build');

var USER_HOME = process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME'];

// TODO:
// migrate to cortex-profile
var CORTEX_ROOT = node_path.join(USER_HOME, '.cortex');
var module_root = node_path.join(USER_HOME, '.cortex', 'modules');

function log(msg){
    process.stdout.write(msg + '\n');
};

// Attension: there will no arguments checking
// @param {Object} options:
// - modules: {Object} modules to install, ['a@1.0.1', 'b@0.0.2'];
// - save: {boolean} save cortexDependencies
// - cwd: {string}

// @param {function()} callback
module.exports = function(options, callback){
    var modules = options.modules;
    var should_save = options.save;
    var cwd = options.cwd;

    //
    var temp_dir = node_path.join(CORTEX_ROOT, 'tmp', + new Date + '');

    var installer = new Installer({

        // install modules into a temporary directory
        dir : temp_dir,
        key : "cortexDependencies",
        registry : options.registry
    });

    async.waterfall([
        function(done) {
            log('Installing: ["' + modules.join('", "') + '"]');

            installer.install(modules, function(error, data) {
                if(error){
                    throw error;
                }

                var installed_modules = [];
                var name;

                // {
                //   'a': {
                //         '0.0.1': {}
                //         '0.0.2': {}
                //      }
                // }
                for(name in data){

                    // ['a@0.0.1', 'a@0.0.2']
                    installed_modules = installed_modules.concat(
                        Object.keys(data[name]).map(function(version) {
                            return name + '@' + version;
                        })
                    );
                }

                done(null, installed_modules);
            });
        },

        function(installed_modules, done) {
            // build modules
            var series = [];
            var installed_module_paths = installed_modules.map(function(module_at_version) {
                return module_at_version.replace('@', node_path.sep);
            });

            installed_module_paths.forEach(function(path) {
                series.push(function(d) {

                    // mock process.argv
                    var argv = ['', '', 'build', '--cwd', node_path.join(temp_dir, path, 'package') ];
                    var parsed = argv_parser(argv);

                    command_build(parsed.options, function() {
                        d();
                    });
                });
            });

            async.series(series, function() {
                done(null, installed_module_paths);
            });
        }

    ], function(err, installed_module_paths) {

        // moving folder
        installed_module_paths.forEach(function(module_slash_version) {
            fs.copy(
                node_path.join(temp_dir, module_slash_version),
                node_path.join(module_root, module_slash_version), {
                    force: true
                }
            );
        });

        // remove temp_dir
        fs.delete(temp_dir);

        // save to package.json
        if(should_save){
            var package_file = node_path.join(cwd, 'package.json');
            var pkg = fs.readJSON(package_file);

            var deps = pkg.cortexDependencies || (pkg.cortexDependencies = {});
            var exact_deps = pkg.cortexExactDependencies || (pkg.cortexExactDependencies = {});

            Object.keys(modules).forEach(function(name) {

                var exact_version = installed_module_map[name][0];

                deps[name] = '~' + exact_version;
                exact_deps[name] = exact_version;
            });

            fs.write( package_file, JSON.stringify(pkg, null, 4) );
        }

        callback && callback();
    });
};

<commit_msg>command/install: UNFIXED! add todos and a potential bug( blocked by https://github.com/supersheep/cortex-install/issues/3 )<commit_after>'use strict';

var node_path     	= require('path');
var async           = require('async');
var fs              = require('fs-sync');
var Installer       = require('cortex-install');

// used by ctx.commands.build
var argv_parser     = require('../util/parse-argv');
var command_build   = require('./build');

var USER_HOME = process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME'];

// TODO:
// migrate to cortex-profile
var CORTEX_ROOT = node_path.join(USER_HOME, '.cortex');
var module_root = node_path.join(USER_HOME, '.cortex', 'modules');

function log(msg){
    process.stdout.write(msg + '\n');
};

// Attension: there will no arguments checking
// @param {Object} options:
// - modules: {Object} modules to install, ['a@1.0.1', 'b@0.0.2'];
// - save: {boolean} save cortexDependencies
// - cwd: {string}

// @param {function()} callback
module.exports = function(options, callback){
    var modules = options.modules;
    var should_save = options.save;
    var cwd = options.cwd;

    //
    var temp_dir = node_path.join(CORTEX_ROOT, 'tmp', + new Date + '');

    var installer = new Installer({

        // install modules into a temporary directory
        dir : temp_dir,
        key : "cortexDependencies",
        registry : options.registry
    });

    async.waterfall([
        function(done) {
            log('Installing: ["' + modules.join('", "') + '"]');

            installer.install(modules, function(error, data) {
                if(error){
                    throw error;
                }

                var installed_modules = [];
                var name;

                // {
                //   'a': {
                //         '0.0.1': {}
                //         '0.0.2': {}
                //      }
                // }
                for(name in data){

                    // ['a@0.0.1', 'a@0.0.2']
                    installed_modules = installed_modules.concat(
                        Object.keys(data[name]).map(function(version) {
                            return name + '@' + version;
                        })
                    );
                }

                done(null, installed_modules);
            });
        },

        function(installed_modules, done) {
            // build modules
            var series = [];
            var installed_module_paths = installed_modules.map(function(module_at_version) {
                return module_at_version.replace('@', node_path.sep);
            });

            installed_module_paths.forEach(function(path) {
                series.push(function(d) {

                    // mock process.argv
                    var argv = ['', '', 'build', '--cwd', node_path.join(temp_dir, path, 'package') ];
                    var parsed = argv_parser(argv);

                    command_build(parsed.options, function() {
                        d();
                    });
                });
            });

            async.series(series, function() {
                done(null, installed_module_paths);
            });
        }

    ], function(err, installed_module_paths) {

        // moving folder
        installed_module_paths.forEach(function(module_slash_version) {
            fs.copy(
                node_path.join(temp_dir, module_slash_version),
                node_path.join(module_root, module_slash_version), {
                    force: true
                }
            );
        });

        // remove temp_dir
        fs.delete(temp_dir);

        // save to package.json
        if(should_save){
            var package_file = node_path.join(cwd, 'package.json');
            var pkg = fs.readJSON(package_file);

            var deps = pkg.cortexDependencies || (pkg.cortexDependencies = {});
            var exact_deps = pkg.cortexExactDependencies || (pkg.cortexExactDependencies = {});

            // TODO:
            // there is a bug:

            // case 1:
            // ctx install a b
            // a@0.0.3
            // b@0.0.1 -> ['a@0.0.2']

            // case 2:
            // ctx install a@0.0.1 b
            // b@0.0.1 -> ['a@0.0.2']

            // now we don't know which version to save to package.json
            modules.forEach(function(module) {
                var exact_version = installed_module_map[name][0];

                deps[name] = '~' + exact_version;
                exact_deps[name] = exact_version;
            });

            fs.write( package_file, JSON.stringify(pkg, null, 4) );
        }

        callback && callback();
    });
};

<|endoftext|>