<commit_before>/*!
 * Copyright 2016 Yahoo Inc.
 * Licensed under the terms of the MIT license. Please see LICENSE file in the project root for terms.
 * @license
 */

'use strict';

var merge = require('merge'),
	Row = require('./row'),
	layoutConfig = {},
	layoutData = {};

/**
* Create a new, empty row.
*
* @method createNewRow
* @return A new, empty row of the type specified by this layout.
*/
function createNewRow() {

	var isBreakoutRow;

	// Work out if this is a full width breakout row
	if (layoutConfig.fullWidthBreakoutRowCadence !== false) {
		if (((layoutData._rows.length + 1) % layoutConfig.fullWidthBreakoutRowCadence) === 0) {
			isBreakoutRow = true;
		}
	}

	return new Row({
		top: layoutData._containerHeight,
		left: layoutConfig.containerPadding.left,
		width: layoutConfig.containerWidth - layoutConfig.containerPadding.left - layoutConfig.containerPadding.right,
		spacing: layoutConfig.boxSpacing.horizontal,
		targetRowHeight: layoutConfig.targetRowHeight,
		targetRowHeightTolerance: layoutConfig.targetRowHeightTolerance,
		edgeCaseMinRowHeight: 0.5 * layoutConfig.targetRowHeight,
		edgeCaseMaxRowHeight: 2 * layoutConfig.targetRowHeight,
		rightToLeft: false,
		isBreakoutRow: isBreakoutRow,
		widowLayoutStyle: layoutConfig.widowLayoutStyle
	});
}

/**
 * Add a completed row to the layout.
 * Note: the row must have already been completed.
 *
 * @method addRow
 * @param row {Row} The row to add.
 * @return {Array} Each item added to the row.
 */
function addRow(row) {

	layoutData._rows.push(row);
	layoutData._layoutItems = layoutData._layoutItems.concat(row.getItems());

	// Increment the container height
	layoutData._containerHeight += row.height + layoutConfig.boxSpacing.vertical;

	return row.items;
}

/**
* Calculate the current layout for all items in the list that require layout.
* "Layout" means geometry: position within container and size
*
* @method computeLayout
* @param itemLayoutData {Array} Array of items to lay out, with data required to lay out each item
* @return {Object} The newly-calculated layout, containing the new container height, and lists of layout items
*/
function computeLayout(itemLayoutData) {

	var laidOutItems = [],
		itemAdded,
		currentRow,
		nextToLastRowHeight;

	// Apply forced aspect ratio if specified, and set a flag.
	if (layoutConfig.forceAspectRatio) {
		itemLayoutData.forEach(function (itemData) {
			itemData.forcedAspectRatio = true;
			itemData.aspectRatio = layoutConfig.forceAspectRatio;
		});
	}

	// Loop through the items
	itemLayoutData.some(function (itemData, i) {

		if (isNaN(itemData.aspectRatio)) {
			throw new Error("Item " + i + " has an invalid aspect ratio");
		}

		// If not currently building up a row, make a new one.
		if (!currentRow) {
			currentRow = createNewRow();
		}

		// Attempt to add item to the current row.
		itemAdded = currentRow.addItem(itemData);

		if (currentRow.isLayoutComplete()) {

			// Row is filled; add it and start a new one
			laidOutItems = laidOutItems.concat(addRow(currentRow));

			if (layoutData._rows.length >= layoutConfig.maxNumRows) {
				currentRow = null;
				return true;
			}

			currentRow = createNewRow();

			// Item was rejected; add it to its own row
			if (!itemAdded) {

				itemAdded = currentRow.addItem(itemData);

				if (currentRow.isLayoutComplete()) {

					// If the rejected item fills a row on its own, add the row and start another new one
					laidOutItems = laidOutItems.concat(addRow(currentRow));
					if (layoutData._rows.length >= layoutConfig.maxNumRows) {
						currentRow = null;
						return true;
					}
					currentRow = createNewRow();
				}
			}
		}

	});

	// Handle any leftover content (orphans) depending on where they lie
	// in this layout update, and in the total content set.
	if (currentRow && currentRow.getItems().length && layoutConfig.showWidows) {

		// Last page of all content or orphan suppression is suppressed; lay out orphans.
		if (layoutData._rows.length) {

			// Only Match previous row's height if it exists and it isn't a breakout row
			if (layoutData._rows[layoutData._rows.length - 1].isBreakoutRow) {
				nextToLastRowHeight = layoutData._rows[layoutData._rows.length - 1].targetRowHeight;
			} else {
				nextToLastRowHeight = layoutData._rows[layoutData._rows.length - 1].height;
			}

			currentRow.forceComplete(false, nextToLastRowHeight);

		} else {

			// ...else use target height if there is no other row height to reference.
			currentRow.forceComplete(false);

		}

		laidOutItems = laidOutItems.concat(addRow(currentRow));
		layoutConfig._widowCount = currentRow.getItems().length;

	}

	// We need to clean up the bottom container padding
	// First remove the height added for box spacing
	layoutData._containerHeight = layoutData._containerHeight - layoutConfig.boxSpacing.vertical;
	// Then add our bottom container padding
	layoutData._containerHeight = layoutData._containerHeight + layoutConfig.containerPadding.bottom;

	return {
		containerHeight: layoutData._containerHeight,
		widowCount: layoutConfig._widowCount,
		boxes: layoutData._layoutItems
	};

}

/**
* Takes in a bunch of box data and config. Returns
* geometry to lay them out in a justified view.
*
* @method covertSizesToAspectRatios
* @param sizes {Array} Array of objects with widths and heights
* @return {Array} A list of aspect ratios
**/
module.exports = function (input, config) {

	// Defaults
	var defaults = {
		containerWidth: 1060,
		containerPadding: 10,
		boxSpacing: 10,
		targetRowHeight: 320,
		targetRowHeightTolerance: 0.25,
		maxNumRows: Number.POSITIVE_INFINITY,
		forceAspectRatio: false,
		showWidows: true,
		fullWidthBreakoutRowCadence: false,
		widowLayoutStyle: 'left'
	};

	var containerPadding = {};
	var boxSpacing = {};

	config = config || {};

	// Merge defaults and config passed in
	layoutConfig = merge(defaults, config);

	// Sort out padding and spacing values
	containerPadding.top = (!isNaN(parseFloat(layoutConfig.containerPadding.top))) ? layoutConfig.containerPadding.top : layoutConfig.containerPadding;
	containerPadding.right = (!isNaN(parseFloat(layoutConfig.containerPadding.right))) ? layoutConfig.containerPadding.right : layoutConfig.containerPadding;
	containerPadding.bottom = (!isNaN(parseFloat(layoutConfig.containerPadding.bottom))) ? layoutConfig.containerPadding.bottom : layoutConfig.containerPadding;
	containerPadding.left = (!isNaN(parseFloat(layoutConfig.containerPadding.left))) ? layoutConfig.containerPadding.left : layoutConfig.containerPadding;
	boxSpacing.horizontal = (!isNaN(parseFloat(layoutConfig.boxSpacing.horizontal))) ? layoutConfig.boxSpacing.horizontal : layoutConfig.boxSpacing;
	boxSpacing.vertical = (!isNaN(parseFloat(layoutConfig.boxSpacing.vertical))) ? layoutConfig.boxSpacing.vertical : layoutConfig.boxSpacing;

	layoutConfig.containerPadding = containerPadding;
	layoutConfig.boxSpacing = boxSpacing;

	// Local
	layoutData._layoutItems = [];
	layoutData._awakeItems = [];
	layoutData._inViewportItems = [];
	layoutData._leadingOrphans = [];
	layoutData._trailingOrphans = [];
	layoutData._containerHeight = layoutConfig.containerPadding.top;
	layoutData._rows = [];
	layoutData._orphans = [];
	layoutConfig._widowCount = 0;

	// Convert widths and heights to aspect ratios if we need to
	return computeLayout(input.map(function (item) {
		if (item.width && item.height) {
			return { aspectRatio: item.width / item.height };
		} else {
			return { aspectRatio: item };
		}
	}));
};
<commit_msg>Correctly scope layoutConfig and layoutData<commit_after>/*!
 * Copyright 2016 Yahoo Inc.
 * Licensed under the terms of the MIT license. Please see LICENSE file in the project root for terms.
 * @license
 */

'use strict';

var merge = require('merge'),
	Row = require('./row');

/**
* Create a new, empty row.
*
* @method createNewRow
* @param layoutConfig {Object} The layout configuration
* @param layoutData {Object} The current state of the layout
* @return A new, empty row of the type specified by this layout.
*/
function createNewRow(layoutConfig, layoutData) {

	var isBreakoutRow;

	// Work out if this is a full width breakout row
	if (layoutConfig.fullWidthBreakoutRowCadence !== false) {
		if (((layoutData._rows.length + 1) % layoutConfig.fullWidthBreakoutRowCadence) === 0) {
			isBreakoutRow = true;
		}
	}

	return new Row({
		top: layoutData._containerHeight,
		left: layoutConfig.containerPadding.left,
		width: layoutConfig.containerWidth - layoutConfig.containerPadding.left - layoutConfig.containerPadding.right,
		spacing: layoutConfig.boxSpacing.horizontal,
		targetRowHeight: layoutConfig.targetRowHeight,
		targetRowHeightTolerance: layoutConfig.targetRowHeightTolerance,
		edgeCaseMinRowHeight: 0.5 * layoutConfig.targetRowHeight,
		edgeCaseMaxRowHeight: 2 * layoutConfig.targetRowHeight,
		rightToLeft: false,
		isBreakoutRow: isBreakoutRow,
		widowLayoutStyle: layoutConfig.widowLayoutStyle
	});
}

/**
 * Add a completed row to the layout.
 * Note: the row must have already been completed.
 *
 * @method addRow
 * @param layoutConfig {Object} The layout configuration
 * @param layoutData {Object} The current state of the layout
 * @param row {Row} The row to add.
 * @return {Array} Each item added to the row.
 */
function addRow(layoutConfig, layoutData, row) {

	layoutData._rows.push(row);
	layoutData._layoutItems = layoutData._layoutItems.concat(row.getItems());

	// Increment the container height
	layoutData._containerHeight += row.height + layoutConfig.boxSpacing.vertical;

	return row.items;
}

/**
* Calculate the current layout for all items in the list that require layout.
* "Layout" means geometry: position within container and size
*
* @method computeLayout
* @param layoutConfig {Object} The layout configuration
* @param layoutData {Object} The current state of the layout
* @param itemLayoutData {Array} Array of items to lay out, with data required to lay out each item
* @return {Object} The newly-calculated layout, containing the new container height, and lists of layout items
*/
function computeLayout(layoutConfig, layoutData, itemLayoutData) {

	var laidOutItems = [],
		itemAdded,
		currentRow,
		nextToLastRowHeight;

	// Apply forced aspect ratio if specified, and set a flag.
	if (layoutConfig.forceAspectRatio) {
		itemLayoutData.forEach(function (itemData) {
			itemData.forcedAspectRatio = true;
			itemData.aspectRatio = layoutConfig.forceAspectRatio;
		});
	}

	// Loop through the items
	itemLayoutData.some(function (itemData, i) {

		if (isNaN(itemData.aspectRatio)) {
			throw new Error("Item " + i + " has an invalid aspect ratio");
		}

		// If not currently building up a row, make a new one.
		if (!currentRow) {
			currentRow = createNewRow(layoutConfig, layoutData);
		}

		// Attempt to add item to the current row.
		itemAdded = currentRow.addItem(itemData);

		if (currentRow.isLayoutComplete()) {

			// Row is filled; add it and start a new one
			laidOutItems = laidOutItems.concat(addRow(layoutConfig, layoutData, currentRow));

			if (layoutData._rows.length >= layoutConfig.maxNumRows) {
				currentRow = null;
				return true;
			}

			currentRow = createNewRow(layoutConfig, layoutData);

			// Item was rejected; add it to its own row
			if (!itemAdded) {

				itemAdded = currentRow.addItem(itemData);

				if (currentRow.isLayoutComplete()) {

					// If the rejected item fills a row on its own, add the row and start another new one
					laidOutItems = laidOutItems.concat(addRow(layoutConfig, layoutData, currentRow));
					if (layoutData._rows.length >= layoutConfig.maxNumRows) {
						currentRow = null;
						return true;
					}
					currentRow = createNewRow(layoutConfig, layoutData);
				}
			}
		}

	});

	// Handle any leftover content (orphans) depending on where they lie
	// in this layout update, and in the total content set.
	if (currentRow && currentRow.getItems().length && layoutConfig.showWidows) {

		// Last page of all content or orphan suppression is suppressed; lay out orphans.
		if (layoutData._rows.length) {

			// Only Match previous row's height if it exists and it isn't a breakout row
			if (layoutData._rows[layoutData._rows.length - 1].isBreakoutRow) {
				nextToLastRowHeight = layoutData._rows[layoutData._rows.length - 1].targetRowHeight;
			} else {
				nextToLastRowHeight = layoutData._rows[layoutData._rows.length - 1].height;
			}

			currentRow.forceComplete(false, nextToLastRowHeight);

		} else {

			// ...else use target height if there is no other row height to reference.
			currentRow.forceComplete(false);

		}

		laidOutItems = laidOutItems.concat(addRow(layoutConfig, layoutData, currentRow));
		layoutConfig._widowCount = currentRow.getItems().length;

	}

	// We need to clean up the bottom container padding
	// First remove the height added for box spacing
	layoutData._containerHeight = layoutData._containerHeight - layoutConfig.boxSpacing.vertical;
	// Then add our bottom container padding
	layoutData._containerHeight = layoutData._containerHeight + layoutConfig.containerPadding.bottom;

	return {
		containerHeight: layoutData._containerHeight,
		widowCount: layoutConfig._widowCount,
		boxes: layoutData._layoutItems
	};

}

/**
* Takes in a bunch of box data and config. Returns
* geometry to lay them out in a justified view.
*
* @method covertSizesToAspectRatios
* @param sizes {Array} Array of objects with widths and heights
* @return {Array} A list of aspect ratios
**/
module.exports = function (input, config) {
	var layoutConfig = {};
	var layoutData = {};

	// Defaults
	var defaults = {
		containerWidth: 1060,
		containerPadding: 10,
		boxSpacing: 10,
		targetRowHeight: 320,
		targetRowHeightTolerance: 0.25,
		maxNumRows: Number.POSITIVE_INFINITY,
		forceAspectRatio: false,
		showWidows: true,
		fullWidthBreakoutRowCadence: false,
		widowLayoutStyle: 'left'
	};

	var containerPadding = {};
	var boxSpacing = {};

	config = config || {};

	// Merge defaults and config passed in
	layoutConfig = merge(defaults, config);

	// Sort out padding and spacing values
	containerPadding.top = (!isNaN(parseFloat(layoutConfig.containerPadding.top))) ? layoutConfig.containerPadding.top : layoutConfig.containerPadding;
	containerPadding.right = (!isNaN(parseFloat(layoutConfig.containerPadding.right))) ? layoutConfig.containerPadding.right : layoutConfig.containerPadding;
	containerPadding.bottom = (!isNaN(parseFloat(layoutConfig.containerPadding.bottom))) ? layoutConfig.containerPadding.bottom : layoutConfig.containerPadding;
	containerPadding.left = (!isNaN(parseFloat(layoutConfig.containerPadding.left))) ? layoutConfig.containerPadding.left : layoutConfig.containerPadding;
	boxSpacing.horizontal = (!isNaN(parseFloat(layoutConfig.boxSpacing.horizontal))) ? layoutConfig.boxSpacing.horizontal : layoutConfig.boxSpacing;
	boxSpacing.vertical = (!isNaN(parseFloat(layoutConfig.boxSpacing.vertical))) ? layoutConfig.boxSpacing.vertical : layoutConfig.boxSpacing;

	layoutConfig.containerPadding = containerPadding;
	layoutConfig.boxSpacing = boxSpacing;

	// Local
	layoutData._layoutItems = [];
	layoutData._awakeItems = [];
	layoutData._inViewportItems = [];
	layoutData._leadingOrphans = [];
	layoutData._trailingOrphans = [];
	layoutData._containerHeight = layoutConfig.containerPadding.top;
	layoutData._rows = [];
	layoutData._orphans = [];
	layoutConfig._widowCount = 0;

	// Convert widths and heights to aspect ratios if we need to
	return computeLayout(layoutConfig, layoutData, input.map(function (item) {
		if (item.width && item.height) {
			return { aspectRatio: item.width / item.height };
		} else {
			return { aspectRatio: item };
		}
	}));
};
<|endoftext|>


<commit_before>/*
 * @class GeoJSON
 * @aka L.GeoJSON
 * @inherits FeatureGroup
 *
 * Represents a GeoJSON object or an array of GeoJSON objects. Allows you to parse
 * GeoJSON data and display it on the map. Extends `FeatureGroup`.
 *
 * @example
 *
 * ```js
 * L.geoJSON(data, {
 * 	style: function (feature) {
 * 		return {color: feature.properties.color};
 * 	}
 * }).bindPopup(function (layer) {
 * 	return layer.feature.properties.description;
 * }).addTo(map);
 * ```
 */

L.GeoJSON = L.FeatureGroup.extend({

	/* @section
	 * @aka GeoJSON options
	 *
	 * @option pointToLayer: Function = *
	 * A `Function` defining how GeoJSON points spawn Leaflet layers. It is internally
	 * called when data is added, passing the GeoJSON point feature and its `LatLng`.
	 * The default is to spawn a default `Marker`:
	 * ```js
	 * function(geoJsonPoint, latlng) {
	 * 	return L.marker(latlng);
	 * }
	 * ```
	 *
	 * @option style: Function = *
	 * A `Function` defining the `Path options` for styling GeoJSON lines and polygons,
	 * called internally when data is added.
	 * The default value is to not override any defaults:
	 * ```js
	 * function (geoJsonFeature) {
	 * 	return {}
	 * }
	 * ```
	 *
	 * @option onEachFeature: Function = *
	 * A `Function` that will be called once for each created `Feature`, after it has
	 * been created and styled. Useful for attaching events and popups to features.
	 * The default is to do nothing with the newly created layers:
	 * ```js
	 * function (feature, layer) {}
	 * ```
	 *
	 * @option filter: Function = *
	 * A `Function` that will be used to decide whether to include a feature or not.
	 * The default is to include all features:
	 * ```js
	 * function (geoJsonFeature) {
	 * 	return true;
	 * }
	 * ```
	 * Note: dynamically changing the `filter` option will have effect only on newly
	 * added data. It will _not_ re-evaluate already included features.
	 *
	 * @option coordsToLatLng: Function = *
	 * A `Function` that will be used for converting GeoJSON coordinates to `LatLng`s.
	 * The default is the `coordsToLatLng` static method.
	 */

	initialize: function (geojson, options) {
		L.setOptions(this, options);

		this._layers = {};

		if (geojson) {
			this.addData(geojson);
		}
	},

	// @method addData( <GeoJSON> data ): Layer
	// Adds a GeoJSON object to the layer.
	addData: function (geojson) {
		var features = L.Util.isArray(geojson) ? geojson : geojson.features,
		    i, len, feature;

		if (features) {
			for (i = 0, len = features.length; i < len; i++) {
				// only add this if geometry or geometries are set and not null
				feature = features[i];
				if (feature.geometries || feature.geometry || feature.features || feature.coordinates) {
					this.addData(feature);
				}
			}
			return this;
		}

		var options = this.options;

		if (options.filter && !options.filter(geojson)) { return this; }

		var layer = L.GeoJSON.geometryToLayer(geojson, options);
		if (!layer) {
			return this;
		}
		layer.feature = L.GeoJSON.asFeature(geojson);

		layer.defaultOptions = layer.options;
		this.resetStyle(layer);

		if (options.onEachFeature) {
			options.onEachFeature(geojson, layer);
		}

		return this.addLayer(layer);
	},

	// @method resetStyle( <Path> layer ): Layer
	// Resets the given vector layer's style to the original GeoJSON style, useful for resetting style after hover events.
	resetStyle: function (layer) {
		// reset any custom styles
		layer.options = L.Util.extend({}, layer.defaultOptions);
		this._setLayerStyle(layer, this.options.style);
		return this;
	},

	// @method setStyle( <Function> style ): Layer
	// Changes styles of GeoJSON vector layers with the given style function.
	setStyle: function (style) {
		return this.eachLayer(function (layer) {
			this._setLayerStyle(layer, style);
		}, this);
	},

	_setLayerStyle: function (layer, style) {
		if (typeof style === 'function') {
			style = style(layer.feature);
		}
		if (layer.setStyle) {
			layer.setStyle(style);
		}
	}
});

// @section
// There are several static functions which can be called without instantiating L.GeoJSON:
L.extend(L.GeoJSON, {
	// @function geometryToLayer(featureData: Object, options?: GeoJSON options): Layer
	// Creates a `Layer` from a given GeoJSON feature. Can use a custom
	// [`pointToLayer`](#geojson-pointtolayer) and/or [`coordsToLatLng`](#geojson-coordstolatlng)
	// functions if provided as options.
	geometryToLayer: function (geojson, options) {

		var geometry = geojson.type === 'Feature' ? geojson.geometry : geojson,
		    coords = geometry ? geometry.coordinates : null,
		    layers = [],
		    pointToLayer = options && options.pointToLayer,
		    coordsToLatLng = options && options.coordsToLatLng || this.coordsToLatLng,
		    latlng, latlngs, i, len;

		if (!coords && !geometry) {
			return null;
		}

		switch (geometry.type) {
		case 'Point':
			latlng = coordsToLatLng(coords);
			return pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng);

		case 'MultiPoint':
			for (i = 0, len = coords.length; i < len; i++) {
				latlng = coordsToLatLng(coords[i]);
				layers.push(pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng));
			}
			return new L.FeatureGroup(layers);

		case 'LineString':
		case 'MultiLineString':
			latlngs = this.coordsToLatLngs(coords, geometry.type === 'LineString' ? 0 : 1, coordsToLatLng);
			return new L.Polyline(latlngs, options);

		case 'Polygon':
		case 'MultiPolygon':
			latlngs = this.coordsToLatLngs(coords, geometry.type === 'Polygon' ? 1 : 2, coordsToLatLng);
			return new L.Polygon(latlngs, options);

		case 'GeometryCollection':
			for (i = 0, len = geometry.geometries.length; i < len; i++) {
				var layer = this.geometryToLayer({
					geometry: geometry.geometries[i],
					type: 'Feature',
					properties: geojson.properties
				}, options);

				if (layer) {
					layers.push(layer);
				}
			}
			return new L.FeatureGroup(layers);

		default:
			throw new Error('Invalid GeoJSON object.');
		}
	},

	// @function coordsToLatLng(coords: Array): LatLng
	// Creates a `LatLng` object from an array of 2 numbers (longitude, latitude)
	// or 3 numbers (longitude, latitude, altitude) used in GeoJSON for points.
	coordsToLatLng: function (coords) {
		return new L.LatLng(coords[1], coords[0], coords[2]);
	},

	// @function coordsToLatLngs(coords: Array, levelsDeep?: Number, coordsToLatLng?: Function): Array
	// Creates a multidimensional array of `LatLng`s from a GeoJSON coordinates array.
	// `levelsDeep` specifies the nesting level (0 is for an array of points, 1 for an array of arrays of points, etc., 0 by default).
	// Can use a custom [`coordsToLatLng`](#geojson-coordstolatlng) function.
	coordsToLatLngs: function (coords, levelsDeep, coordsToLatLng) {
		var latlngs = [];

		for (var i = 0, len = coords.length, latlng; i < len; i++) {
			latlng = levelsDeep ?
			        this.coordsToLatLngs(coords[i], levelsDeep - 1, coordsToLatLng) :
			        (coordsToLatLng || this.coordsToLatLng)(coords[i]);

			latlngs.push(latlng);
		}

		return latlngs;
	},

	// @function latLngToCoords(latlng: LatLng): Array
	// Reverse of [`coordsToLatLng`](#geojson-coordstolatlng)
	latLngToCoords: function (latlng) {
		return latlng.alt !== undefined ?
				[latlng.lng, latlng.lat, latlng.alt] :
				[latlng.lng, latlng.lat];
	},

	// @function latLngsToCoords(latlngs: Array, levelsDeep?: Number, closed?: Boolean): Array
	// Reverse of [`coordsToLatLngs`](#geojson-coordstolatlngs)
	// `closed` determines whether the first point should be appended to the end of the array to close the feature, only used when `levelsDeep` is 0. False by default.
	latLngsToCoords: function (latlngs, levelsDeep, closed) {
		var coords = [];

		for (var i = 0, len = latlngs.length; i < len; i++) {
			coords.push(levelsDeep ?
				L.GeoJSON.latLngsToCoords(latlngs[i], levelsDeep - 1, closed) :
				L.GeoJSON.latLngToCoords(latlngs[i]));
		}

		if (!levelsDeep && closed) {
			coords.push(coords[0]);
		}

		return coords;
	},

	getFeature: function (layer, newGeometry) {
		return layer.feature ?
				L.extend({}, layer.feature, {geometry: newGeometry}) :
				L.GeoJSON.asFeature(newGeometry);
	},

	// @function asFeature(geojson: Object): Object
	// Normalize GeoJSON geometries/features into GeoJSON features.
	asFeature: function (geojson) {
		if (geojson.type === 'Feature') {
			return geojson;
		}

		return {
			type: 'Feature',
			properties: {},
			geometry: geojson
		};
	}
});

var PointToGeoJSON = {
	toGeoJSON: function () {
		return L.GeoJSON.getFeature(this, {
			type: 'Point',
			coordinates: L.GeoJSON.latLngToCoords(this.getLatLng())
		});
	}
};

// @namespace Marker
// @method toGeoJSON(): Object
// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the marker (as a GeoJSON `Point` Feature).
L.Marker.include(PointToGeoJSON);

// @namespace CircleMarker
// @method toGeoJSON(): Object
// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the circle marker (as a GeoJSON `Point` Feature).
L.Circle.include(PointToGeoJSON);
L.CircleMarker.include(PointToGeoJSON);

// @namespace Polyline
// @method toGeoJSON(): Object
// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the polyline (as a GeoJSON `LineString` or `MultiLineString` Feature).
L.Polyline.prototype.toGeoJSON = function () {
	var multi = !L.Polyline._flat(this._latlngs);

	var coords = L.GeoJSON.latLngsToCoords(this._latlngs, multi ? 1 : 0);

	return L.GeoJSON.getFeature(this, {
		type: (multi ? 'Multi' : '') + 'LineString',
		coordinates: coords
	});
};

// @namespace Polygon
// @method toGeoJSON(): Object
// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the polygon (as a GeoJSON `Polygon` or `MultiPolygon` Feature).
L.Polygon.prototype.toGeoJSON = function () {
	var holes = !L.Polyline._flat(this._latlngs),
	    multi = holes && !L.Polyline._flat(this._latlngs[0]);

	var coords = L.GeoJSON.latLngsToCoords(this._latlngs, multi ? 2 : holes ? 1 : 0, true);

	if (!holes) {
		coords = [coords];
	}

	return L.GeoJSON.getFeature(this, {
		type: (multi ? 'Multi' : '') + 'Polygon',
		coordinates: coords
	});
};

// @namespace LayerGroup
L.LayerGroup.include({
	toMultiPoint: function () {
		var coords = [];

		this.eachLayer(function (layer) {
			coords.push(layer.toGeoJSON().geometry.coordinates);
		});

		return L.GeoJSON.getFeature(this, {
			type: 'MultiPoint',
			coordinates: coords
		});
	},

	// @method toGeoJSON(): Object
	// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the layer group (as a GeoJSON `GeometryCollection`).
	toGeoJSON: function () {

		var type = this.feature && this.feature.geometry && this.feature.geometry.type;

		if (type === 'MultiPoint') {
			return this.toMultiPoint();
		}

		var isGeometryCollection = type === 'GeometryCollection',
		    jsons = [];

		this.eachLayer(function (layer) {
			if (layer.toGeoJSON) {
				var json = layer.toGeoJSON();
				jsons.push(isGeometryCollection ? json.geometry : L.GeoJSON.asFeature(json));
			}
		});

		if (isGeometryCollection) {
			return L.GeoJSON.getFeature(this, {
				geometries: jsons,
				type: 'GeometryCollection'
			});
		}

		return {
			type: 'FeatureCollection',
			features: jsons
		};
	}
});

// @namespace GeoJSON
// @factory L.geoJSON(geojson?: Object, options?: GeoJSON options)
// Creates a GeoJSON layer. Optionally accepts an object in
// [GeoJSON format](http://geojson.org/geojson-spec.html) to display on the map
// (you can alternatively add it later with `addData` method) and an `options` object.
L.geoJSON = function (geojson, options) {
	return new L.GeoJSON(geojson, options);
};
// Backward compatibility.
L.geoJson = L.geoJSON;
<commit_msg>docstrings: correct GeoJSON methods returns (#5064)<commit_after>/*
 * @class GeoJSON
 * @aka L.GeoJSON
 * @inherits FeatureGroup
 *
 * Represents a GeoJSON object or an array of GeoJSON objects. Allows you to parse
 * GeoJSON data and display it on the map. Extends `FeatureGroup`.
 *
 * @example
 *
 * ```js
 * L.geoJSON(data, {
 * 	style: function (feature) {
 * 		return {color: feature.properties.color};
 * 	}
 * }).bindPopup(function (layer) {
 * 	return layer.feature.properties.description;
 * }).addTo(map);
 * ```
 */

L.GeoJSON = L.FeatureGroup.extend({

	/* @section
	 * @aka GeoJSON options
	 *
	 * @option pointToLayer: Function = *
	 * A `Function` defining how GeoJSON points spawn Leaflet layers. It is internally
	 * called when data is added, passing the GeoJSON point feature and its `LatLng`.
	 * The default is to spawn a default `Marker`:
	 * ```js
	 * function(geoJsonPoint, latlng) {
	 * 	return L.marker(latlng);
	 * }
	 * ```
	 *
	 * @option style: Function = *
	 * A `Function` defining the `Path options` for styling GeoJSON lines and polygons,
	 * called internally when data is added.
	 * The default value is to not override any defaults:
	 * ```js
	 * function (geoJsonFeature) {
	 * 	return {}
	 * }
	 * ```
	 *
	 * @option onEachFeature: Function = *
	 * A `Function` that will be called once for each created `Feature`, after it has
	 * been created and styled. Useful for attaching events and popups to features.
	 * The default is to do nothing with the newly created layers:
	 * ```js
	 * function (feature, layer) {}
	 * ```
	 *
	 * @option filter: Function = *
	 * A `Function` that will be used to decide whether to include a feature or not.
	 * The default is to include all features:
	 * ```js
	 * function (geoJsonFeature) {
	 * 	return true;
	 * }
	 * ```
	 * Note: dynamically changing the `filter` option will have effect only on newly
	 * added data. It will _not_ re-evaluate already included features.
	 *
	 * @option coordsToLatLng: Function = *
	 * A `Function` that will be used for converting GeoJSON coordinates to `LatLng`s.
	 * The default is the `coordsToLatLng` static method.
	 */

	initialize: function (geojson, options) {
		L.setOptions(this, options);

		this._layers = {};

		if (geojson) {
			this.addData(geojson);
		}
	},

	// @method addData( <GeoJSON> data ): this
	// Adds a GeoJSON object to the layer.
	addData: function (geojson) {
		var features = L.Util.isArray(geojson) ? geojson : geojson.features,
		    i, len, feature;

		if (features) {
			for (i = 0, len = features.length; i < len; i++) {
				// only add this if geometry or geometries are set and not null
				feature = features[i];
				if (feature.geometries || feature.geometry || feature.features || feature.coordinates) {
					this.addData(feature);
				}
			}
			return this;
		}

		var options = this.options;

		if (options.filter && !options.filter(geojson)) { return this; }

		var layer = L.GeoJSON.geometryToLayer(geojson, options);
		if (!layer) {
			return this;
		}
		layer.feature = L.GeoJSON.asFeature(geojson);

		layer.defaultOptions = layer.options;
		this.resetStyle(layer);

		if (options.onEachFeature) {
			options.onEachFeature(geojson, layer);
		}

		return this.addLayer(layer);
	},

	// @method resetStyle( <Path> layer ): this
	// Resets the given vector layer's style to the original GeoJSON style, useful for resetting style after hover events.
	resetStyle: function (layer) {
		// reset any custom styles
		layer.options = L.Util.extend({}, layer.defaultOptions);
		this._setLayerStyle(layer, this.options.style);
		return this;
	},

	// @method setStyle( <Function> style ): this
	// Changes styles of GeoJSON vector layers with the given style function.
	setStyle: function (style) {
		return this.eachLayer(function (layer) {
			this._setLayerStyle(layer, style);
		}, this);
	},

	_setLayerStyle: function (layer, style) {
		if (typeof style === 'function') {
			style = style(layer.feature);
		}
		if (layer.setStyle) {
			layer.setStyle(style);
		}
	}
});

// @section
// There are several static functions which can be called without instantiating L.GeoJSON:
L.extend(L.GeoJSON, {
	// @function geometryToLayer(featureData: Object, options?: GeoJSON options): Layer
	// Creates a `Layer` from a given GeoJSON feature. Can use a custom
	// [`pointToLayer`](#geojson-pointtolayer) and/or [`coordsToLatLng`](#geojson-coordstolatlng)
	// functions if provided as options.
	geometryToLayer: function (geojson, options) {

		var geometry = geojson.type === 'Feature' ? geojson.geometry : geojson,
		    coords = geometry ? geometry.coordinates : null,
		    layers = [],
		    pointToLayer = options && options.pointToLayer,
		    coordsToLatLng = options && options.coordsToLatLng || this.coordsToLatLng,
		    latlng, latlngs, i, len;

		if (!coords && !geometry) {
			return null;
		}

		switch (geometry.type) {
		case 'Point':
			latlng = coordsToLatLng(coords);
			return pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng);

		case 'MultiPoint':
			for (i = 0, len = coords.length; i < len; i++) {
				latlng = coordsToLatLng(coords[i]);
				layers.push(pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng));
			}
			return new L.FeatureGroup(layers);

		case 'LineString':
		case 'MultiLineString':
			latlngs = this.coordsToLatLngs(coords, geometry.type === 'LineString' ? 0 : 1, coordsToLatLng);
			return new L.Polyline(latlngs, options);

		case 'Polygon':
		case 'MultiPolygon':
			latlngs = this.coordsToLatLngs(coords, geometry.type === 'Polygon' ? 1 : 2, coordsToLatLng);
			return new L.Polygon(latlngs, options);

		case 'GeometryCollection':
			for (i = 0, len = geometry.geometries.length; i < len; i++) {
				var layer = this.geometryToLayer({
					geometry: geometry.geometries[i],
					type: 'Feature',
					properties: geojson.properties
				}, options);

				if (layer) {
					layers.push(layer);
				}
			}
			return new L.FeatureGroup(layers);

		default:
			throw new Error('Invalid GeoJSON object.');
		}
	},

	// @function coordsToLatLng(coords: Array): LatLng
	// Creates a `LatLng` object from an array of 2 numbers (longitude, latitude)
	// or 3 numbers (longitude, latitude, altitude) used in GeoJSON for points.
	coordsToLatLng: function (coords) {
		return new L.LatLng(coords[1], coords[0], coords[2]);
	},

	// @function coordsToLatLngs(coords: Array, levelsDeep?: Number, coordsToLatLng?: Function): Array
	// Creates a multidimensional array of `LatLng`s from a GeoJSON coordinates array.
	// `levelsDeep` specifies the nesting level (0 is for an array of points, 1 for an array of arrays of points, etc., 0 by default).
	// Can use a custom [`coordsToLatLng`](#geojson-coordstolatlng) function.
	coordsToLatLngs: function (coords, levelsDeep, coordsToLatLng) {
		var latlngs = [];

		for (var i = 0, len = coords.length, latlng; i < len; i++) {
			latlng = levelsDeep ?
			        this.coordsToLatLngs(coords[i], levelsDeep - 1, coordsToLatLng) :
			        (coordsToLatLng || this.coordsToLatLng)(coords[i]);

			latlngs.push(latlng);
		}

		return latlngs;
	},

	// @function latLngToCoords(latlng: LatLng): Array
	// Reverse of [`coordsToLatLng`](#geojson-coordstolatlng)
	latLngToCoords: function (latlng) {
		return latlng.alt !== undefined ?
				[latlng.lng, latlng.lat, latlng.alt] :
				[latlng.lng, latlng.lat];
	},

	// @function latLngsToCoords(latlngs: Array, levelsDeep?: Number, closed?: Boolean): Array
	// Reverse of [`coordsToLatLngs`](#geojson-coordstolatlngs)
	// `closed` determines whether the first point should be appended to the end of the array to close the feature, only used when `levelsDeep` is 0. False by default.
	latLngsToCoords: function (latlngs, levelsDeep, closed) {
		var coords = [];

		for (var i = 0, len = latlngs.length; i < len; i++) {
			coords.push(levelsDeep ?
				L.GeoJSON.latLngsToCoords(latlngs[i], levelsDeep - 1, closed) :
				L.GeoJSON.latLngToCoords(latlngs[i]));
		}

		if (!levelsDeep && closed) {
			coords.push(coords[0]);
		}

		return coords;
	},

	getFeature: function (layer, newGeometry) {
		return layer.feature ?
				L.extend({}, layer.feature, {geometry: newGeometry}) :
				L.GeoJSON.asFeature(newGeometry);
	},

	// @function asFeature(geojson: Object): Object
	// Normalize GeoJSON geometries/features into GeoJSON features.
	asFeature: function (geojson) {
		if (geojson.type === 'Feature') {
			return geojson;
		}

		return {
			type: 'Feature',
			properties: {},
			geometry: geojson
		};
	}
});

var PointToGeoJSON = {
	toGeoJSON: function () {
		return L.GeoJSON.getFeature(this, {
			type: 'Point',
			coordinates: L.GeoJSON.latLngToCoords(this.getLatLng())
		});
	}
};

// @namespace Marker
// @method toGeoJSON(): Object
// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the marker (as a GeoJSON `Point` Feature).
L.Marker.include(PointToGeoJSON);

// @namespace CircleMarker
// @method toGeoJSON(): Object
// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the circle marker (as a GeoJSON `Point` Feature).
L.Circle.include(PointToGeoJSON);
L.CircleMarker.include(PointToGeoJSON);

// @namespace Polyline
// @method toGeoJSON(): Object
// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the polyline (as a GeoJSON `LineString` or `MultiLineString` Feature).
L.Polyline.prototype.toGeoJSON = function () {
	var multi = !L.Polyline._flat(this._latlngs);

	var coords = L.GeoJSON.latLngsToCoords(this._latlngs, multi ? 1 : 0);

	return L.GeoJSON.getFeature(this, {
		type: (multi ? 'Multi' : '') + 'LineString',
		coordinates: coords
	});
};

// @namespace Polygon
// @method toGeoJSON(): Object
// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the polygon (as a GeoJSON `Polygon` or `MultiPolygon` Feature).
L.Polygon.prototype.toGeoJSON = function () {
	var holes = !L.Polyline._flat(this._latlngs),
	    multi = holes && !L.Polyline._flat(this._latlngs[0]);

	var coords = L.GeoJSON.latLngsToCoords(this._latlngs, multi ? 2 : holes ? 1 : 0, true);

	if (!holes) {
		coords = [coords];
	}

	return L.GeoJSON.getFeature(this, {
		type: (multi ? 'Multi' : '') + 'Polygon',
		coordinates: coords
	});
};

// @namespace LayerGroup
L.LayerGroup.include({
	toMultiPoint: function () {
		var coords = [];

		this.eachLayer(function (layer) {
			coords.push(layer.toGeoJSON().geometry.coordinates);
		});

		return L.GeoJSON.getFeature(this, {
			type: 'MultiPoint',
			coordinates: coords
		});
	},

	// @method toGeoJSON(): Object
	// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the layer group (as a GeoJSON `GeometryCollection`).
	toGeoJSON: function () {

		var type = this.feature && this.feature.geometry && this.feature.geometry.type;

		if (type === 'MultiPoint') {
			return this.toMultiPoint();
		}

		var isGeometryCollection = type === 'GeometryCollection',
		    jsons = [];

		this.eachLayer(function (layer) {
			if (layer.toGeoJSON) {
				var json = layer.toGeoJSON();
				jsons.push(isGeometryCollection ? json.geometry : L.GeoJSON.asFeature(json));
			}
		});

		if (isGeometryCollection) {
			return L.GeoJSON.getFeature(this, {
				geometries: jsons,
				type: 'GeometryCollection'
			});
		}

		return {
			type: 'FeatureCollection',
			features: jsons
		};
	}
});

// @namespace GeoJSON
// @factory L.geoJSON(geojson?: Object, options?: GeoJSON options)
// Creates a GeoJSON layer. Optionally accepts an object in
// [GeoJSON format](http://geojson.org/geojson-spec.html) to display on the map
// (you can alternatively add it later with `addData` method) and an `options` object.
L.geoJSON = function (geojson, options) {
	return new L.GeoJSON(geojson, options);
};
// Backward compatibility.
L.geoJson = L.geoJSON;
<|endoftext|>


<commit_before>/*
  Single review page for an add-on.

  Lists the add-on's versions, each with their own approve and reject buttons.
*/
import React from 'react';
import {connect, Provider} from 'react-redux';
import {ReverseLink} from 'react-router-reverse';
import {bindActionCreators} from 'redux';

import AddonVersionListingContainer from './versionListing';
import {fetch as fetchAddon} from '../actions/addon';
import {getInstalled as getInstalledAddons,
        install as installAddon} from '../actions/mozApps';
import {AddonForReviewDetail} from '../components/addon';
import AddonInstall from '../components/install';
import AddonSubnav from '../components/subnav';
import {Page, PageSection} from '../../site/components/page';

export class AddonReviewDetail extends React.Component {
  static contextTypes = {
    store: React.PropTypes.object,
  };
  static propTypes = {
    addon: React.PropTypes.object,
    fetchAddon: React.PropTypes.func.isRequired,
    getInstalledAddons: React.PropTypes.func.isRequired,
    installAddon: React.PropTypes.func.isRequired,
    slug: React.PropTypes.string.isRequired,
    user: React.PropTypes.object,
  };

  constructor(props) {
    super(props);
    this.props.fetchAddon(this.props.slug);
    this.props.getInstalledAddons();
  }

  render() {
    const addon = this.props.addon;

    if (!addon || !addon.slug) {
      return (
        <Page subnav={<AddonSubnav user={this.props.user}/>}
              title="Loading Firefox OS Add-on..."/>
      );
    }
    return (
      <Page breadcrumbText="Review Add-ons"
            breadcrumbTo="addon-review"
            className="addon-review-detail"
            title={`Reviewing Firefox OS Add-on: ${addon.name}`}
            subnav={<AddonSubnav user={this.props.user}/>}>
        <AddonForReviewDetail {...addon}/>

        {addon.latest_version &&
          <PageSection title="Install Add-on">
            <AddonInstall
              install={this.props.installAddon}
              installErrorMessage={addon.installErrorMessage}
              isInstalled={addon.isInstalled}
              isInstalling={addon.isInstalling}
              manifestUrl={addon.latest_version.reviewer_mini_manifest_url}
              slug={addon.slug}/>
          </PageSection>
        }

        <Provider store={this.context.store}>
          {() => <AddonVersionListingContainer showReviewActions={true}/>}
        </Provider>
      </Page>
    );
  }
};

export default connect(
  state => ({
    addon: state.addon.addons[state.router.params.slug],
    slug: state.router.params.slug
  }),
  dispatch => bindActionCreators({
    fetchAddon,
    getInstalledAddons,
    installAddon,
  }, dispatch)
)(AddonReviewDetail);
<commit_msg>redirect to queue after review (bug 1204697)<commit_after>/*
  Single review page for an add-on.

  Lists the add-on's versions, each with their own approve and reject buttons.
*/
import React from 'react';
import {connect, Provider} from 'react-redux';
import {reverse, ReverseLink} from 'react-router-reverse';
import {bindActionCreators} from 'redux';

import AddonVersionListingContainer from './versionListing';
import {fetch as fetchAddon} from '../actions/addon';
import {getInstalled as getInstalledAddons,
        install as installAddon} from '../actions/mozApps';
import {AddonForReviewDetail} from '../components/addon';
import AddonInstall from '../components/install';
import AddonSubnav from '../components/subnav';
import {Page, PageSection} from '../../site/components/page';

export class AddonReviewDetail extends React.Component {
  static contextTypes = {
    store: React.PropTypes.object,
    router: React.PropTypes.object
  };

  static propTypes = {
    addon: React.PropTypes.object,
    fetchAddon: React.PropTypes.func.isRequired,
    getInstalledAddons: React.PropTypes.func.isRequired,
    installAddon: React.PropTypes.func.isRequired,
    slug: React.PropTypes.string.isRequired,
    user: React.PropTypes.object,
  };

  constructor(props) {
    super(props);
    this.props.fetchAddon(this.props.slug);
    this.props.getInstalledAddons();
  }

  componentDidUpdate(prevProps) {
    // Add-on was reviewed, redirect back to reviewer queue.
    if (prevProps.addon.status !== this.props.addon.status) {
      const path = reverse(this.context.router.routes, 'addon-review');
      this.context.router.transitionTo(path);
    }
  }

  render() {
    const addon = this.props.addon;

    if (!addon || !addon.slug) {
      return (
        <Page subnav={<AddonSubnav user={this.props.user}/>}
              title="Loading Firefox OS Add-on..."/>
      );
    }
    return (
      <Page breadcrumbText="Review Add-ons"
            breadcrumbTo="addon-review"
            className="addon-review-detail"
            title={`Reviewing Firefox OS Add-on: ${addon.name}`}
            subnav={<AddonSubnav user={this.props.user}/>}>
        <AddonForReviewDetail {...addon}/>

        {addon.latest_version &&
          <PageSection title="Install Add-on">
            <AddonInstall
              install={this.props.installAddon}
              installErrorMessage={addon.installErrorMessage}
              isInstalled={addon.isInstalled}
              isInstalling={addon.isInstalling}
              manifestUrl={addon.latest_version.reviewer_mini_manifest_url}
              slug={addon.slug}/>
          </PageSection>
        }

        <Provider store={this.context.store}>
          {() => <AddonVersionListingContainer showReviewActions={true}/>}
        </Provider>
      </Page>
    );
  }
};

export default connect(
  state => ({
    addon: state.addon.addons[state.router.params.slug],
    slug: state.router.params.slug
  }),
  dispatch => bindActionCreators({
    fetchAddon,
    getInstalledAddons,
    installAddon,
  }, dispatch)
)(AddonReviewDetail);
<|endoftext|>


<commit_before>// Dependencies
var Gry = require("gry")
  , Abs = require("abs")
  , GitUrlParse = require("git-url-parse")
  , OneByOne = require("one-by-one")
  , ParentSearch = require("parent-search")
  , Deffy = require("deffy")
  ;

// Constants
// TODO Fix this to get the default remote origin
const REMOTE = "origin";

/**
 * SshRemote
 * Changes the remote url to use the ssh url.
 *
 * @name SshRemote
 * @function
 * @param {String} path The repository path.
 * @param {Function} callback The callback function.
 */
function SshRemote(path, callback) {

    if (typeof path === "function") {
        callback = path;
        path = process.cwd();
    } else {
        path = Deffy(path, process.cwd());
        callback = callback || function () {};
        path = Abs(path);
    }

    var repo = new Gry(path);
    OneByOne([
        ParentSearch.bind(this, path, ".git")
      , function (next, gitPath) {
            next(gitPath ? null : new Error("Cannot find the git repository"));
        }
      , repo.exec.bind(repo, "config --get remote." + REMOTE +".url")
      , function (next, remoteUrl) {
            var parsed = GitUrlParse(remoteUrl);
            if (parsed.protocol === "ssh") {
                return callback(null, "The remote url is already ssh.");
            }
            if (parsed.protocol === "file") {
                return next(new Error("The remote url points to another local directory."));
            }
            next(null, parsed.toString("ssh"));
        }
      , function (next, sshUrl) {
            repo.exec("remote set-url " + REMOTE + " " + sshUrl, next);
        }
    ], callback);
}

module.exports = SshRemote;
<commit_msg>Show a human readable error<commit_after>// Dependencies
var Gry = require("gry")
  , Abs = require("abs")
  , GitUrlParse = require("git-url-parse")
  , OneByOne = require("one-by-one")
  , ParentSearch = require("parent-search")
  , Deffy = require("deffy")
  ;

// Constants
// TODO Fix this to get the default remote origin
//      Contributions are welcome! :)
const REMOTE = "origin";

/**
 * SshRemote
 * Changes the remote url to use the ssh url.
 *
 * @name SshRemote
 * @function
 * @param {String} path The repository path.
 * @param {Function} callback The callback function.
 */
function SshRemote(path, callback) {

    if (typeof path === "function") {
        callback = path;
        path = process.cwd();
    } else {
        path = Deffy(path, process.cwd());
        callback = callback || function () {};
        path = Abs(path);
    }

    var repo = new Gry(path);
    OneByOne([
        ParentSearch.bind(this, path, ".git")
      , function (next, gitPath) {
            next(gitPath ? null : new Error("Cannot find the git repository"));
        }
      , repo.exec.bind(repo, "config --get remote." + REMOTE +".url")
      , function (next, remoteUrl) {
            var parsed = GitUrlParse(remoteUrl);
            if (parsed.protocol === "ssh") {
                return callback(null, "The remote url is already ssh.");
            }
            if (parsed.protocol === "file") {
                return next(new Error("The remote url points to another local directory."));
            }
            next(null, parsed.toString("ssh"));
        }
      , function (next, sshUrl) {
            repo.exec("remote set-url " + REMOTE + " " + sshUrl, next);
        }
    ], function (err, data) {
        if (err) {
            debugger
            if (err.message.indexOf("Command failed") !== -1) {
                err = new Error("Failed to get the git remote url. Do you have an origin url in this project?");
            }
        }
        callback(err, data);
    });
}

module.exports = SshRemote;
<|endoftext|>


<commit_before>var camera, controls, scene, renderer;

var tick = 0;
var lamp, water;

var rockClusters = [];

init();
render();
animate();

function init() {

    scene = new THREE.Scene();
    // scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 );
    scene.fog = new THREE.Fog(0xece9ca, 500, 2000);

    camera = new THREE.PerspectiveCamera( 45,
                                          window.innerWidth / window.innerHeight,
                                          1,
                                          1000 );

    camera.position.set( 0, -30, 20 );
    camera.lookAt( scene.position );

    renderer = new THREE.WebGLRenderer( { alpha: true,
                                          antialias: false } );
 	renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setClearColor( scene.fog.color, 1 );
    renderer.setSize( window.innerWidth, window.innerHeight );
	renderer.sortObjects = false;

    controls = new THREE.OrbitControls( camera );
    controls.addEventListener( 'change', render );

    document.body.appendChild( renderer.domElement );

    window.addEventListener( 'resize', onWindowResize, false );

    initializeLights();
    createEnvironment( Math.random() * 20 + 10, Math.random() * 30 + 10, 2 );
}

function onWindowResize() {

    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

    renderer.setSize( window.innerWidth, window.innerHeight );

    render();

}

function animate() {

    render();
    tick++;
    controls.update();
    requestAnimationFrame( animate );

}

function render() {

    renderer.render( scene, camera );

}

function initializeLights() {

    var sceneLight = new THREE.HemisphereLight(0xdddddd, 0x202020, .1);

    lamp = new THREE.DirectionalLight(0xdddddd, 1);
    lamp.position.set(0, 10, 30);
    lamp.castShadow = true;
    lamp.shadowDarkness = .5;

    var light = new THREE.DirectionalLight(0xdddddd, 1);
    light.position.set(-10, -10, 0);
    light.castShadow = true;
    light.shadowDarkness = .5;

    scene.add( sceneLight );
    scene.add( lamp );
    scene.add( light );

}

function createEnvironment( width, height, depth ) {

    var sand = createSand( width, height );
    var base = createBase( width, height, depth );

    var rock = basicRockFactory( 3, 2, 2 );
    rock.position.z -= depth / 2;

    scene.add( sand );
    scene.add( base );
    scene.add( rock );

}

function createSand( width, height ) {

    var geometry = new THREE.PlaneGeometry( width, height, width, height );

    // var texture = THREE.ImageUtils.loadTexture('img/sand.png');
    var material = new THREE.MeshPhongMaterial( { color : 0xfcfbdf,
                                                  shading : THREE.FlatShading,
                                                  shininess : 10,
                                                  refractionRatio : 0.5 } );

    for ( var i = 0; i < geometry.vertices.length; i++ ) {
        var vertex = geometry.vertices[i];
        vertex.z = peturb( vertex.z, .25 );
    }

    geometry.computeFaceNormals();
    geometry.computeVertexNormals();

    var mesh = new THREE.Mesh( geometry, material );
    mesh.receiveShadow = true;
    mesh.castShadow = true;

    return mesh;

}

function createBase( width, height, depth ) {

    var offset = 1;
    var baseFloor = boxFactory( width + offset, height + offset, offset );
    baseFloor.position.z = -depth;

    var baseNorth = boxFactory( width + offset, offset, depth );
    baseNorth.position.y = height / 2;
    baseNorth.position.z = -depth / 2 + offset / 2;

    var baseSouth = boxFactory( width + offset, offset, depth );
    baseSouth.position.y = -height / 2;
    baseSouth.position.z = -depth / 2 + offset / 2;

    var baseEast = boxFactory( offset, height - offset, depth );
    baseEast.position.x = width / 2;
    baseEast.position.z = -depth / 2 + offset / 2;

    var baseWest = boxFactory( offset, height - offset, depth );
    baseWest.position.x = -width / 2;
    baseWest.position.z = -depth / 2 + offset / 2;

    var geometry = mergeMeshGeometry( [ baseFloor,
                                        baseNorth,
                                        baseSouth,
                                        baseEast,
                                        baseWest ] );
    geometry.computeFaceNormals();
    geometry.computeVertexNormals();
    var material = new THREE.MeshPhongMaterial( { color : 0x996633,
                                                  shading : THREE.FlatShading,
                                                  shininess : 5,
                                                  refractionRatio : 0.1 } );

    var mesh = new THREE.Mesh( geometry, material );
    mesh.receiveShadow = true;
    mesh.castShadow = true;

    return mesh;
}

function boxFactory( width, height, depth, attributes ) {

    var geometry = new THREE.BoxGeometry( width, height, depth );
    var material = new THREE.MeshBasicMaterial( attributes );

    var mesh = new THREE.Mesh( geometry, material );

    return mesh;

}

function basicRockFactory( width, height, depth, attributes ) {

    var geometry = new THREE.BoxGeometry( width, height, 0.01, width * 2, height * 2, 10 );

    var axis = new THREE.Vector3( peturb( 0, width ), peturb( 0, height ), 0 );
    var maxDist = Math.sqrt( width * width + height * height );

    for ( var i = 0; i < geometry.vertices.length; i++ ) {
        var vertex = geometry.vertices[i];
        vertex.x = peturb( vertex.x, 0.1 );
        vertex.y = peturb( vertex.y, 0.1 );

        if ( vertex.z == 0.005 ) {
            vertex.z = peturb( ( maxDist - vertex.distanceTo( axis ) ) * 3 * depth / 4, depth / 4 );
        }
    }
    geometry.computeFaceNormals();
    geometry.computeVertexNormals();

    var material = new THREE.MeshPhongMaterial( { color : 0x202020,
                                                  shading : THREE.FlatShading,
                                                  shininess : 20,
                                                  refractionRatio : 0.1 } );
    var mesh = new THREE.Mesh( geometry, material );
    mesh.receiveShadow = true;
    mesh.castShadow = true;

    rockClusters.push( mesh );

    return mesh;

}

function peturb( value, range ) {

    return value + ( Math.random() * range ) - ( range / 2 ) ;

}

function mergeMeshGeometry( meshes ) {

    var combined = new THREE.Geometry();

    for ( var i = 0; i < meshes.length; i++ ) {
        meshes[i].updateMatrix();

        combined.merge(meshes[i].geometry, meshes[i].matrix);
    }

    return combined;

}
<commit_msg>Beginning lantern creation.<commit_after>var camera, controls, scene, renderer;

var tick = 0;
var lamp, water;

var rockClusters = [];

init();
render();
animate();

function init() {

    scene = new THREE.Scene();
    // scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 );
    scene.fog = new THREE.Fog(0xece9ca, 500, 2000);

    camera = new THREE.PerspectiveCamera( 45,
                                          window.innerWidth / window.innerHeight,
                                          1,
                                          1000 );

    camera.position.set( 0, -30, 20 );
    camera.lookAt( scene.position );

    renderer = new THREE.WebGLRenderer( { alpha: true,
                                          antialias: false } );
 	renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setClearColor( scene.fog.color, 1 );
    renderer.setSize( window.innerWidth, window.innerHeight );
	renderer.sortObjects = false;

    controls = new THREE.OrbitControls( camera );
    controls.addEventListener( 'change', render );

    document.body.appendChild( renderer.domElement );

    window.addEventListener( 'resize', onWindowResize, false );

    initializeLights();
    createEnvironment( Math.random() * 20 + 10, Math.random() * 30 + 10, 2 );
}

function onWindowResize() {

    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

    renderer.setSize( window.innerWidth, window.innerHeight );

    render();

}

function animate() {

    render();
    tick++;
    controls.update();
    requestAnimationFrame( animate );

}

function render() {

    renderer.render( scene, camera );

}

function initializeLights() {

    var sceneLight = new THREE.HemisphereLight(0xdddddd, 0x202020, .1);

    lamp = new THREE.DirectionalLight(0xdddddd, 1);
    lamp.position.set(0, 10, 30);
    lamp.castShadow = true;
    lamp.shadowDarkness = .5;

    var light = new THREE.DirectionalLight(0xdddddd, 1);
    light.position.set(-10, -10, 0);
    light.castShadow = true;
    light.shadowDarkness = .5;

    scene.add( sceneLight );
    scene.add( lamp );
    scene.add( light );

}

function createEnvironment( width, height, depth ) {

    var sand = createSand( width, height );
    var base = createBase( width, height, depth );

    var rock = basicRockFactory( 3, 2, 2 );
    rock.position.z -= depth / 2;

    var lantern = lanternFactory( 3, 3, 3, 3 );
    lantern.position.z += 5;

    scene.add( sand );
    scene.add( base );
    scene.add( rock );
    scene.add( lantern );

}

function createSand( width, height ) {

    var geometry = new THREE.PlaneGeometry( width, height, width, height );

    // var texture = THREE.ImageUtils.loadTexture('img/sand.png');
    var material = new THREE.MeshPhongMaterial( { color : 0xfcfbdf,
                                                  shading : THREE.FlatShading,
                                                  shininess : 10,
                                                  refractionRatio : 0.5 } );

    for ( var i = 0; i < geometry.vertices.length; i++ ) {
        var vertex = geometry.vertices[i];
        vertex.z = peturb( vertex.z, .25 );
    }

    geometry.computeFaceNormals();
    geometry.computeVertexNormals();

    var mesh = new THREE.Mesh( geometry, material );
    mesh.receiveShadow = true;
    mesh.castShadow = true;

    return mesh;

}

function createBase( width, height, depth ) {

    var offset = 1;
    var baseFloor = boxFactory( width + offset, height + offset, offset );
    baseFloor.position.z = -depth;

    var baseNorth = boxFactory( width + offset, offset, depth );
    baseNorth.position.y = height / 2;
    baseNorth.position.z = -depth / 2 + offset / 2;

    var baseSouth = boxFactory( width + offset, offset, depth );
    baseSouth.position.y = -height / 2;
    baseSouth.position.z = -depth / 2 + offset / 2;

    var baseEast = boxFactory( offset, height - offset, depth );
    baseEast.position.x = width / 2;
    baseEast.position.z = -depth / 2 + offset / 2;

    var baseWest = boxFactory( offset, height - offset, depth );
    baseWest.position.x = -width / 2;
    baseWest.position.z = -depth / 2 + offset / 2;

    var geometry = mergeMeshGeometry( [ baseFloor,
                                        baseNorth,
                                        baseSouth,
                                        baseEast,
                                        baseWest ] );
    geometry.computeFaceNormals();
    geometry.computeVertexNormals();
    var material = new THREE.MeshPhongMaterial( { color : 0x996633,
                                                  shading : THREE.FlatShading,
                                                  shininess : 5,
                                                  refractionRatio : 0.1 } );

    var mesh = new THREE.Mesh( geometry, material );
    mesh.receiveShadow = true;
    mesh.castShadow = true;

    return mesh;
}

function lanternFactory( width, height, depth, postDepth ) {

    var lantern = new THREE.Group();

    var lightContainer = boxFactory( width / 2,
                                     height / 2,
                                     depth / 2,
                                     {
                                     } );

    lantern.traverse( function( object ) {

        if ( object instanceof THREE.Mesh ) {
            object.castShadow = true;
            object.receiveShadow = true;
        }

    } );

    return lantern;

}

function boxFactory( width, height, depth, attributes ) {

    var geometry = new THREE.BoxGeometry( width, height, depth );
    var material = new THREE.MeshPhongMaterial( attributes );

    var mesh = new THREE.Mesh( geometry, material );

    return mesh;

}

function basicRockFactory( width, height, depth, attributes ) {

    var geometry = new THREE.BoxGeometry( width, height, 0.01, width * 2, height * 2, 10 );

    var axis = new THREE.Vector3( peturb( 0, width ), peturb( 0, height ), 0 );
    var maxDist = Math.sqrt( width * width + height * height );

    for ( var i = 0; i < geometry.vertices.length; i++ ) {
        var vertex = geometry.vertices[i];
        vertex.x = peturb( vertex.x, 0.1 );
        vertex.y = peturb( vertex.y, 0.1 );

        if ( vertex.z == 0.005 ) {
            vertex.z = peturb( ( maxDist - vertex.distanceTo( axis ) ) * 3 * depth / 4, depth / 4 );
        }
    }
    geometry.computeFaceNormals();
    geometry.computeVertexNormals();

    var material = new THREE.MeshPhongMaterial( { color : 0x202020,
                                                  shading : THREE.FlatShading,
                                                  shininess : 20,
                                                  refractionRatio : 0.1 } );
    var mesh = new THREE.Mesh( geometry, material );
    mesh.receiveShadow = true;
    mesh.castShadow = true;

    rockClusters.push( mesh );

    return mesh;

}

function peturb( value, range ) {

    return value + ( Math.random() * range ) - ( range / 2 ) ;

}

function mergeMeshGeometry( meshes ) {

    var combined = new THREE.Geometry();

    for ( var i = 0; i < meshes.length; i++ ) {
        meshes[i].updateMatrix();

        combined.merge(meshes[i].geometry, meshes[i].matrix);
    }

    return combined;

}
<|endoftext|>


<commit_before>var gulp = require('gulp');
var chug = require('gulp-chug');
var gulpWebpack = require('webpack-stream');
var sass = require('gulp-sass');
var rename = require('gulp-rename');
var minifyCss = require('gulp-minify-css');
var file = require('gulp-file');
var preprocess = require('gulp-preprocess');
var gulpif = require('gulp-if');
var prompt = require('gulp-prompt');
var bump = require('gulp-bump');
var git = require('gulp-git');
var assign = require('object-assign');
var webpack = require('webpack');
var del = require('del');
var path = require('path');
var fs = require('fs');
var coveralls = require('gulp-coveralls');
var blanket = require('gulp-blanket-mocha');
var runSequence = require('run-sequence');
var spawn = require('child_process').spawn;
var mkdirp = require('mkdirp');

function getPackageJSON() {
  delete require.cache[require.resolve('./package.json')];
  var packageJSON = require('./package.json');
  delete packageJSON.devDependencies;
  delete packageJSON.config;
  packageJSON.main = 'index.js';
  packageJSON.dependencies = {
    'react': '^0.13.1',
    'react-intl': '^1.2.0',
    'inuit-box-sizing': '~0.2.0',
    'inuit-clearfix': '^0.2.1',
    'inuit-defaults': '~0.2.1',
    'inuit-functions': '~0.2.0',
    'inuit-headings': '~0.3.0',
    'inuit-images': '~0.3.3',
    'inuit-list-bare': '~0.3.0',
    'inuit-lists': '~0.1.0',
    'inuit-mixins': '~0.2.3',
    'inuit-normalize': '~3.0.2',
    'inuit-page': '~0.2.1',
    'inuit-reset': '~0.1.1',
    'inuit-responsive-settings': '~0.1.2',
    'inuit-responsive-tools': '~0.1.1',
    'inuit-shared': '~0.1.5',
    'mkdirp': '^0.5.0',
    'gulp': '^3.8.11',
    'gulp-template': '^3.0.0',
    'gulp-install': '^0.4.0',
    "lodash": "^3.8.0",
    "reflux": "^0.2.7",
    "superagent": "^1.1.0",
    "yargs": "^3.8.0"
  };
  return packageJSON;
}

var opts = {
  dist: path.resolve(__dirname, 'dist'),
  copyAssets: [
    'README.md',
    'src/js/**',
    {
      asset: 'src/scss/**',
      dist: 'dist/scss/'
    },
    {
      asset: 'src/utils/**',
      dist: 'dist/utils/'
    },
    'src/img/**',
    {
      asset: 'bin/**',
      dist: 'dist/bin/'
    },
    {
      asset: 'templates/**',
      dist: 'dist/templates/'
    },
    {
      asset: 'examples/**',
      dist: 'dist/examples/',
      ignores: [
        'node_modules/',
        'dist/'
      ]
    },
    {
      filename: 'package.json',
      asset: JSON.stringify(getPackageJSON(), null, 2)
    },
    {
      asset: 'src/utils/gulp/.eslintrc',
      dist: 'dist/utils/gulp/'
    }
  ],
  scssAssets: ['src/scss/**/*.scss'],
  jsAssets: [
    'src/js/**/*.js',
    'src/utils/**/*.js',
    'test/**/*.js',
    'examples/cto-app-tuner/src/**/*.js',
    'examples/server/*.js'
  ],
  mainJs: 'src/js/index.js',
  mainScss: 'src/scss/grommet-core/index.scss',
  sync: {
    hostname: 'grommet.io',
    username: 'grommet',
    remoteDestination: '/var/www/html/assets/' + getPackageJSON().version
  },
  webpack: {
    output: {
      filename: 'grommet.min.js',
      libraryTarget: 'var',
      library: 'Grommet'
    },
    resolve: {
      modulesDirectories: ['node_modules', 'src/js', 'src/scss']
    },
    externals: {
      'react': 'React'
    }
  },
  distPreprocess: ['dist-css'],
  scsslint: true,
  testPaths: [
    'test/**/*.js'
  ]
};

require('./src/utils/gulp/gulp-tasks')(gulp, opts);

gulp.task('dist-css', function() {
  gulp.src('src/scss/hpinc/*.scss')
    .pipe(sass({
      includePaths: [path.resolve(__dirname, './node_modules')]
    }))
    .pipe(rename('grommet-hpinc.min.css'))
    .pipe(minifyCss())
    .pipe(gulp.dest('dist/'));

  gulp.src('src/scss/hpe/*.scss')
    .pipe(sass({
      includePaths: [path.resolve(__dirname, './node_modules')]
    }))
    .pipe(rename('grommet-hpe.min.css'))
    .pipe(minifyCss())
    .pipe(gulp.dest('dist/'));

  return gulp.src('src/scss/grommet-core/*.scss')
    .pipe(sass({
      includePaths: [path.resolve(__dirname, './node_modules')]
    }))
    .pipe(rename('grommet.min.css'))
    .pipe(minifyCss())
    .pipe(gulp.dest('dist/'));
});

gulp.task('sync-all', function() {

  gulp.src('./examples/demo/gulpfile.js', {
    read: false
  }).pipe(chug({
    tasks: ['sync']
  }));

  gulp.src('./examples/tour/gulpfile.js', {
    read: false
  }).pipe(chug({
    tasks: ['sync']
  }));

  gulp.src('./examples/server/gulpfile.js', {
    read: false
  }).pipe(chug({
    tasks: ['sync']
  }));

  gulp.src('./docs/gulpfile.js', {
    read: false
  }).pipe(chug({
    tasks: ['sync']
  }));

  gulp.src('./gulpfile.js', {
    read: false
  }).pipe(chug({
    tasks: ['sync']
  }));
});

var bowerWebpackConfig = {
  output: {
    filename: 'grommet.js',
    libraryTarget: 'var',
    library: 'Grommet'
  },
  resolve: {
    root: [
      path.resolve(__dirname, 'src/js'),
      path.resolve(__dirname, 'src/scss'),
      path.resolve(__dirname, 'node_modules')
    ],
    extensions: ['', '.js', '.json', '.htm', '.html', '.scss']
  },
  externals: {
    'react': 'React'
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        loader: 'jsx-loader'
      },
      {
        test: /\.json$/,
        loader: 'json-loader'
      },
      {
        test: /\.svg$/,
        loader: 'file-loader?mimetype=image/svg'
      },
      {
        test: /\.jpg$/,
        loader: 'file-loader?mimetype=image/jpg'
      },
      {
        test: /\.woff$/,
        loader: 'file-loader?mimetype=application/font-woff'
      }
    ]
  },
  plugins: [
    //new webpack.optimize.DedupePlugin()
  ]
};

var bowerMinWebpackConfig = assign({}, bowerWebpackConfig, {
  output: {
    filename: 'grommet.min.js',
    libraryTarget: 'var',
    library: 'Grommet'
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      }
    })
  //new webpack.optimize.DedupePlugin()
  ]
});

function distCss(path, name, minify) {
  gulp.src(path)
    .pipe(sass({
      includePaths: ['node_modules']
    }))
    .pipe(rename(name))
    .pipe(gulpif(minify, minifyCss()))
    .pipe(gulp.dest('dist-bower/css'));
}

function distBower(config) {
  return gulp.src(opts.mainJs)
    .pipe(gulpWebpack(config))
    .pipe(gulp.dest('dist-bower'));
}

gulp.task('dist-bower:exploded', function() {
  distBower(bowerWebpackConfig);
});

gulp.task('dist-bower:minified', function() {
  distBower(bowerMinWebpackConfig);
});

gulp.task('dist-bower:preprocess', function(done) {
  del.sync(['dist-bower']);
  runSequence(['dist-bower:exploded', 'dist-bower:minified'], done);
});

gulp.task('dist-bower', ['dist-bower:preprocess'], function() {

  distCss('src/scss/grommet-core/*.scss', 'grommet.css');
  distCss('src/scss/grommet-core/*.scss', 'grommet.min.css', true);
  distCss('src/scss/hpe/*.scss', 'grommet-hpe.css');
  distCss('src/scss/hpe/*.scss', 'grommet-hpe.min.css', true);
  distCss('src/scss/hpinc/*.scss', 'grommet-hpinc.css');
  distCss('src/scss/hpinc/*.scss', 'grommet-hpinc.min.css', true);

  //sample-grommet
  gulp.src('examples/todo-app/index.html')
    .pipe(preprocess({
      context: {
        NODE_ENV: 'production'
      }
    }))
    .pipe(rename('sample-grommet.html'))
    .pipe(gulp.dest('dist-bower'));

  var bowerJSON = getPackageJSON();
  bowerJSON.dependencies = {
    'react': '^0.13.1',
    'grommet': 'HewlettPackard/grommet-bower'
  };
  bowerJSON.main = 'grommet.js';
  delete bowerJSON.devDependencies;
  delete bowerJSON.scripts;
  delete bowerJSON.config;

  return gulp.src('.')
    .pipe(file('bower.json', JSON.stringify(bowerJSON, null, 2)))
    .pipe(gulp.dest('dist-bower'));
});

gulp.task('blanket-lcov-reporter', function(done) {
  require('./src/utils/test/test-compiler');
  require('./src/utils/test/mocked-dom')('');

  gulp.src('./test/**/*.js', {
    read: false
  }).pipe(blanket({
    instrument: [path.join(__dirname, 'src/js')],
    captureFile: 'test/lcov.info',
    reporter: 'mocha-lcov-reporter'
  }));

  done();
});

gulp.task('coveralls', function() {
  var lcovPath = './test/lcov.info';
  fs.exists(lcovPath, function(exists) {
    if (exists) {
      gulp.src(lcovPath).pipe(coveralls());
    } else {
      console.error('Could not find lcov report file.');
      process.exit(1);
    }
  });
});

gulp.task('release:bump', function(done) {
  gulp.src('./')
    .pipe(prompt.prompt({
      type: 'input',
      name: 'bump',
      message: 'What type of bump would you like to do (patch, minor, major)?',
      validate: function(pass) {
        if (pass !== 'patch' && pass !== 'minor' && pass !== 'major') {
          return false;
        }
        return true;
      }
    }, function(res) {
      gulp.src('./package.json')
        .pipe(bump({
          type: res.bump
        }))
        .pipe(gulp.dest('./')).on('end', function() {
        opts.copyAssets.push({
          filename: 'package.json',
          asset: JSON.stringify(getPackageJSON(), null, 2)
        });
        done();
      });
    }));
});

gulp.task('release:npm', function(done) {
  process.chdir('dist');
  spawn('npm', ['publish'], {
    stdio: 'inherit'
  }).on('close', function() {
    process.chdir(__dirname);
    var version = 'v' + getPackageJSON().version;
    gulp.src('./')
      .pipe(git.add({
        args: '--all'
      }))
      .pipe(git.commit(version)).on('end', function() {
      git.push('origin', 'master', function(err) {
        if (err) {
          throw err;
        }

        git.tag(version, version, function(err) {
          if (err) {
            throw err;
          }

          git.push('origin', version, function(err) {
            if (err) {
              throw err;
            }
            process.chdir(__dirname);
            done();
          });
        });
      });
    });
  });
});

gulp.task('release:createTmp', function(done) {
  del.sync(['./tmp']);
  mkdirp('./tmp', function(err) {
    if (err) {
      throw err;
    }
    done();
  });
});

gulp.task('release:bower', ['release:createTmp'], function(done) {
  git.clone('https://github.com/HewlettPackard/grommet-bower.git',
    {
      cwd: './tmp/'
    },
    function(err) {
      if (err) {
        throw err;
      }
      gulp.src('./dist-bower/**').pipe(gulp.dest('./tmp/grommet-bower'));

      var version = 'v' + getPackageJSON().version;
      process.chdir('./tmp/grommet-bower');
      gulp.src('./')
        .pipe(git.add({
          args: '--all'
        }))
        .pipe(git.commit(version)).on('end', function() {
        git.push('origin', 'master', function(err) {
          if (err) {
            throw err;
          }

          git.tag(version, version, function(err) {
            if (err) {
              throw err;
            }

            git.push('origin', version, function(err) {
              if (err) {
                throw err;
              }
              process.chdir(__dirname);
              done();
            });
          });
        });
      });
    }
  );
});

gulp.task('release:stable', ['dist', 'release:createTmp'], function(done) {
  if (process.env.CI) {
    git.clone('https://' + process.env.GH_TOKEN + '@github.com/HewlettPackard/grommet.git',
      {
        cwd: './tmp/'
      },
      function(err) {
        if (err) {
          throw err;
        }

        process.chdir('./tmp/grommet');
        git.checkout('stable', function(err) {
          if (err) {
            throw err;
          }

          gulp.src('../../dist/**').pipe(gulp.dest('./')).on('end', function() {
            git.status({
              args: '--porcelain'
            }, function(err, stdout) {
              if (err) {
                throw err;
              }

              if (stdout && stdout !== '') {
                gulp.src('./')
                  .pipe(git.add({
                    args: '--all'
                  }))
                  .pipe(git.commit('Stable dev version update.')).on('end', function() {
                  git.push('origin', 'stable', { quiet: true }, function(err) {
                    if (err) {
                      throw err;
                    }

                    process.chdir(__dirname);
                    done();
                  });
                });
              } else {
                console.log('No difference since last commit, skipping stable release.');

                process.chdir(__dirname);
                done();
              }
            });
          });
        });
      }
    );
  } else {
    console.warn('Skipping release. Release:stable task should be executed by CI only.');
  }
});

gulp.task('release:clean', function() {
  del.sync(['./tmp']);
});

gulp.task('release:site', function() {
  gulp.src('./docs/gulpfile.js', {
    read: false
  }).pipe(chug({
    tasks: ['sync']
  }));

  gulp.src('./examples/server/gulpfile.js', {
    read: false
  }).pipe(chug({
    tasks: ['sync']
  }));

  gulp.src('./examples/medium-app/gulpfile.js', {
    read: false
  }).pipe(chug({
    tasks: ['sync']
  }));
});

gulp.task('release', function(done) {
  runSequence('release:bump', ['dist-bower', 'dist'], 'release:npm', 'release:bower', 'release:clean', 'release:site', done);
});
<commit_msg>Avoid running gulp dev from Grommet root folder.<commit_after>var gulp = require('gulp');
var chug = require('gulp-chug');
var gulpWebpack = require('webpack-stream');
var sass = require('gulp-sass');
var rename = require('gulp-rename');
var minifyCss = require('gulp-minify-css');
var file = require('gulp-file');
var preprocess = require('gulp-preprocess');
var gulpif = require('gulp-if');
var prompt = require('gulp-prompt');
var bump = require('gulp-bump');
var git = require('gulp-git');
var assign = require('object-assign');
var webpack = require('webpack');
var del = require('del');
var path = require('path');
var fs = require('fs');
var coveralls = require('gulp-coveralls');
var blanket = require('gulp-blanket-mocha');
var runSequence = require('run-sequence');
var spawn = require('child_process').spawn;
var mkdirp = require('mkdirp');

function getPackageJSON() {
  delete require.cache[require.resolve('./package.json')];
  var packageJSON = require('./package.json');
  delete packageJSON.devDependencies;
  delete packageJSON.config;
  packageJSON.main = 'index.js';
  packageJSON.dependencies = {
    'react': '^0.13.1',
    'react-intl': '^1.2.0',
    'inuit-box-sizing': '~0.2.0',
    'inuit-clearfix': '^0.2.1',
    'inuit-defaults': '~0.2.1',
    'inuit-functions': '~0.2.0',
    'inuit-headings': '~0.3.0',
    'inuit-images': '~0.3.3',
    'inuit-list-bare': '~0.3.0',
    'inuit-lists': '~0.1.0',
    'inuit-mixins': '~0.2.3',
    'inuit-normalize': '~3.0.2',
    'inuit-page': '~0.2.1',
    'inuit-reset': '~0.1.1',
    'inuit-responsive-settings': '~0.1.2',
    'inuit-responsive-tools': '~0.1.1',
    'inuit-shared': '~0.1.5',
    'mkdirp': '^0.5.0',
    'gulp': '^3.8.11',
    'gulp-template': '^3.0.0',
    'gulp-install': '^0.4.0',
    "lodash": "^3.8.0",
    "reflux": "^0.2.7",
    "superagent": "^1.1.0",
    "yargs": "^3.8.0"
  };
  return packageJSON;
}

var opts = {
  dist: path.resolve(__dirname, 'dist'),
  copyAssets: [
    'README.md',
    'src/js/**',
    {
      asset: 'src/scss/**',
      dist: 'dist/scss/'
    },
    {
      asset: 'src/utils/**',
      dist: 'dist/utils/'
    },
    'src/img/**',
    {
      asset: 'bin/**',
      dist: 'dist/bin/'
    },
    {
      asset: 'templates/**',
      dist: 'dist/templates/'
    },
    {
      asset: 'examples/**',
      dist: 'dist/examples/',
      ignores: [
        'node_modules/',
        'dist/'
      ]
    },
    {
      filename: 'package.json',
      asset: JSON.stringify(getPackageJSON(), null, 2)
    },
    {
      asset: 'src/utils/gulp/.eslintrc',
      dist: 'dist/utils/gulp/'
    }
  ],
  scssAssets: ['src/scss/**/*.scss'],
  jsAssets: [
    'src/js/**/*.js',
    'src/utils/**/*.js',
    'test/**/*.js',
    'examples/cto-app-tuner/src/**/*.js',
    'examples/server/*.js'
  ],
  mainJs: 'src/js/index.js',
  mainScss: 'src/scss/grommet-core/index.scss',
  sync: {
    hostname: 'grommet.io',
    username: 'grommet',
    remoteDestination: '/var/www/html/assets/' + getPackageJSON().version
  },
  webpack: {
    output: {
      filename: 'grommet.min.js',
      libraryTarget: 'var',
      library: 'Grommet'
    },
    resolve: {
      modulesDirectories: ['node_modules', 'src/js', 'src/scss']
    },
    externals: {
      'react': 'React'
    }
  },
  distPreprocess: ['dist-css'],
  scsslint: true,
  testPaths: [
    'test/**/*.js'
  ]
};

require('./src/utils/gulp/gulp-tasks')(gulp, opts);

gulp.task('dist-css', function() {
  gulp.src('src/scss/hpinc/*.scss')
    .pipe(sass({
      includePaths: [path.resolve(__dirname, './node_modules')]
    }))
    .pipe(rename('grommet-hpinc.min.css'))
    .pipe(minifyCss())
    .pipe(gulp.dest('dist/'));

  gulp.src('src/scss/hpe/*.scss')
    .pipe(sass({
      includePaths: [path.resolve(__dirname, './node_modules')]
    }))
    .pipe(rename('grommet-hpe.min.css'))
    .pipe(minifyCss())
    .pipe(gulp.dest('dist/'));

  return gulp.src('src/scss/grommet-core/*.scss')
    .pipe(sass({
      includePaths: [path.resolve(__dirname, './node_modules')]
    }))
    .pipe(rename('grommet.min.css'))
    .pipe(minifyCss())
    .pipe(gulp.dest('dist/'));
});

gulp.task('sync-all', function() {

  gulp.src('./examples/demo/gulpfile.js', {
    read: false
  }).pipe(chug({
    tasks: ['sync']
  }));

  gulp.src('./examples/tour/gulpfile.js', {
    read: false
  }).pipe(chug({
    tasks: ['sync']
  }));

  gulp.src('./examples/server/gulpfile.js', {
    read: false
  }).pipe(chug({
    tasks: ['sync']
  }));

  gulp.src('./docs/gulpfile.js', {
    read: false
  }).pipe(chug({
    tasks: ['sync']
  }));

  gulp.src('./gulpfile.js', {
    read: false
  }).pipe(chug({
    tasks: ['sync']
  }));
});

var bowerWebpackConfig = {
  output: {
    filename: 'grommet.js',
    libraryTarget: 'var',
    library: 'Grommet'
  },
  resolve: {
    root: [
      path.resolve(__dirname, 'src/js'),
      path.resolve(__dirname, 'src/scss'),
      path.resolve(__dirname, 'node_modules')
    ],
    extensions: ['', '.js', '.json', '.htm', '.html', '.scss']
  },
  externals: {
    'react': 'React'
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        loader: 'jsx-loader'
      },
      {
        test: /\.json$/,
        loader: 'json-loader'
      },
      {
        test: /\.svg$/,
        loader: 'file-loader?mimetype=image/svg'
      },
      {
        test: /\.jpg$/,
        loader: 'file-loader?mimetype=image/jpg'
      },
      {
        test: /\.woff$/,
        loader: 'file-loader?mimetype=application/font-woff'
      }
    ]
  },
  plugins: [
    //new webpack.optimize.DedupePlugin()
  ]
};

var bowerMinWebpackConfig = assign({}, bowerWebpackConfig, {
  output: {
    filename: 'grommet.min.js',
    libraryTarget: 'var',
    library: 'Grommet'
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      }
    })
  //new webpack.optimize.DedupePlugin()
  ]
});

function distCss(path, name, minify) {
  gulp.src(path)
    .pipe(sass({
      includePaths: ['node_modules']
    }))
    .pipe(rename(name))
    .pipe(gulpif(minify, minifyCss()))
    .pipe(gulp.dest('dist-bower/css'));
}

function distBower(config) {
  return gulp.src(opts.mainJs)
    .pipe(gulpWebpack(config))
    .pipe(gulp.dest('dist-bower'));
}

gulp.task('dist-bower:exploded', function() {
  distBower(bowerWebpackConfig);
});

gulp.task('dist-bower:minified', function() {
  distBower(bowerMinWebpackConfig);
});

gulp.task('dist-bower:preprocess', function(done) {
  del.sync(['dist-bower']);
  runSequence(['dist-bower:exploded', 'dist-bower:minified'], done);
});

gulp.task('dist-bower', ['dist-bower:preprocess'], function() {

  distCss('src/scss/grommet-core/*.scss', 'grommet.css');
  distCss('src/scss/grommet-core/*.scss', 'grommet.min.css', true);
  distCss('src/scss/hpe/*.scss', 'grommet-hpe.css');
  distCss('src/scss/hpe/*.scss', 'grommet-hpe.min.css', true);
  distCss('src/scss/hpinc/*.scss', 'grommet-hpinc.css');
  distCss('src/scss/hpinc/*.scss', 'grommet-hpinc.min.css', true);

  //sample-grommet
  gulp.src('examples/todo-app/index.html')
    .pipe(preprocess({
      context: {
        NODE_ENV: 'production'
      }
    }))
    .pipe(rename('sample-grommet.html'))
    .pipe(gulp.dest('dist-bower'));

  var bowerJSON = getPackageJSON();
  bowerJSON.dependencies = {
    'react': '^0.13.1',
    'grommet': 'HewlettPackard/grommet-bower'
  };
  bowerJSON.main = 'grommet.js';
  delete bowerJSON.devDependencies;
  delete bowerJSON.scripts;
  delete bowerJSON.config;

  return gulp.src('.')
    .pipe(file('bower.json', JSON.stringify(bowerJSON, null, 2)))
    .pipe(gulp.dest('dist-bower'));
});

gulp.task('blanket-lcov-reporter', function(done) {
  require('./src/utils/test/test-compiler');
  require('./src/utils/test/mocked-dom')('');

  gulp.src('./test/**/*.js', {
    read: false
  }).pipe(blanket({
    instrument: [path.join(__dirname, 'src/js')],
    captureFile: 'test/lcov.info',
    reporter: 'mocha-lcov-reporter'
  }));

  done();
});

gulp.task('coveralls', function() {
  var lcovPath = './test/lcov.info';
  fs.exists(lcovPath, function(exists) {
    if (exists) {
      gulp.src(lcovPath).pipe(coveralls());
    } else {
      console.error('Could not find lcov report file.');
      process.exit(1);
    }
  });
});

gulp.task('release:bump', function(done) {
  gulp.src('./')
    .pipe(prompt.prompt({
      type: 'input',
      name: 'bump',
      message: 'What type of bump would you like to do (patch, minor, major)?',
      validate: function(pass) {
        if (pass !== 'patch' && pass !== 'minor' && pass !== 'major') {
          return false;
        }
        return true;
      }
    }, function(res) {
      gulp.src('./package.json')
        .pipe(bump({
          type: res.bump
        }))
        .pipe(gulp.dest('./')).on('end', function() {
        opts.copyAssets.push({
          filename: 'package.json',
          asset: JSON.stringify(getPackageJSON(), null, 2)
        });
        done();
      });
    }));
});

gulp.task('release:npm', function(done) {
  process.chdir('dist');
  spawn('npm', ['publish'], {
    stdio: 'inherit'
  }).on('close', function() {
    process.chdir(__dirname);
    var version = 'v' + getPackageJSON().version;
    gulp.src('./')
      .pipe(git.add({
        args: '--all'
      }))
      .pipe(git.commit(version)).on('end', function() {
      git.push('origin', 'master', function(err) {
        if (err) {
          throw err;
        }

        git.tag(version, version, function(err) {
          if (err) {
            throw err;
          }

          git.push('origin', version, function(err) {
            if (err) {
              throw err;
            }
            process.chdir(__dirname);
            done();
          });
        });
      });
    });
  });
});

gulp.task('release:createTmp', function(done) {
  del.sync(['./tmp']);
  mkdirp('./tmp', function(err) {
    if (err) {
      throw err;
    }
    done();
  });
});

gulp.task('release:bower', ['release:createTmp'], function(done) {
  git.clone('https://github.com/HewlettPackard/grommet-bower.git',
    {
      cwd: './tmp/'
    },
    function(err) {
      if (err) {
        throw err;
      }
      gulp.src('./dist-bower/**').pipe(gulp.dest('./tmp/grommet-bower'));

      var version = 'v' + getPackageJSON().version;
      process.chdir('./tmp/grommet-bower');
      gulp.src('./')
        .pipe(git.add({
          args: '--all'
        }))
        .pipe(git.commit(version)).on('end', function() {
        git.push('origin', 'master', function(err) {
          if (err) {
            throw err;
          }

          git.tag(version, version, function(err) {
            if (err) {
              throw err;
            }

            git.push('origin', version, function(err) {
              if (err) {
                throw err;
              }
              process.chdir(__dirname);
              done();
            });
          });
        });
      });
    }
  );
});

gulp.task('release:stable', ['dist', 'release:createTmp'], function(done) {
  if (process.env.CI) {
    git.clone('https://' + process.env.GH_TOKEN + '@github.com/HewlettPackard/grommet.git',
      {
        cwd: './tmp/'
      },
      function(err) {
        if (err) {
          throw err;
        }

        process.chdir('./tmp/grommet');
        git.checkout('stable', function(err) {
          if (err) {
            throw err;
          }

          gulp.src('../../dist/**').pipe(gulp.dest('./')).on('end', function() {
            git.status({
              args: '--porcelain'
            }, function(err, stdout) {
              if (err) {
                throw err;
              }

              if (stdout && stdout !== '') {
                gulp.src('./')
                  .pipe(git.add({
                    args: '--all'
                  }))
                  .pipe(git.commit('Stable dev version update.')).on('end', function() {
                  git.push('origin', 'stable', { quiet: true }, function(err) {
                    if (err) {
                      throw err;
                    }

                    process.chdir(__dirname);
                    done();
                  });
                });
              } else {
                console.log('No difference since last commit, skipping stable release.');

                process.chdir(__dirname);
                done();
              }
            });
          });
        });
      }
    );
  } else {
    console.warn('Skipping release. Release:stable task should be executed by CI only.');
  }
});

gulp.task('release:clean', function() {
  del.sync(['./tmp']);
});

gulp.task('release:site', function() {
  gulp.src('./docs/gulpfile.js', {
    read: false
  }).pipe(chug({
    tasks: ['sync']
  }));

  gulp.src('./examples/server/gulpfile.js', {
    read: false
  }).pipe(chug({
    tasks: ['sync']
  }));

  gulp.src('./examples/medium-app/gulpfile.js', {
    read: false
  }).pipe(chug({
    tasks: ['sync']
  }));
});

gulp.task('release', function(done) {
  runSequence('release:bump', ['dist-bower', 'dist'], 'release:npm', 'release:bower', 'release:clean', 'release:site', done);
});

gulp.task('dev', function() {
  console.error('Running "gulp dev" at Grommet root folder is not supported. If you want to start the website, run "gulp dev" at docs folder');
});
<|endoftext|>