<commit_before>/*
Name:         cloudsight
Description:  Node.js module to access CloudSight API methods
Author:       Franklin van de Meent (https://frankl.in)
Source code:  https://github.con/fvdm/nodejs-cloudsight
Feedback:     https://github.con/fvdm/nodejs-cloudsight/issues
License:      Unlicense (Public Domain, see LICENSE file)
*/

var httpreq = require ('httpreq');

var config = {
  apikey: null,
  endpoint: null,
  timeout: null
};

/**
 * GUID generator
 *
 * @param parts {number=8} - Number of parts to generate
 * @param prefix {string=-} - Prefix parts with string
 * @returns {string}
 */

function guidGenerator () {
  function S4 (parts, prefix) {
    var str = '';
    var i;

    parts = parts || 8;
    prefix = prefix || '-';

    for (i = parts || 1; i > 0; i--) {
      str += prefix;
      str += parseInt (((Math.random () + 1) * 0x10000), 10)
        .toString (16)
        .substring (1);
    }

    return str;
  }

  return (S4 (2) + S4 (4, '-') + S4 (2));
}

/**
 * Communication
 *
 * @param {object} props
 * @param {string} [props.method=GET] - GET or POST
 * @param {string) props.path - i.e. /image_requests/token
 * @param {object} [props.data] - Data fields to send
 * @param {string} [props.endpoint=config.endpoint] - API endpoint override
 * @param {number} [props.timeout=config.timeout] - Request timeout override
 * @param {function} callback - Process response
 * @returns {void}
 */

function talk (props, callback) {
  var options = {
    url: config.endpoint + props.path,
    method: props.method || 'GET',
    parameters: props.data || null,
    files: props.files || null,
    timeout: props.timeout || config.timeout,
    encodePostParameters: false,
    headers: {
      'Accept': 'application/json',
      'Authorization': 'CloudSight ' + config.apikey,
      'User-Agent': 'cloudsight node/' + process.versions.node + ' (https://github.com/fvdm/nodejs-cloudsight)'
    }
  };

  httpreq.doRequest (options, function (err, res) {
    var data = res && res.body || '';
    var code = res && res.statusCode || null;
    var error = null;

    // request error
    if (err) {
      error = new Error ('request failed');
      error.statusCode = code;
      error.error = err;
      callback (error);
      return;
    }

    // parse body
    try {
      data = JSON.parse (data);
    } catch (e) {
      error = e;
      error.statusCode = code;
      error.body = data;
      callback (error);
      return;
    }

    // API error
    if (data.error) {
      error = new Error ('API error');
      error.statusCode = code;
      error.error = data.error;
      callback (error);
      return;
    }

    // all good
    callback (null, data);
  });
}

/**
 * Get result data for image
 *
 * @param {string} token - Image token
 * @param {function} callback
 * @returns {void}
 */

function imageResponses (token, callback) {
  var options = {
    method: 'GET',
    path: '/image_responses/' + token
  };

  talk (options, callback);
}

/**
 * Check status at preferred interval
 *
 * @param {string} token - Image token
 * @param {function} callback
 * @returns {void}
 */

function pollStatus (token, callback) {
  imageResponses (token, function (err, data) {
    if (err) {
      err.token = token;
      callback (err);
      return;
    }

    if (data.status === 'not completed') {
      setTimeout (function () {
        pollStatus (token, callback);
      }, 1000);
    } else {
      callback (null, data);
    }
  });
}

/**
 * Send an image for processing
 *
 * @param {object} props - See README.md
 * @param {boolean} [polling=false] - Callback only when results are ready
 * @param {function} callback - Callback response
 * @returns {void}
 */

function imageRequests (props, polling, callback) {
  var options = {
    method: 'POST',
    path: '/image_requests',
    files: {},
    data: {}
  };

  var keys;
  var i;

  // default values
  props.locale = props.locale || 'en-US';
  props.language = props.language || 'en';
  props.device_id = props.device_id || guidGenerator ();

  // image is a file, overrides URL
  if (props.image) {
    options.files ['image_request[image]'] = props.image;
    delete props.image;
    delete props.remote_image_url;
  }

  // wrap fieldnames
  if (props.focus_x) {
    options.data ['focus[x]'] = props.focus_x;
    delete props.focus_x;
  }

  if (props.focus_y) {
    options.data ['focus[y]'] = props.focus_y;
    delete props.focus_y;
  }

  keys = Object.keys (props);

  for (i = 0; i < keys.length; i++) {
    options.data ['image_request[' + keys [i] + ']'] = props [keys [i]];
  }

  // send it
  talk (options, function (err, data) {
    if (err) {
      callback (err);
      return;
    }

    if (polling && data.token) {
      setTimeout (function () {
        pollStatus (data.token, callback);
      }, 4000);

      return;
    }

    callback (null, data);
  });
}

/**
 * Module config and defaults
 *
 * @param {object} conf
 * @param {string} conf.apikey - Account API key
 * @param {string} [conf.endpoint] - Override API endpoint
 * @param {number} [conf.timeout=5000] - Override request timeout
 * @returns {object} - Module methods
 */

module.exports = function (conf) {
  config.apikey = conf.apikey || null;
  config.endpoint = conf.endpoint || 'https://api.cloudsightapi.com';
  config.timeout = conf.timeout || 5000;

  return {
    request: imageRequests,
    response: imageResponses
  };
};
<commit_msg>Fixed guidGenerator()<commit_after>/*
Name:         cloudsight
Description:  Node.js module to access CloudSight API methods
Author:       Franklin van de Meent (https://frankl.in)
Source code:  https://github.con/fvdm/nodejs-cloudsight
Feedback:     https://github.con/fvdm/nodejs-cloudsight/issues
License:      Unlicense (Public Domain, see LICENSE file)
*/

var httpreq = require ('httpreq');

var config = {
  apikey: null,
  endpoint: null,
  timeout: null
};

/**
 * GUID generator
 *
 * @param parts {number=8} - Number of parts to generate
 * @param prefix {string=-} - Prefix parts with string
 * @returns {string}
 */

function guidGenerator () {
  function s4 () {
    return Math.floor ((1 + Math.random ()) * 0x10000)
      .toString (16)
      .substring (1);
  }

  return s4 () + s4 () + '-' + s4 () + '-' + s4 () + '-' + s4 () + '-' + s4 () + s4 () + s4 ();
}

/**
 * Communication
 *
 * @param {object} props
 * @param {string} [props.method=GET] - GET or POST
 * @param {string) props.path - i.e. /image_requests/token
 * @param {object} [props.data] - Data fields to send
 * @param {string} [props.endpoint=config.endpoint] - API endpoint override
 * @param {number} [props.timeout=config.timeout] - Request timeout override
 * @param {function} callback - Process response
 * @returns {void}
 */

function talk (props, callback) {
  var options = {
    url: config.endpoint + props.path,
    method: props.method || 'GET',
    parameters: props.data || null,
    files: props.files || null,
    timeout: props.timeout || config.timeout,
    encodePostParameters: false,
    headers: {
      'Accept': 'application/json',
      'Authorization': 'CloudSight ' + config.apikey,
      'User-Agent': 'cloudsight node/' + process.versions.node + ' (https://github.com/fvdm/nodejs-cloudsight)'
    }
  };

  httpreq.doRequest (options, function (err, res) {
    var data = res && res.body || '';
    var code = res && res.statusCode || null;
    var error = null;

    // request error
    if (err) {
      error = new Error ('request failed');
      error.statusCode = code;
      error.error = err;
      callback (error);
      return;
    }

    // parse body
    try {
      data = JSON.parse (data);
    } catch (e) {
      error = e;
      error.statusCode = code;
      error.body = data;
      callback (error);
      return;
    }

    // API error
    if (data.error) {
      error = new Error ('API error');
      error.statusCode = code;
      error.error = data.error;
      callback (error);
      return;
    }

    // all good
    callback (null, data);
  });
}

/**
 * Get result data for image
 *
 * @param {string} token - Image token
 * @param {function} callback
 * @returns {void}
 */

function imageResponses (token, callback) {
  var options = {
    method: 'GET',
    path: '/image_responses/' + token
  };

  talk (options, callback);
}

/**
 * Check status at preferred interval
 *
 * @param {string} token - Image token
 * @param {function} callback
 * @returns {void}
 */

function pollStatus (token, callback) {
  imageResponses (token, function (err, data) {
    if (err) {
      err.token = token;
      callback (err);
      return;
    }

    if (data.status === 'not completed') {
      setTimeout (function () {
        pollStatus (token, callback);
      }, 1000);
    } else {
      callback (null, data);
    }
  });
}

/**
 * Send an image for processing
 *
 * @param {object} props - See README.md
 * @param {boolean} [polling=false] - Callback only when results are ready
 * @param {function} callback - Callback response
 * @returns {void}
 */

function imageRequests (props, polling, callback) {
  var options = {
    method: 'POST',
    path: '/image_requests',
    files: {},
    data: {}
  };

  var keys;
  var i;

  // default values
  props.locale = props.locale || 'en-US';
  props.language = props.language || 'en';
  props.device_id = props.device_id || guidGenerator ();

  // image is a file, overrides URL
  if (props.image) {
    options.files ['image_request[image]'] = props.image;
    delete props.image;
    delete props.remote_image_url;
  }

  // wrap fieldnames
  if (props.focus_x) {
    options.data ['focus[x]'] = props.focus_x;
    delete props.focus_x;
  }

  if (props.focus_y) {
    options.data ['focus[y]'] = props.focus_y;
    delete props.focus_y;
  }

  keys = Object.keys (props);

  for (i = 0; i < keys.length; i++) {
    options.data ['image_request[' + keys [i] + ']'] = props [keys [i]];
  }

  // send it
  talk (options, function (err, data) {
    if (err) {
      callback (err);
      return;
    }

    if (polling && data.token) {
      setTimeout (function () {
        pollStatus (data.token, callback);
      }, 4000);

      return;
    }

    callback (null, data);
  });
}

/**
 * Module config and defaults
 *
 * @param {object} conf
 * @param {string} conf.apikey - Account API key
 * @param {string} [conf.endpoint] - Override API endpoint
 * @param {number} [conf.timeout=5000] - Override request timeout
 * @returns {object} - Module methods
 */

module.exports = function (conf) {
  config.apikey = conf.apikey || null;
  config.endpoint = conf.endpoint || 'https://api.cloudsightapi.com';
  config.timeout = conf.timeout || 5000;

  return {
    request: imageRequests,
    response: imageResponses
  };
};
<|endoftext|>


<commit_before>"use strict";
(function() {
  var $, CheckBoxOption, ExclusionRulesOption, NonEmptyTextOption, NumberOption, Option, TextOption,
    activateHelpDialog, bgSettings, bgExclusions, enableSaveButton, maintainLinkHintsView,
    ExclusionRulesOnPopupOption, initOptionsPage, initPopupPage, BG,
    __hasProp = Object.prototype.hasOwnProperty,
    __extends = function(child, parent) {
      for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
      function ctor() { this.constructor = child; } ctor.prototype = parent.prototype;
      child.prototype = new ctor(); child.__super__ = parent.prototype;
      return child;
    };

  $ = document.getElementById.bind(document);
  BG = chrome.extension.getBackgroundPage();
  bgSettings = BG.Settings;
  bgExclusions = BG.Exclusions;

  function Option(field, onUpdated) {
    this.field = field;
    this.onUpdated = onUpdated;
    this.element = $(this.field);
    this.element.addEventListener("change", this.onUpdated);
    this.fetch();
    Option.all.push(this);
  }

  Option.all = [];

  Option.prototype.fetch = function() {
    this.populateElement(this.previous = bgSettings.get(this.field));
    return this.previous;
  };

  Option.prototype.save = function() {
    var value = this.readValueFromElement();
    if (!this.areEqual(value, this.previous)) {
      bgSettings.set(this.field, this.previous = value);
    }
  };

  Option.prototype.areEqual = function(a, b) {
    return a === b;
  };

  Option.prototype.restoreToDefault = function() {
    bgSettings.clear(this.field);
    return this.fetch();
  };

  Option.saveOptions = function() {
    Option.all.forEach(function(option) {
      option.save();
    });
  };

  NumberOption = (function(_super) {
    __extends(NumberOption, _super);

    function NumberOption() {
      return NumberOption.__super__.constructor.apply(this, arguments);
    }

    NumberOption.prototype.populateElement = function(value) {
      return this.element.value = value;
    };

    NumberOption.prototype.readValueFromElement = function() {
      return parseFloat(this.element.value);
    };

    return NumberOption;

  })(Option);

  TextOption = (function(_super) {
    __extends(TextOption, _super);

    function TextOption() {
      TextOption.__super__.constructor.apply(this, arguments);
      this.element.addEventListener("input", this.onUpdated);
    }

    TextOption.prototype.populateElement = function(value) {
      return this.element.value = value.replace(/\n /g, '\n\xa0');
    };

    TextOption.prototype.readValueFromElement = function() {
      return this.element.value.trim().replace(/\xa0/g, ' ');
    };

    return TextOption;

  })(Option);

  NonEmptyTextOption = (function(_super) {
    __extends(NonEmptyTextOption, _super);

    function NonEmptyTextOption(field, enableSaveButton) {
      NonEmptyTextOption.__super__.constructor.apply(this, arguments);
      this.element.addEventListener("input", this.onUpdated);
    }

    NonEmptyTextOption.prototype.populateElement = function(value) {
      return this.element.value = value.replace(/\n /g, '\n\xa0');
    };

    NonEmptyTextOption.prototype.readValueFromElement = function() {
      var value = this.element.value.trim().replace(/\xa0/g, ' ');
      if (value) {
        return value;
      } else {
        return this.restoreToDefault();
      }
    };

    return NonEmptyTextOption;

  })(Option);

  CheckBoxOption = (function(_super) {
    __extends(CheckBoxOption, _super);

    function CheckBoxOption() {
      return CheckBoxOption.__super__.constructor.apply(this, arguments);
    }

    CheckBoxOption.prototype.populateElement = function(value) {
      return this.element.checked = value;
    };

    CheckBoxOption.prototype.readValueFromElement = function() {
      return this.element.checked;
    };

    return CheckBoxOption;

  })(Option);

  ExclusionRulesOption = (function(_super) {
    __extends(ExclusionRulesOption, _super);

    function ExclusionRulesOption() {
      this.onRemoveRow = this.onRemoveRow.bind(this);
      ExclusionRulesOption.__super__.constructor.apply(this, arguments);
      $("exclusionAddButton").addEventListener("click", this.addRule.bind(this, null));
    }

    ExclusionRulesOption.prototype.addRule = function(pattern) {
      var element, exclusionScrollBox;
      if (pattern == null) {
        pattern = "";
      }
      element = this.appendRule({
        pattern: pattern,
        passKeys: ""
      });
      this.getPattern(element).focus();
      exclusionScrollBox = $("exclusionScrollBox");
      exclusionScrollBox.scrollTop = exclusionScrollBox.scrollHeight;
      this.onUpdated();
      return element;
    };

    ExclusionRulesOption.prototype.populateElement = function(rules) {
      rules.forEach(this.appendRule.bind(this));
    };

    ExclusionRulesOption.prototype.appendRule = function(rule) {
      var element, field, row, _i, _j, _ref, _ref1;
      row = document.importNode($('exclusionRuleTemplate').content, true);
      _ref = ["pattern", "passKeys"];
      _ref1 = ["input", "change"];
      for (_i = _ref.length; 0 <= --_i; ) {
        field = _ref[_i];
        element = row.querySelector('.' + field);
        element.value = rule[field];
        for (_j = _ref1.length; 0 <= --_j; ) {
          element.addEventListener(_ref1[_j], this.onUpdated);
        }
      }
      this.getRemoveButton(row).addEventListener("click", this.onRemoveRow);
      this.element.appendChild(row);
      return this.element.children[this.element.children.length - 1];
    };

    ExclusionRulesOption.prototype.onRemoveRow = function(event) {
      var row1 = event.target.parentNode.parentNode;
      row1.parentNode.removeChild(row1);
      this.onUpdated();
    };

    ExclusionRulesOption.prototype.readValueFromElement = function() {
      var element, passKeys, pattern, rules, _i, _len, _ref, wchRegex;
      rules = [];
      wchRegex = /\s+/;
      _ref = this.element.getElementsByClassName("exclusionRuleInstance");
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        element = _ref[_i];
        pattern = this.getPattern(element).value.replace(wchRegex, "");
        if (!pattern) {
          continue;
        }
        passKeys = this.getPassKeys(element).value.replace(wchRegex, "");
        rules.push({
          pattern: pattern,
          passKeys: passKeys
        });
      }
      if (JSON.stringify(rules) === JSON.stringify(bgSettings.defaults.exclusionRules)) {
        rules = bgSettings.defaults.exclusionRules;
      }
      return rules;
    };

    ExclusionRulesOption.prototype.flatten = function(rule) {
      return (rule && rule.pattern) ? (rule.pattern + "\r" + rule.passKeys) : "";
    };

    ExclusionRulesOption.prototype.areEqual = function(a, b) {
      return a.map(this.flatten).join("\n") === b.map(this.flatten).join("\n");
    };

    ExclusionRulesOption.prototype.getPattern = function(element) {
      return element.querySelector(".pattern");
    };

    ExclusionRulesOption.prototype.getPassKeys = function(element) {
      return element.querySelector(".passKeys");
    };

    ExclusionRulesOption.prototype.getRemoveButton = function(element) {
      return element.querySelector(".exclusionRemoveButton");
    };

    return ExclusionRulesOption;

  })(Option);

  ExclusionRulesOnPopupOption = (function(_super) {
    __extends(ExclusionRulesOnPopupOption, _super);

    function ExclusionRulesOnPopupOption(url) {
      this.url = url;
      this.onKeyup = this.onKeyup.bind(this);
      ExclusionRulesOnPopupOption.__super__.constructor.apply(this,
        2 <= arguments.length ? Array.prototype.slice.call(arguments, 1) : []);
    }

    ExclusionRulesOnPopupOption.prototype.addRule = function() {
      var element = ExclusionRulesOnPopupOption.__super__.addRule.call(this,
        this.generateDefaultPattern());
      this.activatePatternWatcher(element);
      this.getPassKeys(element).focus();
      return element;
    };

    ExclusionRulesOnPopupOption.prototype.populateElement = function(rules) {
      var element, elements, haveMatch, pattern, _i, _j, _len, _len1;
      ExclusionRulesOnPopupOption.__super__.populateElement.call(this, rules);
      elements = this.element.getElementsByClassName("exclusionRuleInstance");
      for (_i = 0, _len = elements.length; _i < _len; _i++) {
        this.activatePatternWatcher(elements[_i]);
      }
      haveMatch = false;
      for (_j = 0, _len1 = elements.length; _j < _len1; _j++) {
        element = elements[_j];
        pattern = this.getPattern(element).value.trim();
        if (0 <= this.url.search(bgExclusions.getRegex(pattern))) {
          haveMatch = true;
          this.getPassKeys(element).focus();
        } else {
          element.style.display = 'none';
        }
      }
      if (!haveMatch) {
        this.addRule();
      }
    };

    ExclusionRulesOnPopupOption.prototype.activatePatternWatcher = function(element) {
      this.getPattern(element).addEventListener("keyup", this.onKeyup);
    };

    ExclusionRulesOnPopupOption.prototype.onKeyup = function(event) {
      var patternElement = event.target;
      if (this.url.match(bgExclusions.getRegex(patternElement.value))) {
        patternElement.title = patternElement.style.color = "";
      } else {
        patternElement.style.color = "red";
        patternElement.title = "Red text means that the pattern does not\nmatch the current URL.";
      }
    }

    ExclusionRulesOnPopupOption.prototype.httpRegex = /^https?:\/\/./;
    ExclusionRulesOnPopupOption.prototype.urlRegex = /^[a-z]{3,}:\/\/./;
    ExclusionRulesOnPopupOption.prototype.generateDefaultPattern = function() {
      return this.httpRegex.test(this.url)
        ? ("https?://" + this.url.split("/", 3)[2] + "/*")
        : this.urlRegex.test(this.url)
        ? (this.url.split("/", 3).join("/") + "/*")
        : (this.url + "*");
    };

    return ExclusionRulesOnPopupOption;

  })(ExclusionRulesOption);

  initOptionsPage = function() {
    var activateHelpDialog, element, maintainLinkHintsView, name, onUpdated //
      , options, saveOptions, toggleAdvancedOptions, type, _i, _ref;

    onUpdated = function() {
      var saveBtn = $("saveOptions");
      saveBtn.removeAttribute("disabled");
      saveBtn.innerHTML = "Save Changes";
    };

    maintainLinkHintsView = function() {
      var hide, show;
      hide = function(el) {
        el.parentNode.parentNode.style.display = "none";
      };
      show = function(el) {
        el.parentNode.parentNode.style.display = "table-row";
      };
      if ($("filterLinkHints").checked) {
        hide($("linkHintCharacters"));
        show($("linkHintNumbers"));
      } else {
        show($("linkHintCharacters"));
        hide($("linkHintNumbers"));
      }
    };

    var _advancedMode = !bgSettings.get("showAdvancedOptions");
    toggleAdvancedOptions = function(event) {
      if (_advancedMode) {
        $("advancedOptions").style.display = "none";
        $("advancedOptionsLink").innerHTML = "Show advanced options…";
      } else {
        $("advancedOptions").style.display = "table-row-group";
        $("advancedOptionsLink").innerHTML = "Hide advanced options";
      }
      _advancedMode = !_advancedMode;
      bgSettings.set("showAdvancedOptions", _advancedMode);
      event.preventDefault();
      document.activeElement.blur();
    };

    activateHelpDialog = function() {
      showHelpDialog({
        html: BG.helpDialogHtml(true, true, "Command Listing"),
        advanced: bgSettings.get("showAdvancedCommands")
      });
      document.activeElement.blur();
    };

    saveOptions = function() {
      var btn = $("saveOptions");
      if (btn.disabled) {
        return;
      }
      Option.saveOptions();
      btn.disabled = true;
      btn.innerHTML = "No Changes";
      setTimeout(function () {
        window.onfocus();
        bgSettings.buildBuffer();
        BG.sendRequestToAllTabs({
          name: "settings",
          frameId: 0,
          load: bgSettings.bufferToLoad
        });
      }, 100);
    };

    $("saveOptions").addEventListener("click", saveOptions);
    $("advancedOptionsLink").addEventListener("click", toggleAdvancedOptions);
    toggleAdvancedOptions({preventDefault: function() {}});
    $("showCommands").addEventListener("click", activateHelpDialog);
    $("filterLinkHints").addEventListener("click", maintainLinkHintsView);
    _ref = document.getElementsByClassName("nonEmptyTextOption");
    for (_i = _ref.length; 0 <= --_i; ) {
      element = _ref[_i];
      element.className = element.className + " example info";
      element.innerHTML = "Leave empty to reset this option.";
    }
    maintainLinkHintsView();
    window.onbeforeunload = function() {
      if (!$("saveOptions").disabled) {
        return "You have unsaved changes to options.";
      }
    };
    document.addEventListener("keyup", function(event) {
      if (event.ctrlKey && event.keyCode === 13) {
        if (document.activeElement && document.activeElement.blur) {
          document.activeElement.blur();
        }
        saveOptions();
      }
    });

    options = {
      exclusionRules: ExclusionRulesOption,
      filterLinkHints: CheckBoxOption,
      hideHud: CheckBoxOption,
      vomnibarInMain: CheckBoxOption,
      keyMappings: TextOption,
      linkHintCharacters: NonEmptyTextOption,
      linkHintNumbers: NonEmptyTextOption,
      newTabUrl: NonEmptyTextOption,
      nextPatterns: NonEmptyTextOption,
      previousPatterns: NonEmptyTextOption,
      regexFindMode: CheckBoxOption,
      scrollStepSize: NumberOption,
      smoothScroll: CheckBoxOption,
      searchEngines: TextOption,
      searchUrl: NonEmptyTextOption,
      userDefinedCss: TextOption
    };
    for (name in options) {
      type = options[name];
      new type(name, onUpdated);
    }
  };

  initPopupPage = function(tab) {
    var exclusions, onUpdated, saveOptions, updateState, url;
    exclusions = null;
    url = BG.urlForTab[tab.id] || tab.url;
    updateState = function() {
      var rule = bgExclusions.getRule(url, exclusions.readValueFromElement());
      $("state").innerHTML = "Vimium will " + (rule && rule.passKeys
        ? "exclude " + rule.passKeys + ""
        : rule ? "be disabled" : "be enabled");
    };
    onUpdated = function() {
      var btn = $("saveOptions");
      $("helpText").innerHTML = "Type Ctrl-Enter to save and close.";
      btn.removeAttribute("disabled");
      btn.innerHTML = "Save Changes";
      if (exclusions) {
        updateState();
      }
    };
    saveOptions = function() {
      var btn = $("saveOptions");
      if (btn.disabled) {
        return;
      }
      Option.saveOptions();
      btn.innerHTML = "Saved";
      btn.disabled = true;
      var rule = bgExclusions.getRule(url);
      BG.g_requestHandlers.setIcon(tab.id //
        , rule ? (rule.passKeys ? "partial" : "disabled") : "enabled");
    };
    $("saveOptions").addEventListener("click", saveOptions);
    document.addEventListener("keyup", function(event) {
      if (event.ctrlKey && event.keyCode === 13) {
        saveOptions();
        // although the tab calls window.onfocus after it closes,
        // it is too early for the tab to know new exclusion rules.
        setTimeout(window.close, 300);
      }
    });
    exclusions = new ExclusionRulesOnPopupOption(url, "exclusionRules", onUpdated);
    updateState();
    document.addEventListener("keyup", updateState);
  };

  document.addEventListener("DOMContentLoaded", function() {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "/pages/exclusions.html", true);
    xhr.onreadystatechange = function() {
      if (xhr.readyState === 4) {
        $("exclusionScrollBox").innerHTML = xhr.responseText;
        if (window.location.pathname.endsWith("popup.html")) {
          chrome.tabs.getSelected(null, initPopupPage);
        } else if (location.pathname.endsWith("options.html") >= 0) {
          initOptionsPage();
        }
      }
    };
    xhr.send();
  });

})();
<commit_msg>use [this.field] when accessing to Settings.defaults<commit_after>"use strict";
(function() {
  var $, CheckBoxOption, ExclusionRulesOption, NonEmptyTextOption, NumberOption, Option, TextOption,
    activateHelpDialog, bgSettings, bgExclusions, enableSaveButton, maintainLinkHintsView,
    ExclusionRulesOnPopupOption, initOptionsPage, initPopupPage, BG,
    __hasProp = Object.prototype.hasOwnProperty,
    __extends = function(child, parent) {
      for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
      function ctor() { this.constructor = child; } ctor.prototype = parent.prototype;
      child.prototype = new ctor(); child.__super__ = parent.prototype;
      return child;
    };

  $ = document.getElementById.bind(document);
  BG = chrome.extension.getBackgroundPage();
  bgSettings = BG.Settings;
  bgExclusions = BG.Exclusions;

  function Option(field, onUpdated) {
    this.field = field;
    this.onUpdated = onUpdated;
    this.element = $(this.field);
    this.element.addEventListener("change", this.onUpdated);
    this.fetch();
    Option.all.push(this);
  }

  Option.all = [];

  Option.prototype.fetch = function() {
    this.populateElement(this.previous = bgSettings.get(this.field));
    return this.previous;
  };

  Option.prototype.save = function() {
    var value = this.readValueFromElement();
    if (!this.areEqual(value, this.previous)) {
      bgSettings.set(this.field, this.previous = value);
    }
  };

  Option.prototype.areEqual = function(a, b) {
    return a === b;
  };

  Option.prototype.restoreToDefault = function() {
    bgSettings.clear(this.field);
    return this.fetch();
  };

  Option.saveOptions = function() {
    Option.all.forEach(function(option) {
      option.save();
    });
  };

  NumberOption = (function(_super) {
    __extends(NumberOption, _super);

    function NumberOption() {
      return NumberOption.__super__.constructor.apply(this, arguments);
    }

    NumberOption.prototype.populateElement = function(value) {
      return this.element.value = value;
    };

    NumberOption.prototype.readValueFromElement = function() {
      return parseFloat(this.element.value);
    };

    return NumberOption;

  })(Option);

  TextOption = (function(_super) {
    __extends(TextOption, _super);

    function TextOption() {
      TextOption.__super__.constructor.apply(this, arguments);
      this.element.addEventListener("input", this.onUpdated);
    }

    TextOption.prototype.populateElement = function(value) {
      return this.element.value = value.replace(/\n /g, '\n\xa0');
    };

    TextOption.prototype.readValueFromElement = function() {
      return this.element.value.trim().replace(/\xa0/g, ' ');
    };

    return TextOption;

  })(Option);

  NonEmptyTextOption = (function(_super) {
    __extends(NonEmptyTextOption, _super);

    function NonEmptyTextOption(field, enableSaveButton) {
      NonEmptyTextOption.__super__.constructor.apply(this, arguments);
      this.element.addEventListener("input", this.onUpdated);
    }

    NonEmptyTextOption.prototype.populateElement = function(value) {
      return this.element.value = value.replace(/\n /g, '\n\xa0');
    };

    NonEmptyTextOption.prototype.readValueFromElement = function() {
      var value = this.element.value.trim().replace(/\xa0/g, ' ');
      if (value) {
        return value;
      } else {
        return this.restoreToDefault();
      }
    };

    return NonEmptyTextOption;

  })(Option);

  CheckBoxOption = (function(_super) {
    __extends(CheckBoxOption, _super);

    function CheckBoxOption() {
      return CheckBoxOption.__super__.constructor.apply(this, arguments);
    }

    CheckBoxOption.prototype.populateElement = function(value) {
      return this.element.checked = value;
    };

    CheckBoxOption.prototype.readValueFromElement = function() {
      return this.element.checked;
    };

    return CheckBoxOption;

  })(Option);

  ExclusionRulesOption = (function(_super) {
    __extends(ExclusionRulesOption, _super);

    function ExclusionRulesOption() {
      this.onRemoveRow = this.onRemoveRow.bind(this);
      ExclusionRulesOption.__super__.constructor.apply(this, arguments);
      $("exclusionAddButton").addEventListener("click", this.addRule.bind(this, null));
    }

    ExclusionRulesOption.prototype.addRule = function(pattern) {
      var element, exclusionScrollBox;
      if (pattern == null) {
        pattern = "";
      }
      element = this.appendRule({
        pattern: pattern,
        passKeys: ""
      });
      this.getPattern(element).focus();
      exclusionScrollBox = $("exclusionScrollBox");
      exclusionScrollBox.scrollTop = exclusionScrollBox.scrollHeight;
      this.onUpdated();
      return element;
    };

    ExclusionRulesOption.prototype.populateElement = function(rules) {
      rules.forEach(this.appendRule.bind(this));
    };

    ExclusionRulesOption.prototype.appendRule = function(rule) {
      var element, field, row, _i, _j, _ref, _ref1;
      row = document.importNode($('exclusionRuleTemplate').content, true);
      _ref = ["pattern", "passKeys"];
      _ref1 = ["input", "change"];
      for (_i = _ref.length; 0 <= --_i; ) {
        field = _ref[_i];
        element = row.querySelector('.' + field);
        element.value = rule[field];
        for (_j = _ref1.length; 0 <= --_j; ) {
          element.addEventListener(_ref1[_j], this.onUpdated);
        }
      }
      this.getRemoveButton(row).addEventListener("click", this.onRemoveRow);
      this.element.appendChild(row);
      return this.element.children[this.element.children.length - 1];
    };

    ExclusionRulesOption.prototype.onRemoveRow = function(event) {
      var row1 = event.target.parentNode.parentNode;
      row1.parentNode.removeChild(row1);
      this.onUpdated();
    };

    ExclusionRulesOption.prototype.readValueFromElement = function() {
      var element, passKeys, pattern, rules, _i, _len, _ref, wchRegex;
      rules = [];
      wchRegex = /\s+/;
      _ref = this.element.getElementsByClassName("exclusionRuleInstance");
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        element = _ref[_i];
        pattern = this.getPattern(element).value.replace(wchRegex, "");
        if (!pattern) {
          continue;
        }
        passKeys = this.getPassKeys(element).value.replace(wchRegex, "");
        rules.push({
          pattern: pattern,
          passKeys: passKeys
        });
      }
      if (JSON.stringify(rules) === JSON.stringify(bgSettings.defaults[this.field])) {
        rules = bgSettings.defaults[this.field];
      }
      return rules;
    };

    ExclusionRulesOption.prototype.flatten = function(rule) {
      return (rule && rule.pattern) ? (rule.pattern + "\r" + rule.passKeys) : "";
    };

    ExclusionRulesOption.prototype.areEqual = function(a, b) {
      return a.map(this.flatten).join("\n") === b.map(this.flatten).join("\n");
    };

    ExclusionRulesOption.prototype.getPattern = function(element) {
      return element.querySelector(".pattern");
    };

    ExclusionRulesOption.prototype.getPassKeys = function(element) {
      return element.querySelector(".passKeys");
    };

    ExclusionRulesOption.prototype.getRemoveButton = function(element) {
      return element.querySelector(".exclusionRemoveButton");
    };

    return ExclusionRulesOption;

  })(Option);

  ExclusionRulesOnPopupOption = (function(_super) {
    __extends(ExclusionRulesOnPopupOption, _super);

    function ExclusionRulesOnPopupOption(url) {
      this.url = url;
      this.onKeyup = this.onKeyup.bind(this);
      ExclusionRulesOnPopupOption.__super__.constructor.apply(this,
        2 <= arguments.length ? Array.prototype.slice.call(arguments, 1) : []);
    }

    ExclusionRulesOnPopupOption.prototype.addRule = function() {
      var element = ExclusionRulesOnPopupOption.__super__.addRule.call(this,
        this.generateDefaultPattern());
      this.activatePatternWatcher(element);
      this.getPassKeys(element).focus();
      return element;
    };

    ExclusionRulesOnPopupOption.prototype.populateElement = function(rules) {
      var element, elements, haveMatch, pattern, _i, _j, _len, _len1;
      ExclusionRulesOnPopupOption.__super__.populateElement.call(this, rules);
      elements = this.element.getElementsByClassName("exclusionRuleInstance");
      for (_i = 0, _len = elements.length; _i < _len; _i++) {
        this.activatePatternWatcher(elements[_i]);
      }
      haveMatch = false;
      for (_j = 0, _len1 = elements.length; _j < _len1; _j++) {
        element = elements[_j];
        pattern = this.getPattern(element).value.trim();
        if (0 <= this.url.search(bgExclusions.getRegex(pattern))) {
          haveMatch = true;
          this.getPassKeys(element).focus();
        } else {
          element.style.display = 'none';
        }
      }
      if (!haveMatch) {
        this.addRule();
      }
    };

    ExclusionRulesOnPopupOption.prototype.activatePatternWatcher = function(element) {
      this.getPattern(element).addEventListener("keyup", this.onKeyup);
    };

    ExclusionRulesOnPopupOption.prototype.onKeyup = function(event) {
      var patternElement = event.target;
      if (this.url.match(bgExclusions.getRegex(patternElement.value))) {
        patternElement.title = patternElement.style.color = "";
      } else {
        patternElement.style.color = "red";
        patternElement.title = "Red text means that the pattern does not\nmatch the current URL.";
      }
    }

    ExclusionRulesOnPopupOption.prototype.httpRegex = /^https?:\/\/./;
    ExclusionRulesOnPopupOption.prototype.urlRegex = /^[a-z]{3,}:\/\/./;
    ExclusionRulesOnPopupOption.prototype.generateDefaultPattern = function() {
      return this.httpRegex.test(this.url)
        ? ("https?://" + this.url.split("/", 3)[2] + "/*")
        : this.urlRegex.test(this.url)
        ? (this.url.split("/", 3).join("/") + "/*")
        : (this.url + "*");
    };

    return ExclusionRulesOnPopupOption;

  })(ExclusionRulesOption);

  initOptionsPage = function() {
    var activateHelpDialog, element, maintainLinkHintsView, name, onUpdated //
      , options, saveOptions, toggleAdvancedOptions, type, _i, _ref;

    onUpdated = function() {
      var saveBtn = $("saveOptions");
      saveBtn.removeAttribute("disabled");
      saveBtn.innerHTML = "Save Changes";
    };

    maintainLinkHintsView = function() {
      var hide, show;
      hide = function(el) {
        el.parentNode.parentNode.style.display = "none";
      };
      show = function(el) {
        el.parentNode.parentNode.style.display = "table-row";
      };
      if ($("filterLinkHints").checked) {
        hide($("linkHintCharacters"));
        show($("linkHintNumbers"));
      } else {
        show($("linkHintCharacters"));
        hide($("linkHintNumbers"));
      }
    };

    var _advancedMode = !bgSettings.get("showAdvancedOptions");
    toggleAdvancedOptions = function(event) {
      if (_advancedMode) {
        $("advancedOptions").style.display = "none";
        $("advancedOptionsLink").innerHTML = "Show advanced options…";
      } else {
        $("advancedOptions").style.display = "table-row-group";
        $("advancedOptionsLink").innerHTML = "Hide advanced options";
      }
      _advancedMode = !_advancedMode;
      bgSettings.set("showAdvancedOptions", _advancedMode);
      event.preventDefault();
      document.activeElement.blur();
    };

    activateHelpDialog = function() {
      showHelpDialog({
        html: BG.helpDialogHtml(true, true, "Command Listing"),
        advanced: bgSettings.get("showAdvancedCommands")
      });
      document.activeElement.blur();
    };

    saveOptions = function() {
      var btn = $("saveOptions");
      if (btn.disabled) {
        return;
      }
      Option.saveOptions();
      btn.disabled = true;
      btn.innerHTML = "No Changes";
      setTimeout(function () {
        window.onfocus();
        bgSettings.buildBuffer();
        BG.sendRequestToAllTabs({
          name: "settings",
          frameId: 0,
          load: bgSettings.bufferToLoad
        });
      }, 100);
    };

    $("saveOptions").addEventListener("click", saveOptions);
    $("advancedOptionsLink").addEventListener("click", toggleAdvancedOptions);
    toggleAdvancedOptions({preventDefault: function() {}});
    $("showCommands").addEventListener("click", activateHelpDialog);
    $("filterLinkHints").addEventListener("click", maintainLinkHintsView);
    _ref = document.getElementsByClassName("nonEmptyTextOption");
    for (_i = _ref.length; 0 <= --_i; ) {
      element = _ref[_i];
      element.className = element.className + " example info";
      element.innerHTML = "Leave empty to reset this option.";
    }
    maintainLinkHintsView();
    window.onbeforeunload = function() {
      if (!$("saveOptions").disabled) {
        return "You have unsaved changes to options.";
      }
    };
    document.addEventListener("keyup", function(event) {
      if (event.ctrlKey && event.keyCode === 13) {
        if (document.activeElement && document.activeElement.blur) {
          document.activeElement.blur();
        }
        saveOptions();
      }
    });

    options = {
      exclusionRules: ExclusionRulesOption,
      filterLinkHints: CheckBoxOption,
      hideHud: CheckBoxOption,
      vomnibarInMain: CheckBoxOption,
      keyMappings: TextOption,
      linkHintCharacters: NonEmptyTextOption,
      linkHintNumbers: NonEmptyTextOption,
      newTabUrl: NonEmptyTextOption,
      nextPatterns: NonEmptyTextOption,
      previousPatterns: NonEmptyTextOption,
      regexFindMode: CheckBoxOption,
      scrollStepSize: NumberOption,
      smoothScroll: CheckBoxOption,
      searchEngines: TextOption,
      searchUrl: NonEmptyTextOption,
      userDefinedCss: TextOption
    };
    for (name in options) {
      type = options[name];
      new type(name, onUpdated);
    }
  };

  initPopupPage = function(tab) {
    var exclusions, onUpdated, saveOptions, updateState, url;
    exclusions = null;
    url = BG.urlForTab[tab.id] || tab.url;
    updateState = function() {
      var rule = bgExclusions.getRule(url, exclusions.readValueFromElement());
      $("state").innerHTML = "Vimium will " + (rule && rule.passKeys
        ? "exclude " + rule.passKeys + ""
        : rule ? "be disabled" : "be enabled");
    };
    onUpdated = function() {
      var btn = $("saveOptions");
      $("helpText").innerHTML = "Type Ctrl-Enter to save and close.";
      btn.removeAttribute("disabled");
      btn.innerHTML = "Save Changes";
      if (exclusions) {
        updateState();
      }
    };
    saveOptions = function() {
      var btn = $("saveOptions");
      if (btn.disabled) {
        return;
      }
      Option.saveOptions();
      btn.innerHTML = "Saved";
      btn.disabled = true;
      var rule = bgExclusions.getRule(url);
      BG.g_requestHandlers.setIcon(tab.id //
        , rule ? (rule.passKeys ? "partial" : "disabled") : "enabled");
    };
    $("saveOptions").addEventListener("click", saveOptions);
    document.addEventListener("keyup", function(event) {
      if (event.ctrlKey && event.keyCode === 13) {
        saveOptions();
        // although the tab calls window.onfocus after it closes,
        // it is too early for the tab to know new exclusion rules.
        setTimeout(window.close, 300);
      }
    });
    exclusions = new ExclusionRulesOnPopupOption(url, "exclusionRules", onUpdated);
    updateState();
    document.addEventListener("keyup", updateState);
  };

  document.addEventListener("DOMContentLoaded", function() {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "/pages/exclusions.html", true);
    xhr.onreadystatechange = function() {
      if (xhr.readyState === 4) {
        $("exclusionScrollBox").innerHTML = xhr.responseText;
        if (window.location.pathname.endsWith("popup.html")) {
          chrome.tabs.getSelected(null, initPopupPage);
        } else if (location.pathname.endsWith("options.html") >= 0) {
          initOptionsPage();
        }
      }
    };
    xhr.send();
  });

})();
<|endoftext|>


<commit_before>var jsonlint = require('jsonlint-lines');

function hint(str) {

    var errors = [];

    function root(_) {
        if (!_.type) {
            errors.push({
                message: 'The type property is required and was not found',
                line: _.__line__
            });
        } else if (!types[_.type]) {
            errors.push({
                message: 'The type ' + _.type + ' is unknown',
                line: _.__line__
            });
        } else {
            types[_.type](_);
        }
    }

    function everyIs(_, type) {
        return _.every(function(x) { return typeof x === 'number'; });
    }

    function requiredProperty(_, name, type) {
        if (typeof _[name] == 'undefined') {
            return errors.push({
                message: '"' + name + '" property required',
                line: _.__line__
            });
        } else if (type === 'array') {
            if (!Array.isArray(_[name])) {
                return errors.push({
                    message: '"' + name +
                        '" property should be an array, but is an ' +
                        (typeof _[name]) + ' instead',
                    line: _.__line__
                });
            }
        } else if (type && typeof _[name] !== type) {
            return errors.push({
                message: '"' + name +
                    '" property should be ' + (type) +
                    ', but is an ' + (typeof _[name]) + ' instead',
                line: _.__line__
            });
        }
    }

    // http://geojson.org/geojson-spec.html#feature-collection-objects
    function FeatureCollection(_) {
        crs(_);
        bbox(_);
        if (!requiredProperty(_, 'features', 'array')) {
            _.features.forEach(Feature);
        }
    }

    // http://geojson.org/geojson-spec.html#positions
    function position(_, line) {
        if (!Array.isArray(_)) {
            return errors.push({
                message: 'position should be an array, is a ' + (typeof _) +
                    ' instead',
                line: _.__line__ || line
            });
        } else {
            if (_.length < 2) {
                return errors.push({
                    message: 'position must have 2 or more elements',
                    line: _.__line__ || line
                });
            }
            if (!everyIs(_, 'number')) {
                return errors.push({
                    message: 'each element in a position must be a number',
                    line: _.__line__ || line
                });
            }
        }
    }

    function positionArray(coords, depth, line) {
        if (line === undefined && coords.__line__ !== undefined) {
            line = coords.__line__;
        }
        if (depth === 0) {
            return position(coords, line);
        } else {
            if (!Array.isArray(coords)) {
                return errors.push({
                    message: 'coordinates should be an array, are an ' + (typeof coords) +
                        'instead',
                    line: line
                });
            }
            coords.forEach(function(c) {
                positionArray(c, depth - 1, c.__line__ || line);
            });
        }
    }

    function crs(_) {
        if (!_.crs) return;
        if (typeof _.crs === 'object') {
            var strErr = requiredProperty(_.crs, 'type', 'string'),
                propErr = requiredProperty(_.crs, 'properties', 'object');
            if (!strErr && !propErr) {
                // http://geojson.org/geojson-spec.html#named-crs
                if (_.crs.type == 'name') {
                    requiredProperty(_.crs.properties, 'name', 'string');
                } else if (_.crs.type == 'link') {
                    requiredProperty(_.crs.properties, 'href', 'string');
                }
            }
        }
    }

    function bbox(_) {
        if (!_.bbox) return;
        if (Array.isArray(_.bbox)) {
            if (!everyIs(_.bbox, 'number')) {
                return errors.push({
                    message: 'each element in a bbox property must be a number',
                    line: _.bbox.__line__
                });
            }
        } else {
            errors.push({
                message: 'bbox property must be an array of numbers, but is a ' + (typeof _.bbox),
                line: _.__line__
            });
        }
    }

    // http://geojson.org/geojson-spec.html#point
    function Point(_) {
        crs(_);
        bbox(_);
        if (!requiredProperty(_, 'coordinates', 'array')) {
            position(_.coordinates);
        }
    }

    // http://geojson.org/geojson-spec.html#polygon
    function Polygon(_) {
        crs(_);
        bbox(_);
        if (!requiredProperty(_, 'coordinates', 'array')) {
            positionArray(_.coordinates, 2);
        }
    }

    // http://geojson.org/geojson-spec.html#multipolygon
    function MultiPolygon(_) {
        crs(_);
        bbox(_);
        if (!requiredProperty(_, 'coordinates', 'array')) {
            positionArray(_.coordinates, 3);
        }
    }

    // http://geojson.org/geojson-spec.html#linestring
    function LineString(_) {
        crs(_);
        bbox(_);
        if (!requiredProperty(_, 'coordinates', 'array')) {
            positionArray(_.coordinates, 1);
        }
    }

    // http://geojson.org/geojson-spec.html#multilinestring
    function MultiLineString(_) {
        crs(_);
        bbox(_);
        if (!requiredProperty(_, 'coordinates', 'array')) {
            positionArray(_.coordinates, 2);
        }
    }

    // http://geojson.org/geojson-spec.html#multipoint
    function MultiPoint(_) {
        crs(_);
        bbox(_);
        if (!requiredProperty(_, 'coordinates', 'array')) {
            positionArray(_.coordinates, 1);
        }
    }

    function GeometryCollection(_) {
        crs(_);
        bbox(_);
        if (!requiredProperty(_, 'geometries', 'array')) {
            _.geometries.forEach(root);
        }
    }

    function Feature(_) {
        crs(_);
        bbox(_);
        if (_.type !== 'Feature') {
            errors.push({
                message: 'GeoJSON features must have a type=feature property',
                line: _.__line__
            });
        }
        requiredProperty(_, 'properties', 'object');
        requiredProperty(_, 'geometry', 'object');
        root(_.geometry);
    }

    var types = {
        Point: Point,
        Feature: Feature,
        MultiPoint: MultiPoint,
        LineString: LineString,
        MultiLineString: MultiLineString,
        FeatureCollection: FeatureCollection,
        GeometryCollection: GeometryCollection,
        Polygon: Polygon,
        MultiPolygon: MultiPolygon
    };

    try {
        gj = jsonlint.parse(str);
    } catch(e) {
        return e;
    }

    root(gj);

    return errors;
}

module.exports.hint = hint;
<commit_msg>Fix global leak<commit_after>var jsonlint = require('jsonlint-lines');

function hint(str) {

    var errors = [], gj;

    function root(_) {
        if (!_.type) {
            errors.push({
                message: 'The type property is required and was not found',
                line: _.__line__
            });
        } else if (!types[_.type]) {
            errors.push({
                message: 'The type ' + _.type + ' is unknown',
                line: _.__line__
            });
        } else {
            types[_.type](_);
        }
    }

    function everyIs(_, type) {
        return _.every(function(x) { return typeof x === 'number'; });
    }

    function requiredProperty(_, name, type) {
        if (typeof _[name] == 'undefined') {
            return errors.push({
                message: '"' + name + '" property required',
                line: _.__line__
            });
        } else if (type === 'array') {
            if (!Array.isArray(_[name])) {
                return errors.push({
                    message: '"' + name +
                        '" property should be an array, but is an ' +
                        (typeof _[name]) + ' instead',
                    line: _.__line__
                });
            }
        } else if (type && typeof _[name] !== type) {
            return errors.push({
                message: '"' + name +
                    '" property should be ' + (type) +
                    ', but is an ' + (typeof _[name]) + ' instead',
                line: _.__line__
            });
        }
    }

    // http://geojson.org/geojson-spec.html#feature-collection-objects
    function FeatureCollection(_) {
        crs(_);
        bbox(_);
        if (!requiredProperty(_, 'features', 'array')) {
            _.features.forEach(Feature);
        }
    }

    // http://geojson.org/geojson-spec.html#positions
    function position(_, line) {
        if (!Array.isArray(_)) {
            return errors.push({
                message: 'position should be an array, is a ' + (typeof _) +
                    ' instead',
                line: _.__line__ || line
            });
        } else {
            if (_.length < 2) {
                return errors.push({
                    message: 'position must have 2 or more elements',
                    line: _.__line__ || line
                });
            }
            if (!everyIs(_, 'number')) {
                return errors.push({
                    message: 'each element in a position must be a number',
                    line: _.__line__ || line
                });
            }
        }
    }

    function positionArray(coords, depth, line) {
        if (line === undefined && coords.__line__ !== undefined) {
            line = coords.__line__;
        }
        if (depth === 0) {
            return position(coords, line);
        } else {
            if (!Array.isArray(coords)) {
                return errors.push({
                    message: 'coordinates should be an array, are an ' + (typeof coords) +
                        'instead',
                    line: line
                });
            }
            coords.forEach(function(c) {
                positionArray(c, depth - 1, c.__line__ || line);
            });
        }
    }

    function crs(_) {
        if (!_.crs) return;
        if (typeof _.crs === 'object') {
            var strErr = requiredProperty(_.crs, 'type', 'string'),
                propErr = requiredProperty(_.crs, 'properties', 'object');
            if (!strErr && !propErr) {
                // http://geojson.org/geojson-spec.html#named-crs
                if (_.crs.type == 'name') {
                    requiredProperty(_.crs.properties, 'name', 'string');
                } else if (_.crs.type == 'link') {
                    requiredProperty(_.crs.properties, 'href', 'string');
                }
            }
        }
    }

    function bbox(_) {
        if (!_.bbox) return;
        if (Array.isArray(_.bbox)) {
            if (!everyIs(_.bbox, 'number')) {
                return errors.push({
                    message: 'each element in a bbox property must be a number',
                    line: _.bbox.__line__
                });
            }
        } else {
            errors.push({
                message: 'bbox property must be an array of numbers, but is a ' + (typeof _.bbox),
                line: _.__line__
            });
        }
    }

    // http://geojson.org/geojson-spec.html#point
    function Point(_) {
        crs(_);
        bbox(_);
        if (!requiredProperty(_, 'coordinates', 'array')) {
            position(_.coordinates);
        }
    }

    // http://geojson.org/geojson-spec.html#polygon
    function Polygon(_) {
        crs(_);
        bbox(_);
        if (!requiredProperty(_, 'coordinates', 'array')) {
            positionArray(_.coordinates, 2);
        }
    }

    // http://geojson.org/geojson-spec.html#multipolygon
    function MultiPolygon(_) {
        crs(_);
        bbox(_);
        if (!requiredProperty(_, 'coordinates', 'array')) {
            positionArray(_.coordinates, 3);
        }
    }

    // http://geojson.org/geojson-spec.html#linestring
    function LineString(_) {
        crs(_);
        bbox(_);
        if (!requiredProperty(_, 'coordinates', 'array')) {
            positionArray(_.coordinates, 1);
        }
    }

    // http://geojson.org/geojson-spec.html#multilinestring
    function MultiLineString(_) {
        crs(_);
        bbox(_);
        if (!requiredProperty(_, 'coordinates', 'array')) {
            positionArray(_.coordinates, 2);
        }
    }

    // http://geojson.org/geojson-spec.html#multipoint
    function MultiPoint(_) {
        crs(_);
        bbox(_);
        if (!requiredProperty(_, 'coordinates', 'array')) {
            positionArray(_.coordinates, 1);
        }
    }

    function GeometryCollection(_) {
        crs(_);
        bbox(_);
        if (!requiredProperty(_, 'geometries', 'array')) {
            _.geometries.forEach(root);
        }
    }

    function Feature(_) {
        crs(_);
        bbox(_);
        if (_.type !== 'Feature') {
            errors.push({
                message: 'GeoJSON features must have a type=feature property',
                line: _.__line__
            });
        }
        requiredProperty(_, 'properties', 'object');
        requiredProperty(_, 'geometry', 'object');
        root(_.geometry);
    }

    var types = {
        Point: Point,
        Feature: Feature,
        MultiPoint: MultiPoint,
        LineString: LineString,
        MultiLineString: MultiLineString,
        FeatureCollection: FeatureCollection,
        GeometryCollection: GeometryCollection,
        Polygon: Polygon,
        MultiPolygon: MultiPolygon
    };

    try {
        gj = jsonlint.parse(str);
    } catch(e) {
        return e;
    }

    root(gj);

    return errors;
}

module.exports.hint = hint;
<|endoftext|>


<commit_before>module.exports = {
  systemBusy:                         { code: -1,     message: 'system busy, retry later'},
  success:                            { code: 0,      message: 'success'},
  internalError:                      { code: 1,      message: 'internal error, contact us'},
  requireAppKey:                      { code: 10001,  message: 'require appKey'},
  requireAppSecret:                   { code: 10002,  message: 'require appSecret'},
  requireDeviceUdid:                  { code: 10003,  message: 'require deviceUdid'},
  invalidAppKey:                      { code: 10004,  message: 'invalid appKey'},
  invalidAppSecret:                   { code: 10005,  message: 'invalid appSecret'},
  failedToSaveDevice:                 { code: 10006,  message: 'failed to create/update device, contact us'},
  invalidToken:                       { code: 10007,  message: 'invalid token'},
  tokenExpired:                       { code: 10008,  message: 'token is expired'},
  failedToGenerateToken:              { code: 10009,  message: 'failed to generate token, contact us'},
  requireToken:                       { code: 10010,  message: 'require token'},
  requireDataFile:                    { code: 10011,  message: 'require uploaded data file'},
  requireAppBundle:                   { code: 10012,  message: 'require appBundle'},
  failedToGetApp:                     { code: 10013,  message: 'rpc error, failed to Get App'},
  requireUserId:                      { code: 10014,  message: 'require user id'},
  requireUsername:                    { code: 11001,  message: 'require username'},
  requirePassword:                    { code: 11002,  message: 'require password'},
  userNotExist:                       { code: 11003,  message: 'user not exist'},
  passwordNotMatch:                   { code: 11004,  message: 'password not match'},
  failedToGenerateToken:              { code: 11005,  message: 'failed to generate token, contact us'},
  failedToCreateUser:                 { code: 11006,  message: 'failed to create user'},
  failedToHashPassword:               { code: 11007,  message: 'failed to hash password'},
  failedToSaveUser:                   { code: 11008,  message: 'failed to save user, please check if required field is correct'},
  failedToSaveFile:                   { code: 11009,  message: 'failed to save file'},
  failedToDeleteFile:                 { code: 11010,  message: 'failed to delete file'},
  fileNotExist:                       { code: 11011,  message: 'file not exist'},
  failedToReadFile:                   { code: 11012,  message: 'error when read file'},
  failedToQueuePoiImportJob:          { code: 11013,  message: 'failed to create poi import task'},
  requireClientKey:                   { code: 11014,  message: 'require clientKey'},
  requireClientSecret:                { code: 11015,  message: 'require clientSecret'},
  clientNotExist:                     { code: 11016,  message: 'client not exist'},
  invalidClientKey:                   { code: 11017,  message: 'invalid clientKey'},
  invalidClientSecret:                { code: 11018,  message: 'invalid clientSecret'},
  failedToCreateDevice:               { code: 40001,  message: 'failed to create device, contact us'},
  failedToGetDevice:                  { code: 40002,  message: 'failed to get device, contact us'},
  failedToUpdateDevice:               { code: 40003,  message: 'failed to update device, contact us'},
  failedToQueueDeviceDataCollectJob:  { code: 40004,  message: 'failed to queue device data collect job'},
  failedToQueuePoiImportJob:          { code: 40005,  message: 'failed to queue poi import job'},
  failedToFindRegions:                { code: 40006,  message: 'failed to find regions'},
  failedToFindPois:                   { code: 40007,  message: 'failed to find pois'},
  failedToEnsureDevice:               { code: 40008,  message: 'rpc error, failed to ensure device'},
  requirePoiId:                       { code: 40009,  message: 'require poi id'},
  poiNotExist:                        { code: 40010,  message: 'poi not exist'}
};
<commit_msg>add error messages of poi pull request.<commit_after>module.exports = {
  systemBusy:                         { code: -1,     message: 'system busy, retry later'},
  success:                            { code: 0,      message: 'success'},
  internalError:                      { code: 1,      message: 'internal error, contact us'},
  requireAppKey:                      { code: 10001,  message: 'require appKey'},
  requireAppSecret:                   { code: 10002,  message: 'require appSecret'},
  requireDeviceUdid:                  { code: 10003,  message: 'require deviceUdid'},
  invalidAppKey:                      { code: 10004,  message: 'invalid appKey'},
  invalidAppSecret:                   { code: 10005,  message: 'invalid appSecret'},
  failedToSaveDevice:                 { code: 10006,  message: 'failed to create/update device, contact us'},
  invalidToken:                       { code: 10007,  message: 'invalid token'},
  tokenExpired:                       { code: 10008,  message: 'token is expired'},
  failedToGenerateToken:              { code: 10009,  message: 'failed to generate token, contact us'},
  requireToken:                       { code: 10010,  message: 'require token'},
  requireDataFile:                    { code: 10011,  message: 'require uploaded data file'},
  requireAppBundle:                   { code: 10012,  message: 'require appBundle'},
  failedToGetApp:                     { code: 10013,  message: 'rpc error, failed to Get App'},
  requireUserId:                      { code: 10014,  message: 'require user id'},
  requireUsername:                    { code: 11001,  message: 'require username'},
  requirePassword:                    { code: 11002,  message: 'require password'},
  userNotExist:                       { code: 11003,  message: 'user not exist'},
  passwordNotMatch:                   { code: 11004,  message: 'password not match'},
  failedToCreateUser:                 { code: 11006,  message: 'failed to create user'},
  failedToHashPassword:               { code: 11007,  message: 'failed to hash password'},
  failedToSaveUser:                   { code: 11008,  message: 'failed to save user, please check if required field is correct'},
  failedToSaveFile:                   { code: 11009,  message: 'failed to save file'},
  failedToDeleteFile:                 { code: 11010,  message: 'failed to delete file'},
  fileNotExist:                       { code: 11011,  message: 'file not exist'},
  failedToReadFile:                   { code: 11012,  message: 'error when read file'},
  requireClientKey:                   { code: 11014,  message: 'require clientKey'},
  requireClientSecret:                { code: 11015,  message: 'require clientSecret'},
  clientNotExist:                     { code: 11016,  message: 'client not exist'},
  invalidClientKey:                   { code: 11017,  message: 'invalid clientKey'},
  invalidClientSecret:                { code: 11018,  message: 'invalid clientSecret'},
  failedToCreateDevice:               { code: 40001,  message: 'failed to create device, contact us'},
  failedToGetDevice:                  { code: 40002,  message: 'failed to get device, contact us'},
  failedToUpdateDevice:               { code: 40003,  message: 'failed to update device, contact us'},
  failedToQueueDeviceDataCollectJob:  { code: 40004,  message: 'failed to queue device data collect job'},
  failedToQueuePoiImportJob:          { code: 40005,  message: 'failed to queue poi import job'},
  failedToFindRegions:                { code: 40006,  message: 'failed to find regions'},
  failedToFindPois:                   { code: 40007,  message: 'failed to find pois'},
  failedToEnsureDevice:               { code: 40008,  message: 'rpc error, failed to ensure device'},
  requirePoiId:                       { code: 40009,  message: 'require poi id'},
  poiNotExist:                        { code: 40010,  message: 'poi not exist'},
  requirePullRequest:                 { code: 40011,  message: 'require pull request info'},
  poiNotReady:                        { code: 40012,  message: 'poi not ready'}
};
<|endoftext|>


<commit_before>var webdriver = require('selenium-webdriver'),
    Q = require('q'),
    phantomjs = require('phantomjs-bin');

var safariAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) ' +
  'AppleWebKit/537.73.11 (KHTML, like Gecko) Version/7.0.1 Safari/537.73.11';

var CSA_HOME_URL = 'https://www.commsecadviserservices.com.au/';
var CSA_PORTFOLIO_SUMMARY_URL = 'https://www.commsecadviserservices.com.au/Private/MyPortfolio/Statements/StatementsPortfolioSummary.aspx';

module.exports = CSA;
function CSA(options) {
  this.options = options;
  options = options || {};
  options.browserName = options.browserName || 'phantomjs';
  options.userAgent = options.userAgent || safariAgent;
  this.flow = webdriver.promise.controlFlow();
}

CSA.prototype.execute = function (fn, cb) {
  var promise = this.flow.execute(fn, cb);
  if (cb) Q(promise).nodeify(cb);
};

CSA.prototype.init = function init(cb) {
  var self = this;

  self.driver = new webdriver.Builder()
  .withCapabilities({
     browserName: self.options.browserName,
     'phantomjs.binary.path': phantomjs.path,
     'phantomjs.page.settings.userAgent': self.options.userAgent
  })
  .build();

  for (var i in self.driver) {
    if (typeof self.driver[i] === 'function' && !(i in self)) {
      self[i] = self.driver[i].bind(self.driver);
    }
  }

  if (cb) this.execute(cb.bind(null, null, this));
  return this;
};

CSA.prototype.quit = function (cb) {
  this.driver.quit();
  if (cb) this.execute(cb);
  return this;
};

CSA.prototype.login = function (username, password, cb) {
  var driver = this;

  driver.get(CSA_HOME_URL);
  driver.sleep(500);
  driver.wait(function () {
    return driver.isVisible('#ctl00_AdviserLoginControl_txtACUserName');
  }, 20000, 'cant find username');
  driver.findElement(webdriver.By.id(
    'ctl00_AdviserLoginControl_txtACUserName'))
    .sendKeys(username);
  driver.findElement(webdriver.By.id(
    'ctl00_AdviserLoginControl_txtACPassword'))
    .sendKeys(password);
  driver.findElement(webdriver.By.id('ctl00_AdviserLoginControl_btnACLogIn_implementation_field')).click();

  // Wait till logged in
  driver.wait(function () {
    return driver.isElementPresent(
      webdriver.By.css('#ctl00_AdviserLoginControl_lblDisplayAccountName_field'));
  }, 20000, 'error waiting to logging in');

  if (cb) this.execute(cb);
  return this;
};

CSA.prototype.portfolioSummary = function (cb) {
  var driver = this;
  driver.get(CSA_PORTFOLIO_SUMMARY_URL);

  var summary = {
    balance: null,
    marketValue: null,
    totalCost: null,
    profitLoss: null,
    changePct: null
  };

  // Wait till can see portfolio balance
  driver.wait(function () {
    return driver.isElementPresent(
      webdriver.By.css('#ctl00_BodyPlaceHolder_StatementsPortfolioSummaryView1_lblPortfolioValue_field'));
  }, 20000, 'error waiting for portfolio element to appear');

  // Wait until balance is populated
  driver.wait(function () {
    return driver.findElement(webdriver.By.id(
      'ctl00_BodyPlaceHolder_StatementsPortfolioSummaryView1_lblPortfolioValue_field')).then(
      function (el) {
        return el.getInnerHtml().then(function (html) {
          return html.trim().length > 0;
        });
      }
    );
  }, 20000, 'error waiting for portfolio balance');

  var values = {
    '#ctl00_BodyPlaceHolder_StatementsPortfolioSummaryView1_lblPortfolioValue_field':
      'balance',
    '#ctl00_BodyPlaceHolder_StatementsPortfolioSummaryView1_gvSharePortfolio_Underlying_ctl03_lblProfitLoss_field':
      'profitLoss',
    '#ctl00_BodyPlaceHolder_StatementsPortfolioSummaryView1_gvSharePortfolio_Underlying_ctl03_lblTotalCost_field': 'totalCost',
    '#ctl00_BodyPlaceHolder_StatementsPortfolioSummaryView1_gvSharePortfolio_Underlying_ctl03_lblMarketValue_field': 'marketValue',
    '#ctl00_BodyPlaceHolder_StatementsPortfolioSummaryView1_gvSharePortfolio_Underlying_ctl03_lblChange_field': 'changePct'
  };

  for (var selector in values) {
    (function (selector, fieldName) {
      driver.getSelectorValue(selector).then(function (html) {
        summary[fieldName] = parseFloat(html.replace(/,/, ''));
      });
    })(selector, values[selector]);
  }

  if (cb) this.execute(cb.bind(null, null, summary));
  return this;
};

CSA.prototype.setAttribute = function (selector, attr, value) {
  var driver = this.driver;
  return driver.executeScript(function (selector, attr, value) {
    var els = Array.prototype.slice.call(document.querySelectorAll(selector));
    els.forEach(function (el) {
      el[attr] = value;
    });
  }, selector, attr, value);
}

CSA.prototype.getSelectorValue = function (selector) {
  var flow = this.flow,
      driver = this.driver;

  return flow.execute(function () {
    return driver.findElement(webdriver.By.css(selector)).then(
      function (el) {
        return el.getInnerHtml().then(function (html) {
          return html.trim();
        });
      }
    );
  });
};

CSA.prototype.sleep = function (ms) {
  var flow = this.flow;
  return flow.execute(function () {
    return webdriver.promise.delayed(ms);
  });
};

CSA.prototype.isVisible = function(selector) {
  var driver = this.driver;
  return driver.executeScript(function (selector) {
    var visible = false;
    var el = document.querySelector(selector);
    if (el) visible = !(el.offsetWidth <= 0 && el.offsetHeight <= 0);
    return visible;
  }, selector);
};
<commit_msg>Update selector IDs<commit_after>var webdriver = require('selenium-webdriver'),
    Q = require('q'),
    phantomjs = require('phantomjs-bin');

var safariAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) ' +
  'AppleWebKit/537.73.11 (KHTML, like Gecko) Version/7.0.1 Safari/537.73.11';

var CSA_HOME_URL = 'https://www.commsecadviserservices.com.au/';
var CSA_PORTFOLIO_SUMMARY_URL = 'https://www.commsecadviserservices.com.au/Private/MyPortfolio/Statements/StatementsPortfolioSummary.aspx';

module.exports = CSA;
function CSA(options) {
  this.options = options;
  options = options || {};
  options.browserName = options.browserName || 'phantomjs';
  options.userAgent = options.userAgent || safariAgent;
  this.flow = webdriver.promise.controlFlow();
}

CSA.prototype.execute = function (fn, cb) {
  var promise = this.flow.execute(fn, cb);
  if (cb) Q(promise).nodeify(cb);
};

CSA.prototype.init = function init(cb) {
  var self = this;

  self.driver = new webdriver.Builder()
  .withCapabilities({
     browserName: self.options.browserName,
     'phantomjs.binary.path': phantomjs.path,
     'phantomjs.page.settings.userAgent': self.options.userAgent
  })
  .build();

  for (var i in self.driver) {
    if (typeof self.driver[i] === 'function' && !(i in self)) {
      self[i] = self.driver[i].bind(self.driver);
    }
  }

  if (cb) this.execute(cb.bind(null, null, this));
  return this;
};

CSA.prototype.quit = function (cb) {
  this.driver.quit();
  if (cb) this.execute(cb);
  return this;
};

CSA.prototype.login = function (username, password, cb) {
  var driver = this;

  driver.get(CSA_HOME_URL);
  driver.sleep(500);
  driver.wait(function () {
    return driver.isVisible('#ctl00_AdviserLoginControl_txtACUserName');
  }, 20000, 'cant find username');
  driver.findElement(webdriver.By.id(
    'ctl00_AdviserLoginControl_txtACUserName'))
    .sendKeys(username);
  driver.findElement(webdriver.By.id(
    'ctl00_AdviserLoginControl_txtACPassword'))
    .sendKeys(password);
  driver.findElement(webdriver.By.id('ctl00_AdviserLoginControl_btnACLogIn_implementation_field')).click();

  // Wait till logged in
  driver.wait(function () {
    return driver.isElementPresent(
      webdriver.By.css('#ctl00_AdviserLoginControl_lblDisplayAccountName_field'));
  }, 20000, 'error waiting to logging in');

  if (cb) this.execute(cb);
  return this;
};

CSA.prototype.portfolioSummary = function (cb) {
  var driver = this;
  driver.get(CSA_PORTFOLIO_SUMMARY_URL);

  var summary = {
    balance: null,
    marketValue: null,
    totalCost: null,
    profitLoss: null,
    changePct: null
  };

  // Wait till can see portfolio balance
  driver.wait(function () {
    return driver.isElementPresent(
      webdriver.By.css('#ctl00_BodyPlaceHolder_StatementsPortfolioSummaryView1_lblPortfolioValue_field'));
  }, 20000, 'error waiting for portfolio element to appear');

  // Wait until balance is populated
  driver.wait(function () {
    return driver.findElement(webdriver.By.id(
      'ctl00_BodyPlaceHolder_StatementsPortfolioSummaryView1_lblPortfolioValue_field')).then(
      function (el) {
        return el.getInnerHtml().then(function (html) {
          return html.trim().length > 0;
        });
      }
    );
  }, 20000, 'error waiting for portfolio balance');

  var values = {
    '#ctl00_BodyPlaceHolder_StatementsPortfolioSummaryView1_lblPortfolioValue_field':
      'balance',
    '#ctl00_BodyPlaceHolder_StatementsPortfolioSummaryView1_gvCASSharePortfolio_Underlying_ctl03_lblProfitLoss_field':
      'profitLoss',
    '#ctl00_BodyPlaceHolder_StatementsPortfolioSummaryView1_gvCASSharePortfolio_Underlying_ctl03_lblTotalCost_field': 'totalCost',
    '#ctl00_BodyPlaceHolder_StatementsPortfolioSummaryView1_gvCASSharePortfolio_Underlying_ctl03_lblMarketValue_field': 'marketValue',
    '#ctl00_BodyPlaceHolder_StatementsPortfolioSummaryView1_gvCASSharePortfolio_Underlying_ctl03_lblChange_field': 'changePct'
  };

  for (var selector in values) {
    (function (selector, fieldName) {
      driver.getSelectorValue(selector).then(function (html) {
        summary[fieldName] = parseFloat(html.replace(/,/, ''));
      });
    })(selector, values[selector]);
  }

  if (cb) this.execute(cb.bind(null, null, summary));
  return this;
};

CSA.prototype.setAttribute = function (selector, attr, value) {
  var driver = this.driver;
  return driver.executeScript(function (selector, attr, value) {
    var els = Array.prototype.slice.call(document.querySelectorAll(selector));
    els.forEach(function (el) {
      el[attr] = value;
    });
  }, selector, attr, value);
}

CSA.prototype.getSelectorValue = function (selector) {
  var flow = this.flow,
      driver = this.driver;

  return flow.execute(function () {
    return driver.findElement(webdriver.By.css(selector)).then(
      function (el) {
        return el.getInnerHtml().then(function (html) {
          return html.trim();
        });
      }
    );
  });
};

CSA.prototype.sleep = function (ms) {
  var flow = this.flow;
  return flow.execute(function () {
    return webdriver.promise.delayed(ms);
  });
};

CSA.prototype.isVisible = function(selector) {
  var driver = this.driver;
  return driver.executeScript(function (selector) {
    var visible = false;
    var el = document.querySelector(selector);
    if (el) visible = !(el.offsetWidth <= 0 && el.offsetHeight <= 0);
    return visible;
  }, selector);
};
<|endoftext|>


<commit_before>#!/usr/bin/env node
var program = require('commander'),
    globalify = require('./globalify'),
    packageJson = require('./package.json'),
    fs = require('fs');

program
    .version(packageJson.version)
    .usage('<module> [options]')
    .arguments('<module>')
    .option('-o, --out <outputFileName>', 'the output path')
    .option('-g, --globalVariable [globalVariable]', 'the name of the global variable to expose')
    .parse(process.argv);

if (program.args.length !== 1) {
    program.help()
}

var moduleNameAndVersion = program.args[0].split('@'),
    moduleName = moduleNameAndVersion[0],
    version = moduleNameAndVersion[1] || 'x.x.x';

var outStream = fs.createWriteStream(program.out || moduleName + '.js');

globalify({
        module: moduleName,
        version: version,
        globalVariable: program.globalVariable,
        installDirectory: packageJson.installDirectory
    },
    function(error){
        if(error){
            console.log(error);
        }
    }
).pipe(outStream);
<commit_msg>Add support for scoped package<commit_after>#!/usr/bin/env node
var program = require('commander'),
    globalify = require('./globalify'),
    packageJson = require('./package.json'),
    fs = require('fs');

program
    .version(packageJson.version)
    .usage('<module> [options]')
    .arguments('<module>')
    .option('-o, --out <outputFileName>', 'the output path')
    .option('-g, --globalVariable [globalVariable]', 'the name of the global variable to expose')
    .parse(process.argv);

if (program.args.length !== 1) {
    program.help();
}

var moduleArgument = program.args[0];

var moduleNodes, moduleName, version;
if (moduleArgument.indexOf('@') === 0) {
    // scoped package
    moduleNodes = moduleArgument.slice(1).split('@');
    moduleName = '@' + moduleNodes[0];
}
else {
    moduleNodes = moduleArgument.split('@');
    moduleName = moduleNodes[0];
}

version = moduleNodes[1] || 'x.x.x';

var outStream = fs.createWriteStream(program.out || moduleName.replace('/', '-') + '.js');

globalify({
        module: moduleName,
        version: version,
        globalVariable: program.globalVariable,
        installDirectory: packageJson.installDirectory
    },
    function(error){
        if(error){
            console.log(error);
        }
    }
).pipe(outStream);
<|endoftext|>


<commit_before>// Process @[youtube](youtubeVideoID)
// Process @[vimeo](vimeoVideoID)
// Process @[vine](vineVideoID)
// Process @[prezi](preziID)
// Process @[file](guid)

const ytRegex = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#&?]*).*/;
function youtubeParser(url) {
  const match = url.match(ytRegex);
  return match && match[7].length === 11 ? match[7] : url;
}

/* eslint-disable max-len */
const vimeoRegex = /https?:\/\/(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/([^/]*)\/videos\/|album\/(\d+)\/video\/|)(\d+)(?:$|\/|\?)/;
/* eslint-enable max-len */
function vimeoParser(url) {
  const match = url.match(vimeoRegex);
  return match && typeof match[3] === 'string' ? match[3] : url;
}

const vineRegex = /^http(?:s?):\/\/(?:www\.)?vine\.co\/v\/([a-zA-Z0-9]{1,13}).*/;
function vineParser(url) {
  const match = url.match(vineRegex);
  return match && match[1].length === 11 ? match[1] : url;
}

const preziRegex = /^https:\/\/prezi.com\/(.[^/]+)/;
function preziParser(url) {
  const match = url.match(preziRegex);
  return match ? match[1] : url;
}
const mfrRegex = /^http(?:s?):\/\/(?:www\.)?mfr\.osf\.io\/render\?url=http(?:s?):\/\/osf\.io\/([a-zA-Z0-9]{1,5})\/\?action=download/;
function mfrParser(url) {
  const match = url.match(mfrRegex);
  return match ? match[1] : url;
}

const EMBED_REGEX = /@\[([a-zA-Z].+)]\([\s]*(.*?)[\s]*[)]/g;

function videoEmbed(md, options) {
  function videoReturn(state, silent) {
    var serviceEnd;
    var serviceStart;
    var token;
    var videoID;
    var theState = state;
    const oldPos = state.pos;

    if (state.src.charCodeAt(oldPos) !== 0x40/* @ */ ||
        state.src.charCodeAt(oldPos + 1) !== 0x5B/* [ */) {
      return false;
    }

    const match = EMBED_REGEX.exec(state.src);

    if (!match || match.length < 3) {
      return false;
    }

    const service = match[1];
    videoID = match[2];
    const serviceLower = service.toLowerCase();

    if (serviceLower === 'youtube') {
      videoID = youtubeParser(videoID);
    } else if (serviceLower === 'vimeo') {
      videoID = vimeoParser(videoID);
    } else if (serviceLower === 'vine') {
      videoID = vineParser(videoID);
    } else if (serviceLower === 'prezi') {
      videoID = preziParser(videoID);
    } else if (serviceLower === 'file') {
      videoID = mfrParser(videoID);
    } else if (!options[serviceLower]) {
      return false;
    }

    // If the videoID field is empty, regex currently make it the close parenthesis.
    if (videoID === ')') {
      videoID = '';
    }

    serviceStart = oldPos + 2;
    serviceEnd = md.helpers.parseLinkLabel(state, oldPos + 1, false);

    //
    // We found the end of the link, and know for a fact it's a valid link;
    // so all that's left to do is to call tokenizer.
    //
    if (!silent) {
      theState.pos = serviceStart;
      theState.posMax = serviceEnd;
      theState.service = theState.src.slice(serviceStart, serviceEnd);
      const newState = new theState.md.inline.State(service, theState.md, theState.env, []);
      newState.md.inline.tokenize(newState);

      token = theState.push('video', '');
      token.videoID = videoID;
      token.service = service;
      token.level = theState.level;
    }

    theState.pos += theState.src.indexOf(')', theState.pos);
    theState.posMax = theState.tokens.length;
    return true;
  }

  return videoReturn;
}

function videoUrl(service, videoID, options) {
  switch (service) {
    case 'youtube':
      return 'https://www.youtube.com/embed/' + videoID;
    case 'vimeo':
      return 'https://player.vimeo.com/video/' + videoID;
    case 'vine':
      return 'https://vine.co/v/' + videoID + '/embed/' + options.vine.embed;
    case 'prezi':
      return 'https://prezi.com/embed/' + videoID +
        '/?bgcolor=ffffff&lock_to_path=0&autoplay=0&autohide_ctrls=0&' +
        'landing_data=bHVZZmNaNDBIWnNjdEVENDRhZDFNZGNIUE43MHdLNWpsdFJLb2ZHanI5N1lQVHkxSHFxazZ0UUNCRHloSXZROHh3PT0&' +
        'landing_sign=1kD6c0N6aYpMUS0wxnQjxzSqZlEB8qNFdxtdjYhwSuI';
    case 'file':
      return "https://mfr.osf.io/render?url=https://osf.io/" + videoID + "/?action=download"
    default:
      return service;
  }
}

function tokenizeVideo(md, options) {
  function tokenizeReturn(tokens, idx) {
    const videoID = md.utils.escapeHtml(tokens[idx].videoID);
    const service = md.utils.escapeHtml(tokens[idx].service).toLowerCase();
    var num;

    if (service === 'file') {
      num = Math.random() * 0x10000;
      return '

';
    }

    return videoID === '' ? '' :
      '

';
  }

  return tokenizeReturn;
}

const defaults = {
  url: videoUrl,
  youtube: { width: 640, height: 390 },
  vimeo: { width: 500, height: 281 },
  vine: { width: 600, height: 600, embed: 'simple' },
  prezi: { width: 550, height: 400 },
  file: { width: '100%', height: '100%' },
};

module.exports = function videoPlugin(md, options) {
  var theOptions = options;
  var theMd = md;
  if (theOptions) {
    Object.keys(defaults).forEach(function checkForKeys(key) {
      if (typeof theOptions[key] === 'undefined') {
        theOptions[key] = defaults[key];
      }
    });
  } else {
    theOptions = defaults;
  }
  theMd.renderer.rules.video = tokenizeVideo(theMd, theOptions);
  theMd.inline.ruler.before('emphasis', 'video', videoEmbed(theMd, theOptions));
};
<commit_msg>fix doubling issue<commit_after>// Process @[youtube](youtubeVideoID)
// Process @[vimeo](vimeoVideoID)
// Process @[vine](vineVideoID)
// Process @[prezi](preziID)
// Process @[file](guid)

const ytRegex = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#&?]*).*/;
function youtubeParser(url) {
  const match = url.match(ytRegex);
  return match && match[7].length === 11 ? match[7] : url;
}

/* eslint-disable max-len */
const vimeoRegex = /https?:\/\/(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/([^/]*)\/videos\/|album\/(\d+)\/video\/|)(\d+)(?:$|\/|\?)/;
/* eslint-enable max-len */
function vimeoParser(url) {
  const match = url.match(vimeoRegex);
  return match && typeof match[3] === 'string' ? match[3] : url;
}

const vineRegex = /^http(?:s?):\/\/(?:www\.)?vine\.co\/v\/([a-zA-Z0-9]{1,13}).*/;
function vineParser(url) {
  const match = url.match(vineRegex);
  return match && match[1].length === 11 ? match[1] : url;
}

const preziRegex = /^https:\/\/prezi.com\/(.[^/]+)/;
function preziParser(url) {
  const match = url.match(preziRegex);
  return match ? match[1] : url;
}
const mfrRegex = /^http(?:s?):\/\/(?:www\.)?mfr\.osf\.io\/render\?url=http(?:s?):\/\/osf\.io\/([a-zA-Z0-9]{1,5})\/\?action=download/;
function mfrParser(url) {
  const match = url.match(mfrRegex);
  return match ? match[1] : url;
}

const EMBED_REGEX = /@\[([a-zA-Z].+)]\([\s]*(.*?)[\s]*[)]/im;

function videoEmbed(md, options) {
  function videoReturn(state, silent) {
    var serviceEnd;
    var serviceStart;
    var token;
    var videoID;
    var theState = state;
    const oldPos = state.pos;

    if (state.src.charCodeAt(oldPos) !== 0x40/* @ */ ||
        state.src.charCodeAt(oldPos + 1) !== 0x5B/* [ */) {
      return false;
    }
    const match = EMBED_REGEX.exec(state.src.slice(state.pos, state.src.length));

    if (!match || match.length < 3) {
      return false;
    }

    const service = match[1];
    videoID = match[2];
    const serviceLower = service.toLowerCase();

    if (serviceLower === 'youtube') {
      videoID = youtubeParser(videoID);
    } else if (serviceLower === 'vimeo') {
      videoID = vimeoParser(videoID);
    } else if (serviceLower === 'vine') {
      videoID = vineParser(videoID);
    } else if (serviceLower === 'prezi') {
      videoID = preziParser(videoID);
    } else if (serviceLower === 'file') {
      videoID = mfrParser(videoID);
    } else if (!options[serviceLower]) {
      return false;
    }

    // If the videoID field is empty, regex currently make it the close parenthesis.
    if (videoID === ')') {
      videoID = '';
    }

    serviceStart = oldPos + 2;
    serviceEnd = md.helpers.parseLinkLabel(state, oldPos + 1, false);

    //
    // We found the end of the link, and know for a fact it's a valid link;
    // so all that's left to do is to call tokenizer.
    //
    if (!silent) {
      theState.pos = serviceStart;
      theState.posMax = serviceEnd;
      theState.service = theState.src.slice(serviceStart, serviceEnd);
      const newState = new theState.md.inline.State(service, theState.md, theState.env, []);
      newState.md.inline.tokenize(newState);

      token = theState.push('video', '');
      token.videoID = videoID;
      token.service = service;
      token.level = theState.level;
    }

    theState.pos += theState.src.indexOf(')', theState.pos);
    theState.posMax = theState.tokens.length;
    return true;
  }

  return videoReturn;
}

function videoUrl(service, videoID, options) {
  switch (service) {
    case 'youtube':
      return 'https://www.youtube.com/embed/' + videoID;
    case 'vimeo':
      return 'https://player.vimeo.com/video/' + videoID;
    case 'vine':
      return 'https://vine.co/v/' + videoID + '/embed/' + options.vine.embed;
    case 'prezi':
      return 'https://prezi.com/embed/' + videoID +
        '/?bgcolor=ffffff&lock_to_path=0&autoplay=0&autohide_ctrls=0&' +
        'landing_data=bHVZZmNaNDBIWnNjdEVENDRhZDFNZGNIUE43MHdLNWpsdFJLb2ZHanI5N1lQVHkxSHFxazZ0UUNCRHloSXZROHh3PT0&' +
        'landing_sign=1kD6c0N6aYpMUS0wxnQjxzSqZlEB8qNFdxtdjYhwSuI';
    case 'file':
      return "https://mfr.osf.io/render?url=https://osf.io/" + videoID + "/?action=download"
    default:
      return service;
  }
}

function tokenizeVideo(md, options) {
  function tokenizeReturn(tokens, idx) {
    const videoID = md.utils.escapeHtml(tokens[idx].videoID);
    const service = md.utils.escapeHtml(tokens[idx].service).toLowerCase();
    var num;

    if (service === 'file') {
      num = Math.random() * 0x10000;
      return '

';
    }

    return videoID === '' ? '' :
      '

';
  }

  return tokenizeReturn;
}

const defaults = {
  url: videoUrl,
  youtube: { width: 640, height: 390 },
  vimeo: { width: 500, height: 281 },
  vine: { width: 600, height: 600, embed: 'simple' },
  prezi: { width: 550, height: 400 },
  file: { width: '100%', height: '100%' },
};

module.exports = function videoPlugin(md, options) {
  var theOptions = options;
  var theMd = md;
  if (theOptions) {
    Object.keys(defaults).forEach(function checkForKeys(key) {
      if (typeof theOptions[key] === 'undefined') {
        theOptions[key] = defaults[key];
      }
    });
  } else {
    theOptions = defaults;
  }
  theMd.renderer.rules.video = tokenizeVideo(theMd, theOptions);
  theMd.inline.ruler.before('emphasis', 'video', videoEmbed(theMd, theOptions));
};
<|endoftext|>


<commit_before>/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Famous Industries Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

module.exports = {
    components: require('./components'),
    core: require('./core'),
    engine: require('./engine'),
    domRenderables: require('./dom-renderables'),
    math: require('./math'),
    physics: require('./physics'),
    renderers: require('./renderers'),
    stylesheets: require('./stylesheets'),
    router: require('./router'),
    transitions: require('./transitions'),
    utilities: require('./utilities'),
    webglRenderables: require('./webgl-renderables'),
    webglGeometries: require('./webgl-geometries'),
    webglMaterials: require('./webgl-materials'),
    webglShaders: require('./webgl-shaders'),
    polyfills: require('./polyfills')
};
<commit_msg>chore: remove stale reference to the stylesheet<commit_after>/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Famous Industries Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

module.exports = {
    components: require('./components'),
    core: require('./core'),
    engine: require('./engine'),
    domRenderables: require('./dom-renderables'),
    math: require('./math'),
    physics: require('./physics'),
    renderers: require('./renderers'),
    router: require('./router'),
    transitions: require('./transitions'),
    utilities: require('./utilities'),
    webglRenderables: require('./webgl-renderables'),
    webglGeometries: require('./webgl-geometries'),
    webglMaterials: require('./webgl-materials'),
    webglShaders: require('./webgl-shaders'),
    polyfills: require('./polyfills')
};
<|endoftext|>


<commit_before>var through2 = require('through2')

module.exports = function createEventuateStream (eventuate) {
    var stream = through2.obj(function produceChunk (chunk, enc, cb) {
        eventuate.produce(chunk)
        cb()
    })

    eventuate(streamConsumer)
    stream.on('finish', cleanup)
    stream.on('end', cleanup)
    stream.on('error', cleanup) // should signalError here too

    return stream

    function streamConsumer (data) {
        stream.push(data)
    }

    function cleanup () {
        eventuate.removeConsumer(streamConsumer)
    }
}
<commit_msg>remove extraneous (for now) comments<commit_after>var through2 = require('through2')

module.exports = function createEventuateStream (eventuate) {
    var stream = through2.obj(function produceChunk (chunk, enc, cb) {
        eventuate.produce(chunk)
        cb()
    })

    eventuate(streamConsumer)
    stream.on('finish', cleanup)
    stream.on('end', cleanup)
    stream.on('error', cleanup)

    return stream

    function streamConsumer (data) {
        stream.push(data)
    }

    function cleanup () {
        eventuate.removeConsumer(streamConsumer)
    }
}
<|endoftext|>