<commit_before>var myReporter = {

jasmine_format: {},
suite_info: [],
spec: {},
suite_count: 0,
spec_count: 0,

jasmineStarted: function(suiteInfo) {
	this.jasmine_format["started"] = new Date().toUTCString();
	this.jasmine_format["type"] = "Jasmine"
},

suiteStarted: function(result) {
# suite object initialization
	this.suite_info[this.suite_count] = result;
	this.suite_info[this.suite_count]["started"] = new Date().toUTCString();
	this.suite_count++;
},

specStarted: function(result) {
// spec object initialization
	this.spec[this.spec_count] = {}
	this.spec[this.spec_count]["name"] = result.description;
	this.spec[this.spec_count]["fullName"] = result.fullName;
	this.spec[this.spec_count]["started"] = new Date().toUTCString();
},

specDone: function(result) {
	this.spec[this.spec_count]["status"] = result.status;
	var i = this.suite_count - 1;

// Attach specs to corresponding suite
	suite_name = this.spec[this.spec_count]["fullName"].replace(this.spec[this.spec_count]["name"],"").trim();
	while(i > 0){
		if(suite_name == this.suite_info[i]["fullName"]){
			if(typeof this.suite_info[i]["children"] == "undefined"){
				this.suite_info[i]["children"] = []
				this.suite_info[i]["children"][0] = this.spec[this.spec_count];
			}else{
				var k = this.suite_info[i]["children"].length;
				this.suite_info[i]["children"][k] = this.spec[this.spec_count];
			}
		}
		i--;
	}
	this.spec[this.spec_count]["finished"] = new Date().toUTCString();
	this.spec_count ++;
},

suiteDone: function(result) {
// Suite final assignments and attachment to parent suite
	var i = this.suite_count - 1;
	var index = 0;
	var k = 0;

	while(i > 0){
		if(this.suite_info[i]["description"] == result.description){
			index = i;
			break;
		}
		i--;
	}

	if(typeof this.suite_info[index]["children"] != "undefined"){
		while(k < this.suite_info[index]["children"].length){
			if(this.suite_info[index]["children"][k]["status"] == "failed"){
				this.suite_info[index]["status"] = "failed";
				k = this.suite_info[index]["children"].length;
			}else{
				this.suite_info[index]["status"] = "passed";
			}
			k++;
		}
		k = 0;
	}
	this.suite_info[index]["finished"] = new Date().toUTCString();
	console.log(this.suite_info);
},

jasmineDone: function() {
// Attach suites to parent suites (which are already not attached). Set the parent suite status
	var k = this.suite_count - 1;
	while(k > 0){
		parent = this.suite_info[k]["fullName"].replace(this.suite_info[k]["description"],"").trim();
		if(parent != ""){
			for(var i = 0; i < k; i++){
				if(parent == this.suite_info[i]["fullName"]){
					if(typeof this.suite_info[i]["children"] == "undefined"){
						this.suite_info[i]["children"] = []
						this.suite_info[i]["children"][0] = this.suite_info[k];
						this.suite_info[i]["status"] = status(this.suite_info[i]["status"], this.suite_info[k]["status"])
						this.suite_info = remove(this.suite_info, k);
					}else{
						var p = this.suite_info[i]["children"].length;
						this.suite_info[i]["children"][p] = this.suite_info[k];
						this.suite_info[i]["status"] = status(this.suite_info[i]["status"], this.suite_info[i]["status"])
						this.suite_info = remove(this.suite_info, k);
					}
				}
			}
		}
		k--;
	}
this.jasmine_format["finished"] = new Date().toUTCString();
this.jasmine_format["results"] = this.suite_info;
return JSON.stringify(this.jasmine_format)
},

};

// Returns the status of suite
function status(current_status, status){
	if(status == "failed"){
		return "failed";
	}else{
		if(current_status != "failed"){
			return "passed"
		}
	}
}

// Remove empty or unused array slot
function remove(suite, position){
	suite.splice(position, 1);
	return suite;
}<commit_msg>Changed name<commit_after>var jasmineReporter = {

jasmine_format: {},
suite_info: [],
spec: {},
suite_count: 0,
spec_count: 0,

jasmineStarted: function(suiteInfo) {
	this.jasmine_format["started"] = new Date().toUTCString();
	this.jasmine_format["type"] = "Jasmine"
},

suiteStarted: function(result) {
# suite object initialization
	this.suite_info[this.suite_count] = result;
	this.suite_info[this.suite_count]["started"] = new Date().toUTCString();
	this.suite_count++;
},

specStarted: function(result) {
// spec object initialization
	this.spec[this.spec_count] = {}
	this.spec[this.spec_count]["name"] = result.description;
	this.spec[this.spec_count]["fullName"] = result.fullName;
	this.spec[this.spec_count]["started"] = new Date().toUTCString();
},

specDone: function(result) {
	this.spec[this.spec_count]["status"] = result.status;
	var i = this.suite_count - 1;

// Attach specs to corresponding suite
	suite_name = this.spec[this.spec_count]["fullName"].replace(this.spec[this.spec_count]["name"],"").trim();
	while(i > 0){
		if(suite_name == this.suite_info[i]["fullName"]){
			if(typeof this.suite_info[i]["children"] == "undefined"){
				this.suite_info[i]["children"] = []
				this.suite_info[i]["children"][0] = this.spec[this.spec_count];
			}else{
				var k = this.suite_info[i]["children"].length;
				this.suite_info[i]["children"][k] = this.spec[this.spec_count];
			}
		}
		i--;
	}
	this.spec[this.spec_count]["finished"] = new Date().toUTCString();
	this.spec_count ++;
},

suiteDone: function(result) {
// Suite final assignments and attachment to parent suite
	var i = this.suite_count - 1;
	var index = 0;
	var k = 0;

	while(i > 0){
		if(this.suite_info[i]["description"] == result.description){
			index = i;
			break;
		}
		i--;
	}

	if(typeof this.suite_info[index]["children"] != "undefined"){
		while(k < this.suite_info[index]["children"].length){
			if(this.suite_info[index]["children"][k]["status"] == "failed"){
				this.suite_info[index]["status"] = "failed";
				k = this.suite_info[index]["children"].length;
			}else{
				this.suite_info[index]["status"] = "passed";
			}
			k++;
		}
		k = 0;
	}
	this.suite_info[index]["finished"] = new Date().toUTCString();
	console.log(this.suite_info);
},

jasmineDone: function() {
// Attach suites to parent suites (which are already not attached). Set the parent suite status
	var k = this.suite_count - 1;
	while(k > 0){
		parent = this.suite_info[k]["fullName"].replace(this.suite_info[k]["description"],"").trim();
		if(parent != ""){
			for(var i = 0; i < k; i++){
				if(parent == this.suite_info[i]["fullName"]){
					if(typeof this.suite_info[i]["children"] == "undefined"){
						this.suite_info[i]["children"] = []
						this.suite_info[i]["children"][0] = this.suite_info[k];
						this.suite_info[i]["status"] = status(this.suite_info[i]["status"], this.suite_info[k]["status"])
						this.suite_info = remove(this.suite_info, k);
					}else{
						var p = this.suite_info[i]["children"].length;
						this.suite_info[i]["children"][p] = this.suite_info[k];
						this.suite_info[i]["status"] = status(this.suite_info[i]["status"], this.suite_info[i]["status"])
						this.suite_info = remove(this.suite_info, k);
					}
				}
			}
		}
		k--;
	}
this.jasmine_format["finished"] = new Date().toUTCString();
this.jasmine_format["results"] = this.suite_info;
return JSON.stringify(this.jasmine_format)
},

};

// Returns the status of suite
function status(current_status, status){
	if(status == "failed"){
		return "failed";
	}else{
		if(current_status != "failed"){
			return "passed"
		}
	}
}

// Remove empty or unused array slot
function remove(suite, position){
	suite.splice(position, 1);
	return suite;
}<|endoftext|>


<commit_before>/*
 *  Takes cities objects from libs/va.json file
 *  and converts them to the format needed for
 *  libs/cityReference.json, mainly adding a
 *  center object inside of the city
 *
 *  To create libs/cityReference, output of this
 *  file piped into libs/cityReference.json
 *
 *  node addCenter.js > libs/cityReference.json
 * */

var cities = require('./libs/va.json');

var newCities = []

/*cities.forEach(function(city){
  if(city.county_name) {
    var temp = {
      name: city.name,
      center: {
        latitude: parseFloat(city.primary_latitude),
        longitude: parseFloat(city.primary_longitude)
      }
    };

    newCities.push(temp);
  }
});
*/
newCities = cities.reduce(function(all, city) {
    if(city.county_name) {
      var temp = {
        name: city.name,
        center: {
          latitude: parseFloat(city.primary_latitude),
          longitude: parseFloat(city.primary_longitude)
        }
      };
      all.push(temp);
    }
    return all;
},[])

console.log(JSON.stringify(newCities, null, 2));
<commit_msg>deleted commented code<commit_after>/*
 *  Takes cities objects from libs/va.json file
 *  and converts them to the format needed for
 *  libs/cityReference.json, mainly adding a
 *  center object inside of the city
 *
 *  To create libs/cityReference, output of this
 *  file piped into libs/cityReference.json
 *
 *  node addCenter.js > libs/cityReference.json
 * */

var cities = require('./libs/va.json');

var newCities = []

newCities = cities.reduce(function(all, city) {
    if(city.county_name) {
      var temp = {
        name: city.name,
        center: {
          latitude: parseFloat(city.primary_latitude),
          longitude: parseFloat(city.primary_longitude)
        }
      };
      all.push(temp);
    }
    return all;
},[])

console.log(JSON.stringify(newCities, null, 2));
<|endoftext|>


<commit_before>'use strict';

module.exports = function(d3_select, d3_event, d3_mouse, d3_dispatch, axisannotation, plotMixin) { // Injected dependencies
  return function() { // Closure function
    var p = {},  // Container for private, direct access mixed in variables
        dispatch = d3_dispatch('enter', 'out', 'move'),
        xAnnotation = [],
        yAnnotation = [],
        verticalWireRange,
        horizontalWireRange,
        change = 0; // Track changes to this object, to know when to redraw

    function crosshair(g) {
      var group = g.selectAll('g.data.top').data([change], function(d) { return d; }),
          groupEnter = group.enter(),
          dataEnter = groupEnter.append('g').attr('class', 'data top').style('display', 'none');

      group.exit().remove();

      dataEnter.append('path').attr('class', 'horizontal wire');
      dataEnter.append('path').attr('class', 'vertical wire');

      appendAnnotation(dataEnter, d3_select, 'x', xAnnotation);
      appendAnnotation(dataEnter, d3_select, 'y', yAnnotation);

      g.selectAll('rect').data([0]).enter().append('rect').style({ fill: 'none', 'pointer-events': 'all' });

      crosshair.refresh(g);
    }

    crosshair.refresh = function(g) {
      var xRange = p.xScale.range(),
          yRange = p.yScale.range(),
          group = g.selectAll('g.data'),
          mouseSelection = g.selectAll('rect'),
          pathVerticalSelection = group.selectAll('path.vertical'),
          pathHorizontalSelection = group.selectAll('path.horizontal'),
          xAnnotationSelection = group.selectAll('g.axisannotation.x > g'),
          yAnnotationSelection = group.selectAll('g.axisannotation.y > g');

      mouseSelection.attr({
          x: Math.min(xRange[0], xRange[xRange.length-1]),
          y: Math.min(yRange[0], yRange[yRange.length-1]),
          height: Math.abs(yRange[yRange.length-1] - yRange[0]),
          width: Math.abs(xRange[xRange.length-1] - xRange[0])
        })
        .on('mouseenter', function() {
          display(g, 'inline');
          dispatch.enter();
        })
        .on('mouseout', function() {
          display(g, 'none');
          dispatch.out();
        })
        .on('mousemove', mousemoveRefresh(d3_select, d3_mouse, p, dispatch, xAnnotation, yAnnotation,
          pathVerticalSelection, pathHorizontalSelection, xAnnotationSelection, yAnnotationSelection,
          verticalWireRange, horizontalWireRange)
        );

      refresh(d3_select, p, xAnnotation, yAnnotation, pathVerticalSelection, pathHorizontalSelection,
        xAnnotationSelection, yAnnotationSelection, verticalWireRange, horizontalWireRange
      );
    };

    crosshair.xAnnotation = function(_) {
      if(!arguments.length) return xAnnotation;
      xAnnotation = _ instanceof Array ? _ : [_];
      change++; // Annotations have changed, increment to trigger a redraw
      return crosshair;
    };

    crosshair.yAnnotation = function(_) {
      if(!arguments.length) return yAnnotation;
      yAnnotation = _ instanceof Array ? _ : [_];
      change++; // Annotations have changed, increment to trigger a redraw
      return crosshair;
    };

    crosshair.verticalWireRange = function(_) {
      if(!arguments.length) return verticalWireRange;
      verticalWireRange = _;
      return crosshair;
    };

    crosshair.horizontalWireRange = function(_) {
      if(!arguments.length) return horizontalWireRange;
      horizontalWireRange = _;
      return crosshair;
    };

    // Mixin scale management and event listening
    plotMixin(crosshair, p)
      .xScale()
      .yScale()
      .on(dispatch);

    return crosshair;
  };
};

function display(g, style) {
  g.select('g.data.top').style('display', style);
}

function mousemoveRefresh(d3_select, d3_mouse, p, dispatch, xAnnotation, yAnnotation, pathVerticalSelection, pathHorizontalSelection,
                          xAnnotationSelection, yAnnotationSelection, verticalWireRange, horizontalWireRange) {
  var event = [new Array(xAnnotation.length), new Array(yAnnotation.length)];

  return function() {
    var coords = d3_mouse(this),
        x = p.xScale,
        y = p.yScale;

    refresh(d3_select, p, xAnnotation, yAnnotation,
      pathVerticalSelection.datum(x.invert(coords[0])),
      pathHorizontalSelection.datum(y.invert(coords[1])),
      xAnnotationSelection.each(updateAnnotationValue(xAnnotation, coords[0], event[0])),
      yAnnotationSelection.each(updateAnnotationValue(yAnnotation, coords[1], event[1])),
      verticalWireRange, horizontalWireRange
    );

    dispatch.move(event);
  };
}

function refresh(d3_select, p, xAnnotation, yAnnotation, xPath, yPath,
                 xAnnotationSelection, yAnnotationSelection,
                 verticalWireRange, horizontalWireRange) {
  var x = p.xScale,
      y = p.yScale;

  xPath.attr('d', verticalPathLine(x, verticalWireRange || y.range()));
  yPath.attr('d', horizontalPathLine(y, horizontalWireRange || x.range()));
  xAnnotationSelection.each(refreshAnnotation(d3_select, xAnnotation));
  yAnnotationSelection.each(refreshAnnotation(d3_select, yAnnotation));
}

function horizontalPathLine(y, range) {
  return function(d) {
    if(!d) return "M 0 0";
    var value = y(d);
    return ['M', range[0], value, 'L', range[range.length-1], value].join(' ');
  };
}

function verticalPathLine(x, range) {
  return function(d) {
    if(!d) return "M 0 0";
    var value = x(d);
    return ['M', value, range[0], 'L', value, range[range.length-1]].join(' ');
  };
}

function updateAnnotationValue(annotations, value, event) {
  return function(d, i) {
    event[i] = annotations[i].axis().scale().invert(value);
    // d[0] because only ever 1 value for crosshairs
    d[0].value = event[i];
  };
}

function appendAnnotation(selection, d3_select, clazz, annotation) {
  var annotationSelection = selection.append('g').attr('class', 'axisannotation ' + clazz)
    .selectAll('g').data(annotation.map(function() { return [{ value: null }]; }));

  annotationSelection.enter().append('g').attr('class', function(d, i) { return i; })
    .each(function(d, i) { annotation[i](d3_select(this)); });
}

function refreshAnnotation(d3_select, annotation) {
  return function(d, i) {
    annotation[i].refresh(d3_select(this));
  };
}<commit_msg>Cleaning up crosshair class layout<commit_after>'use strict';

module.exports = function(d3_select, d3_event, d3_mouse, d3_dispatch, axisannotation, plotMixin) { // Injected dependencies
  return function() { // Closure function
    var p = {},  // Container for private, direct access mixed in variables
        dispatch = d3_dispatch('enter', 'out', 'move'),
        xAnnotation = [],
        yAnnotation = [],
        verticalWireRange,
        horizontalWireRange,
        change = 0; // Track changes to this object, to know when to redraw

    function crosshair(g) {
      var group = g.selectAll('g.data.top').data([change], function(d) { return d; }),
          groupEnter = group.enter(),
          dataEnter = groupEnter.append('g').attr('class', 'data top').style('display', 'none');

      group.exit().remove();

      dataEnter.append('path').attr('class', 'horizontal wire');
      dataEnter.append('path').attr('class', 'vertical wire');

      appendAnnotation(dataEnter, 'x', xAnnotation);
      appendAnnotation(dataEnter, 'y', yAnnotation);

      g.selectAll('rect').data([0]).enter().append('rect').style({ fill: 'none', 'pointer-events': 'all' });

      crosshair.refresh(g);
    }

    crosshair.refresh = function(g) {
      var xRange = p.xScale.range(),
          yRange = p.yScale.range(),
          group = g.selectAll('g.data'),
          mouseSelection = g.selectAll('rect'),
          pathVerticalSelection = group.selectAll('path.vertical'),
          pathHorizontalSelection = group.selectAll('path.horizontal'),
          xAnnotationSelection = group.selectAll('g.axisannotation.x > g'),
          yAnnotationSelection = group.selectAll('g.axisannotation.y > g');

      mouseSelection.attr({
          x: Math.min(xRange[0], xRange[xRange.length-1]),
          y: Math.min(yRange[0], yRange[yRange.length-1]),
          height: Math.abs(yRange[yRange.length-1] - yRange[0]),
          width: Math.abs(xRange[xRange.length-1] - xRange[0])
        })
        .on('mouseenter', function() {
          display(g, 'inline');
          dispatch.enter();
        })
        .on('mouseout', function() {
          display(g, 'none');
          dispatch.out();
        })
        .on('mousemove', mousemoveRefresh(pathVerticalSelection, pathHorizontalSelection,
          xAnnotationSelection, yAnnotationSelection)
        );

      refresh(pathVerticalSelection, pathHorizontalSelection, xAnnotationSelection, yAnnotationSelection);
    };

    function mousemoveRefresh(pathVerticalSelection, pathHorizontalSelection,
                              xAnnotationSelection, yAnnotationSelection) {
      var event = [new Array(xAnnotation.length), new Array(yAnnotation.length)];

      return function() {
        var coords = d3_mouse(this);

        refresh(pathVerticalSelection.datum(p.xScale.invert(coords[0])),
          pathHorizontalSelection.datum(p.yScale.invert(coords[1])),
          xAnnotationSelection.each(updateAnnotationValue(xAnnotation, coords[0], event[0])),
          yAnnotationSelection.each(updateAnnotationValue(yAnnotation, coords[1], event[1]))
        );

        dispatch.move(event);
      };
    }

    function refresh(xPath, yPath, xAnnotationSelection, yAnnotationSelection) {
      var x = p.xScale,
          y = p.yScale;

      xPath.attr('d', verticalPathLine(x, verticalWireRange || y.range()));
      yPath.attr('d', horizontalPathLine(y, horizontalWireRange || x.range()));
      xAnnotationSelection.each(refreshAnnotation(xAnnotation));
      yAnnotationSelection.each(refreshAnnotation(yAnnotation));
    }

    crosshair.xAnnotation = function(_) {
      if(!arguments.length) return xAnnotation;
      xAnnotation = _ instanceof Array ? _ : [_];
      change++; // Annotations have changed, increment to trigger a redraw
      return crosshair;
    };

    crosshair.yAnnotation = function(_) {
      if(!arguments.length) return yAnnotation;
      yAnnotation = _ instanceof Array ? _ : [_];
      change++; // Annotations have changed, increment to trigger a redraw
      return crosshair;
    };

    crosshair.verticalWireRange = function(_) {
      if(!arguments.length) return verticalWireRange;
      verticalWireRange = _;
      return crosshair;
    };

    crosshair.horizontalWireRange = function(_) {
      if(!arguments.length) return horizontalWireRange;
      horizontalWireRange = _;
      return crosshair;
    };

    // Mixin scale management and event listening
    plotMixin(crosshair, p)
      .xScale()
      .yScale()
      .on(dispatch);

    return crosshair;
  };

  function appendAnnotation(selection, clazz, annotation) {
    var annotationSelection = selection.append('g').attr('class', 'axisannotation ' + clazz)
      .selectAll('g').data(annotation.map(function() { return [{ value: null }]; }));

    annotationSelection.enter().append('g').attr('class', function(d, i) { return i; })
      .each(function(d, i) { annotation[i](d3_select(this)); });
  }

  function refreshAnnotation(annotation) {
    return function(d, i) {
      annotation[i].refresh(d3_select(this));
    };
  }
};

function display(g, style) {
  g.select('g.data.top').style('display', style);
}

function horizontalPathLine(y, range) {
  return function(d) {
    if(!d) return "M 0 0";
    var value = y(d);
    return ['M', range[0], value, 'L', range[range.length-1], value].join(' ');
  };
}

function verticalPathLine(x, range) {
  return function(d) {
    if(!d) return "M 0 0";
    var value = x(d);
    return ['M', value, range[0], 'L', value, range[range.length-1]].join(' ');
  };
}

function updateAnnotationValue(annotations, value, event) {
  return function(d, i) {
    event[i] = annotations[i].axis().scale().invert(value);
    // d[0] because only ever 1 value for crosshairs
    d[0].value = event[i];
  };
}<|endoftext|>


<commit_before>eg.module("persist", ["jQuery", window, document], function($, global, doc) {
	/**
	* Support persist event in jQuery
	* @ko jQuery custom persist 이벤트 지원
	* @name jQuery#persist
	* @event
	* @param {Event} e event <ko>이벤트 객체</ko>
	* @param {Object} e.state state info to be restored <ko>복원되어야 하는 상태의 정보</ko>
	*
	* @support {"ie": "9+", "ch" : "latest", "ff" : "1.5+",  "sf" : "latest", "ios" : "7+", "an" : "2.2+ (except 3.x)", "n-ios" : "latest", "n-an" : "latest" }
	*
	* @example
	$(window).on("persist",function(e){
		// restore state
		if(e.state.flickingPage)
			oSlideFlicking.moveTo(e.state.flickingPage);
		if(e.state.scrollTop)
			document.scrollTo(e.state.scrollTop);
	});
	*/
	var wp = global.performance;
	var history = global.history;
	var location = global.location;
	var JSON = global.JSON;
	var CONST_PERSIST = "___persist___";
	var GLOBAL_KEY = "KEY" + CONST_PERSIST;
	var $global = $(global);
	var isPersisted = $global.attr(CONST_PERSIST) === true;

	// In case of IE8, TYPE_BACK_FORWARD is undefined.
	var isBackForwardNavigated = (wp && wp.navigation &&
									(wp.navigation.type === (wp.navigation.TYPE_BACK_FORWARD || 2)));
	var isSupportState = "replaceState" in history && "state" in history;
	var storage = (function() {
		if (!isSupportState) {
			if ("sessionStorage" in global) {
				var tmpKey = "__tmp__" + CONST_PERSIST;
				sessionStorage.setItem(tmpKey, CONST_PERSIST);
				return sessionStorage.getItem(tmpKey) === CONST_PERSIST ?
						sessionStorage :
						localStorage;
			} else {
				return localStorage;
			}
		}
	})();

	function onPageshow(e) {
		isPersisted = isPersisted || (e.originalEvent && e.originalEvent.persisted);
		if (!isPersisted && isBackForwardNavigated) {
			$global.trigger("persist");
		} else {
			reset();
		}
	}

	/*
	 * flush current history state
	 */
	function reset() {
		setState(null);
	}

	/*
	 * Getter for state
	 */
	function getState() {
		var stateStr;
		if (isSupportState) {
			stateStr = history.state;

			// If typeof stateStr is not a "string", it is not a valid state data for Persist module
			if (typeof stateStr === "string") {
				try {
					return JSON.parse(stateStr) || {};
				} catch (e) {}
			}
			return {};
		} else {
			stateStr = storage.getItem(location.href + CONST_PERSIST);

			// Note2 (4.3) return value is null
			return (stateStr && stateStr.length > 0) ? JSON.parse(stateStr) : {};
		}
	}
	function getStateByKey(key) {
		var result = getState()[key];

		// some device returns "null" or undefined
		if (result === "null" || typeof result === "undefined") {
			result = null;
		}
		return result;
	}

	/*
	 * Setter for state
	 */
	function setState(state) {
		if (isSupportState) {
			history.replaceState(JSON.stringify(state), doc.title, location.href);
		} else {
			if (state) {
				storage.setItem(location.href + CONST_PERSIST, JSON.stringify(state));
			} else {
				storage.removeItem(location.href  + CONST_PERSIST);
			}
		}
		state ? $global.attr(CONST_PERSIST, true) : $global.attr(CONST_PERSIST, null);
	}

	function setStateByKey(key, data) {
		var beforeData = getState();
		beforeData[key] = data;
		setState(beforeData);
	}
	/**
	* Saves state and returns current state.
	* @ko 인자로 넘긴 현재 상태정보를 저장한다.
	* @method jQuery.persist
    * @param {Object} state State object to be stored in order to restore UI component's state <ko>UI 컴포넌트의 상태를 복원하기위해 저장하려는 상태 객체</ko>
	* @example
	$("a").on("click",function(e){
		e.preventdefault();
		// save state
		$.persist(state);
	});
	*/
	/**
	* Saves state and returns current state.
	* @ko 인자로 넘긴 현재 상태정보를 반환한다.
	* @method jQuery.persist
	* @return {Object} state Stored state object <ko>복원을 위해 저장되어있는 상태 객체</ko>
	* @example
	$("a").on("click",function(e){
		e.preventdefault();
		// get state
		var state = $.persist();
	});
	*/
	/**
	* Saves state and returns current state.
	* @ko 인자로 넘긴 현재 상태정보를 저장한다.
	* @method jQuery.persist
    * @param {String} key State key to be stored in order to restore UI component's state <ko>UI 컴포넌트의 상태를 복원하기위해 저장하려는 상태 객체의 키</ko>
    * @param {String} state State object to be stored in order to restore UI component's state <ko>UI 컴포넌트의 상태를 복원하기위해 저장하려는 상태 객체</ko>
	* @return {Object} state Stored state object <ko>복원을 위해 저장되어있는 상태 객체</ko>
	* @example
	$("a").on("click",function(e){
		e.preventdefault();
		// save state
		$.persist("KEY",state);
	});
	*/
	/**
	* Saves state and returns current state.
	* @ko 인자로 넘긴 현재 상태정보를 반환한다.
	* @method jQuery.persist
	* @param {String} key State key to be stored in order to restore UI component's state <ko>UI 컴포넌트의 상태를 복원하기위해 저장하려는 상태 객체의 키</ko>
	* @return {Object} state Stored state object <ko>복원을 위해 저장되어있는 상태 객체</ko>
	* @example
	$("a").on("click",function(e){
		e.preventdefault();
		// get state
		var state = $.persist("KEY");
	});
	*/
	$.persist = function(state) {
		var key;
		var data;
		if (typeof state === "string") {
			key = state;
			data = arguments.length === 2 ? arguments[1] : null;
		} else {
			key = GLOBAL_KEY;
			data = arguments.length === 1 ? state : null;
		}
		data && setStateByKey(key, data);
		return getStateByKey(key);
	};

	// in case of reload
	!isBackForwardNavigated && reset();

	$.event.special.persist = {
		setup: function() {
			$global.on("pageshow", onPageshow);
		},
		teardown: function() {
			$global.off("pageshow", onPageshow);
		},
		trigger: function(e) {

			//If you use 'persist' event, you can get global-key only!
			e.state = getStateByKey(GLOBAL_KEY);
		}
	};
	return {
		"isBackForwardNavigated": isBackForwardNavigated,
		"onPageshow": onPageshow,
		"reset": reset,
		"getState": getState,
		"setState": setState,
		"persist": $.persist,
		"GLOBALKEY": GLOBAL_KEY
	};
});<commit_msg>fix(persist): more strictly filter history.state in getState<commit_after>eg.module("persist", ["jQuery", window, document], function($, global, doc) {
	/**
	* Support persist event in jQuery
	* @ko jQuery custom persist 이벤트 지원
	* @name jQuery#persist
	* @event
	* @param {Event} e event <ko>이벤트 객체</ko>
	* @param {Object} e.state state info to be restored <ko>복원되어야 하는 상태의 정보</ko>
	*
	* @support {"ie": "9+", "ch" : "latest", "ff" : "1.5+",  "sf" : "latest", "ios" : "7+", "an" : "2.2+ (except 3.x)", "n-ios" : "latest", "n-an" : "latest" }
	*
	* @example
	$(window).on("persist",function(e){
		// restore state
		if(e.state.flickingPage)
			oSlideFlicking.moveTo(e.state.flickingPage);
		if(e.state.scrollTop)
			document.scrollTo(e.state.scrollTop);
	});
	*/
	var wp = global.performance;
	var history = global.history;
	var location = global.location;
	var JSON = global.JSON;
	var CONST_PERSIST = "___persist___";
	var GLOBAL_KEY = "KEY" + CONST_PERSIST;
	var $global = $(global);
	var isPersisted = $global.attr(CONST_PERSIST) === true;

	// In case of IE8, TYPE_BACK_FORWARD is undefined.
	var isBackForwardNavigated = (wp && wp.navigation &&
									(wp.navigation.type === (wp.navigation.TYPE_BACK_FORWARD || 2)));
	var isSupportState = "replaceState" in history && "state" in history;
	var storage = (function() {
		if (!isSupportState) {
			if ("sessionStorage" in global) {
				var tmpKey = "__tmp__" + CONST_PERSIST;
				sessionStorage.setItem(tmpKey, CONST_PERSIST);
				return sessionStorage.getItem(tmpKey) === CONST_PERSIST ?
						sessionStorage :
						localStorage;
			} else {
				return localStorage;
			}
		}
	})();

	function onPageshow(e) {
		isPersisted = isPersisted || (e.originalEvent && e.originalEvent.persisted);
		if (!isPersisted && isBackForwardNavigated) {
			$global.trigger("persist");
		} else {
			reset();
		}
	}

	/*
	 * flush current history state
	 */
	function reset() {
		setState(null);
	}

	/*
	 * Getter for state
	 */
	function getState() {
		var stateStr;
		var state = {};
		if (isSupportState) {
			stateStr = history.state;

			// "string", "null" is not a valid
			if (typeof stateStr === "string" && stateStr !== "null") {
				try {
					state = JSON.parse(stateStr);

					// like '[ ... ]', '1', '1.234', '"123"' is also not valid
					if (typeof state !== "object" || state instanceof Array) {
						throw new Error("Window.history is not valid form for persist.");
					}
				} catch (e) {
					/* jshint ignore:start */
					console.warn(e.message);
					/* jshint ignore:end */
				}
			}
			return state;
		} else {
			stateStr = storage.getItem(location.href + CONST_PERSIST);

			// Note2 (4.3) return value is null
			return (stateStr && stateStr.length > 0) ? JSON.parse(stateStr) : {};
		}
	}
	function getStateByKey(key) {
		var result = getState()[key];

		// some device returns "null" or undefined
		if (result === "null" || typeof result === "undefined") {
			result = null;
		}
		return result;
	}

	/*
	 * Setter for state
	 */
	function setState(state) {
		if (isSupportState) {
			history.replaceState(JSON.stringify(state), doc.title, location.href);
		} else {
			if (state) {
				storage.setItem(location.href + CONST_PERSIST, JSON.stringify(state));
			} else {
				storage.removeItem(location.href  + CONST_PERSIST);
			}
		}
		state ? $global.attr(CONST_PERSIST, true) : $global.attr(CONST_PERSIST, null);
	}

	function setStateByKey(key, data) {
		var beforeData = getState();
		beforeData[key] = data;
		setState(beforeData);
	}
	/**
	* Saves state and returns current state.
	* @ko 인자로 넘긴 현재 상태정보를 저장한다.
	* @method jQuery.persist
    * @param {Object} state State object to be stored in order to restore UI component's state <ko>UI 컴포넌트의 상태를 복원하기위해 저장하려는 상태 객체</ko>
	* @example
	$("a").on("click",function(e){
		e.preventdefault();
		// save state
		$.persist(state);
	});
	*/
	/**
	* Saves state and returns current state.
	* @ko 인자로 넘긴 현재 상태정보를 반환한다.
	* @method jQuery.persist
	* @return {Object} state Stored state object <ko>복원을 위해 저장되어있는 상태 객체</ko>
	* @example
	$("a").on("click",function(e){
		e.preventdefault();
		// get state
		var state = $.persist();
	});
	*/
	/**
	* Saves state and returns current state.
	* @ko 인자로 넘긴 현재 상태정보를 저장한다.
	* @method jQuery.persist
    * @param {String} key State key to be stored in order to restore UI component's state <ko>UI 컴포넌트의 상태를 복원하기위해 저장하려는 상태 객체의 키</ko>
    * @param {String} state State object to be stored in order to restore UI component's state <ko>UI 컴포넌트의 상태를 복원하기위해 저장하려는 상태 객체</ko>
	* @return {Object} state Stored state object <ko>복원을 위해 저장되어있는 상태 객체</ko>
	* @example
	$("a").on("click",function(e){
		e.preventdefault();
		// save state
		$.persist("KEY",state);
	});
	*/
	/**
	* Saves state and returns current state.
	* @ko 인자로 넘긴 현재 상태정보를 반환한다.
	* @method jQuery.persist
	* @param {String} key State key to be stored in order to restore UI component's state <ko>UI 컴포넌트의 상태를 복원하기위해 저장하려는 상태 객체의 키</ko>
	* @return {Object} state Stored state object <ko>복원을 위해 저장되어있는 상태 객체</ko>
	* @example
	$("a").on("click",function(e){
		e.preventdefault();
		// get state
		var state = $.persist("KEY");
	});
	*/
	$.persist = function(state) {
		var key;
		var data;
		if (typeof state === "string") {
			key = state;
			data = arguments.length === 2 ? arguments[1] : null;
		} else {
			key = GLOBAL_KEY;
			data = arguments.length === 1 ? state : null;
		}
		data && setStateByKey(key, data);
		return getStateByKey(key);
	};

	// in case of reload
	!isBackForwardNavigated && reset();

	$.event.special.persist = {
		setup: function() {
			$global.on("pageshow", onPageshow);
		},
		teardown: function() {
			$global.off("pageshow", onPageshow);
		},
		trigger: function(e) {

			//If you use 'persist' event, you can get global-key only!
			e.state = getStateByKey(GLOBAL_KEY);
		}
	};
	return {
		"isBackForwardNavigated": isBackForwardNavigated,
		"onPageshow": onPageshow,
		"reset": reset,
		"getState": getState,
		"setState": setState,
		"persist": $.persist,
		"GLOBALKEY": GLOBAL_KEY
	};
});<|endoftext|>


<commit_before>var
  Promise = require('bluebird'),
  _kuzzle;

/**
 *
 * @param kuzzle
 * @param engine {InternalEngine}
 * @constructor
 */
function InternalEngineBootstrap (kuzzle, engine) {
  _kuzzle = kuzzle;
  this.engine = engine || _kuzzle.internalEngine;
}

/**
 * Bootstraps Kuzzle storage engine
 * Creates the internal index and collections if needed
 *
 * @returns {Promise.<T>}
 */
InternalEngineBootstrap.prototype.all = function internalEngineBootstrapAll () {
  return this.engine.createInternalIndex()
    .then(() => this.createCollections())
    .then(() => this.engine.refresh())
    .then(() => Promise.resolve(_kuzzle.indexCache.add(this.engine.index)))
    .catch(error => {
      // plugin manager is not initialized yet, cannot use the logger
      console.error(error, error.stack);  // eslint-disable-line no-console
      throw error;
    });
};

InternalEngineBootstrap.prototype.createCollections = function internalEngineBootstrapCreateCollections () {
  return this.createPluginsCollection()
    .then(() => this.createRolesCollection())
    .then(() => this.createProfilesCollection())
    .then(() => this.createUsersCollection())
    .then(() => this.createValidationCollection(_kuzzle.config.validation));
};

InternalEngineBootstrap.prototype.createRolesCollection = function internalEngineBootstrapCreateRolesCollection () {
  if (_kuzzle.indexCache.exists(this.engine.index, 'roles')) {
    return Promise.resolve();
  }

  return this.engine.updateMapping('roles', {
    properties: {
      controllers: {enabled: false}
    }
  })
    .then(() => {
      var promises = ['anonymous', 'default', 'admin'].map(roleId => {
        return this.engine.createOrReplace('roles', roleId, _kuzzle.config.security.default.role);
      });

      _kuzzle.indexCache.add(this.engine.index, 'roles');

      return Promise.all(promises);
    });
};

InternalEngineBootstrap.prototype.createPluginsCollection = function internalEngineBootstrapCreatePluginsCollection () {
  if (_kuzzle.indexCache.exists(this.engine.index, 'plugins')) {
    return Promise.resolve();
  }

  return this.engine.updateMapping('plugins', {
    properties: {
      config: {enabled: false}
    }
  });
};

InternalEngineBootstrap.prototype.createProfilesCollection = function internalEngineBootstrapCreateProfilesCollection () {
  if (_kuzzle.indexCache.exists(this.engine.index, 'profiles')) {
    return Promise.resolve();
  }

  return this.engine.updateMapping('profiles', {
    properties: {
      policies: {
        properties: {
          _id: {
            index: 'not_analyzed',
            type: 'string'
          }
        }
      }
    }
  })
    .then(() => {
      var promises;

      _kuzzle.indexCache.add(this.engine.index, 'profiles');

      promises = ['default', 'anonymous', 'admin'].map(profileId => {
        return this.engine.createOrReplace('profiles', profileId, {
          policies: [{roleId: profileId, allowInternalIndex: true}]
        });
      });

      return Promise.all(promises);
    });
};

InternalEngineBootstrap.prototype.createUsersCollection = function internalEngineBootstrapCreateUsersCollection () {
  if (_kuzzle.indexCache.exists(this.engine.index, 'users')) {
    return Promise.resolve();
  }

  return this.engine.updateMapping('users', {
    properties: {
      profileIds: {
        index: 'not_analyzed',
        type: 'string'
      },
      password: {
        index: 'no',
        type: 'string'
      }
    }
  })
    .then(() => {
      _kuzzle.indexCache.add(this.engine.index, 'users');
    });
};

InternalEngineBootstrap.prototype.createValidationCollection = function internalEngineBootstrapCreateValidationCollection (validationConfiguration) {
  if (_kuzzle.indexCache.exists(this.engine.index, 'validations')) {
    return Promise.resolve();
  }

  _kuzzle.pluginsManager.trigger('log:info', '== Creating validation collection...');

  return this.engine.updateMapping('validations', {
    properties: {
      index: {
        index: 'not_analyzed',
        type: 'string'
      },
      collection: {
        index: 'not_analyzed',
        type: 'string'
      },
      validation: {
        enabled: false
      }
    }
  }).then(() => {
    var promises = [];
    if (validationConfiguration) {
      Object.keys(validationConfiguration).forEach(indexName => {
        Object.keys(validationConfiguration[indexName]).forEach(collectionName => {
          // createOrReplace instead of create to avoid mess on concurency
          // TODO fix with a lock instead
          promises.push(_kuzzle.internalEngine.createOrReplace('validations', `${indexName}#${collectionName}`, {
            index: indexName,
            collection: collectionName,
            validation: validationConfiguration[indexName][collectionName]
          }));
        });
      });

      return Promise.all(promises);
    }

    return Promise.resolve();
  })
    .then(() => {
      _kuzzle.indexCache.add(this.engine.index, 'validations');
    });
};

InternalEngineBootstrap.prototype.adminExists = function internalEngineBootstrapAdminExists () {
  return this.engine.search('users', {query: {terms: {profileIds: ['admin']}}}, 0, 0)
    .then(response => (response.hits.total > 0));
};

module.exports = InternalEngineBootstrap;
<commit_msg>correction of a problem on adminExists<commit_after>var
  Promise = require('bluebird'),
  _kuzzle;

/**
 *
 * @param kuzzle
 * @param engine {InternalEngine}
 * @constructor
 */
function InternalEngineBootstrap (kuzzle, engine) {
  _kuzzle = kuzzle;
  this.engine = engine || _kuzzle.internalEngine;
}

/**
 * Bootstraps Kuzzle storage engine
 * Creates the internal index and collections if needed
 *
 * @returns {Promise.<T>}
 */
InternalEngineBootstrap.prototype.all = function internalEngineBootstrapAll () {
  return this.engine.createInternalIndex()
    .then(() => this.createCollections())
    .then(() => this.engine.refresh())
    .then(() => Promise.resolve(_kuzzle.indexCache.add(this.engine.index)))
    .catch(error => {
      // plugin manager is not initialized yet, cannot use the logger
      console.error(error, error.stack);  // eslint-disable-line no-console
      throw error;
    });
};

InternalEngineBootstrap.prototype.createCollections = function internalEngineBootstrapCreateCollections () {
  return this.createPluginsCollection()
    .then(() => this.createRolesCollection())
    .then(() => this.createProfilesCollection())
    .then(() => this.createUsersCollection())
    .then(() => this.createValidationCollection(_kuzzle.config.validation));
};

InternalEngineBootstrap.prototype.createRolesCollection = function internalEngineBootstrapCreateRolesCollection () {
  if (_kuzzle.indexCache.exists(this.engine.index, 'roles')) {
    return Promise.resolve();
  }

  return this.engine.updateMapping('roles', {
    properties: {
      controllers: {enabled: false}
    }
  })
    .then(() => {
      var promises = ['anonymous', 'default', 'admin'].map(roleId => {
        return this.engine.createOrReplace('roles', roleId, _kuzzle.config.security.default.role);
      });

      _kuzzle.indexCache.add(this.engine.index, 'roles');

      return Promise.all(promises);
    });
};

InternalEngineBootstrap.prototype.createPluginsCollection = function internalEngineBootstrapCreatePluginsCollection () {
  if (_kuzzle.indexCache.exists(this.engine.index, 'plugins')) {
    return Promise.resolve();
  }

  return this.engine.updateMapping('plugins', {
    properties: {
      config: {enabled: false}
    }
  });
};

InternalEngineBootstrap.prototype.createProfilesCollection = function internalEngineBootstrapCreateProfilesCollection () {
  if (_kuzzle.indexCache.exists(this.engine.index, 'profiles')) {
    return Promise.resolve();
  }

  return this.engine.updateMapping('profiles', {
    properties: {
      policies: {
        properties: {
          _id: {
            index: 'not_analyzed',
            type: 'string'
          }
        }
      }
    }
  })
    .then(() => {
      var promises;

      _kuzzle.indexCache.add(this.engine.index, 'profiles');

      promises = ['default', 'anonymous', 'admin'].map(profileId => {
        return this.engine.createOrReplace('profiles', profileId, {
          policies: [{roleId: profileId, allowInternalIndex: true}]
        });
      });

      return Promise.all(promises);
    });
};

InternalEngineBootstrap.prototype.createUsersCollection = function internalEngineBootstrapCreateUsersCollection () {
  if (_kuzzle.indexCache.exists(this.engine.index, 'users')) {
    return Promise.resolve();
  }

  return this.engine.updateMapping('users', {
    properties: {
      profileIds: {
        index: 'not_analyzed',
        type: 'string'
      },
      password: {
        index: 'no',
        type: 'string'
      }
    }
  })
    .then(() => {
      _kuzzle.indexCache.add(this.engine.index, 'users');
    });
};

InternalEngineBootstrap.prototype.createValidationCollection = function internalEngineBootstrapCreateValidationCollection (validationConfiguration) {
  if (_kuzzle.indexCache.exists(this.engine.index, 'validations')) {
    return Promise.resolve();
  }

  _kuzzle.pluginsManager.trigger('log:info', '== Creating validation collection...');

  return this.engine.updateMapping('validations', {
    properties: {
      index: {
        index: 'not_analyzed',
        type: 'string'
      },
      collection: {
        index: 'not_analyzed',
        type: 'string'
      },
      validation: {
        enabled: false
      }
    }
  }).then(() => {
    var promises = [];
    if (validationConfiguration) {
      Object.keys(validationConfiguration).forEach(indexName => {
        Object.keys(validationConfiguration[indexName]).forEach(collectionName => {
          // createOrReplace instead of create to avoid mess on concurency
          // TODO fix with a lock instead
          promises.push(_kuzzle.internalEngine.createOrReplace('validations', `${indexName}#${collectionName}`, {
            index: indexName,
            collection: collectionName,
            validation: validationConfiguration[indexName][collectionName]
          }));
        });
      });

      return Promise.all(promises);
    }

    return Promise.resolve();
  })
    .then(() => {
      _kuzzle.indexCache.add(this.engine.index, 'validations');
    });
};

InternalEngineBootstrap.prototype.adminExists = function internalEngineBootstrapAdminExists () {
  return this.engine.search('users', {query: {terms: {profileIds: ['admin']}}}, 0, 0)
    .then(response => (response.total > 0));
};

module.exports = InternalEngineBootstrap;
<|endoftext|>


<commit_before>const fixedPath = location.href.replace('/-/', '/#/')
if (fixedPath != location.href) {
  location.href = fixedPath
}

function install (hook, vm) {
  const dom = Docsify.dom
  const disqus = vm.config.disqus
  if (!disqus) {
    throw Error('$docsify.disqus is required')
  }

  hook.init(_ => {
    const script = dom.create('script')

    script.async = true
    script.src = `https://${disqus}.disqus.com/embed.js`
    script.setAttribute('data-timestamp', +new Date())
    dom.appendTo(dom.body, script)
  })

  hook.mounted(_ => {
    const div = dom.create('div')
    div.id = 'disqus_thread'
    const main = dom.getNode('#main')
    div.style = `width: ${main.clientWidth}px; margin: 0 auto 20px;`
    dom.appendTo(dom.find('.content'), div)

    // eslint-disable-next-line
    window.disqus_config = function() {
      this.page.url = location.origin + '/-' + vm.route.path
      this.page.identifier = vm.route.path
      this.page.title = document.title
    }
  })

  hook.doneEach(_ => {
    if (typeof window.DISQUS !== 'undefined') {
      window.DISQUS.reset({
        reload: true,
        config: function () {
          this.page.url = location.origin + '/-' + vm.route.path
          this.page.identifier = vm.route.path
          this.page.title = document.title
        }
      })
    }
  })
}

$docsify.plugins = [].concat(install, $docsify.plugins)
<commit_msg>chore: tweaks code<commit_after>const fixedPath = location.href.replace('/-/', '/#/')
if (fixedPath !== location.href) {
  location.href = fixedPath
}

function install (hook, vm) {
  const dom = Docsify.dom
  const disqus = vm.config.disqus
  if (!disqus) {
    throw Error('$docsify.disqus is required')
  }

  hook.init(_ => {
    const script = dom.create('script')

    script.async = true
    script.src = `https://${disqus}.disqus.com/embed.js`
    script.setAttribute('data-timestamp', +new Date())
    dom.appendTo(dom.body, script)
  })

  hook.mounted(_ => {
    const div = dom.create('div')
    div.id = 'disqus_thread'
    const main = dom.getNode('#main')
    div.style = `width: ${main.clientWidth}px; margin: 0 auto 20px;`
    dom.appendTo(dom.find('.content'), div)

    // eslint-disable-next-line
    window.disqus_config = function() {
      this.page.url = location.origin + '/-' + vm.route.path
      this.page.identifier = vm.route.path
      this.page.title = document.title
    }
  })

  hook.doneEach(_ => {
    if (typeof window.DISQUS !== 'undefined') {
      window.DISQUS.reset({
        reload: true,
        config: function () {
          this.page.url = location.origin + '/-' + vm.route.path
          this.page.identifier = vm.route.path
          this.page.title = document.title
        }
      })
    }
  })
}

$docsify.plugins = [].concat(install, $docsify.plugins)
<|endoftext|>


<commit_before>'use strict';

require('buffer-v6-polyfill');

const vow = require('vow');
const vowFs = require('vow-fs');
const Vinyl = require('vinyl');
const Readable = require('stream').Readable;
const inherits = require('util').inherits;

function SrcLoader(paths, options) {
    if (!(this instanceof SrcLoader)) {
        return new SrcLoader(paths, options);
    }

    Readable.call(this, options);

    this.__paths = [].concat(paths || []);
}

inherits(SrcLoader, Readable);

SrcLoader.obj = function(paths, options) {
    options = options || {};
    options.objectMode = true;

    return new SrcLoader(paths, options);
};

SrcLoader.prototype._read = function () {
    vow.all(this.__paths.map(file => vowFs
            .read(file.fullname, 'utf8')
            .then(content => new Vinyl({
                  path: file.fullname,
                  contents: Buffer.from(content)
            }))
        ))
        .then(
            vinyls => {
                vinyls.forEach(file => { this.push(file); });
                this.push(null);
            },
            err => { process.nextTick(() => this.emit('error', err)); });
};

module.exports = SrcLoader;
<commit_msg>use readable-stream<commit_after>'use strict';

require('buffer-v6-polyfill');

const vow = require('vow');
const vowFs = require('vow-fs');
const Vinyl = require('vinyl');
const Readable = require('readable-stream').Readable;
const inherits = require('util').inherits;

function SrcLoader(paths, options) {
    if (!(this instanceof SrcLoader)) {
        return new SrcLoader(paths, options);
    }

    Readable.call(this, options);

    this.__paths = [].concat(paths || []);
}

inherits(SrcLoader, Readable);

SrcLoader.obj = function(paths, options) {
    options = options || {};
    options.objectMode = true;

    return new SrcLoader(paths, options);
};

SrcLoader.prototype._read = function () {
    vow.all(this.__paths.map(file => vowFs
            .read(file.fullname, 'utf8')
            .then(content => new Vinyl({
                  path: file.fullname,
                  contents: Buffer.from(content)
            }))
        ))
        .then(
            vinyls => {
                vinyls.forEach(file => { this.push(file); });
                this.push(null);
            },
            err => { process.nextTick(() => this.emit('error', err)); });
};

module.exports = SrcLoader;
<|endoftext|>


<commit_before>var _ = require('underscore'),
    seq = require('seq'),
    Canvas = require('canvas'),
    error = require('../error'),
    assets = require('../assets'),
    relations = require('../relations');

function calculateSpritePadding(paddingStr) {
    if (paddingStr) {
        // Strip units ('px' assumed)
        var tokens = [];
        paddingStr.split(/\s+/).forEach(function (token) {
            var num = parseInt(token.replace(/[a-z]+$/, ''), 10);
            if (!isNaN(num)) {
                tokens.push(num);
            }
        });
        if (tokens.length === 4) {
            return tokens;
        } else if (tokens.length === 3) {
            return [tokens[0], tokens[1], tokens[2], tokens[1]]; // T, L+R, B
        } else if (tokens.length === 2) {
            return [tokens[0], tokens[1], tokens[0], tokens[1]]; // T+B, L+R
        } else if (tokens.length === 1) {
            return [tokens[0], tokens[0], tokens[0], tokens[0]];
        }
    }
    return [0, 0, 0, 0];
}

module.exports = function () {
    return function spriteBackgroundImages(err, assetGraph, cb) {
        if (err) {
            throw err;
        }
        var spriteGroups = {};
        assetGraph.findRelations({type: 'CSSImage'}).forEach(function (relation) {
            var spriteInfo = assets.CSS.extractInfoFromRule(relation.cssRule, assets.CSS.vendorPrefix + '-sprite-'),
                asset = relation.to;
            if (spriteInfo.group) {
                var spriteGroup = spriteGroups[spriteInfo.group];
                if (!spriteGroup) {
                    spriteGroup = spriteGroups[spriteInfo.group] = {
                        imageInfosById: {}
                    };
                }
                var imageInfo = spriteGroup[asset.id],
                    padding = calculateSpritePadding(spriteInfo.padding);
                if (!imageInfo) {
                    imageInfo = spriteGroup.imageInfosById[asset.id] = {
                        padding: padding,
                        asset: asset,
                        incomingRelations: [relation]
                    };
                } else {
                    imageInfo.incomingRelations.push(relation);
                    for (var i = 0 ; i < 4 ; i += 1) {
                        imageInfo.padding[i] = Math.max(padding[i], imageInfo.padding[i]);
                    }
                }
            }
        });

        // Find the sprite configurations (if any):
        assetGraph.findRelations({type: 'CSSSpritePlaceholder'}).forEach(function (cssSpritePlaceholder) {
            // TODO: Emit a warning if the sprite configuration selector won't be reachable
            var spriteGroupName = cssSpritePlaceholder.to.parseTree.selectorForGroup; // Eeh
            if (spriteGroupName in spriteGroups) {
                spriteGroups[spriteGroupName].cssSpritePlaceholder = cssSpritePlaceholder;
            }
        });

        if (!_.keys(spriteGroups).length) {
            return cb();
        }

        seq.ap(_.keys(spriteGroups)).
            seqEach(function (spriteGroupName) {
                var callback = this,
                    spriteGroup = spriteGroups[spriteGroupName],
                    imageInfos = _.values(spriteGroup.imageInfosById),
                    spriteInfo = spriteGroup.cssSpritePlaceholder ? spriteGroup.cssSpritePlaceholder.to.parseTree : {};

                seq.ap(imageInfos).
                    parMap(function (imageInfo) {
                        imageInfo.asset.getCanvasImage(this);
                    }).
                    seqEach(function (canvasImage, i) {
                        _.extend(imageInfos[i], {
                            canvasImage: canvasImage,
                            width: canvasImage.width,
                            height: canvasImage.height
                        });
                        process.nextTick(this);
                    }).
                    seq(function () {
                        var packerName = {
                            'jim-scott': 'jimScott',
                            horizontal: 'horizontal',
                            vertical: 'vertical'
                        }[spriteInfo.packer] || 'tryAll';
                        var packingData = require('./spriteBackgroundImages/packers/' + packerName).pack(imageInfos),
                            canvas = new Canvas(packingData.width, packingData.height),
                            ctx = canvas.getContext('2d');
                        imageInfos = packingData.imageInfos;
                        if ('backgroundColor' in spriteInfo) {
                            ctx.fillStyle = spriteInfo.imageBackgroundColor;
                            ctx.fillRect(0, 0, canvas.width, canvas.height);
                        }
                        imageInfos.forEach(function (imageInfo) {
                            ctx.drawImage(imageInfo.canvasImage, imageInfo.x, imageInfo.y, imageInfo.width, imageInfo.height);
                        });
                        canvas.toBuffer(this);
                    }).
                    seq(function (spriteBuffer) {
                        var spriteAsset = new assets.PNG({
                            rawSrc: spriteBuffer
                        });
                        spriteAsset.url = assetGraph.resolver.root + spriteAsset.id + '.' + spriteAsset.defaultExtension; // FIXME
                        assetGraph.addAsset(spriteAsset);
                        if (spriteGroup.cssSpritePlaceholder) {
                            var cssRule = spriteGroup.cssSpritePlaceholder.cssRule;
                            cssRule.style.setProperty('background-image', 'url(...)',
                                                      spriteGroup.cssSpritePlaceholder.to.parseTree.important && 'important');
                            assetGraph.addRelation(new relations.CSSImage({
                                cssRule: cssRule,
                                propertyName: 'background-image',
                                from: spriteGroup.cssSpritePlaceholder.from,
                                to: spriteAsset
                            }), 'before', spriteGroup.cssSpritePlaceholder);
                            assetGraph.detachAndRemoveRelation(spriteGroup.cssSpritePlaceholder);
                            assetGraph.removeAsset(spriteGroup.cssSpritePlaceholder.to);
                        }
                        imageInfos.forEach(function (imageInfo) {
                            imageInfo.incomingRelations.forEach(function (incomingRelation) {
                                assetGraph.markAssetDirty(incomingRelation.from);
                                var relationSpriteInfo = assets.CSS.extractInfoFromRule(incomingRelation.cssRule, assets.CSS.vendorPrefix + '-sprite-');
                                incomingRelation.cssRule.style.setProperty('background-position',
                                                                           (imageInfo.x ? (-imageInfo.x) + "px " : "0 ") +
                                                                           (imageInfo.y ? -imageInfo.y + "px" : "0"),
                                                                           relationSpriteInfo.important && 'important');
                                ['group', 'padding', 'no-group-selector', 'important'].forEach(function (propertyName) {
                                    incomingRelation.cssRule.style.removeProperty(assets.CSS.vendorPrefix + '-sprite-' + propertyName);
                                }, this);
                                if (relationSpriteInfo.noGroupSelector) {
                                    // The user specified that this selector needs its own background-image/background
                                    // property pointing at the sprite rather than relying on the HTML elements also being
                                    // matched by the sprite group's "main" selector, which would have been preferable.
                                    assetGraph.addRelation(new relations.CSSImage({
                                        cssRule: incomingRelation.cssRule,
                                        propertyName: incomingRelation.propertyName,
                                        from: incomingRelation.from,
                                        to: spriteAsset
                                    }), 'before', incomingRelation);
                                    assetGraph.removeRelation(incomingRelation);
                                } else {
                                    assetGraph.detachAndRemoveRelation(incomingRelation);
                                }

                                // Remove the original image if it has become an orphan:
                                if (!assetGraph.findRelations({to: incomingRelation.to}).length) {
                                    assetGraph.removeAsset(incomingRelation.to);
                                }
                            });
                        });
                        callback();
                    })
                    ['catch'](callback);
            }).
            seq(function () {
                cb();
            })
            ['catch'](cb);
    };
};
<commit_msg>transforms.spriteBackgroundImages: Consistent seq() usage and indentation.<commit_after>var _ = require('underscore'),
    seq = require('seq'),
    Canvas = require('canvas'),
    error = require('../error'),
    assets = require('../assets'),
    relations = require('../relations');

function calculateSpritePadding(paddingStr) {
    if (paddingStr) {
        // Strip units ('px' assumed)
        var tokens = [];
        paddingStr.split(/\s+/).forEach(function (token) {
            var num = parseInt(token.replace(/[a-z]+$/, ''), 10);
            if (!isNaN(num)) {
                tokens.push(num);
            }
        });
        if (tokens.length === 4) {
            return tokens;
        } else if (tokens.length === 3) {
            return [tokens[0], tokens[1], tokens[2], tokens[1]]; // T, L+R, B
        } else if (tokens.length === 2) {
            return [tokens[0], tokens[1], tokens[0], tokens[1]]; // T+B, L+R
        } else if (tokens.length === 1) {
            return [tokens[0], tokens[0], tokens[0], tokens[0]];
        }
    }
    return [0, 0, 0, 0];
}

module.exports = function () {
    return function spriteBackgroundImages(err, assetGraph, cb) {
        if (err) {
            throw err;
        }
        var spriteGroups = {};
        assetGraph.findRelations({type: 'CSSImage'}).forEach(function (relation) {
            var spriteInfo = assets.CSS.extractInfoFromRule(relation.cssRule, assets.CSS.vendorPrefix + '-sprite-'),
                asset = relation.to;
            if (spriteInfo.group) {
                var spriteGroup = spriteGroups[spriteInfo.group];
                if (!spriteGroup) {
                    spriteGroup = spriteGroups[spriteInfo.group] = {
                        imageInfosById: {}
                    };
                }
                var imageInfo = spriteGroup[asset.id],
                    padding = calculateSpritePadding(spriteInfo.padding);
                if (!imageInfo) {
                    imageInfo = spriteGroup.imageInfosById[asset.id] = {
                        padding: padding,
                        asset: asset,
                        incomingRelations: [relation]
                    };
                } else {
                    imageInfo.incomingRelations.push(relation);
                    for (var i = 0 ; i < 4 ; i += 1) {
                        imageInfo.padding[i] = Math.max(padding[i], imageInfo.padding[i]);
                    }
                }
            }
        });

        // Find the sprite configurations (if any):
        assetGraph.findRelations({type: 'CSSSpritePlaceholder'}).forEach(function (cssSpritePlaceholder) {
            // TODO: Emit a warning if the sprite configuration selector won't be reachable
            var spriteGroupName = cssSpritePlaceholder.to.parseTree.selectorForGroup; // Eeh
            if (spriteGroupName in spriteGroups) {
                spriteGroups[spriteGroupName].cssSpritePlaceholder = cssSpritePlaceholder;
            }
        });

        if (!_.keys(spriteGroups).length) {
            return cb();
        }

        seq()
            .extend(_.keys(spriteGroups))
            .seqEach(function (spriteGroupName) {
                var callback = this,
                    spriteGroup = spriteGroups[spriteGroupName],
                    imageInfos = _.values(spriteGroup.imageInfosById),
                    spriteInfo = spriteGroup.cssSpritePlaceholder ? spriteGroup.cssSpritePlaceholder.to.parseTree : {};

                seq()
                    .extend(imageInfos)
                    .parMap(function (imageInfo) {
                        imageInfo.asset.getCanvasImage(this);
                    })
                    .seqEach(function (canvasImage, i) {
                        _.extend(imageInfos[i], {
                            canvasImage: canvasImage,
                            width: canvasImage.width,
                            height: canvasImage.height
                        });
                        process.nextTick(this);
                    })
                    .seq(function () {
                        var packerName = {
                            'jim-scott': 'jimScott',
                            horizontal: 'horizontal',
                            vertical: 'vertical'
                        }[spriteInfo.packer] || 'tryAll';
                        var packingData = require('./spriteBackgroundImages/packers/' + packerName).pack(imageInfos),
                            canvas = new Canvas(packingData.width, packingData.height),
                            ctx = canvas.getContext('2d');
                        imageInfos = packingData.imageInfos;
                        if ('backgroundColor' in spriteInfo) {
                            ctx.fillStyle = spriteInfo.imageBackgroundColor;
                            ctx.fillRect(0, 0, canvas.width, canvas.height);
                        }
                        imageInfos.forEach(function (imageInfo) {
                            ctx.drawImage(imageInfo.canvasImage, imageInfo.x, imageInfo.y, imageInfo.width, imageInfo.height);
                        });
                        canvas.toBuffer(this);
                    })
                    .seq(function (spriteBuffer) {
                        var spriteAsset = new assets.PNG({
                            rawSrc: spriteBuffer
                        });
                        spriteAsset.url = assetGraph.resolver.root + spriteAsset.id + '.' + spriteAsset.defaultExtension; // FIXME
                        assetGraph.addAsset(spriteAsset);
                        if (spriteGroup.cssSpritePlaceholder) {
                            var cssRule = spriteGroup.cssSpritePlaceholder.cssRule;
                            cssRule.style.setProperty('background-image', 'url(...)',
                                                      spriteGroup.cssSpritePlaceholder.to.parseTree.important && 'important');
                            assetGraph.addRelation(new relations.CSSImage({
                                cssRule: cssRule,
                                propertyName: 'background-image',
                                from: spriteGroup.cssSpritePlaceholder.from,
                                to: spriteAsset
                            }), 'before', spriteGroup.cssSpritePlaceholder);
                            assetGraph.detachAndRemoveRelation(spriteGroup.cssSpritePlaceholder);
                            assetGraph.removeAsset(spriteGroup.cssSpritePlaceholder.to);
                        }
                        imageInfos.forEach(function (imageInfo) {
                            imageInfo.incomingRelations.forEach(function (incomingRelation) {
                                assetGraph.markAssetDirty(incomingRelation.from);
                                var relationSpriteInfo = assets.CSS.extractInfoFromRule(incomingRelation.cssRule, assets.CSS.vendorPrefix + '-sprite-');
                                incomingRelation.cssRule.style.setProperty('background-position',
                                                                           (imageInfo.x ? (-imageInfo.x) + "px " : "0 ") +
                                                                           (imageInfo.y ? -imageInfo.y + "px" : "0"),
                                                                           relationSpriteInfo.important && 'important');
                                ['group', 'padding', 'no-group-selector', 'important'].forEach(function (propertyName) {
                                    incomingRelation.cssRule.style.removeProperty(assets.CSS.vendorPrefix + '-sprite-' + propertyName);
                                }, this);
                                if (relationSpriteInfo.noGroupSelector) {
                                    // The user specified that this selector needs its own background-image/background
                                    // property pointing at the sprite rather than relying on the HTML elements also being
                                    // matched by the sprite group's "main" selector, which would have been preferable.
                                    assetGraph.addRelation(new relations.CSSImage({
                                        cssRule: incomingRelation.cssRule,
                                        propertyName: incomingRelation.propertyName,
                                        from: incomingRelation.from,
                                        to: spriteAsset
                                    }), 'before', incomingRelation);
                                    assetGraph.removeRelation(incomingRelation);
                                } else {
                                    assetGraph.detachAndRemoveRelation(incomingRelation);
                                }

                                // Remove the original image if it has become an orphan:
                                if (!assetGraph.findRelations({to: incomingRelation.to}).length) {
                                    assetGraph.removeAsset(incomingRelation.to);
                                }
                            });
                        });
                        callback();
                    })
                    ['catch'](callback);
            })
            .seq(function () {
                cb();
            })
            ['catch'](cb);
    };
};
<|endoftext|>


<commit_before>import React from 'react';
import styled from 'styled-components';
import UIState from 'ui/UIState';

const HorizontalHandle = styled.div`
  width: 100%;
  height: 4px;
  cursor: ns-resize;
  background-color: transparent;
`;

const VerticalHandle = styled.div`
  position: absolute;
  height: 100%;
  width: 3px;
  top: 0;
  right: 0;
  cursor: ew-resize;
  background-color: transparent;
`;

class ResizeHandle extends React.Component {

  initResize = (event) => {
    this.start = this.props.horizontal ? event.clientY : event.clientX;
    this.initialSize = this.props.horizontal ? UIState.editorHeight : UIState.mocksSidebarWidth;

    document.addEventListener('mousemove', this.resize);
    document.addEventListener('mouseup', this.stopResize);
  };

  resize = (event) => {
    const delta = this.props.horizontal
      ? this.start - event.clientY
      : event.clientX - this.start;

    if (this.props.horizontal) {
      UIState.update({ editorHeight: this.initialSize + delta });
    }

    if (this.props.vertical) {
      UIState.update({ mocksSidebarWidth: this.initialSize + delta });
    }
  };

  stopResize = () => {
    document.removeEventListener('mousemove', this.resize, false);
    document.removeEventListener('mouseup', this.stopResize, false);
  };

  render() {
    let Handle;

    if (this.props.vertical) {
      Handle = VerticalHandle;
    }

    if (this.props.horizontal) {
      Handle = HorizontalHandle;
    }

    return (
      <Handle onMouseDown={ this.initResize }/>
    );
  }
}

export default ResizeHandle;<commit_msg>disable resizing with right mouse button<commit_after>import React from 'react';
import styled from 'styled-components';
import UIState from 'ui/UIState';

const HorizontalHandle = styled.div`
  width: 100%;
  height: 4px;
  cursor: ns-resize;
  background-color: transparent;
`;

const VerticalHandle = styled.div`
  position: absolute;
  height: 100%;
  width: 3px;
  top: 0;
  right: 0;
  cursor: ew-resize;
  background-color: transparent;
`;

class ResizeHandle extends React.Component {

  initResize = (event) => {
    if (event.button !== 0) {
      // Disable resizing on right click
      return;
    }

    this.start = this.props.horizontal ? event.clientY : event.clientX;
    this.initialSize = this.props.horizontal ? UIState.editorHeight : UIState.mocksSidebarWidth;

    document.addEventListener('mousemove', this.resize);
    document.addEventListener('mouseup', this.stopResize);
  };

  resize = (event) => {
    const delta = this.props.horizontal
      ? this.start - event.clientY
      : event.clientX - this.start;

    if (this.props.horizontal) {
      UIState.update({ editorHeight: this.initialSize + delta });
    }

    if (this.props.vertical) {
      UIState.update({ mocksSidebarWidth: this.initialSize + delta });
    }
  };

  stopResize = () => {
    document.removeEventListener('mousemove', this.resize, false);
    document.removeEventListener('mouseup', this.stopResize, false);
  };

  render() {
    let Handle;

    if (this.props.vertical) {
      Handle = VerticalHandle;
    }

    if (this.props.horizontal) {
      Handle = HorizontalHandle;
    }

    return (
      <Handle onMouseDown={ this.initResize }/>
    );
  }
}

export default ResizeHandle;<|endoftext|>


<commit_before>var Mongo = require('../shared/mongo'),
    URI = require('urijs');

class Proc {
    constructor(logger, settings, redis) {
        this.logger = logger;
        this.redis = redis;
        this.settings = settings;
        this.db = new Mongo(settings.mongoUrl, logger);
        this.channels = [].concat(this.settings.channels);
        this.procId = 0;
        this.checkedCalls = ['reaction_added', 'reaction_removed', 'message_deleted', 'message_changed', 'message'];

        // Ensure index on TS
        this.db.perform((db, callback) => {
            this.collection = db.collection('items');
            db.collection('items').createIndex(
                { 'ts': 1 },
                { 'unique': true },
                function(err, results) {
                    callback();
                }
            );
            this.loop();
        });
    }

    waitForProcess(func, timeout) {
        var released = false,
            releaseTime = null,
            valid = true,
            id = this.procId++,
            tout;
        var invalidate = () => {
            this.logger.warn(`Proc#${id}`, `Last procedure #${id} took longer than ${timeout}ms. Releasing loop...`);
            valid = false;
            callback();
        }
        var callback = () => {
            clearTimeout(tout);
            if(!released) {
                if(valid) {
                    this.logger.verbose(`Proc#${id}`, 'Completed.');
                }
                released = true;
                releaseTime = Date.now();
                this.loop();
            } else {
                var now = Date.now();
                this.logger.warn(`Proc#${id}`, `Reentry attempt after ${now - releaseTime}ms.`);
            }
        };
        tout = setTimeout(invalidate, timeout);
        this.logger.verbose(`Proc#${id}`, 'Starting');
        func(callback);
    }

    loop() {
        this.redis.blpop('digest_process_queue', 0, (err, data) => {
            try {
                this.logger.verbose('Proc', `Dequed: ${data}`);
                data = JSON.parse(data[1]);
                this.waitForProcess((callback) => this.process(data, callback), 30000);
            } catch(ex) {
                this.logger.error('Proc', 'Error processing data: ');
                this.logger.error('Proc', ex);
                try {
                    this.redis.rpush('digest_error_queue', JSON.stringify(data))
                    this.logger.info('Proc', 'Old received data has been pushed back to digest_error_queue.');
                } catch(ex) {
                    this.logger.error('Proc', 'Error pushing data to error queue. Data was lost.');
                }
            }
        })
        .catch((ex) => {
            this.logger.error('Proc', 'Error caught: ');
            this.logger.error('Proc', ex);
        });
    }

    channelCheck(chn) {
        if(!chn) {
            this.logger.warn('channelCheck', 'Received empty or false-y chn: ', chn);
            return false;
        }
        return this.channels.indexOf(chn) > -1;
    }

    process(msg, callback) {
        if(!msg) {
            callback();
            return;
        }

        if(msg.subtype) {
            msg.type = msg.subtype;
        }

        if(this.checkedCalls.indexOf(msg.type) > -1 && !this.channelCheck(msg.channel)) {
            callback();
            return;
        }

        var matches;
        switch(msg.type) {
            case 'group_joined':
                if(this.settings.autoWatch) {
                    if(this.channels.indexOf(msg.channel.name) === -1) {
                        this.channels.push(msg.channel.name);
                    }
                }
                callback();
                break;

            case 'reaction_added':
            case 'reaction_removed':
                var delta = msg.type === 'reaction_added' ? 1 : -1,
                    reaction = msg.reaction;
                if(reaction.indexOf('::') > -1) {
                    reaction = reaction.split('::')[0];
                }
                this.logger.verbose('Proc', `Message TS ${msg.item.ts} updating reactions index with delta ${delta}`);
                this.collection.findOne({ ts: msg.item.ts }).then((doc) => {
                        if(doc) {
                            if(!doc.reactions.hasOwnProperty(reaction)) {
                                doc.reactions[reaction] = 0;
                            }
                            doc.reactions[reaction] = Math.max(0, doc.reactions[reaction] + delta);
                            if(doc.reactions[reaction] === 0) {
                                delete doc.reactions[reaction];
                            }
                            this.collection.replaceOne({ _id: doc._id }, doc, () => callback());
                        } else {
                            callback();
                        }
                    })
                    .catch((ex) => {
                        logger.error('Proc', `Error processing findOne for ts ${msg.item.ts}`, ex);
                        callback();
                    });
                break;

            case 'message_deleted':
                this.collection.deleteMany({ ts: msg.deleted_ts }, (err, num) => {
                    if(num === 1) {
                        this.logger.verbose('Proc', `Message TS ${msg.deleted_ts} removed`);
                    }
                    callback();
                });
                break;

            case 'message_changed':
                this.logger.verbose('Proc', `Message TS ${msg.message.ts} was edited.`);
                matches = []
                URI.withinString(msg.message.text, (u) => {
                    matches.push(u);
                    return u;
                });
                if(matches && matches.length > 0) {
                    this.logger.verbose('Proc', `Message TS ${msg.message.ts} still is eligible.`);
                    // Insert or update.
                    this.collection.findOne({ ts: msg.message.ts })
                        .then((doc) => {
                            if(doc) {
                                this.logger.verbose('Proc', `Message TS ${msg.message.ts} found on storage. Updating text...`);
                                // update.
                                doc.text = msg.message.text
                                this.collection.replaceOne({ ts: msg.message.ts }, doc, () => callback());
                            } else {
                                // insert.
                                this.logger.verbose('Proc', `Message TS ${msg.message.ts} not found on storage. Inserting a new one...`);
                                this.collection.insertOne(this.objectForMessage(msg), () => callback());
                            }
                        });
                } else {
                    // delete.
                    this.logger.verbose('Proc', `Message TS ${msg.message.ts} is not eligible anymore and will be removed.`);
                    this.collection.deleteMany({ ts: msg.message.ts }, {}, () => callback());
                }
                break;

            case 'message':
                if(msg.text) {
                    matches = [];
                    URI.withinString(msg.text, (u) => {
                        matches.push(u);
                        return u;
                    });
                    if(matches && matches.length > 0) {
                        this.collection.findOne({ ts: msg.ts })
                            .then((doc) => {
                                if(!doc) {
                                    this.logger.verbose('Loopr', `Message TS ${msg.ts} is eligible and does not exist on storage. Inserting now...`);
                                    this.collection.insertOne(this.objectForMessage(msg), () => callback());
                                } else {
                                    this.logger.verbose('Loopr', `Message TS ${msg.ts} is eligible and already exists on storage. Skipping...`);
                                    callback();
                                }
                        });
                    } else {
                        callback();
                    }
                } else {
                    callback();
                }
                break;
        }
    }

    objectForMessage(msg) {
        return {
            ts: msg.ts,
            text: msg.text,
            channel: msg.channel,
            reactions: {},
            date: Date.now(),
            user: msg.user,
        };
    }
}

module.exports = Proc;
<commit_msg>Update processor to publish a notification when an item has its reactions changed<commit_after>var Mongo = require('../shared/mongo'),
    URI = require('urijs');

class Proc {
    constructor(logger, settings, redis) {
        this.logger = logger;
        this.redis = redis;
        this.settings = settings;
        this.db = new Mongo(settings.mongoUrl, logger);
        this.channels = [].concat(this.settings.channels);
        this.procId = 0;
        this.checkedCalls = ['reaction_added', 'reaction_removed', 'message_deleted', 'message_changed', 'message'];

        // Ensure index on TS
        this.db.perform((db, callback) => {
            this.collection = db.collection('items');
            db.collection('items').createIndex(
                { 'ts': 1 },
                { 'unique': true },
                function(err, results) {
                    callback();
                }
            );
            this.loop();
        });
    }

    waitForProcess(func, timeout) {
        var released = false,
            releaseTime = null,
            valid = true,
            id = this.procId++,
            tout;
        var invalidate = () => {
            this.logger.warn(`Proc#${id}`, `Last procedure #${id} took longer than ${timeout}ms. Releasing loop...`);
            valid = false;
            callback();
        }
        var callback = () => {
            clearTimeout(tout);
            if(!released) {
                if(valid) {
                    this.logger.verbose(`Proc#${id}`, 'Completed.');
                }
                released = true;
                releaseTime = Date.now();
                this.loop();
            } else {
                var now = Date.now();
                this.logger.warn(`Proc#${id}`, `Reentry attempt after ${now - releaseTime}ms.`);
            }
        };
        tout = setTimeout(invalidate, timeout);
        this.logger.verbose(`Proc#${id}`, 'Starting');
        func(callback);
    }

    loop() {
        this.redis.blpop('digest_process_queue', 0, (err, data) => {
            try {
                this.logger.verbose('Proc', `Dequed: ${data}`);
                data = JSON.parse(data[1]);
                this.waitForProcess((callback) => this.process(data, callback), 30000);
            } catch(ex) {
                this.logger.error('Proc', 'Error processing data: ');
                this.logger.error('Proc', ex);
                try {
                    this.redis.rpush('digest_error_queue', JSON.stringify(data))
                    this.logger.info('Proc', 'Old received data has been pushed back to digest_error_queue.');
                } catch(ex) {
                    this.logger.error('Proc', 'Error pushing data to error queue. Data was lost.');
                }
            }
        })
        .catch((ex) => {
            this.logger.error('Proc', 'Error caught: ');
            this.logger.error('Proc', ex);
        });
    }

    channelCheck(chn) {
        if(!chn) {
            this.logger.warn('channelCheck', 'Received empty or false-y chn: ', chn);
            return false;
        }
        return this.channels.indexOf(chn) > -1;
    }

    process(msg, callback) {
        if(!msg) {
            callback();
            return;
        }

        if(msg.subtype) {
            msg.type = msg.subtype;
        }

        if(this.checkedCalls.indexOf(msg.type) > -1 && !this.channelCheck(msg.channel)) {
            callback();
            return;
        }

        var matches;
        switch(msg.type) {
            case 'group_joined':
                if(this.settings.autoWatch) {
                    if(this.channels.indexOf(msg.channel.name) === -1) {
                        this.channels.push(msg.channel.name);
                    }
                }
                callback();
                break;

            case 'reaction_added':
            case 'reaction_removed':
                var delta = msg.type === 'reaction_added' ? 1 : -1,
                    reaction = msg.reaction;
                if(reaction.indexOf('::') > -1) {
                    reaction = reaction.split('::')[0];
                }
                this.logger.verbose('Proc', `Message TS ${msg.item.ts} updating reactions index with delta ${delta}`);
                this.collection.findOne({ ts: msg.item.ts }).then((doc) => {
                        if(doc) {
                            if(!doc.reactions.hasOwnProperty(reaction)) {
                                doc.reactions[reaction] = 0;
                            }
                            doc.reactions[reaction] = Math.max(0, doc.reactions[reaction] + delta);
                            if(doc.reactions[reaction] === 0) {
                                delete doc.reactions[reaction];
                            }
                            this.collection.replaceOne({ _id: doc._id }, doc, () => {
                                this.redis.publish('digest_notifications', JSON.stringify({
                                    type: 'precache_item',
                                    ts: doc.ts
                                }));
                                callback();
                            });
                        } else {
                            callback();
                        }
                    })
                    .catch((ex) => {
                        logger.error('Proc', `Error processing findOne for ts ${msg.item.ts}`, ex);
                        callback();
                    });
                break;

            case 'message_deleted':
                this.collection.deleteMany({ ts: msg.deleted_ts }, (err, num) => {
                    if(num === 1) {
                        this.logger.verbose('Proc', `Message TS ${msg.deleted_ts} removed`);
                    }
                    callback();
                });
                break;

            case 'message_changed':
                this.logger.verbose('Proc', `Message TS ${msg.message.ts} was edited.`);
                matches = []
                URI.withinString(msg.message.text, (u) => {
                    matches.push(u);
                    return u;
                });
                if(matches && matches.length > 0) {
                    this.logger.verbose('Proc', `Message TS ${msg.message.ts} still is eligible.`);
                    // Insert or update.
                    this.collection.findOne({ ts: msg.message.ts })
                        .then((doc) => {
                            if(doc) {
                                this.logger.verbose('Proc', `Message TS ${msg.message.ts} found on storage. Updating text...`);
                                // update.
                                doc.text = msg.message.text
                                this.collection.replaceOne({ ts: msg.message.ts }, doc, () => callback());
                            } else {
                                // insert.
                                this.logger.verbose('Proc', `Message TS ${msg.message.ts} not found on storage. Inserting a new one...`);
                                this.collection.insertOne(this.objectForMessage(msg), () => callback());
                            }
                        });
                } else {
                    // delete.
                    this.logger.verbose('Proc', `Message TS ${msg.message.ts} is not eligible anymore and will be removed.`);
                    this.collection.deleteMany({ ts: msg.message.ts }, {}, () => callback());
                }
                break;

            case 'message':
                if(msg.text) {
                    matches = [];
                    URI.withinString(msg.text, (u) => {
                        matches.push(u);
                        return u;
                    });
                    if(matches && matches.length > 0) {
                        this.collection.findOne({ ts: msg.ts })
                            .then((doc) => {
                                if(!doc) {
                                    this.logger.verbose('Loopr', `Message TS ${msg.ts} is eligible and does not exist on storage. Inserting now...`);
                                    this.collection.insertOne(this.objectForMessage(msg), () => callback());
                                } else {
                                    this.logger.verbose('Loopr', `Message TS ${msg.ts} is eligible and already exists on storage. Skipping...`);
                                    callback();
                                }
                        });
                    } else {
                        callback();
                    }
                } else {
                    callback();
                }
                break;
        }
    }

    objectForMessage(msg) {
        return {
            ts: msg.ts,
            text: msg.text,
            channel: msg.channel,
            reactions: {},
            date: Date.now(),
            user: msg.user,
        };
    }
}

module.exports = Proc;
<|endoftext|>


<commit_before>//  - Reports stats about:
//    * Total number of renderers
//    * For mapnik renderers:
//      - the mapnik-pool status: count, unused and waiting
//      - the internally cached objects: png and grid

var _ = require('underscore');
var MapnikRenderer = require('../../renderers/mapnik');

function RendererStatsReporter(renderCache, statsInterval) {
    this.renderCache = renderCache;
    this.statsInterval = statsInterval || 6e4;
    this.renderersStatsIntervalId = null;
}

module.exports = RendererStatsReporter;

RendererStatsReporter.prototype.start = function() {
    var self = this;
    this.renderersStatsIntervalId = setInterval(function() {
        var renderCacheEntries = self.renderCache.renderers;

        if (!renderCacheEntries) {
            return null;
        }

        global.statsClient.gauge('windshaft.rendercache.count', _.keys(renderCacheEntries).length);

        var renderersStats = _.filter(renderCacheEntries, function(cacheEntry) {
            return cacheEntry.renderer && cacheEntry.renderer.constructor === MapnikRenderer.adaptor &&
                cacheEntry.renderer.renderer._pool;
        }).reduce(
            function(_rendererStats, cacheEntry) {
                if (cacheEntry.renderer.renderer._pool) {
                    _rendererStats.pool.count += cacheEntry.renderer.renderer._pool.getPoolSize();
                    _rendererStats.pool.unused += cacheEntry.renderer.renderer._pool.availableObjectsCount();
                    _rendererStats.pool.waiting += cacheEntry.renderer.renderer._pool.waitingClientsCount();
                }

                if (cacheEntry.renderer.renderer._tileCache && cacheEntry.renderer.renderer._tileCache.results) {
                    _rendererStats.cache = Object.keys(cacheEntry.renderer.renderer._tileCache.results).reduce(
                        function(cacheStats, key) {
                            if (key.match(/^utf/)) {
                                cacheStats.grid += 1;
                            } else {
                                cacheStats.png += 1;
                                var buf = cacheEntry.renderer.renderer._tileCache.results[key][1];
                                if (buf) {
                                    cacheStats.pngBufferSize += buf.length || 0;
                                }
                            }
                            return cacheStats;
                        },
                        _rendererStats.cache
                    );
                }

                return _rendererStats;
            },
            {
                pool: {
                    count: 0,
                    unused: 0,
                    waiting: 0
                },
                cache: {
                    pngBufferSize: 0,
                    png: 0,
                    grid: 0
                }
            }
        );

        global.statsClient.gauge('windshaft.mapnik-cache.png', renderersStats.cache.png);
        global.statsClient.gauge('windshaft.mapnik-cache.png-size', renderersStats.cache.pngBufferSize);
        global.statsClient.gauge('windshaft.mapnik-cache.grid', renderersStats.cache.grid);

        global.statsClient.gauge('windshaft.mapnik-pool.count', renderersStats.pool.count);
        global.statsClient.gauge('windshaft.mapnik-pool.unused', renderersStats.pool.unused);
        global.statsClient.gauge('windshaft.mapnik-pool.waiting', renderersStats.pool.waiting);
    }, this.statsInterval);

};

RendererStatsReporter.prototype.stop = function() {
    clearInterval(this.renderersStatsIntervalId);
    this.renderersStatsIntervalId = null;
};
<commit_msg>Report stats based on getStats from renderers<commit_after>//  - Reports stats about:
//    * Total number of renderers
//    * For mapnik renderers:
//      - the mapnik-pool status: count, unused and waiting
//      - the internally cached objects: png and grid

var _ = require('underscore');
var MapnikRenderer = require('../../renderers/mapnik');

function RendererStatsReporter(renderCache, statsInterval) {
    this.renderCache = renderCache;
    this.statsInterval = statsInterval || 6e4;
    this.renderersStatsIntervalId = null;
}

module.exports = RendererStatsReporter;

RendererStatsReporter.prototype.start = function() {
    var self = this;
    this.renderersStatsIntervalId = setInterval(function() {
        var renderCacheEntries = self.renderCache.renderers;

        if (!renderCacheEntries) {
            return null;
        }

        global.statsClient.gauge('windshaft.rendercache.count', _.keys(renderCacheEntries).length);

        var renderersStats = _.reduce(renderCacheEntries, function(_rendererStats, cacheEntry) {
                var stats = cacheEntry.renderer && cacheEntry.renderer.getStats && cacheEntry.renderer.getStats();
                if (!stats) {
                    return _rendererStats;
                }

                _rendererStats.pool.count += stats.pool.count;
                _rendererStats.pool.unused += stats.pool.unused;
                _rendererStats.pool.waiting += stats.pool.waiting;

                _rendererStats.cache.pngBufferSize += stats.cache.pngBufferSize;
                _rendererStats.cache.grid += stats.cache.grid;
                _rendererStats.cache.png += stats.cache.png;

                return _rendererStats;
            },
            {
                pool: {
                    count: 0,
                    unused: 0,
                    waiting: 0
                },
                cache: {
                    pngBufferSize: 0,
                    png: 0,
                    grid: 0
                }
            }
        );

        global.statsClient.gauge('windshaft.mapnik-cache.png', renderersStats.cache.png);
        global.statsClient.gauge('windshaft.mapnik-cache.png-size', renderersStats.cache.pngBufferSize);
        global.statsClient.gauge('windshaft.mapnik-cache.grid', renderersStats.cache.grid);

        global.statsClient.gauge('windshaft.mapnik-pool.count', renderersStats.pool.count);
        global.statsClient.gauge('windshaft.mapnik-pool.unused', renderersStats.pool.unused);
        global.statsClient.gauge('windshaft.mapnik-pool.waiting', renderersStats.pool.waiting);
    }, this.statsInterval);

};

RendererStatsReporter.prototype.stop = function() {
    clearInterval(this.renderersStatsIntervalId);
    this.renderersStatsIntervalId = null;
};
<|endoftext|>