<commit_before>import {ticks} from "d3-array";
import {format} from "d3-format";
import constant from "./constant";
import nice from "./nice";
import {default as quantitative, copy} from "./quantitative";

var tickFormat10 = format(".0e"),
    tickFormatOther = format(",");

function deinterpolate(a, b) {
  return (b = Math.log(b / a))
      ? function(x) { return Math.log(x / a) / b; }
      : constant(b);
}

function reinterpolate(a, b) {
  return a < 0
      ? function(t) { return -Math.pow(-b, t) * Math.pow(-a, 1 - t); }
      : function(t) { return Math.pow(b, t) * Math.pow(a, 1 - t); };
}

function powp(base) {
  return base === 10 ? function(x) { return isFinite(x) ? +("1e" + x) : x < 0 ? 0 : x; }
      : base === Math.E ? Math.exp
      : function(x) { return Math.pow(base, x); };
}

function logp(base) {
  return base === Math.E ? Math.log
      : base === 10 && Math.log10
      || base === 2 && Math.log2
      || (base = Math.log(base), function(x) { return Math.log(x) / base; });
}

function reflect(f) {
  return function(x) {
    return -f(-x);
  };
}

export default function log() {
  var scale = quantitative(deinterpolate, reinterpolate).domain([1, 10]),
      domain = scale.domain,
      base = 10,
      logs = logp(10),
      pows = powp(10);

  function rescale() {
    logs = logp(base), pows = powp(base);
    if (domain()[0] < 0) logs = reflect(logs), pows = reflect(pows);
    return scale;
  }

  scale.base = function(_) {
    return arguments.length ? (base = +_, rescale()) : base;
  };

  scale.domain = function(_) {
    return arguments.length ? (domain(_), rescale()) : domain();
  };

  scale.nice = function() {
    return domain(nice(domain(), {
      floor: function(x) { return pows(Math.floor(logs(x))); },
      ceil: function(x) { return pows(Math.ceil(logs(x))); }
    }));
  };

  scale.ticks = function(count) {
    var d = domain(),
        u = d[0],
        v = d[d.length - 1];

    if (v < u) i = u, u = v, v = i;

    var i = logs(u),
        j = logs(v),
        p,
        k,
        t,
        n = count == null ? 10 : +count,
        z = [];

    if (!(base % 1) && j - i < n) {
      i = Math.floor(i), j = Math.ceil(j);
      if (u > 0) {
        for (--j, k = 1, p = pows(i); k < base; ++k) if ((t = p * k) < u) continue; else z.push(t);
        while (++i < j) for (k = 1, p = pows(i); k < base; ++k) z.push(p * k);
        for (k = 1, p = pows(i); k <= base; ++k) if ((t = p * k) > v) break; else z.push(t);
      } else {
        for (++i, k = base, p = pows(i); k >= 1; --k) if ((t = p * k) < u) continue; else z.push(t);
        while (++i < j) for (k = base - 1, p = pows(i); k >= 1; --k) z.push(p * k);
        for (k = base - 1, p = pows(i); k >= 1; --k) if ((t = p * k) > v) break; else z.push(t);
      }
    } else {
      z = ticks(i, j, Math.min(j - i, n)).map(pows);
    }

    return z;
  };

  scale.tickFormat = function(count, specifier) {
    if (specifier == null) specifier = base === 10 ? tickFormat10 : tickFormatOther;
    else if (typeof specifier !== "function") specifier = format(specifier);
    if (count == null) return specifier;
    var k = Math.max(1, base * count / scale.ticks().length); // TODO fast estimate?
    return function(d) {
      var i = d / pows(Math.round(logs(d)));
      if (i * base < base - 0.5) i *= base;
      return i <= k ? specifier(d) : "";
    };
  };

  scale.copy = function() {
    return copy(scale, log().base(base));
  };

  return scale;
};
<commit_msg>One fewer closure.<commit_after>import {ticks} from "d3-array";
import {format} from "d3-format";
import constant from "./constant";
import nice from "./nice";
import {default as quantitative, copy} from "./quantitative";

var tickFormat10 = format(".0e"),
    tickFormatOther = format(",");

function deinterpolate(a, b) {
  return (b = Math.log(b / a))
      ? function(x) { return Math.log(x / a) / b; }
      : constant(b);
}

function reinterpolate(a, b) {
  return a < 0
      ? function(t) { return -Math.pow(-b, t) * Math.pow(-a, 1 - t); }
      : function(t) { return Math.pow(b, t) * Math.pow(a, 1 - t); };
}

function pow10(x) {
  return isFinite(x) ? +("1e" + x) : x < 0 ? 0 : x;
}

function powp(base) {
  return base === 10 ? pow10
      : base === Math.E ? Math.exp
      : function(x) { return Math.pow(base, x); };
}

function logp(base) {
  return base === Math.E ? Math.log
      : base === 10 && Math.log10
      || base === 2 && Math.log2
      || (base = Math.log(base), function(x) { return Math.log(x) / base; });
}

function reflect(f) {
  return function(x) {
    return -f(-x);
  };
}

export default function log() {
  var scale = quantitative(deinterpolate, reinterpolate).domain([1, 10]),
      domain = scale.domain,
      base = 10,
      logs = logp(10),
      pows = powp(10);

  function rescale() {
    logs = logp(base), pows = powp(base);
    if (domain()[0] < 0) logs = reflect(logs), pows = reflect(pows);
    return scale;
  }

  scale.base = function(_) {
    return arguments.length ? (base = +_, rescale()) : base;
  };

  scale.domain = function(_) {
    return arguments.length ? (domain(_), rescale()) : domain();
  };

  scale.nice = function() {
    return domain(nice(domain(), {
      floor: function(x) { return pows(Math.floor(logs(x))); },
      ceil: function(x) { return pows(Math.ceil(logs(x))); }
    }));
  };

  scale.ticks = function(count) {
    var d = domain(),
        u = d[0],
        v = d[d.length - 1];

    if (v < u) i = u, u = v, v = i;

    var i = logs(u),
        j = logs(v),
        p,
        k,
        t,
        n = count == null ? 10 : +count,
        z = [];

    if (!(base % 1) && j - i < n) {
      i = Math.floor(i), j = Math.ceil(j);
      if (u > 0) {
        for (--j, k = 1, p = pows(i); k < base; ++k) if ((t = p * k) < u) continue; else z.push(t);
        while (++i < j) for (k = 1, p = pows(i); k < base; ++k) z.push(p * k);
        for (k = 1, p = pows(i); k <= base; ++k) if ((t = p * k) > v) break; else z.push(t);
      } else {
        for (++i, k = base, p = pows(i); k >= 1; --k) if ((t = p * k) < u) continue; else z.push(t);
        while (++i < j) for (k = base - 1, p = pows(i); k >= 1; --k) z.push(p * k);
        for (k = base - 1, p = pows(i); k >= 1; --k) if ((t = p * k) > v) break; else z.push(t);
      }
    } else {
      z = ticks(i, j, Math.min(j - i, n)).map(pows);
    }

    return z;
  };

  scale.tickFormat = function(count, specifier) {
    if (specifier == null) specifier = base === 10 ? tickFormat10 : tickFormatOther;
    else if (typeof specifier !== "function") specifier = format(specifier);
    if (count == null) return specifier;
    var k = Math.max(1, base * count / scale.ticks().length); // TODO fast estimate?
    return function(d) {
      var i = d / pows(Math.round(logs(d)));
      if (i * base < base - 0.5) i *= base;
      return i <= k ? specifier(d) : "";
    };
  };

  scale.copy = function() {
    return copy(scale, log().base(base));
  };

  return scale;
};
<|endoftext|>


<commit_before>/*
MagJS v0.22.6
http://github.com/magnumjs/mag.js
(c) Michael Glazer
License: MIT
*/
(function(mag, document, undefined) {

  //'use strict';

  //Plugins:
  var hookins = {
    values: [],
    attributes: [],
    elementMatcher: []
  }

  mag.create = function(id, module, props) {
    return function(id2, props2) {
      if (typeof id2 !== 'string') {
        props2 = id2
        id2 = 0
      }
      return mag.module(id2 || id, module, mag.utils.merge(props || {}, props2 || {}))
    }
  }

  mag.module = function(id, mod, props) {

    props = props || {}

    // already here before?
    if (mag.utils.items.isItem(id)) {
      if (reloader(mag.utils.items.getItem(id), getNode(id))) return;
    }

    // get unique instance ID if not exists or with props.key
    var idInstance;
    // get unique instance ID if not exists or with props.key
    if (props.key && mag.utils.items.isItem(id + '.' + props.key)) {
      idInstance = mag.utils.items.getItem(id + '.' + props.key)
    } else {
      idInstance = mag.utils.getItemInstanceId(props.key ? id + '.' + props.key : id);
    }

    // TODO: cache/ clearable
    // clear cache if exists
    if (!props.retain) mag.mod.clear(idInstance)

    // get unqiue instance ID's module
    mag.mod.submodule(id, idInstance, mod, props)

    // NODE
    var node = getNode(id)

    //WATCH
    observer(idInstance, id)

    // LIFE CYCLE EVENT
    if (mag.utils.callLCEvent('willload', mag.mod.getState(idInstance), node, idInstance, 1)) return;

    // unloader handlers in controller
    addControllerUnloaders(idInstance)

    // DRAW async
    mag.redraw(node, idInstance, 1);

    // LIFE CYCLE EVENT
    mag.utils.callLCEvent('didload', mag.mod.getState(idInstance), node, idInstance, 1);

    // return function to clone create new clone instances ;)
    return makeClone(idInstance, node, mod, mag.utils.copy(props))
  }

  var isValidId = function(nodeId, idInstance) {

    // verify idInstance
    if (idInstance < 0 || idInstance != mag.utils.items.getItem(nodeId)) {
      // if original id is a match
      if (nodeId == mag.mod.getId(idInstance)) return true;
      return false
    }
    return true
  }

  var pendingRequests = []

  mag.begin = function(id) {
    if (typeof pendingRequests[id] == 'undefined') {
      pendingRequests[id] = 1;
    } else {
      pendingRequests[id]++;
    }
  }

  mag.end = function(id) {
    if (pendingRequests[id] > 1) pendingRequests[id]--;
    else {
      pendingRequests[id] = 0;
      var nid = mag.utils.items.getItemVal(id)
      mag.redraw(getNode(nid), id);
    }

  }
  var timers = [];
  mag.redraw = function(node, idInstance, force) {
    if (!pendingRequests[idInstance]) {

      if (!node || typeof idInstance == 'undefined') {
        throw Error('Mag.JS - Id or node invalid: ' + mag.utils.items.getItemVal(idInstance));
      }

      // verify idInstance
      if (!isValidId(node.id, idInstance)) {
        return
      }

      // clear existing configs ?
      // TODO: per idInstance / id ?
      if (force) mag.fill.configs.splice(0, mag.fill.configs.length)

      if (force) mag.mod.clear(idInstance)

      var fun = makeRedrawFun(node, idInstance, force)

      // check for existing frame id then clear it if exists
      //ENQUEUE
      //debounce
      cancelAnimationFrame(timers[idInstance]);
      timers[idInstance] = requestAnimationFrame(fun);
      //save frame id with the instance
      // then if instance already has frame id create new discard old or just retain old
    }
  }

  mag.hookin = function(name, key, handler) {
    hookins[name].push({
      context: {},
      handler: handler,
      key: key
    })
  }

  mag.hook = function(name, key, data) {
    for (var i = 0, size = hookins[name].length; i < size; i++) {
      mag.utils.callHook(hookins, key, name, i, data)
    }
  }
  var cloners = {},
    prevState = [],
    handler = function(ids, handler) {
      // call handler on each new change to state or props
      mag.utils.onLCEvent('didupdate', ids, function(state, props) {

          var current = mag.utils.merge(mag.utils.copy(props), mag.utils.copy(state));

          if (JSON.stringify(current) !== JSON.stringify(prevState[ids])) {
            prevState[ids] = current;
            handler(state, props, prevState[ids]);
          }
        })
        //TODO: return `dispose` function to remove handler
    };
  var makeClone = function(idInstance, node, mod, props) {
    // recursion warning
    var clones = [];
    var a = function(id, node, mod, props, index) {
      //TODO: what is this use case? if no index?

      // prevent recursion?
      var id = node.id + (props.key ? '.' + props.key : '') + '.' + (index || 0);
      var cloner = cloners[id] || {};
      cloner.id = id;
      // if clone already exists return ?
      if (!mag.utils.items.isItem(id)) {
        cloners[id] = cloner = node.cloneNode(1);
        cloner.id = id;
      }
      if (cloner instanceof HTMLElement) {

        var idInstance2 = mag.utils.getItemInstanceId(cloner.id);

        clones.push({
          instanceId: idInstance2,
          id: cloner.id,
          subscribe: handler.bind({}, idInstance2)
        });

        // get unique instance ID's module
        mag.mod.submodule(cloner.id, idInstance2, mod, props)

        observer(idInstance2, cloner.id)

        // DRAW
        mag.redraw(cloner, idInstance2, 1)

        return cloner;
      }

    }.bind({}, idInstance, node, mod, props)

    a.clones = function() {
      return clones
    };

    //BIND CLONE INSTANCE METHODS
    a.getId = function(ids) {
      return ids
    }.bind({}, idInstance);
    a.draw = function(node, ids, force) {
      mag.redraw(node, ids, force)
    }.bind({}, node, idInstance)
    a.getState = function(ids, id) {
      return mag.mod.getState(id || ids)
    }.bind({}, idInstance)
    a.getProps = function(ids, id) {
      return mag.mod.getProps(id || ids)
    }.bind({}, idInstance);

    a.subscribe = handler.bind({}, idInstance);

    return a;
  };

  var nodeCache = [];

  function getNode(id, clear) {
    //cache nodes?
    if (nodeCache[id] && !clear) return nodeCache[id]
    var node = document.getElementById(id);
    if (node) nodeCache[id] = node
    if (!node) {}
    return node;
  }

  var observer = function(idInstance, nodeId) {
    var callback = function(index, id) {
      if (getNode(id)) {
        mag.redraw(getNode(id), index)
      } else if (mag.utils.items.isItem(id)) {
        mag.clear(index)
          //throw Error('invalid node id ' + id + ' index ' + index)
      }
    }.bind({}, idInstance, nodeId)
    mag.mod.setFrameId(idInstance, callback);
  }

  mag.clear = function(index) {
    cancelAnimationFrame(timers[index]);
    mag.mod.setFrameId(index, null)
      // remove from indexes
    mag.utils.items.removeItem(index)
      //mag.mod.remove(index)
    mag.mod.clear(index)
      //observer index ?

    // fill data cache
    mag.fill.clearCache(mag.mod.getId(index))
  }

  var makeRedrawFun = function(node1, idInstance1, force1) {
    return function(node, idInstance, force) {

      getNode(node.id, 1)

      // verify idInstance
      if (!isValidId(node.id, idInstance) || !node) {
        return
      }

      var state = mag.mod.getState(idInstance)

      // LIFE CYCLE EVENT
      if (mag.utils.callLCEvent('isupdate', state, node, idInstance)) return;

      var props = mag.mod.getProps(idInstance)

      var data = mag.utils.merge(mag.utils.copy(props), mag.utils.copy(state))

      // CACHED?
      if (mag.mod.iscached(idInstance, data) && !force) {
        return 0;
      };

      // LIFE CYCLE EVENT
      if (mag.utils.callLCEvent('willupdate', state, node, idInstance)) return;

      //RUN VIEW FUN
      mag.mod.callView(node, idInstance);

      //START DOM
      mag.fill.setId(node.id)
      mag.fill.run(node, state)
        // END DOM

      //CONFIGS
      callConfigs(node.id, mag.fill.configs)

      // add configs unloaders
      addConfigUnloaders(node.id, idInstance)

      // LIFE CYCLE EVENT
      mag.utils.callLCEvent('didupdate', state, node, idInstance)

      // get parent to call
      if (node && node.parentNode) {
        var parent = findClosestId(node.parentNode)
        if (parent) {
          mag.redraw(parent, mag.utils.items.getItem(parent.id))
        }
      }

    }.bind({}, node1, idInstance1, force1)
  }

  var findClosestId = function(node) {
    if (node.id) return node
    if (node.parentNode) return findClosestId(node.parentNode)
  }

  var callConfigs = function(id, configs) {
    for (var k in configs) {
      if (k.indexOf('id("' + id + '")/') > -1) {
        configs[k]()
      }
    }
  }

  var addControllerUnloaders = function(idInstance) {
    // TODO: controller unloaders
    var state = mag.mod.getState(idInstance)
    mag.utils.unloaders[idInstance] = mag.utils.unloaders[idInstance] || []
    if (state.onunload) mag.utils.unloaders[idInstance].push({
      controller: state,
      handler: state.onunload
    })
  }

  var addConfigUnloaders = function(id, index) {

    for (var k in mag.fill.cached) {
      if (k.indexOf('id("' + id + '")/') > -1 && k.indexOf('-config') > -1 && mag.fill.cached[k].configContext) {

        mag.utils.unloaders[index] = mag.utils.unloaders[index] || []

        mag.utils.unloaders[index].push({
          controller: mag.fill.cached[k].configContext,
          handler: mag.fill.cached[k].configContext.onunload
        })

      }
    }
  }

  var reloader = function(idInstance, node) {
    return mag.utils.callLCEvent('onreload', mag.mod.getState(idInstance), node, idInstance)
  }

  mag.getNode = getNode
  window.mag = mag

})(window.mag || {}, document);
<commit_msg>Update mag.js<commit_after>/*
MagJS v0.22.6
http://github.com/magnumjs/mag.js
(c) Michael Glazer
License: MIT
*/
(function(mag, document, undefined) {

  //'use strict';

  //Plugins:
  var hookins = {
    values: [],
    attributes: [],
    elementMatcher: []
  }

  mag.create = function(id, module, props) {
    return function(id2, props2) {
      if (typeof id2 !== 'string') {
        props2 = id2
        id2 = 0
      }
      return mag.module(id2 || id, module, mag.utils.merge(props || {}, props2 || {}))
    }
  }

  mag.module = function(id, mod, props) {

    props = props || {}

    // already here before?
    if (mag.utils.items.isItem(id)) {
      if (reloader(mag.utils.items.getItem(id), getNode(id))) return;
    }

    // get unique instance ID if not exists or with props.key
    var idInstance;
    // get unique instance ID if not exists or with props.key
    if (props.key && mag.utils.items.isItem(id + '.' + props.key)) {
      idInstance = mag.utils.items.getItem(id + '.' + props.key)
    } else {
      idInstance = mag.utils.getItemInstanceId(props.key ? id + '.' + props.key : id);
    }

    // TODO: cache/ clearable
    // clear cache if exists
    if (!props.retain) mag.mod.clear(idInstance)

    // get unqiue instance ID's module
    mag.mod.submodule(id, idInstance, mod, props)

    // NODE
    var node = getNode(id)

    //WATCH
    observer(idInstance, id)

    // LIFE CYCLE EVENT
    if (mag.utils.callLCEvent('willload', mag.mod.getState(idInstance), node, idInstance, 1)) return;

    // unloader handlers in controller
    addControllerUnloaders(idInstance)

    // DRAW async
    mag.redraw(node, idInstance, 1);

    // LIFE CYCLE EVENT
    mag.utils.callLCEvent('didload', mag.mod.getState(idInstance), node, idInstance, 1);

    // return function to clone create new clone instances ;)
    return makeClone(idInstance, node, mod, mag.utils.copy(props))
  }

  var isValidId = function(nodeId, idInstance) {

    // verify idInstance
    if (idInstance < 0 || idInstance != mag.utils.items.getItem(nodeId)) {
      // if original id is a match
      if (nodeId == mag.mod.getId(idInstance)) return true;
      return false
    }
    return true
  }

  var pendingRequests = []

  mag.begin = function(id) {
    if (typeof pendingRequests[id] == 'undefined') {
      pendingRequests[id] = 1;
    } else {
      pendingRequests[id]++;
    }
  }

  mag.end = function(id) {
    if (pendingRequests[id] > 1) pendingRequests[id]--;
    else {
      pendingRequests[id] = 0;
      var nid = mag.utils.items.getItemVal(id)
      mag.redraw(getNode(nid), id);
    }

  }
  var timers = [];
  mag.redraw = function(node, idInstance, force) {
    if (!pendingRequests[idInstance]) {

      if (!node || typeof idInstance == 'undefined') {
        throw Error('Mag.JS - Id or node invalid: ' + mag.utils.items.getItemVal(idInstance));
      }

      // verify idInstance
      if (!isValidId(node.id, idInstance)) {
        return
      }

      // clear existing configs ?
      // TODO: per idInstance / id ?
      if (force) mag.fill.configs.splice(0, mag.fill.configs.length)

      if (force) mag.mod.clear(idInstance)

      var fun = makeRedrawFun(node, idInstance, force)

      // check for existing frame id then clear it if exists
      //ENQUEUE
      //debounce
      cancelAnimationFrame(timers[idInstance]);
      timers[idInstance] = requestAnimationFrame(fun);
      //save frame id with the instance
      // then if instance already has frame id create new discard old or just retain old
    }
  }

  mag.hookin = function(name, key, handler) {
    hookins[name].push({
      context: {},
      handler: handler,
      key: key
    })
  }

  mag.hook = function(name, key, data) {
    for (var i = 0, size = hookins[name].length; i < size; i++) {
      mag.utils.callHook(hookins, key, name, i, data)
    }
  }
  var cloners = {},
    prevState = [],
    handler = function(ids, handler) {
      // call handler on each new change to state or props
      mag.utils.onLCEvent('didupdate', ids, function(state, props) {

          var current = mag.utils.merge(mag.utils.copy(props), mag.utils.copy(state));

          if (JSON.stringify(current) !== JSON.stringify(prevState[ids])) {
            prevState[ids] = current;
            handler(state, props, prevState[ids]);
          }
        })
        //TODO: return `dispose` function to remove handler
    };
  var makeClone = function(idInstance, node, mod, props) {
    // recursion warning
    var clones = [];
    var a = function(id, node, mod, props, index) {
      //TODO: what is this use case? if no index?

      // prevent recursion?
      var id = node.id + (props.key ? '.' + props.key : '') + '.' + (index || 0);
      var cloner = cloners[id] || {};
      cloner.id = id;
      // if clone already exists return ?
      if (!mag.utils.items.isItem(id)) {
        cloners[id] = cloner = node.cloneNode(1);
        cloner.id = id;
      }
      if (cloner instanceof HTMLElement) {

        var idInstance2 = mag.utils.getItemInstanceId(cloner.id);

        clones.push({
          instanceId: idInstance2,
          id: cloner.id, // TODO: remove, use mag.getId(instanceId)
          subscribe: handler.bind({}, idInstance2)
        });

        // get unique instance ID's module
        mag.mod.submodule(cloner.id, idInstance2, mod, props)

        observer(idInstance2, cloner.id)

        // DRAW
        mag.redraw(cloner, idInstance2, 1)

        return cloner;
      }

    }.bind({}, idInstance, node, mod, props)

    a.clones = function() {
      return clones
    };

    //BIND CLONE INSTANCE METHODS
    a.getId = function(ids) {
      return ids
    }.bind({}, idInstance);
    a.draw = function(node, ids, force) {
      mag.redraw(node, ids, force)
    }.bind({}, node, idInstance)
    a.getState = function(ids, id) {
      return mag.mod.getState(id || ids)
    }.bind({}, idInstance)
    a.getProps = function(ids, id) {
      return mag.mod.getProps(id || ids)
    }.bind({}, idInstance);

    a.subscribe = handler.bind({}, idInstance);

    return a;
  };

  var nodeCache = [];

  function getNode(id, clear) {
    //cache nodes?
    if (nodeCache[id] && !clear) return nodeCache[id]
    var node = document.getElementById(id);
    if (node) nodeCache[id] = node
    if (!node) {}
    return node;
  }

  var observer = function(idInstance, nodeId) {
    var callback = function(index, id) {
      if (getNode(id)) {
        mag.redraw(getNode(id), index)
      } else if (mag.utils.items.isItem(id)) {
        mag.clear(index)
          //throw Error('invalid node id ' + id + ' index ' + index)
      }
    }.bind({}, idInstance, nodeId)
    mag.mod.setFrameId(idInstance, callback);
  }

  mag.clear = function(index) {
    cancelAnimationFrame(timers[index]);
      // remove from indexes
    mag.utils.items.removeItem(index)
      //mag.mod.remove(index)
    mag.mod.clear(index)
      //observer index ?

    // fill data cache
    mag.fill.clearCache(mag.mod.getId(index))
  }

  var makeRedrawFun = function(node1, idInstance1, force1) {
    return function(node, idInstance, force) {

      getNode(node.id, 1)

      // verify idInstance
      if (!isValidId(node.id, idInstance) || !node) {
        return
      }

      var state = mag.mod.getState(idInstance)

      // LIFE CYCLE EVENT
      if (mag.utils.callLCEvent('isupdate', state, node, idInstance)) return;

      var props = mag.mod.getProps(idInstance)

      var data = mag.utils.merge(mag.utils.copy(props), mag.utils.copy(state))

      // CACHED?
      if (mag.mod.iscached(idInstance, data) && !force) {
        return 0;
      };

      // LIFE CYCLE EVENT
      if (mag.utils.callLCEvent('willupdate', state, node, idInstance)) return;

      //RUN VIEW FUN
      mag.mod.callView(node, idInstance);

      //START DOM
      mag.fill.setId(node.id)
      mag.fill.run(node, state)
        // END DOM

      //CONFIGS
      callConfigs(node.id, mag.fill.configs)

      // add configs unloaders
      addConfigUnloaders(node.id, idInstance)

      // LIFE CYCLE EVENT
      mag.utils.callLCEvent('didupdate', state, node, idInstance)

      // get parent to call
      if (node && node.parentNode) {
        var parent = findClosestId(node.parentNode)
        if (parent) {
          mag.redraw(parent, mag.utils.items.getItem(parent.id))
        }
      }

    }.bind({}, node1, idInstance1, force1)
  }

  var findClosestId = function(node) {
    if (node.id) return node
    if (node.parentNode) return findClosestId(node.parentNode)
  }

  var callConfigs = function(id, configs) {
    for (var k in configs) {
      if (k.indexOf('id("' + id + '")/') > -1) {
        configs[k]()
      }
    }
  }

  var addControllerUnloaders = function(idInstance) {
    // TODO: controller unloaders
    var state = mag.mod.getState(idInstance)
    mag.utils.unloaders[idInstance] = mag.utils.unloaders[idInstance] || []
    if (state.onunload) mag.utils.unloaders[idInstance].push({
      controller: state,
      handler: state.onunload
    })
  }

  var addConfigUnloaders = function(id, index) {

    for (var k in mag.fill.cached) {
      if (k.indexOf('id("' + id + '")/') > -1 && k.indexOf('-config') > -1 && mag.fill.cached[k].configContext) {

        mag.utils.unloaders[index] = mag.utils.unloaders[index] || []

        mag.utils.unloaders[index].push({
          controller: mag.fill.cached[k].configContext,
          handler: mag.fill.cached[k].configContext.onunload
        })

      }
    }
  }

  var reloader = function(idInstance, node) {
    return mag.utils.callLCEvent('onreload', mag.mod.getState(idInstance), node, idInstance)
  }

  mag.getNode = getNode
  window.mag = mag

})(window.mag || {}, document);
<|endoftext|>


<commit_before>//////////////////////////////////
//MagJS
//////////////////////////////////
/**!
 * @name mag.js - Copyright (c) 2013, 2014 Michael Glazer
 * @description MagnumJS core code library
 * @author Michael Glazer
 * @date 4/20/2014
 * @version Alpha - 0.2.29
 * @license MIT https://github.com/magnumjs/mag.js/blob/master/LICENSE
 * @link https://github.com/magnumjs/mag.js
 */
'use strict';
(function(mag, undefined) {
  var LOG_LEVEL = 'warn'; //info|warn|error|debug|log
  window.log = function() {
    var level = [].shift.apply(arguments);
    var args = Array.prototype.slice.call(arguments);
    if (level == LOG_LEVEL && console) console[LOG_LEVEL](args.join(','));
  };
  mag.reserved = ['__requires', '__instance'];
  mag.aspect = {
    injectors: [],
    namespace: null,
    add: function(type, name, fun) {
      mag.aspect.injectors.push({
        type: type,
        name: name,
        fun: fun
      });
    },
    attach: function() {
      for (var i in mag.aspect.injectors) {
        var inject = mag.aspect.injectors[i];
        if (mag.aspect[inject.type]) {
          mag.aspect[inject.type](inject.name, inject.fun);
        }
      }
    },
    around: function(pointcut, advice) {
      var ns = mag.aspect.namespace;
      for (var member in mag.aspect.namespace) {
        if (typeof ns[member] == 'function' && member.match(pointcut)) {
          (function(fn, fnName, ns) {
            ns[fnName] = function() {
              return advice.call(ns, {
                fn: fn,
                fnName: fnName,
                arguments: arguments
              });
            };
          })(ns[member], member, ns);
        }
      }
    },
    before: function(pointcut, advice) {
      mag.aspect.around(pointcut,
        function(f) {
          advice.apply(mag.aspect.namespace, f.arguments);
          return mag.aspect.next(f)
        });
    },
    after: function(pointcut, advice) {
      mag.aspect.around(pointcut,
        function(f) {
          var ret = mag.aspect.next(f);
          advice.apply(mag.aspect.namespace, f.arguments);
          return ret;
        });
    },
    next: function(f) {
      return f.fn.apply(mag.aspect.namespace, f.arguments);
    }
  };
  mag.inject = function(ns) {
    mag.aspect.namespace = ns;
    mag.aspect.attach();
  };
  mag.module = function(name, /* [] = create new override existing 'name' */ dependentModules) {
    log('info', 'module name:' + name);
    this.modules = this.modules || {};
    var instance = this.modules[name];
    //TODO: create new instance if second parameter is empty array
    // USE CASES; 1. module exists && no dependencies
    if (instance && ((!dependentModules) || (dependentModules && dependentModules.length != 0))) {
      return instance;
    }
    var Injector = {
      namespace: undefined,
      dependencies: {},
      waiting: [],
      findArgs: function(target) {
        if (typeof target !== 'function') return;
        var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
        var FN_ARG_SPLIT = /,/;
        var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
        var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
        var text = target.toString().replace(STRIP_COMMENTS, '');
        var argDecl = text.match(FN_ARGS);
        var args = argDecl[1].split(FN_ARG_SPLIT).map(
          function(arg) {
            return arg.trim()
          });
        return args;
      },
      getInstance: function(instance) {
        this.instances = this.instances || {};
        this.instances[this.namespace] = this.instances[this.namespace] || {};
        if (this.instances[this.namespace][instance]) {
          return this.instances[this.namespace][instance];
        }
      },
      setInstance: function(instance, object) {
        this.instances[this.namespace][instance] = object;
      },
      process: function(target, sargs, instance, context, name) {
        var args = this.findArgs(target);
        var these = sargs || args;

        function construct(constructor, args, context) {
          function F() {
            return constructor.apply(context || this, args);
          }
          F.prototype = constructor.prototype;
          return new F();
        }
        if (instance) {
          //TODO: cache to maintain state for services, good idea?
          var object = this.getInstance(instance);
          if (object) return object;
          object = construct(target, this.getArrayDependencies(these));
          this.setInstance(instance, object);
          return object;
        }
        if (this.isRegistered(these)) {
          var promise = target.apply(context, this.getArrayDependencies(these));

          if (promise && promise.done) {
            promise.done(function() {
              (context.controls[name]);
            })
          };

        } else {
          //wait for notice
          var waiter = {
            target: target,
            args: these
          };
          this.waiting.push(waiter);
        }
      },
      isRegistered: function(args) {
        var registered = true;
        log('info', 'isRegistered args:', args);
        for (var i in args) {
          var name = args[i];
          if (!this.getDependencies()[name]) {
            log('info', 'Dependency not registered when called:', name);
            registered = false;
            break;
          }
        }
        return registered;
      },
      getArrayDependencies: function(arr) {
        var depends = this.getDependencies();
        // make sure dependencies requires are loaded
        var that = this;
        return arr.map(function(value) {
          // need to return promise/deferred objects
          if (depends[value] && depends[value]['__requires']) {
            log('info', 'this dependency has dependencies: ' + value);
            log('info', 'requires: ' + depends[value]['__requires']);
          }
          if (depends[value] && depends[value]['__instance']) {
            return that.process(depends[value], null, value);
            //return new depends[value];
          }
          return depends[value];
        });
      },
      getDependencies: function(namespace) {
        return this.dependencies[namespace || this.namespace] || {};
      },
      register: function(name, dependency, instance) {
        var depends = this.findArgs(dependency);
        log('info', name + ' requires ' + depends);
        this.getDependencies()[name] = dependency;
        if (instance) this.getDependencies()[name]['__instance'] = instance;
        this.getDependencies()[name]['__requires'] = depends;
        this.service();
      },
      service: function() {
        for (var i in this.waiting) {
          var waiter = this.waiting[i];
          if (this.isRegistered(waiter.args)) {
            waiter.target.apply(waiter.target, this.getArrayDependencies(waiter.args));
            delete this.waiting[i];
          }
        }
      }
    };
    Injector.namespace = name;
    Injector.dependencies[name] = {};
    // load dependency modules first
    if (dependentModules) {
      var loadDependencies = function(dependentModules) {
        var depends = [];
        for (var index = 0, size = dependentModules.length; index < size; index++) {
          var dependent = dependentModules[index];
          if (this.modules[dependent]) {
            var depend = this.modules[dependent];
            depends.push(depend);
            //if dependency not yet defined give it to the waiter
            for (var skey in depend.services) {
              Injector.register(skey, depend.services[skey], 1);
            }
            for (var fkey in depend.factories) {
              Injector.register(fkey, depend.factories[fkey]());
            }
          }
        }
      }.bind(this);
      loadDependencies(dependentModules);
    }

    function processArgs(fun) {
      var args;
      if (typeof fun != 'function') {
        args = fun;
        var mfun = args.pop();
        var fs = mfun.toString();
        var nf = fs.substring(fs.indexOf("{") + 1, fs.lastIndexOf("}"));
        fun = new Function(args.join(), nf);
      }
      return [fun, args];
    }
    return this.modules[name] = new function() {
      this.name = name;
      this.config = function(fun) {
        Injector.process(fun);
      };
      this.service = function(name, fun) {
        this.services = this.services || {};
        this.services[name] = this.services[name] || fun;
        Injector.register(name, fun, 1);
      };
      this.factory = function(name, fun) {
        this.factories = this.factories || {};
        this.factories[name] = this.factories[name] || fun;
        Injector.register(name, this.factories[name]());
      }
      this.control = function(name, fun) {
        this.controls = this.controls || {};
        Injector.register('Scope', this.getScope(name));
        var ret = processArgs(fun);
        this.fire('mag.control.process.begin', [name]);
        Injector.process(ret[0], ret[1], 0, this, name);
        this.fire('mag.control.process.end', [name]);
      }
      this.getScope = function(name) {
        this.controls = this.controls || {};
        return this.controls[name] = this.controls[name] || {};
      }
      this.observers = {};
      this.on = function(eventNames, listener) {
        eventNames = eventNames.split(/\s+/);
        var eventName;
        while (eventName = eventNames.shift()) {
          if (!this.observers[eventName]) this.observers[eventName] = [];
          this.observers[eventName].push(listener);
        }
      }
      this.fire = function(eventName, args) {
        if (this.observers[eventName]) {
          for (var i = 0; i < this.observers[eventName].length; i++) {
            this.observers[eventName][i].apply(this, args);
          }
        }
      }
      mag.inject(this);
    }
  }
})(window.mag = {});
<commit_msg>Update mag.js<commit_after>//////////////////////////////////
//MagJS
//////////////////////////////////
/**!
 * @name mag.js - Copyright (c) 2013, 2014 Michael Glazer
 * @description MagnumJS core code library
 * @author Michael Glazer
 * @date 4/25/2014
 * @version Alpha - 0.2.32
 * @license MIT https://github.com/magnumjs/mag.js/blob/master/LICENSE
 * @link https://github.com/magnumjs/mag.js
 */
'use strict';
(function(mag, undefined) {
  var LOG_LEVEL = 'warn'; //info|warn|error|debug|log
  window.log = function() {
    var level = [].shift.apply(arguments);
    var args = Array.prototype.slice.call(arguments);
    if (level == LOG_LEVEL && console) console[LOG_LEVEL](args.join(','));
  };
  mag.reserved = ['__requires', '__instance'];

  mag.module = function(name, /* [] = create new override existing 'name' */ dependentModules) {
    log('info', 'module name:' + name);
    this.modules = this.modules || {};
    var instance = this.modules[name];
    //TODO: create new instance if second parameter is empty array
    // USE CASES; 1. module exists && no dependencies
    if (instance && ((!dependentModules) || (dependentModules && dependentModules.length != 0))) {
      return instance;
    }
    mag.inject.namespace = name;
    mag.inject.dependencies[name] = {};
    // load dependency modules first
    if (dependentModules) {
      var loadDependencies = function(dependentModules) {
        var depends = [];
        for (var index = 0, size = dependentModules.length; index < size; index++) {
          var dependent = dependentModules[index];
          if (this.modules[dependent]) {
            var depend = this.modules[dependent];
            depends.push(depend);
            //if dependency not yet defined give it to the waiter
            for (var skey in depend.services) {
              mag.inject.register(skey, depend.services[skey], 1);
            }
            for (var fkey in depend.factories) {
              mag.inject.register(fkey, depend.factories[fkey]());
            }
          }
        }
      }.bind(this);
      loadDependencies(dependentModules);
    }

    function processArgs(fun) {
      var args;
      if (typeof fun != 'function') {
        args = fun;
        var mfun = args.pop();
        var fs = mfun.toString();
        var nf = fs.substring(fs.indexOf("{") + 1, fs.lastIndexOf("}"));
        fun = new Function(args.join(), nf);
      }
      return [fun, args];
    }
    return this.modules[name] = new function() {
      this.name = name;
      this.directive = function(name, fun) {
        // https://docs.angularjs.org/guide/directive
        // register to the renderer?
        //       .directive('myCustomer', function() {
        //   return {
        //     template: 'Name: {{customer.name}} Address: {{customer.address}}'
        //   };
        // });
      };
      this.config = function(fun) {
        mag.inject.process(fun);
      };
      this.service = function(name, fun) {
        this.services = this.services || {};
        this.services[name] = this.services[name] || fun;
        mag.inject.register(name, fun, 1);
      };
      this.factory = function(name, fun) {
        this.factories = this.factories || {};
        this.factories[name] = this.factories[name] || fun;
        mag.inject.register(name, this.factories[name]());
      }
      this.control = function(name, fun) {
        this.controls = this.controls || {};
        mag.inject.register('Scope', this.getScope(name));
        var ret = processArgs(fun);
        this.fire('mag.control.process.begin', [name]);
        mag.inject.process(ret[0], ret[1], 0, this, name);
        this.fire('mag.control.process.end', [name]);
      }
      this.getScope = function(name) {
        this.controls = this.controls || {};
        return this.controls[name] = this.controls[name] || {};
      }
      this.observers = {};
      this.on = function(eventNames, listener) {
        eventNames = eventNames.split(/\s+/);
        var eventName;
        while (eventName = eventNames.shift()) {
          if (!this.observers[eventName]) this.observers[eventName] = [];
          this.observers[eventName].push(listener);
        }
      }
      this.fire = function(eventName, args) {
        if (this.observers[eventName]) {
          for (var i = 0; i < this.observers[eventName].length; i++) {
            this.observers[eventName][i].apply(this, args);
          }
        }
      }
      mag.injection(this);
    }
  }
})(window.mag = {});
<|endoftext|>


<commit_before>import _   from 'lodash';
import Joi from 'joi';

function mapType(key, attribute) {
    switch (key) {
        // NUMBER TYPES
        case 'BIGINT':
        case 'INTEGER':
            return Joi.number().integer();

        case 'DECIMAL':
        case 'DOUBLE':
        case 'FLOAT':
            return Joi.number();

        // STRING TYPES
        case 'STRING':
        case 'TEXT':
            return Joi.string();
        case 'UUID':
            return Joi.string().guid();
        case 'ENUM':
            return Joi.string().allow(attribute.values);

        case 'DATEONLY':
        case 'DATE':
            return Joi.date();

        // OTHER TYPES
        case 'BLOB':
            return Joi.any();
        case 'BOOLEAN':
            return Joi.boolean();
        case 'ARRAY':
            return Joi.array().sparse();
        case 'JSON':
        case 'JSONB':
            return Joi.object();

        default:
            return Joi.any();
    }
}

function mapValidator(joi, validator, key) {
    if (validator === false) { return joi; }

    switch (key) {
        case 'is':
            return joi.regex(validator);
        case 'isEmail':
            return joi.email();
        case 'isUrl':
            return joi.uri();
        case 'isIP':
            return joi.ip();
        case 'isIPv4':
            return joi.ip({ version: ['ipv4'] });
        case 'isIPv6':
            return joi = joi.ip({ version: ['ipv6'] });
        case 'min':
            return joi.min(validator);
        case 'max':
            return joi.max(validator);
        case 'notEmpty':
            return joi.min(1);
        default:
            return joi;
    }
}

export default function (attribute) {
    let joi = mapType(_.get(attribute, 'type.key', ''), attribute);

    // Add model comments to schema description
    if (attribute.comment) {
        joi = joi.description(attribute.comment);
    }

    if (attribute.allowNull === false) {
        joi = joi.required();
    } else {
        joi = joi.allow(null);
    }

    if (attribute.defaultValue && !_.isObject(attribute.defaultValue) && !_.isFunction(attribute.defaultValue)) {
        joi = joi.default(attribute.defaultValue);
    }

    _.each(attribute.validate, (validator, key) => {
        joi = mapValidator(joi, validator, key);
    });

    return joi;
}
<commit_msg>:sparkles: feat: add validation for array type<commit_after>import _   from 'lodash';
import Joi from 'joi';

function mapType(key, attribute) {
    switch (key) {
        // NUMBER TYPES
        case 'BIGINT':
        case 'INTEGER':
            return Joi.number().integer();

        case 'DECIMAL':
        case 'DOUBLE':
        case 'FLOAT':
            return Joi.number();

        // STRING TYPES
        case 'STRING':
        case 'TEXT':
            return Joi.string();
        case 'UUID':
            return Joi.string().guid();
        case 'ENUM':
            return Joi.string().allow(attribute.values);

        case 'DATEONLY':
        case 'DATE':
            return Joi.date();

        // OTHER TYPES
        case 'BLOB':
            return Joi.any();
        case 'BOOLEAN':
            return Joi.boolean();
        case 'ARRAY':
            return Joi.array().sparse().items(mapType(_.get(attribute, 'type.type.key', ''), attribute.type));
        case 'JSON':
        case 'JSONB':
            return Joi.object();

        default:
            return Joi.any();
    }
}

function mapValidator(joi, validator, key) {
    if (validator === false) { return joi; }

    switch (key) {
        case 'is':
            return joi.regex(validator);
        case 'isEmail':
            return joi.email();
        case 'isUrl':
            return joi.uri();
        case 'isIP':
            return joi.ip();
        case 'isIPv4':
            return joi.ip({ version: ['ipv4'] });
        case 'isIPv6':
            return joi = joi.ip({ version: ['ipv6'] });
        case 'min':
            return joi.min(validator);
        case 'max':
            return joi.max(validator);
        case 'notEmpty':
            return joi.min(1);
        default:
            return joi;
    }
}

export default function (attribute) {
    let joi = mapType(_.get(attribute, 'type.key', ''), attribute);

    // Add model comments to schema description
    if (attribute.comment) {
        joi = joi.description(attribute.comment);
    }

    if (attribute.allowNull === false) {
        joi = joi.required();
    } else {
        joi = joi.allow(null);
    }

    if (attribute.defaultValue && !_.isObject(attribute.defaultValue) && !_.isFunction(attribute.defaultValue)) {
        joi = joi.default(attribute.defaultValue);
    }

    _.each(attribute.validate, (validator, key) => {
        joi = mapValidator(joi, validator, key);
    });

    return joi;
}
<|endoftext|>


<commit_before>/* globals document console window */

document.addEventListener('DOMContentLoaded', () => {

    const in_view = el => {
        const top = el.getBoundingClientRect().top;
        const bottom = el.getBoundingClientRect().bottom;
        return top >= 0 && bottom <= window.innerHeight;
    };

    const scroll_into_view = el => {
        if (!in_view(el)) {
            el.scrollIntoView();
            window.scroll(0, window.scrollY);
        }
    };

    const disable_all_modals = () => {
        [...document.querySelectorAll('.modal-container')].forEach(l => {
            l.classList.add('hidden');
        });
    };

    const nav = selector => {
        let link = document.querySelector(selector);

        link.classList.add('active');

        return {
            next: () => {
                if (link.nextSibling == null) {
                    return;
                }
                link.classList.remove('active');
                link = link.nextSibling;
                scroll_into_view(link);
                link.classList.add('active');
            },
            previous: () => {
                if (link.previousSibling == null) {
                    window.scrollTo(0, 0);
                    return;
                }
                link.classList.remove('active');
                link = link.previousSibling;
                scroll_into_view(link);
                link.classList.add('active');
            },
            current: link
        };
    };

    const toggle_help_menu = () => {
        document.querySelector('#help').classList.toggle('hidden');
    };

    const toggle_settings_menu = () => {
        document.querySelector('#settings').classList.toggle('hidden');
    };

    const links_nav = nav('.link-container > li');

    document.addEventListener('keydown', event => {

        if (document.activeElement.tagName.toLowerCase() !== 'body') return;

        // takes in `event` from the current scope so it can be called more cleanly
        const is_key = k => {
            return k === {
                75: 'k',
                74: 'j',
                76: 'l',
                72: 'h',
                68: 'd',
                65: 'a',
                83: 's',
                70: 'f',
                78: 'n',
                79: 'o',
                80: 'p',
                191: '/',
                13: 'enter',
                27: 'esc',
                219: ']',
                51: '3',
                188: ','
            }[event.keyCode];
        };

        if (is_key('j') || (event.ctrlKey && is_key('n'))) {
            links_nav.next();
        } else if (is_key('k') || (event.ctrlKey && is_key('p'))) {
            links_nav.previous();
        } else if (is_key('d')) {
            console.log('delete');
        } else if (is_key('a')) {
            console.log('archive');
        } else if (is_key('/') && event.shiftKey) {
            toggle_help_menu();
        } else if (is_key('/')) {
            console.log('search');
        } else if (is_key('l')) {
            console.log('switch to right column || wrap around to the left column');
        } else if (is_key('h')) {
            console.log('switch to left coloumn || wrap around to the right column');
        } else if (is_key('o')) {
            console.log('open in a new tab');
        } else if (is_key('enter')) {
            console.log('open in current tab');
        } else if (is_key('esc') || (is_key(']') && event.ctrlKey)) {
            disable_all_modals();
        } else if (is_key('3') && event.shiftKey) {
            console.log('delete current item');
        } else if (is_key(',')) {
            console.log('toggle settings menu');
            toggle_settings_menu();
        }
        console.log(event.keyCode);
        console.log(event.ctrlKey);

    });

});
<commit_msg>Keybinds now work to open links<commit_after>/* globals document console window */

document.addEventListener('DOMContentLoaded', () => {

    const in_view = el => {
        const top = el.getBoundingClientRect().top;
        const bottom = el.getBoundingClientRect().bottom;
        return top >= 0 && bottom <= window.innerHeight;
    };

    const scroll_into_view = el => {
        if (!in_view(el)) {
            el.scrollIntoView();
            window.scroll(0, window.scrollY);
        }
    };

    const disable_all_modals = () => {
        [...document.querySelectorAll('.modal-container')].forEach(l => {
            l.classList.add('hidden');
        });
    };

    const nav = selector => {
        let link = document.querySelector(selector);

        link.classList.add('active');

        return {
            next: () => {
                if (link.nextSibling == null) {
                    return;
                }
                link.classList.remove('active');
                link = link.nextSibling;
                scroll_into_view(link);
                link.classList.add('active');
            },
            previous: () => {
                if (link.previousSibling == null) {
                    window.scrollTo(0, 0);
                    return;
                }
                link.classList.remove('active');
                link = link.previousSibling;
                scroll_into_view(link);
                link.classList.add('active');
            },
            current: link
        };
    };

    const toggle_help_menu = () => {
        document.querySelector('#help').classList.toggle('hidden');
    };

    const toggle_settings_menu = () => {
        document.querySelector('#settings').classList.toggle('hidden');
    };

    const open_current_link_current_tab = () => {
        window.location.href = document.querySelector('.link-container > li.active > a.source').href;
    };

    const open_current_link_new_tab = () => {
        const url = document.querySelector('.link-container > li.active > a.source').href;
        window.open(url, '_blank');
    };

    const links_nav = nav('.link-container > li');

    document.addEventListener('keydown', event => {

        if (document.activeElement.tagName.toLowerCase() !== 'body') return;

        // takes in `event` from the current scope so it can be called more cleanly
        const is_key = k => {
            return k === {
                75: 'k',
                74: 'j',
                76: 'l',
                72: 'h',
                68: 'd',
                65: 'a',
                83: 's',
                70: 'f',
                78: 'n',
                79: 'o',
                80: 'p',
                191: '/',
                13: 'enter',
                27: 'esc',
                219: ']',
                51: '3',
                188: ','
            }[event.keyCode];
        };

        if (is_key('j') || (event.ctrlKey && is_key('n'))) {
            links_nav.next();
        } else if (is_key('k') || (event.ctrlKey && is_key('p'))) {
            links_nav.previous();
        } else if (is_key('d')) {
            console.log('delete');
        } else if (is_key('a')) {
            console.log('archive');
        } else if (is_key('/') && event.shiftKey) {
            toggle_help_menu();
        } else if (is_key('/')) {
            console.log('search');
        } else if (is_key('l')) {
            console.log('switch to right column || wrap around to the left column');
        } else if (is_key('h')) {
            console.log('switch to left coloumn || wrap around to the right column');
        } else if (is_key('o')) {
            open_current_link_new_tab();
        } else if (is_key('enter')) {
            open_current_link_current_tab();
        } else if (is_key('esc') || (is_key(']') && event.ctrlKey)) {
            disable_all_modals();
        } else if (is_key('3') && event.shiftKey) {
            console.log('delete current item');
        } else if (is_key(',')) {
            console.log('toggle settings menu');
            toggle_settings_menu();
        }
        console.log(event.keyCode);
        console.log(event.ctrlKey);

    });

});
<|endoftext|>


<commit_before>// @ts-check
'use strict';

const spawnSync = require('child_process').spawnSync;
const castArray = require('lodash/castArray');
const listify = require('listify');
const json = require('./formats/json');

/**
 * Install given npm packages if they aren’t installed yet
 *
 * @param {string|string[]} deps
 * @param {Object} [options]
 * @param {boolean} [options.dev=true] --save-dev
 * @param {Function} [exec]
 */
function install(deps, options, exec) {
	options = options || {};
	deps = castArray(deps);
	const dev = options.dev !== false;

	const pkg = json('package.json', {
		dependencies: {},
		devDependencies: {},
	});
	const installed = pkg.get(dev ? 'devDependencies' : 'dependencies') || {};

	const newDeps = deps.filter(dep => !installed[dep]);
	if (newDeps.length === 0) {
		return;
	}

	// eslint-disable-next-line no-console
	console.log(`Installing ${listify(newDeps)}...`);
	runNpm(newDeps, { dev }, exec);
}

/*
 * Uninstall given npm packages
 *
 * @param {string|string[]} deps
 * @param {Object} [options]
 * @param {boolean} [options.dev=true] --save-dev
 * @param {Function} [exec]
 */
function uninstall(deps, options, exec) {
	options = options || {};
	deps = castArray(deps);
	const dev = options.dev !== false;

	const pkg = json('package.json', {
		dependencies: {},
		devDependencies: {},
	});
	const installed = pkg.get(dev ? 'devDependencies' : 'dependencies') || {};

	const newDeps = deps.filter(dep => installed[dep]);

	if (newDeps.length === 0) {
		return;
	}

	// eslint-disable-next-line no-console
	console.log(`Uninstalling ${listify(newDeps)}...`);
	runNpm(newDeps, { remove: true, dev }, exec);
}

/**
 * Install given npm packages
 *
 * @param {Array|string} deps
 * @param {Object} [options]
 * @param {boolean} [options.dev=true] --save-dev (--save by default)
 * @param {boolean} [options.remove=false] uninstall package (install by default)
 * @param {Function} [exec]
 * @return {Object}
 */
function runNpm(deps, options, exec) {
	options = options || {};
	exec = exec || spawnSync;

	const args = [
		options.remove ? 'uninstall' : 'install',
		options.dev ? '--save-dev' : '--save',
	].concat(deps);

	return exec('npm', args, {
		stdio: options.stdio === undefined ? 'inherit' : options.stdio,
		cwd: options.cwd,
	});
}

module.exports = {
	install,
	uninstall,
};
<commit_msg>Refactor: json → packageJson<commit_after>// @ts-check
'use strict';

const spawnSync = require('child_process').spawnSync;
const castArray = require('lodash/castArray');
const listify = require('listify');
const packageJson = require('./files/packageJson');

/**
 * Install given npm packages if they aren’t installed yet
 *
 * @param {string|string[]} deps
 * @param {Object} [options]
 * @param {boolean} [options.dev=true] --save-dev
 * @param {Function} [exec]
 */
function install(deps, options, exec) {
	options = options || {};
	deps = castArray(deps);
	const dev = options.dev !== false;

	const pkg = packageJson({
		dependencies: {},
		devDependencies: {},
	});
	const installed = pkg.get(dev ? 'devDependencies' : 'dependencies') || {};

	const newDeps = deps.filter(dep => !installed[dep]);
	if (newDeps.length === 0) {
		return;
	}

	// eslint-disable-next-line no-console
	console.log(`Installing ${listify(newDeps)}...`);
	runNpm(newDeps, { dev }, exec);
}

/*
 * Uninstall given npm packages
 *
 * @param {string|string[]} deps
 * @param {Object} [options]
 * @param {boolean} [options.dev=true] --save-dev
 * @param {Function} [exec]
 */
function uninstall(deps, options, exec) {
	options = options || {};
	deps = castArray(deps);
	const dev = options.dev !== false;

	const pkg = packageJson({
		dependencies: {},
		devDependencies: {},
	});
	const installed = pkg.get(dev ? 'devDependencies' : 'dependencies') || {};

	const newDeps = deps.filter(dep => installed[dep]);

	if (newDeps.length === 0) {
		return;
	}

	// eslint-disable-next-line no-console
	console.log(`Uninstalling ${listify(newDeps)}...`);
	runNpm(newDeps, { remove: true, dev }, exec);
}

/**
 * Install given npm packages
 *
 * @param {Array|string} deps
 * @param {Object} [options]
 * @param {boolean} [options.dev=true] --save-dev (--save by default)
 * @param {boolean} [options.remove=false] uninstall package (install by default)
 * @param {Function} [exec]
 * @return {Object}
 */
function runNpm(deps, options, exec) {
	options = options || {};
	exec = exec || spawnSync;

	const args = [
		options.remove ? 'uninstall' : 'install',
		options.dev ? '--save-dev' : '--save',
	].concat(deps);

	return exec('npm', args, {
		stdio: options.stdio === undefined ? 'inherit' : options.stdio,
		cwd: options.cwd,
	});
}

module.exports = {
	install,
	uninstall,
};
<|endoftext|>


<commit_before>;(function(global, undefined) {
'use strict';

var document = global.document;
var IS_SUPPORT_TOUCH_EVENT = 'ontouchstart' in document;
var IS_SUPPORT_POINTER_EVENT = !!global.PointerEvent;
var EVENTS = {
        START  : IS_SUPPORT_TOUCH_EVENT && 'touchstart'  || IS_SUPPORT_POINTER_EVENT && 'pointerdown'   || 'mousedown',
        MOVE   : IS_SUPPORT_TOUCH_EVENT && 'touchmove'   || IS_SUPPORT_POINTER_EVENT && 'pointermove'   || 'mousemove',
        END    : IS_SUPPORT_TOUCH_EVENT && 'touchend'    || IS_SUPPORT_POINTER_EVENT && 'pointerup'     || 'mouseup',
        CANCEL : IS_SUPPORT_TOUCH_EVENT && 'touchcancel' || IS_SUPPORT_POINTER_EVENT && 'pointercancel' || 'mouseleave'
};
var defaultSetting = {
        pressDuration: 500,
        doubleTapDuration: 400,
        motionThreshold: 5,
        preventClickEvent: true
};
var identifierKey = IS_SUPPORT_TOUCH_EVENT && 'identifier' || IS_SUPPORT_POINTER_EVENT && 'pointerId' || 'button';

function Paw(rootNode, option) {
    if (rootNode && !rootNode.addEventListener) {
        throw new Error('Argument Error: First argument must be Node');
    }
    var setting = this.setting = {};

    if (!option) {
        option = {};
    }
    for (var key in defaultSetting) {
        setting[key] = (option[key] !== undefined) ? option[key] : defaultSetting[key];
    }
    this.rootNode = rootNode || document;
    this.rootNode.addEventListener(EVENTS.START, this);
    this.handlers = {};
    this.timers = {};
}

Paw.keys = Object.keys || (_ && _.keys);
Paw.IS_SUPPORT_TOUCH_EVENT = IS_SUPPORT_TOUCH_EVENT;
Paw.IS_SUPPORT_POINTER_EVENT = IS_SUPPORT_POINTER_EVENT;
Paw.EVENT_TYPES = {
        TAP: 'tap',
        DOUBLE_TAP: 'doubletap',
        PRESS: 'press',
        CLICK: 'click'
};
Paw.EVENT_INTERFACES = {
    TOUCH_EVENT   : 'touchevent',
    POINTER_EVENT : 'pointerevent',
    MOUSE_EVENT   : 'mouseevent'
};

Paw.prototype = {
    constructor: Paw,
    handleEvent: _handleEvent,
    onStart: _onStart,
    onMove: _onMove,
    onEnd: _onEnd,
    onCancel: _onCancel,
    onTimeout: _onTimeout,
    setTimer: _setTimer,
    clearTimer: _clearTimer,
    bindEvents: _bindEvents,
    unbindEvents: _unbindEvents,
    dispose: _dispose
};

function _handleEvent(ev) {
    switch (ev.type) {
        case EVENTS.MOVE:
            this.onMove(ev);
            break;
        case EVENTS.START:
            this.onStart(ev);
            break;
        case EVENTS.END:
            this.onEnd(ev);
            break;
        case EVENTS.CANCEL:
            this.onCancel(ev);
            break;
    }
}

function _onStart(ev) {
    var setting = this.setting;
    var handlers = this.handlers;
    var touches = __getTouchInfoList(ev);
    var handler, touchInfo, id;

    for (var i = 0, iz = touches.length; i < iz; i++) {
        touchInfo = touches[i];
        id = touchInfo[identifierKey];
        handler = new Paw.Touch(id, touchInfo, setting);
        handlers[id] = handler;
        this.setTimer(id);
    }
    this.bindEvents();
}

function _onMove(ev) {
    var handlers = this.handlers;
    var touches = __getTouchInfoList(ev);
    var touchInfo, handler, id;

    for (var i = 0, iz = touches.length; i < iz; i++) {
        touchInfo = touches[i];
        id = touchInfo[identifierKey];
        handler = handlers[id];
        if (handler) {
            handler.move(touchInfo);
        }
    }
}

function _onEnd(ev) {
    var handlers = this.handlers;
    var touches = __getTouchInfoList(ev);
    var touchInfo, handler, id;

    for (var i = 0, iz = touches.length; i < iz; i++) {
        touchInfo = touches[i];
        id = touchInfo[identifierKey];
        handler = handlers[id];
        if (handler) {
            handler.end(touchInfo);
            delete handlers[id];
        }
        this.clearTimer(id);
    }
    this.unbindEvents();
}

function _onCancel(ev) {
    var handlers = this.handlers;
    var touches = __getTouchInfoList(ev);
    var touchInfo, handler, id;

    for (var i = 0, iz = touches.length; i < iz; i++) {
        touchInfo = touches[i];
        id = touchInfo[identifierKey];
        handler = handlers[id];
        if (handler) {
            handler.cancel(touchInfo);
            delete handlers[id];
        }
        this.clearTimer(id);
    }
    this.unbindEvents();
}

function _onTimeout(id) {
    var handlers = this.handlers;
    var handler = handlers[id];

    if (handler) {
        handler.timeout();
        delete handlers[id];
    }
    this.clearTimer(id);
}

function _setTimer(id) {
    var that = this;

    this.timers[id] = global.setTimeout(function() {
        that.onTimeout(id);
    }, this.setting.pressDuration);
}

function _clearTimer(id) {
    var timers = this.timers;

    global.clearTimeout(timers[id]);
    delete timers[id];
}

function _bindEvents() {
    if (this.boundEvents) {
        return;
    }
    var rootNode = this.rootNode;

    this.boundEvents = true;
    rootNode.addEventListener(EVENTS.MOVE, this);
    rootNode.addEventListener(EVENTS.END, this);
    rootNode.addEventListener(EVENTS.CANCEL, this);
}

function _unbindEvents() {
    if (!this.boundEvents || Paw.keys(this.handlers).length > 0) {
        return;
    }
    var rootNode = this.rootNode;

    this.boundEvents = false;
    rootNode.removeEventListener(EVENTS.MOVE, this);
    rootNode.removeEventListener(EVENTS.END, this);
    rootNode.removeEventListener(EVENTS.CANCEL, this);
}

function _dispose(cond) {
    var handlers = this.handlers;
    var rootNode = this.rootNode;

    for (var id in handlers) {
        delete handlers[id];
        this.clearTimer(id);
    }
    rootNode.removeEventListener(EVENTS.START);
    this.unbindEvents();
    if (cond) {
        Paw.Touch.dispose();
    }
}

//// private methods
function __getTouchInfoList(ev) {
    return IS_SUPPORT_TOUCH_EVENT && ev.changedTouches || [ev];
}

// exports
global.Paw = Paw;

})(this.self || global, void 0);
<commit_msg>add Paw.createTouchEvent method<commit_after>;(function(global, undefined) {
'use strict';

var document = global.document;
var IS_SUPPORT_TOUCH_EVENT = 'ontouchstart' in document;
var IS_SUPPORT_POINTER_EVENT = !!global.PointerEvent;
var EVENTS = {
        START  : IS_SUPPORT_TOUCH_EVENT && 'touchstart'  || IS_SUPPORT_POINTER_EVENT && 'pointerdown'   || 'mousedown',
        MOVE   : IS_SUPPORT_TOUCH_EVENT && 'touchmove'   || IS_SUPPORT_POINTER_EVENT && 'pointermove'   || 'mousemove',
        END    : IS_SUPPORT_TOUCH_EVENT && 'touchend'    || IS_SUPPORT_POINTER_EVENT && 'pointerup'     || 'mouseup',
        CANCEL : IS_SUPPORT_TOUCH_EVENT && 'touchcancel' || IS_SUPPORT_POINTER_EVENT && 'pointercancel' || 'mouseleave'
};
var defaultSetting = {
        pressDuration: 500,
        doubleTapDuration: 400,
        motionThreshold: 5,
        preventClickEvent: true
};
var identifierKey = IS_SUPPORT_TOUCH_EVENT && 'identifier' || IS_SUPPORT_POINTER_EVENT && 'pointerId' || 'button';

function Paw(rootNode, option) {
    if (rootNode && !rootNode.addEventListener) {
        throw new Error('Argument Error: First argument must be Node');
    }
    var setting = this.setting = {};

    if (!option) {
        option = {};
    }
    for (var key in defaultSetting) {
        setting[key] = (option[key] !== undefined) ? option[key] : defaultSetting[key];
    }
    this.rootNode = rootNode || document;
    this.rootNode.addEventListener(EVENTS.START, this);
    this.handlers = {};
    this.timers = {};
}

Paw.IS_SUPPORT_TOUCH_EVENT = IS_SUPPORT_TOUCH_EVENT;
Paw.IS_SUPPORT_POINTER_EVENT = IS_SUPPORT_POINTER_EVENT;
Paw.EVENT_TYPES = {
        TAP: 'tap',
        DOUBLE_TAP: 'doubletap',
        PRESS: 'press',
        CLICK: 'click'
};
Paw.EVENT_INTERFACES = {
    TOUCH_EVENT   : 'touchevent',
    POINTER_EVENT : 'pointerevent',
    MOUSE_EVENT   : 'mouseevent'
};
Paw.keys = Object.keys || (_ && _.keys);
Paw.env = __getEnvData(global.navigator.userAgent);
Paw.createTouchEvent = (function(env) {
    var _defaultView = document.defaultView;

    if (env.isAndroid && (env.version && env.version[0] < 4)) {
        return function(type, target, bubbles, cancelable, pageX, pageY, identifier) {
            var event = document.createEvent('MouseEvent');
            var touchList = _getTouchList(target, identifier, pageX, pageY);

            event.initMouseEvent(
                type,
                bubbles,
                cancelable,
                _defaultView,
                1, // detail
                0, // screenX
                0, // screenY
                pageX,
                pageY,
                false, // ctrlKey
                false, // altKey
                false, // shiftKey
                false, // metaKey
                identifier,
                null // relatedTarget
            );
            event.touches = touchList;
            event.targetTouches = touchList;
            event.changedTouches = touchList;
            event.scale = 0;
            event.rotation = 0;
            return event;
        };
    }
    // create touch event for android stock browser spec
    else if (env.isAndroid && !env.isChrome) {
        return function(type, target, bubbles, cancelable, pageX, pageY, identifier) {
            var event = document.createEvent('MouseEvent');
            var touchList = _getTouchList(target, identifier, pageX, pageY);

            event.initTouchEvent(
                touchList,
                touchList,
                touchList,
                type,
                _defaultView,
                0, // screenX
                0, // screenY
                pageX,
                pageY,
                false, // ctrlKey
                false, // altKey
                false, // shiftKey
                false  // metaKey
            );
            return event;
        };
    }
    // w3c spec touch event
    else {
        return function(type, target, bubbles, cancelable, pageX, pageY, identifier) {
            var event = document.createEvent('MouseEvent');
            var touchList = _getTouchList(target, identifier, pageX, pageY);

            event.initTouchEvent(
                type,
                bubbles,
                cancelable,
                _defaultView,
                1, // detail
                0, // screenX
                0, // screenY
                pageX,
                pageY,
                false, // ctrlKey
                false, // altKey
                false, // shiftKey
                false, // metaKey
                touchList,
                touchList,
                touchList,
                0, // scale
                0  // rotation
            );
            return event;
        };
    }

    function _getTouchList(target, identifier, pageX, pageY) {
        var touch = document.createTouch(
                _defaultView,
                target,
                identifier,
                pageX,
                pageY,
                0, // screenX
                0, // screenY
                0, // clientX
                0, // clientY
                0, // radiusX
                0, // radiusY
                0, // rotationAngle
                1  // force
        );

        return document.createTouchList(touch);
    }
})(Paw.env);

Paw.prototype = {
    constructor: Paw,
    handleEvent: _handleEvent,
    onStart: _onStart,
    onMove: _onMove,
    onEnd: _onEnd,
    onCancel: _onCancel,
    onTimeout: _onTimeout,
    setTimer: _setTimer,
    clearTimer: _clearTimer,
    bindEvents: _bindEvents,
    unbindEvents: _unbindEvents,
    dispose: _dispose
};

function _handleEvent(ev) {
    switch (ev.type) {
        case EVENTS.MOVE:
            this.onMove(ev);
            break;
        case EVENTS.START:
            this.onStart(ev);
            break;
        case EVENTS.END:
            this.onEnd(ev);
            break;
        case EVENTS.CANCEL:
            this.onCancel(ev);
            break;
    }
}

function _onStart(ev) {
    var setting = this.setting;
    var handlers = this.handlers;
    var touches = __getTouchInfoList(ev);
    var handler, touchInfo, id;

    for (var i = 0, iz = touches.length; i < iz; i++) {
        touchInfo = touches[i];
        id = touchInfo[identifierKey];
        handler = new Paw.Touch(id, touchInfo, setting);
        handlers[id] = handler;
        this.setTimer(id);
    }
    this.bindEvents();
}

function _onMove(ev) {
    var handlers = this.handlers;
    var touches = __getTouchInfoList(ev);
    var touchInfo, handler, id;

    for (var i = 0, iz = touches.length; i < iz; i++) {
        touchInfo = touches[i];
        id = touchInfo[identifierKey];
        handler = handlers[id];
        if (handler) {
            handler.move(touchInfo);
        }
    }
}

function _onEnd(ev) {
    var handlers = this.handlers;
    var touches = __getTouchInfoList(ev);
    var touchInfo, handler, id;

    for (var i = 0, iz = touches.length; i < iz; i++) {
        touchInfo = touches[i];
        id = touchInfo[identifierKey];
        handler = handlers[id];
        if (handler) {
            handler.end(touchInfo);
            delete handlers[id];
        }
        this.clearTimer(id);
    }
    this.unbindEvents();
}

function _onCancel(ev) {
    var handlers = this.handlers;
    var touches = __getTouchInfoList(ev);
    var touchInfo, handler, id;

    for (var i = 0, iz = touches.length; i < iz; i++) {
        touchInfo = touches[i];
        id = touchInfo[identifierKey];
        handler = handlers[id];
        if (handler) {
            handler.cancel(touchInfo);
            delete handlers[id];
        }
        this.clearTimer(id);
    }
    this.unbindEvents();
}

function _onTimeout(id) {
    var handlers = this.handlers;
    var handler = handlers[id];

    if (handler) {
        handler.timeout();
        delete handlers[id];
    }
    this.clearTimer(id);
}

function _setTimer(id) {
    var that = this;

    this.timers[id] = global.setTimeout(function() {
        that.onTimeout(id);
    }, this.setting.pressDuration);
}

function _clearTimer(id) {
    var timers = this.timers;

    global.clearTimeout(timers[id]);
    delete timers[id];
}

function _bindEvents() {
    if (this.boundEvents) {
        return;
    }
    var rootNode = this.rootNode;

    this.boundEvents = true;
    rootNode.addEventListener(EVENTS.MOVE, this);
    rootNode.addEventListener(EVENTS.END, this);
    rootNode.addEventListener(EVENTS.CANCEL, this);
}

function _unbindEvents() {
    if (!this.boundEvents || Paw.keys(this.handlers).length > 0) {
        return;
    }
    var rootNode = this.rootNode;

    this.boundEvents = false;
    rootNode.removeEventListener(EVENTS.MOVE, this);
    rootNode.removeEventListener(EVENTS.END, this);
    rootNode.removeEventListener(EVENTS.CANCEL, this);
}

function _dispose(cond) {
    var handlers = this.handlers;
    var rootNode = this.rootNode;

    for (var id in handlers) {
        delete handlers[id];
        this.clearTimer(id);
    }
    rootNode.removeEventListener(EVENTS.START);
    this.unbindEvents();
    if (cond) {
        Paw.Touch.dispose();
    }
}

//// private methods
function __getTouchInfoList(ev) {
    return IS_SUPPORT_TOUCH_EVENT && ev.changedTouches || [ev];
}

function __getEnvData(ua) {
    ua = ua.toLowerString();

    var appleWebkitRE = /applewebkit/;
    var res = {
        isAndroid : /android/.test(ua),
        isIOS     : /ip(hone|od|ad)/.test(ua),
        isChrome  : /(chrome|crios)/.test(ua),
        versionString: null,
        version: null
    };
    var version, versionString;

    res.isAndroidBrowser = !res.isChrome && res.isAndroid && appleWebkitRE.test(ua);
    res.isMobileSafari = !res.isChrome && res.isIOS && appleWebkitRE.test(ua);

    versionString =
        (res.isAndroidBrowser || res.android && res.chrome) ? ua.match(/android\s(\S.*?)\;/) :
        (res.isMobileSafari || res.isIOS && res.chrome) ? ua.match(/os\s(\S.*?)\s/) :
        null;
    if (versionString) {
        if (res.isIOS) {
            versionString = versionString[1].replace('_', '.');
        } else {
            versionString = versionString[1];
        }
        version = versionString.split('.');
        for (var i = 0, iz = version.length; i < iz; i++) {
            version[i] = version[i]|0;
        }
        res.versionString = versionString;
        res.version = version;
    }
    return res;
}

// exports
global.Paw = Paw;

})(this.self || global, void 0);
<|endoftext|>


<commit_before>import assert from 'assert';
import jsonFile from 'json-file-plus';
import Q from 'q';
import exec from './exec';
import semverRegex from 'semver-regex';
import { memoize } from 'lodash';

// update to exact versions
// return whether the new version is not a major bump (ie, safe to merge without review)
const exactVersion = version => {
    const match = version.match(semverRegex());
    assert(match, `${version} must be valid semver`);
    return match[0];
};
const getPublishedVersion = memoize((packageName, logger) => (
    exec(`npm view ${packageName} version`, { logger }).then(version => version.trim())
));

const getVersion = ({ path, packageName, logger }) => (
    Q.fcall(() => (
        jsonFile(path)
    )).then(file => (
        Q.all([
            file.get(),
            getPublishedVersion(packageName, logger)
        ]).spread(({
            dependencies = {},
            devDependencies = {},
            peerDependencies = {}
        }) => {
            if (dependencies.hasOwnProperty(packageName)) {
                assert(!devDependencies.hasOwnProperty(packageName), `${packageName} found in both dependencies and devDependencies`);
                assert(!peerDependencies.hasOwnProperty(packageName), `${packageName} found in both dependencies and peerDependencies`);
                return exactVersion(dependencies[packageName]);
            }
            if (devDependencies.hasOwnProperty(packageName)) {
                return exactVersion(devDependencies[packageName]);
            }
            if (peerDependencies.hasOwnProperty(packageName)) {
                return exactVersion(peerDependencies[packageName]);
            }
            throw new Error(`${packageName} not found`);
        })
    ))
);

const updateVersion = ({ path, packageName, logger }) => (
    Q.fcall(() => (
        jsonFile(path)
    )).then(file => (
        Q.all([
            file.get(),
            getPublishedVersion(packageName, logger)
        ]).spread(({
            dependencies = {},
            devDependencies = {},
            peerDependencies = {}
        }, version) => {
            if (dependencies.hasOwnProperty(packageName)) {
                return file.set({
                    dependencies: {
                        [packageName]: `^${version}`
                    }
                });
            }
            if (devDependencies.hasOwnProperty(packageName)) {
                return file.set({
                    devDependencies: {
                        [packageName]: `^${version}`
                    }
                });
            }
            if (peerDependencies.hasOwnProperty(packageName)) {
                return file.set({
                    peerDependencies: {
                        [packageName]: `^${version}`
                    }
                });
            }
            throw new Error(`${packageName} not found`);
        }).then(() => (
            file.save()
        ))
    ))
);

export default ({ path, packageName, logger }) => (
    Q.fcall(() => (
        getVersion({ path, packageName, logger })
    )).then(before => (
        Q.fcall(() => (
            updateVersion({ path, packageName, logger })
        )).then(() => (
            getVersion({ path, packageName, logger })
        )).then(after => (
            [before, after]
        ))
    ))
);
<commit_msg>bail on updates when the latest version of a dep matches existing semver<commit_after>import assert from 'assert';
import jsonFile from 'json-file-plus';
import Q from 'q';
import exec from './exec';
import semverRegex from 'semver-regex';
import { memoize } from 'lodash';
import { satisfies } from 'semver';

// update to exact versions
// return whether the new version is not a major bump (ie, safe to merge without review)
const exactVersion = version => {
    const match = version.match(semverRegex());
    assert(match, `${version} must be valid semver`);
    return match[0];
};
const getPublishedVersion = memoize((packageName, logger) => (
    exec(`npm view ${packageName} version`, { logger }).then(version => version.trim())
));

const getVersion = ({ path, packageName }) => (
    Q.fcall(() => (
        jsonFile(path)
    )).then(file => (
        file.get()
    )).then(({
        dependencies = {},
        devDependencies = {},
        peerDependencies = {}
    }) => {
        if (dependencies.hasOwnProperty(packageName)) {
            assert(!devDependencies.hasOwnProperty(packageName), `${packageName} found in both dependencies and devDependencies`);
            assert(!peerDependencies.hasOwnProperty(packageName), `${packageName} found in both dependencies and peerDependencies`);
            return exactVersion(dependencies[packageName]);
        }
        if (devDependencies.hasOwnProperty(packageName)) {
            return exactVersion(devDependencies[packageName]);
        }
        if (peerDependencies.hasOwnProperty(packageName)) {
            return exactVersion(peerDependencies[packageName]);
        }
        throw new Error(`${packageName} not found`);
    })
);

const updateVersion = ({ path, packageName, logger }) => (
    Q.fcall(() => (
        jsonFile(path)
    )).then(file => (
        Q.all([
            file.get(),
            getPublishedVersion(packageName, logger)
        ]).spread(({
            dependencies = {},
            devDependencies = {},
            peerDependencies = {}
        }, version) => {
            if (dependencies.hasOwnProperty(packageName)) {
                assert(!satisfies(version, dependencies[packageName]), `${packageName} latest version ${version} matches existing dependency ${dependencies[packageName]}`);
                return file.set({
                    dependencies: {
                        [packageName]: `^${version}`
                    }
                });
            }
            if (devDependencies.hasOwnProperty(packageName)) {
                assert(!satisfies(version, devDependencies[packageName]), `${packageName} latest version ${version} matches existing devDependency version ${devDependencies[packageName]}`);
                return file.set({
                    devDependencies: {
                        [packageName]: `^${version}`
                    }
                });
            }
            if (peerDependencies.hasOwnProperty(packageName)) {
                assert(!satisfies(version, peerDependencies[packageName]), `${packageName} latest version ${version} matches existing peerDependency version ${peerDependencies[packageName]}`);
                return file.set({
                    peerDependencies: {
                        [packageName]: `^${version}`
                    }
                });
            }
            throw new Error(`${packageName} not found`);
        }).then(() => (
            file.save()
        ))
    ))
);

export default ({ path, packageName, logger }) => (
    Q.fcall(() => (
        getVersion({ path, packageName, logger })
    )).then(before => (
        Q.fcall(() => (
            updateVersion({ path, packageName, logger })
        )).then(() => (
            getVersion({ path, packageName, logger })
        )).then(after => (
            [before, after]
        ))
    ))
);
<|endoftext|>


<commit_before>import closestHead from './utils/closestHead';
import intersectOrb from './utils/intersectcenter';
import viewer from './viewer';
import InstancedItem from './instanced-item';
import Room from './room';
import layout from './room/layout';
import settings from './settings';
import controllers from './controllers';

export default function create({ rooms, orb }) {
  const { holeHeight } = settings;
  let pointerX;
  let pointerY;
  let hoverPerformance;
  let hoverOrb;

  const onMouseMove = ({ clientX, clientY }) => {
    if (viewer.vrEffect.isPresenting) return;
    pointerX = clientX;
    pointerY = clientY;
  };

  const onMouseDown = ({ clientX, clientY, touches }) => {
    if (viewer.vrEffect.isPresenting) return;
    let x = clientX;
    let y = clientY;
    if (touches && touches.length > 0) {
      x = touches[0].pageX;
      y = touches[0].pageY;
    }

    hoverOrb = intersectOrb(x, y);
    hoverPerformance = closestHead(x, y, rooms);

    if (hoverPerformance || hoverOrb) {
      viewer.switchCamera('default');
      InstancedItem.group.add(viewer.camera);
    }
  };

  const onMouseUp = () => {
    if (viewer.vrEffect.isPresenting) return;
    hoverPerformance = null;
    hoverOrb = false;
    viewer.switchCamera('orthographic');
  };

  const clearHighlights = () => {
    hoverPerformance = null;
    hoverOrb = false;
    orb.unhighlight();
    Room.setHighlight();
  };

  window.addEventListener('vrdisplaypresentchange', clearHighlights, false);

  const POV = {
    update: (progress = 0, fixedControllers = false) => {
      if (!viewer.vrEffect.isPresenting) {
        if (intersectOrb(pointerX, pointerY)) {
          orb.highlight();
          Room.setHighlight();
        } else {
          orb.unhighlight();
          if (!hoverPerformance && !hoverOrb) {
            Room.setHighlight(
              closestHead(
                pointerX,
                pointerY,
                rooms
              )
            );
          }
        }
      }

      //  for some reason position has to be done here as well as in playback
      //  otherwise the positional values begin spiraling into infinity
      const position = layout.getPosition(progress + 0.5);
      position.y += holeHeight;
      position.z *= -1;

      if (fixedControllers) {
        controllers.fixToPosition(position);
      }
      viewer.camera.position.copy(position);
      if (hoverOrb) {
        // Move camera into orb:
        viewer.camera.position.z *= -1;
        viewer.camera.rotation.set(0, Math.PI, 0);
      } else if (hoverPerformance) {
        // Move camera into head of performance:
        const [index, headIndex] = hoverPerformance;
        rooms[index].transformToHead(viewer.camera, headIndex);
      }
    },

    setupInput: () => {
      window.addEventListener('mousemove', onMouseMove);
      window.addEventListener('mousedown', onMouseDown);
      window.addEventListener('mouseup', onMouseUp);
      window.addEventListener('touchstart', onMouseDown, false);
      window.addEventListener('touchend', onMouseUp, false);
    },

    removeInput: () => {
      window.removeEventListener('mousemove', onMouseMove);
      window.removeEventListener('mousedown', onMouseDown);
      window.removeEventListener('mouseup', onMouseUp);
      window.removeEventListener('vrdisplaypresentchange', clearHighlights);
    },

    clearHighlights,
  };

  return POV;
}
<commit_msg>remove comment, since it no longer applies<commit_after>import closestHead from './utils/closestHead';
import intersectOrb from './utils/intersectcenter';
import viewer from './viewer';
import InstancedItem from './instanced-item';
import Room from './room';
import layout from './room/layout';
import settings from './settings';
import controllers from './controllers';

export default function create({ rooms, orb }) {
  const { holeHeight } = settings;
  let pointerX;
  let pointerY;
  let hoverPerformance;
  let hoverOrb;

  const onMouseMove = ({ clientX, clientY }) => {
    if (viewer.vrEffect.isPresenting) return;
    pointerX = clientX;
    pointerY = clientY;
  };

  const onMouseDown = ({ clientX, clientY, touches }) => {
    if (viewer.vrEffect.isPresenting) return;
    let x = clientX;
    let y = clientY;
    if (touches && touches.length > 0) {
      x = touches[0].pageX;
      y = touches[0].pageY;
    }

    hoverOrb = intersectOrb(x, y);
    hoverPerformance = closestHead(x, y, rooms);

    if (hoverPerformance || hoverOrb) {
      viewer.switchCamera('default');
      InstancedItem.group.add(viewer.camera);
    }
  };

  const onMouseUp = () => {
    if (viewer.vrEffect.isPresenting) return;
    hoverPerformance = null;
    hoverOrb = false;
    viewer.switchCamera('orthographic');
  };

  const clearHighlights = () => {
    hoverPerformance = null;
    hoverOrb = false;
    orb.unhighlight();
    Room.setHighlight();
  };

  window.addEventListener('vrdisplaypresentchange', clearHighlights, false);

  const POV = {
    update: (progress = 0, fixedControllers = false) => {
      if (!viewer.vrEffect.isPresenting) {
        if (intersectOrb(pointerX, pointerY)) {
          orb.highlight();
          Room.setHighlight();
        } else {
          orb.unhighlight();
          if (!hoverPerformance && !hoverOrb) {
            Room.setHighlight(
              closestHead(
                pointerX,
                pointerY,
                rooms
              )
            );
          }
        }
      }

      const position = layout.getPosition(progress + 0.5);
      position.y += holeHeight;
      position.z *= -1;

      if (fixedControllers) {
        controllers.fixToPosition(position);
      }
      viewer.camera.position.copy(position);
      if (hoverOrb) {
        // Move camera into orb:
        viewer.camera.position.z *= -1;
        viewer.camera.rotation.set(0, Math.PI, 0);
      } else if (hoverPerformance) {
        // Move camera into head of performance:
        const [index, headIndex] = hoverPerformance;
        rooms[index].transformToHead(viewer.camera, headIndex);
      }
    },

    setupInput: () => {
      window.addEventListener('mousemove', onMouseMove);
      window.addEventListener('mousedown', onMouseDown);
      window.addEventListener('mouseup', onMouseUp);
      window.addEventListener('touchstart', onMouseDown, false);
      window.addEventListener('touchend', onMouseUp, false);
    },

    removeInput: () => {
      window.removeEventListener('mousemove', onMouseMove);
      window.removeEventListener('mousedown', onMouseDown);
      window.removeEventListener('mouseup', onMouseUp);
      window.removeEventListener('vrdisplaypresentchange', clearHighlights);
    },

    clearHighlights,
  };

  return POV;
}
<|endoftext|>