<commit_before>(function() {

  function Queue() {

    // callback storage
    this._methods = [];

    // reference to the response
    this._response = null;

    // all queues start off unflushed
    this._flushed = false;

  };

  Queue.prototype = {

    // adds callbacks to the queue
    add: function(fn) {

      // if the queue had been flushed, return immediately
      if (this._flushed) {

        // otherwise push it on the queue
        fn(this._response);

      } else {
        this._methods.push(fn);
      }

    },

    flush: function(resp) {

      // flush only ever happens once
      if (this._flushed) {
        return;
      }

      // store the response for subsequent calls after flush()
      this._response = resp;

      // mark that it's been flushed
      this._flushed = true;

      // shift 'em out and call 'em back
      while (this._methods[0]) {
        this._methods.shift()(resp);
      }

    }

  };

  ImageModel = cdb.core.Model.extend({
    defaults: {
      format: "png",
      zoom: 10,
      center: [0, 0],
      size:  [320, 240],
      tiler_port: 80,
      tiler_domain: "cartodb.com"
    }
  });

  var Image = function() {

    var self = this;

    this.model = new ImageModel();

    this.layers = [];

    this.supported_formats = ["png", "jpg"];

    this.options = _.defaults({
      ajax: window.$ ? window.$.ajax : reqwest.compat,
      pngParams: ['map_key', 'api_key', 'cache_policy', 'updated_at'],
      gridParams: ['map_key', 'api_key', 'cache_policy', 'updated_at'],
      cors: this.isCORSSupported(),
      btoa: this.isBtoaSupported() ? this._encodeBase64Native : this._encodeBase64,
      MAX_GET_SIZE: 2033,
      force_cors: false,
      instanciateCallback: function() {
        return '_cdbc_' + self._callbackName();
      }
    });

    this.defaults = {
      tiler_domain: "cartodb.com",
      tiler_port: "80"
    };

    this.available_basemaps = ["light_all", "light_nolabels", "dark_all", "dark_nolabels"];

    this.layerToken = null;
    this.urls = null;
    this.silent = false;
    this.interactionEnabled = []; //TODO: refactor, include inside layer
    this._layerTokenQueue = [];
    this._timeout = -1;
    this._queue = [];
    this._waiting = false;
    this.lastTimeUpdated = null;
    this._refreshTimer = -1;

  };

  Image.prototype = _.extend({}, Map.prototype, {

    load: function(vizjson, options) {

      _.bindAll(this, "_onVisLoaded");

      this.queue = new Queue;

      options = _.defaults(options, { vizjson: vizjson, id: "s" + this._getUUID() }, this.model.defaults);

      this.model.set(options);

      cdb.image.Loader.get(vizjson, this._onVisLoaded);

      return this;

    },

    loadLayerDefinition: function(layerDefinition) {

      var self = this;

      this.queue = new Queue;

      if (!layerDefinition.user_name) {
        cartodb.log.error("Please, specify the username");
        return;
      }

      this.model.set({
        username: layerDefinition.user_name
      });

      this._generateEndpoint(layerDefinition.user_name, layerDefinition.tiler_port, layerDefinition.tiler_domain);

      this._getLayerGroupID(layerDefinition);

    },

    _generateEndpoint: function(username, port, domain) {

      if (parseInt(port, 10) === 80 || port === undefined) {
        port = "";
      } else {
        port = ":" + port;
      }

      domain ? domain : this.model.defaults.tiler_domain;

      this.model.set("endpoint", "http://" + username + "." + domain + port + "/api/v1/map");

    },

    _onVisLoaded: function(data) {

      if (data) {

        var layerDefinition;
        var baseLayer = data.layers[0];
        var dataLayer = data.layers[1];

        this._chooseBasemap(baseLayer.options);

        this.model.set({
          username: dataLayer.options.user_name,
          zoom: data.zoom,
          center: JSON.parse(data.center),
          bounds: data.bounds
        });

        if (dataLayer.type === "namedmap") {
          layerDefinition = this._getNamedmapLayerDefinition(dataLayer.options);
        } else {
          layerDefinition = this._getLayergroupLayerDefinition(dataLayer.options);
        }

        this._generateEndpoint(dataLayer.options.user_name, dataLayer.options.tiler_port, dataLayer.options.tiler_domain);
        this._getLayerGroupID(layerDefinition);

      }

    },

    _getLayerGroupID: function(layerDefinition) {

      var self = this;

      this._requestPOST(layerDefinition, function(data) {

        if (data) {
          self.model.set("layergroupid", data.layergroupid);
          self.queue.flush(this);
        }

      });

    },

    _getBasemapLayer: function() {

      return {
        type: "http",
        options: {
          urlTemplate: "http://{s}.basemaps.cartocdn.com/" + this.model.get("basemap") + "/{z}/{x}/{y}.png",
          subdomains: [ "a", "b", "c" ]
        }
      };

    },

    _getLayergroupLayerDefinition: function(options) {

      var layerDefinition = new LayerDefinition(options.layer_definition, options);

      var ld = layerDefinition.toJSON();

      // TODO: remove this
      for (var i = 0; i<ld.layers.length; i++) {
        delete ld.layers[i].options.interactivity
      }

      ld.layers.unshift(this._getBasemapLayer());

      return ld;

    },

    _getNamedmapLayerDefinition: function(options) {

      var layerDefinition = new NamedMap(options.named_map, options);

      layerDefinition.options.type = "named";

      var layers  =  [
        this._getBasemapLayer(), {
        type: "named",
        options: {
          name: layerDefinition.named_map.name
        }
      }];

      var ld = {
        layers: layers
      };

      return ld;

    },

    toJSON: function() {
      return this.layers[0];
    },

    _requestPOST: function(params, callback) {

      this.options.ajax({
        crossorigin: true,
        type: 'POST',
        method: 'POST',
        dataType: 'json',
        contentType: 'application/json',
        url: this.model.get("endpoint"),
        data: JSON.stringify(params),
        success: function(data) {
          callback(data);
        },
        error: function(xhr) {
          callback(null);
        }
      });

    },

    _tilerHost: function() {
      var opts = this.options;
      return opts.tiler_protocol +
        "://" + ((opts.user_name) ? opts.user_name+".":"")  +
      opts.tiler_domain +
        ((opts.tiler_port != "") ? (":" + opts.tiler_port) : "");
    },

    _host: function(subhost) {
      var opts = this.options;
      if (opts.no_cdn) {
        return this._tilerHost();
      } else {
        var h = opts.tiler_protocol + "://";
        if (subhost) {
          h += subhost + ".";
        }
        var cdn_host = opts.cdn_url || cdb.CDB_HOST;
        if(!cdn_host.http && !cdn_host.https) {
          throw new Error("cdn_host should contain http and/or https entries");
        }
        h += cdn_host[opts.tiler_protocol] + "/" + opts.user_name;
        return h;
      }
    },

    _getUrl: function() {

      var username     = this.model.get("username");
      var zoom         = this.model.get("zoom");
      var bbox         = this.model.get("bbox");
      var lat          = this.model.get("center")[0];
      var lon          = this.model.get("center")[1];
      var width        = this.model.get("size")[0];
      var height       = this.model.get("size")[1];
      var layergroupid = this.model.get("layergroupid");
      var format       = this.model.get("format");
      var endpoint     = this.model.get("endpoint");

      if (bbox) {
        return [endpoint, "static/bbox" , layergroupid, bbox[0].join(",") + "," + bbox[1].join(","), width, height + "." + format].join("/");
      } else {
        return [endpoint, "static/center" , layergroupid, zoom, lat, lon, width, height + "." + format].join("/");
      }

    },

    _chooseBasemap: function(basemap_layer) {

      if (this.model.get("basemap")) return;

      var type = basemap_layer.base_type;

      if (!_.include(this.available_basemaps, type)) {

        if (type && type.indexOf("toner") !== -1)      basemap = "dark_all";
        else if (type && type.indexOf("dark")  !== -1) basemap = "dark_all";
        else if (type && type.indexOf("night") !== -1) basemap = "dark_all";
        else if (type && type.indexOf("night") !== -1) basemap = "dark_all";
        else if (type && type.indexOf("light") !== -1) basemap = "light_all";
        else basemap = "light_all";

        this.model.set("basemap", basemap);

      }

    },

    // Generates a random string
    _getUUID: function() {
      var S4 = function() {
        return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
      };
      return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
    },

    /* Setters */
    _set: function(name, value) {

      var self = this;

      this.queue.add(function() {
        self.model.set(name,value);
      });

      return this;

    },

    zoom: function(zoom) {
      return this._set("zoom", zoom);
    },

    bbox: function(bbox) {
      return this._set("bbox", bbox);
    },

    center: function(center) {
      return this._set("center", center);
    },

    format: function(format) {
      return this._set("format", _.include(this.supported_formats, format) ? format : this.model.defaults.format);
    },

    size: function(width, height) {
      return this._set("size", [width, height === undefined ? width : height]);
    },

    /* Methods */

    /* Image.into(HTMLImageElement)
       inserts the image in the HTMLImageElement specified */
    into: function(img) {

      var self = this;

      if (!(img instanceof HTMLImageElement)) {
        cartodb.log.error("img should be an image");
        return;
      }

      this.model.set("size", [img.width, img.height]);

      this.queue.add(function(response) {
        img.src = self._getUrl();
      });

    },

    /* Image.getUrl(callback(err, url))
       gets the url for the image, err is null is there was no error */

    getUrl: function(callback) {

      var self = this;

      this.queue.add(function() {
        if (callback) {
          callback(null, self._getUrl()); // TODO: return the error
        }
      });

    },

    /* Image.write(attributes)
       adds a img tag in the same place script is executed */
      // TODO: document class, id and src attributes

    write: function(attributes) {

      var self = this;

      this.model.set("attributes", attributes);

      if (attributes && attributes.src) {
        document.write('');
      } else {
        document.write('');
      }

      this.queue.add(function() {

        var element = document.getElementById(self.model.get("id"));

        element.src = self._getUrl();
        element.removeAttribute("id");

        var attributes = self.model.get("attributes");

        if (attributes) {
          if (attributes.class) { element.setAttribute("class", attributes.class); }
          if (attributes.id)    { element.setAttribute("id", attributes.id); }
        }

      });

      return this;
    }

  })

  cdb.Image = function(data, options) {

    if (!options) options = {};

    var image = new Image();

    if (typeof data === 'string') {
      image.load(data, options);
    } else {
      image.loadLayerDefinition(data);
    }

    return image;

  };

  var ImageLoader = cdb.image.Loader = {

    queue: [],
    current: undefined,
    _script: null,
    head: null,

    loadScript: function(src) {
      var script = document.createElement('script');
      script.type = 'text/javascript';
      script.src = src;
      script.async = true;
      if (!ImageLoader.head) {
        ImageLoader.head = document.getElementsByTagName('head')[0];
      }
      // defer the loading because IE9 loads in the same frame the script
      // so Loader._script is null
      setTimeout(function() {
        ImageLoader.head.appendChild(script);
      }, 0);
      return script;
    },

    get: function(url, callback) {
      if (!ImageLoader._script) {
        ImageLoader.current = callback;
        ImageLoader._script = ImageLoader.loadScript(url + (~url.indexOf('?') ? '&' : '?') + 'callback=imgjson');
      } else {
        ImageLoader.queue.push([url, callback]);
      }
    },

    getPath: function(file) {
      var scripts = document.getElementsByTagName('script'),
      cartodbJsRe = /\/?cartodb[\-\._]?([\w\-\._]*)\.js\??/;
      for (i = 0, len = scripts.length; i < len; i++) {
        src = scripts[i].src;
        matches = src.match(cartodbJsRe);

        if (matches) {
          var bits = src.split('/');
          delete bits[bits.length - 1];
          return bits.join('/') + file;
        }
      }
      return null;
    },

    loadModule: function(modName) {
      var file = "cartodb.mod." + modName + (cartodb.DEBUG ? ".uncompressed.js" : ".js");
      var src = this.getPath(file);
      if (!src) {
        cartodb.log.error("can't find cartodb.js file");
      }
      ImageLoader.loadScript(src);
    }
  };

  window.imgjson = function(data) {
    ImageLoader.current && ImageLoader.current(data);
    // remove script
    ImageLoader.head.removeChild(ImageLoader._script);
    ImageLoader._script = null;
    // next element
    var a = ImageLoader.queue.shift();
    if (a) {
      ImageLoader.get(a[0], a[1]);
    }
  };
})();
<commit_msg>code refactor<commit_after>(function() {

  function Queue() {

    // callback storage
    this._methods = [];

    // reference to the response
    this._response = null;

    // all queues start off unflushed
    this._flushed = false;

  };

  Queue.prototype = {

    // adds callbacks to the queue
    add: function(fn) {

      // if the queue had been flushed, return immediately
      if (this._flushed) {

        // otherwise push it on the queue
        fn(this._response);

      } else {
        this._methods.push(fn);
      }

    },

    flush: function(resp) {

      // flush only ever happens once
      if (this._flushed) {
        return;
      }

      // store the response for subsequent calls after flush()
      this._response = resp;

      // mark that it's been flushed
      this._flushed = true;

      // shift 'em out and call 'em back
      while (this._methods[0]) {
        this._methods.shift()(resp);
      }

    }

  };

  ImageModel = cdb.core.Model.extend({
    defaults: {
      format: "png",
      zoom: 10,
      center: [0, 0],
      size:  [320, 240],
      tiler_port: 80,
      tiler_domain: "cartodb.com"
    }
  });

  var Image = function() {

    var self = this;

    this.model = new ImageModel();

    this.supported_formats = ["png", "jpg"];

    this.options = _.defaults({
      ajax: window.$ ? window.$.ajax : reqwest.compat,
      pngParams: ['map_key', 'api_key', 'cache_policy', 'updated_at'],
      gridParams: ['map_key', 'api_key', 'cache_policy', 'updated_at'],
      cors: this.isCORSSupported(),
      btoa: this.isBtoaSupported() ? this._encodeBase64Native : this._encodeBase64,
      MAX_GET_SIZE: 2033,
      force_cors: false,
      instanciateCallback: function() {
        return '_cdbc_' + self._callbackName();
      }
    });

    this.defaults = {
      tiler_domain: "cartodb.com",
      tiler_port: "80"
    };

    this.available_basemaps = ["light_all", "light_nolabels", "dark_all", "dark_nolabels"];

    this.layerToken = null;
    this.urls = null;
    this.silent = false;
    this.interactionEnabled = []; //TODO: refactor, include inside layer
    this._layerTokenQueue = [];
    this._timeout = -1;
    this._queue = [];
    this._waiting = false;
    this.lastTimeUpdated = null;
    this._refreshTimer = -1;

  };

  Image.prototype = _.extend({}, Map.prototype, {

    load: function(vizjson, options) {

      _.bindAll(this, "_onVisLoaded");

      this.queue = new Queue;

      options = _.defaults(options, { vizjson: vizjson, id: "s" + this._getUUID() }, this.model.defaults);

      this.model.set(options);

      cdb.image.Loader.get(vizjson, this._onVisLoaded);

      return this;

    },

    loadLayerDefinition: function(layerDefinition) {

      var self = this;

      this.queue = new Queue;

      if (!layerDefinition.user_name) {
        cartodb.log.error("Please, specify the username");
        return;
      }

      this.model.set({
        username: layerDefinition.user_name
      });

      this._generateEndpoint(layerDefinition.user_name, layerDefinition.tiler_port, layerDefinition.tiler_domain);
      this._getLayerGroupID(layerDefinition);

    },

    _generateEndpoint: function(username, port, domain) {

      if (parseInt(port, 10) === 80 || port === undefined) {
        port = "";
      } else {
        port = ":" + port;
      }

      if (domain === undefined) domain = this.model.defaults.tiler_domain;

      this.model.set("endpoint", "http://" + username + "." + domain + port + "/api/v1/map");

    },

    _onVisLoaded: function(data) {

      if (data) {

        var layerDefinition;
        var baseLayer = data.layers[0];
        var dataLayer = data.layers[1];

        this._chooseBasemap(baseLayer.options);

        this.model.set({
          username: dataLayer.options.user_name,
          zoom: data.zoom,
          center: JSON.parse(data.center),
          bounds: data.bounds
        });

        if (dataLayer.type === "namedmap") {
          layerDefinition = this._getNamedmapLayerDefinition(dataLayer.options);
        } else {
          layerDefinition = this._getLayergroupLayerDefinition(dataLayer.options);
        }

        this._generateEndpoint(dataLayer.options.user_name, dataLayer.options.tiler_port, dataLayer.options.tiler_domain);
        this._getLayerGroupID(layerDefinition);

      }

    },

    _getLayerGroupID: function(layerDefinition) {

      var self = this;

      this._requestPOST(layerDefinition, function(data) {

        if (data) {
          self.model.set("layergroupid", data.layergroupid);
          self.queue.flush(this);
        }

      });

    },

    _getBasemapLayer: function() {

      return {
        type: "http",
        options: {
          urlTemplate: "http://{s}.basemaps.cartocdn.com/" + this.model.get("basemap") + "/{z}/{x}/{y}.png",
          subdomains: [ "a", "b", "c" ]
        }
      };

    },

    _getLayergroupLayerDefinition: function(options) {

      var layerDefinition = new LayerDefinition(options.layer_definition, options);

      var ld = layerDefinition.toJSON();

      // TODO: remove this
      for (var i = 0; i<ld.layers.length; i++) {
        delete ld.layers[i].options.interactivity
      }

      ld.layers.unshift(this._getBasemapLayer());

      return ld;

    },

    _getNamedmapLayerDefinition: function(options) {

      var layerDefinition = new NamedMap(options.named_map, options);

      layerDefinition.options.type = "named";

      var layers  =  [
        this._getBasemapLayer(), {
        type: "named",
        options: {
          name: layerDefinition.named_map.name
        }
      }];

      var ld = {
        layers: layers
      };

      return ld;

    },

    _requestPOST: function(params, callback) {

      this.options.ajax({
        crossorigin: true,
        type: 'POST',
        method: 'POST',
        dataType: 'json',
        contentType: 'application/json',
        url: this.model.get("endpoint"),
        data: JSON.stringify(params),
        success: function(data) {
          callback(data);
        },
        error: function(xhr) {
          callback(null);
        }
      });

    },

    _tilerHost: function() {
      var opts = this.options;
      return opts.tiler_protocol +
        "://" + ((opts.user_name) ? opts.user_name+".":"")  +
      opts.tiler_domain +
        ((opts.tiler_port != "") ? (":" + opts.tiler_port) : "");
    },

    _host: function(subhost) {
      var opts = this.options;
      if (opts.no_cdn) {
        return this._tilerHost();
      } else {
        var h = opts.tiler_protocol + "://";
        if (subhost) {
          h += subhost + ".";
        }
        var cdn_host = opts.cdn_url || cdb.CDB_HOST;
        if(!cdn_host.http && !cdn_host.https) {
          throw new Error("cdn_host should contain http and/or https entries");
        }
        h += cdn_host[opts.tiler_protocol] + "/" + opts.user_name;
        return h;
      }
    },

    _getUrl: function() {

      var username     = this.model.get("username");
      var zoom         = this.model.get("zoom");
      var bbox         = this.model.get("bbox");
      var lat          = this.model.get("center")[0];
      var lon          = this.model.get("center")[1];
      var width        = this.model.get("size")[0];
      var height       = this.model.get("size")[1];
      var layergroupid = this.model.get("layergroupid");
      var format       = this.model.get("format");
      var endpoint     = this.model.get("endpoint");

      if (bbox) {
        return [endpoint, "static/bbox" , layergroupid, bbox[0].join(",") + "," + bbox[1].join(","), width, height + "." + format].join("/");
      } else {
        return [endpoint, "static/center" , layergroupid, zoom, lat, lon, width, height + "." + format].join("/");
      }

    },

    _chooseBasemap: function(basemap_layer) {

      if (this.model.get("basemap")) return;

      var type = basemap_layer.base_type;

      if (!_.include(this.available_basemaps, type)) {

        if (type && type.indexOf("toner") !== -1)      basemap = "dark_all";
        else if (type && type.indexOf("dark")  !== -1) basemap = "dark_all";
        else if (type && type.indexOf("night") !== -1) basemap = "dark_all";
        else if (type && type.indexOf("night") !== -1) basemap = "dark_all";
        else if (type && type.indexOf("light") !== -1) basemap = "light_all";
        else basemap = "light_all";

        this.model.set("basemap", basemap);

      }

    },

    // Generates a random string
    _getUUID: function() {
      var S4 = function() {
        return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
      };
      return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
    },

    /* Setters */
    _set: function(name, value) {

      var self = this;

      this.queue.add(function() {
        self.model.set(name,value);
      });

      return this;

    },

    zoom: function(zoom) {
      return this._set("zoom", zoom);
    },

    bbox: function(bbox) {
      return this._set("bbox", bbox);
    },

    center: function(center) {
      return this._set("center", center);
    },

    format: function(format) {
      return this._set("format", _.include(this.supported_formats, format) ? format : this.model.defaults.format);
    },

    size: function(width, height) {
      return this._set("size", [width, height === undefined ? width : height]);
    },

    /* Methods */

    /* Image.into(HTMLImageElement)
       inserts the image in the HTMLImageElement specified */
    into: function(img) {

      var self = this;

      if (!(img instanceof HTMLImageElement)) {
        cartodb.log.error("img should be an image");
        return;
      }

      this.model.set("size", [img.width, img.height]);

      this.queue.add(function(response) {
        img.src = self._getUrl();
      });

    },

    /* Image.getUrl(callback(err, url))
       gets the url for the image, err is null is there was no error */

    getUrl: function(callback) {

      var self = this;

      this.queue.add(function() {
        if (callback) {
          callback(null, self._getUrl()); // TODO: return the error
        }
      });

    },

    /* Image.write(attributes)
       adds a img tag in the same place script is executed */
      // TODO: document class, id and src attributes

    write: function(attributes) {

      var self = this;

      this.model.set("attributes", attributes);

      if (attributes && attributes.src) {
        document.write('');
      } else {
        document.write('');
      }

      this.queue.add(function() {

        var element = document.getElementById(self.model.get("id"));

        element.src = self._getUrl();
        element.removeAttribute("id");

        var attributes = self.model.get("attributes");

        if (attributes && attributes.class) { element.setAttribute("class", attributes.class); }
        if (attributes && attributes.id)    { element.setAttribute("id", attributes.id); }

      });

      return this;
    }

  })

  cdb.Image = function(data, options) {

    if (!options) options = {};

    var image = new Image();

    if (typeof data === 'string') {
      image.load(data, options);
    } else {
      image.loadLayerDefinition(data);
    }

    return image;

  };

  var ImageLoader = cdb.image.Loader = {

    queue: [],
    current: undefined,
    _script: null,
    head: null,

    loadScript: function(src) {
      var script = document.createElement('script');
      script.type = 'text/javascript';
      script.src = src;
      script.async = true;
      if (!ImageLoader.head) {
        ImageLoader.head = document.getElementsByTagName('head')[0];
      }
      // defer the loading because IE9 loads in the same frame the script
      // so Loader._script is null
      setTimeout(function() {
        ImageLoader.head.appendChild(script);
      }, 0);
      return script;
    },

    get: function(url, callback) {
      if (!ImageLoader._script) {
        ImageLoader.current = callback;
        ImageLoader._script = ImageLoader.loadScript(url + (~url.indexOf('?') ? '&' : '?') + 'callback=imgjson');
      } else {
        ImageLoader.queue.push([url, callback]);
      }
    },

    getPath: function(file) {
      var scripts = document.getElementsByTagName('script'),
      cartodbJsRe = /\/?cartodb[\-\._]?([\w\-\._]*)\.js\??/;
      for (i = 0, len = scripts.length; i < len; i++) {
        src = scripts[i].src;
        matches = src.match(cartodbJsRe);

        if (matches) {
          var bits = src.split('/');
          delete bits[bits.length - 1];
          return bits.join('/') + file;
        }
      }
      return null;
    },

    loadModule: function(modName) {
      var file = "cartodb.mod." + modName + (cartodb.DEBUG ? ".uncompressed.js" : ".js");
      var src = this.getPath(file);
      if (!src) {
        cartodb.log.error("can't find cartodb.js file");
      }
      ImageLoader.loadScript(src);
    }
  };

  window.imgjson = function(data) {
    ImageLoader.current && ImageLoader.current(data);
    // remove script
    ImageLoader.head.removeChild(ImageLoader._script);
    ImageLoader._script = null;
    // next element
    var a = ImageLoader.queue.shift();
    if (a) {
      ImageLoader.get(a[0], a[1]);
    }
  };
})();
<|endoftext|>


<commit_before>import Immutable, { List, Map, Set } from 'immutable';
import { isSmallScreen } from '../utils/media_utils';
import { endsWith } from '../utils/string_utils';
import { parseUrl } from '../utils/url_utils';
import * as i18n from '../i18n';
import trim from 'trim';
import * as gp from '../avatar/gravatar_provider';
import { dataFns } from '../utils/data_utils';

const {
  get,
  init,
  remove,
  reset,
  set,
  tget,
  tset,
  tremove
} = dataFns(["core"]);

export function setup(id, clientID, domain, options, logInCallback, hookRunner, emitEventFn) {
  let m = init(id, Immutable.fromJS({
    assetsUrl: extractAssetsUrlOption(options, domain),
    auth: extractAuthOptions(options),
    clientID: clientID,
    domain: domain,
    emitEventFn: emitEventFn,
    hookRunner: hookRunner,
    logInCallback: logInCallback,
    allowedConnections: Immutable.fromJS(options.allowedConnections || []),
    ui: extractUIOptions(id, options)
  }));

  m = i18n.initI18n(m);

  return m;
}

export function id(m) {
  return m.get("id");
}

export function clientID(m) {
  return get(m, "clientID");
}

export function domain(m) {
  return get(m, "domain");
}

export function assetsUrl(m) {
  return get(m, "assetsUrl");
}

export function setSubmitting(m, value, error = "") {
  m = tset(m, "submitting", value);
  m = clearGlobalSuccess(m);
  m = error && !value ? setGlobalError(m, error) : clearGlobalError(m);
  return m;
}

export function submitting(m) {
  return tget(m, "submitting", false);
}

export function setGlobalError(m, str) {
  return tset(m, "globalError", str);
}

export function globalError(m) {
  return tget(m, "globalError", "");
}

export function clearGlobalError(m) {
  return tremove(m, "globalError");
}

export function setGlobalSuccess(m, str) {
  return tset(m, "globalSuccess", str);
}

export function globalSuccess(m) {
  return tget(m, "globalSuccess", "");
}

export function clearGlobalSuccess(m) {
  return tremove(m, "globalSuccess");
}

export function rendering(m) {
  return tget(m, "render", false);
}

export function stopRendering(m) {
  return tremove(m, "render");
}

function extractUIOptions(id, options) {
  const closable = options.container ? false : undefined === options.closable ? true : !!options.closable;
  const theme = options.theme || {};
  const { logo, primaryColor } = theme;

  const avatar = options.avatar !== null;
  const customAvatarProvider = options.avatar
    && typeof options.avatar.url === "function"
    && typeof options.avatar.displayName === "function"
    && options.avatar;
  const avatarProvider = customAvatarProvider || gp;

  return new Immutable.fromJS({
    containerID: options.container || `auth0-lock-container-${id}`,
    appendContainer: !options.container,
    autoclose: undefined === options.autoclose ? false : closable && options.autoclose,
    autofocus: undefined === options.autofocus ? !(options.container || isSmallScreen()) : !!options.autofocus,
    avatar: avatar,
    avatarProvider: avatarProvider,
    logo: typeof logo === "string" ? logo : undefined,
    closable: closable,
    language: undefined === options.language ? "en" : trim(options.language || "").toLowerCase(),
    dict: typeof options.languageDictionary === "object" ? options.languageDictionary : {},
    disableWarnings: options.disableWarnings === undefined ? false : !!options.disableWarnings,
    mobile: undefined === options.mobile ? false : !!options.mobile,
    popupOptions: undefined === options.popupOptions ? {} : options.popupOptions,
    primaryColor: typeof primaryColor === "string" ? primaryColor : undefined,
    rememberLastLogin: undefined === options.rememberLastLogin ? true : !!options.rememberLastLogin
  });
}

const { get: getUIAttribute } = dataFns(["core", "ui"]);

export const ui = {
  containerID: lock => getUIAttribute(lock, "containerID"),
  appendContainer: lock => getUIAttribute(lock, "appendContainer"),
  autoclose: lock => getUIAttribute(lock, "autoclose"),
  autofocus: lock => getUIAttribute(lock, "autofocus"),
  avatar: lock => getUIAttribute(lock, "avatar"),
  avatarProvider: lock => getUIAttribute(lock, "avatarProvider"),
  closable: lock => getUIAttribute(lock, "closable"),
  dict: lock => getUIAttribute(lock, "dict"),
  disableWarnings: lock => getUIAttribute(lock, "disableWarnings"),
  language: lock => getUIAttribute(lock, "language"),
  logo: lock => getUIAttribute(lock, "logo"),
  mobile: lock => getUIAttribute(lock, "mobile"),
  popupOptions: lock => getUIAttribute(lock, "popupOptions"),
  primaryColor: lock => getUIAttribute(lock, "primaryColor"),
  rememberLastLogin: lock => getUIAttribute(lock, "rememberLastLogin")
};

const { get: getAuthAttribute } = dataFns(["core", "auth"]);

export const auth = {
  params: lock => getAuthAttribute(lock, "params"),
  redirect: lock => getAuthAttribute(lock, "redirect"),
  redirectUrl: lock => getAuthAttribute(lock, "redirectUrl"),
  responseType: lock => getAuthAttribute(lock, "responseType"),
  sso: lock => getAuthAttribute(lock, "sso")
};

function extractAuthOptions(options) {
  // TODO: shouldn't all options be namespased in authentication?
  let {
    params,
    redirect,
    redirectUrl,
    responseType,
    sso
  } = options.auth || {};

  params = typeof params === "object" ? params : {};
  redirectUrl = typeof redirectUrl === "string" && redirectUrl ? redirectUrl : undefined;
  redirect = typeof redirect === "boolean" ? redirect : true;
  responseType = typeof responseType === "string" ? responseType : redirectUrl ? "code" : "token";
  sso = typeof sso === "boolean" ? sso : true;

  if (trim(params.scope || "") === "openid profile") {
    warn(options, "Usage of scope 'openid profile' is not recommended. See https://auth0.com/docs/scopes for more details.");
  }

  return Immutable.fromJS({
    params,
    redirect,
    redirectUrl,
    responseType,
    sso
  });
}

export function withAuthOptions(m, opts) {
  return Immutable.fromJS(opts)
    .merge(get(m, "auth"))
    .toJS();
}

function extractAssetsUrlOption(opts, domain) {
  if (opts.assetsUrl && typeof opts.assetsUrl === "string") {
    return opts.assetsUrl;
  }

  const domainUrl = "https://" + domain;
  const hostname = parseUrl(domainUrl).hostname;
  const DOT_AUTH0_DOT_COM = ".auth0.com";
  const AUTH0_US_CDN_URL = "https://cdn.auth0.com";
  if (endsWith(hostname, DOT_AUTH0_DOT_COM)) {
    const parts = hostname.split(".");
    return parts.length > 3
      ? "https://cdn." + parts[parts.length - 3] + DOT_AUTH0_DOT_COM
      : AUTH0_US_CDN_URL;
  } else {
    return domainUrl;
  }
}

export function invokeLogInCallback(m, ...args) {
  get(m, "logInCallback").apply(undefined, args);
}

export function render(m) {
  return tset(m, "render", true);
}

export { reset };

export function setLoggedIn(m, value) {
  return tset(m, "loggedIn", value);
}

export function loggedIn(m) {
  return tget(m, "loggedIn", false);
}

export function warn(x, str) {
  const shouldOutput = Map.isMap(x)
    ? !ui.disableWarnings(x)
    : !x.disableWarnings;

  if (shouldOutput && console && console.warn) {
    console.warn(str);
  }
}

export function error(x, str) {
  const shouldOutput = Map.isMap(x)
    ? !ui.disableWarnings(x)
    : !x.disableWarnings;

  if (shouldOutput && console && console.error) {
    console.error(str);
  }
}

export function allowedConnections(m) {
  return get(m, "allowedConnections");
}

export function connections(m, type = undefined, ...strategies) {
  if (arguments.length === 1) {
    return get(m, "connections", Map())
      .filter((v, k) => k !== "unknown")
      .valueSeq()
      .flatten(true);
  }

  const xs = get(m, ["connections", type], List());
  return strategies.length > 0
    ? xs.filter(x => ~strategies.indexOf(x.get("strategy")))
    : xs;
}

export function connection(m, type = undefined, ...strategies) {
  return connections(m, type, ...strategies).get(0);
}

export function hasOneConnection(m, type = undefined) {
  const xs = connections(m);
  return xs.count() === 1 && (!type || xs.getIn([0, "type"]) === type);
}

export function hasOnlyConnections(m, type = undefined, ...strategies) {
  const all = connections(m).count();
  const filtered = connections(m, type, ...strategies).count();
  return all > 0 && all === filtered;
}

export function hasSomeConnections(m, type = undefined, ...strategies) {
  return connections(m, type, ...strategies).count() > 0;
}

export function findConnection(m, name) {
  return connections(m).find(m1 => m1.get("name") === name);
}

export function hasConnection(m, name) {
  return !!findConnection(m, name);
}

export function runHook(m, str, ...args) {
  return get(m, "hookRunner")(str, m, ...args);
}

export function emitEvent(m, str, ...args) {
  get(m, "emitEventFn")(str, ...args);
}

export function loginErrorMessage(m, error) {
  // NOTE: previous version of lock checked for status codes and, at
  // some point, if the status code was 401 it defaults to an
  // "invalid_user_password" error (actually the
  // "wrongEmailPasswordErrorText" dict entry) instead of checking
  // explicitly. We should figure out if there was a reason for that.

  if (error.status === 0) {
    return i18n.str(m, ["error", "login", "lock.network"]);
  }

  // Custom rule error (except blocked_user)
  if (error.code === "rule_error") {
    return error.description
      || i18n.str(m, ["error", "login", "lock.fallback"]);
  }

  return i18n.str(m, ["error", "login", error.error || error.code])
    || i18n.str(m, ["error", "login", "lock.fallback"]);
}

export function stop(m) {
  return set(m, "stopped", true);
}

export function hasStopped(m) {
  return get(m, "stopped");
}
<commit_msg>Allow to invoke the callback with an error<commit_after>import Immutable, { List, Map, Set } from 'immutable';
import { isSmallScreen } from '../utils/media_utils';
import { endsWith } from '../utils/string_utils';
import { parseUrl } from '../utils/url_utils';
import * as i18n from '../i18n';
import trim from 'trim';
import * as gp from '../avatar/gravatar_provider';
import { dataFns } from '../utils/data_utils';

const {
  get,
  init,
  remove,
  reset,
  set,
  tget,
  tset,
  tremove
} = dataFns(["core"]);

export function setup(id, clientID, domain, options, logInCallback, hookRunner, emitEventFn) {
  let m = init(id, Immutable.fromJS({
    assetsUrl: extractAssetsUrlOption(options, domain),
    auth: extractAuthOptions(options),
    clientID: clientID,
    domain: domain,
    emitEventFn: emitEventFn,
    hookRunner: hookRunner,
    logInCallback: logInCallback,
    allowedConnections: Immutable.fromJS(options.allowedConnections || []),
    ui: extractUIOptions(id, options)
  }));

  m = i18n.initI18n(m);

  return m;
}

export function id(m) {
  return m.get("id");
}

export function clientID(m) {
  return get(m, "clientID");
}

export function domain(m) {
  return get(m, "domain");
}

export function assetsUrl(m) {
  return get(m, "assetsUrl");
}

export function setSubmitting(m, value, error = "") {
  m = tset(m, "submitting", value);
  m = clearGlobalSuccess(m);
  m = error && !value ? setGlobalError(m, error) : clearGlobalError(m);
  return m;
}

export function submitting(m) {
  return tget(m, "submitting", false);
}

export function setGlobalError(m, str) {
  return tset(m, "globalError", str);
}

export function globalError(m) {
  return tget(m, "globalError", "");
}

export function clearGlobalError(m) {
  return tremove(m, "globalError");
}

export function setGlobalSuccess(m, str) {
  return tset(m, "globalSuccess", str);
}

export function globalSuccess(m) {
  return tget(m, "globalSuccess", "");
}

export function clearGlobalSuccess(m) {
  return tremove(m, "globalSuccess");
}

export function rendering(m) {
  return tget(m, "render", false);
}

export function stopRendering(m) {
  return tremove(m, "render");
}

function extractUIOptions(id, options) {
  const closable = options.container ? false : undefined === options.closable ? true : !!options.closable;
  const theme = options.theme || {};
  const { logo, primaryColor } = theme;

  const avatar = options.avatar !== null;
  const customAvatarProvider = options.avatar
    && typeof options.avatar.url === "function"
    && typeof options.avatar.displayName === "function"
    && options.avatar;
  const avatarProvider = customAvatarProvider || gp;

  return new Immutable.fromJS({
    containerID: options.container || `auth0-lock-container-${id}`,
    appendContainer: !options.container,
    autoclose: undefined === options.autoclose ? false : closable && options.autoclose,
    autofocus: undefined === options.autofocus ? !(options.container || isSmallScreen()) : !!options.autofocus,
    avatar: avatar,
    avatarProvider: avatarProvider,
    logo: typeof logo === "string" ? logo : undefined,
    closable: closable,
    language: undefined === options.language ? "en" : trim(options.language || "").toLowerCase(),
    dict: typeof options.languageDictionary === "object" ? options.languageDictionary : {},
    disableWarnings: options.disableWarnings === undefined ? false : !!options.disableWarnings,
    mobile: undefined === options.mobile ? false : !!options.mobile,
    popupOptions: undefined === options.popupOptions ? {} : options.popupOptions,
    primaryColor: typeof primaryColor === "string" ? primaryColor : undefined,
    rememberLastLogin: undefined === options.rememberLastLogin ? true : !!options.rememberLastLogin
  });
}

const { get: getUIAttribute } = dataFns(["core", "ui"]);

export const ui = {
  containerID: lock => getUIAttribute(lock, "containerID"),
  appendContainer: lock => getUIAttribute(lock, "appendContainer"),
  autoclose: lock => getUIAttribute(lock, "autoclose"),
  autofocus: lock => getUIAttribute(lock, "autofocus"),
  avatar: lock => getUIAttribute(lock, "avatar"),
  avatarProvider: lock => getUIAttribute(lock, "avatarProvider"),
  closable: lock => getUIAttribute(lock, "closable"),
  dict: lock => getUIAttribute(lock, "dict"),
  disableWarnings: lock => getUIAttribute(lock, "disableWarnings"),
  language: lock => getUIAttribute(lock, "language"),
  logo: lock => getUIAttribute(lock, "logo"),
  mobile: lock => getUIAttribute(lock, "mobile"),
  popupOptions: lock => getUIAttribute(lock, "popupOptions"),
  primaryColor: lock => getUIAttribute(lock, "primaryColor"),
  rememberLastLogin: lock => getUIAttribute(lock, "rememberLastLogin")
};

const { get: getAuthAttribute } = dataFns(["core", "auth"]);

export const auth = {
  params: lock => getAuthAttribute(lock, "params"),
  redirect: lock => getAuthAttribute(lock, "redirect"),
  redirectUrl: lock => getAuthAttribute(lock, "redirectUrl"),
  responseType: lock => getAuthAttribute(lock, "responseType"),
  sso: lock => getAuthAttribute(lock, "sso")
};

function extractAuthOptions(options) {
  // TODO: shouldn't all options be namespased in authentication?
  let {
    params,
    redirect,
    redirectUrl,
    responseType,
    sso
  } = options.auth || {};

  params = typeof params === "object" ? params : {};
  redirectUrl = typeof redirectUrl === "string" && redirectUrl ? redirectUrl : undefined;
  redirect = typeof redirect === "boolean" ? redirect : true;
  responseType = typeof responseType === "string" ? responseType : redirectUrl ? "code" : "token";
  sso = typeof sso === "boolean" ? sso : true;

  if (trim(params.scope || "") === "openid profile") {
    warn(options, "Usage of scope 'openid profile' is not recommended. See https://auth0.com/docs/scopes for more details.");
  }

  return Immutable.fromJS({
    params,
    redirect,
    redirectUrl,
    responseType,
    sso
  });
}

export function withAuthOptions(m, opts) {
  return Immutable.fromJS(opts)
    .merge(get(m, "auth"))
    .toJS();
}

function extractAssetsUrlOption(opts, domain) {
  if (opts.assetsUrl && typeof opts.assetsUrl === "string") {
    return opts.assetsUrl;
  }

  const domainUrl = "https://" + domain;
  const hostname = parseUrl(domainUrl).hostname;
  const DOT_AUTH0_DOT_COM = ".auth0.com";
  const AUTH0_US_CDN_URL = "https://cdn.auth0.com";
  if (endsWith(hostname, DOT_AUTH0_DOT_COM)) {
    const parts = hostname.split(".");
    return parts.length > 3
      ? "https://cdn." + parts[parts.length - 3] + DOT_AUTH0_DOT_COM
      : AUTH0_US_CDN_URL;
  } else {
    return domainUrl;
  }
}

export function invokeLogInCallback(m, ...args) {
  get(m, "logInCallback").apply(undefined, args);
}

export function render(m) {
  return tset(m, "render", true);
}

export { reset };

export function setLoggedIn(m, value) {
  return tset(m, "loggedIn", value);
}

export function loggedIn(m) {
  return tget(m, "loggedIn", false);
}

export function warn(x, str) {
  const shouldOutput = Map.isMap(x)
    ? !ui.disableWarnings(x)
    : !x.disableWarnings;

  if (shouldOutput && console && console.warn) {
    console.warn(str);
  }
}

export function error(x, str) {
  const shouldOutput = Map.isMap(x)
    ? !ui.disableWarnings(x)
    : !x.disableWarnings;

  if (shouldOutput && console && console.error) {
    console.error(str);
  }
}

export function allowedConnections(m) {
  return get(m, "allowedConnections");
}

export function connections(m, type = undefined, ...strategies) {
  if (arguments.length === 1) {
    return get(m, "connections", Map())
      .filter((v, k) => k !== "unknown")
      .valueSeq()
      .flatten(true);
  }

  const xs = get(m, ["connections", type], List());
  return strategies.length > 0
    ? xs.filter(x => ~strategies.indexOf(x.get("strategy")))
    : xs;
}

export function connection(m, type = undefined, ...strategies) {
  return connections(m, type, ...strategies).get(0);
}

export function hasOneConnection(m, type = undefined) {
  const xs = connections(m);
  return xs.count() === 1 && (!type || xs.getIn([0, "type"]) === type);
}

export function hasOnlyConnections(m, type = undefined, ...strategies) {
  const all = connections(m).count();
  const filtered = connections(m, type, ...strategies).count();
  return all > 0 && all === filtered;
}

export function hasSomeConnections(m, type = undefined, ...strategies) {
  return connections(m, type, ...strategies).count() > 0;
}

export function findConnection(m, name) {
  return connections(m).find(m1 => m1.get("name") === name);
}

export function hasConnection(m, name) {
  return !!findConnection(m, name);
}

export function runHook(m, str, ...args) {
  return get(m, "hookRunner")(str, m, ...args);
}

export function emitEvent(m, str, ...args) {
  get(m, "emitEventFn")(str, ...args);
}

export function loginErrorMessage(m, error) {
  // NOTE: previous version of lock checked for status codes and, at
  // some point, if the status code was 401 it defaults to an
  // "invalid_user_password" error (actually the
  // "wrongEmailPasswordErrorText" dict entry) instead of checking
  // explicitly. We should figure out if there was a reason for that.

  if (error.status === 0) {
    return i18n.str(m, ["error", "login", "lock.network"]);
  }

  // Custom rule error (except blocked_user)
  if (error.code === "rule_error") {
    return error.description
      || i18n.str(m, ["error", "login", "lock.fallback"]);
  }

  return i18n.str(m, ["error", "login", error.error || error.code])
    || i18n.str(m, ["error", "login", "lock.fallback"]);
}

// TODO: rename to something less generic that is easier to grep
export function stop(m, error) {
  if (error) {
    setTimeout(() => invokeLogInCallback(m, error), 0);
  }

  return set(m, "stopped", true);
}

export function hasStopped(m) {
  return get(m, "stopped");
}
<|endoftext|>


<commit_before>export const patterns = [{
	name:"Date in format dd/mm/yyyy",
	regex:/^(0?[1-9]|[12][0-9]|3[01])([ /\-])(0?[1-9]|1[012])\2([0-9][0-9][0-9][0-9])$/,
	description:"Will match dates with dashes, slashes or with spaces dd-mm-yyyy dd/mm/yyyy dd mm yyyy",
	tags:"date,time"
},
{
	name:"Time in 24-hour format",
	regex:/([01]?[0-9]|2[0-3]):[0-5][0-9]/,
	description: "Match times in 24 hour format",
	tags:"date,time"
},
{
	name: "Date and time in ISO-8601 format",
	regex: /^(?![+-]?\d{4,5}-?(?:\d{2}|W\d{2})T)(?:|(\d{4}|[+-]\d{5})-?(?:|(0\d|1[0-2])(?:|-?([0-2]\d|3[0-1]))|([0-2]\d{2}|3[0-5]\d|36[0-6])|W([0-4]\d|5[0-3])(?:|-?([1-7])))(?:(?!\d)|T(?=\d)))(?:|([01]\d|2[0-4])(?:|:?([0-5]\d)(?:|:?([0-5]\d)(?:|\.(\d{3})))(?:|[zZ]|([+-](?:[01]\d|2[0-4]))(?:|:?([0-5]\d)))))$/,
	description: "Will match a valid date and times in the ISO-8601 format, excludes durations.",
	tags: "date,time"
},
{
	name:"HTML tags",
	regex:/^<([a-z1-6]+)([^<]+)*(?:>(.*)<\/\1>| *\/>)$/,
	description:"Match opening and closing HTML tags with content between",
	tags:"markup,xml,html"
},
{
	name:"Username",
	regex:/^[a-zA-Z0-9_-]{3,16}$/,
	description:"A string between 3 and 16 characters, allowing alphanumeric characters and hyphens and underscores",
	tags:"username,validation"
},
{
	name:"Hex Color Value",
	regex:/^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/,
	description:"RGB hex colors",
	tags:"hex,color"
},
{
	name:"URL Slug",
	regex:/^[a-z0-9-]+$/,
	description:"Match valid URL slugs",
	tags:"URL"
},
{
	name:"Email",
	regex:/^.+@.+$/,
	description:"Verify that there is an @ symbol with something before it",
	tags:"email,validation"
},
{
	name:"SRC of image tag",
	regex:/^<\s*img[^>]+src\s*=\s*(["'])(.*?)\1[^>]*>$/,
	description:"Match the src attribute of an HTML image tag",
	tags:"html,tag,image"
},
{
	name:"URL",
	regex:/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/,
	description:"Match URL with optional protocal",
	tags:"url,address,http"
},
{
	name:"IPv4 Address",
	regex:/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,
	description:"Match IP v4 addresses",
	tags:"tcpip,internet,address"
},
{
	name:"IPv6 Address",
	regex:/^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/,
	description: "Match IP v6 addresses",
	tags:"tcpip,internet,address"
},
{
	name:"Positive Integer",
	regex:/^\d+$/,
	descriptions:"Match whole numbers above zero",
	tags:"number"
},
{
	name:"Negative Integer",
	regex:/^-\d+$/,
	description:"Match whole numbers below zero",
	tags:"number"
},
{
	name:"Integer",
	regex:/^-?\d+$/,
	description:"Match whole numbers, above or below zero",
	tags:"number"
},
{
	name:"Positive number",
	regex:/^\d*\.?\d+$/,
	description:"Match integers or floats that are positive",
	tags:"float"
},
{
	name:"Negative number",
	regex:/^-\d*\.?\d+$/,
	description:"Match integers or floats that are negative",
	tags:"float"
},
{
	name:"Positive or negative number",
	regex:/^-?\d*\.?\d+$/,
	description:"Match integers or floats that are positive or negative",
	tags:"float"
},
{
	name:"Phone number",
	regex:/^\+?[\d\s]{3,}$/,
	description:"Match phone numbers at least 3 digits long",
	tags:"validation"
},
{
	name:"New line",
	regex:/[\r\n]|$/,
	description:"Match new lines within text",
	tags:"text"
},
{
	name:"ID of Youtube video",
	regex:/https?:\/\/(?:youtu\.be\/|(?:[a-z]{2,3}\.)?youtube\.com\/watch(?:\?|#\!)v=)([\w-]{11}).*/gi,
	description:"Match the ID of a youtube video URL",
	tags:"video,youtube,url"
},
{
	name:"ID of Youtube Channel",
	regex:/https?:\/\/(www\.)?youtube.com\/channel\/UC([-_a-z0-9]{22})/i,
	description:"Match the ID of a youtube channel URL",
	tags:"channel,youtube,url"
},
{
	name:"CSS comment",
	regex:/\/\*[^*]*\*+([^/*][^*]*\*+)*\//,
	description:"Match standard CSS comments",
	tags:"css,comment,code"
},
{
	name:"Wordpress shortcodes",
	regex:/^\[([a-z-_0-9]+)([^\[]+)*(?:\](.*)\[\/\1\]|\s+\/\])$/,
	description:"Matches opening and closing shortcode tags with content in-between them.",
	tags:"wordpress,shortcodes,markup"
},
{
	name:"U.S./Canadian ZIP/Postal Code",
	regex:/(^\d{5}(-\d{4})?$)|(^[ABCEGHJKLMNPRSTVXY]{1}\d{1}[A-Z]{1} *\d{1}[A-Z]{1}\d{1}$)/,
	description:"Matches US ZIP, ZIP+4, and Canadian Postal Codes",
	tags:"address, postal, zip"
},
{
	name:"Morse Code",
	regex:/^[.-]{1,5}(?:[ \t]+[.-]{1,5})*(?:[ \t]+[.-]{1,5}(?:[ \t]+[.-]{1,5})*)*$/,
	description:"Matches valid Morse Code",
	tags:"morse, code"
},
{
	name:"Image shortcode",
	regex:/\[img\](.*?)\[\/img\]/,
	description:"Matches the content in between [img][/img]. Useful for making dynamic WYSIWYG editors",
	tags:"img, shortcode, wysiwyg"
}
];
<commit_msg>fix phone number<commit_after>export const patterns = [{
	name:"Date in format dd/mm/yyyy",
	regex:/^(0?[1-9]|[12][0-9]|3[01])([ /\-])(0?[1-9]|1[012])\2([0-9][0-9][0-9][0-9])$/,
	description:"Will match dates with dashes, slashes or with spaces dd-mm-yyyy dd/mm/yyyy dd mm yyyy",
	tags:"date,time"
},
{
	name:"Time in 24-hour format",
	regex:/([01]?[0-9]|2[0-3]):[0-5][0-9]/,
	description: "Match times in 24 hour format",
	tags:"date,time"
},
{
	name: "Date and time in ISO-8601 format",
	regex: /^(?![+-]?\d{4,5}-?(?:\d{2}|W\d{2})T)(?:|(\d{4}|[+-]\d{5})-?(?:|(0\d|1[0-2])(?:|-?([0-2]\d|3[0-1]))|([0-2]\d{2}|3[0-5]\d|36[0-6])|W([0-4]\d|5[0-3])(?:|-?([1-7])))(?:(?!\d)|T(?=\d)))(?:|([01]\d|2[0-4])(?:|:?([0-5]\d)(?:|:?([0-5]\d)(?:|\.(\d{3})))(?:|[zZ]|([+-](?:[01]\d|2[0-4]))(?:|:?([0-5]\d)))))$/,
	description: "Will match a valid date and times in the ISO-8601 format, excludes durations.",
	tags: "date,time"
},
{
	name:"HTML tags",
	regex:/^<([a-z1-6]+)([^<]+)*(?:>(.*)<\/\1>| *\/>)$/,
	description:"Match opening and closing HTML tags with content between",
	tags:"markup,xml,html"
},
{
	name:"Username",
	regex:/^[a-zA-Z0-9_-]{3,16}$/,
	description:"A string between 3 and 16 characters, allowing alphanumeric characters and hyphens and underscores",
	tags:"username,validation"
},
{
	name:"Hex Color Value",
	regex:/^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/,
	description:"RGB hex colors",
	tags:"hex,color"
},
{
	name:"URL Slug",
	regex:/^[a-z0-9-]+$/,
	description:"Match valid URL slugs",
	tags:"URL"
},
{
	name:"Email",
	regex:/^.+@.+$/,
	description:"Verify that there is an @ symbol with something before it",
	tags:"email,validation"
},
{
	name:"SRC of image tag",
	regex:/^<\s*img[^>]+src\s*=\s*(["'])(.*?)\1[^>]*>$/,
	description:"Match the src attribute of an HTML image tag",
	tags:"html,tag,image"
},
{
	name:"URL",
	regex:/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/,
	description:"Match URL with optional protocal",
	tags:"url,address,http"
},
{
	name:"IPv4 Address",
	regex:/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,
	description:"Match IP v4 addresses",
	tags:"tcpip,internet,address"
},
{
	name:"IPv6 Address",
	regex:/^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/,
	description: "Match IP v6 addresses",
	tags:"tcpip,internet,address"
},
{
	name:"Positive Integer",
	regex:/^\d+$/,
	descriptions:"Match whole numbers above zero",
	tags:"number"
},
{
	name:"Negative Integer",
	regex:/^-\d+$/,
	description:"Match whole numbers below zero",
	tags:"number"
},
{
	name:"Integer",
	regex:/^-?\d+$/,
	description:"Match whole numbers, above or below zero",
	tags:"number"
},
{
	name:"Positive number",
	regex:/^\d*\.?\d+$/,
	description:"Match integers or floats that are positive",
	tags:"float"
},
{
	name:"Negative number",
	regex:/^-\d*\.?\d+$/,
	description:"Match integers or floats that are negative",
	tags:"float"
},
{
	name:"Positive or negative number",
	regex:/^-?\d*\.?\d+$/,
	description:"Match integers or floats that are positive or negative",
	tags:"float"
},
{
	name:"Phone number",
	regex:/^\+?(\d.*){3,}$/,
	description:"Match phone numbers at least 3 digits long",
	tags:"validation"
},
{
	name:"New line",
	regex:/[\r\n]|$/,
	description:"Match new lines within text",
	tags:"text"
},
{
	name:"ID of Youtube video",
	regex:/https?:\/\/(?:youtu\.be\/|(?:[a-z]{2,3}\.)?youtube\.com\/watch(?:\?|#\!)v=)([\w-]{11}).*/gi,
	description:"Match the ID of a youtube video URL",
	tags:"video,youtube,url"
},
{
	name:"ID of Youtube Channel",
	regex:/https?:\/\/(www\.)?youtube.com\/channel\/UC([-_a-z0-9]{22})/i,
	description:"Match the ID of a youtube channel URL",
	tags:"channel,youtube,url"
},
{
	name:"CSS comment",
	regex:/\/\*[^*]*\*+([^/*][^*]*\*+)*\//,
	description:"Match standard CSS comments",
	tags:"css,comment,code"
},
{
	name:"Wordpress shortcodes",
	regex:/^\[([a-z-_0-9]+)([^\[]+)*(?:\](.*)\[\/\1\]|\s+\/\])$/,
	description:"Matches opening and closing shortcode tags with content in-between them.",
	tags:"wordpress,shortcodes,markup"
},
{
	name:"U.S./Canadian ZIP/Postal Code",
	regex:/(^\d{5}(-\d{4})?$)|(^[ABCEGHJKLMNPRSTVXY]{1}\d{1}[A-Z]{1} *\d{1}[A-Z]{1}\d{1}$)/,
	description:"Matches US ZIP, ZIP+4, and Canadian Postal Codes",
	tags:"address, postal, zip"
},
{
	name:"Morse Code",
	regex:/^[.-]{1,5}(?:[ \t]+[.-]{1,5})*(?:[ \t]+[.-]{1,5}(?:[ \t]+[.-]{1,5})*)*$/,
	description:"Matches valid Morse Code",
	tags:"morse, code"
},
{
	name:"Image shortcode",
	regex:/\[img\](.*?)\[\/img\]/,
	description:"Matches the content in between [img][/img]. Useful for making dynamic WYSIWYG editors",
	tags:"img, shortcode, wysiwyg"
}
];
<|endoftext|>


<commit_before>// **Github:** https://github.com/teambition/ilog
//
// **License:** MIT
'use strict'

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

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

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

ilog.display = true
ilog.level = 7
ilog.levels = levels.slice()

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

      error.name = ccase(level)

      if (ilog.display) {
        // reformatting output for jcolorz
        // error = ilog._stringify(ilog._errorify(error))
        error = ilog._errorify(error)

        ilog._stderr.write(ilog._assembleLog(error.message, level, ilog._time(new Date())))
        jlog(error)
      }

      else {
        error = ilog._stringify(ilog._errorify(error))
        ilog._stderr.write(ilog._assembleLog(error, level, ilog._time(new Date())))
      }
    }
  }
})

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

ilog.debug = function () {
  // ilog.level === -1 turns off all levels
  // ilog.level === -2 turns on debug logging
  if (arguments.length && (ilog.level >= 7 || ilog.level === -2)) {
    let messages

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

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

    else messages = format.apply(null, arguments)

    ilog._stdout.write(ilog._assembleLog(messages, 'DEBUG', ilog._time(new Date())))
    if (stack) jlog(stack)
  }
}

ilog.trace = function () {
  if (arguments.length && ilog.level >= 8) {
    let messages = format.apply(null, arguments)

    ilog._stdout.write(ilog._assembleLog(messages, 'TRACE', ilog._time(new Date())))
  }
}

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

ilog.log = ilog
ilog._stdout = process.stdout
ilog._stderr = process.stderr
ilog._procname = process.argv[1].split('/').pop()

ilog._time = function (time) {
  return `${ilog._procname} »`
  // making generic
  // return `[${time.toISOString()}]`
}

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

ilog._assembleLog = function (log, level, time) {
  if (level) log = `${level} ${log}`

  // doing this to enable "time" to be configured as
  // a generic component prompt
  if (time) log = `${time} ${log}\n`
  else log = `${ilog._time()} ${log}\n`

  return log
}

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

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

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

module.exports = ilog<commit_msg>update debug/ilog<commit_after>// **Github:** https://github.com/teambition/ilog
//
// **License:** MIT
'use strict'

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

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

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

ilog.display = true
ilog.level = 7
ilog.levels = levels.slice()

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

      error.name = ccase(level)

      if (ilog.display) {
        // reformatting output for jcolorz
        // error = ilog._stringify(ilog._errorify(error))
        error = ilog._errorify(error)

        ilog._stderr.write(ilog._assembleLog(error.message, '\u001b[31m'+level+'\u001b[39m', ilog._time(new Date())))
        jlog(error)
      }

      else {
        error = ilog._stringify(ilog._errorify(error))
        ilog._stderr.write(ilog._assembleLog(error, level, ilog._time(new Date())))
      }
    }
  }
})

// ilog.notice, ilog.info
levels.slice(5, 7).map((level, index) => {
  index += 5
  ilog[level.toLowerCase()] = function (message) {
    if (message != null && index <= ilog.level) {
      message = ilog._stringify(message)
      ilog._stdout.write(ilog._assembleLog(message, '\u001b[90m'+level+'\u001b[39m', ilog._time(new Date())))
    }
  }
})

ilog.debug = function () {
  // ilog.level === -1 turns off all levels
  // ilog.level === -2 turns on debug logging
  if (arguments.length && (ilog.level >= 7 || ilog.level === -2)) {
    let messages

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

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

    else messages = format.apply(null, arguments)

    ilog._stdout.write(ilog._assembleLog(messages, '\u001b[34mDEBUG\u001b[39m', ilog._time(new Date())))
    if (stack) jlog(stack)
  }
}

ilog.trace = function () {
  if (arguments.length && ilog.level >= 8) {
    let messages = format.apply(null, arguments)

    ilog._stdout.write(ilog._assembleLog(messages, 'TRACE', ilog._time(new Date())))
  }
}

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

ilog.log = ilog
ilog._stdout = process.stdout
ilog._stderr = process.stderr
ilog._procname = process.argv[1].split('/').pop()

ilog._time = function (time) {
  return `${ilog._procname} »`
  // making generic
  // return `[${time.toISOString()}]`
}

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

ilog._assembleLog = function (log, level, time) {
  if (level) log = `${level} ${log}`

  // doing this to enable "time" to be configured as
  // a generic component prompt
  if (time) log = `${time} ${log}\n`
  else log = `${ilog._time()} ${log}\n`

  return log
}

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

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

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

module.exports = ilog
<|endoftext|>


<commit_before>import React, {Component, PropTypes} from 'react';
import lodash from 'lodash';
import {EventEmitter} from 'events';

export function listeningTo(propNames, eventMapping) {
    if (typeof eventMapping === 'function') {
        eventMapping = {'init change': eventMapping};
    }

    return decorator;

    function decorator(ChildComponent) {
        class ListeningContainerComponent extends Component {
            static propTypes = genPropTypes(propNames);

            static Original = ChildComponent;
            static displayName = `ListeningContainerComponent(${ChildComponent.displayName || ChildComponent.name})`;

            getEmitters(props) {
                return lodash.map(propNames, propName => props[propName]);
            }

            componentWillMount() {
                this.fireEvent('init');
            }

            componentDidMount() {
                this.startListening(this.getEmitters(this.props));
            }

            startListening(emitters) {
                lodash.each(emitters, emitter => {
                    lodash.each(this.eventHandlers, ({eventName, handler}) => {
                        emitter.on(eventName, handler);
                    });
                });
            }

            componentWillUnmount() {
                this.stopListening(this.getEmitters(this.props));
            }

            stopListening(emitters) {
                lodash.each(emitters, emitter => {
                    lodash.each(this.eventHandlers, ({eventName, handler}) => {
                        emitter.removeListener(eventName, handler);
                    });
                });
            }

            componentWillReceiveProps(nextProps) {
                this.stopListening(this.getEmitters(this.props));
                this.startListening(this.getEmitters(nextProps));
            }

            constructor(props, context) {
                super(props, context);

                this.state = {
                    childProps: {}
                };

                this.eventHandlers = this.generateHandlers();
            }

            fireEvent(eventName, event) {
                lodash.chain(this.eventHandlers)
                    .where({eventName})
                    .forEach(({handler}) => {
                        handler(event);
                    })
                    .commit();
            }

            handleEvent(eventName, event, getter) {
                const component = this.refs.child;

                const newProps = getter(this.props, event, component);

                // if the getter returns null/undefined, ignore it's result
                if (newProps) {
                    this.setState(({childProps}) => {
                        return {
                            childProps: {...childProps, ...newProps}
                        };
                    });
                }
            }

            generateHandlers() {
                return lodash.chain(eventMapping)
                    .map((getter, key) => {
                        return lodash.map(key.split(' '), eventName => {
                            return {
                                eventName,
                                handler: (event) => {
                                    this.handleEvent(eventName, event, getter);
                                }
                            };
                        });
                    })
                    .flatten()
                    .value();
            }

            render() {
                const {childProps} = this.state;

                return (
                    <ChildComponent
                        {...this.props}
                        {...childProps}
                        ref="child"
                    />
                );
            }
        }

        return ListeningContainerComponent;
    }

    function genPropTypes(propNames) {
        return lodash.zipObject(lodash.map(propNames, propName => {
            return [propName, emitterPropType];
        }));
    }

    function emitterPropType(props, propName, componentName) {
        if (props[propName] instanceof EventEmitter) {
            return;
        } else if (props[propName] != null && typeof props[propName].on === 'function') {
            return;
        } else {
            return new TypeError(`Required prop "${propName}" is no a valid event emitter`);
        }
    }
}
<commit_msg>Reinitialize when props change<commit_after>import React, {Component, PropTypes} from 'react';
import lodash from 'lodash';
import {EventEmitter} from 'events';

export function listeningTo(propNames, eventMapping) {
    if (typeof eventMapping === 'function') {
        eventMapping = {'init change': eventMapping};
    }

    return decorator;

    function decorator(ChildComponent) {
        class ListeningContainerComponent extends Component {
            static propTypes = genPropTypes(propNames);

            static Original = ChildComponent;
            static displayName = `ListeningContainerComponent(${ChildComponent.displayName || ChildComponent.name})`;

            getEmitters(props) {
                return lodash.map(propNames, propName => props[propName]);
            }

            componentWillMount() {
                this.fireEvent('init');
            }

            componentDidMount() {
                this.startListening(this.getEmitters(this.props));
            }

            startListening(emitters) {
                lodash.each(emitters, emitter => {
                    lodash.each(this.eventHandlers, ({eventName, handler}) => {
                        emitter.on(eventName, handler);
                    });
                });
            }

            componentWillUnmount() {
                this.stopListening(this.getEmitters(this.props));
            }

            stopListening(emitters) {
                lodash.each(emitters, emitter => {
                    lodash.each(this.eventHandlers, ({eventName, handler}) => {
                        emitter.removeListener(eventName, handler);
                    });
                });
            }

            componentWillReceiveProps(nextProps) {
                this.stopListening(this.getEmitters(this.props));
                this.startListening(this.getEmitters(nextProps));
                this.fireEvent('init', nextProps);
            }

            constructor(props, context) {
                super(props, context);

                this.state = {
                    childProps: {}
                };

                this.eventHandlers = this.generateHandlers();
            }

            fireEvent(eventName, event, props) {
                lodash.chain(this.eventHandlers)
                    .where({eventName})
                    .forEach(({handler}) => {
                        handler(event, props);
                    })
                    .commit();
            }

            handleEvent(eventName, event, getter, props = this.props) {
                const component = this.refs.child;

                const newProps = getter(props, event, component);

                // if the getter returns null/undefined, ignore it's result
                if (newProps) {
                    this.setState(({childProps}) => {
                        return {
                            childProps: {...childProps, ...newProps}
                        };
                    });
                }
            }

            generateHandlers() {
                return lodash.chain(eventMapping)
                    .map((getter, key) => {
                        return lodash.map(key.split(' '), eventName => {
                            return {
                                eventName,
                                handler: (event, props) => {
                                    this.handleEvent(eventName, event, getter, props);
                                }
                            };
                        });
                    })
                    .flatten()
                    .value();
            }

            render() {
                const {childProps} = this.state;

                return (
                    <ChildComponent
                        {...this.props}
                        {...childProps}
                        ref="child"
                    />
                );
            }
        }

        return ListeningContainerComponent;
    }

    function genPropTypes(propNames) {
        return lodash.zipObject(lodash.map(propNames, propName => {
            return [propName, emitterPropType];
        }));
    }

    function emitterPropType(props, propName, componentName) {
        if (props[propName] instanceof EventEmitter) {
            return;
        } else if (props[propName] != null && typeof props[propName].on === 'function') {
            return;
        } else {
            return new TypeError(`Required prop "${propName}" is no a valid event emitter`);
        }
    }
}
<|endoftext|>


<commit_before>import { IS_NON_DIMENSIONAL } from '../constants';
import options from '../options';

/**
 * Diff the old and new properties of a VNode and apply changes to the DOM node
 * @param {import('../internal').PreactElement} dom The DOM node to apply
 * changes to
 * @param {object} newProps The new props
 * @param {object} oldProps The old props
 * @param {boolean} isSvg Whether or not this node is an SVG node
 */
export function diffProps(dom, newProps, oldProps, isSvg) {
	let keys = Object.keys(newProps).sort();
	for (let i = 0; i < keys.length; i++) {
		let k = keys[i];
		if (k!=='children' && k!=='key' && (!oldProps || ((k==='value' || k==='checked') ? dom : oldProps)[k]!==newProps[k])) {
			setProperty(dom, k, newProps[k], oldProps[k], isSvg);
		}
	}

	for (let i in oldProps) {
		if (i!=='children' && i!=='key' && (!newProps || !(i in newProps))) {
			setProperty(dom, i, null, oldProps[i], isSvg);
		}
	}
}

let CAMEL_REG = /-?(?=[A-Z])/g;

/**
 * Set a property value on a DOM node
 * @param {import('../internal').PreactElement} dom The DOM node to modify
 * @param {string} name The name of the property to set
 * @param {*} value The value to set the property to
 * @param {*} oldValue The old value the property had
 * @param {boolean} isSvg Whether or not this DOM node is an SVG node or not
 */
function setProperty(dom, name, value, oldValue, isSvg) {
	let v;
	if (name==='class' || name==='className') name = isSvg ? 'class' : 'className';

	if (name==='style') {

		/* Possible golfing activities for setting styles:
		 *   - we could just drop String style values. They're not supported in other VDOM libs.
		 *   - assigning to .style sets .style.cssText - TODO: benchmark this, might not be worth the bytes.
		 *   - assigning also casts to String, and ignores invalid values. This means assigning an Object clears all styles.
		 */
		let s = dom.style;

		if (typeof value==='string') {
			s.cssText = value;
		}
		else {
			if (typeof oldValue==='string') s.cssText = '';
			else {
				// remove values not in the new list
				for (let i in oldValue) {
					if (value==null || !(i in value)) s.setProperty(i.replace(CAMEL_REG, '-'), '');
				}
			}
			for (let i in value) {
				v = value[i];
				if (oldValue==null || v!==oldValue[i]) {
					s.setProperty(i.replace(CAMEL_REG, '-'), typeof v==='number' && IS_NON_DIMENSIONAL.test(i)===false ? (v + 'px') : v);
				}
			}
		}
	}
	else if (name==='dangerouslySetInnerHTML') {
		return;
	}
	// Benchmark for comparison: https://esbench.com/bench/574c954bdb965b9a00965ac6
	else if (name[0]==='o' && name[1]==='n') {
		let useCapture = name !== (name=name.replace(/Capture$/, ''));
		let nameLower = name.toLowerCase();
		name = (nameLower in dom ? nameLower : name).substring(2);

		if (value) {
			if (!oldValue) dom.addEventListener(name, eventProxy, useCapture);
		}
		else {
			dom.removeEventListener(name, eventProxy, useCapture);
		}
		(dom._listeners || (dom._listeners = {}))[name] = value;
	}
	else if (name!=='list' && name!=='tagName' && !isSvg && (name in dom)) {
		dom[name] = value==null ? '' : value;
	}
	else if (value==null || value===false) {
		if (name!==(name = name.replace(/^xlink:?/, ''))) dom.removeAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase());
		else dom.removeAttribute(name);
	}
	else if (typeof value!=='function') {
		if (name!==(name = name.replace(/^xlink:?/, ''))) dom.setAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase(), value);
		else dom.setAttribute(name, value);
	}
}

/**
 * Proxy an event to hooked event handlers
 * @param {Event} e The event object from the browser
 * @private
 */
function eventProxy(e) {
	return this._listeners[e.type](options.event ? options.event(e) : e);
}
<commit_msg>Golf down 2 bytes<commit_after>import { IS_NON_DIMENSIONAL } from '../constants';
import options from '../options';

/**
 * Diff the old and new properties of a VNode and apply changes to the DOM node
 * @param {import('../internal').PreactElement} dom The DOM node to apply
 * changes to
 * @param {object} newProps The new props
 * @param {object} oldProps The old props
 * @param {boolean} isSvg Whether or not this node is an SVG node
 */
export function diffProps(dom, newProps, oldProps, isSvg) {
	let keys = Object.keys(newProps).sort();
	for (let i = 0; i < keys.length; i++) {
		if (keys[i]!=='children' && keys[i]!=='key' && (!oldProps || ((keys[i]==='value' || keys[i]==='checked') ? dom : oldProps)[keys[i]]!==newProps[keys[i]])) {
			setProperty(dom, keys[i], newProps[keys[i]], oldProps[keys[i]], isSvg);
		}
	}

	for (let i in oldProps) {
		if (i!=='children' && i!=='key' && (!newProps || !(i in newProps))) {
			setProperty(dom, i, null, oldProps[i], isSvg);
		}
	}
}

let CAMEL_REG = /-?(?=[A-Z])/g;

/**
 * Set a property value on a DOM node
 * @param {import('../internal').PreactElement} dom The DOM node to modify
 * @param {string} name The name of the property to set
 * @param {*} value The value to set the property to
 * @param {*} oldValue The old value the property had
 * @param {boolean} isSvg Whether or not this DOM node is an SVG node or not
 */
function setProperty(dom, name, value, oldValue, isSvg) {
	let v;
	if (name==='class' || name==='className') name = isSvg ? 'class' : 'className';

	if (name==='style') {

		/* Possible golfing activities for setting styles:
		 *   - we could just drop String style values. They're not supported in other VDOM libs.
		 *   - assigning to .style sets .style.cssText - TODO: benchmark this, might not be worth the bytes.
		 *   - assigning also casts to String, and ignores invalid values. This means assigning an Object clears all styles.
		 */
		let s = dom.style;

		if (typeof value==='string') {
			s.cssText = value;
		}
		else {
			if (typeof oldValue==='string') s.cssText = '';
			else {
				// remove values not in the new list
				for (let i in oldValue) {
					if (value==null || !(i in value)) s.setProperty(i.replace(CAMEL_REG, '-'), '');
				}
			}
			for (let i in value) {
				v = value[i];
				if (oldValue==null || v!==oldValue[i]) {
					s.setProperty(i.replace(CAMEL_REG, '-'), typeof v==='number' && IS_NON_DIMENSIONAL.test(i)===false ? (v + 'px') : v);
				}
			}
		}
	}
	else if (name==='dangerouslySetInnerHTML') {
		return;
	}
	// Benchmark for comparison: https://esbench.com/bench/574c954bdb965b9a00965ac6
	else if (name[0]==='o' && name[1]==='n') {
		let useCapture = name !== (name=name.replace(/Capture$/, ''));
		let nameLower = name.toLowerCase();
		name = (nameLower in dom ? nameLower : name).substring(2);

		if (value) {
			if (!oldValue) dom.addEventListener(name, eventProxy, useCapture);
		}
		else {
			dom.removeEventListener(name, eventProxy, useCapture);
		}
		(dom._listeners || (dom._listeners = {}))[name] = value;
	}
	else if (name!=='list' && name!=='tagName' && !isSvg && (name in dom)) {
		dom[name] = value==null ? '' : value;
	}
	else if (value==null || value===false) {
		if (name!==(name = name.replace(/^xlink:?/, ''))) dom.removeAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase());
		else dom.removeAttribute(name);
	}
	else if (typeof value!=='function') {
		if (name!==(name = name.replace(/^xlink:?/, ''))) dom.setAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase(), value);
		else dom.setAttribute(name, value);
	}
}

/**
 * Proxy an event to hooked event handlers
 * @param {Event} e The event object from the browser
 * @private
 */
function eventProxy(e) {
	return this._listeners[e.type](options.event ? options.event(e) : e);
}
<|endoftext|>


<commit_before>/* @flow strict-local */
import 'string.fromcodepoint'; // eslint-disable-line spellcheck/spell-checker

import type { ImageEmojiType } from '../types';
import { unicodeCodeByName, override } from './codePointMap';

const unicodeEmojiNames = Object.keys(unicodeCodeByName);

const parseUnicodeEmojiCode = (code: string): string /* force line */ =>
  code
    .split('-')
    .map(hex => String.fromCodePoint(parseInt(hex, 16)))
    .join('');

export const nameToEmojiMap = unicodeEmojiNames.reduce((obj, name) => {
  obj[name] = parseUnicodeEmojiCode(unicodeCodeByName[name]);
  return obj;
}, ({}: { [string]: string }));

export const codeToEmojiMap = unicodeEmojiNames.reduce((obj, name) => {
  const code = unicodeCodeByName[name];
  const displayCode = override[code] || code;
  obj[code] = parseUnicodeEmojiCode(displayCode);
  return obj;
}, ({}: { [string]: string }));

export const getFilteredEmojiNames = (
  query: string,
  activeRealmEmojiByName: $ReadOnly<{ [string]: ImageEmojiType }>,
): string[] => {
  const names = [...unicodeEmojiNames, ...Object.keys(activeRealmEmojiByName)];
  return Array.from(new Set([...names.filter(x => x.indexOf(query) === 0).sort()]));
};
<commit_msg>emoji/data: Rewrite false `reduce`s to plain `forEach`.<commit_after>/* @flow strict-local */
import 'string.fromcodepoint'; // eslint-disable-line spellcheck/spell-checker

import type { ImageEmojiType } from '../types';
import { unicodeCodeByName, override } from './codePointMap';

const unicodeEmojiNames = Object.keys(unicodeCodeByName);

const parseUnicodeEmojiCode = (code: string): string /* force line */ =>
  code
    .split('-')
    .map(hex => String.fromCodePoint(parseInt(hex, 16)))
    .join('');

export const nameToEmojiMap = (() => {
  const obj = ({}: { [string]: string });
  unicodeEmojiNames.forEach(name => {
    obj[name] = parseUnicodeEmojiCode(unicodeCodeByName[name]);
  });
  return obj;
})();

export const codeToEmojiMap = (() => {
  const obj = ({}: { [string]: string });
  unicodeEmojiNames.forEach(name => {
    const code = unicodeCodeByName[name];
    const displayCode = override[code] || code;
    obj[code] = parseUnicodeEmojiCode(displayCode);
  });
  return obj;
})();

export const getFilteredEmojiNames = (
  query: string,
  activeRealmEmojiByName: $ReadOnly<{ [string]: ImageEmojiType }>,
): string[] => {
  const names = [...unicodeEmojiNames, ...Object.keys(activeRealmEmojiByName)];
  return Array.from(new Set([...names.filter(x => x.indexOf(query) === 0).sort()]));
};
<|endoftext|>


<commit_before>function descProperty(val, enumerable, writable, configurable) {
  return {
    value: val,
    enumerable: enumerable,
    writable: writable,
    configurable: configurable
  };
}
function descMethod(func, enumerable, writable, configurable) {
  return descProperty(func, enumerable, writable, configurable);
}
function descAccessor(get, set, enumerable, writable, configurable) {
  return {
    get: get,
    set: set,
    enumerable: enumerable,
    writable: writable,
    configurable: configurable
  };
}
function descConst(val) {
  return { value:  val };
}
<commit_msg>Set default property attributes.<commit_after>function descProperty(val) {
  return {
    value: val,
    writable: true,
    configurable: true,
    enumerable: true
  };
}
function descMethod(func) {
  return descProperty(func);
}
function descAccessor(get, set) {
  return {
    get: get,
    set: set,
    configurable: true,
    enumerable: true
  };
}
function descConst(val) {
  return {
    value:  val,
    configurable: true,
    enumerable: true
  };
}
<|endoftext|>


<commit_before>'use strict'

module.exports = (app) => {
  let slapp = app.slapp

  let help = `
  view role definition (owner|reviewer|developer)
  view role assignment (owners|qa reviewers|dev reviewers|developers)
  assign myself to (owners|qa reviewers|dev reviewers|developers)
  remove myself from (owners|qa reviewers|dev reviewers|developers)
  submit work item *[owners only]*
  view work items (all|rejected|canceled|workable|in progress|in review|complete) (detail|debug) <- Optional
  view work item (work item title) (detail|debug) <- Optional
  cancel work item (work item title) *[owners only]*
  (qa|dev) review (work item title) (yes|no) *[dev/qa reviewers only]*
  begin work (work item title) *[developers only]*
  request review (work item title) (https://git.aarons.com/PullRequestURL) *[developers only]*
  review work (work item title) (yes|no) *[dev reviewers only]*
  `

  slapp.command('/cfq', /^\s*help\s*$/, (msg) => {
    msg.respond(help)
  })

  slapp.message('help', ['direct_mention', 'direct_message', 'ambient'], (msg, text) => {
    msg.say(help)
  })

  slapp.message('who am i', ['mention', 'direct_message'], (msg) => {
    slapp.client.users.info({ token: msg.meta.bot_token, user: msg.meta.user_id }, (err, data) => {
        if (err) return msg.respond(`Sorry, something went wrong. Try again? (${err.message || err})`)
            msg.say(data.user.name);
        })
  })

}<commit_msg>help bust be directed at bot<commit_after>'use strict'

module.exports = (app) => {
  let slapp = app.slapp

  let help = `
  view role definition (owner|reviewer|developer)
  view role assignment (owners|qa reviewers|dev reviewers|developers)
  assign myself to (owners|qa reviewers|dev reviewers|developers)
  remove myself from (owners|qa reviewers|dev reviewers|developers)
  submit work item *[owners only]*
  view work items (all|rejected|canceled|workable|in progress|in review|complete) (detail|debug) <- Optional
  view work item (work item title) (detail|debug) <- Optional
  cancel work item (work item title) *[owners only]*
  (qa|dev) review (work item title) (yes|no) *[dev/qa reviewers only]*
  begin work (work item title) *[developers only]*
  request review (work item title) (https://git.aarons.com/PullRequestURL) *[developers only]*
  review work (work item title) (yes|no) *[dev reviewers only]*
  `

  slapp.command('/cfq', /^\s*help\s*$/, (msg) => {
    msg.respond(help)
  })

  slapp.message('help', ['direct_mention', 'direct_message'], (msg, text) => {
    msg.say(help)
  })

  slapp.message('who am i', ['mention', 'direct_message'], (msg) => {
    slapp.client.users.info({ token: msg.meta.bot_token, user: msg.meta.user_id }, (err, data) => {
        if (err) return msg.respond(`Sorry, something went wrong. Try again? (${err.message || err})`)
            msg.say(data.user.name);
        })
  })

}<|endoftext|>


<commit_before>/**
 * This file declares various pieces of functional programming.
 *
 * This isn't a general purpose functional library, to keep things small it
 * has just the parts useful for Oboe.js.
 */

/**
 * Call a single function with the given arguments array.
 * Basically, a functional-style version of the OO-style Function#apply for
 * when we don't care about the context ('this') of the call.
 *
 * The order of arguments allows partial completion of the arguments array
 */
function apply(args, fn) {
   return fn.apply(undefined, args);
}

/**
 * Define variable argument functions but cut out all that tedious messing about
 * with the arguments object. Delivers the variable-length part of the arguments
 * list as an array.
 *
 * Eg:
 *
 * var myFunction = varArgs(
 *    function( fixedArgument, otherFixedArgument, variableNumberOfArguments ){
 *       console.log( variableNumberOfArguments );
 *    }
 * )
 *
 * myFunction('a', 'b', 1, 2, 3); // logs [1,2,3]
 *
 * var myOtherFunction = varArgs(function( variableNumberOfArguments ){
 *    console.log( variableNumberOfArguments );
 * })
 *
 * myFunction(1, 2, 3); // logs [1,2,3]
 *
 */
function varArgs(fn){

   var numberOfFixedArguments = fn.length -1;

   return function(){

      var numberOfVaraibleArguments = arguments.length - numberOfFixedArguments,

          argumentsToFunction = Array.prototype.slice.call(arguments);

      // remove the last n element from the array and append it onto the end of
      // itself as a sub-array
      argumentsToFunction.push(
         argumentsToFunction.splice(numberOfFixedArguments, numberOfVaraibleArguments)
      );

      return fn.apply( this, argumentsToFunction );
   }
}

/**
 * Partially complete a function.
 *
 * Eg:
 *    var add3 = partialComplete( function add(a,b){return a+b}, [3] );
 *
 *    add3(4) // gives 7
 */
var partialComplete = varArgs(function( fn, boundArgs ) {

      return varArgs(function( callArgs ) {

         return fn.apply(this, boundArgs.concat(callArgs));
      });
   }),

/**
 * Compose zero or more functions:
 *
 *    compose(f1, f2, f3)(x) = f1(f2(f3(x))))
 *
 * The last (inner-most) function may take more than one parameter:
 *
 *    compose(f1, f2, f3)(x,y) = f1(f2(f3(x,y))))
 */
   compose = varArgs(function(fns) {

      var fnsList = arrayAsList(fns);

      function next(params, curFn) {
         return [apply(params, curFn)];
      }

      return varArgs(function(startParams){

         return foldR(next, startParams, fnsList)[0];
      });
   });

/**
 * Swap the order of parameters to a binary function
 *
 * A bit like this flip: http://zvon.org/other/haskell/Outputprelude/flip_f.html
 */
function flip(fn){
   return function(a, b){
      return fn(b,a);
   }
}

/**
 * Call a list of functions with the same args until one returns a
 * truthy result. Similar to the || operator.
 *
 * So:
 *      lazyUnion([f1,f2,f3 ... fn])( p1, p2 ... pn )
 *
 * Is equivalent to:
 *      apply([p1, p2 ... pn], f1) ||
 *      apply([p1, p2 ... pn], f2) ||
 *      apply([p1, p2 ... pn], f3) ... apply(fn, [p1, p2 ... pn])
 *
 * @returns the first return value that is given that is truthy.
 */
var lazyUnion = varArgs(function(fns) {

   return varArgs(function(params){

      var maybeValue;

      for (var i = 0; i < len(fns); i++) {

         maybeValue = apply(params, fns[i]);

         if( maybeValue ) {
            return maybeValue;
         }
      }
   });
});

/**
 * Create a function which is the intersection of two other functions.
 *
 * Like the && operator, if the first is truthy, the second is never called,
 * otherwise the return value from the second is returned.
 */
function lazyIntersection(fn1, fn2) {

   return function (param) {

      return fn1(param) && fn2(param);
   };
}

<commit_msg>reorder<commit_after>/**
 * Partially complete a function.
 *
 * Eg:
 *    var add3 = partialComplete( function add(a,b){return a+b}, [3] );
 *
 *    add3(4) // gives 7
 */
var partialComplete = varArgs(function( fn, boundArgs ) {

      return varArgs(function( callArgs ) {

         return fn.apply(this, boundArgs.concat(callArgs));
      });
   }),

/**
 * Compose zero or more functions:
 *
 *    compose(f1, f2, f3)(x) = f1(f2(f3(x))))
 *
 * The last (inner-most) function may take more than one parameter:
 *
 *    compose(f1, f2, f3)(x,y) = f1(f2(f3(x,y))))
 */
   compose = varArgs(function(fns) {

      var fnsList = arrayAsList(fns);

      function next(params, curFn) {
         return [apply(params, curFn)];
      }

      return varArgs(function(startParams){

         return foldR(next, startParams, fnsList)[0];
      });
   }),

/**
 * Call a list of functions with the same args until one returns a
 * truthy result. Similar to the || operator.
 *
 * So:
 *      lazyUnion([f1,f2,f3 ... fn])( p1, p2 ... pn )
 *
 * Is equivalent to:
 *      apply([p1, p2 ... pn], f1) ||
 *      apply([p1, p2 ... pn], f2) ||
 *      apply([p1, p2 ... pn], f3) ... apply(fn, [p1, p2 ... pn])
 *
 * @returns the first return value that is given that is truthy.
 */
   lazyUnion = varArgs(function(fns) {

      return varArgs(function(params){

         var maybeValue;

         for (var i = 0; i < len(fns); i++) {

            maybeValue = apply(params, fns[i]);

            if( maybeValue ) {
               return maybeValue;
            }
         }
      });
   });

/**
 * This file declares various pieces of functional programming.
 *
 * This isn't a general purpose functional library, to keep things small it
 * has just the parts useful for Oboe.js.
 */

/**
 * Call a single function with the given arguments array.
 * Basically, a functional-style version of the OO-style Function#apply for
 * when we don't care about the context ('this') of the call.
 *
 * The order of arguments allows partial completion of the arguments array
 */
function apply(args, fn) {
   return fn.apply(undefined, args);
}

/**
 * Define variable argument functions but cut out all that tedious messing about
 * with the arguments object. Delivers the variable-length part of the arguments
 * list as an array.
 *
 * Eg:
 *
 * var myFunction = varArgs(
 *    function( fixedArgument, otherFixedArgument, variableNumberOfArguments ){
 *       console.log( variableNumberOfArguments );
 *    }
 * )
 *
 * myFunction('a', 'b', 1, 2, 3); // logs [1,2,3]
 *
 * var myOtherFunction = varArgs(function( variableNumberOfArguments ){
 *    console.log( variableNumberOfArguments );
 * })
 *
 * myFunction(1, 2, 3); // logs [1,2,3]
 *
 */
function varArgs(fn){

   var numberOfFixedArguments = fn.length -1;

   return function(){

      var numberOfVaraibleArguments = arguments.length - numberOfFixedArguments,

          argumentsToFunction = Array.prototype.slice.call(arguments);

      // remove the last n element from the array and append it onto the end of
      // itself as a sub-array
      argumentsToFunction.push(
         argumentsToFunction.splice(numberOfFixedArguments, numberOfVaraibleArguments)
      );

      return fn.apply( this, argumentsToFunction );
   }
}

/**
 * Swap the order of parameters to a binary function
 *
 * A bit like this flip: http://zvon.org/other/haskell/Outputprelude/flip_f.html
 */
function flip(fn){
   return function(a, b){
      return fn(b,a);
   }
}

/**
 * Create a function which is the intersection of two other functions.
 *
 * Like the && operator, if the first is truthy, the second is never called,
 * otherwise the return value from the second is returned.
 */
function lazyIntersection(fn1, fn2) {

   return function (param) {

      return fn1(param) && fn2(param);
   };
}

<|endoftext|>