<commit_before>/* global d3 */

// TODO:
// reimplement zoom

"use strict";

var events = window.events || require('events');
var eventEmitter = new events.EventEmitter();
var shortId = require('shortid');
var getSet = require('get-set');

var _ = require('underscore');
    _.str = require('underscore.string');
    _.mixin(_.str.exports());

    // l-dash-trim helper
    _.dash = function(string){
      var dashed = _.dasherize(string);
      if(_.startsWith(dashed, '-')) dashed = dashed.substr(1);
      return dashed;
    };

var timeLine;

// property descriptor
var baseDesc = {

  // collects the layers
  layers: { writable: true },

  // modifiable xScale
  xScale: { writable: true },

  // modifiable yScale
  yScale: { writable: true },

  // reference xScale when zooming

  // reference svg element
  svg: { writable: true },
  el: { enumerable: true, writable: true },

  // reference svg element
  selection: { writable: true },

  dragInit: { writable: true },

  _brushing: { writable: true },

  // swapX: { enumerable: true, writable: true },
  // swapY: { enumerable: true, writable: true },

  on: { enumerable: true, writable: true },
  trigger: { writable: true },

  // init
  // ----

  init: {
    value: function(options) {
      options = options || {}; // fail safe

      // generic getters(setters) accessors and defaults
      getSet(this)([
        'id', 'margin', 'xDomain', 'yDomain', 'height', 'width', 'data'
      ]);

      // initialize
      this.layers = {};
      this.xScale = d3.scale.linear();
      this.yScale = d3.scale.linear();

      this.on = eventEmitter.on;
      this.trigger = eventEmitter.emit;

      this.id(options.id || shortId.generate());
      this.margin({top: 0, right: 0, bottom: 0, left: 0});
      this.xDomain([0, 0]);
      this.yDomain([0, 0]);
      // this.swapX = false;
      // this.swapY = false;
      // this.zoom = false;

      // for throttling
      this.fps = 60;

      return this;
    }
  },

  // inverts the order of the elements in a range array
  // swapRange: {
  //   value: function(range){
  //     var _range = [range[1], range[0]];
  //     range = _range;
  //     return _range;
  //   }
  // },

  // layer 'plugin' interface
  // adds new layers to layout
  layer: {
    enumerable: true, value: function(layer){
      this.layers[layer.name()] = layer;
      return this;
    }
  },

  // draws the layers
  draw: {
    enumerable: true, value: function(sel){
      var that = timeLine; // binding fix when called from d3
      sel = sel || that.selection;
      that.selection = sel;

      // normalize dimensions based on the margins
      that.width(that.width() - that.margin().left - that.margin().right);
      that.height(that.height() - that.margin().top - that.margin().bottom);

      that.initLayers();
      // console.log(that.width())

      sel.each(function() {
        var prevSvg = d3.select(this).select('svg');
        that.svg = (!!prevSvg.node())?
            prevSvg
          : d3.select(this).append("svg");

        that.svg
          .attr("width", that.width() + that.margin().left + that.margin().right)
          .attr("height", that.height() + that.margin().top + that.margin().bottom);

        that.el = that.svg;

        // events

        // !!! remember to unbind when deleting element !!!
        that.svg.on('mousedown', function() {
          that.dragInit = d3.event.target;
          that.trigger(that.id() + ':mousedown', d3.event );
        });

        that.svg.on('mouseup', function() {
          that.trigger(that.id() + ':mouseup', d3.event );
        });

        // for mousedrag we call a configured d3.drag behaviour returned from the objects drag method
        // that.svg.on('drag'...

        that.svg.call(that.drag(function(d) {
          // that.throttle(that.trigger(that.id() + ':drag', {target: this, event: d3.event, d:d, dragged: that.dragInit} ));
          that.trigger(that.id() + ':drag', {target: this, event: d3.event, d:d, dragged: that.dragInit} );
        }));

        document.body.addEventListener('mouseout', function(evt) {
          // console.log(evt.fromElement)
          if(evt.fromElement === document.body){
            that.trigger(that.id() + ':mouseout', d3.event );
          }
        });

        // layout group
        var prevg = that.svg.select('g');
        var g = (!!prevg.node())?
            prevg
          : that.svg.append("g");

          g.attr("class", 'layout')
          .attr("transform", "translate(" + that.margin().left + "," + that.margin().top + ")");

        // Updates scales
        // --------------

        var xRange = [0, that.width()];
        if(that.swapX) xRange = that.swapRange(xRange);

        var yRange = [that.height(), 0];
        if(that.swapY) yRange = that.swapRange(yRange); // y is always expected to be upside down

        that.xScale
            .domain(that.xDomain())
            .range(xRange);

        that.yScale
            .domain(that.yDomain())
            .range(yRange);

        // keep a reference unmodified scale range for use in the layers when zooming
        that.originalXscale = that.xScale.copy();

        // enter layers
        that.enterLayers(g);
      });

      return this;
    }
  },

  // handles and delegates to local drag behaviours
  drag: {
    enumerable: true, value: function(cb) {
      var that = this;
      var delta; // null unless we pass through drag

      // global drag behaviours
      return d3.behavior.drag()
        .on("drag", function(){

          // var parentDragged = that.dragInit.parentNode;

          // still used?
          // get the delta values
          // delta = {
          //   x: parseInt(d3.event.dx, 10),
          //   y: parseInt(d3.event.dy, 10)
          // };

          // executes local drag for each selected element
          that.selection.selectAll('.selected')
            .each(function(d) {
              cb.call(this, d);
            });
        });

    }
  },

  // sets the brushing state for interaction and a css class for styles
  brushing: {
    enumerable: true, value: function(state) {
      if(!arguments.length) return this._brushing;
      this._brushing = state;
      d3.select(document.body).classed('brushing', state);
    }
  },

  // only call on requestAnimationFrame ticks
  // throttle: {
  //   enumerable: true, value: function(func) {
  //     var wait, args, context, now, delta;
  //     var then = Date.now();
  //     var interval = 1000/this.fps;

  //     console.log(this.fps);

  //     return function () {
  //       if (wait) return;
  //       wait = true;
  //       args = arguments;
  //       context = this;

  //       window.requestAnimationFrame(function () {
  //         wait = false;

  //         now = Date.now();
  //         delta = now - then;

  //         if (delta > interval) {
  //             func.apply(context, args);
  //             then = now - (delta % interval);
  //         }
  //       });
  //     };
  //   }
  // },

  xZoom: {
    enumerable: true, value: function(zoom) {

      var that = this;
      var layers = this.layers;

      zoom.anchor = this.originalXscale.invert(zoom.anchor); // in px to domain

      // this.zoomFactor = zoom.factor;
      this.xZoomCompute(zoom, this);

      // redraw layers
      _.each(layers, function(layer){
        if(layer.hasOwnProperty('xScale')) that.xZoomCompute(zoom, layer);
        if(layer.hasOwnProperty('xZoom')) layer.xZoom(zoom);
        // if(layer.xZoom) that.throttle(layer.xZoom());
      });

    }
  },

  // thanks Charles Picasso <charles.picasso@ircam.fr> !!
  xZoomCompute: {
    enumerable: true, value: function(zoom, ly) {
      var deltaY = zoom.delta.y;
      var deltaX = zoom.delta.x;
      var anchor = zoom.anchor;
      var factor = zoom.factor;

      // start and length (instead of end)
      var targetStart = ly.originalXscale.domain()[0];
      var currentLength = ly.originalXscale.domain()[1] - targetStart;

      // length after scaling
      var targetLength = currentLength * factor;
      // unchanged length in px
      var rangeLength = ly.originalXscale.range()[1] - ly.originalXscale.range()[0];

      // zoom
      if (deltaY){
        var offsetOrig = ( (anchor - targetStart) / currentLength ) * rangeLength;
        var offsetFina = ( (anchor - targetStart) / targetLength ) * rangeLength;
        targetStart += ( (offsetFina - offsetOrig) / rangeLength ) * targetLength;
      }

      // translate x
      if (deltaX){
        var translation = (deltaX / rangeLength) * targetLength;
        targetStart += translation;
      }

      // ly.targetStart = targetStart;
      // updating the scale
      ly.xScale.domain([targetStart, targetStart + targetLength]);

    }
  },

  xZoomSet: {
    enumerable: true, value: function() {
      var layers = this.layers;
      // saves new scale reference

      this.originalXscale = this.xScale.copy();

      _.each(layers, function(layer){
         if (layer.hasOwnProperty('xScale')) layer.originalXscale = layer.xScale.copy();
      });

    }
  },

  update: {
    enumerable: true, value: function(){

      var that = this;
      var layers = this.layers;
      _.each(layers, function(layer){
        layer.update();
      });

    }
  },

  // initialize layers
  initLayers: {
    value: function(){

      var that = this;
      var layers = this.layers;
      // console.log(layers)
      _.each(layers, function(layer){
        // console.log(layer)
        layer.load(that);
        layer.dname = _.dash(layer.name()); // dashed name
        that.delegateScales(layer);
        // layer.xScale = that.xScale;
        // layer.yScale = d3.scale.linear();
      });

    }
  },

  drawLayers: {
    value: function(name){
      name = name || '';
      var layers = this.layers;

      // update all layers excepthe one passed
      // rethink this later
      _.each(layers, function(layer){
        if(layer.draw && layer.name !== name) layer.draw();
      });

    }
  },

  // internal scale update
  delegateScales: {
    value: function(layer){

      if(layer.hasOwnProperty('xScale')) {
        var baseXscale = this.xScale.copy();
        if(!!layer.xDomain && !!layer.xDomain()) baseXscale.domain(layer.xDomain());
        if(!!layer.xRange && !!layer.xRange()) baseXscale.range(layer.xRange());
        layer.xScale = baseXscale;
        layer.originalXscale = baseXscale.copy();
      }

      if(layer.hasOwnProperty('yScale')) {
        var baseYscale = this.yScale.copy();
        if(!!layer.yDomain && !!layer.yDomain()) baseYscale.domain(layer.yDomain());
        if(!!layer.yRange && !!layer.yRange()) baseYscale.range(layer.yRange());
        layer.yScale = baseYscale;
      }
    }
  },

  // call layer enter method
  enterLayers: {
    value: function(g){

      var that = this;
      var layers = this.layers;

      // setup external layers containers and dimensions
      _.each(layers, function(layer){
        // rebind Scales in case they updated
        that.delegateScales(layer);

        // margin/position handling
        var top = layer.top && layer.top() || 0;
        // be more elegantl please
        if(layer.height && !!!layer.height()) layer.height(that.height());
        var height = layer.height && layer.height() || that.height();
        var width = that.width();

        // layer group
        // var klen = Object.keys(that.layers).length;
        // var lg = (klen > 1) ? g.append("g") // if there are more than one layer we append a layer group
        //                     : g; // otherwise we work only with the inner group

        // var lg = g.append("g");
        var prevLg = g.select('.' + layer.dname);
        var lg = (!!prevLg.node())?
          prevLg
          : g.append("g");

        // apply all the dimensions to our group
        lg.classed(layer.dname, true)
          .attr('height', height)
          .attr("transform", "translate(0, " + top + ")");
        if(layer.hasOwnProperty('bind')) layer.bind(lg);
      });

    }
  },

  swapRange: {
    value: function(range) {
      return [range[1], range[0]];
    }
  },

  // moves selected item to front
  toFront: {
    value: function(item) {
      item.parentNode.appendChild(item);
    }
  }

};

// exported factory
// ----------------
module.exports = function timeline(options){
  timeLine = Object.create({}, baseDesc);
  return timeLine.init(options); // return initiated object
};
<commit_msg>fixed no height bugs with clamp()<commit_after>/* global d3 */

// TODO:
// reimplement zoom

"use strict";

var events = window.events || require('events');
var eventEmitter = new events.EventEmitter();
var shortId = require('shortid');
var getSet = require('get-set');

var _ = require('underscore');
    _.str = require('underscore.string');
    _.mixin(_.str.exports());

    // l-dash-trim helper
    _.dash = function(string){
      var dashed = _.dasherize(string);
      if(_.startsWith(dashed, '-')) dashed = dashed.substr(1);
      return dashed;
    };

var timeLine;

// property descriptor
var baseDesc = {

  // collects the layers
  layers: { writable: true },

  // modifiable xScale
  xScale: { writable: true },

  // modifiable yScale
  yScale: { writable: true },

  // reference xScale when zooming

  // reference svg element
  svg: { writable: true },
  el: { enumerable: true, writable: true },

  // reference svg element
  selection: { writable: true },

  dragInit: { writable: true },

  _brushing: { writable: true },

  // swapX: { enumerable: true, writable: true },
  // swapY: { enumerable: true, writable: true },

  on: { enumerable: true, writable: true },
  trigger: { writable: true },

  // init
  // ----

  init: {
    value: function(options) {
      options = options || {}; // fail safe

      // generic getters(setters) accessors and defaults
      getSet(this)([
        'id', 'margin', 'xDomain', 'yDomain', 'height', 'width', 'data'
      ]);

      // initialize
      this.layers = {};
      this.xScale = d3.scale.linear().clamp(true);
      this.yScale = d3.scale.linear().clamp(true);

      this.on = eventEmitter.on;
      this.trigger = eventEmitter.emit;

      this.id(options.id || shortId.generate());
      this.margin({top: 0, right: 0, bottom: 0, left: 0});
      this.xDomain([0, 0]);
      this.yDomain([0, 1]);
      // this.swapX = false;
      // this.swapY = false;
      // this.zoom = false;

      // for throttling
      this.fps = 60;

      return this;
    }
  },

  // inverts the order of the elements in a range array
  // swapRange: {
  //   value: function(range){
  //     var _range = [range[1], range[0]];
  //     range = _range;
  //     return _range;
  //   }
  // },

  // layer 'plugin' interface
  // adds new layers to layout
  layer: {
    enumerable: true, value: function(layer){
      this.layers[layer.name()] = layer;
      return this;
    }
  },

  // draws the layers
  draw: {
    enumerable: true, value: function(sel){
      var that = timeLine; // binding fix when called from d3
      sel = sel || that.selection;
      that.selection = sel;

      // normalize dimensions based on the margins
      that.width(that.width() - that.margin().left - that.margin().right);
      that.height(that.height() - that.margin().top - that.margin().bottom);

      that.initLayers();
      // console.log(that.width())

      sel.each(function() {
        var prevSvg = d3.select(this).select('svg');
        that.svg = (!!prevSvg.node())?
            prevSvg
          : d3.select(this).append("svg");

        that.svg
          .attr("width", that.width() + that.margin().left + that.margin().right)
          .attr("height", that.height() + that.margin().top + that.margin().bottom);

        that.el = that.svg;

        // events

        // !!! remember to unbind when deleting element !!!
        that.svg.on('mousedown', function() {
          that.dragInit = d3.event.target;
          that.trigger(that.id() + ':mousedown', d3.event );
        });

        that.svg.on('mouseup', function() {
          that.trigger(that.id() + ':mouseup', d3.event );
        });

        // for mousedrag we call a configured d3.drag behaviour returned from the objects drag method
        // that.svg.on('drag'...

        that.svg.call(that.drag(function(d) {
          // that.throttle(that.trigger(that.id() + ':drag', {target: this, event: d3.event, d:d, dragged: that.dragInit} ));
          that.trigger(that.id() + ':drag', {target: this, event: d3.event, d:d, dragged: that.dragInit} );
        }));

        document.body.addEventListener('mouseout', function(evt) {
          // console.log(evt.fromElement)
          if(evt.fromElement === document.body){
            that.trigger(that.id() + ':mouseout', d3.event );
          }
        });

        // layout group
        var prevg = that.svg.select('g');
        var g = (!!prevg.node())?
            prevg
          : that.svg.append("g");

          g.attr("class", 'layout')
          .attr("transform", "translate(" + that.margin().left + "," + that.margin().top + ")");

        // Updates scales
        // --------------

        var xRange = [0, that.width()];
        if(that.swapX) xRange = that.swapRange(xRange);

        var yRange = [that.height(), 0];
        if(that.swapY) yRange = that.swapRange(yRange); // y is always expected to be upside down

        that.xScale
            .domain(that.xDomain())
            .range(xRange);

        that.yScale
            .domain(that.yDomain())
            .range(yRange);

        // keep a reference unmodified scale range for use in the layers when zooming
        that.originalXscale = that.xScale.copy();

        // enter layers
        that.enterLayers(g);
      });

      return this;
    }
  },

  // handles and delegates to local drag behaviours
  drag: {
    enumerable: true, value: function(cb) {
      var that = this;
      var delta; // null unless we pass through drag

      // global drag behaviours
      return d3.behavior.drag()
        .on("drag", function(){

          // var parentDragged = that.dragInit.parentNode;

          // still used?
          // get the delta values
          // delta = {
          //   x: parseInt(d3.event.dx, 10),
          //   y: parseInt(d3.event.dy, 10)
          // };

          // executes local drag for each selected element
          that.selection.selectAll('.selected')
            .each(function(d) {
              cb.call(this, d);
            });
        });

    }
  },

  // sets the brushing state for interaction and a css class for styles
  brushing: {
    enumerable: true, value: function(state) {
      if(!arguments.length) return this._brushing;
      this._brushing = state;
      d3.select(document.body).classed('brushing', state);
    }
  },

  // only call on requestAnimationFrame ticks
  // throttle: {
  //   enumerable: true, value: function(func) {
  //     var wait, args, context, now, delta;
  //     var then = Date.now();
  //     var interval = 1000/this.fps;

  //     console.log(this.fps);

  //     return function () {
  //       if (wait) return;
  //       wait = true;
  //       args = arguments;
  //       context = this;

  //       window.requestAnimationFrame(function () {
  //         wait = false;

  //         now = Date.now();
  //         delta = now - then;

  //         if (delta > interval) {
  //             func.apply(context, args);
  //             then = now - (delta % interval);
  //         }
  //       });
  //     };
  //   }
  // },

  xZoom: {
    enumerable: true, value: function(zoom) {

      var that = this;
      var layers = this.layers;

      zoom.anchor = this.originalXscale.invert(zoom.anchor); // in px to domain

      // this.zoomFactor = zoom.factor;
      this.xZoomCompute(zoom, this);

      // redraw layers
      _.each(layers, function(layer){
        if(layer.hasOwnProperty('xScale')) that.xZoomCompute(zoom, layer);
        if(layer.hasOwnProperty('xZoom')) layer.xZoom(zoom);
        // if(layer.xZoom) that.throttle(layer.xZoom());
      });

    }
  },

  // thanks Charles Picasso <charles.picasso@ircam.fr> !!
  xZoomCompute: {
    enumerable: true, value: function(zoom, ly) {
      var deltaY = zoom.delta.y;
      var deltaX = zoom.delta.x;
      var anchor = zoom.anchor;
      var factor = zoom.factor;

      // start and length (instead of end)
      var targetStart = ly.originalXscale.domain()[0];
      var currentLength = ly.originalXscale.domain()[1] - targetStart;

      // length after scaling
      var targetLength = currentLength * factor;
      // unchanged length in px
      var rangeLength = ly.originalXscale.range()[1] - ly.originalXscale.range()[0];

      // zoom
      if (deltaY){
        var offsetOrig = ( (anchor - targetStart) / currentLength ) * rangeLength;
        var offsetFina = ( (anchor - targetStart) / targetLength ) * rangeLength;
        targetStart += ( (offsetFina - offsetOrig) / rangeLength ) * targetLength;
      }

      // translate x
      if (deltaX){
        var translation = (deltaX / rangeLength) * targetLength;
        targetStart += translation;
      }

      // ly.targetStart = targetStart;
      // updating the scale
      ly.xScale.domain([targetStart, targetStart + targetLength]);

    }
  },

  xZoomSet: {
    enumerable: true, value: function() {
      var layers = this.layers;
      // saves new scale reference

      this.originalXscale = this.xScale.copy();

      _.each(layers, function(layer){
         if (layer.hasOwnProperty('xScale')) layer.originalXscale = layer.xScale.copy();
      });

    }
  },

  update: {
    enumerable: true, value: function(){

      var that = this;
      var layers = this.layers;
      _.each(layers, function(layer){
        layer.update();
      });

    }
  },

  // initialize layers
  initLayers: {
    value: function(){

      var that = this;
      var layers = this.layers;
      // console.log(layers)
      _.each(layers, function(layer){
        // console.log(layer)
        layer.load(that);
        layer.dname = _.dash(layer.name()); // dashed name
        that.delegateScales(layer);
        // layer.xScale = that.xScale;
        // layer.yScale = d3.scale.linear();
      });

    }
  },

  drawLayers: {
    value: function(name){
      name = name || '';
      var layers = this.layers;

      // update all layers excepthe one passed
      // rethink this later
      _.each(layers, function(layer){
        if(layer.draw && layer.name !== name) layer.draw();
      });

    }
  },

  // internal scale update
  delegateScales: {
    value: function(layer){

      if(layer.hasOwnProperty('xScale')) {
        var baseXscale = this.xScale.copy();
        if(!!layer.xDomain && !!layer.xDomain()) baseXscale.domain(layer.xDomain());
        if(!!layer.xRange && !!layer.xRange()) baseXscale.range(layer.xRange());
        layer.xScale = baseXscale;
        layer.originalXscale = baseXscale.copy();
      }

      if(layer.hasOwnProperty('yScale')) {
        var baseYscale = this.yScale.copy();
        if(!!layer.yDomain && !!layer.yDomain()) baseYscale.domain(layer.yDomain());
        if(!!layer.yRange && !!layer.yRange()) baseYscale.range(layer.yRange());
        layer.yScale = baseYscale;
      }
    }
  },

  // call layer enter method
  enterLayers: {
    value: function(g){

      var that = this;
      var layers = this.layers;

      // setup external layers containers and dimensions
      _.each(layers, function(layer){
        // rebind Scales in case they updated
        that.delegateScales(layer);

        // margin/position handling
        var top = layer.top && layer.top() || 0;
        // be more elegantl please
        if(layer.height && !!!layer.height()) layer.height(that.height());
        var height = layer.height && layer.height() || that.height();
        var width = that.width();

        // layer group
        // var klen = Object.keys(that.layers).length;
        // var lg = (klen > 1) ? g.append("g") // if there are more than one layer we append a layer group
        //                     : g; // otherwise we work only with the inner group

        // var lg = g.append("g");
        var prevLg = g.select('.' + layer.dname);
        var lg = (!!prevLg.node())?
          prevLg
          : g.append("g");

        // apply all the dimensions to our group
        lg.classed(layer.dname, true)
          .attr('height', height)
          .attr("transform", "translate(0, " + top + ")");
        if(layer.hasOwnProperty('bind')) layer.bind(lg);
      });

    }
  },

  swapRange: {
    value: function(range) {
      return [range[1], range[0]];
    }
  },

  // moves selected item to front
  toFront: {
    value: function(item) {
      item.parentNode.appendChild(item);
    }
  }

};

// exported factory
// ----------------
module.exports = function timeline(options){
  timeLine = Object.create({}, baseDesc);
  return timeLine.init(options); // return initiated object
};
<|endoftext|>


<commit_before>module.exports = {
    rules: {
        "accessor-pairs": 0,
        "array-callback-return": 2,
        "block-scoped-var": 2,
        "complexity": [
            0, 11
        ],
        "consistent-return": 2,
        "curly": [
            2, "multi-line"
        ],
        "default-case": 0,
        "dot-notation": [
            2, {
                "allowKeywords": true
            }
        ],
        "dot-location": 0,
        "eqeqeq": [
            2, "allow-null"
        ],
        "guard-for-in": 0,
        "id-blacklist": 0,
        "no-alert": 1,
        "no-caller": 2,
        "no-case-declarations": 2,
        "no-div-regex": 0,
        "no-else-return": 2,
        "no-empty-function": [
            2, {
                "allow": ["arrowFunctions", "functions", "methods"]
            }
        ],
        "no-empty-pattern": 2,
        "no-extra-label": 2,
        "no-eq-null": 0,
        "no-eval": 2,
        "no-extend-native": 2,
        "no-extra-bind": 2,
        "no-fallthrough": 0,
        "no-floating-decimal": 2,
        "no-implicit-coercion": 0,
        "no-implied-eval": 2,
        "no-invalid-this": 0,
        "no-iterator": 2,
        "no-labels": 1,
        "no-lone-blocks": 2,
        "no-loop-func": 2,
        "no-magic-numbers": [
            0, {
                "ignore": [],
                "ignoreArrayIndexes": true,
                "enforceConst": true,
                "detectObjects": false
            }
        ],
        "no-multi-spaces": 1,
        "no-multi-str": 2,
        "no-native-reassign": 2,
        "no-new": 2,
        "no-new-func": 2,
        "no-new-wrappers": 2,
        "no-octal": 2,
        "no-octal-escape": 2,
        "no-param-reassign": [
            2, {
                "props": true
            }
        ],
        "no-process-env": 0,
        "no-proto": 2,
        "no-redeclare": 2,
        "no-restricted-syntax": [
            2, "DebuggerStatement", "LabeledStatement", "WithStatement"
        ],
        "no-return-assign": 2,
        "no-script-url": 2,
        "no-self-compare": 2,
        "no-sequences": 2,
        "no-throw-literal": 2,
        "no-unmodified-loop-condition": 0,
        "no-unsafe-finally": 2,
        "no-unused-expressions": 0,
        "no-unused-labels": 2,
        "no-useless-call": 0,
        "no-useless-concat": 2,
        "no-useless-escape": 2,
        "no-void": 0,
        "no-warning-comments": [
            0, {
                "terms": [
                    "todo", "fixme", "xxx"
                ],
                "location": "start"
            }
        ],
        "no-with": 2,
        "radix": 2,
        "vars-on-top": 2,
        "wrap-iife": [
            2, "outside"
        ],
        "yoda": 2,
        "no-cond-assign": [
            2, "always"
        ],
        "no-console": 0,
        "no-constant-condition": 1,
        "no-control-regex": 2,
        "no-debugger": 2,
        "no-dupe-args": 2,
        "no-dupe-keys": 2,
        "no-duplicate-case": 2,
        "no-empty-character-class": 2,
        "no-empty": 2,
        "no-ex-assign": 2,
        "no-extra-boolean-cast": 0,
        "no-extra-parens": [
            0,
            "all", {
                "conditionalAssign": true,
                "nestedBinaryExpressions": false
            }
        ],
        "no-extra-semi": 2,
        "no-func-assign": 2,
        "no-inner-declarations": 2,
        "no-invalid-regexp": 2,
        "no-irregular-whitespace": 2,
        "no-negated-in-lhs": 2,
        "no-obj-calls": 2,
        "no-regex-spaces": 2,
        "no-sparse-arrays": 2,
        "no-unreachable": 2,
        "use-isnan": 2,
        "valid-jsdoc": 0,
        "valid-typeof": 2,
        "no-unexpected-multiline": 0,
        "callback-return": 0,
        "global-require": 0,
        "handle-callback-err": 0,
        "no-mixed-requires": [
            0, false
        ],
        "no-new-require": 0,
        "no-path-concat": 0,
        "no-process-exit": 0,
        "no-restricted-modules": 0,
        "no-sync": 0,
        "import/no-unresolved": 0,
        "array-bracket-spacing": [
            2, "never"
        ],
        "block-spacing": [
            2, "always"
        ],
        "brace-style": [
            2,
            "1tbs", {
                "allowSingleLine": true
            }
        ],
        "camelcase": [
            2, {
                "properties": "never"
            }
        ],
        "comma-spacing": [
            2, {
                "before": false,
                "after": true
            }
        ],
        "comma-style": [
            2, "last"
        ],
        "computed-property-spacing": [
            2, "never"
        ],
        "consistent-this": 0,
        "eol-last": 2,
        "func-names": 1,
        "func-style": 0,
        "id-length": 0,
        "indent": [
            2,
            2, {
                "SwitchCase": 1
            }
        ],
        "jsx-quotes": 1,
        "key-spacing": [
            2, {
                "beforeColon": false,
                "afterColon": true
            }
        ],
        "keyword-spacing": [
            2, {
                "before": true,
                "after": true,
                "overrides": {
                    "return": {
                        "after": true
                    },
                    "throw": {
                        "after": true
                    },
                    "case": {
                        "after": true
                    }
                }
            }
        ],
        "lines-around-comment": 0,
        "linebreak-style": 0,
        "max-len": [
            1, {
                "code": 120,
                "ignoreComments": true,
                "ignoreUrls": true,
                "ignoreTemplateLiterals": true
            }
        ],
        "max-nested-callbacks": 0,
        "max-statements-per-line": [
            0, {
                "max": 1
            }
        ],
        "new-cap": [
            2, {
                "newIsCap": true
            }
        ],
        "new-parens": 0,
        "newline-after-var": 0,
        "newline-before-return": 0,
        "newline-per-chained-call": [
            2, {
                "ignoreChainWithDepth": 3
            }
        ],
        "no-array-constructor": 2,
        "no-continue": 0,
        "no-inline-comments": 0,
        "no-lonely-if": 0,
        "no-mixed-spaces-and-tabs": 2,
        "no-multiple-empty-lines": [
            2, {
                "max": 2,
                "maxEOF": 1
            }
        ],
        "no-negated-condition": 0,
        "no-nested-ternary": 2,
        "no-new-object": 2,
        "no-spaced-func": 2,
        "no-ternary": 0,
        "no-trailing-spaces": 1,
        "no-underscore-dangle": 0,
        "no-unneeded-ternary": [
            2, {
                "defaultAssignment": false
            }
        ],
        "no-whitespace-before-property": 2,
        "object-curly-spacing": [
            1, "always"
        ],
        "one-var": [
            2, "never"
        ],
        "one-var-declaration-per-line": [
            2, "always"
        ],
        "operator-assignment": 0,
        "operator-linebreak": 0,
        "padded-blocks": 0,
        "quote-props": 0,
        "quotes": [
            1, "single", {
                "avoidEscape": true,
                "allowTemplateLiterals": true
            }
        ],
        "id-match": 0,
        "require-jsdoc": 0,
        "semi-spacing": [
            2, {
                "before": false,
                "after": true
            }
        ],
        "semi": 1,
        "sort-vars": 0,
        "space-before-blocks": 2,
        "space-before-function-paren": [
            1, "never"
        ],
        "space-in-parens": [
            2, "never"
        ],
        "space-infix-ops": 2,
        "space-unary-ops": 0,
        "spaced-comment": [
            2,
            "always", {
                "exceptions": [
                    "-", "+"
                ],
                "markers": ["=", "!"]
            }
        ],
        "wrap-regex": 0,
        "init-declarations": 0,
        "no-catch-shadow": 0,
        "no-delete-var": 2,
        "no-implicit-globals": 0,
        "no-label-var": 0,
        "no-self-assign": 2,
        "no-shadow-restricted-names": 2,
        "no-shadow": 2,
        "no-undef-init": 0,
        "no-undef": 2,
        "no-undefined": 0,
        "no-unused-vars": [
            1, {
                "vars": "local",
                "args": "after-used"
            }
        ],
        "no-use-before-define": 0,
        "arrow-body-style": [
            2, "as-needed"
        ],
        "arrow-parens": 0,
        "arrow-spacing": [
            2, {
                "before": true,
                "after": true
            }
        ],
        "comma-dangle": 0,
        "constructor-super": 0,
        "generator-star-spacing": 0,
        "no-class-assign": 2,
        "no-confusing-arrow": [
            2, {
                "allowParens": true
            }
        ],
        "no-const-assign": 2,
        "no-dupe-class-members": 2,
        "no-duplicate-imports": 2,
        "no-new-symbol": 2,
        "no-restricted-globals": 0,
        "no-restricted-imports": 0,
        "no-this-before-super": 0,
        "no-var": 2,
        "no-useless-computed-key": 2,
        "no-useless-constructor": 2,
        "object-shorthand": [
            2, "always"
        ],
        "prefer-arrow-callback": [
            2, {
                "allowNamedFunctions": true,
                "allowUnboundThis": true
            }
        ],
        "prefer-const": 1,
        "prefer-spread": 0,
        "prefer-reflect": 0,
        "prefer-rest-params": 2,
        "prefer-template": 1,
        "require-yield": 0,
        "sort-imports": 0,
        "template-curly-spacing": 2,
        "yield-star-spacing": [
            2, "after"
        ],
        "import/export": 2,
        "import/default": 0,
        "import/extensions": [
            0, "never"
        ],
        "import/named": 0,
        "import/namespace": 0,
        "import/no-extraneous-dependencies": [
            0, {
                "devDependencies": false,
                "optionalDependencies": false
            }
        ],
        "import/no-named-as-default": 0,
        "import/no-commonjs": 0,
        "import/no-amd": 2,
        "import/imports-first": [
            0, "absolute-first"
        ],
        "import/no-duplicates": 0,
        "import/no-deprecated": 0,
        "import/no-namespace": 0,
        "import/no-named-as-default-member": 0,
        "import/no-nodejs-modules": 0,
        "import/order": [
            0, {
                "groups": [
                    "builtin",
                    "external",
                    "internal",
                    "parent",
                    "sibling",
                    "index"
                ],
                "newlines-between": "never"
            }
        ],
        "import/newline-after-import": 0,
        "import/no-mutable-exports": 2,
        "strict": [
            2, "never"
        ],
        "react/display-name": [
            0, {
                "ignoreTranspilerName": false
            }
        ],
        "react/forbid-prop-types": [
            0, {
                "forbid": ["any", "array", "object"]
            }
        ],
        "react/jsx-boolean-value": [
            2, "never"
        ],
        "react/jsx-closing-bracket-location": 0,
        "react/jsx-curly-spacing": [
            2,
            "never", {
                "allowMultiline": true
            }
        ],
        "react/jsx-handler-names": [
            0, {
                "eventHandlerPrefix": "handle",
                "eventHandlerPropPrefix": "on"
            }
        ],
        "react/jsx-indent-props": 0,
        "react/jsx-key": 0,
        "react/jsx-max-props-per-line": [
            0, {
                "maximum": 1
            }
        ],
        "react/jsx-no-bind": [
            2, {
                "ignoreRefs": true,
                "allowArrowFunctions": true,
                "allowBind": false
            }
        ],
        "react/jsx-no-duplicate-props": [
            0, {
                "ignoreCase": false
            }
        ],
        "react/jsx-no-literals": 0,
        "react/jsx-no-undef": 2,
        "react/jsx-pascal-case": 2,
        "react/sort-prop-types": [
            0, {
                "ignoreCase": false,
                "callbacksLast": false
            }
        ],
        "react/jsx-sort-prop-types": 0,
        "react/jsx-sort-props": [
            0, {
                "ignoreCase": false,
                "callbacksLast": false
            }
        ],
        "react/jsx-filename-extension": 0,
        "react/jsx-uses-react": 1,
        "react/jsx-uses-vars": 1,
        "react/no-danger": 0,
        "react/no-deprecated": 1,
        "react/no-did-mount-set-state": 2,
        "react/no-did-update-set-state": 2,
        "react/no-direct-mutation-state": 0,
        "react/no-is-mounted": 2,
        "react/no-multi-comp": [
            2, {
                "ignoreStateless": true
            }
        ],
        "react/no-set-state": 0,
        "react/no-string-refs": 0,
        "react/no-unknown-property": 2,
        "react/prefer-es6-class": [
            2, "always"
        ],
        "react/prefer-stateless-function": 0,
        "react/prop-types": 0,
        "react/react-in-jsx-scope": 1,
        "react/require-extension": [
            0, {
                "extensions": [".jsx"]
            }
        ],
        "react/require-render-return": 2,
        "react/self-closing-comp": 0,
        "react/jsx-space-before-closing": [
            2, "always"
        ],
        "react/sort-comp": 0,
        "react/jsx-first-prop-new-line": 0,
        "react/jsx-equals-spacing": [
            2, "never"
        ],
        "react/jsx-indent": [
            1, 2
        ],
    }
};
<commit_msg>Indent should be warning, not error<commit_after>module.exports = {
    rules: {
        "accessor-pairs": 0,
        "array-callback-return": 2,
        "block-scoped-var": 2,
        "complexity": [
            0, 11
        ],
        "consistent-return": 2,
        "curly": [
            2, "multi-line"
        ],
        "default-case": 0,
        "dot-notation": [
            2, {
                "allowKeywords": true
            }
        ],
        "dot-location": 0,
        "eqeqeq": [
            2, "allow-null"
        ],
        "guard-for-in": 0,
        "id-blacklist": 0,
        "no-alert": 1,
        "no-caller": 2,
        "no-case-declarations": 2,
        "no-div-regex": 0,
        "no-else-return": 2,
        "no-empty-function": [
            2, {
                "allow": ["arrowFunctions", "functions", "methods"]
            }
        ],
        "no-empty-pattern": 2,
        "no-extra-label": 2,
        "no-eq-null": 0,
        "no-eval": 2,
        "no-extend-native": 2,
        "no-extra-bind": 2,
        "no-fallthrough": 0,
        "no-floating-decimal": 2,
        "no-implicit-coercion": 0,
        "no-implied-eval": 2,
        "no-invalid-this": 0,
        "no-iterator": 2,
        "no-labels": 1,
        "no-lone-blocks": 2,
        "no-loop-func": 2,
        "no-magic-numbers": [
            0, {
                "ignore": [],
                "ignoreArrayIndexes": true,
                "enforceConst": true,
                "detectObjects": false
            }
        ],
        "no-multi-spaces": 1,
        "no-multi-str": 2,
        "no-native-reassign": 2,
        "no-new": 2,
        "no-new-func": 2,
        "no-new-wrappers": 2,
        "no-octal": 2,
        "no-octal-escape": 2,
        "no-param-reassign": [
            2, {
                "props": true
            }
        ],
        "no-process-env": 0,
        "no-proto": 2,
        "no-redeclare": 2,
        "no-restricted-syntax": [
            2, "DebuggerStatement", "LabeledStatement", "WithStatement"
        ],
        "no-return-assign": 2,
        "no-script-url": 2,
        "no-self-compare": 2,
        "no-sequences": 2,
        "no-throw-literal": 2,
        "no-unmodified-loop-condition": 0,
        "no-unsafe-finally": 2,
        "no-unused-expressions": 0,
        "no-unused-labels": 2,
        "no-useless-call": 0,
        "no-useless-concat": 2,
        "no-useless-escape": 2,
        "no-void": 0,
        "no-warning-comments": [
            0, {
                "terms": [
                    "todo", "fixme", "xxx"
                ],
                "location": "start"
            }
        ],
        "no-with": 2,
        "radix": 2,
        "vars-on-top": 2,
        "wrap-iife": [
            2, "outside"
        ],
        "yoda": 2,
        "no-cond-assign": [
            2, "always"
        ],
        "no-console": 0,
        "no-constant-condition": 1,
        "no-control-regex": 2,
        "no-debugger": 2,
        "no-dupe-args": 2,
        "no-dupe-keys": 2,
        "no-duplicate-case": 2,
        "no-empty-character-class": 2,
        "no-empty": 2,
        "no-ex-assign": 2,
        "no-extra-boolean-cast": 0,
        "no-extra-parens": [
            0,
            "all", {
                "conditionalAssign": true,
                "nestedBinaryExpressions": false
            }
        ],
        "no-extra-semi": 2,
        "no-func-assign": 2,
        "no-inner-declarations": 2,
        "no-invalid-regexp": 2,
        "no-irregular-whitespace": 2,
        "no-negated-in-lhs": 2,
        "no-obj-calls": 2,
        "no-regex-spaces": 2,
        "no-sparse-arrays": 2,
        "no-unreachable": 2,
        "use-isnan": 2,
        "valid-jsdoc": 0,
        "valid-typeof": 2,
        "no-unexpected-multiline": 0,
        "callback-return": 0,
        "global-require": 0,
        "handle-callback-err": 0,
        "no-mixed-requires": [
            0, false
        ],
        "no-new-require": 0,
        "no-path-concat": 0,
        "no-process-exit": 0,
        "no-restricted-modules": 0,
        "no-sync": 0,
        "import/no-unresolved": 0,
        "array-bracket-spacing": [
            2, "never"
        ],
        "block-spacing": [
            2, "always"
        ],
        "brace-style": [
            2,
            "1tbs", {
                "allowSingleLine": true
            }
        ],
        "camelcase": [
            2, {
                "properties": "never"
            }
        ],
        "comma-spacing": [
            2, {
                "before": false,
                "after": true
            }
        ],
        "comma-style": [
            2, "last"
        ],
        "computed-property-spacing": [
            2, "never"
        ],
        "consistent-this": 0,
        "eol-last": 2,
        "func-names": 1,
        "func-style": 0,
        "id-length": 0,
        "indent": [
            1,
            2, {
                "SwitchCase": 1
            }
        ],
        "jsx-quotes": 1,
        "key-spacing": [
            2, {
                "beforeColon": false,
                "afterColon": true
            }
        ],
        "keyword-spacing": [
            2, {
                "before": true,
                "after": true,
                "overrides": {
                    "return": {
                        "after": true
                    },
                    "throw": {
                        "after": true
                    },
                    "case": {
                        "after": true
                    }
                }
            }
        ],
        "lines-around-comment": 0,
        "linebreak-style": 0,
        "max-len": [
            1, {
                "code": 120,
                "ignoreComments": true,
                "ignoreUrls": true,
                "ignoreTemplateLiterals": true
            }
        ],
        "max-nested-callbacks": 0,
        "max-statements-per-line": [
            0, {
                "max": 1
            }
        ],
        "new-cap": [
            2, {
                "newIsCap": true
            }
        ],
        "new-parens": 0,
        "newline-after-var": 0,
        "newline-before-return": 0,
        "newline-per-chained-call": [
            2, {
                "ignoreChainWithDepth": 3
            }
        ],
        "no-array-constructor": 2,
        "no-continue": 0,
        "no-inline-comments": 0,
        "no-lonely-if": 0,
        "no-mixed-spaces-and-tabs": 2,
        "no-multiple-empty-lines": [
            2, {
                "max": 2,
                "maxEOF": 1
            }
        ],
        "no-negated-condition": 0,
        "no-nested-ternary": 2,
        "no-new-object": 2,
        "no-spaced-func": 2,
        "no-ternary": 0,
        "no-trailing-spaces": 1,
        "no-underscore-dangle": 0,
        "no-unneeded-ternary": [
            2, {
                "defaultAssignment": false
            }
        ],
        "no-whitespace-before-property": 2,
        "object-curly-spacing": [
            1, "always"
        ],
        "one-var": [
            2, "never"
        ],
        "one-var-declaration-per-line": [
            2, "always"
        ],
        "operator-assignment": 0,
        "operator-linebreak": 0,
        "padded-blocks": 0,
        "quote-props": 0,
        "quotes": [
            1, "single", {
                "avoidEscape": true,
                "allowTemplateLiterals": true
            }
        ],
        "id-match": 0,
        "require-jsdoc": 0,
        "semi-spacing": [
            2, {
                "before": false,
                "after": true
            }
        ],
        "semi": 1,
        "sort-vars": 0,
        "space-before-blocks": 2,
        "space-before-function-paren": [
            1, "never"
        ],
        "space-in-parens": [
            2, "never"
        ],
        "space-infix-ops": 2,
        "space-unary-ops": 0,
        "spaced-comment": [
            2,
            "always", {
                "exceptions": [
                    "-", "+"
                ],
                "markers": ["=", "!"]
            }
        ],
        "wrap-regex": 0,
        "init-declarations": 0,
        "no-catch-shadow": 0,
        "no-delete-var": 2,
        "no-implicit-globals": 0,
        "no-label-var": 0,
        "no-self-assign": 2,
        "no-shadow-restricted-names": 2,
        "no-shadow": 2,
        "no-undef-init": 0,
        "no-undef": 2,
        "no-undefined": 0,
        "no-unused-vars": [
            1, {
                "vars": "local",
                "args": "after-used"
            }
        ],
        "no-use-before-define": 0,
        "arrow-body-style": [
            2, "as-needed"
        ],
        "arrow-parens": 0,
        "arrow-spacing": [
            2, {
                "before": true,
                "after": true
            }
        ],
        "comma-dangle": 0,
        "constructor-super": 0,
        "generator-star-spacing": 0,
        "no-class-assign": 2,
        "no-confusing-arrow": [
            2, {
                "allowParens": true
            }
        ],
        "no-const-assign": 2,
        "no-dupe-class-members": 2,
        "no-duplicate-imports": 2,
        "no-new-symbol": 2,
        "no-restricted-globals": 0,
        "no-restricted-imports": 0,
        "no-this-before-super": 0,
        "no-var": 2,
        "no-useless-computed-key": 2,
        "no-useless-constructor": 2,
        "object-shorthand": [
            2, "always"
        ],
        "prefer-arrow-callback": [
            2, {
                "allowNamedFunctions": true,
                "allowUnboundThis": true
            }
        ],
        "prefer-const": 1,
        "prefer-spread": 0,
        "prefer-reflect": 0,
        "prefer-rest-params": 2,
        "prefer-template": 1,
        "require-yield": 0,
        "sort-imports": 0,
        "template-curly-spacing": 2,
        "yield-star-spacing": [
            2, "after"
        ],
        "import/export": 2,
        "import/default": 0,
        "import/extensions": [
            0, "never"
        ],
        "import/named": 0,
        "import/namespace": 0,
        "import/no-extraneous-dependencies": [
            0, {
                "devDependencies": false,
                "optionalDependencies": false
            }
        ],
        "import/no-named-as-default": 0,
        "import/no-commonjs": 0,
        "import/no-amd": 2,
        "import/imports-first": [
            0, "absolute-first"
        ],
        "import/no-duplicates": 0,
        "import/no-deprecated": 0,
        "import/no-namespace": 0,
        "import/no-named-as-default-member": 0,
        "import/no-nodejs-modules": 0,
        "import/order": [
            0, {
                "groups": [
                    "builtin",
                    "external",
                    "internal",
                    "parent",
                    "sibling",
                    "index"
                ],
                "newlines-between": "never"
            }
        ],
        "import/newline-after-import": 0,
        "import/no-mutable-exports": 2,
        "strict": [
            2, "never"
        ],
        "react/display-name": [
            0, {
                "ignoreTranspilerName": false
            }
        ],
        "react/forbid-prop-types": [
            0, {
                "forbid": ["any", "array", "object"]
            }
        ],
        "react/jsx-boolean-value": [
            2, "never"
        ],
        "react/jsx-closing-bracket-location": 0,
        "react/jsx-curly-spacing": [
            2,
            "never", {
                "allowMultiline": true
            }
        ],
        "react/jsx-handler-names": [
            0, {
                "eventHandlerPrefix": "handle",
                "eventHandlerPropPrefix": "on"
            }
        ],
        "react/jsx-indent-props": 0,
        "react/jsx-key": 0,
        "react/jsx-max-props-per-line": [
            0, {
                "maximum": 1
            }
        ],
        "react/jsx-no-bind": [
            2, {
                "ignoreRefs": true,
                "allowArrowFunctions": true,
                "allowBind": false
            }
        ],
        "react/jsx-no-duplicate-props": [
            0, {
                "ignoreCase": false
            }
        ],
        "react/jsx-no-literals": 0,
        "react/jsx-no-undef": 2,
        "react/jsx-pascal-case": 2,
        "react/sort-prop-types": [
            0, {
                "ignoreCase": false,
                "callbacksLast": false
            }
        ],
        "react/jsx-sort-prop-types": 0,
        "react/jsx-sort-props": [
            0, {
                "ignoreCase": false,
                "callbacksLast": false
            }
        ],
        "react/jsx-filename-extension": 0,
        "react/jsx-uses-react": 1,
        "react/jsx-uses-vars": 1,
        "react/no-danger": 0,
        "react/no-deprecated": 1,
        "react/no-did-mount-set-state": 2,
        "react/no-did-update-set-state": 2,
        "react/no-direct-mutation-state": 0,
        "react/no-is-mounted": 2,
        "react/no-multi-comp": [
            2, {
                "ignoreStateless": true
            }
        ],
        "react/no-set-state": 0,
        "react/no-string-refs": 0,
        "react/no-unknown-property": 2,
        "react/prefer-es6-class": [
            2, "always"
        ],
        "react/prefer-stateless-function": 0,
        "react/prop-types": 0,
        "react/react-in-jsx-scope": 1,
        "react/require-extension": [
            0, {
                "extensions": [".jsx"]
            }
        ],
        "react/require-render-return": 2,
        "react/self-closing-comp": 0,
        "react/jsx-space-before-closing": [
            2, "always"
        ],
        "react/sort-comp": 0,
        "react/jsx-first-prop-new-line": 0,
        "react/jsx-equals-spacing": [
            2, "never"
        ],
        "react/jsx-indent": [
            1, 2
        ],
    }
};
<|endoftext|>


<commit_before>var fetch = fetch || require('node-fetch')

function jsref(ob, opts={}) {
  if (typeof ob !== 'object') return ob
  var $ref = opts.$ref || '$ref'
  var refs = opts.refs || {}
  var root = opts.root || 'http://localhost/'
  var vals = []
  var find = url => fetch(url.indexOf('http') ? root+url : url, opts.http).then(res => res.json())

  function extRefs(url) {
    var [url,ref] = url.split('#')
    ref = (ref && ref.length) ? ref : opts.frag
    var rec = find(url).then(rec => ref ? setRefs('#'+ref,rec) : rec)
    return opts.deep ? rec.then(getRefs) : rec
  }

  function setRefs(ref, val=ob) {
    if (ref[0] != '#') return opts.lazy ? extRefs(ref) : vals.push(extRefs(ref))
    var keys = ref.substring(1).split(/[\.\/]/)
    if (!keys[0].length) keys.shift()
    while(val && keys.length) val = val[keys.shift()]
    return val
  }

  function getRefs(ob) {
    if (ob && ob[$ref] && (!opts.like || RegExp(opts.like).test(ob[$ref]))) {
      if (!refs[ob[$ref]]) refs[ob[$ref]] = setRefs(ob[$ref])
    } else for (var i in ob) if (typeof ob[i] === 'object') getRefs(ob[i])
    return ob
  }

  function fixRefs(ob) {
    if (ob && ob[$ref]) return fixRefs(refs[ob[$ref]]) || ob
    for (var k in ob) if (typeof ob[k] === 'object') ob[k] = fixRefs(ob[k])
    return ob
  }

  getRefs(ob)
  if (opts.lazy) return Promise.resolve(fixRefs(ob))
  return Promise.all(vals).then(recs => {
    for (var r in refs) if (!isNaN(refs[r])) refs[r] = recs[refs[r]-1]
    return fixRefs(ob)
  }).catch(console.log)
}

if (typeof module == 'object') module.exports = jsref<commit_msg>refactor<commit_after>var fetch = fetch || require('node-fetch')

function jsref(ob, opts={}) {
  if (typeof ob !== 'object') return ob
  var $ref = opts.$ref || '$ref'
  var refs = opts.refs || {}
  var root = opts.root || 'http://localhost/'
  var find = url => fetch(url.indexOf('http') ? root+url : url, opts.http).then(res => res.json())
  var vals = []

  function extRefs(url) {
    var [url,ref] = url.split('#')
    ref = (ref && ref.length) ? ref : opts.frag
    var rec = (opts.find||find)(url).then(rec => ref ? setRefs('#'+ref,rec) : rec)
    return opts.deep ? rec.then(getRefs) : rec
  }

  function setRefs(ref, val=ob) {
    if (ref[0] != '#') return opts.lazy ? extRefs(ref) : vals.push(extRefs(ref))
    var keys = ref.substring(1).split(/[\.\/]/)
    if (!keys[0].length) keys.shift()
    while(val && keys.length) val = val[keys.shift()]
    return val
  }

  function getRefs(ob) {
    if (ob && ob[$ref] && (!opts.like || RegExp(opts.like).test(ob[$ref]))) {
      if (!refs[ob[$ref]]) refs[ob[$ref]] = setRefs(ob[$ref])
    } else for (var i in ob) if (typeof ob[i] === 'object') getRefs(ob[i])
    return ob
  }

  function fixRefs(ob) {
    if (ob && ob[$ref]) return fixRefs(refs[ob[$ref]]) || ob
    for (var k in ob) if (typeof ob[k] === 'object') ob[k] = fixRefs(ob[k])
    return ob
  }

  getRefs(ob)
  if (opts.lazy) return Promise.resolve(fixRefs(ob))
  return Promise.all(vals).then(recs => {
    for (var r in refs) if (!isNaN(refs[r])) refs[r] = recs[refs[r]-1]
    return fixRefs(ob)
  })
}

if (typeof module == 'object') module.exports = jsref<|endoftext|>


<commit_before>'use strict'

const request = require('request-promise-native')
const _async = require('asyncawait/async')
const _await = require('asyncawait/await')

const endpointsSpec = require('./endpointsSpec')

function nodeGlvrd (appName) {
  if (typeof appName !== 'string' || !appName.length) {
    throw new Error(`appName is required and should be a string. Got ${typeof appName} ${appName}`)
  }

  this.params = {
    app: appName,
    maxTextLength: 10000,
    maxHintsCount: 25
  }

  this.hintsCache = {}

  this.req = request.defaults({
    baseUrl: endpointsSpec.baseUrl,
    timeout: 1600
  })
}

nodeGlvrd.prototype.checkStatus = _async(function checkStatus () {
  let response = _await(this._makeRequest('getStatus'))

  this.params.maxTextLength = response['max_text_length']
  this.params.maxHintsCount = response['max_hints_count']

  return response
})

nodeGlvrd.prototype.proofread = _async(function proofread (text, callback) {
  try {
    let fragmentsWithoutHints = _await(this._makeRequest('postProofread', 'text=' + text))
    this._checkIfServerError(fragmentsWithoutHints)

    let fragmentsWithHints = []
    fragmentsWithHints = _await(this._fillRawFragmentsWithHints(fragmentsWithoutHints.fragments))
    this._checkIfServerError(fragmentsWithoutHints)

    if (!callback) return fragmentsWithHints
    callback(null, fragmentsWithHints)
  } catch (err) {
    if (!callback) throw new Error(err)
    callback(err, null)
  }
})

nodeGlvrd.prototype._fillRawFragmentsWithHints = _async(function _fillRawFragmentsWithHints (rawFragments) {
  // Check which hints already chached
  let uncachedHints = []
  rawFragments.forEach(fragment => this.hintsCache.hasOwnProperty(fragment.hint_id) ? false : uncachedHints.push(fragment.hint_id))

  // Early return if all our hints are cached
  if (uncachedHints.length === 0) {
    return _await(this._fillFragmentsWithHintFromCache(rawFragments))
  }

  // Remove duplicate hints
  let uncachedHintIds = {}
  uncachedHints.forEach(hintId => { uncachedHintIds[hintId] = null })

  // Query for uncached hints by chanks -- amount of hints in a singl request is limited
  let hintRequests = []
  this._chunkArray(Object.keys(uncachedHintIds), this.params.maxHintsCount)
    .forEach(uncachedHintIdsChunk =>
      hintRequests.push(this._makeRequest('postHints', 'ids=' + uncachedHintIdsChunk.join(',')))
    )

  let hintResposes = _await(Promise.all(hintRequests))

  // Fill cache with new hints
  let hints = []
  hintResposes.forEach(response => hints.concat(response.hints))
  Object.assign(this.hintsCache, hints)

  return this._fillFragmentsWithHintFromCache(rawFragments)
})

nodeGlvrd.prototype._fillFragmentsWithHintFromCache = function _fillFragmentsWithHintFromCache (fragments) {
  let prepareFragments = fragment => {
    let { name, description } = this.hintsCache[fragment.hint_id]

    fragment.hint = {
      id: fragment.hint_id,
      name: name,
      description: description
    }

    delete fragment.hint_id
    return fragment
  }

  return fragments.splice().map(prepareFragments)
}

nodeGlvrd.prototype._makeRequest = _async(function _makeRequest (endpointKey, body, isJson = true) {
  let endpoint = endpointsSpec.endpoints[endpointKey]
  let weNeedSessionForRequest = endpoint.queryParams.includes('session')

  if (weNeedSessionForRequest) {
    _await(this._checkSessionBeforeRequest())
  }

  // Prepare request
  let queryParams = this._fillQueryParams(endpoint.queryParams)
  let options = {
    method: endpoint.method,
    uri: endpoint.name,
    qs: queryParams,
    json: isJson
  }

  if (body) {
    options.body = body
  }

  // Make request
  let responseBody = _await(this.req(options))

  // Check request response
  if (responseBody.status && responseBody.status === 'error') {
    if (responseBody.code === endpointsSpec.errorsForCover.bad_session.code) {
      // Try to update session and repeat request silently
      _await(this._createSession())
      responseBody = _await(this.req(options))
    } else {
      throw new Error(responseBody)
    }
  }

  if (endpoint.method === 'post') {
    this._extendSession() // Every POST request extends session
  }

  return responseBody
})

nodeGlvrd.prototype._checkSessionBeforeRequest = _async(function _checkSessionBeforeRequest () {
  let isSessionValid = this.params.sessionValidUntil > (Date.now() + 1000)

  if (this.params.session && isSessionValid) {
    return
  }

  _await(this._createSession())
})

nodeGlvrd.prototype._fillQueryParams = function _fillQueryParams (endpointQueryParams) {
  let queryParams = {}

  endpointQueryParams.forEach(queryParamName => {
    if (this.params.hasOwnProperty(queryParamName)) {
      queryParams[queryParamName] = this.params[queryParamName]
    }
  })

  return queryParams
}

nodeGlvrd.prototype._createSession = _async(function _createSession () {
  let response = _await(this._makeRequest('postSession'))
  this._resetSessionParams(response.session, response.lifespan)
})

nodeGlvrd.prototype._extendSession = function _extendSession () {
  this._resetSessionParams(this.params.session, this.params.sessionLifespan)
}

nodeGlvrd.prototype._resetSessionParams = function _resetSessionParams (session, lifespan) {
  if (session !== this.params.session) {
    this.hintsCache = {}
  }

  this.params.session = session
  this.params.sessionLifespan = lifespan
  this.params.sessionValidUntil = Date.now() + lifespan * 1000
}

nodeGlvrd.prototype._chunkArray = function _chunkArray (arr, len) {
  let chunks = []
  let i = 0
  let n = arr.length

  while (i < n) {
    chunks.push(arr.slice(i, i += len))
  }

  return chunks
}

nodeGlvrd.prototype._checkIfServerError = function _checkIfServerError (functionResult) {
  if (functionResult.status && functionResult.status === 'error') {
    throw (functionResult)
  }
}

module.exports = nodeGlvrd
<commit_msg>fix(request): Increase request timeout<commit_after>'use strict'

const request = require('request-promise-native')
const _async = require('asyncawait/async')
const _await = require('asyncawait/await')

const endpointsSpec = require('./endpointsSpec')

function nodeGlvrd (appName) {
  if (typeof appName !== 'string' || !appName.length) {
    throw new Error(`appName is required and should be a string. Got ${typeof appName} ${appName}`)
  }

  this.params = {
    app: appName,
    maxTextLength: 10000,
    maxHintsCount: 25
  }

  this.hintsCache = {}

  this.req = request.defaults({
    baseUrl: endpointsSpec.baseUrl,
    timeout: 3000
  })
}

nodeGlvrd.prototype.checkStatus = _async(function checkStatus () {
  let response = _await(this._makeRequest('getStatus'))

  this.params.maxTextLength = response['max_text_length']
  this.params.maxHintsCount = response['max_hints_count']

  return response
})

nodeGlvrd.prototype.proofread = _async(function proofread (text, callback) {
  try {
    let fragmentsWithoutHints = _await(this._makeRequest('postProofread', 'text=' + text))
    this._checkIfServerError(fragmentsWithoutHints)

    let fragmentsWithHints = []
    fragmentsWithHints = _await(this._fillRawFragmentsWithHints(fragmentsWithoutHints.fragments))
    this._checkIfServerError(fragmentsWithoutHints)

    if (!callback) return fragmentsWithHints
    callback(null, fragmentsWithHints)
  } catch (err) {
    if (!callback) throw new Error(err)
    callback(err, null)
  }
})

nodeGlvrd.prototype._fillRawFragmentsWithHints = _async(function _fillRawFragmentsWithHints (rawFragments) {
  // Check which hints already chached
  let uncachedHints = []
  rawFragments.forEach(fragment => this.hintsCache.hasOwnProperty(fragment.hint_id) ? false : uncachedHints.push(fragment.hint_id))

  // Early return if all our hints are cached
  if (uncachedHints.length === 0) {
    return _await(this._fillFragmentsWithHintFromCache(rawFragments))
  }

  // Remove duplicate hints
  let uncachedHintIds = {}
  uncachedHints.forEach(hintId => { uncachedHintIds[hintId] = null })

  // Query for uncached hints by chanks -- amount of hints in a singl request is limited
  let hintRequests = []
  this._chunkArray(Object.keys(uncachedHintIds), this.params.maxHintsCount)
    .forEach(uncachedHintIdsChunk =>
      hintRequests.push(this._makeRequest('postHints', 'ids=' + uncachedHintIdsChunk.join(',')))
    )

  let hintResposes = _await(Promise.all(hintRequests))

  // Fill cache with new hints
  let hints = []
  hintResposes.forEach(response => hints.concat(response.hints))
  Object.assign(this.hintsCache, hints)

  return this._fillFragmentsWithHintFromCache(rawFragments)
})

nodeGlvrd.prototype._fillFragmentsWithHintFromCache = function _fillFragmentsWithHintFromCache (fragments) {
  let prepareFragments = fragment => {
    let { name, description } = this.hintsCache[fragment.hint_id]

    fragment.hint = {
      id: fragment.hint_id,
      name: name,
      description: description
    }

    delete fragment.hint_id
    return fragment
  }

  return fragments.splice().map(prepareFragments)
}

nodeGlvrd.prototype._makeRequest = _async(function _makeRequest (endpointKey, body, isJson = true) {
  let endpoint = endpointsSpec.endpoints[endpointKey]
  let weNeedSessionForRequest = endpoint.queryParams.includes('session')

  if (weNeedSessionForRequest) {
    _await(this._checkSessionBeforeRequest())
  }

  // Prepare request
  let queryParams = this._fillQueryParams(endpoint.queryParams)
  let options = {
    method: endpoint.method,
    uri: endpoint.name,
    qs: queryParams,
    json: isJson
  }

  if (body) {
    options.body = body
  }

  // Make request
  let responseBody = _await(this.req(options))

  // Check request response
  if (responseBody.status && responseBody.status === 'error') {
    if (responseBody.code === endpointsSpec.errorsForCover.bad_session.code) {
      // Try to update session and repeat request silently
      _await(this._createSession())
      responseBody = _await(this.req(options))
    } else {
      throw new Error(responseBody)
    }
  }

  if (endpoint.method === 'post') {
    this._extendSession() // Every POST request extends session
  }

  return responseBody
})

nodeGlvrd.prototype._checkSessionBeforeRequest = _async(function _checkSessionBeforeRequest () {
  let isSessionValid = this.params.sessionValidUntil > (Date.now() + 1000)

  if (this.params.session && isSessionValid) {
    return
  }

  _await(this._createSession())
})

nodeGlvrd.prototype._fillQueryParams = function _fillQueryParams (endpointQueryParams) {
  let queryParams = {}

  endpointQueryParams.forEach(queryParamName => {
    if (this.params.hasOwnProperty(queryParamName)) {
      queryParams[queryParamName] = this.params[queryParamName]
    }
  })

  return queryParams
}

nodeGlvrd.prototype._createSession = _async(function _createSession () {
  let response = _await(this._makeRequest('postSession'))
  this._resetSessionParams(response.session, response.lifespan)
})

nodeGlvrd.prototype._extendSession = function _extendSession () {
  this._resetSessionParams(this.params.session, this.params.sessionLifespan)
}

nodeGlvrd.prototype._resetSessionParams = function _resetSessionParams (session, lifespan) {
  if (session !== this.params.session) {
    this.hintsCache = {}
  }

  this.params.session = session
  this.params.sessionLifespan = lifespan
  this.params.sessionValidUntil = Date.now() + lifespan * 1000
}

nodeGlvrd.prototype._chunkArray = function _chunkArray (arr, len) {
  let chunks = []
  let i = 0
  let n = arr.length

  while (i < n) {
    chunks.push(arr.slice(i, i += len))
  }

  return chunks
}

nodeGlvrd.prototype._checkIfServerError = function _checkIfServerError (functionResult) {
  if (functionResult.status && functionResult.status === 'error') {
    throw (functionResult)
  }
}

module.exports = nodeGlvrd
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2014, CKSource - Frederico Knabben. All rights reserved.
 * Licensed under the terms of the MIT License (see LICENSE.md).
 */

'use strict';

var minimatch = require( 'minimatch' ),
	fs = require( 'graceful-fs' ),
	path = require( 'path' );

/**
 * Reads directory recursively
 * @param  {String}   dir               Directory to be read
 * @param  {Object}   [options]         Configuration options
 * @param  {String}   [options.ignore]  Ignore file pattern, supports globstar matching
 * @param  {Boolean}  [options.stats]   Return file objects containing file statistics
 * @param  {Function} callback          Function called when done or error occured
 */
function gerard( dir, options, callback ) {
	var results = [],
		count = 0;

	if ( typeof options == 'function' ) {
		callback = options;
		options = {};
	}

	function decreaseCounter() {
		count--;

		if ( !count ) {
			callback( null, results );
		}
	}

	fs.readdir( dir, function( err, files ) {
		if ( err ) {
			return callback( err );
		}

		if ( !( count = files.length ) ) {
			return callback( null, results );
		}

		files.forEach( function( file ) {
			var name = file;

			file = path.join( dir, file );

			if ( options.ignore && minimatch( file, options.ignore ) ) {
				return decreaseCounter();
			}

			fs.lstat( file, function( err, stats ) {
				if ( err ) {
					return callback( err );
				}

				if ( stats.isDirectory() ) {
					gerard( file, options, function( err, files ) {
						if ( err ) {
							return callback( err );
						}

						results = results.concat( files );

						decreaseCounter();
					} );
				} else {
					if ( options.stats ) {
						results.push( {
							name: name,
							dir: dir,
							path: file,
							stats: stats
						} );
					} else {
						results.push( file );
					}

					decreaseCounter();
				}
			} );
		} );
	} );
}

module.exports = gerard;
<commit_msg>Resolved #2 - added stopOnErrors option.<commit_after>/**
 * Copyright (c) 2014, CKSource - Frederico Knabben. All rights reserved.
 * Licensed under the terms of the MIT License (see LICENSE.md).
 */

'use strict';

var minimatch = require( 'minimatch' ),
	fs = require( 'graceful-fs' ),
	path = require( 'path' );

/**
 * Reads directory recursively
 * @param  {String}   dir                     Directory to be read
 * @param  {Object}   [options]               Configuration options
 * @param  {String}   [options.ignore]        Ignore file pattern, supports globstar matching
 * @param  {Boolean}  [options.stats]         Return file objects containing file statistics
 * @param  {Boolean}  [options.stopOnErrors]  Stop reading the directory on first error
 * @param  {Function} callback                Function called when done or error occured
 */
function gerard( dir, options, callback ) {
	var results = [],
		count = 0;

	if ( arguments.length < 2 ) {
		return callback( new Error( 'Invalid number arguments for Gerard specified.' ) );
	}

	if ( typeof options == 'function' ) {
		callback = options;
		options = {};
	}

	options.stopOnErrors = ( options.stopOnErrors === undefined ) ? true : options.stopOnErrors;

	function decreaseCounter() {
		count--;

		if ( !count ) {
			callback( null, results );
		}
	}

	fs.readdir( dir, function( err, files ) {
		if ( err && options.stopOnErrors ) {
			return callback( err );
		}

		if ( !files || !( count = files.length ) ) {
			return callback( null, results );
		}

		files.forEach( function( file ) {
			var name = file;

			file = path.join( dir, file );

			if ( options.ignore && minimatch( file, options.ignore ) ) {
				return decreaseCounter();
			}

			fs.lstat( file, function( err, stats ) {
				if ( err && options.stopOnErrors ) {
					return callback( err );
				}

				if ( err ) {
					return decreaseCounter();
				}

				if ( stats.isDirectory() ) {
					gerard( file, options, function( err, files ) {
						if ( err && options.stopOnErrors ) {
							return callback( err );
						}

						if ( !err ) {
							results = results.concat( files );
						}

						decreaseCounter();
					} );
				} else {
					if ( options.stats ) {
						results.push( {
							name: name,
							dir: dir,
							path: file,
							stats: stats
						} );
					} else {
						results.push( file );
					}

					decreaseCounter();
				}
			} );
		} );
	} );
}

module.exports = gerard;
<|endoftext|>


<commit_before>'use strict';

var React = require('react-native');
var {
  PixelRatio,
  StatusBarIOS,
  StyleSheet,
  Text,
  TouchableOpacity,
  View
} = React;

var NavigatorNavigationBarStyles = require('NavigatorNavigationBarStyles');
var StaticContainer = require('StaticContainer.react');

var styles = StyleSheet.create({
  navBarContainer: {
    height: NavigatorNavigationBarStyles.General.TotalNavHeight,
    backgroundColor: 'white',
    flexDirection: 'row',
    alignItems: 'flex-end',
    paddingBottom: 5,
    borderBottomColor: 'rgba(0, 0, 0, 0.5)',
    borderBottomWidth: 1 / PixelRatio.get(),
    justifyContent: 'space-between',
  },
  customTitle: {
    position: 'absolute',
    alignItems: 'center',
    bottom: 5,
    left: 0,
    right: 0,
  },
  navBarText: {
    fontSize: 16,
    marginVertical: 10,
    flex: 2,
    textAlign: 'center',
  },
  navBarTitleText: {
    color: '#373e4d',
    fontWeight: '500',
    position: 'absolute',
    left: 0,
    right: 0,
    bottom: 15,
  },
  navBarLeftButton: {
    paddingLeft: 10,
  },
  navBarRightButton: {
    paddingRight: 10,
  },
  navBarButtonText: {
    color: '#5890ff',
  }
});

var NavigationBar = React.createClass({

  propTypes: {
    navigator: React.PropTypes.object.isRequired,
    route: React.PropTypes.object.isRequired,
  },

  getDefaultProps: function() {
    return {
      shouldUpdate: false
    }
  },

  /*
   * If there are no routes in the stack, `hidePrev` isn't provided or false,
   * and we haven't received `onPrev` click handler, return true
   */
  prevButtonShouldBeHidden: function() {
    var {
      onPrev,
      hidePrev,
      navigator
    } = this.props;

    var getCurrentRoutes = navigator.getCurrentRoutes;

    return (
      hidePrev ||
      (getCurrentRoutes && getCurrentRoutes().length <= 1 && !onPrev)
    );
  },

  /**
   * Describes how we get a left button in the navbar
   */
  getLeftButtonElement: function() {
    var {
      onPrev,
      prevTitle,
      navigator,
      route,
      buttonsColor,
      customPrev,
    } = this.props;

    /*
     * If we have a `customPrev` component, then return
     * it's clone with additional attributes
     */
    if (customPrev) {
      return React.addons.cloneWithProps(customPrev, { navigator, route });
    }

    /*
     * Check if we need to hide `prev` button
     */
    if (this.prevButtonShouldBeHidden()) {
      return <View style={styles.navBarLeftButton}></View>;
    }

    /*
     * Apply custom background styles to button
     */
    var customStyle = buttonsColor ? { color: buttonsColor } : {};

    return (
      <TouchableOpacity onPress={onPrev || navigator.pop}>
        <View style={styles.navBarLeftButton}>
          <Text style={[styles.navBarText, styles.navBarButtonText, customStyle]}>
            {prevTitle || 'Back'}
          </Text>
        </View>
      </TouchableOpacity>
    );
  },

  /*
   * Describe how we get a title for the navbar
   */
  getTitleElement: function() {
    var {
      title,
      titleColor,
      customTitle,
      navigator,
      route,
    } = this.props;

    /*
     * Return `customTitle` component if we have it
     */
    if (customTitle) {
      return (
        <View style={styles.customTitle}>
          {React.addons.cloneWithProps(customTitle, { navigator, route })}
        </View>
      );
    }

    if (title && !title.length) {
      return true;
    }

    var titleStyle = [
      styles.navBarText,
      styles.navBarTitleText,
      { color: titleColor }
    ];

    return (
      <Text style={titleStyle}>
        {title}
      </Text>
    );
  },

  getRightButtonElement: function() {
    var {
      onNext,
      nextTitle,
      navigator,
      route,
      buttonsColor,
      customNext
    } = this.props;

    /*
     * If we have a `customNext` component, then return
     * it's clone with additional attributes
     */
    if (customNext) {
      return React.addons.cloneWithProps(customNext, { navigator, route });
    }

    /*
     * If we haven't received `onNext` handler, then just return
     * a placeholder for button to keep markup consistant and
     * title aligned to the center
     */
    if (!onNext) {
      return <Text style={styles.navBarRightButton}></Text>;
    }

    /*
     * Apply custom background styles to button
     */
    var customStyle = buttonsColor ? { color: buttonsColor } : {};

    return (
      <TouchableOpacity onPress={onNext}>
        <View style={styles.navBarRightButton}>
          <Text style={[styles.navBarText, styles.navBarButtonText, customStyle]}>
            {nextTitle || 'Next'}
          </Text>
        </View>
      </TouchableOpacity>
    );
  },

  render: function() {

    if (this.props.statusBar === 'lightContent') {
      StatusBarIOS.setStyle('light-content', false);
    } else if (this.props.statusBar === 'default') {
      StatusBarIOS.setStyle('default', false);
    }

    var backgroundStyle = this.props.backgroundColor ?
      { backgroundColor: this.props.backgroundColor } : {},
        customStyle = this.props.style;

    return (
      <StaticContainer shouldUpdate={this.props.shouldUpdate}>
        <View style={[styles.navBarContainer, backgroundStyle, customStyle ]}>
          {this.getTitleElement()}
          {this.getLeftButtonElement()}
          {this.getRightButtonElement()}
        </View>
      </StaticContainer>
    );
  },
});

module.exports = NavigationBar;
<commit_msg>Adding "shouldUpdate" to propTypes<commit_after>'use strict';

var React = require('react-native');
var {
  PixelRatio,
  StatusBarIOS,
  StyleSheet,
  Text,
  TouchableOpacity,
  View
} = React;

var NavigatorNavigationBarStyles = require('NavigatorNavigationBarStyles');
var StaticContainer = require('StaticContainer.react');

var styles = StyleSheet.create({
  navBarContainer: {
    height: NavigatorNavigationBarStyles.General.TotalNavHeight,
    backgroundColor: 'white',
    flexDirection: 'row',
    alignItems: 'flex-end',
    paddingBottom: 5,
    borderBottomColor: 'rgba(0, 0, 0, 0.5)',
    borderBottomWidth: 1 / PixelRatio.get(),
    justifyContent: 'space-between',
  },
  customTitle: {
    position: 'absolute',
    alignItems: 'center',
    bottom: 5,
    left: 0,
    right: 0,
  },
  navBarText: {
    fontSize: 16,
    marginVertical: 10,
    flex: 2,
    textAlign: 'center',
  },
  navBarTitleText: {
    color: '#373e4d',
    fontWeight: '500',
    position: 'absolute',
    left: 0,
    right: 0,
    bottom: 15,
  },
  navBarLeftButton: {
    paddingLeft: 10,
  },
  navBarRightButton: {
    paddingRight: 10,
  },
  navBarButtonText: {
    color: '#5890ff',
  }
});

var NavigationBar = React.createClass({

  propTypes: {
    navigator: React.PropTypes.object.isRequired,
    route: React.PropTypes.object.isRequired,
    shouldUpdate: React.PropTypes.bool
  },

  getDefaultProps: function() {
    return {
      shouldUpdate: false
    }
  },

  /*
   * If there are no routes in the stack, `hidePrev` isn't provided or false,
   * and we haven't received `onPrev` click handler, return true
   */
  prevButtonShouldBeHidden: function() {
    var {
      onPrev,
      hidePrev,
      navigator
    } = this.props;

    var getCurrentRoutes = navigator.getCurrentRoutes;

    return (
      hidePrev ||
      (getCurrentRoutes && getCurrentRoutes().length <= 1 && !onPrev)
    );
  },

  /**
   * Describes how we get a left button in the navbar
   */
  getLeftButtonElement: function() {
    var {
      onPrev,
      prevTitle,
      navigator,
      route,
      buttonsColor,
      customPrev,
    } = this.props;

    /*
     * If we have a `customPrev` component, then return
     * it's clone with additional attributes
     */
    if (customPrev) {
      return React.addons.cloneWithProps(customPrev, { navigator, route });
    }

    /*
     * Check if we need to hide `prev` button
     */
    if (this.prevButtonShouldBeHidden()) {
      return <View style={styles.navBarLeftButton}></View>;
    }

    /*
     * Apply custom background styles to button
     */
    var customStyle = buttonsColor ? { color: buttonsColor } : {};

    return (
      <TouchableOpacity onPress={onPrev || navigator.pop}>
        <View style={styles.navBarLeftButton}>
          <Text style={[styles.navBarText, styles.navBarButtonText, customStyle]}>
            {prevTitle || 'Back'}
          </Text>
        </View>
      </TouchableOpacity>
    );
  },

  /*
   * Describe how we get a title for the navbar
   */
  getTitleElement: function() {
    var {
      title,
      titleColor,
      customTitle,
      navigator,
      route,
    } = this.props;

    /*
     * Return `customTitle` component if we have it
     */
    if (customTitle) {
      return (
        <View style={styles.customTitle}>
          {React.addons.cloneWithProps(customTitle, { navigator, route })}
        </View>
      );
    }

    if (title && !title.length) {
      return true;
    }

    var titleStyle = [
      styles.navBarText,
      styles.navBarTitleText,
      { color: titleColor }
    ];

    return (
      <Text style={titleStyle}>
        {title}
      </Text>
    );
  },

  getRightButtonElement: function() {
    var {
      onNext,
      nextTitle,
      navigator,
      route,
      buttonsColor,
      customNext
    } = this.props;

    /*
     * If we have a `customNext` component, then return
     * it's clone with additional attributes
     */
    if (customNext) {
      return React.addons.cloneWithProps(customNext, { navigator, route });
    }

    /*
     * If we haven't received `onNext` handler, then just return
     * a placeholder for button to keep markup consistant and
     * title aligned to the center
     */
    if (!onNext) {
      return <Text style={styles.navBarRightButton}></Text>;
    }

    /*
     * Apply custom background styles to button
     */
    var customStyle = buttonsColor ? { color: buttonsColor } : {};

    return (
      <TouchableOpacity onPress={onNext}>
        <View style={styles.navBarRightButton}>
          <Text style={[styles.navBarText, styles.navBarButtonText, customStyle]}>
            {nextTitle || 'Next'}
          </Text>
        </View>
      </TouchableOpacity>
    );
  },

  render: function() {

    if (this.props.statusBar === 'lightContent') {
      StatusBarIOS.setStyle('light-content', false);
    } else if (this.props.statusBar === 'default') {
      StatusBarIOS.setStyle('default', false);
    }

    var backgroundStyle = this.props.backgroundColor ?
      { backgroundColor: this.props.backgroundColor } : {},
        customStyle = this.props.style;

    return (
      <StaticContainer shouldUpdate={this.props.shouldUpdate}>
        <View style={[styles.navBarContainer, backgroundStyle, customStyle ]}>
          {this.getTitleElement()}
          {this.getLeftButtonElement()}
          {this.getRightButtonElement()}
        </View>
      </StaticContainer>
    );
  },
});

module.exports = NavigationBar;
<|endoftext|>


<commit_before>//filter will reemit the data if cb(err,pass) pass is truthy

// reduce is more tricky
// maybe we want to group the reductions or emit progress updates occasionally
// the most basic reduce just emits one 'data' event after it has recieved 'end'

var through = require('through')

module.exports = split

//TODO pass in a function to map across the lines.

function split (matcher, mapper) {
  var soFar = ''
  if('function' === typeof matcher)
    mapper = matcher, matcher = null
  if (!matcher)
    matcher = '\n'

  return through(function (buffer) {
    var stream = this
      , pieces = (soFar + buffer).split(matcher)
    soFar = pieces.pop()

    for (var i = 0; i < pieces.length; i++) {
      var piece = pieces[i]
      if(mapper) {
        piece = mapper(piece)
        if('undefined' !== typeof piece)
          stream.queue(piece)
      }
      else
        stream.queue(piece)
    }
  },
  function () {
    if(soFar)
      this.queue(soFar)
    this.queue(null)
  })
}

<commit_msg>fix bug with empty lines at end (where last char is a \n)<commit_after>//filter will reemit the data if cb(err,pass) pass is truthy

// reduce is more tricky
// maybe we want to group the reductions or emit progress updates occasionally
// the most basic reduce just emits one 'data' event after it has recieved 'end'

var through = require('through')

module.exports = split

//TODO pass in a function to map across the lines.

function split (matcher, mapper) {
  var soFar = ''
  if('function' === typeof matcher)
    mapper = matcher, matcher = null
  if (!matcher)
    matcher = '\n'

  return through(function (buffer) {
    var stream = this
      , pieces = (soFar + buffer).split(matcher)
    soFar = pieces.pop()

    for (var i = 0; i < pieces.length; i++) {
      var piece = pieces[i]
      if(mapper) {
        piece = mapper(piece)
        if('undefined' !== typeof piece)
          stream.queue(piece)
      }
      else
        stream.queue(piece)
    }
  },
  function () {
    if(soFar != null)
      this.queue(soFar)
    this.queue(null)
  })
}

<|endoftext|>


<commit_before>// ==UserScript==
// @name        khanacademy-disable-sub
// @description disable youtube subs by default
// @namespace   https://gitlab.com/zalent/khanacademy-disable-sub
// @include     https://www.khanacademy.org/*
// @version     0.1.0.2
// @author      liartuw
// @run-at      document-end
// @grant       none
// @downloadURL https://gitlab.com/zalent/khanacademy-disable-sub/raw/master/index.js
// @updateURL   https://gitlab.com/zalent/khanacademy-disable-sub/raw/master/index.js
// ==/UserScript==
(() => {
    addOnChangeEventListenerTo(document.body, () => {
        if (isVideoPlayerLoaded()) {
            disableVideoPlayerSubtitles();
        }
    });

    function addOnChangeEventListenerTo(element, listener) {
        let observer = new MutationObserver(listener);
        observer.observe(
            element,
            {
                childList: true,
                subtree: true,
                attributes: false,
                characterData: false,
            }
        );
    }

    function isVideoPlayerLoaded() {
        let playerContainer = getVideoPlayerContainer();
        return playerContainer !== null;
    }

    function disableVideoPlayerSubtitles() {
        let playerIframe = getVideoPlayerContainer().firstChild;
        let isSubEnabled = playerIframe.src.includes(SUB_ENABLED_URL_PARAM);
        if (isSubEnabled) {
            let srcUrlWithSubDisabled = playerIframe.src.replace(
                SUB_ENABLED_URL_PARAM,
                SUB_DISABLED_URL_PARAM,
            );
            playerIframe.src = srcUrlWithSubDisabled;
        }
    }

    function getVideoPlayerContainer() {
        return document.querySelector(PLAYER_CONTAINER_SELECTOR);
    }

    const PLAYER_CONTAINER_SELECTOR = '.ka-video-player-container';
    const SUB_ENABLED_URL_PARAM = 'cc_load_policy=1';
    const SUB_DISABLED_URL_PARAM = 'cc_load_policy=0';
})();
<commit_msg>Fix js syntax for ES5<commit_after>// ==UserScript==
// @name        khanacademy-disable-sub
// @description disable youtube subs by default
// @namespace   https://gitlab.com/zalent/khanacademy-disable-sub
// @include     https://www.khanacademy.org/*
// @version     0.1.0.3
// @author      liartuw
// @run-at      document-end
// @grant       none
// @downloadURL https://gitlab.com/zalent/khanacademy-disable-sub/raw/master/index.js
// @updateURL   https://gitlab.com/zalent/khanacademy-disable-sub/raw/master/index.js
// ==/UserScript==
(() => {
    addOnChangeEventListenerTo(document.body, () => {
        if (isVideoPlayerLoaded()) {
            disableVideoPlayerSubtitles();
        }
    });

    function addOnChangeEventListenerTo(element, listener) {
        let observer = new MutationObserver(listener);
        observer.observe(
            element,
            {
                childList: true,
                subtree: true,
                attributes: false,
                characterData: false,
            }
        );
    }

    function isVideoPlayerLoaded() {
        let playerContainer = getVideoPlayerContainer();
        return playerContainer !== null;
    }

    function disableVideoPlayerSubtitles() {
        let playerIframe = getVideoPlayerContainer().firstChild;
        let isSubEnabled = playerIframe.src.includes(SUB_ENABLED_URL_PARAM);
        if (isSubEnabled) {
            let srcUrlWithSubDisabled = playerIframe.src.replace(
                SUB_ENABLED_URL_PARAM,
                SUB_DISABLED_URL_PARAM
            );
            playerIframe.src = srcUrlWithSubDisabled;
        }
    }

    function getVideoPlayerContainer() {
        return document.querySelector(PLAYER_CONTAINER_SELECTOR);
    }

    const PLAYER_CONTAINER_SELECTOR = '.ka-video-player-container';
    const SUB_ENABLED_URL_PARAM = 'cc_load_policy=1';
    const SUB_DISABLED_URL_PARAM = 'cc_load_policy=0';
})();
<|endoftext|>