<commit_before>dojo.provide("dojox.layout.BorderContainer");

dojo.require("dijit.layout._LayoutWidget");

dojo.experimental("dojox.layout.BorderContainer");

dojo.declare(
	"dojox.layout.BorderContainer",
//	[dijit._Widget, dijit._Container, dijit._Contained],
	dijit.layout._LayoutWidget,
{
	// summary
	//	Provides layout in 5 regions, a center and borders along its 4 sides.
	//
	// details
	//	A BorderContainer is a box with a specified size (like style="width: 500px; height: 500px;"),
	//	that contains children widgets marked with "position" of "top", "bottom", "leading", "trailing", "center".
	//  Children will be laid out inside the edges of the box with the remaining space left for the center.
	//  Optional splitters may be specified on the edge widgets to make them resizable by the user.
	//  The outer size must be specified on the BorderContainer node.  Width must be specified for the sides
	//  and height for the top and bottom.
	//  "left" and "right" may be used interchangably for "leading" and "trailing" except that those terms do
	//  not reflect the fact that they will be reversed in right-to-left environments.
	//
	// usage
	//
	//

	//
header text

	//
table of contents

	//
client area

	//

	// priority: String
	//  choose which panels get priority in the layout: "headline" where the top and bottom extend the full width
	//  of the container, or "sidebar" where the left and right sides extend from top to bottom.
	priority: "headline",

//TODO: activeSizing, persist for splitters?

	postCreate: function(){
		this.inherited("postCreate", arguments);

		this.domNode.style.position = "relative";
		dojo.addClass(this.domNode, "dijitBorderContainer");
	},

	layout: function(){
		this._layoutChildren(this.domNode, this._contentBox, this.getChildren());
	},

	addChild: function(/*Widget*/ child, /*Integer?*/ insertIndex){
		dijit._Container.prototype.addChild.apply(this, arguments);
		if(this._started){
			this._layoutChildren(this.domNode, this._contentBox, this.getChildren());
		}
	},

	removeChild: function(/*Widget*/ widget){
		dijit._Container.prototype.removeChild.apply(this, arguments);
		if(this._started){
			this._layoutChildren(this.domNode, this._contentBox, this.getChildren());
		}
	},

	_layoutChildren: function(/*DomNode*/ container, /*Object*/ dim, /*Object[]*/ children){
		/**
		 * summary
		 *		Layout a bunch of child dom nodes within a parent dom node
		 * container:
		 *		parent node
		 * dim:
		 *		{l, t, w, h} object specifying dimensions of container into which to place children
		 * children:
		 *		an array like [ {domNode: foo, position: "bottom" }, {domNode: bar, position: "client"} ]
		 */

//TODO: what is dim and why doesn't it look right?
		// copy dim because we are going to modify it
//		dim = dojo.mixin({}, dim);
if(!this._init){
		this._splitters = {};
		//FIXME: do this once? somewhere else?
		dojo.forEach(this.getChildren(), function(child){
			var position = child.position;
			if(position){
				child.domNode.style.position = "absolute";

				if(position == "leading"){ position = "left"; }
				if(position == "trailing"){ position = "right"; }
				if(!dojo._isBodyLtr()){
					if(position == "left"){
						position = "right";
					}else if(position == "right"){
						position = "left";
					}
				}
				this["_"+position] = child.domNode;

				if(child.splitter){
					var splitter = new dojox.layout._Splitter({ container: this, childNode: child.domNode, position: position });
					this._splitters[position] = splitter.domNode;
					dojo.place(splitter.domNode, child.domNode, "after");
				}
			}
		}, this);
this._init = true;
}

		var sidebarLayout = (this.priority == "sidebar");
		var topHeight = 0, bottomHeight = 0, leftWidth = 0, rightWidth = 0;
		var topStyle = {}, leftStyle = {}, rightStyle = {}, bottomStyle = {},
			centerStyle = (this._center && this._center.style) || {};

		if(this._top){
			topStyle = this._top.style;
			topHeight = dojo.coords(this._top).h;
		}
		if(this._left){
			leftStyle = this._left.style;
			leftWidth = dojo.coords(this._left).w;
		}
		if(this._right){
			rightStyle = this._right.style;
			rightWidth = dojo.coords(this._right).w;
		}
		if(this._bottom){
			bottomStyle = this._bottom.style;
			bottomHeight = dojo.coords(this._bottom).h;
		}

		var topSplitter = this._splitters.top;
		if(topSplitter){
			topSplitter.style.top = topHeight + "px";
			topSplitter.style.left = (sidebarLayout ? leftWidth : "0") + "px";
			topSplitter.style.right = (sidebarLayout ? rightWidth : "0") + "px";
		}

		var bottomSplitter = this._splitters.bottom;
		if(bottomSplitter){
			bottomSplitter.style.bottom = bottomHeight + "px";
			bottomSplitter.style.left = (sidebarLayout ? leftWidth : "0") + "px";
			bottomSplitter.style.right = (sidebarLayout ? rightWidth : "0") + "px";
		}

		var leftSplitter = this._splitters.left;
		if(leftSplitter){
			leftSplitter.style.left = leftWidth + "px";
			leftSplitter.style.top = (sidebarLayout ? "0" : topHeight) + "px";
			leftSplitter.style.bottom = (sidebarLayout ? "0" : bottomHeight) + "px";
		}

		var rightSplitter = this._splitters.right;
		if(rightSplitter){
			rightSplitter.style.right = rightWidth + "px";
			rightSplitter.style.top = (sidebarLayout ? "0" : topHeight) + "px";
			rightSplitter.style.bottom = (sidebarLayout ? "0" : bottomHeight) + "px";
		}

		centerStyle.top = topHeight + (topSplitter ? dojo.coords(topSplitter).h : 0) + "px";
		centerStyle.left = leftWidth + (leftSplitter ? dojo.coords(leftSplitter).w : 0) + "px";
		centerStyle.right =  rightWidth + (rightSplitter ? dojo.coords(rightSplitter).w : 0) + "px";
		centerStyle.bottom = bottomHeight + (bottomSplitter ? dojo.coords(bottomSplitter).h : 0) + "px";

		leftStyle.top = rightStyle.top = sidebarLayout ? "0px" : centerStyle.top;
		leftStyle.left = rightStyle.right = "0px";
		leftStyle.bottom = rightStyle.bottom = sidebarLayout ? "0px" : centerStyle.bottom;

		topStyle.top = "0px";
		bottomStyle.bottom = "0px";
		if(sidebarLayout){
			topStyle.left = bottomStyle.left = leftWidth + (leftSplitter && !dojo._isBodyLtr() ? dojo.coords(leftSplitter).w : 0) + "px";
			topStyle.right = bottomStyle.right = rightWidth + (rightSplitter && dojo._isBodyLtr() ? dojo.coords(rightSplitter).w : 0) + "px";
		}else{
			topStyle.left = topStyle.right = "0px";
			bottomStyle.left = bottomStyle.right = "0px";
		}

//FIXME: refactor so that IE codes still runs if any of /top|bottom|left|right/ are undefined
		if(dojo.isIE){
			this.domNode._top = this._top;
			this.domNode._bottom = this._bottom;
			var containerHeight = "dojo.style("+this.id+",'height')";
			var middleHeight = containerHeight+"-dojo.style("+this.id+"._top,'height')-dojo.style("+this.id+"._bottom, 'height')";
			centerStyle.setExpression("height", middleHeight);
//What I'd think would work
//			leftStyle.setExpression("height", sidebarLayout ? containerHeight : middleHeight);
//			rightStyle.setExpression("height", sidebarLayout ? containerHeight : middleHeight);
//What actually works
			leftStyle.setExpression("height", sidebarLayout ? this.id+".offsetHeight" : middleHeight + "+" + this.id+".offsetHeight-"+containerHeight);
			rightStyle.setExpression("height", sidebarLayout ? this.id+".offsetHeight" : middleHeight + "+" + this.id+".offsetHeight-"+containerHeight);

			if(dojo.isIE < 7){
				this.domNode._left = this._left;
				this.domNode._right = this._right;
				var containerWidth = "dojo.style("+this.id+",'width')";
				var middleWidth = containerWidth+"-dojo.style("+this.id+"._left,'width')-dojo.style("+this.id+"._right, 'width')";
				centerStyle.setExpression("width", middleWidth);
				topStyle.setExpression("width", sidebarLayout ? middleWidth + "+" + this.id+".offsetWidth-"+containerWidth : this.id+".offsetWidth");
				bottomStyle.setExpression("width", sidebarLayout ? middleWidth + "+" + this.id+".offsetWidth-"+containerWidth : this.id+".offsetWidth");
			}
		}

		dojo.forEach(this.getChildren(), function(child){ child.resize && child.resize(); });
	},

	resize: function(args){
		this.layout();
	}
});

// This argument can be specified for the children of a BorderContainer.
// Since any widget can be specified as a LayoutContainer child, mix it
// into the base widget class.  (This is a hack, but it's effective.)
dojo.extend(dijit._Widget, {
	// position: String
	//		"top", "bottom", "leading", "trailing", "left", "right", "center".
	//		See the BorderContainer description for details on this parameter.
	position: 'none',

	// splitter: Boolean
	splitter: false
});

dojo.require("dijit._Templated");

dojo.declare("dojox.layout._Splitter", [ dijit._Widget, dijit._Templated ],
{
	// thickness: Number
	thickness: 10,

	container: null,
	childNode: null,
	position: null,

	// live: Boolean
	//		If true, the child's size changes as you drag the bar;
	//		otherwise, the size doesn't change until you drop the bar (by mouse-up)
	live: true,

	// summary: A draggable spacer between two items in a BorderContainer
	templateString: '

',

	postCreate: function(){
		this.inherited("postCreate", arguments);
		this.horizontal = /top|bottom/.test(this.position);
		dojo.addClass(this.domNode, "dijitSplitter" + this.horizontal ? "Horizontal" : "Vertical");
		this.domNode.style[this.horizontal ? "height" : "width"] = this.thickness + "px";
	},

	_startDrag: function(e){
		dojo.addClass(this.domNode, "dijitSplitterActive");
		this._resize = this.live;
		var horizontal = this.horizontal;
		this._pageStart = horizontal ? e.pageY : e.pageX;
		this._childStart = dojo.coords(this.childNode)[ horizontal ? 'h' : 'w' ];
		var axis = horizontal ? 'y' : 'x';
		this._splitterStart = dojo.coords(this.domNode)[axis] - dojo.coords(this.container.domNode)[axis];
		this._handlers = [
				dojo.connect(dojo.doc, "onmousemove", this, "_drag"),
				dojo.connect(dojo.doc, "onmouseup", this, "_stopDrag")
			];
		dojo.stopEvent(e);
	},

	_drag: function(e){
		var delta = (this.horizontal ? e.pageY : e.pageX) - this._pageStart;
		if(this._resize){
			this._move(delta, this._childStart);
		}else{
			var splitterCoord = delta + this._splitterStart;
			this.domNode.style[ this.horizontal ? "top" : "left" ] = splitterCoord + "px"; //FIXME: this ends up off by a few pixels for right/bottom
		}
	},

	_stopDrag: function(e){
		dojo.removeClass(this.domNode, "dijitSplitterActive");
		this._drag(e);
		this._resize = true;
		this._drag(e);
		dojo.forEach(this._handlers, dojo.disconnect);
		delete this._handlers;
	},

	_onKeyPress: function(/*Event*/ e){
		// should we apply typematic to this?
		this._resize = true;
		var horizontal = this.horizontal;
		var tick = 1;
		switch(e.keyCode){
			case horizontal ? dojo.keys.UP_ARROW : dojo.keys.LEFT_ARROW:
				tick *= -1;
				break;
			case horizontal ? dojo.keys.DOWN_ARROW : dojo.keys.RIGHT_ARROW:
				break;
			default:
//				this.inherited("_onKeyPress", arguments);
				return;
		}
		this._move(tick, dojo.coords(this.childNode)[ horizontal ? 'h' : 'w' ]);
		dojo.stopEvent(e);
	},

	_move: function(/*Number*/delta, oldChildSize){
		var factor = /top|left/.test(this.position) ? 1 : -1;
		var childStart = oldChildSize;
		var childSize = factor * delta + childStart;
		this.childNode.style[ this.horizontal ? "height" : "width" ] = childSize + "px";
		this.container.layout();
	},

	destroy: function(){
		this.inherited("destroy", arguments);
		this._stopDrag();
		delete this.childNode;
		delete this.container;
	}
});
<commit_msg>make sparse layouts work in IE<commit_after>dojo.provide("dojox.layout.BorderContainer");

dojo.require("dijit.layout._LayoutWidget");

dojo.experimental("dojox.layout.BorderContainer");

dojo.declare(
	"dojox.layout.BorderContainer",
//	[dijit._Widget, dijit._Container, dijit._Contained],
	dijit.layout._LayoutWidget,
{
	// summary
	//	Provides layout in 5 regions, a center and borders along its 4 sides.
	//
	// details
	//	A BorderContainer is a box with a specified size (like style="width: 500px; height: 500px;"),
	//	that contains children widgets marked with "position" of "top", "bottom", "leading", "trailing", "center".
	//  Children will be laid out inside the edges of the box with the remaining space left for the center.
	//  Optional splitters may be specified on the edge widgets to make them resizable by the user.
	//  The outer size must be specified on the BorderContainer node.  Width must be specified for the sides
	//  and height for the top and bottom.
	//  "left" and "right" may be used interchangably for "leading" and "trailing" except that those terms do
	//  not reflect the fact that they will be reversed in right-to-left environments.
	//
	// usage
	//
	//

	//
header text

	//
table of contents

	//
client area

	//

	// priority: String
	//  choose which panels get priority in the layout: "headline" where the top and bottom extend the full width
	//  of the container, or "sidebar" where the left and right sides extend from top to bottom.
	priority: "headline",

//TODO: activeSizing, persist for splitters?

	postCreate: function(){
		this.inherited("postCreate", arguments);

		this.domNode.style.position = "relative";
		dojo.addClass(this.domNode, "dijitBorderContainer");
	},

	layout: function(){
		this._layoutChildren(this.domNode, this._contentBox, this.getChildren());
	},

	addChild: function(/*Widget*/ child, /*Integer?*/ insertIndex){
		dijit._Container.prototype.addChild.apply(this, arguments);
		if(this._started){
			this._layoutChildren(this.domNode, this._contentBox, this.getChildren());
		}
	},

	removeChild: function(/*Widget*/ widget){
		dijit._Container.prototype.removeChild.apply(this, arguments);
		if(this._started){
			this._layoutChildren(this.domNode, this._contentBox, this.getChildren());
		}
	},

	_layoutChildren: function(/*DomNode*/ container, /*Object*/ dim, /*Object[]*/ children){
		/**
		 * summary
		 *		Layout a bunch of child dom nodes within a parent dom node
		 * container:
		 *		parent node
		 * dim:
		 *		{l, t, w, h} object specifying dimensions of container into which to place children
		 * children:
		 *		an array like [ {domNode: foo, position: "bottom" }, {domNode: bar, position: "client"} ]
		 */

//TODO: what is dim and why doesn't it look right?
		// copy dim because we are going to modify it
//		dim = dojo.mixin({}, dim);
if(!this._init){
		this._splitters = {};
		//FIXME: do this once? somewhere else?
		dojo.forEach(this.getChildren(), function(child){
			var position = child.position;
			if(position){
				child.domNode.style.position = "absolute";

				if(position == "leading"){ position = "left"; }
				if(position == "trailing"){ position = "right"; }
				if(!dojo._isBodyLtr()){
					if(position == "left"){
						position = "right";
					}else if(position == "right"){
						position = "left";
					}
				}
				this["_"+position] = child.domNode;

				if(child.splitter){
					var splitter = new dojox.layout._Splitter({ container: this, childNode: child.domNode, position: position });
					this._splitters[position] = splitter.domNode;
					dojo.place(splitter.domNode, child.domNode, "after");
				}
			}
		}, this);
this._init = true;
}

		var sidebarLayout = (this.priority == "sidebar");
		var topHeight = 0, bottomHeight = 0, leftWidth = 0, rightWidth = 0;
		var topStyle = {}, leftStyle = {}, rightStyle = {}, bottomStyle = {},
			centerStyle = (this._center && this._center.style) || {};

		if(this._top){
			topStyle = this._top.style;
			topHeight = dojo.coords(this._top).h;
		}
		if(this._left){
			leftStyle = this._left.style;
			leftWidth = dojo.coords(this._left).w;
		}
		if(this._right){
			rightStyle = this._right.style;
			rightWidth = dojo.coords(this._right).w;
		}
		if(this._bottom){
			bottomStyle = this._bottom.style;
			bottomHeight = dojo.coords(this._bottom).h;
		}

		var topSplitter = this._splitters.top;
		if(topSplitter){
			topSplitter.style.top = topHeight + "px";
			topSplitter.style.left = (sidebarLayout ? leftWidth : "0") + "px";
			topSplitter.style.right = (sidebarLayout ? rightWidth : "0") + "px";
		}

		var bottomSplitter = this._splitters.bottom;
		if(bottomSplitter){
			bottomSplitter.style.bottom = bottomHeight + "px";
			bottomSplitter.style.left = (sidebarLayout ? leftWidth : "0") + "px";
			bottomSplitter.style.right = (sidebarLayout ? rightWidth : "0") + "px";
		}

		var leftSplitter = this._splitters.left;
		if(leftSplitter){
			leftSplitter.style.left = leftWidth + "px";
			leftSplitter.style.top = (sidebarLayout ? "0" : topHeight) + "px";
			leftSplitter.style.bottom = (sidebarLayout ? "0" : bottomHeight) + "px";
		}

		var rightSplitter = this._splitters.right;
		if(rightSplitter){
			rightSplitter.style.right = rightWidth + "px";
			rightSplitter.style.top = (sidebarLayout ? "0" : topHeight) + "px";
			rightSplitter.style.bottom = (sidebarLayout ? "0" : bottomHeight) + "px";
		}

		centerStyle.top = topHeight + (topSplitter ? dojo.coords(topSplitter).h : 0) + "px";
		centerStyle.left = leftWidth + (leftSplitter ? dojo.coords(leftSplitter).w : 0) + "px";
		centerStyle.right =  rightWidth + (rightSplitter ? dojo.coords(rightSplitter).w : 0) + "px";
		centerStyle.bottom = bottomHeight + (bottomSplitter ? dojo.coords(bottomSplitter).h : 0) + "px";

		leftStyle.top = rightStyle.top = sidebarLayout ? "0px" : centerStyle.top;
		leftStyle.left = rightStyle.right = "0px";
		leftStyle.bottom = rightStyle.bottom = sidebarLayout ? "0px" : centerStyle.bottom;

		topStyle.top = "0px";
		bottomStyle.bottom = "0px";
		if(sidebarLayout){
			topStyle.left = bottomStyle.left = leftWidth + (leftSplitter && !dojo._isBodyLtr() ? dojo.coords(leftSplitter).w : 0) + "px";
			topStyle.right = bottomStyle.right = rightWidth + (rightSplitter && dojo._isBodyLtr() ? dojo.coords(rightSplitter).w : 0) + "px";
		}else{
			topStyle.left = topStyle.right = "0px";
			bottomStyle.left = bottomStyle.right = "0px";
		}

		if(dojo.isIE){
			this.domNode._top = this._top;
			this.domNode._bottom = this._bottom;
			var containerHeight = "dojo.style("+this.id+",'height')";
			var middleHeight = containerHeight;
			if(this._top){ middleHeight += "-dojo.style("+this.id+"._top,'height')"; }
			if(this._bottom){ middleHeight += "-dojo.style("+this.id+"._bottom, 'height')"; }
			if(this._center){ centerStyle.setExpression("height", middleHeight); }
//What I'd think would work
//			leftStyle.setExpression("height", sidebarLayout ? containerHeight : middleHeight);
//			rightStyle.setExpression("height", sidebarLayout ? containerHeight : middleHeight);
//What actually works
			if(this._left){ leftStyle.setExpression("height", sidebarLayout ? this.id+".offsetHeight" : middleHeight + "+" + this.id+".offsetHeight-"+containerHeight); }
			if(this._right){ rightStyle.setExpression("height", sidebarLayout ? this.id+".offsetHeight" : middleHeight + "+" + this.id+".offsetHeight-"+containerHeight); }

			if(dojo.isIE < 7){
				this.domNode._left = this._left;
				this.domNode._right = this._right;
				var containerWidth = "dojo.style("+this.id+",'width')";
				var middleWidth = containerWidth;
				if(this._left){ middleWidth += "-dojo.style("+this.id+"._left,'width')"; }
				if(this._right){ middleWidth += "-dojo.style("+this.id+"._right, 'width')"; }
				if(this._center){ centerStyle.setExpression("width", middleWidth); }
				if(this._top){ topStyle.setExpression("width", sidebarLayout ? middleWidth + "+" + this.id+".offsetWidth-"+containerWidth : this.id+".offsetWidth"); }
				if(this._bottom){ bottomStyle.setExpression("width", sidebarLayout ? middleWidth + "+" + this.id+".offsetWidth-"+containerWidth : this.id+".offsetWidth"); }
			}
		}

		dojo.forEach(this.getChildren(), function(child){ child.resize && child.resize(); });
	},

	resize: function(args){
		this.layout();
	}
});

// This argument can be specified for the children of a BorderContainer.
// Since any widget can be specified as a LayoutContainer child, mix it
// into the base widget class.  (This is a hack, but it's effective.)
dojo.extend(dijit._Widget, {
	// position: String
	//		"top", "bottom", "leading", "trailing", "left", "right", "center".
	//		See the BorderContainer description for details on this parameter.
	position: 'none',

	// splitter: Boolean
	splitter: false
});

dojo.require("dijit._Templated");

dojo.declare("dojox.layout._Splitter", [ dijit._Widget, dijit._Templated ],
{
	// thickness: Number
	thickness: 10,

	container: null,
	childNode: null,
	position: null,

	// live: Boolean
	//		If true, the child's size changes as you drag the bar;
	//		otherwise, the size doesn't change until you drop the bar (by mouse-up)
	live: true,

	// summary: A draggable spacer between two items in a BorderContainer
	templateString: '

',

	postCreate: function(){
		this.inherited("postCreate", arguments);
		this.horizontal = /top|bottom/.test(this.position);
		dojo.addClass(this.domNode, "dijitSplitter" + this.horizontal ? "Horizontal" : "Vertical");
		this.domNode.style[this.horizontal ? "height" : "width"] = this.thickness + "px";
	},

	_startDrag: function(e){
		dojo.addClass(this.domNode, "dijitSplitterActive");
		this._resize = this.live;
		var horizontal = this.horizontal;
		this._pageStart = horizontal ? e.pageY : e.pageX;
		this._childStart = dojo.coords(this.childNode)[ horizontal ? 'h' : 'w' ];
		var axis = horizontal ? 'y' : 'x';
		this._splitterStart = dojo.coords(this.domNode)[axis] - dojo.coords(this.container.domNode)[axis];
		this._handlers = [
				dojo.connect(dojo.doc, "onmousemove", this, "_drag"),
				dojo.connect(dojo.doc, "onmouseup", this, "_stopDrag")
			];
		dojo.stopEvent(e);
	},

	_drag: function(e){
		var delta = (this.horizontal ? e.pageY : e.pageX) - this._pageStart;
		if(this._resize){
			this._move(delta, this._childStart);
		}else{
			var splitterCoord = delta + this._splitterStart;
			this.domNode.style[ this.horizontal ? "top" : "left" ] = splitterCoord + "px"; //FIXME: this ends up off by a few pixels for right/bottom
		}
	},

	_stopDrag: function(e){
		dojo.removeClass(this.domNode, "dijitSplitterActive");
		this._drag(e);
		this._resize = true;
		this._drag(e);
		dojo.forEach(this._handlers, dojo.disconnect);
		delete this._handlers;
	},

	_onKeyPress: function(/*Event*/ e){
		// should we apply typematic to this?
		this._resize = true;
		var horizontal = this.horizontal;
		var tick = 1;
		switch(e.keyCode){
			case horizontal ? dojo.keys.UP_ARROW : dojo.keys.LEFT_ARROW:
				tick *= -1;
				break;
			case horizontal ? dojo.keys.DOWN_ARROW : dojo.keys.RIGHT_ARROW:
				break;
			default:
//				this.inherited("_onKeyPress", arguments);
				return;
		}
		this._move(tick, dojo.coords(this.childNode)[ horizontal ? 'h' : 'w' ]);
		dojo.stopEvent(e);
	},

	_move: function(/*Number*/delta, oldChildSize){
		var factor = /top|left/.test(this.position) ? 1 : -1;
		var childStart = oldChildSize;
		var childSize = factor * delta + childStart;
		this.childNode.style[ this.horizontal ? "height" : "width" ] = childSize + "px";
		this.container.layout();
	},

	destroy: function(){
		this.inherited("destroy", arguments);
		this._stopDrag();
		delete this.childNode;
		delete this.container;
	}
});
<|endoftext|>


<commit_before>'use strict';

var fs = require('fs');
var path = require('path');
var XRegExp = require('xregexp').XRegExp;
var GoogleAnalytics = require('./google-analytics');
var EventEmitter = require('events').EventEmitter;
var util = require('util');
var _ = require('lodash');

module.exports = (function () {

  function ErrorMatcher() {
    this.regex = null;
    this.cwd = null;
    this.stdout = null;
    this.stderr = null;
    this.currentMatch = [];

    atom.commands.add('atom-workspace', 'build:error-match', this.match.bind(this));
    atom.commands.add('atom-workspace', 'build:error-match-first', this.matchFirst.bind(this));
  }

  util.inherits(ErrorMatcher, EventEmitter);

  ErrorMatcher.prototype._gotoNext = function () {
    this._goto(this.currentMatch[0].id);
    this.currentMatch.push(this.currentMatch.shift());
  };

  ErrorMatcher.prototype._goto = function (id) {
    var match = _.findWhere(this.currentMatch, { id: id });
    if (match.absFile) {
      atom.notifications.addWarning('`absFile` is deprecated.', {
        detail: 'You should name your match `file` only. It handles both relative and absolute paths.'
      });
    }

    if (!match.file && !match.absFile) {
      return this.emit('error', 'Did not match any file. Don\'t know what to open.');
    }

    var file = match.file ? match.file : match.absFile;
    if (!path.isAbsolute(file)) {
      file = this.cwd + path.sep + file;
    }

    var row = match.line ? match.line - 1 : 0; /* Because atom is zero-based */
    var col =  match.col ? match.col - 1 : 0; /* Because atom is zero-based */

    fs.exists(file, function (exists) {
      if (!exists) {
        return this.emit('error', 'Matched file does not exist: ' + file);
      }
      atom.workspace.open(file, {
        initialLine: row,
        initialColumn: col,
        searchAllPanes: true
      });
      this.emit('scroll', match.type, match.id);
    }.bind(this));
  };

  ErrorMatcher.prototype._parse = function () {
    this.currentMatch = XRegExp.forEach(this.output, this.regex, function (match, i) {
      match.type = 'error';
      match.id = 'error-' + i;
      this.push(match);
    }, []);
    var output = _.escape(this.output);
    var matchIndex;
    for (matchIndex in this.currentMatch) {
      var search = _.escape(this.currentMatch[matchIndex][0]);
      var replace = '$&';
      output = output.replace(search, replace);
    }
    this.emit('replace', output, this._goto.bind(this));
    return this.currentMatch.length;
  };

  ErrorMatcher.prototype.set = function (regex, cwd, output) {
    this.regex = XRegExp(regex);
    this.cwd = cwd;
    this.output = output;
    this.currentMatch = [];
  };

  ErrorMatcher.prototype.match = function () {
    if (!this.regex) {
      return;
    }

    GoogleAnalytics.sendEvent('errorMatch', 'match');

    if (0 === this.currentMatch.length && 0 === this._parse()) {
      return;
    }

    this._gotoNext();
  };

  ErrorMatcher.prototype.matchFirst = function () {
    if (!this.regex) {
      return;
    }

    GoogleAnalytics.sendEvent('errorMatch', 'first');

    if (0 === this._parse()) {
      return;
    }

    this._gotoNext();
  };

  return ErrorMatcher;
})();
<commit_msg>fixed bug: same string gets matched two times -> highlight both times<commit_after>'use strict';

var fs = require('fs');
var path = require('path');
var XRegExp = require('xregexp').XRegExp;
var GoogleAnalytics = require('./google-analytics');
var EventEmitter = require('events').EventEmitter;
var util = require('util');
var _ = require('lodash');

module.exports = (function () {

  function ErrorMatcher() {
    this.regex = null;
    this.cwd = null;
    this.stdout = null;
    this.stderr = null;
    this.currentMatch = [];

    atom.commands.add('atom-workspace', 'build:error-match', this.match.bind(this));
    atom.commands.add('atom-workspace', 'build:error-match-first', this.matchFirst.bind(this));
  }

  util.inherits(ErrorMatcher, EventEmitter);

  ErrorMatcher.prototype._gotoNext = function () {
    this._goto(this.currentMatch[0].id);
    this.currentMatch.push(this.currentMatch.shift());
  };

  ErrorMatcher.prototype._goto = function (id) {
    var match = _.findWhere(this.currentMatch, { id: id });
    if (match.absFile) {
      atom.notifications.addWarning('`absFile` is deprecated.', {
        detail: 'You should name your match `file` only. It handles both relative and absolute paths.'
      });
    }

    if (!match.file && !match.absFile) {
      return this.emit('error', 'Did not match any file. Don\'t know what to open.');
    }

    var file = match.file ? match.file : match.absFile;
    if (!path.isAbsolute(file)) {
      file = this.cwd + path.sep + file;
    }

    var row = match.line ? match.line - 1 : 0; /* Because atom is zero-based */
    var col =  match.col ? match.col - 1 : 0; /* Because atom is zero-based */

    fs.exists(file, function (exists) {
      if (!exists) {
        return this.emit('error', 'Matched file does not exist: ' + file);
      }
      atom.workspace.open(file, {
        initialLine: row,
        initialColumn: col,
        searchAllPanes: true
      });
      this.emit('scroll', match.type, match.id);
    }.bind(this));
  };

  ErrorMatcher.prototype._parse = function () {
    this.currentMatch = XRegExp.forEach(this.output, this.regex, function (match, i) {
      match.type = 'error';
      match.id = 'error-' + i;
      this.push(match);
    }, []);

    var output = '';
    var lastEnd = 0;
    for (var matchIndex in this.currentMatch) {
      var match = this.currentMatch[matchIndex];

      output += _.escape(this.output.substr(lastEnd, match.index - lastEnd));
      output += '' + _.escape(match[0]) + '';
      lastEnd = match.index + match[0].length;
    }
    output += _.escape(this.output.substr(lastEnd));

    this.emit('replace', output, this._goto.bind(this));
    return this.currentMatch.length;
  };

  ErrorMatcher.prototype.set = function (regex, cwd, output) {
    this.regex = XRegExp(regex);
    this.cwd = cwd;
    this.output = output;
    this.currentMatch = [];
  };

  ErrorMatcher.prototype.match = function () {
    if (!this.regex) {
      return;
    }

    GoogleAnalytics.sendEvent('errorMatch', 'match');

    if (0 === this.currentMatch.length && 0 === this._parse()) {
      return;
    }

    this._gotoNext();
  };

  ErrorMatcher.prototype.matchFirst = function () {
    if (!this.regex) {
      return;
    }

    GoogleAnalytics.sendEvent('errorMatch', 'first');

    if (0 === this._parse()) {
      return;
    }

    this._gotoNext();
  };

  return ErrorMatcher;
})();
<|endoftext|>


<commit_before>'use strict'

let cli = require('heroku-cli-util')
let co = require('co')

function map (stack) {
  return stack === 'cedar-10' ? 'cedar' : stack
}

function * run (context, heroku) {
  let stack = map(context.args.stack)
  yield heroku.request({
    method: 'PATCH',
    path: `/apps/${context.app}`,
    body: {build_stack: stack}
  })
  cli.log(`Stack set. Next release on ${cli.color.app(context.app)} will use ${cli.color.green(stack)}.`)
  cli.log(`Run ${cli.color.cmd('git push heroku master')} to create a new release on ${cli.color.app(context.app)}.`)
}

let cmd = {
  topic: 'stack',
  command: 'set',
  needsApp: true,
  needsAuth: true,
  description: 'set the stack of an app',
  help: `
Example:

  $ heroku stack:set cedar-14 -a myapp
  Stack set. Next release on myapp will use cedar-14.
  Run git push heroku master to create a new release on myapp.`,
  args: [{name: 'stack'}],
  run: cli.command(co.wrap(run))
}

module.exports = [
  Object.assign({topic: 'apps', command: 'stacks:set'}, cmd),
  Object.assign({topic: 'stack', command: 'set', hidden: true}, cmd)
]
<commit_msg>fix stack:set aliases<commit_after>'use strict'

let cli = require('heroku-cli-util')
let co = require('co')

function map (stack) {
  return stack === 'cedar-10' ? 'cedar' : stack
}

function * run (context, heroku) {
  let stack = map(context.args.stack)
  yield heroku.request({
    method: 'PATCH',
    path: `/apps/${context.app}`,
    body: {build_stack: stack}
  })
  cli.log(`Stack set. Next release on ${cli.color.app(context.app)} will use ${cli.color.green(stack)}.`)
  cli.log(`Run ${cli.color.cmd('git push heroku master')} to create a new release on ${cli.color.app(context.app)}.`)
}

let cmd = {
  needsApp: true,
  needsAuth: true,
  description: 'set the stack of an app',
  help: `
Example:

  $ heroku stack:set cedar-14 -a myapp
  Stack set. Next release on myapp will use cedar-14.
  Run git push heroku master to create a new release on myapp.`,
  args: [{name: 'stack'}],
  run: cli.command(co.wrap(run))
}

module.exports = [
  Object.assign({topic: 'apps', command: 'stacks:set'}, cmd),
  Object.assign({topic: 'stack', command: 'set', hidden: true}, cmd)
]
<|endoftext|>


<commit_before>
/**
 * Module dependencies.
 */

var express = require('express');
var http = require('http');
var path = require('path');
var os = require('os');
var wams = require('wams.js-server');
var WorkspaceManager = require('./workspaceManager');
var Workspace = require('./workspace');

var app = express();

var iface = os.networkInterfaces().wlp3s0;
var IP;
iface && iface.forEach(function(connection) {
   if (connection.family === 'IPv4') {
      IP = connection.address;
   }
});

// all environments
app.set('ip', process.argv[2] || process.env.IP || IP || '127.0.0.1');
app.set('port', process.argv[3] || process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// app.set('env', 'development');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

// development only
if ('development' === app.get('env')) {
  app.use(express.errorHandler());
}

function renderRoot(req, res) {
   res.render('sharedWorkspace', { title: 'Shared space between clients' });
}

app.get('/', renderRoot);

var server = http.createServer(app);
server.listen(app.get('port'), function(){
  console.log('Express server listening on ' + app.get('ip') + ':' + app.get('port'));
});

function drop4balls(uuid) {
   for (var i = 1; i <= 4; i++) {
      wams.emit('RECV_MSG', uuid, {
         source: '',
         data: {
            action: 'new_element',
            element: {
               tag: 'div',
               attributes: {
                  id: 'ball' + i,
                  class: 'ball',
                  'data-lock': ''
               }
            }
         }
      });
   }
}

function notifyResize(uuid, screen) {
   var users = wams.getSnapshot(), i, len, listUUID;
   for (i = 0, len = users.length; i < len; i++) {
      listUUID = users[i].uuid;
      if (listUUID !== uuid) {
         wams.emit('RECV_MSG', listUUID, {
            source: '',
            data: {
               action: 'adjust_other_workspace',
               metadata: {
                  uuid: uuid,
                  screen: screen
               }
            }
         });
      }
   }
}

wams.listen(server);
var workspaceManager = new WorkspaceManager(wams);
wams.on(wams.when.new_connection, function(data) {
   var screen = Workspace.decode(data.description.screen);
   var users = wams.getSnapshot();
   var user = users[users.length - 1];
   var uuid = user.uuid;
   var adjustedScreen = workspaceManager.addScreen(uuid, screen);
   var notifiedDisableRemoteList = [];

   user.description.screen = Workspace.encode(adjustedScreen);

   if (adjustedScreen.x === 0 && adjustedScreen.y === 0) {
      drop4balls(uuid);
   }

   wams.emit('adjust_workspace', uuid, {
      screen: Workspace.encode(adjustedScreen)
   });
   notifyResize(uuid, Workspace.encode(adjustedScreen));

   wams.on('resize_screen', uuid, function(data) {
      var screen = Workspace.decode(data.data.screen);
      workspaceManager.resize(uuid, screen.width, screen.height);

      notifyResize(uuid, data.data.screen);
   });

   wams.on('disconnect', uuid, function() {
      workspaceManager.deleteScreen(uuid);
   });

   var handler = function(data) {
      if (!data.data.element.length) {
         return;
      }
      var elem = data.data.element[0], corner = [{}, {}, {}, {}], i, len,
         enableRemoteList = [], disableRemoteList = [],
         screen = workspaceManager.getScreen(uuid);
      elem.x += screen.x;
      elem.y += screen.y;
      corner[0].x = elem.x;
      corner[0].y = elem.y;
      corner[1].x = corner[0].x + elem.w;
      corner[1].y = corner[0].y;
      corner[2].x = corner[0].x;
      corner[2].y = corner[0].y + elem.h;
      corner[3].x = corner[0].x + elem.w;
      corner[3].y = corner[0].y + elem.h;

      for (i = 0, len = corner.length; i < len; i++) {
         var under = workspaceManager.under(corner[i].x, corner[i].y);
         under.forEach(function(el) {
            if (enableRemoteList.indexOf(el) === -1) {
               enableRemoteList.push(el);
            }
         });
      }

      disableRemoteList = workspaceManager.allExcept(enableRemoteList);
      if (enableRemoteList) {
         enableRemoteList.forEach(function(listUUID) {
            var indexOfNDRL = notifiedDisableRemoteList.indexOf(listUUID);
            if (indexOfNDRL > -1) {
               notifiedDisableRemoteList.splice(indexOfNDRL, 1);
            }

            if (uuid !== listUUID) {
               var abs = {
                  x: elem.x,
                  y: elem.y
               };
               elem.x -= workspaceManager.getScreen(listUUID).x;
               elem.y -= workspaceManager.getScreen(listUUID).y;
               wams.emit('enable_remote', listUUID, data);
               elem.x = abs.x;
               elem.y = abs.y;
            }
         });
      }
      if (disableRemoteList) {
         disableRemoteList.forEach(function(listUUID) {
            if (notifiedDisableRemoteList.indexOf(listUUID) === -1) {
               var msg = {
                  data: {
                     element: [
                        { attributes: { id:'' } }
                     ]
                  }
               }, i, len;
               for (i = 0, len = data.data.element.length; i < len; i++) {
                  msg.data.element[i].attributes.id = data.data.element[i].attributes.id;
               }
               wams.emit('disable_remote', listUUID, msg);
               notifiedDisableRemoteList.push(listUUID);
            }
         });
      }
   };

   wams.on('touch', uuid, handler);
   wams.on('drag', uuid, handler);
   wams.on('release', uuid, handler);
});

<commit_msg>fix(resize): save adjusted screen to user's description<commit_after>
/**
 * Module dependencies.
 */

var express = require('express');
var http = require('http');
var path = require('path');
var os = require('os');
var wams = require('wams.js-server');
var WorkspaceManager = require('./workspaceManager');
var Workspace = require('./workspace');

var app = express();

var iface = os.networkInterfaces().wlp3s0;
var IP;
iface && iface.forEach(function(connection) {
   if (connection.family === 'IPv4') {
      IP = connection.address;
   }
});

// all environments
app.set('ip', process.argv[2] || process.env.IP || IP || '127.0.0.1');
app.set('port', process.argv[3] || process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// app.set('env', 'development');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

// development only
if ('development' === app.get('env')) {
  app.use(express.errorHandler());
}

function renderRoot(req, res) {
   res.render('sharedWorkspace', { title: 'Shared space between clients' });
}

app.get('/', renderRoot);

var server = http.createServer(app);
server.listen(app.get('port'), function(){
  console.log('Express server listening on ' + app.get('ip') + ':' + app.get('port'));
});

function drop4balls(uuid) {
   for (var i = 1; i <= 4; i++) {
      wams.emit('RECV_MSG', uuid, {
         source: '',
         data: {
            action: 'new_element',
            element: {
               tag: 'div',
               attributes: {
                  id: 'ball' + i,
                  class: 'ball',
                  'data-lock': ''
               }
            }
         }
      });
   }
}

function notifyResize(uuid, screen) {
   var users = wams.getSnapshot(), i, len, listUUID;
   for (i = 0, len = users.length; i < len; i++) {
      listUUID = users[i].uuid;
      if (listUUID !== uuid) {
         wams.emit('RECV_MSG', listUUID, {
            source: '',
            data: {
               action: 'adjust_other_workspace',
               metadata: {
                  uuid: uuid,
                  screen: screen
               }
            }
         });
      }
   }
}

wams.listen(server);
var workspaceManager = new WorkspaceManager(wams);
wams.on(wams.when.new_connection, function(data) {
   var screen = Workspace.decode(data.description.screen);
   var users = wams.getSnapshot();
   var user = users[users.length - 1];
   var uuid = user.uuid;
   var adjustedScreen = workspaceManager.addScreen(uuid, screen);
   var notifiedDisableRemoteList = [];

   user.description.screen = Workspace.encode(adjustedScreen);

   if (adjustedScreen.x === 0 && adjustedScreen.y === 0) {
      drop4balls(uuid);
   }

   wams.emit('adjust_workspace', uuid, {
      screen: Workspace.encode(adjustedScreen)
   });
   notifyResize(uuid, Workspace.encode(adjustedScreen));

   wams.on('resize_screen', uuid, function(data) {
      var screen = Workspace.decode(data.data.screen);
      workspaceManager.resize(uuid, screen.width, screen.height);
      user.description.screen = data.data.screen;

      notifyResize(uuid, data.data.screen);
   });

   wams.on('disconnect', uuid, function() {
      workspaceManager.deleteScreen(uuid);
   });

   var handler = function(data) {
      if (!data.data.element.length) {
         return;
      }
      var elem = data.data.element[0], corner = [{}, {}, {}, {}], i, len,
         enableRemoteList = [], disableRemoteList = [],
         screen = workspaceManager.getScreen(uuid);
      elem.x += screen.x;
      elem.y += screen.y;
      corner[0].x = elem.x;
      corner[0].y = elem.y;
      corner[1].x = corner[0].x + elem.w;
      corner[1].y = corner[0].y;
      corner[2].x = corner[0].x;
      corner[2].y = corner[0].y + elem.h;
      corner[3].x = corner[0].x + elem.w;
      corner[3].y = corner[0].y + elem.h;

      for (i = 0, len = corner.length; i < len; i++) {
         var under = workspaceManager.under(corner[i].x, corner[i].y);
         under.forEach(function(el) {
            if (enableRemoteList.indexOf(el) === -1) {
               enableRemoteList.push(el);
            }
         });
      }

      disableRemoteList = workspaceManager.allExcept(enableRemoteList);
      if (enableRemoteList) {
         enableRemoteList.forEach(function(listUUID) {
            var indexOfNDRL = notifiedDisableRemoteList.indexOf(listUUID);
            if (indexOfNDRL > -1) {
               notifiedDisableRemoteList.splice(indexOfNDRL, 1);
            }

            if (uuid !== listUUID) {
               var abs = {
                  x: elem.x,
                  y: elem.y
               };
               elem.x -= workspaceManager.getScreen(listUUID).x;
               elem.y -= workspaceManager.getScreen(listUUID).y;
               wams.emit('enable_remote', listUUID, data);
               elem.x = abs.x;
               elem.y = abs.y;
            }
         });
      }
      if (disableRemoteList) {
         disableRemoteList.forEach(function(listUUID) {
            if (notifiedDisableRemoteList.indexOf(listUUID) === -1) {
               var msg = {
                  data: {
                     element: [
                        { attributes: { id:'' } }
                     ]
                  }
               }, i, len;
               for (i = 0, len = data.data.element.length; i < len; i++) {
                  msg.data.element[i].attributes.id = data.data.element[i].attributes.id;
               }
               wams.emit('disable_remote', listUUID, msg);
               notifiedDisableRemoteList.push(listUUID);
            }
         });
      }
   };

   wams.on('touch', uuid, handler);
   wams.on('drag', uuid, handler);
   wams.on('release', uuid, handler);
});

<|endoftext|>


<commit_before>import {
  formatFrame,
  formatTime,
  frameToSeconds,
  roundToFrame
} from '../../../src/lib/video'

describe('video', () => {
  describe('Mount', () => {
    it('roundToFrame', () => {
      expect(roundToFrame(1, 24)).toBe(1.0008)
      expect(roundToFrame(0.95, 24)).toBe(0.9591)
      expect(roundToFrame(2, 24)).toBe(2.0016)
      expect(roundToFrame(60, 24)).toBe(60.0063)
      expect(roundToFrame(60, 25)).toBe(60)
      expect(roundToFrame(50, 25)).toBe(50)
      expect(roundToFrame(49.1, 25)).toBe(49.12)
      expect(roundToFrame(49.13, 25)).toBe(49.12)
      expect(roundToFrame(49.14, 25)).toBe(49.16)
      expect(roundToFrame(49.15, 25)).toBe(49.16)
      expect(roundToFrame(49.2, 25)).toBe(49.2)
      expect(roundToFrame(49.3, 25)).toBe(49.32)
      expect(roundToFrame(49.4, 25)).toBe(49.4)
    })

    it('frameToSeconds', () => {
      expect(frameToSeconds(1, { fps: 24 })).toBe(0.042)
      expect(frameToSeconds(10, { fps: 24 })).toBe(0.417)
      expect(frameToSeconds(24, { fps: 24 })).toBe(1)
      expect(frameToSeconds(48, { fps: 24 })).toBe(2)
      expect(frameToSeconds(32, { fps: 24 })).toBe(1.333)
      expect(frameToSeconds(47, { fps: 24 })).toBe(1.958)
      expect(frameToSeconds(1, { fps: 25 })).toBe(0.04)
      expect(frameToSeconds(10, { fps: 25 })).toBe(0.4)
      expect(frameToSeconds(25, { fps: 25 })).toBe(1)
      expect(frameToSeconds(50, { fps: 25 })).toBe(2)
      expect(frameToSeconds(32, { fps: 25 })).toBe(1.28)
      expect(frameToSeconds(47, { fps: 25 })).toBe(1.88)
    })

    it('formatFrame', () => {
      expect(formatFrame(1)).toBe('001')
      expect(formatFrame(123)).toBe('123')
    })

    it('formatTime', () => {
      expect(formatTime(0.091)).toBe('00:00.091')
      expect(formatTime(0.001)).toBe('00:00.001')
      expect(formatTime(0.900)).toBe('00:00.900')
      expect(formatTime(0.960)).toBe('00:00.960')
      expect(formatTime(0.966)).toBe('00:00.966')
      expect(formatTime(2.416)).toBe('00:02.416')
      expect(formatTime(2.016)).toBe('00:02.016')
      expect(formatTime(60.018)).toBe('01:00.018')
      expect(formatTime(362.018)).toBe('06:02.018')
    })
  })
})
<commit_msg>[qa] code scrub<commit_after>import {
  formatFrame,
  formatTime,
  frameToSeconds,
  roundToFrame
} from '../../../src/lib/video'

describe('video', () => {
  it('roundToFrame', () => {
    expect(roundToFrame(1, 24)).toBe(1.0008)
    expect(roundToFrame(0.95, 24)).toBe(0.9591)
    expect(roundToFrame(2, 24)).toBe(2.0016)
    expect(roundToFrame(60, 24)).toBe(60.0063)
    expect(roundToFrame(60, 25)).toBe(60)
    expect(roundToFrame(50, 25)).toBe(50)
    expect(roundToFrame(49.1, 25)).toBe(49.12)
    expect(roundToFrame(49.13, 25)).toBe(49.12)
    expect(roundToFrame(49.14, 25)).toBe(49.16)
    expect(roundToFrame(49.15, 25)).toBe(49.16)
    expect(roundToFrame(49.2, 25)).toBe(49.2)
    expect(roundToFrame(49.3, 25)).toBe(49.32)
    expect(roundToFrame(49.4, 25)).toBe(49.4)
  })

  it('frameToSeconds', () => {
    expect(frameToSeconds(1, { fps: 24 })).toBe(0.042)
    expect(frameToSeconds(10, { fps: 24 })).toBe(0.417)
    expect(frameToSeconds(24, { fps: 24 })).toBe(1)
    expect(frameToSeconds(48, { fps: 24 })).toBe(2)
    expect(frameToSeconds(32, { fps: 24 })).toBe(1.333)
    expect(frameToSeconds(47, { fps: 24 })).toBe(1.958)
    expect(frameToSeconds(1, { fps: 25 })).toBe(0.04)
    expect(frameToSeconds(10, { fps: 25 })).toBe(0.4)
    expect(frameToSeconds(25, { fps: 25 })).toBe(1)
    expect(frameToSeconds(50, { fps: 25 })).toBe(2)
    expect(frameToSeconds(32, { fps: 25 })).toBe(1.28)
    expect(frameToSeconds(47, { fps: 25 })).toBe(1.88)
  })

  it('formatFrame', () => {
    expect(formatFrame(1)).toBe('001')
    expect(formatFrame(123)).toBe('123')
  })

  it('formatTime', () => {
    expect(formatTime(0.091)).toBe('00:00.091')
    expect(formatTime(0.001)).toBe('00:00.001')
    expect(formatTime(0.900)).toBe('00:00.900')
    expect(formatTime(0.960)).toBe('00:00.960')
    expect(formatTime(0.966)).toBe('00:00.966')
    expect(formatTime(2.416)).toBe('00:02.416')
    expect(formatTime(2.016)).toBe('00:02.016')
    expect(formatTime(60.018)).toBe('01:00.018')
    expect(formatTime(362.018)).toBe('06:02.018')
  })
})
<|endoftext|>


<commit_before>const MongoClient = require('mongodb').MongoClient;
var dbUrl = "mongodb://localhost:27017/";

MongoClient.connect(dbUrl, {
    useNewUrlParser: true,
    useUnifiedTopology: true
}, function (err, connection) {
    if (err) throw err;
    const db = connection.db('webstore4');
    const product1 = {
        "name": "Best Headphones",
        "price": 16.5,
        "description": "Bluetooth headphones with good quality",
        "imageUrl": "https://www.logitechg.com/content/dam/products/gaming/mice/g402-hyperion-fury-fps-gaming-mouse/910-004068/g402-hyperion-fury-ultra-fast-fps-gaming-mouse30.png.imgw.902.902.png"
    }
    db.collection('products').insertOne(product1, function (err, res) {
        if (err) throw err;
        if (res.insertedCount == 1) {
            console.log(`New product inserted with ID: ${res.insertedId}`);
            // console.log(res);
        }
        connection.close();
    })
    console.log("Database connected!");
});<commit_msg>small chanhges<commit_after>const MongoClient = require('mongodb').MongoClient;
var dbUrl = "mongodb://localhost:27017/";

MongoClient.connect(dbUrl, {
    useNewUrlParser: true,
    useUnifiedTopology: true
}, function (err, connection) {
    if (err) throw err;
    const db = connection.db('webstore_fmi_2022');
    const product1 = {
        "name": "Best Headphones",
        "price": 16.5,
        "description": "Bluetooth headphones with good quality",
        "imageUrl": "https://www.logitechg.com/content/dam/products/gaming/mice/g402-hyperion-fury-fps-gaming-mouse/910-004068/g402-hyperion-fury-ultra-fast-fps-gaming-mouse30.png.imgw.902.902.png"
    }
    db.collection('products').insertOne(product1, function (err, res) {
        if (err) throw err;
        if (res.insertedCount == 1) {
            console.log(`New product inserted with ID: ${res.insertedId}`);
            // console.log(res);
        }
        connection.close();
    })
    console.log("Database connected!");
});<|endoftext|>


<commit_before>'use strict';
var ss;

function put(s) {
	ss.push(s)
}

function indent(level) {
	while (level--)
		put('\t')
}

function block(a, level) {
	put('{\n')
	if (a.type == 'BlockStatement')
		for (var b of a.body)
			stmt(b, level + 1)
	else
		stmt(a, level + 1)
	indent(level)
	put('}')
}

function expr(a, level) {
	switch (a.type) {
	case 'ArrayExpression':
		put('[\n')
		for (var b of a.elements) {
			indent(level + 1)
			expr(b, level + 1)
			put(',\n')
		}
		indent(level)
		put(']')
		break
	case 'AssignmentExpression':
	case 'BinaryExpression':
	case 'LogicalExpression':
		expr(a.left, level)
		put(' ' + a.operator + ' ')
		expr(a.right, level)
		break
	case 'CallExpression':
		expr(a.callee, level)
		put('(')
		for (var i = 0; i < a.arguments.length; i++) {
			if (i)
				put(', ')
			expr(a.arguments[i], level)
		}
		put(')')
		break
	case 'ConditionalExpression':
		expr(a.test, level)
		put(' ? ')
		expr(a.consequent, level)
		put(' : ')
		expr(a.alternate, level)
		break
	case 'FunctionExpression':
		put('function (')
		for (var i = 0; i < a.params.length; i++) {
			if (i)
				put(', ')
			expr(a.params[i], level)
		}
		put(') ')
		block(a.body, level)
		break
	case 'Identifier':
		put(a.name)
		break
	case 'Literal':
		put(a.raw)
		break
	case 'MemberExpression':
		expr(a.object, level)
		if (a.computed) {
			put('[')
			expr(a.property, level)
			put(']')
		} else {
			put('.')
			expr(a.property, level)
		}
		break
	case 'ObjectExpression':
		put('{\n')
		for (var b of a.properties) {
			indent(level + 1)
			expr(b, level + 1)
			put(',\n')
		}
		indent(level)
		put('}')
		break
	case 'Property':
		expr(a.key, level)
		put(': ')
		expr(a.value, level)
		break
	case 'SequenceExpression':
		for (var i = 0; i < a.expressions.length; i++) {
			if (i)
				put(', ')
			expr(a.expressions[i], level)
		}
		break
	case 'UnaryExpression':
		put(a.operator)
		expr(a.argument, level)
		break
	case 'UpdateExpression':
		if (a.prefix) {
			put(a.operator)
			expr(a.argument, level)
		} else {
			expr(a.argument, level)
			put(a.operator)
		}
		break
	case 'VariableDeclaration':
		put('var ')
		for (var i = 0; i < a.declarations.length; i++) {
			if (i)
				put(', ')
			expr(a.declarations[i], level)
		}
		break
	case 'VariableDeclarator':
		put(a.id.name)
		if (a.init) {
			put(' = ')
			expr(a.init, level)
		}
		break
	default:
		console.assert(0, a)
	}
}

function stmt(a, level) {
	switch (a.type) {
	case 'BlockStatement':
		for (var b of a.body)
			stmt(b, level + 1)
		break
	case 'BreakStatement':
		indent(level)
		put('break')
		if (a.label) {
			put(' ')
			put(a.label.name)
		}
		put(';\n')
		break
	case 'ContinueStatement':
		indent(level)
		put('continue')
		if (a.label) {
			put(' ')
			put(a.label.name)
		}
		put(';\n')
		break
	case 'DoWhileStatement':
		indent(level)
		put('do ')
		block(a.body, level)
		indent(level)
		put(' while (')
		expr(a.test, level)
		put(');\n')
		break
	case 'EmptyStatement':
		indent(level)
		put(';\n')
		break
	case 'ExpressionStatement':
		indent(level)
		expr(a.expression, level)
		put(';\n')
		break
	case 'ForStatement':
		indent(level)
		put('for (')
		expr(a.init, level)
		put('; ')
		expr(a.test, level)
		put('; ')
		expr(a.update, level)
		put(') ')
		block(a.body, level)
		put('\n')
		break
	case 'FunctionDeclaration':
		indent(level)
		put('function ' + a.id.name + '(')
		for (var i = 0; i < a.params.length; i++) {
			if (i)
				put(', ')
			expr(a.params[i], level)
		}
		put(') ')
		block(a.body, level)
		put('\n')
		break
	case 'IfStatement':
		indent(level)
		put('if (')
		expr(a.test, level)
		put(') ')
		block(a.consequent, level)
		if (a.alternate) {
			put(' else ')
			block(a.alternate, level)
		}
		put('\n')
		break
	case 'LabeledStatement':
		stmt(a.body, loop, a.label.name)
		break
	case 'Program':
		for (var b of a.body)
			stmt(b, level)
		break
	case 'ReturnStatement':
		indent(level)
		put('return')
		if (a.argument) {
			put(' ')
			expr(a.argument, level)
		}
		put(';\n')
		break
	case 'SwitchStatement':
		indent(level)
		put('switch (')
		expr(a.discriminant, level)
		put(') {\n')
		for (var c of a.cases) {
			indent(level)
			put('case ')
			expr(c.test, level)
			put(':\n')
			for (var b of c.consequent)
				stmt(b, level + 1)
		}
		indent(level)
		put('}\n')
		break
	case 'VariableDeclaration':
		indent(level)
		put('var ')
		for (var i = 0; i < a.declarations.length; i++) {
			if (i)
				put(', ')
			expr(a.declarations[i], level)
		}
		put(';\n')
		break
	case 'WhileStatement':
		indent(level)
		put('while (')
		expr(a.test, level)
		put(') ')
		block(a.body, level)
		put('\n')
		break
	default:
		console.assert(0, a)
	}
}

function format(a) {
	ss = []
	stmt(a, 0)
	return ss.join('')
}
exports.format = format
<commit_msg>empty block<commit_after>'use strict';
var ss;

function put(s) {
	ss.push(s)
}

function indent(level) {
	while (level--)
		put('\t')
}

function block(a, level) {
	switch (a.type) {
	case 'BlockStatement':
		if (a.body.length == 0 || a.body.length == 1 && a.body[0].type == 'EmptyStatement') {
			put('{}')
			break
		}
		put('{\n')
		for (var b of a.body)
			stmt(b, level + 1)
		put('}')
		break
	case 'EmptyStatement':
		put('{}')
		break
	default:
		put('{\n')
		stmt(a, level + 1)
		put('}')
	}
	indent(level)
}

function expr(a, level) {
	switch (a.type) {
	case 'ArrayExpression':
		put('[\n')
		for (var b of a.elements) {
			indent(level + 1)
			expr(b, level + 1)
			put(',\n')
		}
		indent(level)
		put(']')
		break
	case 'AssignmentExpression':
	case 'BinaryExpression':
	case 'LogicalExpression':
		expr(a.left, level)
		put(' ' + a.operator + ' ')
		expr(a.right, level)
		break
	case 'CallExpression':
		expr(a.callee, level)
		put('(')
		for (var i = 0; i < a.arguments.length; i++) {
			if (i)
				put(', ')
			expr(a.arguments[i], level)
		}
		put(')')
		break
	case 'ConditionalExpression':
		expr(a.test, level)
		put(' ? ')
		expr(a.consequent, level)
		put(' : ')
		expr(a.alternate, level)
		break
	case 'FunctionExpression':
		put('function (')
		for (var i = 0; i < a.params.length; i++) {
			if (i)
				put(', ')
			expr(a.params[i], level)
		}
		put(') ')
		block(a.body, level)
		break
	case 'Identifier':
		put(a.name)
		break
	case 'Literal':
		put(a.raw)
		break
	case 'MemberExpression':
		expr(a.object, level)
		if (a.computed) {
			put('[')
			expr(a.property, level)
			put(']')
		} else {
			put('.')
			expr(a.property, level)
		}
		break
	case 'ObjectExpression':
		put('{\n')
		for (var b of a.properties) {
			indent(level + 1)
			expr(b, level + 1)
			put(',\n')
		}
		indent(level)
		put('}')
		break
	case 'Property':
		expr(a.key, level)
		put(': ')
		expr(a.value, level)
		break
	case 'SequenceExpression':
		for (var i = 0; i < a.expressions.length; i++) {
			if (i)
				put(', ')
			expr(a.expressions[i], level)
		}
		break
	case 'UnaryExpression':
		put(a.operator)
		expr(a.argument, level)
		break
	case 'UpdateExpression':
		if (a.prefix) {
			put(a.operator)
			expr(a.argument, level)
		} else {
			expr(a.argument, level)
			put(a.operator)
		}
		break
	case 'VariableDeclaration':
		put('var ')
		for (var i = 0; i < a.declarations.length; i++) {
			if (i)
				put(', ')
			expr(a.declarations[i], level)
		}
		break
	case 'VariableDeclarator':
		put(a.id.name)
		if (a.init) {
			put(' = ')
			expr(a.init, level)
		}
		break
	default:
		console.assert(0, a)
	}
}

function stmt(a, level) {
	switch (a.type) {
	case 'BlockStatement':
		for (var b of a.body)
			stmt(b, level + 1)
		break
	case 'BreakStatement':
		indent(level)
		put('break')
		if (a.label) {
			put(' ')
			put(a.label.name)
		}
		put(';\n')
		break
	case 'ContinueStatement':
		indent(level)
		put('continue')
		if (a.label) {
			put(' ')
			put(a.label.name)
		}
		put(';\n')
		break
	case 'DoWhileStatement':
		indent(level)
		put('do ')
		block(a.body, level)
		indent(level)
		put(' while (')
		expr(a.test, level)
		put(');\n')
		break
	case 'EmptyStatement':
		indent(level)
		put(';\n')
		break
	case 'ExpressionStatement':
		indent(level)
		expr(a.expression, level)
		put(';\n')
		break
	case 'ForStatement':
		indent(level)
		put('for (')
		expr(a.init, level)
		put('; ')
		expr(a.test, level)
		put('; ')
		expr(a.update, level)
		put(') ')
		block(a.body, level)
		put('\n')
		break
	case 'FunctionDeclaration':
		indent(level)
		put('function ' + a.id.name + '(')
		for (var i = 0; i < a.params.length; i++) {
			if (i)
				put(', ')
			expr(a.params[i], level)
		}
		put(') ')
		block(a.body, level)
		put('\n')
		break
	case 'IfStatement':
		indent(level)
		put('if (')
		expr(a.test, level)
		put(') ')
		block(a.consequent, level)
		if (a.alternate) {
			put(' else ')
			block(a.alternate, level)
		}
		put('\n')
		break
	case 'LabeledStatement':
		stmt(a.body, loop, a.label.name)
		break
	case 'Program':
		for (var b of a.body)
			stmt(b, level)
		break
	case 'ReturnStatement':
		indent(level)
		put('return')
		if (a.argument) {
			put(' ')
			expr(a.argument, level)
		}
		put(';\n')
		break
	case 'SwitchStatement':
		indent(level)
		put('switch (')
		expr(a.discriminant, level)
		put(') {\n')
		for (var c of a.cases) {
			indent(level)
			put('case ')
			expr(c.test, level)
			put(':\n')
			for (var b of c.consequent)
				stmt(b, level + 1)
		}
		indent(level)
		put('}\n')
		break
	case 'VariableDeclaration':
		indent(level)
		put('var ')
		for (var i = 0; i < a.declarations.length; i++) {
			if (i)
				put(', ')
			expr(a.declarations[i], level)
		}
		put(';\n')
		break
	case 'WhileStatement':
		indent(level)
		put('while (')
		expr(a.test, level)
		put(') ')
		block(a.body, level)
		put('\n')
		break
	default:
		console.assert(0, a)
	}
}

function format(a) {
	ss = []
	stmt(a, 0)
	return ss.join('')
}
exports.format = format
<|endoftext|>


<commit_before>import Flickr from "flickrapi"
import Promise from "bluebird"
import fs from "fs"

const flickrOptions = {
  api_key: process.env.FLICKR_API_KEY,
  secret: process.env.FLICKR_SHARED_SECRET,
  user_id: process.env.FLICKR_USER_ID,
  access_token: process.env.FLICKR_ACCESS_TOKEN,
  access_token_secret: process.env.FLICKR_ACCESS_TOKEN_SECRET,
}

function lookupPhoto(id) {
  const filename = `flickr-data/${id}.json`
  if (fs.existsSync(filename)) {
    return Promise.promisify(fs.readFile)(filename)
      .then(data => JSON.parse(data))
      .catch(err => console.error(err))
  }

  return Promise.promisify(Flickr.tokenOnly)(flickrOptions)
    .then(flickr => (
      Promise.promisify(flickr.photos.getSizes)({ photo_id: id })
        .then(result => result.sizes.size)
        .then(sizeArray => sizeArray.reduce((memo, val) => { memo[val.label] = val; return memo }, {})) // eslint-disable-line no-param-reassign
        .then(sizes => {
          Promise.promisify(fs.writeFile)(filename, JSON.stringify(sizes, null, 2))
            .catch(err => console.error(err))
          return sizes
        })
        .catch(err => console.error(err))
    )
  )
}

export default function getImageData(id) {
  return lookupPhoto(id)
    .then(sizes => sizes["Large 1600"] ||
                   sizes.Large ||
                   sizes["Medium 800"] ||
                   sizes["Medium 640"] ||
                   sizes.Medium)
    .then(size => (
      {
        height: size.height,
        width: size.width,
        source: size.source,
      }
    ))
}
<commit_msg>Fetch original size images from flickr<commit_after>import Flickr from "flickrapi"
import Promise from "bluebird"
import fs from "fs"
import childProcess from "child_process"
import path from "path"

Promise.promisifyAll(fs)
Promise.promisifyAll(Flickr)

const flickrOptions = {
  api_key: process.env.FLICKR_API_KEY,
  secret: process.env.FLICKR_SHARED_SECRET,
  user_id: process.env.FLICKR_USER_ID,
  access_token: process.env.FLICKR_ACCESS_TOKEN,
  access_token_secret: process.env.FLICKR_ACCESS_TOKEN_SECRET,
}

function flickrDataFromDisk(id) {
  return fs.readFileAsync(path.resolve(__dirname, `../../flickr-data/${id}.json`))
    .then(data => JSON.parse(data))
    .catch(err => console.error(err))
}

function objectifySizeArray(sizeArray) {
  return sizeArray.reduce((memo, val) => {
    memo[val.label] = val // eslint-disable-line no-param-reassign
    return memo
  }, {})
}

function lookupPhoto(id) {
  const filename = `flickr-data/${id}.json`
  if (fs.existsSync(filename)) return flickrDataFromDisk(id)

  return Flickr.tokenOnlyAsync(flickrOptions)
    .then(flickr => (
      flickr.photos.getSizesAsync({ photo_id: id })
        .then(result => result.sizes.size)
        .then(objectifySizeArray)
        .then(sizes => {
          fs.writeFileAsync(filename, JSON.stringify(sizes, null, 2)).catch(err => console.error(err))
          return sizes
        })
        .catch(err => console.error(err))
    )
  )
}

export const cachePath = (id) => path.resolve(`cache/flickr/${id.slice(0, 2)}/${id}.jpg`)

const largestSize = sizes => (
  sizes.Original ||
  sizes["Large 2048"] ||
  sizes["Large 1600"] ||
  sizes.Large ||
  sizes["Medium 800"] ||
  sizes["Medium 640"] ||
  sizes.Medium
)

async function download(url, output) {
  childProcess.execSync(`curl --silent --create-dirs --compressed --output ${output} ${url}`)
  console.log(`downloaded ${output}`)
}

function cacheImg(id) {
  const outputPath = cachePath(id)
  if (fs.existsSync(outputPath)) return Promise.resolve()

  return flickrDataFromDisk(id)
    .then(largestSize)
    .then(size => size.source)
    .then(url => download(url, outputPath))
}

export default function getImageData(id) {
  cacheImg(id)
  return lookupPhoto(id)
   .then(largestSize)
   .then(size => ({
     height: size.height,
     width: size.width,
     source: cachePath(id),
   }))
}
<|endoftext|>


<commit_before>/*
 *  format.js
 *
 *  David Janes
 *  IOTDB.org
 *  206-01-09
 *
 *  Copyright [2013-2016] [David P. Janes]
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

"use strict";

const _ = require('iotdb-helpers');

const logger = _.logger.make({
    name: "iotdb-format",
    module: "format",
});

/**
 *  LOTS OF WORK NEEDED FOR NON-STRINGS: REFERENCE DJANGO
 */
const _format_string = function (template, d, fd, dotpath) {
    if (dotpath) {
        template = template.replace(/[.]/g, "/")
    }

    d = _.d.compose.shallow(d, {});
    fd = _.d.compose.shallow(fd, {
        upper: s => s.toUpperCase(),
        lower: s => s.toLowerCase(),
        binary: (s, for_false, for_true) => _.coerce.to.Boolean(s, false) ? for_true : for_false,
        'default': (s, otherwise) => (s.length === 0) ? otherwise : s,
        json: (s, indent) => JSON.stringify(s, null, indent || 0),
    });

    const _normalize = function (s, is_final) {
        if (s === undefined) {
            return "";
        } else if (s === null) {
            return "";
        } else if (is_final && !_.is.String(s)) {
            return "" + s;
        } else {
            return s;
        }
    };

    const _pipe = function (value, expression) {
        var match = expression.match(/^:(.*)$/);
        if (match) {
            return fd["default"](value, match[1]);
        }

        match = expression.match(/^([-A-Za-z0-9_]+)([(]([^]*)[)])?/);
        if (!match) {
            throw new Error("bad pipe expression: " + expression);
        }

        const fname = match[1];
        const f = _.d.get(fd, fname);
        if (!f) {
            throw new Error("bad pipe function - not found: " + fname);
        }

        var inners = [];
        if (match[3]) {
            inners = JSON.parse("[" + match[3].replace(/'/g, '"') + "]");
        }

        inners.splice(0, 0, value);

        return _normalize(f.apply(f, inners));
    };

    const _expression_replacer = function (match, variable) {
        const inner = variable.replace(/^\s+/, '').replace(/\s+$/, '');
        const parts = inner.split(/[|]/g);
        variable = parts[0];
        var value = _normalize(_.d.get(d, variable));

        parts.splice(0, 1);

        parts.map(function (part) {
            value = _pipe(value, part);
        });

        return _normalize(value, true);

    };

    return template.replace(/{{(.*?)}}/g, _expression_replacer);
};

/**
 *  This is similar to format, except it will walk the object
 *  looking for strings to replace
 */
const _format_object = function (template_object, d, fd, dotpath) {
    return _.d.transform(template_object, {
        value: function (value, paramd) {
            if (!_.is.String(value)) {
                return value;
            }

            return format(value, d, fd, dotpath);
        },
    });
};

const format = function (template, d, fd) {
    if (_.is.String(template)) {
        return _format_string(template, d, fd);
    } else {
        return _format_object(template, d, fd);
    }
};

const format_dotpath = function (template, d, fd) {
    if (_.is.String(template)) {
        return _format_string(template, d, fd, true);
    } else {
        return _format_object(template, d, fd, true);
    }
};

/**
 *  API
 */
exports.format = format;
exports.format.dotpath = format_dotpath;
<commit_msg>bug fixes<commit_after>/*
 *  format.js
 *
 *  David Janes
 *  IOTDB.org
 *  206-01-09
 *
 *  Copyright [2013-2016] [David P. Janes]
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

"use strict";

const _ = require('iotdb-helpers');

const logger = _.logger.make({
    name: "iotdb-format",
    module: "format",
});

/**
 *  LOTS OF WORK NEEDED FOR NON-STRINGS: REFERENCE DJANGO
 */
const _format_string = function (template, d, fd, dotpath) {
    if (dotpath) {
        template = template.replace(/[.]/g, "/")
    }

    d = _.d.compose.shallow(d, {});
    fd = _.d.compose.shallow(fd, {
        upper: s => s.toUpperCase(),
        lower: s => s.toLowerCase(),
        binary: (s, for_false, for_true) => _.coerce.to.Boolean(s, false) ? for_true : for_false,
        'default': (s, otherwise) => (s.length === 0) ? otherwise : s,
        json: (s, indent) => JSON.stringify(s, null, indent || 0),
    });

    const _normalize = function (s, is_final) {
        if (s === undefined) {
            return "";
        } else if (s === null) {
            return "";
        } else if (is_final && !_.is.String(s)) {
            return "" + s;
        } else {
            return s;
        }
    };

    const _pipe = function (value, expression) {
        var match = expression.match(/^:(.*)$/);
        if (match) {
            return fd["default"](value, match[1]);
        }

        match = expression.match(/^([-A-Za-z0-9_]+)([(]([^]*)[)])?/);
        if (!match) {
            throw new Error("bad pipe expression: " + expression);
        }

        const fname = match[1];
        const f = _.d.get(fd, fname);
        if (!f) {
            throw new Error("bad pipe function - not found: " + fname);
        }

        var inners = [];
        if (match[3]) {
            inners = JSON.parse("[" + match[3].replace(/'/g, '"') + "]");
        }

        inners.splice(0, 0, value);

        return _normalize(f.apply(f, inners));
    };

    const _expression_replacer = function (match, variable) {
        const inner = variable.replace(/^\s+/, '').replace(/\s+$/, '');
        const parts = inner.split(/[|]/g);
        variable = parts[0];
        var value = _normalize(_.d.get(d, variable));

        parts.splice(0, 1);

        parts.map(function (part) {
            value = _pipe(value, part);
        });

        return _normalize(value, true);

    };

    return template.replace(/{{(.*?)}}/g, _expression_replacer);
};

/**
 *  This is similar to format, except it will walk the object
 *  looking for strings to replace
 */
const _format_object = function (template_object, d, fd, dotpath) {
    return _.d.transform(template_object, {
        value: function (value, paramd) {
            if (!_.is.String(value)) {
                return value;
            }

            return _format_string(value, d, fd, dotpath);
        },
    });
};

const format = function (template, d, fd) {
    if (_.is.String(template)) {
        return _format_string(template, d, fd, false);
    } else {
        return _format_object(template, d, fd, false);
    }
};

const format_dotpath = function (template, d, fd) {
    if (_.is.String(template)) {
        return _format_string(template, d, fd, true);
    } else {
        return _format_object(template, d, fd, true);
    }
};

/**
 *  API
 */
exports.format = format;
exports.format.dotpath = format_dotpath;
<|endoftext|>


<commit_before>'use strict';

const path = require('path');
const github = require('./github');
const Ajv = require('ajv');
const ajv = new Ajv({
  allErrors: true,
  useDefaults: true,
  schemas: {
    defs: require('../../schemas/defs.json'),
    rule: require('../../schemas/rule.json'),
    config: require('../../schemas/config.json')
  }
});

const execute = module.exports = {
  async checkRules (config, options={}) {
    config = execute.prepareConfig(config);
    github.setOptions(options);
    const repoSourceRules = await execute.prepareRepoRules(config, options);
    return execute.checkPreparedRules(repoSourceRules);
  },

  async checkPreparedRules (repoSourceRules) {
    const results = {};
    for (const repoOrg in repoSourceRules) {
      const repoResults = results[repoOrg] = {};
      const repoSources = repoSourceRules[repoOrg];
      for (const source in repoSources) {
        const sourceRules = repoSources[source];
        const sourceData = await github.getSource[source](repoOrg);
        for (const ruleName in sourceRules) {
          const ruleConfigs = sourceRules[ruleName];
          repoResults[ruleName] = await checkRule(ruleName, ruleConfigs, sourceData);
        }
      }
    }
    return results;
  },

  async prepareRepoRules (config, options={}) {
    const repoSourceRules = {};
    const {org, rules, organizations, teams, repositories} = config;

    if (rules) {
      // global rules
      const repos = await github.getRepos.organization(org);
      addRepos(repos, rules);
    }

    if (organizations) {
      // organization-specific rules
      for (const orgName in organizations) {
        const repos = await github.getRepos.organization(orgName);
        addRepos(repos, organizations[orgName].rules);
      }
    }

    if (teams) {
      // team specific rules
      for (const teamName in teams) {
        let [orgName, shortTeamName] = teamName.split('/');
        if (!shortTeamName) {
          orgName = org;
          shortTeamName = teamName;
        }
        const repos = await github.getRepos.team(orgName, shortTeamName);
        addRepos(repos, teams[teamName].rules);
      }
    }

    if (repositories) {
      for (const repoName in repositories) {
        const fullRepoName = /\//.test(repoName) ? repoName : org + '/' + repoName;
        const repoRules = repositories[repoName].rules;
        addRepoRules(fullRepoName, repoRules);
      }
    }

    // clean-up
    for (const repoOrg in repoSourceRules) {
      const repoSources = repoSourceRules[repoOrg];
      for (const source in repoSources) {
        if (Object.keys(repoSources[source]).length == 0)
          delete repoSources[source];
      }
      if (Object.keys(repoSources).length == 0)
        delete repoSourceRules[repoOrg];
    }

    return repoSourceRules;

    function addRepos(repos, repoRules) {
      for (const repo of repos) {
        const updatedAt = new Date(repo.updated_at);
        const pushedAt = new Date(repo.pushed_at);
        const inRange = (!options.after || updatedAt >= options.after || pushedAt >= options.after) &&
                        (!options.before || (updatedAt < options.before && pushedAt < options.before));
        if (inRange) addRepoRules(repo.full_name, repoRules);
      }
    }

    function addRepoRules(fullRepoName, repoRules) {
      const repoSources = repoSourceRules[fullRepoName] = repoSourceRules[fullRepoName] || {};
      for (const ruleName in repoRules) {
        const ruleOptions = repoRules[ruleName];
        const ruleDefinition = execute.getRuleDefinition(ruleName);
        const source = ruleDefinition.source;
        const sourceRules = repoSources[source] = repoSources[source] || {};
        // multiple configs per rule - no longer supported
        // sourceRules[ruleName] = sourceRules[ruleName] || [];
        // sourceRules[ruleName].push(ruleOptions);

        // config for smaller scope overrides config for bigger scope
        if (ruleOptions.mode === 0)
          delete sourceRules[ruleName];
        else
          sourceRules[ruleName] = [ruleOptions];
      }
    }
  },

  normaliseRuleOptions(options) {
    switch (typeof options) {
      case 'number': {
        return { mode: options };
      }
      case 'object': {
        if (!Array.isArray(options)) return options;
        const opts = { mode: options[0] };
        for (const item of options) {
          switch (typeof item) {
            case 'string': opts[item] = true; break;
            case 'object': copy(item, opts); break;
          }
        }
        return opts;
      }
    }
  },

  getRuleDefinition(ruleName) {
    try { return require(path.join('..', 'rules', ruleName)); }
    catch(e) { throw new Error(`cannot find rule ${ruleName}: ${e.message}`); }
  },

  prepareConfig(config) {
    config = JSON.parse(JSON.stringify(config));
    callValidate(ajv.getSchema('config'), config, 'config');

    const validate = ajv.getSchema('rule');
    const {organizations, teams, repositories} = config;
    const ruleNames = {};
    const validateRule = {};
    addRules(config, 'global rules');
    addRulesFromMap(organizations, 'organization');
    addRulesFromMap(teams, 'team');
    addRulesFromMap(repositories, 'repository');
    for (const name in ruleNames) {
      let rule = execute.getRuleDefinition(name);
      callValidate(validate, rule, `rule "${name}"`);
    }

    return config;

    function addRules({rules}={}, scope) {
      if (rules) {
        for (const name in rules) {
          rules[name] = execute.normaliseRuleOptions(rules[name]);
          if (!validateRule[name]) {
            const ruleSchema = execute.getRuleDefinition(name).schema;
            validateRule[name] = ajv.compile(ruleSchema);
          }
          callValidate(validateRule[name], rules[name], `config for rule "${name}" in ${scope}`);
          ruleNames[name] = true;
        }
      }
    }

    function addRulesFromMap(group, groupName) {
      if (group) {
        for (const item in group)
          addRules(group[item], `${groupName} "${item}"`);
      }
    }
  }
};

function callValidate(validate, data, title) {
  if (!validate(data))
    throw new Error(`${title} is invalid: ${ajv.errorsText(validate.errors)}`);
}

async function checkRule(ruleName, ruleConfigs, sourceData) {
  const ruleDefinition = execute.getRuleDefinition(ruleName);
  if (typeof ruleDefinition.check != 'function') {
    const schema = ruleDefinition.check;
    ruleDefinition.check = createCheckFunction(ruleName, schema);
  }
  const results = [];
  for (const ruleCfg of ruleConfigs) {
    const result = await ruleDefinition.check(ruleCfg, sourceData, github);
    if (!result.valid) {
      result.mode = ruleCfg.mode;
      results.push(result);
    }
  }
  return results;
}

function createCheckFunction(ruleName, schema) {
  const validate = ajv.compile(schema);
  return function (ruleCfg, sourceData) {
    const valid = validate(sourceData);
    const result = {valid};
    if (!valid) {
      result.message = 'not satisfied';
      result.errors = ajv.errorsText(validate.errors);
    }
    return result;
  };
}

function copy(o, to) {
  to = to || {};
  for (const key in o) to[key] = o[key];
  return to;
}
<commit_msg>refactor: prepareRepoRules<commit_after>'use strict';

const path = require('path');
const github = require('./github');
const Ajv = require('ajv');
const ajv = new Ajv({
  allErrors: true,
  useDefaults: true,
  schemas: {
    defs: require('../../schemas/defs.json'),
    rule: require('../../schemas/rule.json'),
    config: require('../../schemas/config.json')
  }
});

const execute = module.exports = {
  async checkRules (config, options={}) {
    config = execute.prepareConfig(config);
    github.setOptions(options);
    const repoSourceRules = await execute.prepareRepoRules(config, options);
    return execute.checkPreparedRules(repoSourceRules);
  },

  async checkPreparedRules (repoSourceRules) {
    const results = {};
    for (const repoOrg in repoSourceRules) {
      const repoResults = results[repoOrg] = {};
      const repoSources = repoSourceRules[repoOrg];
      for (const source in repoSources) {
        const sourceRules = repoSources[source];
        const sourceData = await github.getSource[source](repoOrg);
        for (const ruleName in sourceRules) {
          const ruleConfigs = sourceRules[ruleName];
          repoResults[ruleName] = await checkRule(ruleName, ruleConfigs, sourceData);
        }
      }
    }
    return results;
  },

  async prepareRepoRules (config, options={}) {
    const repoSourceRules = {};
    const org = config.org;

    await addGlobalRules();
    await addOrganisations();
    await addTeams();
    await addRepositories();
    removeDisabledRules();

    return repoSourceRules;

    async function addGlobalRules() {
      if (config.rules) {
        const repos = await github.getRepos.organization(org);
        addRepos(repos, config.rules);
      }
    }

    async function addOrganisations() {
      const organizations = config.organizations;
      if (organizations) {
        // organization-specific rules
        for (const orgName in organizations) {
          const repos = await github.getRepos.organization(orgName);
          addRepos(repos, organizations[orgName].rules);
        }
      }
    }

    async function addTeams() {
      const teams = config.teams;
      if (teams) {
        // team specific rules
        for (const teamName in teams) {
          let [orgName, shortTeamName] = teamName.split('/');
          if (!shortTeamName) {
            orgName = org;
            shortTeamName = teamName;
          }
          const repos = await github.getRepos.team(orgName, shortTeamName);
          addRepos(repos, teams[teamName].rules);
        }
      }
    }

    async function addRepositories() {
      const repositories = config.repositories;
      if (repositories) {
        for (const repoName in repositories) {
          const fullRepoName = /\//.test(repoName) ? repoName : org + '/' + repoName;
          const repoRules = repositories[repoName].rules;
          addRepoRules(fullRepoName, repoRules);
        }
      }
    }

    function removeDisabledRules() {
      for (const repoOrg in repoSourceRules) {
        const repoSources = repoSourceRules[repoOrg];
        for (const source in repoSources) {
          if (Object.keys(repoSources[source]).length == 0)
            delete repoSources[source];
        }
        if (Object.keys(repoSources).length == 0)
          delete repoSourceRules[repoOrg];
      }
    }

    function addRepos(repos, repoRules) {
      for (const repo of repos) {
        const updatedAt = new Date(repo.updated_at);
        const pushedAt = new Date(repo.pushed_at);
        const inRange = (!options.after || updatedAt >= options.after || pushedAt >= options.after) &&
                        (!options.before || (updatedAt < options.before && pushedAt < options.before));
        if (inRange) addRepoRules(repo.full_name, repoRules);
      }
    }

    function addRepoRules(fullRepoName, repoRules) {
      const repoSources = repoSourceRules[fullRepoName] = repoSourceRules[fullRepoName] || {};
      for (const ruleName in repoRules) {
        const ruleOptions = repoRules[ruleName];
        const ruleDefinition = execute.getRuleDefinition(ruleName);
        const source = ruleDefinition.source;
        const sourceRules = repoSources[source] = repoSources[source] || {};
        // multiple configs per rule - no longer supported
        // sourceRules[ruleName] = sourceRules[ruleName] || [];
        // sourceRules[ruleName].push(ruleOptions);

        // config for smaller scope overrides config for bigger scope
        if (ruleOptions.mode === 0)
          delete sourceRules[ruleName];
        else
          sourceRules[ruleName] = [ruleOptions];
      }
    }
  },

  normaliseRuleOptions(options) {
    switch (typeof options) {
      case 'number': {
        return { mode: options };
      }
      case 'object': {
        if (!Array.isArray(options)) return options;
        const opts = { mode: options[0] };
        for (const item of options) {
          switch (typeof item) {
            case 'string': opts[item] = true; break;
            case 'object': copy(item, opts); break;
          }
        }
        return opts;
      }
    }
  },

  getRuleDefinition(ruleName) {
    try { return require(path.join('..', 'rules', ruleName)); }
    catch(e) { throw new Error(`cannot find rule ${ruleName}: ${e.message}`); }
  },

  prepareConfig(config) {
    config = JSON.parse(JSON.stringify(config));
    callValidate(ajv.getSchema('config'), config, 'config');

    const validate = ajv.getSchema('rule');
    const {organizations, teams, repositories} = config;
    const ruleNames = {};
    const validateRule = {};
    addRules(config, 'global rules');
    addRulesFromMap(organizations, 'organization');
    addRulesFromMap(teams, 'team');
    addRulesFromMap(repositories, 'repository');
    for (const name in ruleNames) {
      let rule = execute.getRuleDefinition(name);
      callValidate(validate, rule, `rule "${name}"`);
    }

    return config;

    function addRules({rules}={}, scope) {
      if (rules) {
        for (const name in rules) {
          rules[name] = execute.normaliseRuleOptions(rules[name]);
          if (!validateRule[name]) {
            const ruleSchema = execute.getRuleDefinition(name).schema;
            validateRule[name] = ajv.compile(ruleSchema);
          }
          callValidate(validateRule[name], rules[name], `config for rule "${name}" in ${scope}`);
          ruleNames[name] = true;
        }
      }
    }

    function addRulesFromMap(group, groupName) {
      if (group) {
        for (const item in group)
          addRules(group[item], `${groupName} "${item}"`);
      }
    }
  }
};

function callValidate(validate, data, title) {
  if (!validate(data))
    throw new Error(`${title} is invalid: ${ajv.errorsText(validate.errors)}`);
}

async function checkRule(ruleName, ruleConfigs, sourceData) {
  const ruleDefinition = execute.getRuleDefinition(ruleName);
  if (typeof ruleDefinition.check != 'function') {
    const schema = ruleDefinition.check;
    ruleDefinition.check = createCheckFunction(ruleName, schema);
  }
  const results = [];
  for (const ruleCfg of ruleConfigs) {
    const result = await ruleDefinition.check(ruleCfg, sourceData, github);
    if (!result.valid) {
      result.mode = ruleCfg.mode;
      results.push(result);
    }
  }
  return results;
}

function createCheckFunction(ruleName, schema) {
  const validate = ajv.compile(schema);
  return function (ruleCfg, sourceData) {
    const valid = validate(sourceData);
    const result = {valid};
    if (!valid) {
      result.message = 'not satisfied';
      result.errors = ajv.errorsText(validate.errors);
    }
    return result;
  };
}

function copy(o, to) {
  to = to || {};
  for (const key in o) to[key] = o[key];
  return to;
}
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.nanos.notification.email',
  name: 'EmailMessage',

  documentation: 'Email message',

  implements: [
    'foam.nanos.auth.CreatedAware',
    'foam.nanos.auth.CreatedByAware',
    'foam.nanos.auth.LastModifiedByAware'
  ],

  tableColumns: [
    'created',
    'subject',
    'to',
    'from',
    'status'
  ],

  properties: [
    {
      class: 'Long',
      name: 'id',
    },
    {
      class: 'DateTime',
      name: 'created',
      tableWidth: 170
    },
    {
      class: 'Reference',
      of: 'foam.nanos.auth.User',
      name: 'createdBy',
      documentation: 'User who created the entry',
    },
    {
      class: 'Reference',
      of: 'foam.nanos.auth.User',
      name: 'createdByAgent',
      documentation: 'User who created the entry',
    },
    {
      class: 'StringArray',
      name: 'to'
    },
    {
      class: 'StringArray',
      name: 'cc',
    },
    {
      class: 'StringArray',
      name: 'bcc'
    },
    {
      class: 'String',
      name: 'subject'
    },
    {
      class: 'String',
      name: 'body',
      view: {
        class: 'foam.u2.MultiView',
        views: [
          { class: 'foam.u2.HTMLView' },
          { class: 'foam.u2.tag.TextArea', rows: 30, cols: 130 }
        ]
      }
    },
    {
      class: 'String',
      name: 'from',
      value: null
    },
    {
      class: 'String',
      name: 'displayName',
      value: null
    },
    {
      class: 'String',
      name: 'replyTo',
      value: null
    },
    {
      class: 'Reference',
      of: 'foam.nanos.auth.User',
      name: 'lastModifiedBy',
      value: '1',
      transient: true,
      hidden: true,
      documentation: 'Added to suppress journal comments regarding "modified by". Also, a non-null value is required.',
      javaFactory: 'return 1L;'
    },
    {
      class: 'Enum',
      of: 'foam.nanos.notification.email.Status',
      name: 'status',
      tableWidth: 100
    },
    {
      class: 'Map',
      name: 'templateArguments',
      view: { class: 'foam.u2.view.MapView' }
    }
  ]
});
<commit_msg>EmailMessageDAO Sections (#4401)<commit_after>/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.nanos.notification.email',
  name: 'EmailMessage',

  documentation: 'Email message',

  implements: [
    'foam.nanos.auth.CreatedAware',
    'foam.nanos.auth.CreatedByAware',
    'foam.nanos.auth.LastModifiedByAware'
  ],

  tableColumns: [
    'created',
    'subject',
    'to',
    'from',
    'status'
  ],

  sections: [
    {
      name: 'emailInformation',
      order: 1
    },
    {
      name: 'templateInformation',
      title: 'Template Arguments',
      order: 2
    }
  ],

  properties: [
    {
      class: 'Long',
      name: 'id',
      section: 'emailInformation'
    },
    {
      class: 'DateTime',
      name: 'created',
      section: 'emailInformation',
      tableWidth: 170
    },
    {
      class: 'Reference',
      of: 'foam.nanos.auth.User',
      name: 'createdBy',
      section: 'emailInformation',
      documentation: 'User who created the entry',
    },
    {
      class: 'Reference',
      of: 'foam.nanos.auth.User',
      name: 'createdByAgent',
      section: 'emailInformation',
      documentation: 'User who created the entry',
    },
    {
      class: 'StringArray',
      name: 'to',
      section: 'emailInformation'
    },
    {
      class: 'StringArray',
      name: 'cc',
      section: 'emailInformation'
    },
    {
      class: 'StringArray',
      name: 'bcc',
      section: 'emailInformation'
    },
    {
      class: 'String',
      name: 'subject',
      section: 'emailInformation'
    },
    {
      class: 'String',
      name: 'body',
      section: 'emailInformation',
      view: {
        class: 'foam.u2.MultiView',
        views: [
          { class: 'foam.u2.HTMLView' },
          { class: 'foam.u2.tag.TextArea', rows: 30, cols: 130 }
        ]
      }
    },
    {
      class: 'String',
      name: 'from',
      section: 'emailInformation',
      value: null
    },
    {
      class: 'String',
      name: 'displayName',
      section: 'emailInformation',
      value: null
    },
    {
      class: 'String',
      name: 'replyTo',
      section: 'emailInformation',
      value: null
    },
    {
      class: 'Reference',
      of: 'foam.nanos.auth.User',
      name: 'lastModifiedBy',
      section: 'emailInformation',
      value: '1',
      transient: true,
      hidden: true,
      documentation: 'Added to suppress journal comments regarding "modified by". Also, a non-null value is required.',
      javaFactory: 'return 1L;'
    },
    {
      class: 'Enum',
      of: 'foam.nanos.notification.email.Status',
      name: 'status',
      section: 'emailInformation',
      tableWidth: 100
    },
    {
      class: 'Map',
      name: 'templateArguments',
      section: 'templateInformation',
      view: { class: 'foam.u2.view.MapView' }
    }
  ]
});
<|endoftext|>