<commit_before>/*!
 * jQuery Stepy - A Wizard Plugin
 *
 * The MIT License
 *
 * @author:  Washington Botelho
 * @doc:     wbotelhos.com/stepy
 * @version: 1.1.0
 *
 */

;(function($) {
  'use strict';

  var methods = {
    init: function(settings) {
      return this.each(function() {
        methods.destroy.call(this);

        this.opt = $.extend({}, $.fn.stepy.defaults, settings);

        var
          that = this,
          self = $(this),
          id   = self.attr('id');

        if (id === undefined || id === '') {
          var id = methods._hash.call(that);

          self.attr('id', id);
        }

        // Remove Validator...
        if (that.opt.validate) {
          jQuery.validator.setDefaults({ ignore: that.opt.ignore });

          self.append('
');
        }

        that.header = methods._header.call(that);
        that.steps  = self.children('fieldset');

        that.steps.each(function(index) {
          methods._createHead.call(that, this, index);
          methods._createButtons.call(that, this, index);
        });

        that.heads = that.header.children('li');

        that.heads.first().addClass('stepy-active');

        methods._bindFinishButton.call(that);

        if (that.opt.titleClick) {
          that.heads.click(function() {
            var
              array   = that.heads.filter('.stepy-active').attr('id').split('-'), // TODO: try keep the number in an attribute.
              current = parseInt(array[array.length - 1], 10),
              clicked = $(this).index();

            if (clicked > current) {
              if (that.opt.next && !methods._execute.call(self, that.opt.next, clicked)) {
                return false;
              }
            } else if (clicked < current) {
              if (that.opt.back && !methods._execute.call(self, that.opt.back, clicked)) {
                return false;
              }
            }

            if (clicked != current) {
              methods.step.call(that, (clicked) + 1);
            }
          });
        } else {
          that.heads.css('cursor', 'default');
        }

        if (that.opt.enter) {
          methods._bindEnter.call(that);
        }

        that.steps.first().find(':input:visible:enabled').first().select().focus();

        self.data({ 'settings': this.opt, 'stepy': true });
      });
    },

    _bindEnter: function() {
      var that = this;

      that.steps.delegate('input[type="text"], input[type="password"]', 'keypress', function(evt) {
        var key = (evt.keyCode ? evt.keyCode : evt.which);

        if (key == 13) {
          evt.preventDefault();

          var buttons = $(this).closest('fieldset').find('.stepy-navigator');

          if (buttons.length) {
            var next = buttons.children('.stepy-next');

            if (next.length) {
              next.trigger('click');
            } else if (that.finishButton) {
              that.finishButton.trigger('click');
            }
          }
        }
      });
    },

    _bindFinishButton: function() {
      var that = $(this);

      this.finishButton = that.find('.stepy-finish');

      if (!this.finishButton.length) {
        return $.error('submit button ".stepy-finish" missing.');
      }

      this.finishButton.hide().on('click.stepy', methods._onFinishButton.bind(this));
    },

    _createBackButton: function(nav, index) {
      var
        that       = this,
        self       = $(this),
        attributes = { href: 'javascript:void(0);', 'class': 'stepy-back', html: that.opt.backLabel };

      $('', attributes).on('click.stepy', function(e) {
        e.preventDefault();

        if (!that.opt.back || methods._execute.call(that, that.opt.back, index - 1, that.steps.length)) {
          methods.step.call(that, (index - 1) + 1);
        }
      }).appendTo(nav);
    },

    _createButtons: function(step, index) {
      var nav = methods._navigator.call(this).appendTo(step);

      if (index === 0) {
        if (this.steps.length > 1) {
          methods._createNextButton.call(this, nav, index);
        }
      } else {
        $(step).hide();

        methods._createBackButton.call(this, nav, index);

        if (index < this.steps.length - 1) {
          methods._createNextButton.call(this, nav, index);
        }
      }
    },

    _createHead: function(step, index) {
      var
        step = $(step).attr('id', $(this).attr('id') + '-step-' + index).addClass('stepy-step'),
        head = methods._head.call(this, index);

      head.append(methods._title.call(this, step));

      if (this.opt.description) {
        head.append(methods._description.call(this, step));
      }

      this.header.append(head);
    },

    _createNextButton: function(nav, index) {
      var
        that       = this,
        self       = $(this),
        attributes = { href: 'javascript:void(0);', 'class': 'stepy-next', html: that.opt.nextLabel };

      $('', attributes).on('click.stepy', function(e) {
        e.preventDefault();

        if (!that.opt.next || methods._execute.call(self, that.opt.next, index + 1, that.steps.length)) {
          methods.step.call(that, (index + 1) + 1);
        }
      }).appendTo(nav);
    },

    _description: function(step) {
      var legend = step.children('legend');

      if (!this.opt.legend) {
        legend.hide();
      }

      if (legend.length) {
        return $('', { html: legend.html() });
      }

      methods._error.call(this, '<legend /> element missing!');
    },

    _error: function(message) {
      $(this).html(message);

      $.error(message);
    },

    _execute: function(callback, index, totalSteps) {
      var isValid = callback.call(this, index + 1, totalSteps);

      return isValid || isValid === undefined;
    },

    _hash: function() {
      this.hash = 'stepy-' + Math.random().toString().substring(2)

      return this.hash;
    },

    _head: function(index) {
      return $('
', { id: $(this).attr('id') + '-head-' + index });
    },

    _header: function() {
      var header = $('
', { id: $(this).attr('id') + '-header', 'class': 'stepy-header' });

      if (this.opt.titleTarget) {
        header.appendTo(this.opt.titleTarget);
      } else {
        header.insertBefore(this);
      }

      return header;
    },

    _navigator: function(index) {
      return $('
');
    },

    _onFinishButton: function(evt) {
      var onSubmit = undefined;

      if (this.tagName === 'FORM') {
        onSubmit = this.getAttribute('onsubmit');

        this.setAttribute('onsubmit', 'return false;');
      }

      if (!methods._execute.call(this, this.opt.finish, this.steps.length - 1)) {
        evt.preventDefault();
      } else if (this.tagName === 'FORM') {
        if (onSubmit) {
          this.setAttribute('onsubmit', onSubmit);
        } else {
          this.removeAttribute('onsubmit');
        }

        var isSubmit = this.finishButton.attr('type') === 'submit';

        if (!isSubmit && (!this.opt.validate || methods.validate.call(this, this.steps.length - 1))) {
          this.submit();
        }
      }
    },

    _title: function(step) {
      return $('
', { html: step.attr('title') || '--' });
    },

    destroy: function() {
      return $(this).each(function() {
        var self = $(this);

        if (self.data('stepy')) {
          var steps = self.data('stepy', false).children('fieldset').css('display', '');

          self.children('.stepy-errors').remove();
          steps.find('p.stepy-navigator').remove();
        }
      });
    },

    step: function(index) {
      var
        that = this,
        self = $(this);

      index--;

      var steps = self.children('fieldset');

      if (index > steps.length - 1) {
        index = steps.length - 1;
      }

      var max = index;
debugger;
      if (this.opt.validate) {
        var isValid = true;

        for (var i = 0; i < index; i++) {
          isValid &= methods.validate.call(this, i);

          if (this.opt.block && !isValid) {
            max = i;
            break;
          }
        }
      }

      if (this.opt.transition == 'fade') {
        steps.fadeOut(this.opt.duration, function() {
          if (--steps.length > 0) {
            return;
          }

          steps.eq(max).fadeIn(this.opt.duration);
        });
      } else if (this.opt.transition == 'slide') {
        steps.slideUp(this.opt.duration, function() {
          if (--steps.length > 0) {
            return;
          }

          steps.eq(max).slideDown(this.opt.duration);
        });
      } else {
        steps.hide(this.opt.duration).eq(max).show(this.opt.duration);
      }

      self[0].heads.removeClass('stepy-active').eq(max).addClass('stepy-active');

      if (self.is('form')) {
        var $fields = undefined;

        if (max == index) {
          $fields = steps.eq(max).find(':input:enabled:visible');
        } else {
          $fields = steps.eq(max).find('.error').select().focus();
        }

        $fields.first().select().focus();
      }

      if (this.opt.select) {
        this.opt.select.call(this, max + 1, steps.length);
      }

      if (methods._isLastStep.call(this, index, steps)) {
        self.find('.stepy-finish').show();
      } else {
        self.find('.stepy-finish').hide();
      }

      return self;
    },

    _isLastStep: function(index, steps) {
      return index === steps.length - 1;
    },

    validate: function(index) {
      var self = $(this);

      if (!self.is('form')) {
        return true;
      }

      var
        that      = this,
        step      = self.children('fieldset').eq(index),
        isValid   = true,
        $title    = $('#' + self.attr('id') + '-header').children().eq(index),
        $validate = self.validate();

      $(step.find(':input:enabled').get().reverse()).each(function() {
        var fieldIsValid = $validate.element($(this));

        if (fieldIsValid === undefined) {
          fieldIsValid = true;
        }

        isValid &= fieldIsValid;

        if (isValid) {
          if (that.opt.errorImage) {
            $title.removeClass('stepy-error');
          }
        } else {
          if (that.opt.errorImage) {
            $title.addClass('stepy-error');
          }

          $validate.focusInvalid();
        }
      });

      return isValid;
    }
  };

  $.fn.stepy = function(method) {
    if (methods[method]) {
      return methods[method].apply($(this)[0], Array.prototype.slice.call(arguments, 1));
    } else if (typeof method === 'object' || !method) {
      return methods.init.apply(this, arguments);
    } else {
      $.error('Method ' + method + ' does not exist!');
    }
  };

  $.fn.stepy.defaults = {
    back:         undefined,
    backLabel:    '< Back',
    block:        false,
    description:  true,
    duration:     undefined, // TODO: set default duration to avoid error on fade
    enter:        true,
    errorImage:   false,
    finish:       undefined,
    finishButton: undefined,
    ignore:       '',
    legend:       true,
    next:         undefined,
    nextLabel:    'Next >',
    select:       undefined,
    titleClick:   false,
    titleTarget:  undefined,
    transition:   undefined,
    validate:     false
  };

})(jQuery);
<commit_msg>refactories<commit_after>/*!
 * jQuery Stepy - A Wizard Plugin
 *
 * The MIT License
 *
 * @author:  Washington Botelho
 * @doc:     wbotelhos.com/stepy
 * @version: 1.1.0
 *
 */

;(function($) {
  'use strict';

  var methods = {
    init: function(settings) {
      return this.each(function() {
        methods.destroy.call(this);

        this.opt = $.extend({}, $.fn.stepy.defaults, settings);

        var
          that = this,
          self = $(this),
          id   = self.attr('id');

        if (id === undefined || id === '') {
          var id = methods._hash.call(this);

          self.attr('id', id);
        }

        // Remove Validator...
        if (this.opt.validate) {
          jQuery.validator.setDefaults({ ignore: this.opt.ignore });

          self.append('
');
        }

        this.header = methods._header.call(this);
        this.steps  = self.children('fieldset');

        this.steps.each(function(index) {
          methods._createHead.call(that, this, index);
          methods._createButtons.call(that, this, index);
        });

        this.heads = this.header.children('li');

        this.heads.first().addClass('stepy-active');

        methods._bindFinishButton.call(this);

        if (this.opt.titleClick) {
          this.heads.click(function() {
            var
              array   = that.heads.filter('.stepy-active').attr('id').split('-'), // TODO: try keep the number in an attribute.
              current = parseInt(array[array.length - 1], 10),
              clicked = $(this).index();

            if (clicked > current) {
              if (that.opt.next && !methods._execute.call(self, that.opt.next, clicked)) {
                return false;
              }
            } else if (clicked < current) {
              if (that.opt.back && !methods._execute.call(self, that.opt.back, clicked)) {
                return false;
              }
            }

            if (clicked != current) {
              methods.step.call(that, (clicked) + 1);
            }
          });
        } else {
          that.heads.css('cursor', 'default');
        }

        if (that.opt.enter) {
          methods._bindEnter.call(that);
        }

        that.steps.first().find(':input:visible:enabled').first().select().focus();

        self.data({ 'settings': this.opt, 'stepy': true });
      });
    },

    _bindEnter: function() {
      var that = this;

      this.steps.delegate(':text, :password', 'keypress', function(evt) {
        var key = (evt.keyCode ? evt.keyCode : evt.which);

        if (key == 13) {
          evt.preventDefault();

          var buttons = $(this).closest('fieldset').find('.stepy-navigator');

          if (buttons.length) {
            var next = buttons.children('.stepy-next');

            if (next.length) {
              next.trigger('click');
            } else if (that.finishButton) {
              that.finishButton.trigger('click');
            }
          }
        }
      });
    },

    _bindFinishButton: function() {
      this.finishButton = $(this).find('.stepy-finish');

      if (!this.finishButton.length) {
        return $.error('submit button ".stepy-finish" missing.');
      }

      this.finishButton.hide().on('click.stepy', methods._onFinishButton.bind(this));
    },

    _createBackButton: function(nav, index) {
      var attributes = { href: 'javascript:void(0);', 'class': 'stepy-back', html: this.opt.backLabel };

      $('', attributes).on('click.stepy', function(e) {
        e.preventDefault();

        if (!this.opt.back || methods._execute.call(this, this.opt.back, index - 1, this.steps.length)) {
          methods.step.call(this, (index - 1) + 1);
        }
      }.bind(this)).appendTo(nav);
    },

    _createButtons: function(step, index) {
      var nav = methods._navigator.call(this).appendTo(step);

      if (index === 0) {
        if (this.steps.length > 1) {
          methods._createNextButton.call(this, nav, index);
        }
      } else {
        $(step).hide();

        methods._createBackButton.call(this, nav, index);

        if (index < this.steps.length - 1) {
          methods._createNextButton.call(this, nav, index);
        }
      }
    },

    _createHead: function(step, index) {
      var
        step = $(step).attr('id', $(this).attr('id') + '-step-' + index).addClass('stepy-step'),
        head = methods._head.call(this, index);

      head.append(methods._title.call(this, step));

      if (this.opt.description) {
        head.append(methods._description.call(this, step));
      }

      this.header.append(head);
    },

    _createNextButton: function(nav, index) {
      var attributes = { href: 'javascript:void(0);', 'class': 'stepy-next', html: this.opt.nextLabel };

      $('', attributes).on('click.stepy', function(e) {
        e.preventDefault();

        if (!this.opt.next || methods._execute.call(this, this.opt.next, index + 1, this.steps.length)) {
          methods.step.call(this, (index + 1) + 1);
        }
      }.bind(this)).appendTo(nav);
    },

    _description: function(step) {
      var legend = step.children('legend');

      if (!this.opt.legend) {
        legend.hide();
      }

      if (legend.length) {
        return $('', { html: legend.html() });
      }

      methods._error.call(this, '<legend /> element missing!');
    },

    _error: function(message) {
      $(this).html(message);

      $.error(message);
    },

    _execute: function(callback, index, totalSteps) {
      var isValid = callback.call(this, index + 1, totalSteps);

      return isValid || isValid === undefined;
    },

    _hash: function() {
      this.hash = 'stepy-' + Math.random().toString().substring(2)

      return this.hash;
    },

    _head: function(index) {
      return $('
', { id: $(this).attr('id') + '-head-' + index });
    },

    _header: function() {
      var header = $('
', { id: $(this).attr('id') + '-header', 'class': 'stepy-header' });

      if (this.opt.titleTarget) {
        header.appendTo(this.opt.titleTarget);
      } else {
        header.insertBefore(this);
      }

      return header;
    },

    _navigator: function(index) {
      return $('
');
    },

    _onFinishButton: function(evt) {
      var onSubmit = undefined;

      if (this.tagName === 'FORM') {
        onSubmit = this.getAttribute('onsubmit');

        this.setAttribute('onsubmit', 'return false;');
      }

      if (!methods._execute.call(this, this.opt.finish, this.steps.length - 1)) {
        evt.preventDefault();
      } else if (this.tagName === 'FORM') {
        if (onSubmit) {
          this.setAttribute('onsubmit', onSubmit);
        } else {
          this.removeAttribute('onsubmit');
        }

        var isSubmit = this.finishButton.attr('type') === 'submit';

        if (!isSubmit && (!this.opt.validate || methods.validate.call(this, this.steps.length - 1))) {
          this.submit();
        }
      }
    },

    _title: function(step) {
      return $('
', { html: step.attr('title') || '--' });
    },

    destroy: function() {
      return $(this).each(function() {
        var self = $(this);

        if (self.data('stepy')) {
          var steps = self.data('stepy', false).children('fieldset').css('display', '');

          self.children('.stepy-errors').remove();
          steps.find('p.stepy-navigator').remove();
        }
      });
    },

    step: function(index) {
      var self = $(this);

      index--;

      var steps = self.children('fieldset');

      if (index > steps.length - 1) {
        index = steps.length - 1;
      }

      var max = index;

      if (this.opt.validate) {
        var isValid = true;

        for (var i = 0; i < index; i++) {
          isValid &= methods.validate.call(this, i);

          if (this.opt.block && !isValid) {
            max = i;
            break;
          }
        }
      }

      if (this.opt.transition == 'fade') {
        steps.fadeOut(this.opt.duration, function() {
          if (--steps.length > 0) {
            return;
          }

          steps.eq(max).fadeIn(this.opt.duration);
        });
      } else if (this.opt.transition == 'slide') {
        steps.slideUp(this.opt.duration, function() {
          if (--steps.length > 0) {
            return;
          }

          steps.eq(max).slideDown(this.opt.duration);
        });
      } else {
        steps.hide(this.opt.duration).eq(max).show(this.opt.duration);
      }

      this.heads.removeClass('stepy-active').eq(max).addClass('stepy-active');

      if (this.tagName === 'FORM') {
        var $fields = undefined;

        if (max == index) {
          $fields = steps.eq(max).find(':input:enabled:visible');
        } else {
          $fields = steps.eq(max).find('.error').select().focus();
        }

        $fields.first().select().focus();
      }

      if (this.opt.select) {
        this.opt.select.call(this, max + 1, steps.length);
      }

      if (methods._isLastStep.call(this, index, steps)) {
        self.find('.stepy-finish').show();
      } else {
        self.find('.stepy-finish').hide();
      }

      return self;
    },

    _isLastStep: function(index, steps) {
      return index === steps.length - 1;
    },

    validate: function(index) {
      var self = $(this);

      if (!this.tagName === 'FORM') {
        return true;
      }

      var
        that      = this,
        step      = self.children('fieldset').eq(index),
        isValid   = true,
        $title    = $('#' + this.id + '-header').children().eq(index),
        $validate = self.validate();

      $(step.find(':input:enabled').get().reverse()).each(function() {
        var fieldIsValid = $validate.element($(this));

        if (fieldIsValid === undefined) {
          fieldIsValid = true;
        }

        isValid &= fieldIsValid;

        if (isValid) {
          if (that.opt.errorImage) {
            $title.removeClass('stepy-error');
          }
        } else {
          if (that.opt.errorImage) {
            $title.addClass('stepy-error');
          }

          $validate.focusInvalid();
        }
      });

      return isValid;
    }
  };

  $.fn.stepy = function(method) {
    if (methods[method]) {
      return methods[method].apply($(this)[0], Array.prototype.slice.call(arguments, 1));
    } else if (typeof method === 'object' || !method) {
      return methods.init.apply(this, arguments);
    } else {
      $.error('Method ' + method + ' does not exist!');
    }
  };

  $.fn.stepy.defaults = {
    back:         undefined,
    backLabel:    '< Back',
    block:        false,
    description:  true,
    duration:     undefined, // TODO: set default duration to avoid error on fade
    enter:        true,
    errorImage:   false,
    finish:       undefined,
    finishButton: undefined,
    ignore:       '',
    legend:       true,
    next:         undefined,
    nextLabel:    'Next >',
    select:       undefined,
    titleClick:   false,
    titleTarget:  undefined,
    transition:   undefined,
    validate:     false
  };

})(jQuery);
<|endoftext|>


<commit_before>var fs = require("fs");
var marked = require('marked');
var pdf = require('html-pdf');
var path = require('path');
var url = require('url');
var mdpreview = atom.packages.activePackages["markdown-preview"];

module.exports = {

  config: {
    "format": {
      "title": "Page Format",
      "type": "string",
      "default": "A4",
      "enum": ["A3", "A4", "A5", "Legal", "Letter", "Tabloid"]
    },
    "orientation": {
      "title": "Page Orientation",
      "type": "string",
      "default": "portrait",
      "enum": ["portrait", "landscape"]
    },
    "timeout": {
      "title": "Timeout",
      "description": "Time (ms) before PhantomJS gives up on rendering. You can set a larger value for very big files.",
      "type": "integer",
      "default": 10000
    },
    "border": {
      "title": "Border Size",
      "type": "string",
      "default": "10mm"
    },
    "type": {
      "title": "Exported Filetype",
      "type": "string",
      "default": "pdf",
      "enum": ["pdf", "png", "jpeg"]
    },
    "quality": {
      "title": "Image Quality",
      "description": "Only used for .png and .jpeg formats.",
      "type": "integer",
      "minimum": 1,
      "maximum": 100,
      "default": 100
    }
  },

  activate: function() {
    atom.workspaceView.command('markdown-pdf:convert', this.convert);
  },

  convert: function() {
    try{
      var outPath = getOutputPath();
      htmlFromMd(function(html){
        html = convertImgSrcToURI(html);
        html = getStyledHtml(html);
        makePdf(html, outPath);
      });
    }
    catch(err){
      alert(err);
      return;
    }
  }

}

function htmlFromMd(callback){

  //explicitly setting default options below, in case we want to further configure the renderer
  marked.setOptions({
    renderer: new marked.Renderer(),
    gfm: true,
    tables: true,
    breaks: false,
    pedantic: false,
    sanitize: true,
    smartLists: true,
    smartypants: false
  });
  if(editorSelected()){
    var md = atom.workspace.getActivePaneItem().buffer.cachedText;
    var html = marked(md);
    callback(html);
  }
  else alert('Please select the editor containing the markdown you wish to convert.');
}

function getStyledHtml(input){
  return getStyles() + wrapHtml(input);
}

function wrapHtml(input){
  return '' + input + '';
}

function getStyles(){
  var user_styles = atom.styles.getStyleElements();
  user_styles = user_styles[user_styles.length - 1].innerHTML;

  var styles = {
    previewStyles: mdpreview.stylesheets[0][1],
    syntaxStyles: atom.themes.getActiveThemes()[0].stylesheets[0][1],
    userStyles: user_styles
  };
  var styleString = '';
  for(var s in styles){
    styleString += '';
  }
  return styleString;
}

function makePdf(inputHtml, outputPath){
  pdf.create(inputHtml, getConfig(), function(err, buffer) {
    if (err) {
      alert("Error converting to image format. Check console for more information.");
      console.log(err + "\nIf the error is a timeout, try running the command again.");
    }
    fs.writeFile(outputPath, buffer);
    console.log("Converted successfully. Output in " + outputPath);
  });
}

function getConfig(){
  //get current configuration settings for this package
  return atom.config.getSettings()['markdown-pdf'];
}

function convertImgSrcToURI(html){
  //input: full html document
  //output: same html document with all "img src" in URI form (i.e. "file://")
  var div = document.createElement('div');
  div.innerHTML = html;
  var imgs = div.getElementsByTagName('img');
  for(var s = 0; s < imgs.length; s++){
    imgs[s].src = processSrc(imgs[s].attributes.src.value);
  }
  return div.innerHTML;
}

function processSrc(src){
  //make a local img src path into a "file:///absolute/path/" if it isn't already

  if(url.parse(src).protocol){
    //if the src already starts with "file://", "https://", etc., it's already in the right form (URI)
    return src;
  }
  else if(path.resolve(src) !== src){
    //if path is not absolute and has no protocol, it should be relative, so make it a URI
    src = path.resolve(path.dirname(outPath), src);
    return 'file://' + src;
  }
  else{
    //otherwise, the src is an absolute path. In this case we can just prepend "file://" to it
    return 'file://' + src;
  }
}

function getOutputPath(){
  var markdownPath = atom.workspaceView.getActivePaneItem().getPath();
  if (!isMd(markdownPath)){
    //file is saved as something other than markdown-type file
    throw 'Please save the file as a markdown (.markdown, .md, .mkd, .mkdown or .ron)';
  }
  else if (!markdownPath){
    //file is unsaved

    //get directory selected in tree-view
    var treeDirPath = atom.packages.getActivePackage('tree-view').mainModule.treeView.selectedPath;
    if(!fs.lstatSync(treeDirPath).isDirectory()){
      treeDirPath = path.dirname(treeDirPath);
    }

    var d = new Date();
    var outName = d.getTime() + '.' + atom.config.get('markdown-pdf.type');
    var outputPath = path.join(treeDirPath, outName);
    return outputPath;
  }
  else{
    //file is saved as markdown type
    var out = markdownPath.replace(getExtension(markdownPath), atom.config.get('markdown-pdf.type'));
    return out;
  }
}

function editorSelected(){
  if(atom.workspace.getActiveTextEditor() !== undefined) return true;
  return false;
}

function isMd(path){
  //if file is unsaved, return true and convert it anyway (see issue #13 in repo)
  if(!path) return true;

  //check extension of current file if it's saved
  var accepted = ["markdown", "md", "mkd", "mkdown", "ron"];
  var current = path.split(".").pop();
  if(accepted.indexOf(current) != -1) return true;
  return false;
}

function getExtension(path){
  var ex = path.split('.').pop();
  return ex;
}
<commit_msg>Add fix for #18<commit_after>var fs = require("fs");
var marked = require('marked');
var pdf = require('html-pdf');
var path = require('path');
var url = require('url');
var mdpreview = atom.packages.activePackages["markdown-preview"];

module.exports = {

  config: {
    "format": {
      "title": "Page Format",
      "type": "string",
      "default": "A4",
      "enum": ["A3", "A4", "A5", "Legal", "Letter", "Tabloid"]
    },
    "orientation": {
      "title": "Page Orientation",
      "type": "string",
      "default": "portrait",
      "enum": ["portrait", "landscape"]
    },
    "timeout": {
      "title": "Timeout",
      "description": "Time (ms) before PhantomJS gives up on rendering. You can set a larger value for very big files.",
      "type": "integer",
      "default": 10000
    },
    "border": {
      "title": "Border Size",
      "type": "string",
      "default": "10mm"
    },
    "type": {
      "title": "Exported Filetype",
      "type": "string",
      "default": "pdf",
      "enum": ["pdf", "png", "jpeg"]
    },
    "quality": {
      "title": "Image Quality",
      "description": "Only used for .png and .jpeg formats.",
      "type": "integer",
      "minimum": 1,
      "maximum": 100,
      "default": 100
    }
  },

  activate: function() {
    atom.workspaceView.command('markdown-pdf:convert', this.convert);
  },

  convert: function() {
    try{
      outPath = getOutputPath();
      htmlFromMd(function(html){
        html = convertImgSrcToURI(html);
        html = getStyledHtml(html);
        makePdf(html, outPath);
      });
    }
    catch(err){
      alert(err);
      return;
    }
  }

}

function htmlFromMd(callback){

  //explicitly setting default options below, in case we want to further configure the renderer
  marked.setOptions({
    renderer: new marked.Renderer(),
    gfm: true,
    tables: true,
    breaks: false,
    pedantic: false,
    sanitize: true,
    smartLists: true,
    smartypants: false
  });
  if(editorSelected()){
    var md = atom.workspace.getActivePaneItem().buffer.cachedText;
    var html = marked(md);
    callback(html);
  }
  else alert('Please select the editor containing the markdown you wish to convert.');
}

function getStyledHtml(input){
  return getStyles() + wrapHtml(input);
}

function wrapHtml(input){
  return '' + input + '';
}

function getStyles(){
  var user_styles = atom.styles.getStyleElements();
  user_styles = user_styles[user_styles.length - 1].innerHTML;

  var styles = {
    previewStyles: mdpreview.stylesheets[0][1],
    syntaxStyles: atom.themes.getActiveThemes()[0].stylesheets[0][1],
    userStyles: user_styles
  };
  var styleString = '';
  for(var s in styles){
    styleString += '';
  }
  return styleString;
}

function makePdf(inputHtml, outputPath){
  pdf.create(inputHtml, getConfig(), function(err, buffer) {
    if (err) {
      alert("Error converting to image format. Check console for more information.");
      console.log(err + "\nIf the error is a timeout, try running the command again.");
    }
    fs.writeFile(outputPath, buffer);
    console.log("Converted successfully. Output in " + outputPath);
  });
}

function getConfig(){
  //get current configuration settings for this package
  return atom.config.getSettings()['markdown-pdf'];
}

function convertImgSrcToURI(html){
  //input: full html document
  //output: same html document with all "img src" in URI form (i.e. "file://")
  var div = document.createElement('div');
  div.innerHTML = html;
  var imgs = div.getElementsByTagName('img');
  for(var s = 0; s < imgs.length; s++){
    imgs[s].src = processSrc(imgs[s].attributes.src.value);
  }
  return div.innerHTML;
}

function processSrc(src){
  //make a local img src path into a "file:///absolute/path/" if it isn't already

  if(url.parse(src).protocol){
    //if the src already starts with "file://", "https://", etc., it's already in the right form (URI)
    return src;
  }
  else if(path.resolve(src) !== src){
    //if path is not absolute and has no protocol, it should be relative, so make it a URI
    src = path.resolve(path.dirname(outPath), src);
    return 'file://' + src;
  }
  else{
    //otherwise, the src is an absolute path. In this case we can just prepend "file://" to it
    return 'file://' + src;
  }
}

function getOutputPath(){
  var markdownPath = atom.workspaceView.getActivePaneItem().getPath();
  if (!isMd(markdownPath)){
    //file is saved as something other than markdown-type file
    throw 'Please save the file as a markdown (.markdown, .md, .mkd, .mkdown or .ron)';
  }
  else if (!markdownPath){
    //file is unsaved

    //get directory selected in tree-view
    var treeDirPath = atom.packages.getActivePackage('tree-view').mainModule.treeView.selectedPath;
    if(!fs.lstatSync(treeDirPath).isDirectory()){
      treeDirPath = path.dirname(treeDirPath);
    }

    var d = new Date();
    var outName = d.getTime() + '.' + atom.config.get('markdown-pdf.type');
    var outputPath = path.join(treeDirPath, outName);
    return outputPath;
  }
  else{
    //file is saved as markdown type
    var out = markdownPath.replace(getExtension(markdownPath), atom.config.get('markdown-pdf.type'));
    return out;
  }
}

function editorSelected(){
  if(atom.workspace.getActiveTextEditor() !== undefined) return true;
  return false;
}

function isMd(path){
  //if file is unsaved, return true and convert it anyway (see issue #13 in repo)
  if(!path) return true;

  //check extension of current file if it's saved
  var accepted = ["markdown", "md", "mkd", "mkdown", "ron"];
  var current = path.split(".").pop();
  if(accepted.indexOf(current) != -1) return true;
  return false;
}

function getExtension(path){
  var ex = path.split('.').pop();
  return ex;
}
<|endoftext|>


<commit_before>'use babel';

/* @flow */

const Mocha = require('mocha');
// const fs = require('fs');
// const path = require('path');

export function run(textEditor) {
  const promise = new Promise(function (resolve, reject) {
    // TODO add to settings
    this.mocha = new Mocha({
      ui: 'bdd',
    });
    this.results = [{
      type: 'Error',
      text: 'Something went wrong',
      range: [[0, 0], [0, 1]],
      filePath: textEditor.getPath(),
    }];

    this.fileName = textEditor.getPath();
    this.mocha.addFile(textEditor.getPath());
    // TODO add to settings
    // const testDir = './test';

    /* fs.readdirSync(testDir)
        .filter(file =>
            // Only keep the .js files
           file.substr(-3) === '.js')
        .forEach(function (file) {
          this.mocha.addFile(
                path.join(testDir, file),
            );
        });*/

    this.runner = this.mocha.run((failures) => {
      process.on('exit', (exitCode) => {
        console.log('process.exit', failures, exitCode);
        if (exitCode !== 0) {
          reject(exitCode);
        }
        process.exit(failures);
      });
      process.on('SIGINT', (error) => {
        console.log('SIGINT', error);
        reject(error);
        process.kill('SIGINT'); // calls runner.abort()
        process.kill('SIGTERM'); // if that didn't work, we're probably in an infinite loop, so make it die.
      });
    });

    const self = this;
    this.runner.on('start', (start) => {
      console.log('START', start);
    });
    this.runner.on('end', (end) => {
      console.log('END', end);
      console.log('self.results', self.results);
      // resolve(this.results);
    });
    this.runner.on('suite', (suite) => {
      console.log('SUITE START', suite);
    });
    this.runner.on('suite end', (suite) => {
      console.log('SUITE END', suite);
    });
    this.runner.on('test', (test) => {
      console.log('TEST START', test);
    });
    this.runner.on('test end', (test) => {
      console.log('TEST END', test);
    });
    this.runner.on('hook', (hook) => {
      console.log('HOOK START', hook);
    });
    this.runner.on('hook end', (hook) => {
      console.log('HOOK END', hook);
    });
    this.runner.on('pass', (test) => {
      this.pushTestResult(test);
      console.log('PASS', test);
    });
    this.runner.on('fail', (test, error) => {
      this.pushTestResult(test);
      console.log('FAIL', test, error);
    });
    this.runner.on('pending', (test) => {
      this.pushTestResult(test);
      console.log('PENDING', test);
    });

    this.pushTestResult = function pushTestResult(test) {
      const trace = test.stackTrace.filter(stackTraceObject =>
        stackTraceObject.fileName === self.fileName);
      console.log('trace', trace);
      self.results.push({
        type: test.state,
        text: test.title,
        range: [
          [trace.lineNumber, trace.columnNumber],
          [trace.lineNumber, trace.columnNumber + test.title.length],
        ],
        filePath: textEditor.getPath(),
      });
    };
  });

  promise.then(function (result) {
    console.log(result); // "Stuff worked!"
    return this.results;
  }, function (err) {
    console.log(err); // Error: "It broke"
    return this.results;
  });

  return promise;
}
<commit_msg>disable reporter<commit_after>'use babel';

/* @flow */

const Mocha = require('mocha');
// const fs = require('fs');
// const path = require('path');

export function run(textEditor) {
  const promise = new Promise(function (resolve, reject) {
    // TODO add to settings
    this.mocha = new Mocha({
      ui: 'bdd',
      reporter: null,
    });
    this.results = [{
      type: 'Error',
      text: 'Something went wrong',
      range: [[0, 0], [0, 1]],
      filePath: textEditor.getPath(),
    }];

    this.fileName = textEditor.getPath();
    this.mocha.addFile(textEditor.getPath());
    // TODO add to settings
    // const testDir = './test';

    /* fs.readdirSync(testDir)
        .filter(file =>
            // Only keep the .js files
           file.substr(-3) === '.js')
        .forEach(function (file) {
          this.mocha.addFile(
                path.join(testDir, file),
            );
        });*/

    this.runner = this.mocha.run((failures) => {
      process.on('exit', (exitCode) => {
        console.log('process.exit', failures, exitCode);
        if (exitCode !== 0) {
          reject(exitCode);
        }
        process.exit(failures);
      });
      process.on('SIGINT', (error) => {
        console.log('SIGINT', error);
        reject(error);
        process.kill('SIGINT'); // calls runner.abort()
        process.kill('SIGTERM'); // if that didn't work, we're probably in an infinite loop, so make it die.
      });
    });

    const self = this;
    this.runner.on('start', (start) => {
      console.log('START', start);
    });
    this.runner.on('end', (end) => {
      console.log('END', end);
      console.log('self.results', self.results);
      // resolve(this.results);
    });
    this.runner.on('suite', (suite) => {
      console.log('SUITE START', suite);
    });
    this.runner.on('suite end', (suite) => {
      console.log('SUITE END', suite);
    });
    this.runner.on('test', (test) => {
      console.log('TEST START', test);
    });
    this.runner.on('test end', (test) => {
      console.log('TEST END', test);
    });
    this.runner.on('hook', (hook) => {
      console.log('HOOK START', hook);
    });
    this.runner.on('hook end', (hook) => {
      console.log('HOOK END', hook);
    });
    this.runner.on('pass', (test) => {
      this.pushTestResult(test);
      console.log('PASS', test);
    });
    this.runner.on('fail', (test, error) => {
      this.pushTestResult(test);
      console.log('FAIL', test, error);
    });
    this.runner.on('pending', (test) => {
      this.pushTestResult(test);
      console.log('PENDING', test);
    });

    this.pushTestResult = function pushTestResult(test) {
      const trace = test.stackTrace.filter(stackTraceObject =>
        stackTraceObject.fileName === self.fileName);
      console.log('trace', trace);
      self.results.push({
        type: test.state,
        text: test.title,
        range: [
          [trace.lineNumber, trace.columnNumber],
          [trace.lineNumber, trace.columnNumber + test.title.length],
        ],
        filePath: textEditor.getPath(),
      });
    };
  });

  promise.then(function (result) {
    console.log(result); // "Stuff worked!"
    return this.results;
  }, function (err) {
    console.log(err); // Error: "It broke"
    return this.results;
  });

  return promise;
}
<|endoftext|>


<commit_before>module.exports = {

	desktop: require("./desktop"),

	Clipboard: require("./desktop/Clipboard").default,
	ClipboardFormats: require("./desktop/ClipboardFormats").default,
	ClipboardTransferMode: require("./desktop/ClipboardTransferMode").default,

	display: require("./display"),

	// Application: require("./display/Application").default,
	Bitmap: require("./display/Bitmap").default,
	BitmapData: require("./display/BitmapData").default,
	BitmapDataChannel: require("./display/BitmapDataChannel").default,
	BlendMode: require("./display/BlendMode").default,
	CanvasRenderer: require("./display/CanvasRenderer").default,
	CapsStyle: require("./display/CapsStyle").default,
	DisplayObject: require("./display/DisplayObject").default,
	DisplayObjectContainer: require("./display/DisplayObjectContainer").default,
	DisplayObjectRenderer: require("./display/DisplayObjectRenderer").default,
	DisplayObjectShader: require("./display/DisplayObjectShader").default,
	DOMElement: require("./display/DOMElement").default,
	DOMRenderer: require("./display/DOMRenderer").default,
	FPS: require("./display/FPS").default,
	FrameLabel: require("./display/FrameLabel").default,
	GradientType: require("./display/GradientType").default,
	Graphics: require("./display/Graphics").default,
	GraphicsBitmapFill: require("./display/GraphicsBitmapFill").default,
	GraphicsEndFill: require("./display/GraphicsEndFill").default,
	GraphicsGradientFill: require("./display/GraphicsGradientFill").default,
	GraphicsPath: require("./display/GraphicsPath").default,
	GraphicsPathCommand: require("./display/GraphicsPathCommand").default,
	GraphicsPathWinding: require("./display/GraphicsPathWinding").default,
	GraphicsQuadPath: require("./display/GraphicsQuadPath").default,
	GraphicsShader: require("./display/GraphicsShader").default,
	GraphicsShaderFill: require("./display/GraphicsShaderFill").default,
	GraphicsSolidFill: require("./display/GraphicsSolidFill").default,
	GraphicsStroke: require("./display/GraphicsStroke").default,
	GraphicsTrianglePath: require("./display/GraphicsTrianglePath").default,
	IBitmapDrawable: require("./display/IBitmapDrawable").default,
	IGraphicsData: require("./display/IGraphicsData").default,
	IGraphicsFill: require("./display/IGraphicsFill").default,
	IGraphicsPath: require("./display/IGraphicsPath").default,
	IGraphicsStroke: require("./display/IGraphicsStroke").default,
	InteractiveObject: require("./display/InteractiveObject").default,
	InterpolationMethod: require("./display/InterpolationMethod").default,
	ITileContainer: require("./display/ITileContainer").default,
	JointStyle: require("./display/JointStyle").default,
	JPEGEncoderOptions: require("./display/JPEGEncoderOptions").default,
	LineScaleMode: require("./display/LineScaleMode").default,
	Loader: require("./display/Loader").default,
	LoaderInfo: require("./display/LoaderInfo").default,
	MovieClip: require("./display/MovieClip").default,
	OpenGLRenderer: require("./display/OpenGLRenderer").default,
	PixelSnapping: require("./display/PixelSnapping").default,
	PNGEncoderOptions: require("./display/PNGEncoderOptions").default,
	Preloader: require("./display/Preloader").default,
	Shader: require("./display/Shader").default,
	ShaderData: require("./display/ShaderData").default,
	ShaderInput: require("./display/ShaderInput").default,
	ShaderJob: require("./display/ShaderJob").default,
	ShaderParameter: require("./display/ShaderParameter").default,
	ShaderParameterType: require("./display/ShaderParameterType").default,
	ShaderPrecision: require("./display/ShaderPrecision").default,
	Shape: require("./display/Shape").default,
	SimpleButton: require("./display/SimpleButton").default,
	SpreadMethod: require("./display/SpreadMethod").default,
	Sprite: require("./display/Sprite").default,
	Stage: require("./display/Stage").default,
	Stage3D: require("./display/Stage3D").default,
	StageAlign: require("./display/StageAlign").default,
	StageDisplayState: require("./display/StageDisplayState").default,
	StageQuality: require("./display/StageQuality").default,
	StageScaleMode: require("./display/StageScaleMode").default,
	Tile: require("./display/Tile").default,
	TileContainer: require("./display/TileContainer").default,
	Tilemap: require("./display/Tilemap").default,
	Tileset: require("./display/Tileset").default,
	TriangleCulling: require("./display/TriangleCulling").default,
	// Window: require("./display/Window").default,

	display3D: require("./display3D"),

	CubeTexture: require("./display3D/textures/CubeTexture").default,
	RectangleTexture: require("./display3D/textures/RectangleTexture").default,
	Texture: require("./display3D/textures/Texture").default,
	TextureBase: require("./display3D/textures/TextureBase").default,
	VideoTexture: require("./display3D/textures/VideoTexture").default,

	Context3D: require("./display3D/Context3D").default,
	Context3DBlendFactor: require("./display3D/Context3DBlendFactor").default,
	Context3DBufferUsage: require("./display3D/Context3DBufferUsage").default,
	Context3DClearMask: require("./display3D/Context3DClearMask").default,
	Context3DCompareMode: require("./display3D/Context3DCompareMode").default,
	Context3DMipFilter: require("./display3D/Context3DMipFilter").default,
	Context3DProfile: require("./display3D/Context3DProfile").default,
	Context3DProgramType: require("./display3D/Context3DProgramType").default,
	Context3DRenderMode: require("./display3D/Context3DRenderMode").default,
	Context3DStencilAction: require("./display3D/Context3DStencilAction").default,
	Context3DTextureFilter: require("./display3D/Context3DTextureFilter").default,
	Context3DTextureFormat: require("./display3D/Context3DTextureFormat").default,
	Context3DTriangleFace: require("./display3D/Context3DTriangleFace").default,
	Context3DVertexBufferFormat: require("./display3D/Context3DVertexBufferFormat").default,
	Context3DWrapMode: require("./display3D/Context3DWrapMode").default,
	IndexBuffer3D: require("./display3D/IndexBuffer3D").default,
	Program3D: require("./display3D/Program3D").default,
	VertexBuffer3D: require("./display3D/VertexBuffer3D").default,

	errors: require("./errors"),

	ArgumentError: require("./errors/ArgumentError").default,
	EOFError: require("./errors/EOFError").default,
	Error: require("./errors/Error").default,
	IllegalOperationError: require("./errors/IllegalOperationError").default,
	IOError: require("./errors/IOError").default,
	RangeError: require("./errors/RangeError").default,
	SecurityError: require("./errors/SecurityError").default,
	TypeError: require("./errors/TypeError").default,

	events: require("./events"),

	AccelerometerEvent: require("./events/AccelerometerEvent").default,
	ActivityEvent: require("./events/ActivityEvent").default,
	AsyncErrorEvent: require("./events/AsyncErrorEvent").default,
	DataEvent: require("./events/DataEvent").default,
	ErrorEvent: require("./events/ErrorEvent").default,
	Event: require("./events/Event").default,
	EventDispatcher: require("./events/EventDispatcher").default,
	EventPhase: require("./events/EventPhase").default,
	FocusEvent: require("./events/FocusEvent").default,
	FullScreenEvent: require("./events/FullScreenEvent").default,
	GameInputEvent: require("./events/GameInputEvent").default,
	HTTPStatusEvent: require("./events/HTTPStatusEvent").default,
	IEventDispatcher: require("./events/IEventDispatcher").default,
	IOErrorEvent: require("./events/IOErrorEvent").default,
	KeyboardEvent: require("./events/KeyboardEvent").default,
	MouseEvent: require("./events/MouseEvent").default,
	NetStatusEvent: require("./events/NetStatusEvent").default,
	ProgressEvent: require("./events/ProgressEvent").default,
	RenderEvent: require("./events/RenderEvent").default,
	SampleDataEvent: require("./events/SampleDataEvent").default,
	SecurityErrorEvent: require("./events/SecurityErrorEvent").default,
	TextEvent: require("./events/TextEvent").default,
	TimerEvent: require("./events/TimerEvent").default,
	TouchEvent: require("./events/TouchEvent").default,
	UncaughtErrorEvent: require("./events/UncaughtErrorEvent").default,
	UncaughtErrorEvents: require("./events/UncaughtErrorEvents").default,

	external: require("./external"),

	ExternalInterface: require("./external/ExternalInterface").default,

	filters: require("./filters"),

	BitmapFilter: require("./filters/BitmapFilter").default,
	BitmapFilterQuality: require("./filters/BitmapFilterQuality").default,
	BitmapFilterShader: require("./filters/BitmapFilterShader").default,
	BitmapFilterType: require("./filters/BitmapFilterType").default,
	BlurFilter: require("./filters/BlurFilter").default,
	ColorMatrixFilter: require("./filters/ColorMatrixFilter").default,
	ConvolutionFilter: require("./filters/ConvolutionFilter").default,
	DropShadowFilter: require("./filters/DropShadowFilter").default,
	GlowFilter: require("./filters/GlowFilter").default,
	ShaderFilter: require("./filters/ShaderFilter").default,

	geom: require("./geom"),

	ColorTransform: require("./geom/ColorTransform").default,
	Matrix: require("./geom/Matrix").default,
	Matrix3D: require("./geom/Matrix3D").default,
	Orientation3D: require("./geom/Orientation3D").default,
	PerspectiveProjection: require("./geom/PerspectiveProjection").default,
	Point: require("./geom/Point").default,
	Rectangle: require("./geom/Rectangle").default,
	Transform: require("./geom/Transform").default,
	Utils3D: require("./geom/Utils3D").default,
	Vector3D: require("./geom/Vector3D").default,

	media: require("./media"),

	ID3Info: require("./media/ID3Info").default,
	Sound: require("./media/Sound").default,
	SoundChannel: require("./media/SoundChannel").default,
	SoundLoaderContext: require("./media/SoundLoaderContext").default,
	SoundMixer: require("./media/SoundMixer").default,
	SoundTransform: require("./media/SoundTransform").default,
	Video: require("./media/Video").default,

	net: require("./net"),

	FileFilter: require("./net/FileFilter").default,
	FileReference: require("./net/FileReference").default,
	FileReferenceList: require("./net/FileReferenceList").default,
	NetConnection: require("./net/NetConnection").default,
	NetStream: require("./net/NetStream").default,
	ObjectEncoding: require("./net/ObjectEncoding").default,
	SharedObject: require("./net/SharedObject").default,
	SharedObjectFlushStatus: require("./net/SharedObjectFlushStatus").default,
	Socket: require("./net/Socket").default,
	URLLoader: require("./net/URLLoader").default,
	URLLoaderDataFormat: require("./net/URLLoaderDataFormat").default,
	URLRequest: require("./net/URLRequest").default,
	URLRequestDefaults: require("./net/URLRequestDefaults").default,
	URLRequestHeader: require("./net/URLRequestHeader").default,
	URLRequestMethod: require("./net/URLRequestMethod").default,
	URLStream: require("./net/URLStream").default,
	URLVariables: require("./net/URLVariables").default,
	XMLSocket: require("./net/XMLSocket").default,
	navigateToURL: require("./net/navigateToURL").default,
	sendToURL: require("./net/sendToURL").default,

	printing: require("./printing"),

	PrintJob: require("./printing/PrintJob").default,
	PrintJobOptions: require("./printing/PrintJobOptions").default,
	PrintJobOrientation: require("./printing/PrintJobOrientation").default,

	profiler: require("./profiler"),

	Telemetry: require("./profiler/Telemetry").default,

	sensors: require("./sensors"),

	Accelerometer: require("./sensors/Accelerometer").default,

	system: require("./system"),

	ApplicationDomain: require("./system/ApplicationDomain").default,
	Capabilities: require("./system/Capabilities").default,
	LoaderContext: require("./system/LoaderContext").default,
	Security: require("./system/Security").default,
	SecurityDomain: require("./system/SecurityDomain").default,
	System: require("./system/System").default,
	TouchscreenType: require("./system/TouchscreenType").default,

	text: require("./text"),

	AntiAliasType: require("./text/AntiAliasType").default,
	Font: require("./text/Font").default,
	FontStyle: require("./text/FontStyle").default,
	FontType: require("./text/FontType").default,
	GridFitType: require("./text/GridFitType").default,
	TextField: require("./text/TextField").default,
	TextFieldAutoSize: require("./text/TextFieldAutoSize").default,
	TextFieldType: require("./text/TextFieldType").default,
	TextFormat: require("./text/TextFormat").default,
	TextFormatAlign: require("./text/TextFormatAlign").default,
	TextLineMetrics: require("./text/TextLineMetrics").default,

	ui: require("./ui"),

	GameInput: require("./ui/GameInput").default,
	GameInputControl: require("./ui/GameInputControl").default,
	GameInputDevice: require("./ui/GameInputDevice").default,
	Keyboard: require("./ui/Keyboard").default,
	KeyLocation: require("./ui/KeyLocation").default,
	Mouse: require("./ui/Mouse").default,
	MouseCursor: require("./ui/MouseCursor").default,
	Multitouch: require("./ui/Multitouch").default,
	MultitouchInputMode: require("./ui/MultitouchInputMode").default,

	utils: require("./utils"),

	AGALMiniAssembler: require("./utils/AGALMiniAssembler").default,
	AssetCache: require("./utils/AssetCache").default,
	AssetLibrary: require("./utils/AssetLibrary").default,
	AssetManifest: require("./utils/AssetManifest").default,
	Assets: require("./utils/Assets").default,
	AssetType: require("./utils/AssetType").default,
	ByteArray: require("./utils/ByteArray").default,
	CompressionAlgorithm: require("./utils/CompressionAlgorithm").default,
	Dictionary: require("./utils/Dictionary").default,
	Endian: require("./utils/Endian").default,
	Future: require("./utils/Future").default,
	IAssetCache: require("./utils/IAssetCache").default,
	IDataInput: require("./utils/IDataInput").default,
	IDataOutput: require("./utils/IDataOutput").default,
	// IExternalizable: require("./utils/IExternalizable").default,
	// Object: require("./utils/Object").default,
	Timer: require("./utils/Timer").default,
	getDefinitionByName: require("./utils/getDefinitionByName").default,
	getQualifiedClassName: require("./utils/getQualifiedClassName").default,
	getQualifiedSuperclassName: require("./utils/getQualifiedSuperclassName").default,
	getTimer: require("./utils/getTimer").default,
	setTimeout: require("./utils/setTimeout").default,
	clearTimeout: require("./utils/clearTimeout").default,

	Lib: require("./Lib").default,
	Memory: require("./Memory").default,
	Vector: require("./Vector").default,

}
<commit_msg>Update index.js<commit_after>module.exports = {

	desktop: require("./desktop"),

	Clipboard: require("./desktop/Clipboard").default,
	ClipboardFormats: require("./desktop/ClipboardFormats").default,
	ClipboardTransferMode: require("./desktop/ClipboardTransferMode").default,

	display: require("./display"),

	// Application: require("./display/Application").default,
	Bitmap: require("./display/Bitmap").default,
	BitmapData: require("./display/BitmapData").default,
	BitmapDataChannel: require("./display/BitmapDataChannel").default,
	BlendMode: require("./display/BlendMode").default,
	CanvasRenderer: require("./display/CanvasRenderer").default,
	CapsStyle: require("./display/CapsStyle").default,
	DisplayObject: require("./display/DisplayObject").default,
	DisplayObjectContainer: require("./display/DisplayObjectContainer").default,
	DisplayObjectRenderer: require("./display/DisplayObjectRenderer").default,
	DisplayObjectShader: require("./display/DisplayObjectShader").default,
	DOMElement: require("./display/DOMElement").default,
	DOMRenderer: require("./display/DOMRenderer").default,
	FPS: require("./display/FPS").default,
	FrameLabel: require("./display/FrameLabel").default,
	GradientType: require("./display/GradientType").default,
	Graphics: require("./display/Graphics").default,
	GraphicsBitmapFill: require("./display/GraphicsBitmapFill").default,
	GraphicsEndFill: require("./display/GraphicsEndFill").default,
	GraphicsGradientFill: require("./display/GraphicsGradientFill").default,
	GraphicsPath: require("./display/GraphicsPath").default,
	GraphicsPathCommand: require("./display/GraphicsPathCommand").default,
	GraphicsPathWinding: require("./display/GraphicsPathWinding").default,
	GraphicsQuadPath: require("./display/GraphicsQuadPath").default,
	GraphicsShader: require("./display/GraphicsShader").default,
	GraphicsShaderFill: require("./display/GraphicsShaderFill").default,
	GraphicsSolidFill: require("./display/GraphicsSolidFill").default,
	GraphicsStroke: require("./display/GraphicsStroke").default,
	GraphicsTrianglePath: require("./display/GraphicsTrianglePath").default,
	IBitmapDrawable: require("./display/IBitmapDrawable").default,
	IGraphicsData: require("./display/IGraphicsData").default,
	IGraphicsFill: require("./display/IGraphicsFill").default,
	IGraphicsPath: require("./display/IGraphicsPath").default,
	IGraphicsStroke: require("./display/IGraphicsStroke").default,
	InteractiveObject: require("./display/InteractiveObject").default,
	InterpolationMethod: require("./display/InterpolationMethod").default,
	ITileContainer: require("./display/ITileContainer").default,
	JointStyle: require("./display/JointStyle").default,
	JPEGEncoderOptions: require("./display/JPEGEncoderOptions").default,
	LineScaleMode: require("./display/LineScaleMode").default,
	Loader: require("./display/Loader").default,
	LoaderInfo: require("./display/LoaderInfo").default,
	MovieClip: require("./display/MovieClip").default,
	OpenGLRenderer: require("./display/OpenGLRenderer").default,
	PixelSnapping: require("./display/PixelSnapping").default,
	PNGEncoderOptions: require("./display/PNGEncoderOptions").default,
	Preloader: require("./display/Preloader").default,
	Shader: require("./display/Shader").default,
	ShaderData: require("./display/ShaderData").default,
	ShaderInput: require("./display/ShaderInput").default,
	ShaderJob: require("./display/ShaderJob").default,
	ShaderParameter: require("./display/ShaderParameter").default,
	ShaderParameterType: require("./display/ShaderParameterType").default,
	ShaderPrecision: require("./display/ShaderPrecision").default,
	Shape: require("./display/Shape").default,
	SimpleButton: require("./display/SimpleButton").default,
	SpreadMethod: require("./display/SpreadMethod").default,
	Sprite: require("./display/Sprite").default,
	Stage: require("./display/Stage").default,
	Stage3D: require("./display/Stage3D").default,
	StageAlign: require("./display/StageAlign").default,
	StageDisplayState: require("./display/StageDisplayState").default,
	StageQuality: require("./display/StageQuality").default,
	StageScaleMode: require("./display/StageScaleMode").default,
	Tile: require("./display/Tile").default,
	TileContainer: require("./display/TileContainer").default,
	Tilemap: require("./display/Tilemap").default,
	Tileset: require("./display/Tileset").default,
	TriangleCulling: require("./display/TriangleCulling").default,
	// Window: require("./display/Window").default,

	display3D: require("./display3D"),

	CubeTexture: require("./display3D/textures/CubeTexture").default,
	RectangleTexture: require("./display3D/textures/RectangleTexture").default,
	Texture: require("./display3D/textures/Texture").default,
	TextureBase: require("./display3D/textures/TextureBase").default,
	VideoTexture: require("./display3D/textures/VideoTexture").default,

	Context3D: require("./display3D/Context3D").default,
	Context3DBlendFactor: require("./display3D/Context3DBlendFactor").default,
	Context3DBufferUsage: require("./display3D/Context3DBufferUsage").default,
	Context3DClearMask: require("./display3D/Context3DClearMask").default,
	Context3DCompareMode: require("./display3D/Context3DCompareMode").default,
	Context3DMipFilter: require("./display3D/Context3DMipFilter").default,
	Context3DProfile: require("./display3D/Context3DProfile").default,
	Context3DProgramType: require("./display3D/Context3DProgramType").default,
	Context3DRenderMode: require("./display3D/Context3DRenderMode").default,
	Context3DStencilAction: require("./display3D/Context3DStencilAction").default,
	Context3DTextureFilter: require("./display3D/Context3DTextureFilter").default,
	Context3DTextureFormat: require("./display3D/Context3DTextureFormat").default,
	Context3DTriangleFace: require("./display3D/Context3DTriangleFace").default,
	Context3DVertexBufferFormat: require("./display3D/Context3DVertexBufferFormat").default,
	Context3DWrapMode: require("./display3D/Context3DWrapMode").default,
	IndexBuffer3D: require("./display3D/IndexBuffer3D").default,
	Program3D: require("./display3D/Program3D").default,
	VertexBuffer3D: require("./display3D/VertexBuffer3D").default,

	errors: require("./errors"),

	ArgumentError: require("./errors/ArgumentError").default,
	EOFError: require("./errors/EOFError").default,
	Error: require("./errors/Error").default,
	IllegalOperationError: require("./errors/IllegalOperationError").default,
	IOError: require("./errors/IOError").default,
	RangeError: require("./errors/RangeError").default,
	SecurityError: require("./errors/SecurityError").default,
	TypeError: require("./errors/TypeError").default,

	events: require("./events"),

	AccelerometerEvent: require("./events/AccelerometerEvent").default,
	ActivityEvent: require("./events/ActivityEvent").default,
	AsyncErrorEvent: require("./events/AsyncErrorEvent").default,
	DataEvent: require("./events/DataEvent").default,
	ErrorEvent: require("./events/ErrorEvent").default,
	Event: require("./events/Event").default,
	EventDispatcher: require("./events/EventDispatcher").default,
	EventPhase: require("./events/EventPhase").default,
	FocusEvent: require("./events/FocusEvent").default,
	FullScreenEvent: require("./events/FullScreenEvent").default,
	GameInputEvent: require("./events/GameInputEvent").default,
	HTTPStatusEvent: require("./events/HTTPStatusEvent").default,
	IEventDispatcher: require("./events/IEventDispatcher").default,
	IOErrorEvent: require("./events/IOErrorEvent").default,
	KeyboardEvent: require("./events/KeyboardEvent").default,
	MouseEvent: require("./events/MouseEvent").default,
	NetStatusEvent: require("./events/NetStatusEvent").default,
	ProgressEvent: require("./events/ProgressEvent").default,
	RenderEvent: require("./events/RenderEvent").default,
	SampleDataEvent: require("./events/SampleDataEvent").default,
	SecurityErrorEvent: require("./events/SecurityErrorEvent").default,
	TextEvent: require("./events/TextEvent").default,
	TimerEvent: require("./events/TimerEvent").default,
	TouchEvent: require("./events/TouchEvent").default,
	UncaughtErrorEvent: require("./events/UncaughtErrorEvent").default,
	UncaughtErrorEvents: require("./events/UncaughtErrorEvents").default,

	external: require("./external"),

	ExternalInterface: require("./external/ExternalInterface").default,

	filters: require("./filters"),

	BitmapFilter: require("./filters/BitmapFilter").default,
	BitmapFilterQuality: require("./filters/BitmapFilterQuality").default,
	BitmapFilterShader: require("./filters/BitmapFilterShader").default,
	BitmapFilterType: require("./filters/BitmapFilterType").default,
	BlurFilter: require("./filters/BlurFilter").default,
	ColorMatrixFilter: require("./filters/ColorMatrixFilter").default,
	ConvolutionFilter: require("./filters/ConvolutionFilter").default,
	DropShadowFilter: require("./filters/DropShadowFilter").default,
	GlowFilter: require("./filters/GlowFilter").default,
	ShaderFilter: require("./filters/ShaderFilter").default,

	geom: require("./geom"),

	ColorTransform: require("./geom/ColorTransform").default,
	Matrix: require("./geom/Matrix").default,
	Matrix3D: require("./geom/Matrix3D").default,
	Orientation3D: require("./geom/Orientation3D").default,
	PerspectiveProjection: require("./geom/PerspectiveProjection").default,
	Point: require("./geom/Point").default,
	Rectangle: require("./geom/Rectangle").default,
	Transform: require("./geom/Transform").default,
	Utils3D: require("./geom/Utils3D").default,
	Vector3D: require("./geom/Vector3D").default,

	media: require("./media"),

	ID3Info: require("./media/ID3Info").default,
	Sound: require("./media/Sound").default,
	SoundChannel: require("./media/SoundChannel").default,
	SoundLoaderContext: require("./media/SoundLoaderContext").default,
	SoundMixer: require("./media/SoundMixer").default,
	SoundTransform: require("./media/SoundTransform").default,
	Video: require("./media/Video").default,

	net: require("./net"),

	FileFilter: require("./net/FileFilter").default,
	FileReference: require("./net/FileReference").default,
	FileReferenceList: require("./net/FileReferenceList").default,
	NetConnection: require("./net/NetConnection").default,
	NetStream: require("./net/NetStream").default,
	ObjectEncoding: require("./net/ObjectEncoding").default,
	SharedObject: require("./net/SharedObject").default,
	SharedObjectFlushStatus: require("./net/SharedObjectFlushStatus").default,
	Socket: require("./net/Socket").default,
	URLLoader: require("./net/URLLoader").default,
	URLLoaderDataFormat: require("./net/URLLoaderDataFormat").default,
	URLRequest: require("./net/URLRequest").default,
	URLRequestDefaults: require("./net/URLRequestDefaults").default,
	URLRequestHeader: require("./net/URLRequestHeader").default,
	URLRequestMethod: require("./net/URLRequestMethod").default,
	URLStream: require("./net/URLStream").default,
	URLVariables: require("./net/URLVariables").default,
	XMLSocket: require("./net/XMLSocket").default,
	navigateToURL: require("./net/navigateToURL").default,
	sendToURL: require("./net/sendToURL").default,

	printing: require("./printing"),

	PrintJob: require("./printing/PrintJob").default,
	PrintJobOptions: require("./printing/PrintJobOptions").default,
	PrintJobOrientation: require("./printing/PrintJobOrientation").default,

	profiler: require("./profiler"),

	Telemetry: require("./profiler/Telemetry").default,

	sensors: require("./sensors"),

	Accelerometer: require("./sensors/Accelerometer").default,

	system: require("./system"),

	ApplicationDomain: require("./system/ApplicationDomain").default,
	Capabilities: require("./system/Capabilities").default,
	LoaderContext: require("./system/LoaderContext").default,
	Security: require("./system/Security").default,
	SecurityDomain: require("./system/SecurityDomain").default,
	System: require("./system/System").default,
	TouchscreenType: require("./system/TouchscreenType").default,

	text: require("./text"),

	AntiAliasType: require("./text/AntiAliasType").default,
	Font: require("./text/Font").default,
	FontStyle: require("./text/FontStyle").default,
	FontType: require("./text/FontType").default,
	GridFitType: require("./text/GridFitType").default,
	TextField: require("./text/TextField").default,
	TextFieldAutoSize: require("./text/TextFieldAutoSize").default,
	TextFieldType: require("./text/TextFieldType").default,
	TextFormat: require("./text/TextFormat").default,
	TextFormatAlign: require("./text/TextFormatAlign").default,
	TextLineMetrics: require("./text/TextLineMetrics").default,

	ui: require("./ui"),

	GameInput: require("./ui/GameInput").default,
	GameInputControl: require("./ui/GameInputControl").default,
	GameInputDevice: require("./ui/GameInputDevice").default,
	Keyboard: require("./ui/Keyboard").default,
	KeyLocation: require("./ui/KeyLocation").default,
	Mouse: require("./ui/Mouse").default,
	MouseCursor: require("./ui/MouseCursor").default,
	Multitouch: require("./ui/Multitouch").default,
	MultitouchInputMode: require("./ui/MultitouchInputMode").default,

	utils: require("./utils"),

	AGALMiniAssembler: require("./utils/AGALMiniAssembler").default,
	AssetCache: require("./utils/AssetCache").default,
	AssetLibrary: require("./utils/AssetLibrary").default,
	AssetManifest: require("./utils/AssetManifest").default,
	Assets: require("./utils/Assets").default,
	AssetType: require("./utils/AssetType").default,
	ByteArray: require("./utils/ByteArray").default,
	CompressionAlgorithm: require("./utils/CompressionAlgorithm").default,
	Dictionary: require("./utils/Dictionary").default,
	Endian: require("./utils/Endian").default,
	Future: require("./utils/Future").default,
	IAssetCache: require("./utils/IAssetCache").default,
	IDataInput: require("./utils/IDataInput").default,
	IDataOutput: require("./utils/IDataOutput").default,
	// IExternalizable: require("./utils/IExternalizable").default,
	// Object: require("./utils/Object").default,
	Timer: require("./utils/Timer").default,
	clearTimeout: require("./utils/clearTimeout").default,
	getDefinitionByName: require("./utils/getDefinitionByName").default,
	getQualifiedClassName: require("./utils/getQualifiedClassName").default,
	getQualifiedSuperclassName: require("./utils/getQualifiedSuperclassName").default,
	getTimer: require("./utils/getTimer").default,
	setTimeout: require("./utils/setTimeout").default,

	Lib: require("./Lib").default,
	Memory: require("./Memory").default,
	Vector: require("./Vector").default,

}
<|endoftext|>


<commit_before>'use strict';

var R = require('ramda');
var request = require('request');
var pjson = require('../package.json');

var PlaidError = require('./PlaidError');
var wrapPromise = require('./wrapPromise');

// Max timeout of ten minutes
var DEFAULT_TIMEOUT_IN_MILLIS = 10 * 60 * 1000;

var handleApiResponse = function(resolve, reject, err, res, $body, isMfa) {
  if (res != null && R.type($body) === 'Object') {
    $body.status_code = res.statusCode;
  }

  // network / usage errors
  if (err != null) {
    return reject(err);

  // success response (MFA)
  } else if (isMfa && res.statusCode === 200) {
    return resolve([null, $body]);

  // mfa response (MFA)
  } else if (isMfa && res.statusCode === 210) {
    return resolve([$body, null]);

  // success response (non mfa)
  } else if (res.statusCode === 200) {
    // extract request id from header for binary data,
    // i.e. mime type application/*
    if (res.headers['plaid-request-id'] != null &&
        res.headers['content-type'] != null &&
        res.headers['content-type'].indexOf('application') === 0) {
      return resolve({
        request_id: res.headers['plaid-request-id'],
        buffer: $body
      });
    }
    return resolve($body);

  // plaid error
  } else if (R.type($body) === 'Object') {
    return reject(new PlaidError($body));

  // Unknown body type returned, return a standard API_ERROR
  } else {
    return reject(new PlaidError({
      error_type: 'API_ERROR',
      status_code: res.statusCode,
      error_code: 'INTERNAL_SERVER_ERROR',
      error_message: String($body),
      display_message: null,
      request_id: null,
    }));
  }
};

var plaidRequest = function(context, requestSpec, clientRequestOptions, cb) {
  var uri = context.env + requestSpec.path;
  var method = 'POST';
  var requestJSON = R.merge(R.dissoc('env', context), requestSpec.body);
  var headers = {
    'User-Agent': 'Plaid Node v' + pjson.version
  };

  if (clientRequestOptions.version != null) {
    headers['Plaid-Version'] = clientRequestOptions.version;
  }

  if (clientRequestOptions.clientApp != null) {
    headers['Plaid-Client-App'] = clientRequestOptions.clientApp
  }

  // merge the default request options with the client specified options,
  // this allows for clients to supply extra options to the request function
  var requestOptions = R.merge({
    uri: uri,
    method: method,
    json: requestJSON,
    headers: headers,
    timeout: DEFAULT_TIMEOUT_IN_MILLIS,
    encoding: requestSpec.binary ? null : 'utf8',
  }, clientRequestOptions);

  return wrapPromise(new Promise(function(resolve, reject) {
    request(requestOptions, function(err, res, body) {
      handleApiResponse(resolve, reject, err, res, body,
        requestSpec.includeMfaResponse);
    });
  }), cb);
};

module.exports = plaidRequest;
<commit_msg>fix lint (#197)<commit_after>'use strict';

var R = require('ramda');
var request = require('request');
var pjson = require('../package.json');

var PlaidError = require('./PlaidError');
var wrapPromise = require('./wrapPromise');

// Max timeout of ten minutes
var DEFAULT_TIMEOUT_IN_MILLIS = 10 * 60 * 1000;

var handleApiResponse = function(resolve, reject, err, res, $body, isMfa) {
  if (res != null && R.type($body) === 'Object') {
    $body.status_code = res.statusCode;
  }

  // network / usage errors
  if (err != null) {
    return reject(err);

  // success response (MFA)
  } else if (isMfa && res.statusCode === 200) {
    return resolve([null, $body]);

  // mfa response (MFA)
  } else if (isMfa && res.statusCode === 210) {
    return resolve([$body, null]);

  // success response (non mfa)
  } else if (res.statusCode === 200) {
    // extract request id from header for binary data,
    // i.e. mime type application/*
    if (res.headers['plaid-request-id'] != null &&
        res.headers['content-type'] != null &&
        res.headers['content-type'].indexOf('application') === 0) {
      return resolve({
        request_id: res.headers['plaid-request-id'],
        buffer: $body
      });
    }
    return resolve($body);

  // plaid error
  } else if (R.type($body) === 'Object') {
    return reject(new PlaidError($body));

  // Unknown body type returned, return a standard API_ERROR
  } else {
    return reject(new PlaidError({
      error_type: 'API_ERROR',
      status_code: res.statusCode,
      error_code: 'INTERNAL_SERVER_ERROR',
      error_message: String($body),
      display_message: null,
      request_id: null,
    }));
  }
};

var plaidRequest = function(context, requestSpec, clientRequestOptions, cb) {
  var uri = context.env + requestSpec.path;
  var method = 'POST';
  var requestJSON = R.merge(R.dissoc('env', context), requestSpec.body);
  var headers = {
    'User-Agent': 'Plaid Node v' + pjson.version
  };

  if (clientRequestOptions.version != null) {
    headers['Plaid-Version'] = clientRequestOptions.version;
  }

  if (clientRequestOptions.clientApp != null) {
    headers['Plaid-Client-App'] = clientRequestOptions.clientApp;
  }

  // merge the default request options with the client specified options,
  // this allows for clients to supply extra options to the request function
  var requestOptions = R.merge({
    uri: uri,
    method: method,
    json: requestJSON,
    headers: headers,
    timeout: DEFAULT_TIMEOUT_IN_MILLIS,
    encoding: requestSpec.binary ? null : 'utf8',
  }, clientRequestOptions);

  return wrapPromise(new Promise(function(resolve, reject) {
    request(requestOptions, function(err, res, body) {
      handleApiResponse(resolve, reject, err, res, body,
        requestSpec.includeMfaResponse);
    });
  }), cb);
};

module.exports = plaidRequest;
<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');
var moment = require('moment');
var times = require('../times');
var levels = require('../levels');
var timeago = require('./timeago')();

// var ALL_STATUS_FIELDS = ['status-symbol', 'status-label', 'iob', 'freq', 'rssi']; Unused variable

function init() {

  var loop = {
    name: 'loop'
    , label: 'Loop'
    , pluginType: 'pill-status'
  };

  var firstPrefs = true;

  loop.getPrefs = function getPrefs(sbx) {

    var prefs = {
      warn: sbx.extendedSettings.warn ? sbx.extendedSettings.warn : 30
      , urgent: sbx.extendedSettings.urgent ? sbx.extendedSettings.urgent : 60
      , enableAlerts: sbx.extendedSettings.enableAlerts
    };

    if (firstPrefs) {
      firstPrefs = false;
      console.info(' Prefs:', prefs);
    }

    return prefs;
  };

  loop.setProperties = function setProperties (sbx) {
    sbx.offerProperty('loop', function setLoop ( ) {
      return loop.analyzeData(sbx);
    });
  };

  loop.analyzeData = function analyzeData (sbx) {
    var recentHours = 6;
    var recentMills = sbx.time - times.hours(recentHours).msecs;

    var recentData = _.chain(sbx.data.devicestatus)
      .filter(function (status) {
        return ('loop' in status) && sbx.entryMills(status) <= sbx.time && sbx.entryMills(status) >= recentMills;
      }).value( );

    var prefs = loop.getPrefs(sbx);
    var recent = moment(sbx.time).subtract(prefs.warn / 2, 'minutes');

    function getDisplayForStatus (status)  {

      var desc = {
        symbol: '⚠'
        , code: 'warning'
        , label: 'Warning'
      };

      if (!status) {
        return desc
      }

      if (status.failureReason || (status.enacted && !status.enacted.received)) {
        desc.symbol = 'x';
        desc.code = 'error';
        desc.label = 'Error';
      } else if (status.enacted && moment(status.timestamp).isAfter(recent)) {
        desc.symbol = '⌁';
        desc.code = 'enacted';
        desc.label = 'Enacted';
      } else if (status.recommendedTempBasal && moment(status.recommendedTempBasal.timestamp).isAfter(recent)) {
        desc.symbol = '⏀';
        desc.code = 'recommendation';
        desc.label = 'Recomendation';
      } else if (status.moment && status.moment.isAfter(recent)) {
        desc.symbol = '↻';
        desc.code = 'looping';
        desc.label = 'Looping';
      }
      return desc;
    }

    var result = {
      lastLoop: null
      , lastEnacted: null
      , lastOkMoment: null
    };

    _.forEach(recentData, function eachStatus (status) {
      if (status && status.loop && status.loop.timestamp) {
        var loop = status.loop
        loop.moment = moment(loop.timestamp);

        var enacted = loop.enacted;
        if (enacted && enacted.timestamp) {
          enacted.moment = moment(enacted.timestamp)
          if (!result.lastEnacted || enacted.moment.isAfter(result.lastEnacted.moment)) {
            result.lastEnacted = enacted;
          }
        }

        if (!result.lastLoop || loop.moment.isAfter(result.lastLoop.moment)) {
          result.lastLoop = loop
        }

        if (!loop.failureReason && (!result.lastOkMoment || loop.moment.isAfter(result.lastOkMoment))) {
          result.lastOkMoment = loop.moment
        }
      }

    });

    result.display = getDisplayForStatus(result.lastLoop);

    return result;
  };

  loop.checkNotifications = function checkNotifications(sbx) {
    var prefs = loop.getPrefs(sbx);

    if (!prefs.enableAlerts) { return; }

    var prop = sbx.properties.loop;

    if (!prop.lastLoop) {
      console.info('Loop hasn\'t reported a loop yet');
      return;
    }

    var now = moment();
    var level = statusLevel(prop, prefs, sbx);
    if (level >= levels.WARN) {
      sbx.notifications.requestNotify({
        level: level
        , title: 'Loop isn\'t looping'
        , message: 'Last Loop: ' + formatAgo(prop.lastLoop.moment, now.valueOf())
        , pushoverSound: 'echo'
        , group: 'Loop'
        , plugin: loop
        , debug: prop
      });
    }
  };

  loop.updateVisualisation = function updateVisualisation (sbx) {
    var prop = sbx.properties.loop;

    var prefs = loop.getPrefs(sbx);

    function valueString (prefix, value) {
      return (value != null) ? prefix + value : '';
    }

    var events = [ ];

    function addRecommendedTempBasal() {
      if (prop.lastLoop && prop.lastLoop.recommendedTempBasal) {

        var recommendedTempBasal = prop.lastLoop.recommendedTempBasal

        var valueParts = [
          'Suggested Temp: ' + recommendedTempBasal.rate + "U/hour for " +
          recommendedTempBasal.duration + "m"
        ];

        valueParts = concatIOB(valueParts);
        valueParts = concatCOB(valueParts);

        events.push({
          time: moment(recommendedTempBasal.timestamp)
          , value: valueParts.join('')
        });
      }
    }

    function concatIOB (valueParts) {
      if (prop.lastLoop && prop.lastLoop.iob) {
        var iob = prop.lastLoop.iob
        valueParts = valueParts.concat([
          ', IOB: '
          , sbx.roundInsulinForDisplayFormat(iob.iob) + 'U'
          , iob.basaliob ? ', Basal IOB ' + sbx.roundInsulinForDisplayFormat(iob.basaliob) + 'U' : ''
        ]);
      }

      return valueParts;
    }

    function concatCOB (valueParts) {
      if (prop.lastLoop && prop.lastLoop.cob) {
        cob = prop.lastLoop.cob
        valueParts = valueParts.concat([
          ', COB: '
          , cob.cob + 'g'
        ]);
      }

      return valueParts;
    }

    function getForecastPoints ( ) {
      var points = [ ];

      function toPoints (startTime, offset) {
        return  function toPoint (value, index) {
          return {
            mgdl: value
            , color: '#ff00ff'
            , mills: startTime.valueOf() + times.mins(5 * index).msecs + offset
            , noFade: true
          };
        };
      }

      if (prop.lastLoop && prop.lastLoop.predicted && prop.lastLoop.predicted.startDate) {
        var predicted = prop.lastLoop.predicted;
        var startTime = moment(predicted.startDate);
        if (predicted.values) {
          points = points.concat(_.map(predicted.values, toPoints(startTime, 0)));
        }
        // if (prop.lastPredBGs.IOB) {
        //   points = points.concat(_.map(prop.lastPredBGs.IOB, toPoints(moment, 3000)));
        // }
        // if (prop.lastPredBGs.COB) {
        //   points = points.concat(_.map(prop.lastPredBGs.COB, toPoints(moment, 7000)));
        // }
      }

      return points;
    }

    if ('error' === prop.display.code) {
      events.push({
        time: prop.lastLoop.moment
        , value: valueString('Error: ', prop.lastLoop.failureReason)
      });
      addRecommendedTempBasal();
    }

    if ('enacted' === prop.display.code) {
      var canceled = prop.lastEnacted.rate === 0 && prop.lastEnacted.duration === 0;

      var valueParts = [
        valueString('BG: ', prop.lastEnacted.bg)
        , 'Temp Basal' + (canceled ? ' Canceled' : ' Started') + ''
        , canceled ? '' : ' ' + prop.lastEnacted.rate.toFixed(2) + 'U/hour for ' + prop.lastEnacted.duration + 'm'
        , valueString(', ', prop.lastEnacted.reason)
      ];

      valueParts = concatIOB(valueParts);
      valueParts = concatCOB(valueParts);

      events.push({
        time: prop.lastEnacted.moment
        , value: valueParts.join('')
      });
    } else {
      addRecommendedTempBasal();
    }

    var sorted = _.sortBy(events, function toMill(event) {
      return event.time.valueOf();
    }).reverse();

    var info = _.map(sorted, function eventToInfo (event) {
      return {
        label: timeAt(false, sbx) + timeFormat(event.time, sbx)
        , value: event.value
      };
    });

    var label = 'Loop ' + prop.display.symbol;

    var lastLoopMoment = prop.lastLoop ? prop.lastLoop.moment : null;

    sbx.pluginBase.updatePillText(loop, {
      value: timeFormat(lastLoopMoment, sbx)
      , label: label
      , info: info
      , pillClass: statusClass(prop, prefs, sbx)
    });

    var forecastPoints = getForecastPoints();
    if (forecastPoints && forecastPoints.length > 0) {
      sbx.pluginBase.addForecastPoints(forecastPoints, {type: 'loop', label: 'Loop Forecasts'});
    }
  };

  function statusClass (prop, prefs, sbx) {
    var level = statusLevel(prop, prefs, sbx);
    var cls = 'current';

    if (level === levels.WARN) {
      cls = 'warn';
    } else if (level === levels.URGENT) {
      cls = 'urgent';
    }

    return cls;
  }

  function statusLevel (prop, prefs, sbx) {
    var level = levels.NONE;
    var now = moment(sbx.time);

    if (prop.lastOkMoment) {
      var urgentTime = prop.lastOkMoment.clone().add(prefs.urgent, 'minutes');
      var warningTime = prop.lastOkMoment.clone().add(prefs.warn, 'minutes');

      if (urgentTime.isBefore(now)) {
        level = levels.URGENT;
      } else if (warningTime.isBefore(now)) {
        level = levels.WARN;
      }
    }

    return level;
  }

  return loop;

}

function timeFormat (m, sbx) {

  var when;
  if (m && sbx.data.inRetroMode) {
    when = m.format('LT');
  } else if (m) {
    when = formatAgo(m, sbx.time);
  } else {
    when = 'unknown';
  }

  return when;
}

function formatAgo (m, nowMills) {
  var ago = timeago.calcDisplay({mills: m.valueOf()}, nowMills);
  return (ago.value ? ago.value : '') + ago.shortLabel + (ago.shortLabel.length === 1 ? ' ago' : '');
}

function timeAt (prefix, sbx) {
  return sbx.data.inRetroMode ? (prefix ? ' ' : '') + '@ ' : (prefix ? ', ' : '');
}

module.exports = init;
<commit_msg>Show last temp when subsequent loops have no recommendation/temp<commit_after>'use strict';

var _ = require('lodash');
var moment = require('moment');
var times = require('../times');
var levels = require('../levels');
var timeago = require('./timeago')();

// var ALL_STATUS_FIELDS = ['status-symbol', 'status-label', 'iob', 'freq', 'rssi']; Unused variable

function init() {

  var loop = {
    name: 'loop'
    , label: 'Loop'
    , pluginType: 'pill-status'
  };

  var firstPrefs = true;

  loop.getPrefs = function getPrefs(sbx) {

    var prefs = {
      warn: sbx.extendedSettings.warn ? sbx.extendedSettings.warn : 30
      , urgent: sbx.extendedSettings.urgent ? sbx.extendedSettings.urgent : 60
      , enableAlerts: sbx.extendedSettings.enableAlerts
    };

    if (firstPrefs) {
      firstPrefs = false;
      console.info(' Prefs:', prefs);
    }

    return prefs;
  };

  loop.setProperties = function setProperties (sbx) {
    sbx.offerProperty('loop', function setLoop ( ) {
      return loop.analyzeData(sbx);
    });
  };

  loop.analyzeData = function analyzeData (sbx) {
    var recentHours = 6;
    var recentMills = sbx.time - times.hours(recentHours).msecs;

    var recentData = _.chain(sbx.data.devicestatus)
      .filter(function (status) {
        return ('loop' in status) && sbx.entryMills(status) <= sbx.time && sbx.entryMills(status) >= recentMills;
      }).value( );

    var prefs = loop.getPrefs(sbx);
    var recent = moment(sbx.time).subtract(prefs.warn / 2, 'minutes');

    function getDisplayForStatus (status)  {

      var desc = {
        symbol: '⚠'
        , code: 'warning'
        , label: 'Warning'
      };

      if (!status) {
        return desc
      }

      if (status.failureReason || (status.enacted && !status.enacted.received)) {
        desc.symbol = 'x';
        desc.code = 'error';
        desc.label = 'Error';
      } else if (status.enacted && moment(status.timestamp).isAfter(recent)) {
        desc.symbol = '⌁';
        desc.code = 'enacted';
        desc.label = 'Enacted';
      } else if (status.recommendedTempBasal && moment(status.recommendedTempBasal.timestamp).isAfter(recent)) {
        desc.symbol = '⏀';
        desc.code = 'recommendation';
        desc.label = 'Recomendation';
      } else if (status.moment && status.moment.isAfter(recent)) {
        desc.symbol = '↻';
        desc.code = 'looping';
        desc.label = 'Looping';
      }
      return desc;
    }

    var result = {
      lastLoop: null
      , lastEnacted: null
      , lastOkMoment: null
    };

    _.forEach(recentData, function eachStatus (status) {
      if (status && status.loop && status.loop.timestamp) {
        var loop = status.loop
        loop.moment = moment(loop.timestamp);

        var enacted = loop.enacted;
        if (enacted && enacted.timestamp) {
          enacted.moment = moment(enacted.timestamp)
          if (!result.lastEnacted || enacted.moment.isAfter(result.lastEnacted.moment)) {
            result.lastEnacted = enacted;
          }
        }

        if (!result.lastLoop || loop.moment.isAfter(result.lastLoop.moment)) {
          result.lastLoop = loop
        }

        if (!loop.failureReason && (!result.lastOkMoment || loop.moment.isAfter(result.lastOkMoment))) {
          result.lastOkMoment = loop.moment
        }
      }

    });

    result.display = getDisplayForStatus(result.lastLoop);

    return result;
  };

  loop.checkNotifications = function checkNotifications(sbx) {
    var prefs = loop.getPrefs(sbx);

    if (!prefs.enableAlerts) { return; }

    var prop = sbx.properties.loop;

    if (!prop.lastLoop) {
      console.info('Loop hasn\'t reported a loop yet');
      return;
    }

    var now = moment();
    var level = statusLevel(prop, prefs, sbx);
    if (level >= levels.WARN) {
      sbx.notifications.requestNotify({
        level: level
        , title: 'Loop isn\'t looping'
        , message: 'Last Loop: ' + formatAgo(prop.lastLoop.moment, now.valueOf())
        , pushoverSound: 'echo'
        , group: 'Loop'
        , plugin: loop
        , debug: prop
      });
    }
  };

  loop.updateVisualisation = function updateVisualisation (sbx) {
    var prop = sbx.properties.loop;

    var prefs = loop.getPrefs(sbx);

    function valueString (prefix, value) {
      return (value != null) ? prefix + value : '';
    }

    var events = [ ];

    function addRecommendedTempBasal() {
      if (prop.lastLoop && prop.lastLoop.recommendedTempBasal) {

        var recommendedTempBasal = prop.lastLoop.recommendedTempBasal

        var valueParts = [
          'Suggested Temp: ' + recommendedTempBasal.rate + "U/hour for " +
          recommendedTempBasal.duration + "m"
        ];

        valueParts = concatIOB(valueParts);
        valueParts = concatCOB(valueParts);

        events.push({
          time: moment(recommendedTempBasal.timestamp)
          , value: valueParts.join('')
        });
      }
    }

    function addLastEnacted() {
      if (prop.lastEnacted) {
        var canceled = prop.lastEnacted.rate === 0 && prop.lastEnacted.duration === 0;

        var valueParts = [
          , 'Temp Basal' + (canceled ? ' Canceled' : ' Started') + ''
          , canceled ? '' : ' ' + prop.lastEnacted.rate.toFixed(2) + 'U/hour for ' + prop.lastEnacted.duration + 'm'
          , valueString(', ', prop.lastEnacted.reason)
        ];

        valueParts = concatIOB(valueParts);
        valueParts = concatCOB(valueParts);

        events.push({
          time: prop.lastEnacted.moment
          , value: valueParts.join('')
        });
      }
    }

    function concatIOB (valueParts) {
      if (prop.lastLoop && prop.lastLoop.iob) {
        var iob = prop.lastLoop.iob
        valueParts = valueParts.concat([
          ', IOB: '
          , sbx.roundInsulinForDisplayFormat(iob.iob) + 'U'
          , iob.basaliob ? ', Basal IOB ' + sbx.roundInsulinForDisplayFormat(iob.basaliob) + 'U' : ''
        ]);
      }

      return valueParts;
    }

    function concatCOB (valueParts) {
      if (prop.lastLoop && prop.lastLoop.cob) {
        cob = prop.lastLoop.cob
        valueParts = valueParts.concat([
          ', COB: '
          , cob.cob + 'g'
        ]);
      }

      return valueParts;
    }

    function getForecastPoints ( ) {
      var points = [ ];

      function toPoints (startTime, offset) {
        return  function toPoint (value, index) {
          return {
            mgdl: value
            , color: '#ff00ff'
            , mills: startTime.valueOf() + times.mins(5 * index).msecs + offset
            , noFade: true
          };
        };
      }

      if (prop.lastLoop && prop.lastLoop.predicted && prop.lastLoop.predicted.startDate) {
        var predicted = prop.lastLoop.predicted;
        var startTime = moment(predicted.startDate);
        if (predicted.values) {
          points = points.concat(_.map(predicted.values, toPoints(startTime, 0)));
        }
        // if (prop.lastPredBGs.IOB) {
        //   points = points.concat(_.map(prop.lastPredBGs.IOB, toPoints(moment, 3000)));
        // }
        // if (prop.lastPredBGs.COB) {
        //   points = points.concat(_.map(prop.lastPredBGs.COB, toPoints(moment, 7000)));
        // }
      }

      return points;
    }

    if ('error' === prop.display.code) {
      events.push({
        time: prop.lastLoop.moment
        , value: valueString('Error: ', prop.lastLoop.failureReason)
      });
      addRecommendedTempBasal();
    } else if ('enacted' === prop.display.code) {
      addLastEnacted()
    } else if ('looping' === prop.display.code) {
      addLastEnacted()
    } else {
      addRecommendedTempBasal();
    }

    var sorted = _.sortBy(events, function toMill(event) {
      return event.time.valueOf();
    }).reverse();

    var info = _.map(sorted, function eventToInfo (event) {
      return {
        label: timeAt(false, sbx) + timeFormat(event.time, sbx)
        , value: event.value
      };
    });

    var label = 'Loop ' + prop.display.symbol;

    var lastLoopMoment = prop.lastLoop ? prop.lastLoop.moment : null;

    sbx.pluginBase.updatePillText(loop, {
      value: timeFormat(lastLoopMoment, sbx)
      , label: label
      , info: info
      , pillClass: statusClass(prop, prefs, sbx)
    });

    var forecastPoints = getForecastPoints();
    if (forecastPoints && forecastPoints.length > 0) {
      sbx.pluginBase.addForecastPoints(forecastPoints, {type: 'loop', label: 'Loop Forecasts'});
    }
  };

  function statusClass (prop, prefs, sbx) {
    var level = statusLevel(prop, prefs, sbx);
    var cls = 'current';

    if (level === levels.WARN) {
      cls = 'warn';
    } else if (level === levels.URGENT) {
      cls = 'urgent';
    }

    return cls;
  }

  function statusLevel (prop, prefs, sbx) {
    var level = levels.NONE;
    var now = moment(sbx.time);

    if (prop.lastOkMoment) {
      var urgentTime = prop.lastOkMoment.clone().add(prefs.urgent, 'minutes');
      var warningTime = prop.lastOkMoment.clone().add(prefs.warn, 'minutes');

      if (urgentTime.isBefore(now)) {
        level = levels.URGENT;
      } else if (warningTime.isBefore(now)) {
        level = levels.WARN;
      }
    }

    return level;
  }

  return loop;

}

function timeFormat (m, sbx) {

  var when;
  if (m && sbx.data.inRetroMode) {
    when = m.format('LT');
  } else if (m) {
    when = formatAgo(m, sbx.time);
  } else {
    when = 'unknown';
  }

  return when;
}

function formatAgo (m, nowMills) {
  var ago = timeago.calcDisplay({mills: m.valueOf()}, nowMills);
  return (ago.value ? ago.value : '') + ago.shortLabel + (ago.shortLabel.length === 1 ? ' ago' : '');
}

function timeAt (prefix, sbx) {
  return sbx.data.inRetroMode ? (prefix ? ' ' : '') + '@ ' : (prefix ? ', ' : '');
}

module.exports = init;
<|endoftext|>