<commit_before>/*
 leaflet.responsive.popup 0.1.0
 (c) 2017 https://github.com/yafred
*/

L.ResponsivePopup = L.Popup.extend({

	options: {
		hasTip: false
		/*
		 * Inherited from L.Popup
		 *
		 * - offset
		 *
		 * - autoPanPadding
		 * - autoPanPaddingTopLeft
		 * - autoPanPaddingBottomRight
		 */
	},

	/**
	 * Overrides https://github.com/Leaflet/Leaflet/blob/release-1.0.2/src/layer/Popup.js#L158
	 */
	_initLayout: function () {

		var prefix = 'leaflet-popup',
		    container = this._container = L.DomUtil.create('div',
			prefix + ' ' + (this.options.className || '') +
			' leaflet-zoom-animated');

		if (this.options.closeButton) {
			var closeButton = this._closeButton = L.DomUtil.create('a', prefix + '-close-button', container);
			closeButton.href = '#close';
			closeButton.innerHTML = '×';

			L.DomEvent.on(closeButton, 'click', this._onCloseButtonClick, this);
		}

		var wrapper = this._wrapper = L.DomUtil.create('div', prefix + '-content-wrapper', container);
		this._contentNode = L.DomUtil.create('div', prefix + '-content', wrapper);

		L.DomEvent
			.disableClickPropagation(wrapper)
			.disableScrollPropagation(this._contentNode)
			.on(wrapper, 'contextmenu', L.DomEvent.stopPropagation);

		if(this.options.hasTip) {
			this._tipContainer = L.DomUtil.create('div', prefix + '-tip-container', container);
			this._tip = L.DomUtil.create('div', prefix + '-tip', this._tipContainer);
		}
	},

	/**
	 * Overrides https://github.com/Leaflet/Leaflet/blob/release-1.0.2/src/layer/DivOverlay.js#L172
	 */
	_updatePosition: function () {

		if (!this._map) { return; }

		var pos = this._map.latLngToLayerPoint(this._latlng),
	        basePoint = this._map.layerPointToContainerPoint(pos),
	        containerWidth = this._container.offsetWidth,
	        containerHeight = this._container.offsetHeight,
		    padding = L.point(this.options.autoPanPadding),
		    paddingTL = L.point(this.options.autoPanPaddingTopLeft || padding),
		    paddingBR = L.point(this.options.autoPanPaddingBottomRight || padding),
	        mapSize = this._map.getSize(),
	        anchor = this._getAnchor(),  // popup anchor
        	offset = L.point(this.options.offset); // offset relative to anchor (option from L.DivOverlay. We only use absolute values).

		// Leaflet default dimensions (should not be hard coded in the future)
  		var tipHeight = 11; //px
  		var tipWidth = 22; //px
  		var containerRadius = 12; //px

  		// Tweak offset to include tip dimensions
  		var offsetX = Math.abs(offset.x);
   		var offsetY = Math.abs(offset.y);
   		if(this.options.hasTip) {
  			offsetX += tipHeight;
  			offsetY += tipHeight;

  			// clear CSS
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-north');
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-south');
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-east');
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-west');
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-north-east');
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-north-west');
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-south-east');
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-south-west');
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-east-north');
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-east-south');
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-west-north');
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-west-south');
  			// this._container.style.display = 'initial'; // this does not work
  		}

		// Where can we fit the popup ?
		var canGoTop = true,
		    canGoBottom = true,
		    canGoLeft = true,
		    canGoRight = true,
		    containerPos = false;

		if(basePoint.y + anchor.y - offsetY - containerHeight - Math.abs(paddingTL.y) < 0) {
			canGoTop = false;
		}
		if(basePoint.y + anchor.y + offsetY + containerHeight + Math.abs(paddingBR.y) > mapSize.y) {
			canGoBottom = false;
		}
		if(basePoint.x + anchor.x - offsetX - containerWidth - Math.abs(paddingTL.x) < 0) {
			canGoLeft = false;
		}
		if(basePoint.x + anchor.x + offsetX + containerWidth + Math.abs(paddingBR.x) > mapSize.x) {
			canGoRight = false;
		}

		// manage overflows
		var subtractX = containerWidth / 2 - anchor.x,
		    subtractY = containerHeight / 2 - anchor.y;

		if(canGoTop || canGoBottom) {
			var containerLeft = basePoint.x + anchor.x - (containerWidth / 2);
			var containerRight = basePoint.x + anchor.x + (containerWidth / 2);
			if(containerLeft < Math.abs(paddingTL.x)) { // left overflow
				subtractX = containerWidth / 2 - anchor.x - Math.abs(paddingTL.x) + containerLeft;
			}
			if(containerRight > mapSize.x - Math.abs(paddingBR.x)) { // right overflow
				subtractX = containerWidth / 2 - anchor.x + containerRight - mapSize.x + Math.abs(paddingBR.x);
			}
		}
		if(canGoLeft || canGoRight) {
			var containerTop = basePoint.y + anchor.y - (containerHeight / 2);
			var containerBottom = basePoint.y + anchor.y + (containerHeight / 2);
			if(containerTop < Math.abs(paddingTL.y)) { // top overflow
				subtractY = containerHeight / 2 - anchor.y - Math.abs(paddingTL.y) + containerTop;
			}
			if(containerBottom > mapSize.y - Math.abs(paddingBR.y)) { // bottom overflow
				subtractY = containerHeight / 2 - anchor.y + containerBottom - mapSize.y + Math.abs(paddingBR.y);
			}
		}

		// position the popup (order of preference is: top, left, bottom, right, centerOnMap)
		if(canGoTop) {
			containerPos = pos.subtract(L.point(subtractX, -anchor.y + containerHeight + offsetY, true));
			if(this.options.hasTip) {
				if(basePoint.x + anchor.x < paddingTL.x + containerRadius + tipWidth/2) {
					containerPos.x = pos.x + anchor.x;
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-north-east');
				}
				else if(basePoint.x + anchor.x > mapSize.x - paddingBR.x - containerRadius - tipWidth/2) {
					containerPos.x = pos.x + anchor.x - containerWidth;
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-north-west');
				}
				else {
					this._tipContainer.style.left = (pos.x + anchor.x - containerPos.x) + 'px';
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-north');
				}
			}
		}
		else if(canGoLeft) {
			containerPos = pos.subtract(L.point(-anchor.x + containerWidth + offsetX, subtractY, true));
			if(this.options.hasTip) {
				if(basePoint.y + anchor.y < paddingTL.y + containerRadius + tipWidth/2) {
					containerPos.y = pos.y + anchor.y;
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-west-south');
				}
				else if(basePoint.y + anchor.y > mapSize.y - paddingBR.y - containerRadius - tipWidth/2) {
					containerPos.y = pos.y + anchor.y - containerHeight;
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-west-north');
				}
				else {
					this._tipContainer.style.top = (pos.y + anchor.y - containerPos.y) + 'px';
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-west');
				}
			}
		}
		else if(canGoBottom) {
			containerPos = pos.subtract(L.point(subtractX, -anchor.y - offsetY, true));
			if(this.options.hasTip) {
				if(basePoint.x + anchor.x < paddingTL.x + containerRadius + tipWidth/2) {
					containerPos.x = pos.x + anchor.x;
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-south-east');
				}
				else if(basePoint.x + anchor.x > mapSize.x - paddingBR.x - containerRadius - tipWidth/2) {
					containerPos.x = pos.x + anchor.x - containerWidth;
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-south-west');
				}
				else {
					this._tipContainer.style.left = (pos.x + anchor.x - containerPos.x) + 'px';
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-south');
				}
			}
		}
		else if(canGoRight) {
			containerPos = pos.subtract(L.point(-anchor.x - offsetX, subtractY, true));
			if(this.options.hasTip) {
				if(basePoint.y + anchor.y < paddingTL.y + containerRadius + tipWidth/2) {
					containerPos.y = pos.y + anchor.y;
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-east-south');
				}
				else if(basePoint.y + anchor.y > mapSize.y - paddingBR.y - containerRadius - tipWidth/2) {
					containerPos.y = pos.y + anchor.y - containerHeight;
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-east-north');
				}
				else {
					this._tipContainer.style.top = (pos.y + anchor.y - containerPos.y) + 'px';
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-east');
				}
			}
		}
		else {
			var pos = this._map.latLngToLayerPoint(this._map.getCenter());
			containerPos = pos.subtract(L.point(containerWidth / 2, containerHeight / 2));
			if(this.options.hasTip) {
				// this._tipContainer.style.display = 'none'; // this does not work
			}
		}

		// if point is not visible, just hide the popup
		if(basePoint.x < 0 || basePoint.y < 0 || basePoint.x > mapSize.x || basePoint.y > mapSize.y) {
			// this._container.style.display = 'none';  // this does not work
		}

		// if container is too big, just hide the popup
		if(containerWidth - Math.abs(paddingTL.x) - Math.abs(paddingBR.x) > mapSize.x || containerHeight - Math.abs(paddingTL.y) - Math.abs(paddingBR.y) > mapSize.y) {
			// this._container.style.display = 'none'; // this does not work
		}

		L.DomUtil.setPosition(this._container, containerPos);
	}

});

//Instantiates a `ResponsivePopup` object given an optional `options` object that describes its appearance and location and an optional `source` object that is used to tag the popup with a reference to the Layer to which it refers.
L.responsivePopup = function (options, source) {
	return new L.ResponsivePopup(options, source);
};
<commit_msg>fix tip position<commit_after>/*
 leaflet.responsive.popup 0.1.0
 (c) 2017 https://github.com/yafred
*/

L.ResponsivePopup = L.Popup.extend({

	options: {
		hasTip: false
		/*
		 * Inherited from L.Popup
		 *
		 * - offset
		 *
		 * - autoPanPadding
		 * - autoPanPaddingTopLeft
		 * - autoPanPaddingBottomRight
		 */
	},

	/**
	 * Overrides https://github.com/Leaflet/Leaflet/blob/release-1.0.2/src/layer/Popup.js#L158
	 */
	_initLayout: function () {

		var prefix = 'leaflet-popup',
		    container = this._container = L.DomUtil.create('div',
			prefix + ' ' + (this.options.className || '') +
			' leaflet-zoom-animated');

		if (this.options.closeButton) {
			var closeButton = this._closeButton = L.DomUtil.create('a', prefix + '-close-button', container);
			closeButton.href = '#close';
			closeButton.innerHTML = '×';

			L.DomEvent.on(closeButton, 'click', this._onCloseButtonClick, this);
		}

		var wrapper = this._wrapper = L.DomUtil.create('div', prefix + '-content-wrapper', container);
		this._contentNode = L.DomUtil.create('div', prefix + '-content', wrapper);

		L.DomEvent
			.disableClickPropagation(wrapper)
			.disableScrollPropagation(this._contentNode)
			.on(wrapper, 'contextmenu', L.DomEvent.stopPropagation);

		if(this.options.hasTip) {
			this._tipContainer = L.DomUtil.create('div', prefix + '-tip-container', container);
			this._tip = L.DomUtil.create('div', prefix + '-tip', this._tipContainer);
		}
	},

	/**
	 * Overrides https://github.com/Leaflet/Leaflet/blob/release-1.0.2/src/layer/DivOverlay.js#L172
	 */
	_updatePosition: function () {

		if (!this._map) { return; }

		var pos = this._map.latLngToLayerPoint(this._latlng),
	        basePoint = this._map.layerPointToContainerPoint(pos),
	        containerWidth = this._container.offsetWidth,
	        containerHeight = this._container.offsetHeight,
		    padding = L.point(this.options.autoPanPadding),
		    paddingTL = L.point(this.options.autoPanPaddingTopLeft || padding),
		    paddingBR = L.point(this.options.autoPanPaddingBottomRight || padding),
	        mapSize = this._map.getSize(),
	        anchor = this._getAnchor(),  // popup anchor
        	offset = L.point(this.options.offset); // offset relative to anchor (option from L.DivOverlay. We only use absolute values).

		// Leaflet default dimensions (should not be hard coded in the future)
  		var tipHeight = 11; //px
  		var tipWidth = 22; //px
  		var containerRadius = 12; //px

  		// Tweak offset to include tip dimensions
  		var offsetX = Math.abs(offset.x);
   		var offsetY = Math.abs(offset.y);
   		if(this.options.hasTip) {
  			offsetX += tipHeight;
  			offsetY += tipHeight;

  			// clear CSS
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-north');
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-south');
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-east');
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-west');
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-north-east');
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-north-west');
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-south-east');
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-south-west');
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-east-north');
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-east-south');
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-west-north');
  			L.DomUtil.removeClass(this._container, 'leaflet-resp-popup-west-south');
  			// this._container.style.display = 'initial'; // this does not work
  		}

		// Where can we fit the popup ?
		var canGoTop = true,
		    canGoBottom = true,
		    canGoLeft = true,
		    canGoRight = true,
		    containerPos = false;

		if(basePoint.y + anchor.y - offsetY - containerHeight - Math.abs(paddingTL.y) < 0) {
			canGoTop = false;
		}
		if(basePoint.y + anchor.y + offsetY + containerHeight + Math.abs(paddingBR.y) > mapSize.y) {
			canGoBottom = false;
		}
		if(basePoint.x + anchor.x - offsetX - containerWidth - Math.abs(paddingTL.x) < 0) {
			canGoLeft = false;
		}
		if(basePoint.x + anchor.x + offsetX + containerWidth + Math.abs(paddingBR.x) > mapSize.x) {
			canGoRight = false;
		}

		// manage overflows
		var subtractX = containerWidth / 2 - anchor.x,
		    subtractY = containerHeight / 2 - anchor.y;

		if(canGoTop || canGoBottom) {
			var containerLeft = basePoint.x + anchor.x - (containerWidth / 2);
			var containerRight = basePoint.x + anchor.x + (containerWidth / 2);
			if(containerLeft < Math.abs(paddingTL.x)) { // left overflow
				subtractX = containerWidth / 2 - anchor.x - Math.abs(paddingTL.x) + containerLeft;
			}
			if(containerRight > mapSize.x - Math.abs(paddingBR.x)) { // right overflow
				subtractX = containerWidth / 2 - anchor.x + containerRight - mapSize.x + Math.abs(paddingBR.x);
			}
		}
		if(canGoLeft || canGoRight) {
			var containerTop = basePoint.y + anchor.y - (containerHeight / 2);
			var containerBottom = basePoint.y + anchor.y + (containerHeight / 2);
			if(containerTop < Math.abs(paddingTL.y)) { // top overflow
				subtractY = containerHeight / 2 - anchor.y - Math.abs(paddingTL.y) + containerTop;
			}
			if(containerBottom > mapSize.y - Math.abs(paddingBR.y)) { // bottom overflow
				subtractY = containerHeight / 2 - anchor.y + containerBottom - mapSize.y + Math.abs(paddingBR.y);
			}
		}

		// position the popup (order of preference is: top, left, bottom, right, centerOnMap)
		if(canGoTop) {
			containerPos = pos.subtract(L.point(subtractX, -anchor.y + containerHeight + offsetY, true));
			if(this.options.hasTip) {
				if(basePoint.x + anchor.x < paddingTL.x + containerRadius + tipWidth/2) {
					containerPos.x = pos.x + anchor.x;
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-north-east');
					this._tipContainer.style.top = containerHeight + 'px';
					this._tipContainer.style.left = '0px';
				}
				else if(basePoint.x + anchor.x > mapSize.x - paddingBR.x - containerRadius - tipWidth/2) {
					containerPos.x = pos.x + anchor.x - containerWidth;
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-north-west');
					this._tipContainer.style.top = containerHeight + 'px';
					this._tipContainer.style.left = containerWidth + 'px';
				}
				else {
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-north');
					this._tipContainer.style.top = containerHeight + 'px';
					this._tipContainer.style.left = (pos.x + anchor.x - containerPos.x) + 'px';
				}
			}
		}
		else if(canGoLeft) {
			containerPos = pos.subtract(L.point(-anchor.x + containerWidth + offsetX, subtractY, true));
			if(this.options.hasTip) {
				if(basePoint.y + anchor.y < paddingTL.y + containerRadius + tipWidth/2) {
					containerPos.y = pos.y + anchor.y;
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-west-south');
					this._tipContainer.style.top = '0px';
					this._tipContainer.style.left = containerWidth + 'px';
				}
				else if(basePoint.y + anchor.y > mapSize.y - paddingBR.y - containerRadius - tipWidth/2) {
					containerPos.y = pos.y + anchor.y - containerHeight;
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-west-north');
					this._tipContainer.style.top = containerHeight + 'px';
					this._tipContainer.style.left = containerWidth + 'px';
				}
				else {
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-west');
					this._tipContainer.style.top = (pos.y + anchor.y - containerPos.y) + 'px';
					this._tipContainer.style.left = containerWidth + 'px';
				}
			}
		}
		else if(canGoBottom) {
			containerPos = pos.subtract(L.point(subtractX, -anchor.y - offsetY, true));
			if(this.options.hasTip) {
				if(basePoint.x + anchor.x < paddingTL.x + containerRadius + tipWidth/2) {
					containerPos.x = pos.x + anchor.x;
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-south-east');
					this._tipContainer.style.top = '0px';
					this._tipContainer.style.left = '0px';
				}
				else if(basePoint.x + anchor.x > mapSize.x - paddingBR.x - containerRadius - tipWidth/2) {
					containerPos.x = pos.x + anchor.x - containerWidth;
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-south-west');
					this._tipContainer.style.top = '0px';
					this._tipContainer.style.left = containerWidth + 'px';
				}
				else {
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-south');
					this._tipContainer.style.top = '0px';
					this._tipContainer.style.left = (pos.x + anchor.x - containerPos.x) + 'px';
				}
			}
		}
		else if(canGoRight) {
			containerPos = pos.subtract(L.point(-anchor.x - offsetX, subtractY, true));
			if(this.options.hasTip) {
				if(basePoint.y + anchor.y < paddingTL.y + containerRadius + tipWidth/2) {
					containerPos.y = pos.y + anchor.y;
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-east-south');
					this._tipContainer.style.top = '0px';
					this._tipContainer.style.left = '0px';
				}
				else if(basePoint.y + anchor.y > mapSize.y - paddingBR.y - containerRadius - tipWidth/2) {
					containerPos.y = pos.y + anchor.y - containerHeight;
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-east-north');
					this._tipContainer.style.top = containerHeight + 'px';
					this._tipContainer.style.left = '0px';
				}
				else {
					L.DomUtil.addClass(this._container, 'leaflet-resp-popup-east');
					this._tipContainer.style.top = (pos.y + anchor.y - containerPos.y) + 'px';
					this._tipContainer.style.left = '0px';
				}
			}
		}
		else {
			var pos = this._map.latLngToLayerPoint(this._map.getCenter());
			containerPos = pos.subtract(L.point(containerWidth / 2, containerHeight / 2));
			if(this.options.hasTip) {
				// this._tipContainer.style.display = 'none'; // this does not work
			}
		}

		// if point is not visible, just hide the popup
		if(basePoint.x < 0 || basePoint.y < 0 || basePoint.x > mapSize.x || basePoint.y > mapSize.y) {
			// this._container.style.display = 'none';  // this does not work
		}

		// if container is too big, just hide the popup
		if(containerWidth - Math.abs(paddingTL.x) - Math.abs(paddingBR.x) > mapSize.x || containerHeight - Math.abs(paddingTL.y) - Math.abs(paddingBR.y) > mapSize.y) {
			// this._container.style.display = 'none'; // this does not work
		}

		L.DomUtil.setPosition(this._container, containerPos);
	}

});

//Instantiates a `ResponsivePopup` object given an optional `options` object that describes its appearance and location and an optional `source` object that is used to tag the popup with a reference to the Layer to which it refers.
L.responsivePopup = function (options, source) {
	return new L.ResponsivePopup(options, source);
};
<|endoftext|>


<commit_before>var fs    = require('fs'),
    plist = require('plist'),
    CSON  = require('cson');

// Read grammar from plist
var psGrammarPlist = fs.readFileSync('vendor/EditorSyntax/PowerShellSyntax.tmLanguage', 'utf8')
var grammar = plist.parse(psGrammarPlist);

// Write out grammar as CSON
var csonGrammar = CSON.stringifySync(filterObject(grammar))
fs.writeFileSync('grammars/powershell.cson', csonGrammar, 'utf8')

// Helper function
// References: https://github.com/atom/apm/blob/c0d657af13a0da4acda6fd4be39eddded7aac1e3/src/package-converter.coffee#L73-75
function filterObject(obj) {
   delete obj.uuid
   delete obj.keyEquivalent
   return obj
}
<commit_msg>Update script to utilize new method names<commit_after>var fs    = require('fs'),
    plist = require('plist'),
    CSON  = require('cson');

// Read grammar from plist
var psGrammarPlist = fs.readFileSync('vendor/EditorSyntax/PowerShellSyntax.tmLanguage', 'utf8')
var grammar = plist.parse(psGrammarPlist);

// Write out grammar as CSON
var csonGrammar = CSON.stringify(filterObject(grammar));
fs.writeFileSync('grammars/powershell.cson', csonGrammar, 'utf8');

// Helper function
// References: https://github.com/atom/apm/blob/c0d657af13a0da4acda6fd4be39eddded7aac1e3/src/package-converter.coffee#L73-75
function filterObject(obj) {
   delete obj.uuid
   delete obj.keyEquivalent
   return obj
}
<|endoftext|>


<commit_before>const path = require("path");
const webpack = require("webpack");
const AssetsPlugin = require("assets-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");

const srcPath = path.resolve(__dirname, "./client/demo");
const distPath = path.resolve(__dirname, "./dist/public/assets");

module.exports = {
    context: srcPath,
    entry:
    {
        vendor: ["./common/vendor"],
        demo: ["./index"]
    },
    output:
    {
        path: distPath,
        publicPath: "/assets/",
        filename: "[name].js",
        chunkFilename: "[id].chunk.js"
    },
    resolve:
    {
        extensions: [".js", ".jsx"],
        modules: [srcPath, "node_modules"]
    },
    module:
    {
        rules: [
            {
                test: /\.jsx?$/,
                use: [
                    {
                        loader: "babel-loader",
                        options: { cacheDirectory: true }
                    }
                ],
                exclude: /node_modules/
            },
            {
                test: /\.(png|jpg)$/,
                use: [
                    {
                        loader: "url-loader",
                        options: {
                            limit: 8192,
                            name: "res/[name].[ext]"
                        }
                    }
                ]
            },
            {
                test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
                use: [
                    {
                        loader: "url-loader",
                        options: {
                            limit: 8192,
                            mimetype: "application/font-woff",
                            name: "res/[name].[ext]"
                        }
                    }
                ]
            },
            {
                test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
                use: [
                    {
                        loader: "file-loader",
                        options: {
                            limit: 8192,
                            mimetype: "application/font-woff",
                            name: "res/[name].[ext]"
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        new CleanWebpackPlugin([distPath]),
        new webpack.optimize.CommonsChunkPlugin({
            name: "vendor",
            minChunks: Infinity
        }),
        new AssetsPlugin({
            filename: "assets.json",
            path: distPath,
            prettyPrint: true
        }),
        new webpack.ProvidePlugin({
            $: "jquery",
            jQuery: "jquery"
        })
    ]
};
<commit_msg>remove modules & ignore clean log<commit_after>const path = require("path");
const webpack = require("webpack");
const AssetsPlugin = require("assets-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");

const srcPath = path.resolve(__dirname, "./client/demo");
const distPath = path.resolve(__dirname, "./dist/public/assets");

module.exports = {
    context: srcPath,
    entry:
    {
        vendor: ["./common/vendor"],
        demo: ["./index"]
    },
    output:
    {
        path: distPath,
        publicPath: "/assets/",
        filename: "[name].js",
        chunkFilename: "[id].chunk.js"
    },
    resolve:
    {
        extensions: [".js", ".jsx"]
    },
    module:
    {
        rules: [
            {
                test: /\.jsx?$/,
                use: [
                    {
                        loader: "babel-loader",
                        options: { cacheDirectory: true }
                    }
                ],
                exclude: /node_modules/
            },
            {
                test: /\.(png|jpg)$/,
                use: [
                    {
                        loader: "url-loader",
                        options: {
                            limit: 8192,
                            name: "res/[name].[ext]"
                        }
                    }
                ]
            },
            {
                test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
                use: [
                    {
                        loader: "url-loader",
                        options: {
                            limit: 8192,
                            mimetype: "application/font-woff",
                            name: "res/[name].[ext]"
                        }
                    }
                ]
            },
            {
                test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
                use: [
                    {
                        loader: "file-loader",
                        options: {
                            limit: 8192,
                            mimetype: "application/font-woff",
                            name: "res/[name].[ext]"
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        new CleanWebpackPlugin([distPath], { verbose: false }),
        new webpack.optimize.CommonsChunkPlugin({
            name: "vendor",
            minChunks: Infinity
        }),
        new AssetsPlugin({
            filename: "assets.json",
            path: distPath,
            prettyPrint: true
        }),
        new webpack.ProvidePlugin({
            $: "jquery",
            jQuery: "jquery"
        })
    ]
};
<|endoftext|>


<commit_before>Ti.include('/includes/enums.js');
Ti.include('/includes/lib/json.i18n.js');
Ti.include('/includes/strip_tags.js');

var Utils = require('includes/utils'),
	Ui = require('includes/ui'),
	Parser = require('includes/parse'),

win = Ti.UI.currentWindow,
defaultTab = Ti.App.Properties.getInt('epg.defaultTab', EPG.TONIGHT),
cachedData = [],

searchBar = Titanium.UI.createSearchBar({
	hintText: I('epg.searchHint'),
	barColor: Ui.getBarColor()
}),

tableView = require('/includes/pull_to_refresh')({
	filterAttribute: 'searchFilter',
	search: searchBar
}),

//the window that will show a loading message while the epg is loading
loadingWin = Ui.createLoadingWindow('45%'),

//the tabbedbar used to select the program schedule
tabbedBar = Ti.UI.iOS.createTabbedBar({
	labels: [I('epg.now'), I('epg.tonight')],
	style: Ti.UI.iPhone.SystemButtonStyle.BAR,
	backgroundColor: Ui.getBarColor(),
	height: 30,
	width: 300,
	index: defaultTab,
	lastIndex: defaultTab
});

win.add(tableView);

tabbedBar.addEventListener('click', function(e) {
	if(e.index != null) {
		loadRSSFeed(true, true);
	}
});

win.setTitleControl(tabbedBar);

Ti.App.addEventListener('beginreload', function(e) {
	loadRSSFeed(false, false);
});

function loadRSSFeed(useCache, displayLoad) {
	if(Ti.Network.networkType == Ti.Network.NETWORK_NONE) {
		Ti.App.fireEvent('endreload', null);
		displayError(Error.NETWORK);
	} else {
		if(useCache && cachedData[tabbedBar.getIndex()] != null) {
			tableView.setData(cachedData[tabbedBar.getIndex()]);
			tabbedBar.lastIndex = tabbedBar.getIndex();
			Ti.App.fireEvent('endreload', null);
		} else {
			if(displayLoad) {
				loadingWin.open();
			}

			var url = null;

			if(tabbedBar.getIndex() === EPG.NOW) {
				url = EPG.NOW_URL;
			} else if(tabbedBar.getIndex() == EPG.TONIGHT) {
				url = EPG.TONIGHT_URL;
			}

			var xhr = Ti.Network.createHTTPClient({
				timeout: 15000,
				onload: function() {
					var xml_txt = (this.getResponseText()).replace(/(\r\n|\n|\r)/m, ''),
					xml = Ti.XML.parseString(xml_txt),
					itemList = xml.documentElement.getElementsByTagName('item');

					tableView.setData([]);
					cachedData[tabbedBar.getIndex()] = [];

					Parser.getAllRows(itemList, function(row) {
						tableView.appendRow(row, {
							animated: true
						});

						cachedData[tabbedBar.getIndex()].push(row);
					});

					tabbedBar.lastIndex = tabbedBar.getIndex();

					loadingWin.close();
					Ti.App.fireEvent('endreload', null);
				},
				onerror: function() {
					displayError(Error.SERVER);
					loadingWin.close();
					Ti.App.fireEvent('endreload', null);
				}
			});

			xhr.open('GET', url);
			xhr.send();
		}
	}
}

function displayError(errorType) {
	tabbedBar.setIndex(tabbedBar.lastIndex);

	var alert = Ti.UI.createAlertDialog({
		title: I('network.message.title'),
		buttonNames: [I('network.buttons.ok')]
	});

	if(errorType == Error.NETWORK) {
		alert.setMessage(I('network.message.epg.connection'));
	} else if(errorType == Error.SERVER) {
		alert.setMessage(I('network.message.epg.server'));
	} else {
		errorType = Error.UNKNOWN;
	}

	alert.setMessage(alert.getMessage() + ' (E' + errorType + ')');
	alert.show();
}

tableView.addEventListener('click', function(e) {
	if(!e.rowData.isHeader && e.rowData.data.title != null) {
		var win = Ti.UI.createWindow({
			url: 'subviews/epg/epg_details.js',
			title: I('epg.details.title'),
			backButtonTitle: I('labels.epg'),
			backgroundColor: Ui.getDefaultBackground(),
			layout: 'vertical',
			data: e.rowData.data
		});

		win.addEventListener('close', function() {
			win = null;
		});

		Ti.UI.currentTab.open(win, {
			animated: true
		});
	}
});

loadRSSFeed(false, true);
<commit_msg>Remove useless include<commit_after>Ti.include('/includes/enums.js');
Ti.include('/includes/lib/json.i18n.js');
Ti.include('/includes/strip_tags.js');

var Ui = require('includes/ui'),
	Parser = require('includes/parse'),

win = Ti.UI.currentWindow,
defaultTab = Ti.App.Properties.getInt('epg.defaultTab', EPG.TONIGHT),
cachedData = [],

searchBar = Titanium.UI.createSearchBar({
	hintText: I('epg.searchHint'),
	barColor: Ui.getBarColor()
}),

tableView = require('/includes/pull_to_refresh')({
	filterAttribute: 'searchFilter',
	search: searchBar
}),

//the window that will show a loading message while the epg is loading
loadingWin = Ui.createLoadingWindow('45%'),

//the tabbedbar used to select the program schedule
tabbedBar = Ti.UI.iOS.createTabbedBar({
	labels: [I('epg.now'), I('epg.tonight')],
	style: Ti.UI.iPhone.SystemButtonStyle.BAR,
	backgroundColor: Ui.getBarColor(),
	height: 30,
	width: 300,
	index: defaultTab,
	lastIndex: defaultTab
});

win.add(tableView);

tabbedBar.addEventListener('click', function(e) {
	if(e.index != null) {
		loadRSSFeed(true, true);
	}
});

win.setTitleControl(tabbedBar);

Ti.App.addEventListener('beginreload', function(e) {
	loadRSSFeed(false, false);
});

function loadRSSFeed(useCache, displayLoad) {
	if(Ti.Network.networkType == Ti.Network.NETWORK_NONE) {
		Ti.App.fireEvent('endreload', null);
		displayError(Error.NETWORK);
	} else {
		if(useCache && cachedData[tabbedBar.getIndex()] != null) {
			tableView.setData(cachedData[tabbedBar.getIndex()]);
			tabbedBar.lastIndex = tabbedBar.getIndex();
			Ti.App.fireEvent('endreload', null);
		} else {
			if(displayLoad) {
				loadingWin.open();
			}

			var url = null;

			if(tabbedBar.getIndex() === EPG.NOW) {
				url = EPG.NOW_URL;
			} else if(tabbedBar.getIndex() == EPG.TONIGHT) {
				url = EPG.TONIGHT_URL;
			}

			var xhr = Ti.Network.createHTTPClient({
				timeout: 15000,
				onload: function() {
					var xml_txt = (this.getResponseText()).replace(/(\r\n|\n|\r)/m, ''),
					xml = Ti.XML.parseString(xml_txt),
					itemList = xml.documentElement.getElementsByTagName('item');

					tableView.setData([]);
					cachedData[tabbedBar.getIndex()] = [];

					Parser.getAllRows(itemList, function(row) {
						tableView.appendRow(row, {
							animated: true
						});

						cachedData[tabbedBar.getIndex()].push(row);
					});

					tabbedBar.lastIndex = tabbedBar.getIndex();

					loadingWin.close();
					Ti.App.fireEvent('endreload', null);
				},
				onerror: function() {
					displayError(Error.SERVER);
					loadingWin.close();
					Ti.App.fireEvent('endreload', null);
				}
			});

			xhr.open('GET', url);
			xhr.send();
		}
	}
}

function displayError(errorType) {
	tabbedBar.setIndex(tabbedBar.lastIndex);

	var alert = Ti.UI.createAlertDialog({
		title: I('network.message.title'),
		buttonNames: [I('network.buttons.ok')]
	});

	if(errorType == Error.NETWORK) {
		alert.setMessage(I('network.message.epg.connection'));
	} else if(errorType == Error.SERVER) {
		alert.setMessage(I('network.message.epg.server'));
	} else {
		errorType = Error.UNKNOWN;
	}

	alert.setMessage(alert.getMessage() + ' (E' + errorType + ')');
	alert.show();
}

tableView.addEventListener('click', function(e) {
	if(!e.rowData.isHeader && e.rowData.data.title != null) {
		var win = Ti.UI.createWindow({
			url: 'subviews/epg/epg_details.js',
			title: I('epg.details.title'),
			backButtonTitle: I('labels.epg'),
			backgroundColor: Ui.getDefaultBackground(),
			layout: 'vertical',
			data: e.rowData.data
		});

		win.addEventListener('close', function() {
			win = null;
		});

		Ti.UI.currentTab.open(win, {
			animated: true
		});
	}
});

loadRSSFeed(false, true);
<|endoftext|>


<commit_before>// ** I18N

// Calendar EN language
// Author: Idan Sofer, <idan@idanso.dyndns.org>
// Encoding: UTF-8
// Distributed under the same terms as the calendar itself.

// For translators: please use UTF-8 if possible.  We strongly believe that
// Unicode is the answer to a real internationalized world.  Also please
// include your contact information in the header, as can be seen above.

// full day names
Calendar._DN = new Array
("ראשון",
 "שני",
 "שלישי",
 "רביעי",
 "חמישי",
 "שישי",
 "שבת",
 "ראשון");

// Please note that the following array of short day names (and the same goes
// for short month names, _SMN) isn't absolutely necessary.  We give it here
// for exemplification on how one can customize the short day names, but if
// they are simply the first N letters of the full name you can simply say:
//
//   Calendar._SDN_len = N; // short day name length
//   Calendar._SMN_len = N; // short month name length
//
// If N = 3 then this is not needed either since we assume a value of 3 if not
// present, to be compatible with translation files that were written before
// this feature.

// short day names
Calendar._SDN = new Array
("א",
 "ב",
 "ג",
 "ד",
 "ה",
 "ו",
 "ש",
 "א");

// full month names
Calendar._MN = new Array
("ינואר",
 "פברואר",
 "מרץ",
 "אפריל",
 "מאי",
 "יוני",
 "יולי",
 "אוגוסט",
 "ספטמבר",
 "אוקטובר",
 "נובמבר",
 "דצמבר");

// short month names
Calendar._SMN = new Array
("ינא",
 "פבר",
 "מרץ",
 "אפר",
 "מאי",
 "יונ",
 "יול",
 "אוג",
 "ספט",
 "אוק",
 "נוב",
 "דצמ");

// tooltips
Calendar._TT = {};
Calendar._TT["INFO"] = "אודות השנתון";

Calendar._TT["ABOUT"] =
"בחרן תאריך/שעה DHTML\n" +
"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-)
"הגירסא האחרונה זמינה ב: http://www.dynarch.com/projects/calendar/\n" +
"מופץ תחת זיכיון ה GNU LGPL.  עיין ב http://gnu.org/licenses/lgpl.html לפרטים נוספים." +
"\n\n" +
בחירת תאריך:\n" +
"- השתמש בכפתורים \xab, \xbb לבחירת שנה\n" +
"- השתמש בכפתורים " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " לבחירת חודש\n" +
"- החזק העכבר לחוץ מעל הכפתורים המוזכרים לעיל לבחירה מהירה יותר.";
Calendar._TT["ABOUT_TIME"] = "\n\n" +
"בחירת זמן:\n" +
"- לחץ על כל אחד מחלקי הזמן כדי להוסיף\n" +
"- או shift בשילוב עם לחיצה כדי להחסיר\n" +
"- או לחץ וגרור לפעולה מהירה יותר.";

Calendar._TT["PREV_YEAR"] = "שנה קודמת - החזק לקבלת תפריט";
Calendar._TT["PREV_MONTH"] = "חודש קודם - החזק לקבלת תפריט";
Calendar._TT["GO_TODAY"] = "עבור להיום";
Calendar._TT["NEXT_MONTH"] = "חודש הבא - החזק לתפריט";
Calendar._TT["NEXT_YEAR"] = "שנה הבאה - החזק לתפריט";
Calendar._TT["SEL_DATE"] = "בחר תאריך";
Calendar._TT["DRAG_TO_MOVE"] = "גרור להזזה";
Calendar._TT["PART_TODAY"] = " )היום(";

// the following is to inform that "%s" is to be the first day of week
// %s will be replaced with the day name.
Calendar._TT["DAY_FIRST"] = "הצג %s קודם";

// This may be locale-dependent.  It specifies the week-end days, as an array
// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1
// means Monday, etc.
Calendar._TT["WEEKEND"] = "6";

Calendar._TT["CLOSE"] = "סגור";
Calendar._TT["TODAY"] = "היום";
Calendar._TT["TIME_PART"] = "(שיפט-)לחץ וגרור כדי לשנות ערך";

// date formats
Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d";
Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e";

Calendar._TT["WK"] = "wk";
Calendar._TT["TIME"] = "שעה::";
<commit_msg>fixed hebrew calender language file for 1.1, closing #2970<commit_after>// ** I18N

// Calendar EN language
// Author: Idan Sofer, <idan@idanso.dyndns.org>
// Encoding: UTF-8
// Distributed under the same terms as the calendar itself.

// For translators: please use UTF-8 if possible.  We strongly believe that
// Unicode is the answer to a real internationalized world.  Also please
// include your contact information in the header, as can be seen above.

// full day names
Calendar._DN = new Array
("ראשון",
 "שני",
 "שלישי",
 "רביעי",
 "חמישי",
 "שישי",
 "שבת",
 "ראשון");

// Please note that the following array of short day names (and the same goes
// for short month names, _SMN) isn't absolutely necessary.  We give it here
// for exemplification on how one can customize the short day names, but if
// they are simply the first N letters of the full name you can simply say:
//
//   Calendar._SDN_len = N; // short day name length
//   Calendar._SMN_len = N; // short month name length
//
// If N = 3 then this is not needed either since we assume a value of 3 if not
// present, to be compatible with translation files that were written before
// this feature.

// short day names
Calendar._SDN = new Array
("א",
 "ב",
 "ג",
 "ד",
 "ה",
 "ו",
 "ש",
 "א");

// First day of the week. "0" means display Sunday first, "1" means display
// Monday first, etc.
Calendar._FD = 0;

// full month names
Calendar._MN = new Array
("ינואר",
 "פברואר",
 "מרץ",
 "אפריל",
 "מאי",
 "יוני",
 "יולי",
 "אוגוסט",
 "ספטמבר",
 "אוקטובר",
 "נובמבר",
 "דצמבר");

// short month names
Calendar._SMN = new Array
("ינא",
 "פבר",
 "מרץ",
 "אפר",
 "מאי",
 "יונ",
 "יול",
 "אוג",
 "ספט",
 "אוק",
 "נוב",
 "דצמ");

// tooltips
Calendar._TT = {};
Calendar._TT["INFO"] = "אודות השנתון";

Calendar._TT["ABOUT"] =
"בחרן תאריך/שעה DHTML\n" +
"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-)
"הגירסא האחרונה זמינה ב: http://www.dynarch.com/projects/calendar/\n" +
"מופץ תחת זיכיון ה GNU LGPL.  עיין ב http://gnu.org/licenses/lgpl.html לפרטים נוספים." +
"\n\n" +
"בחירת תאריך:\n" +
"- השתמש בכפתורים \xab, \xbb לבחירת שנה\n" +
"- השתמש בכפתורים " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " לבחירת חודש\n" +
"- החזק העכבר לחוץ מעל הכפתורים המוזכרים לעיל לבחירה מהירה יותר.";
Calendar._TT["ABOUT_TIME"] = "\n\n" +
"בחירת זמן:\n" +
"- לחץ על כל אחד מחלקי הזמן כדי להוסיף\n" +
"- או shift בשילוב עם לחיצה כדי להחסיר\n" +
"- או לחץ וגרור לפעולה מהירה יותר.";

Calendar._TT["PREV_YEAR"] = "שנה קודמת - החזק לקבלת תפריט";
Calendar._TT["PREV_MONTH"] = "חודש קודם - החזק לקבלת תפריט";
Calendar._TT["GO_TODAY"] = "עבור להיום";
Calendar._TT["NEXT_MONTH"] = "חודש הבא - החזק לתפריט";
Calendar._TT["NEXT_YEAR"] = "שנה הבאה - החזק לתפריט";
Calendar._TT["SEL_DATE"] = "בחר תאריך";
Calendar._TT["DRAG_TO_MOVE"] = "גרור להזזה";
Calendar._TT["PART_TODAY"] = " )היום(";

// the following is to inform that "%s" is to be the first day of week
// %s will be replaced with the day name.
Calendar._TT["DAY_FIRST"] = "הצג %s קודם";

// This may be locale-dependent.  It specifies the week-end days, as an array
// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1
// means Monday, etc.
Calendar._TT["WEEKEND"] = "6";

Calendar._TT["CLOSE"] = "סגור";
Calendar._TT["TODAY"] = "היום";
Calendar._TT["TIME_PART"] = "(שיפט-)לחץ וגרור כדי לשנות ערך";

// date formats
Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d";
Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e";

Calendar._TT["WK"] = "wk";
Calendar._TT["TIME"] = "שעה::";
<|endoftext|>


<commit_before>#!/usr/bin/env node
module.exports = {
	convertStyle : function(xml, tileUrl, callback) {
		convert(xml, tileUrl, function(jsonStyle) {
			callback(jsonStyle);
		});
	}
};

var path = require('path');
var fs = require("fs");
var xml2js = require('xml2js');

var idCounter = 0; // Used to ensure that styles have unique ids

if (require.main == module) {
	main();
}

function main() {
	var args = process.argv;
	args.splice(0, 2); // Remove 'node' and the name of the script

	if (args.length < 3) {
		console.error('Usage: style-conv <mapnik xlm file> <output file> <tile url>');
		process.exit(1);
	}
	var filename = path.resolve(__dirname, args[0]);
	var outFile = path.resolve(__dirname, args[1]);
	var tileUrl = args[2];
	convert(filename, tileUrl, function(jsonStyle) {
		// console.log(jsonStyle);
		fs.writeFile(outFile, jsonStyle, 'utf8', function() {
			process.exit(0);
		});
	});
}

function convert(xmlFile, tileUrl, callback) {
	fs.readFile(xmlFile, 'utf8', function(err, data) {
		if (err)
			throw err;
		xml2js.parseString(data, function(err, result) {
			if (err)
				throw err;
			console.log('Found ' + result.Map.Style.length + ' layers');
			var output = [];
			result.Map.Style.forEach(function(layer) {
				processLayer(output, layer);
			});
			var glStyle = {};
			// Vector source
			var sources = {};
			var map = {};
			glStyle['version'] = 8;
			map['type'] = 'vector';
			map['tiles'] = [ tileUrl ];
			map['maxzoom'] = 14; // Read from xml Parameters field
			sources['map'] = map;
			glStyle['sources'] = sources;
			glStyle['layers'] = output;
			var json = JSON.stringify(glStyle, null, 3);
			callback(json);
		});
	});
}

function processLayer(output, layer) {
	console.log('Processing layer: ' + layer.$.name);
	console.log('Found ' + layer.Rule.length + ' rules');
	var layerRules = [];
	layer.Rule.forEach(function(rule) {
		try {
			processRule(layerRules, rule, layer.$.name, 'map');
		} catch (err) {
			if (err == 'skip') {
				console.log('Skipped problematic rule: ' + JSON.stringify(rule, null, 3));
			} else {
				throw err;
			}
		}
	})
	layerRules.reverse().forEach(function(rule) {
		output.push(rule);
	});
}

function processRule(output, rule, layername, sourcename) {
	var style = {};
	var paint = {};
	var filter = [];
	var id = layername + '-';
	id += ++idCounter;
	style['id'] = id;
	style['source'] = sourcename;
	style['source-layer'] = layername;
	if (!ruleHasVisualizer(rule)) {
		throw Error('No or unsupported symbolizer in rule: ' + JSON.stringify(rule, null, 3));
	}
	var fill = false;
	if (rule.hasOwnProperty('MaxScaleDenominator')) {
		style['minzoom'] = getZoomLevel(rule['MaxScaleDenominator'][0]);
	}
	if (rule.hasOwnProperty('MinScaleDenominator')) {
		style['maxzoom'] = getZoomLevel(rule['MinScaleDenominator'][0]);
	}
	if (rule.hasOwnProperty('PolygonSymbolizer')) {
		fill = true;
		processPolygonSymbolizer(rule, style, paint);
	}
	if (rule.hasOwnProperty('PolygonPatternSymbolizer')) {
		fill = true;
		processPolygonPatternSymbolizer(rule, style, paint);
	}
	if (rule.hasOwnProperty('LineSymbolizer')) {
		if (fill) {
			// Mapnik uses LineSymbolizer for fill outlines as well
			processFillOutline(rule, style, paint);
		} else {
			processLineSymbolizer(rule, style, paint);
		}
	}
	if (rule.hasOwnProperty('MarkersSymbolizer')) {
		processMarkersSymbolizer(rule, style, paint);
	}
	if (rule.hasOwnProperty('TextSymbolizer')) {
		processTextSymbolizer(rule, style, paint);
	}
	if (rule.hasOwnProperty('Filter') && rule.Filter.length > 0) {
		style['filter'] = processFilter(rule.Filter);
	}
	style['paint'] = paint;
	output.push(style);
	console.log('Created style ' + id);
}

function processTextSymbolizer(rule, style, paint) {
	// TODO: Support multiple symbolizers for each rule
	var params = rule.TextSymbolizer[0].$;
	style['type'] = 'symbol';
	style['text-field'] = processOperand(rule.TextSymbolizer[0]._);
	if (params.hasOwnProperty('face-name')) {
		style['text-font'] = [ params['face-name'] ];
	}
	if (params.hasOwnProperty('fill')) { // Text color
		paint['text-color'] = params['fill'];
	}
	if (params.hasOwnProperty('halo-fill')) {
		paint['text-halo-color'] = params['halo-fill'];
	}
	if (params.hasOwnProperty('halo-radius')) {
		paint['text-halo-width'] = processOperand(params['halo-radius']);
	}
	if (params.hasOwnProperty('size')) {
		style['text-size'] = processOperand(params['size']);
	}
	if (params.hasOwnProperty('orientation')) {
		style['text-rotate'] = processOperand(params['orientation']);
	}
	style['text-anchor'] = processTextAlignment(params);
}

function processPolygonPatternSymbolizer(rule, style, paint) {
	// TODO: Support multiple symbolizers for each rule
	var params = rule.PolygonPatternSymbolizer[0].$;
	style['type'] = 'fill';
	paint['fill-pattern'] = params.file;
}

function processMarkersSymbolizer(rule, style, paint) {
	// TODO: Support multiple symbolizers for each rule
	var params = rule.MarkersSymbolizer[0].$;
	style['type'] = 'symbol';
	if (params.hasOwnProperty('allow-overlap')) {
		style['icon-allow-overlap'] = params['allow-overlap'];
	}
	if (params.hasOwnProperty('file')) {
		style['icon-image'] = params['file'];
	} else {
		throw 'skip';
	}
	// TODO Support scaling and rotation
}

function processPolygonSymbolizer(rule, style, paint) {
	// TODO: Support multiple symbolizers for each rule
	var params = rule.PolygonSymbolizer[0].$;
	style['type'] = 'fill';
	if (params.hasOwnProperty('fill')) {
		paint['fill-color'] = params.fill;
	}
	if (params.hasOwnProperty('fill-opacity')) {
		paint['fill-opacity'] = parseFloat(params['fill-opacity']);
	}
}

function processFillOutline(rule, style, paint) {
	// TODO: Support multiple symbolizers for each rule
	var params = rule.LineSymbolizer[0].$;
	if (params.hasOwnProperty('stroke-width')) {
		if (parseFloat(params['stroke-width'], 10) == 0) {
			return; // Skip outline if the width is 0
		}
	}
	if (params.hasOwnProperty('stroke')) {
		paint['fill-outline-color'] = params.stroke;
	}
}

function processLineSymbolizer(rule, style, paint) {
	// TODO: Support multiple symbolizers for each rule
	var params = rule.LineSymbolizer[0].$;
	style['type'] = 'line';
	if (params.hasOwnProperty('stroke')) {
		paint['line-color'] = params.stroke;
	}
	if (params.hasOwnProperty('stroke-opacity')) {
		paint['line-opacity'] = parseFloat(params['stroke-opacity']);
	}
	if (params.hasOwnProperty('stroke-width')) {
		var lineWidth = {};
		lineWidth['base'] = parseFloat(params['stroke-width']);
		paint['line-width'] = lineWidth;
		// TODO: Generate stops
		lineWidth['stops'] = [ [ 0, 1 ] ];
	}
}

function processFilter(filters) {
	var outFilter = [];
	var target = outFilter;
	filters.forEach(function(filter) {
		var expressions = splitFilterExpressions(filter);
		expressions.forEach(function(expr) {
			if (isFilterOperator(expr)) {
				var lastExpr = target.pop();
				target = [];
				outFilter.push(target);
				target.push(processFilterOperator(expr));
				target.push(lastExpr);
			} else {
				target.push(processExpression(expr));
				if (target != outFilter) {
					target = outFilter; // Compound expression finished
				}
			}
		});
	});
	if (filters.length > 1) {
		throw Error('Invalid filter, merging failed! ' + filters);
	}
	console.log('Filters: ' + outFilter[0]);
	return outFilter[0];
}

function processExpression(expr) {
	var output = [];
	var tokens = expr.split(' ');
	if (tokens.length != 3) {
		throw Error('Unexpected number of tokens (' + tokens.length + ') in filter: ' + expr);
	}
	var left = tokens[0];
	var operator = tokens[1];
	var right = tokens[2];
	output.push(processOperator(operator));
	output.push(processOperand(left));
	output.push(processOperand(right));
	return output;
}

function processOperator(value) {
	if (value == '=') {
		return '==';
	} else {
		return value; // Other operators are the same for GL styles and Mapnik
	}
}

function processOperand(value) {
	if (value.indexOf('[') != -1) {
		return value.substring(1, value.length - 1);
	} else {
		var intVal = parseInt(value, 10);
		var floatVal = parseFloat(value);
		if (intVal == floatVal) {
			return intVal;
		} else {
			return floatVal;
		}
	}
}

function splitFilterExpressions(filter) {
	var expressions = [];
	while (filter.indexOf('(') != -1) {
		var start = filter.indexOf('(');
		if (start > 0) {
			// There should be an operating before the start of the expression
			expressions.push(filter.substring(0, start).trim());
		}
		var end = filter.indexOf(')');
		expressions.push(filter.slice(start + 1, end));
		filter = filter.substring(end + 1, filter.length);
	}
	return expressions;
}

function isFilterOperator(value) {
	return (value == 'and' || value == 'or');
}

function processFilterOperator(value) {
	if (value == 'and') {
		return 'all';
	} else if (value == 'or') {
		return 'any';
	}
	throw new Error('Unsupported operator ' + value);
}

function ruleHasVisualizer(rule) {
	return rule.hasOwnProperty('PolygonSymbolizer') || rule.hasOwnProperty('PolygonPatternSymbolizer') || rule.hasOwnProperty('LineSymbolizer')
			|| rule.hasOwnProperty('MarkersSymbolizer') || rule.hasOwnProperty('TextSymbolizer');
	;
}

function getZoomLevel(value) {
	var table = {
		1000000000 : 0,
		500000000 : 1,
		200000000 : 2,
		100000000 : 3,
		50000000 : 4,
		25000000 : 5,
		12500000 : 6,
		6500000 : 7,
		3000000 : 8,
		1500000 : 9,
		750000 : 10,
		400000 : 11,
		200000 : 12,
		100000 : 13,
		50000 : 14,
		25000 : 15,
		12500 : 16,
		5000 : 17,
		2500 : 18,
		1500 : 19,
		750 : 20,
		500 : 21,
		250 : 22,
		100 : 23
	};
	return table[parseInt(value, 10)];
}

function processTextAlignment(params) {
	var vert = 'middle';
	var horiz = 'middle';
	if (params.hasOwnProperty('text-vertical-alignment')) {
		vert = params['text-vertical-alignment'];
	}
	if (params.hasOwnProperty('text-horizontal-alignment')) {
		horiz = params['text-horizontal-alignment'];
	}
	if (vert == 'auto') {
		vert = 'middle';
	}
	if (horiz == 'auto') {
		horiz = 'middle';
	}
	if (horiz == 'left' && vert == 'top') {
		return 'top-left';
	}
	if (horiz == 'middle' && vert == 'top') {
		return 'top';
	}
	if (horiz == 'right' && vert == 'top') {
		return 'top-right';
	}
	if (horiz == 'left' && vert == 'middle') {
		return 'left';
	}
	if (horiz == 'middle' && vert == 'middle') {
		return 'center';
	}
	if (horiz == 'right' && vert == 'middle') {
		return 'right';
	}
	if (horiz == 'left' && vert == 'bottom') {
		return 'bottom-left';
	}
	if (horiz == 'middle' && vert == 'bottom') {
		return 'bottom';
	}
	if (horiz == 'right' && vert == 'bottom') {
		return 'bottom-right';
	}
	throw Error('Invalid text alignment: ' + params);
}
<commit_msg>Correctly set base for stops function<commit_after>#!/usr/bin/env node
module.exports = {
	convertStyle : function(xml, tileUrl, callback) {
		convert(xml, tileUrl, function(jsonStyle) {
			callback(jsonStyle);
		});
	}
};

var path = require('path');
var fs = require("fs");
var xml2js = require('xml2js');

var idCounter = 0; // Used to ensure that styles have unique ids

if (require.main == module) {
	main();
}

function main() {
	var args = process.argv;
	args.splice(0, 2); // Remove 'node' and the name of the script

	if (args.length < 3) {
		console.error('Usage: style-conv <mapnik xlm file> <output file> <tile url>');
		process.exit(1);
	}
	var filename = path.resolve(__dirname, args[0]);
	var outFile = path.resolve(__dirname, args[1]);
	var tileUrl = args[2];
	convert(filename, tileUrl, function(jsonStyle) {
		// console.log(jsonStyle);
		fs.writeFile(outFile, jsonStyle, 'utf8', function() {
			process.exit(0);
		});
	});
}

function convert(xmlFile, tileUrl, callback) {
	fs.readFile(xmlFile, 'utf8', function(err, data) {
		if (err)
			throw err;
		xml2js.parseString(data, function(err, result) {
			if (err)
				throw err;
			console.log('Found ' + result.Map.Style.length + ' layers');
			var output = [];
			result.Map.Style.forEach(function(layer) {
				processLayer(output, layer);
			});
			var glStyle = {};
			// Vector source
			var sources = {};
			var map = {};
			glStyle['version'] = 8;
			map['type'] = 'vector';
			map['tiles'] = [ tileUrl ];
			map['maxzoom'] = 14; // Read from xml Parameters field
			sources['map'] = map;
			glStyle['sources'] = sources;
			glStyle['layers'] = output;
			var json = JSON.stringify(glStyle, null, 3);
			callback(json);
		});
	});
}

function processLayer(output, layer) {
	console.log('Processing layer: ' + layer.$.name);
	console.log('Found ' + layer.Rule.length + ' rules');
	var layerRules = [];
	layer.Rule.forEach(function(rule) {
		try {
			processRule(layerRules, rule, layer.$.name, 'map');
		} catch (err) {
			if (err == 'skip') {
				console.log('Skipped problematic rule: ' + JSON.stringify(rule, null, 3));
			} else {
				throw err;
			}
		}
	})
	layerRules.reverse().forEach(function(rule) {
		output.push(rule);
	});
}

function processRule(output, rule, layername, sourcename) {
	var style = {};
	var paint = {};
	var filter = [];
	var id = layername + '-';
	id += ++idCounter;
	style['id'] = id;
	style['source'] = sourcename;
	style['source-layer'] = layername;
	if (!ruleHasVisualizer(rule)) {
		throw Error('No or unsupported symbolizer in rule: ' + JSON.stringify(rule, null, 3));
	}
	var fill = false;
	if (rule.hasOwnProperty('MaxScaleDenominator')) {
		style['minzoom'] = getZoomLevel(rule['MaxScaleDenominator'][0]);
	}
	if (rule.hasOwnProperty('MinScaleDenominator')) {
		style['maxzoom'] = getZoomLevel(rule['MinScaleDenominator'][0]);
	}
	if (rule.hasOwnProperty('PolygonSymbolizer')) {
		fill = true;
		processPolygonSymbolizer(rule, style, paint);
	}
	if (rule.hasOwnProperty('PolygonPatternSymbolizer')) {
		fill = true;
		processPolygonPatternSymbolizer(rule, style, paint);
	}
	if (rule.hasOwnProperty('LineSymbolizer')) {
		if (fill) {
			// Mapnik uses LineSymbolizer for fill outlines as well
			processFillOutline(rule, style, paint);
		} else {
			processLineSymbolizer(rule, style, paint);
		}
	}
	if (rule.hasOwnProperty('MarkersSymbolizer')) {
		processMarkersSymbolizer(rule, style, paint);
	}
	if (rule.hasOwnProperty('TextSymbolizer')) {
		processTextSymbolizer(rule, style, paint);
	}
	if (rule.hasOwnProperty('Filter') && rule.Filter.length > 0) {
		style['filter'] = processFilter(rule.Filter);
	}
	style['paint'] = paint;
	output.push(style);
	console.log('Created style ' + id);
}

function processTextSymbolizer(rule, style, paint) {
	// TODO: Support multiple symbolizers for each rule
	var params = rule.TextSymbolizer[0].$;
	style['type'] = 'symbol';
	style['text-field'] = processOperand(rule.TextSymbolizer[0]._);
	if (params.hasOwnProperty('face-name')) {
		style['text-font'] = [ params['face-name'] ];
	}
	if (params.hasOwnProperty('fill')) { // Text color
		paint['text-color'] = params['fill'];
	}
	if (params.hasOwnProperty('halo-fill')) {
		paint['text-halo-color'] = params['halo-fill'];
	}
	if (params.hasOwnProperty('halo-radius')) {
		paint['text-halo-width'] = processOperand(params['halo-radius']);
	}
	if (params.hasOwnProperty('size')) {
		style['text-size'] = processOperand(params['size']);
	}
	if (params.hasOwnProperty('orientation')) {
		style['text-rotate'] = processOperand(params['orientation']);
	}
	style['text-anchor'] = processTextAlignment(params);
}

function processPolygonPatternSymbolizer(rule, style, paint) {
	// TODO: Support multiple symbolizers for each rule
	var params = rule.PolygonPatternSymbolizer[0].$;
	style['type'] = 'fill';
	paint['fill-pattern'] = params.file;
}

function processMarkersSymbolizer(rule, style, paint) {
	// TODO: Support multiple symbolizers for each rule
	var params = rule.MarkersSymbolizer[0].$;
	style['type'] = 'symbol';
	if (params.hasOwnProperty('allow-overlap')) {
		style['icon-allow-overlap'] = params['allow-overlap'];
	}
	if (params.hasOwnProperty('file')) {
		style['icon-image'] = params['file'];
	} else {
		throw 'skip';
	}
	// TODO Support scaling and rotation
}

function processPolygonSymbolizer(rule, style, paint) {
	// TODO: Support multiple symbolizers for each rule
	var params = rule.PolygonSymbolizer[0].$;
	style['type'] = 'fill';
	if (params.hasOwnProperty('fill')) {
		paint['fill-color'] = params.fill;
	}
	if (params.hasOwnProperty('fill-opacity')) {
		paint['fill-opacity'] = parseFloat(params['fill-opacity']);
	}
}

function processFillOutline(rule, style, paint) {
	// TODO: Support multiple symbolizers for each rule
	var params = rule.LineSymbolizer[0].$;
	if (params.hasOwnProperty('stroke-width')) {
		if (parseFloat(params['stroke-width'], 10) == 0) {
			return; // Skip outline if the width is 0
		}
	}
	if (params.hasOwnProperty('stroke')) {
		paint['fill-outline-color'] = params.stroke;
	}
}

function processLineSymbolizer(rule, style, paint) {
	// TODO: Support multiple symbolizers for each rule
	var params = rule.LineSymbolizer[0].$;
	style['type'] = 'line';
	if (params.hasOwnProperty('stroke')) {
		paint['line-color'] = params.stroke;
	}
	if (params.hasOwnProperty('stroke-opacity')) {
		paint['line-opacity'] = parseFloat(params['stroke-opacity']);
	}
	if (params.hasOwnProperty('stroke-width')) {
		var lineWidth = {};
		paint['line-width'] = lineWidth;
		lineWidth['base'] = 1.0;
		// TODO: Generate stops
		lineWidth['stops'] = [ [ 0, parseFloat(params['stroke-width']) ] ];
	}
}

function processFilter(filters) {
	var outFilter = [];
	var target = outFilter;
	filters.forEach(function(filter) {
		var expressions = splitFilterExpressions(filter);
		expressions.forEach(function(expr) {
			if (isFilterOperator(expr)) {
				var lastExpr = target.pop();
				target = [];
				outFilter.push(target);
				target.push(processFilterOperator(expr));
				target.push(lastExpr);
			} else {
				target.push(processExpression(expr));
				if (target != outFilter) {
					target = outFilter; // Compound expression finished
				}
			}
		});
	});
	if (filters.length > 1) {
		throw Error('Invalid filter, merging failed! ' + filters);
	}
	console.log('Filters: ' + outFilter[0]);
	return outFilter[0];
}

function processExpression(expr) {
	var output = [];
	var tokens = expr.split(' ');
	if (tokens.length != 3) {
		throw Error('Unexpected number of tokens (' + tokens.length + ') in filter: ' + expr);
	}
	var left = tokens[0];
	var operator = tokens[1];
	var right = tokens[2];
	output.push(processOperator(operator));
	output.push(processOperand(left));
	output.push(processOperand(right));
	return output;
}

function processOperator(value) {
	if (value == '=') {
		return '==';
	} else {
		return value; // Other operators are the same for GL styles and Mapnik
	}
}

function processOperand(value) {
	if (value.indexOf('[') != -1) {
		return value.substring(1, value.length - 1);
	} else {
		var intVal = parseInt(value, 10);
		var floatVal = parseFloat(value);
		if (intVal == floatVal) {
			return intVal;
		} else {
			return floatVal;
		}
	}
}

function splitFilterExpressions(filter) {
	var expressions = [];
	while (filter.indexOf('(') != -1) {
		var start = filter.indexOf('(');
		if (start > 0) {
			// There should be an operating before the start of the expression
			expressions.push(filter.substring(0, start).trim());
		}
		var end = filter.indexOf(')');
		expressions.push(filter.slice(start + 1, end));
		filter = filter.substring(end + 1, filter.length);
	}
	return expressions;
}

function isFilterOperator(value) {
	return (value == 'and' || value == 'or');
}

function processFilterOperator(value) {
	if (value == 'and') {
		return 'all';
	} else if (value == 'or') {
		return 'any';
	}
	throw new Error('Unsupported operator ' + value);
}

function ruleHasVisualizer(rule) {
	return rule.hasOwnProperty('PolygonSymbolizer') || rule.hasOwnProperty('PolygonPatternSymbolizer') || rule.hasOwnProperty('LineSymbolizer')
			|| rule.hasOwnProperty('MarkersSymbolizer') || rule.hasOwnProperty('TextSymbolizer');
	;
}

function getZoomLevel(value) {
	var table = {
		1000000000 : 0,
		500000000 : 1,
		200000000 : 2,
		100000000 : 3,
		50000000 : 4,
		25000000 : 5,
		12500000 : 6,
		6500000 : 7,
		3000000 : 8,
		1500000 : 9,
		750000 : 10,
		400000 : 11,
		200000 : 12,
		100000 : 13,
		50000 : 14,
		25000 : 15,
		12500 : 16,
		5000 : 17,
		2500 : 18,
		1500 : 19,
		750 : 20,
		500 : 21,
		250 : 22,
		100 : 23
	};
	return table[parseInt(value, 10)];
}

function processTextAlignment(params) {
	var vert = 'middle';
	var horiz = 'middle';
	if (params.hasOwnProperty('text-vertical-alignment')) {
		vert = params['text-vertical-alignment'];
	}
	if (params.hasOwnProperty('text-horizontal-alignment')) {
		horiz = params['text-horizontal-alignment'];
	}
	if (vert == 'auto') {
		vert = 'middle';
	}
	if (horiz == 'auto') {
		horiz = 'middle';
	}
	if (horiz == 'left' && vert == 'top') {
		return 'top-left';
	}
	if (horiz == 'middle' && vert == 'top') {
		return 'top';
	}
	if (horiz == 'right' && vert == 'top') {
		return 'top-right';
	}
	if (horiz == 'left' && vert == 'middle') {
		return 'left';
	}
	if (horiz == 'middle' && vert == 'middle') {
		return 'center';
	}
	if (horiz == 'right' && vert == 'middle') {
		return 'right';
	}
	if (horiz == 'left' && vert == 'bottom') {
		return 'bottom-left';
	}
	if (horiz == 'middle' && vert == 'bottom') {
		return 'bottom';
	}
	if (horiz == 'right' && vert == 'bottom') {
		return 'bottom-right';
	}
	throw Error('Invalid text alignment: ' + params);
}
<|endoftext|>


<commit_before>// @flow weak
/* eslint-disable no-console */

const WebpackDevServer = require('webpack-dev-server');
const webpack = require('webpack');
const webpackConfig = require('./webpack.dev.config');

const serverOptions = {
  publicPath: webpackConfig.output.publicPath,
  hot: true,
  historyApiFallback: true,
  stats: {
    // Remove built modules information.
    modules: false,
    // Remove built modules information to chunk information.
    chunkModules: false,
    colors: true,
  },
};

const PORT = 3000;

new WebpackDevServer(webpack(webpackConfig), serverOptions)
  .listen(PORT, '0.0.0.0', (err) => {
    if (err) {
      return console.log(err);
    }

    return console.info(`Webpack dev server listening at http://0.0.0.0:${PORT}/`);
  });
<commit_msg>makes it so you can set the port of the dev server with the MATERIAL_UI_PORT env var (#6536)<commit_after>// @flow weak
/* eslint-disable no-console */

const WebpackDevServer = require('webpack-dev-server');
const webpack = require('webpack');
const webpackConfig = require('./webpack.dev.config');

const serverOptions = {
  publicPath: webpackConfig.output.publicPath,
  hot: true,
  historyApiFallback: true,
  stats: {
    // Remove built modules information.
    modules: false,
    // Remove built modules information to chunk information.
    chunkModules: false,
    colors: true,
  },
};

const PORT = process.env.MATERIAL_UI_PORT || 3000;

new WebpackDevServer(webpack(webpackConfig), serverOptions)
  .listen(PORT, '0.0.0.0', (err) => {
    if (err) {
      return console.log(err);
    }

    return console.info(`Webpack dev server listening at http://0.0.0.0:${PORT}/`);
  });
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016 Bruce Schubert <bruce@emxsys.com>.
 * Released under the MIT License
 * http://www.opensource.org/licenses/mit-license.php
 */

/**
 * Settings content module
 *
 * @param {type} ko
 * @param {type} $
 * @returns {SettingsViewModel}
 */
define(['knockout',
    'jquery',
    'model/Constants'],
    function (ko, $, constants) {

        /**
         * The view model for the Settings panel.
         * @constructor
         */
        function SettingsViewModel(globe, viewElementId, viewUrl, appendToId) {
            var self = this,
                skyLayer, starsLayer, atmosphereLayer, timeZoneLayer, viewControls, widgets, crosshairs,
                tessellation, frameStatistics;

            this.globe = globe;
            this.layerManager = globe.layerManager;

            skyLayer = this.layerManager.findLayer(constants.LAYER_NAME_SKY);
            starsLayer = this.layerManager.findLayer(constants.LAYER_NAME_STARS);
            atmosphereLayer = this.layerManager.findLayer(constants.LAYER_NAME_ATMOSPHERE);
            timeZoneLayer = this.layerManager.findLayer(constants.LAYER_NAME_TIME_ZONES);
            viewControls = this.layerManager.findLayer(constants.LAYER_NAME_VIEW_CONTROLS);
            widgets = this.layerManager.findLayer(constants.LAYER_NAME_WIDGETS);
            crosshairs = this.layerManager.findLayer(constants.LAYER_NAME_RETICLE);
            tessellation = this.layerManager.findLayer("Show Tessellation");
            frameStatistics = this.layerManager.findLayer("Frame Statistics");

            //
            // Observables
            //

            /**
             * The current state of the time zones layer (settable).
             */
            this.timeZonesEnabled = timeZoneLayer ? timeZoneLayer.enabled : ko.observable();
            /**
             * The current state of the time zones layer opacity (settable).
             */
            this.timeZonesOpacity = timeZoneLayer ? timeZoneLayer.opacity : ko.observable();
            /**
             * The globe's timeZoneDetectEnabled observable setting (settable).
             */
            this.timeZoneDetectEnabled = globe.timeZoneDetectEnabled;
            this.timeZoneDetectEnabled.subscribe(function (newValue) {
                self.timeZonesEnabled(newValue);
            });
            /**
             * The globe's use24Time observable setting.
             */
            this.use24Time = globe.use24Time;
            /**
             * Tracks the current background color selection. Used by radio buttons in the view.
             */
            this.backgroundColor = ko.observable(skyLayer && skyLayer.enabled() ? "blue" : "black");
            /**
             * The current state of the blue background layer (settable).
             */
            this.blueBackgroundEnabled = skyLayer ? skyLayer.enabled : ko.observable();
            /**
             * The state of the black background (read-only).
             */
            this.blackBackgroundEnabled = ko.computed(function() {return skyLayer ? !skyLayer.enabled() : true});
            /**
             * The current state of the star field layer (settable).
             */
            this.starsBackgroundEnabled = starsLayer ? starsLayer.enabled : ko.observable();
            /**
             * The current state of the atmosphere layer (settable)
             */
            this.atmosphereBackgroundEnabled = atmosphereLayer ? atmosphereLayer.enabled : ko.observable();
            /**
             * The current opacity level for the atmosphere's nightime effect
             */
            this.nightOpacity = atmosphereLayer ? atmosphereLayer.opacity : ko.observable();

            this.dayNightEnabled = ko.observable(false);

            this.viewControlsEnabled = viewControls ? viewControls.enabled : ko.observable();
            this.widgetsEnabled = widgets ? widgets.enabled : ko.observable();
            this.crosshairsEnabled = crosshairs ? crosshairs.enabled : ko.observable();
            this.tessellationEnabled = tessellation ? tessellation.enabled : ko.observable();
            this.frameStatisticsEnabled = frameStatistics ? frameStatistics.enabled : ko.observable();

            /**
             * Background color selection handler
             */
            this.backgroundColor.subscribe(function (newValue) {
                switch (newValue) {
                case "blue":
                    self.blueBackgroundEnabled(true);
                    break;
                case "black":
                    self.blueBackgroundEnabled(false);
                    // The sky background layer manipulates the canvas' background color.
                    // When it's disabled, the last used color remains in the canvas.
                    // Set the background color to the default when the background is disabled.
                    $(self.globe.wwd.canvas).css('background-color', 'black');
                    break;
                }
            });

            /**
             * Turn off stars if the default background layer is enabled
             */
            this.dayNightEnabled.subscribe(function (newValue) {
                if (atmosphereLayer) {
                    atmosphereLayer.wwLayer.nightEnabled = newValue;
                }
                if (starsLayer) {
                    starsLayer.wwLayer.sunEnabled = newValue;
                }
                globe.redraw();
            });

            //
            // Load the view html into the DOM and apply the Knockout bindings
            //
            $.ajax({
                async: false,
                dataType: 'html',
                url: viewUrl,
                success: function (data) {
                    // Load the view html into the specified DOM element
                    $("#" + appendToId).append(data);

                    // Update the view member
                    self.view = document.getElementById(viewElementId);

                    // Binds the view to this view model.
                    ko.applyBindings(self, self.view);
                }
            });

        }

        return SettingsViewModel;
    }
);
<commit_msg>Changing the dayNightEnabled setting now triggers a redraw. - Improves the user experience with immediate visual feedback. - Re: #65.<commit_after>/*
 * Copyright (c) 2016 Bruce Schubert <bruce@emxsys.com>.
 * Released under the MIT License
 * http://www.opensource.org/licenses/mit-license.php
 */

/**
 * Settings content module
 *
 * @param {type} ko
 * @param {type} $
 * @returns {SettingsViewModel}
 */
define(['knockout',
    'jquery',
    'moment',
    'model/Constants'],
    function (ko, $, moment, constants) {

        /**
         * The view model for the Settings panel.
         * @constructor
         */
        function SettingsViewModel(globe, viewElementId, viewUrl, appendToId) {
            var self = this,
                skyLayer, starsLayer, atmosphereLayer, timeZoneLayer, viewControls, widgets, crosshairs,
                tessellation, frameStatistics;

            this.globe = globe;
            this.layerManager = globe.layerManager;

            skyLayer = this.layerManager.findLayer(constants.LAYER_NAME_SKY);
            starsLayer = this.layerManager.findLayer(constants.LAYER_NAME_STARS);
            atmosphereLayer = this.layerManager.findLayer(constants.LAYER_NAME_ATMOSPHERE);
            timeZoneLayer = this.layerManager.findLayer(constants.LAYER_NAME_TIME_ZONES);
            viewControls = this.layerManager.findLayer(constants.LAYER_NAME_VIEW_CONTROLS);
            widgets = this.layerManager.findLayer(constants.LAYER_NAME_WIDGETS);
            crosshairs = this.layerManager.findLayer(constants.LAYER_NAME_RETICLE);
            tessellation = this.layerManager.findLayer("Show Tessellation");
            frameStatistics = this.layerManager.findLayer("Frame Statistics");

            //
            // Observables
            //

            /**
             * The current state of the time zones layer (settable).
             */
            this.timeZonesEnabled = timeZoneLayer ? timeZoneLayer.enabled : ko.observable();
            /**
             * The current state of the time zones layer opacity (settable).
             */
            this.timeZonesOpacity = timeZoneLayer ? timeZoneLayer.opacity : ko.observable();
            /**
             * The globe's timeZoneDetectEnabled observable setting (settable).
             */
            this.timeZoneDetectEnabled = globe.timeZoneDetectEnabled;
            this.timeZoneDetectEnabled.subscribe(function (newValue) {
                self.timeZonesEnabled(newValue);
            });
            /**
             * The globe's use24Time observable setting.
             */
            this.use24Time = globe.use24Time;
            /**
             * Tracks the current background color selection. Used by radio buttons in the view.
             */
            this.backgroundColor = ko.observable(skyLayer && skyLayer.enabled() ? "blue" : "black");
            /**
             * The current state of the blue background layer (settable).
             */
            this.blueBackgroundEnabled = skyLayer ? skyLayer.enabled : ko.observable();
            /**
             * The state of the black background (read-only).
             */
            this.blackBackgroundEnabled = ko.computed(function() {return skyLayer ? !skyLayer.enabled() : true});
            /**
             * The current state of the star field layer (settable).
             */
            this.starsBackgroundEnabled = starsLayer ? starsLayer.enabled : ko.observable();
            /**
             * The current state of the atmosphere layer (settable)
             */
            this.atmosphereBackgroundEnabled = atmosphereLayer ? atmosphereLayer.enabled : ko.observable();
            /**
             * The current opacity level for the atmosphere's nightime effect
             */
            this.nightOpacity = atmosphereLayer ? atmosphereLayer.opacity : ko.observable();

            this.dayNightEnabled = ko.observable(false);

            this.viewControlsEnabled = viewControls ? viewControls.enabled : ko.observable();
            this.widgetsEnabled = widgets ? widgets.enabled : ko.observable();
            this.crosshairsEnabled = crosshairs ? crosshairs.enabled : ko.observable();
            this.tessellationEnabled = tessellation ? tessellation.enabled : ko.observable();
            this.frameStatisticsEnabled = frameStatistics ? frameStatistics.enabled : ko.observable();

            /**
             * Background color selection handler
             */
            this.backgroundColor.subscribe(function (newValue) {
                switch (newValue) {
                case "blue":
                    self.blueBackgroundEnabled(true);
                    break;
                case "black":
                    self.blueBackgroundEnabled(false);
                    // The sky background layer manipulates the canvas' background color.
                    // When it's disabled, the last used color remains in the canvas.
                    // Set the background color to the default when the background is disabled.
                    $(self.globe.wwd.canvas).css('background-color', 'black');
                    break;
                }
            });

            /**
             * Turn off stars if the default background layer is enabled
             */
            this.dayNightEnabled.subscribe(function (newValue) {
                if (atmosphereLayer) {
                    atmosphereLayer.wwLayer.nightEnabled = newValue;
                }
                if (starsLayer) {
                    starsLayer.wwLayer.sunEnabled = newValue;
                }
                // Tickle the time to force a redraw of the day/night
                var time = new moment(globe.dateTime());
                globe.dateTime(time.add(1,'ms').toDate());
                globe.redraw();
                globe.dateTime(time.subtract(1,'ms').toDate());
                globe.redraw();

            });

            //
            // Load the view html into the DOM and apply the Knockout bindings
            //
            $.ajax({
                async: false,
                dataType: 'html',
                url: viewUrl,
                success: function (data) {
                    // Load the view html into the specified DOM element
                    $("#" + appendToId).append(data);

                    // Update the view member
                    self.view = document.getElementById(viewElementId);

                    // Binds the view to this view model.
                    ko.applyBindings(self, self.view);
                }
            });

        }

        return SettingsViewModel;
    }
);
<|endoftext|>


<commit_before>#!/usr/bin/env node

const inquirer = require('inquirer');
const xRay = require('x-ray')();
const fetch = require('node-fetch');
const { mkdirSync, writeFileSync, existsSync } = require('fs');
const { join, extname } = require('path');
const url = require('url');
const makeDriver = require('request-x-ray');

// mobile user agent because some sites only serve manifest/pwa for mobile
const headers = {
  'User-Agent':
    'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Mobile Safari/537.36'
};

xRay.driver(makeDriver({ headers }));

/**
 *
 * @param {string} size the size of the image, like "144x144"
 * @returns the first dimension, like 144
 */
const parseSize = size => parseInt(size.split('x')[0]);

/**
 *
 * @param {{sizes: string, src: string}[]} icons
 */
const findLargestIcon = icons => {
  const icon = icons.reduce((largestIcon, icon) => {
    if (
      parseSize(icon.sizes) >
      (largestIcon.sizes ? parseSize(largestIcon.sizes) : 0)
    ) {
      return icon;
    }
    return largestIcon;
  });
  return { icon: icon.src, size: icon.sizes };
};

const main = async () => {
  const { appUrl } = await inquirer.prompt([
    {
      name: 'appUrl',
      type: 'input',
      message: 'Link to a page in the PWA'
    }
  ]);
  const manifestLink = await xRay(appUrl, 'link[rel="manifest"]@href')
    .then(link => url.resolve(appUrl, link))
    .catch(err => {
      throw new Error(`Unable to find manifest for ${appUrl}`);
    });

  console.log(`Found manifest at ${manifestLink}`);

  const manifest = await fetch(manifestLink, { headers }).then(d => d.json());
  if (!manifest.icons) {
    throw new Error(`Manifest has no icons`);
  }
  const { icon, size } = findLargestIcon(manifest.icons);
  console.log(`Found icon (${size}) at ${icon}`);
  const { name } = await inquirer.prompt([
    {
      name: 'name',
      type: 'input',
      message: 'Folder name in `images`'
    }
  ]);
  const dir = join('images', name);
  if (!existsSync(dir)) {
    mkdirSync(dir);
  }
  const img = await fetch(url.resolve(appUrl, icon), { headers }).then(d =>
    d.buffer()
  );
  // remove query params from extension
  const ext = extname(icon).replace(/\?.*$/, '');
  const path = join(dir, 'original' + ext);
  writeFileSync(path, img);
  console.log(`Created file ${path}`);
};

main().catch(err =>
  console.error(`Error finding icon for PWA
${err.stack}`)
);
<commit_msg>Add `default` when asking for folder name<commit_after>#!/usr/bin/env node

const inquirer = require('inquirer');
const xRay = require('x-ray')();
const fetch = require('node-fetch');
const { mkdirSync, writeFileSync, existsSync } = require('fs');
const { join, extname } = require('path');
const url = require('url');
const makeDriver = require('request-x-ray');

// mobile user agent because some sites only serve manifest/pwa for mobile
const headers = {
  'User-Agent':
    'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Mobile Safari/537.36'
};

xRay.driver(makeDriver({ headers }));

/**
 *
 * @param {string} size the size of the image, like "144x144"
 * @returns the first dimension, like 144
 */
const parseSize = size => parseInt(size.split('x')[0]);

/**
 *
 * @param {{sizes: string, src: string}[]} icons
 */
const findLargestIcon = icons => {
  const icon = icons.reduce((largestIcon, icon) => {
    if (
      parseSize(icon.sizes) >
      (largestIcon.sizes ? parseSize(largestIcon.sizes) : 0)
    ) {
      return icon;
    }
    return largestIcon;
  });
  return { icon: icon.src, size: icon.sizes };
};

/**
 * @param {string} u the url to retrieve the name from
 * @returns {string|undefined}
 */
const simplifyUrl = u => {
  const { hostname } = url.parse(u);
  if (hostname === null) {
    return undefined;
  }
  return hostname
    .replace(/\.[^.]*$/, '') // remove tld (last dot and everything after it)
    .replace(/^.*\./, '') // remove subdomains (everything up to the last dot)
    .toLowerCase();
};

module.exports = simplifyUrl;

const main = async () => {
  const { appUrl } = await inquirer.prompt([
    {
      name: 'appUrl',
      type: 'input',
      message: 'Link to a page in the PWA'
    }
  ]);
  const manifestLink = await xRay(appUrl, 'link[rel="manifest"]@href')
    .then(link => url.resolve(appUrl, link))
    .catch(err => {
      throw new Error(`Unable to find manifest for ${appUrl}`);
    });

  console.log(`Found manifest at ${manifestLink}`);

  const manifest = await fetch(manifestLink, { headers }).then(d => d.json());
  if (!manifest.icons) {
    throw new Error(`Manifest has no icons`);
  }
  const { icon, size } = findLargestIcon(manifest.icons);
  console.log(`Found icon (${size}) at ${icon}`);
  const { name } = await inquirer.prompt([
    {
      name: 'name',
      type: 'input',
      message: 'Folder name in `images`',
      default: simplifyUrl(appUrl)
    }
  ]);
  const dir = join('images', name);
  if (!existsSync(dir)) {
    mkdirSync(dir);
  }
  const img = await fetch(url.resolve(appUrl, icon), { headers }).then(d =>
    d.buffer()
  );
  // remove query params from extension
  const ext = extname(icon).replace(/\?.*$/, '');
  const path = join(dir, 'original' + ext);
  writeFileSync(path, img);
  console.log(`Created file ${path}`);
};

main().catch(err =>
  console.error(`Error finding icon for PWA
${err.stack}`)
);
<|endoftext|>


<commit_before>import path from 'path';

export default {
  module: {
    loaders: [{
      test: /\.jsx?$/,
      loaders: ['babel-loader'],
      exclude: /node_modules/
    }, {
      test: /\.json$/,
      loader: 'json-loader'
    }]
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js',
    libraryTarget: 'commonjs2'
  },
  resolve: {
    extensions: ['', '.js', '.jsx'],
    packageMains: ['webpack', 'browser', 'web', 'browserify', ['jam', 'main'], 'main']
  },
  plugins: [

  ],
  externals: [
    // put your node 3rd party libraries which can't be built with webpack here
    // (mysql, mongodb, and so on..)
  ]
};
<commit_msg>move dotenv usage to webpack config and write found values using DefinePlugin<commit_after>import webpack from 'webpack';
import path from 'path';
require('dotenv').config({ silent: true });

export default {
  module: {
    loaders: [{
      test: /\.jsx?$/,
      loaders: ['babel-loader'],
      exclude: /node_modules/
    }, {
      test: /\.json$/,
      loader: 'json-loader'
    }]
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js',
    libraryTarget: 'commonjs2'
  },
  resolve: {
    extensions: ['', '.js', '.jsx'],
    packageMains: ['webpack', 'browser', 'web', 'browserify', ['jam', 'main'], 'main']
  },
  plugins: [
	  new webpack.DefinePlugin({
		  'process.env': {
			  TWITCH_CLIENT_ID: process.env.TWITCH_CLIENT_ID,
			  TWITCH_CLIENT_SECRET: process.env.TWITCH_CLIENT_SECRET
		  }
	  })
  ],
  externals: [
    // put your node 3rd party libraries which can't be built with webpack here
    // (mysql, mongodb, and so on..)
  ]
};
<|endoftext|>


<commit_before>import React from 'react';
import { Panel } from 'react-bootstrap';

class ConsoleOutput extends React.Component {
  componentWillReceiveProps(nextProps) {
    if (this.props.output.size === 0 && nextProps.output.size > 0 && !this.props.show) {
      this.props.toggleConsole();
    }
  }

  render() {
    const height = `${String(this.props.height)}px`;
    return (

        <Panel collapsible expanded={this.props.show}>

              {this.props.output.map(line => (
                <code key={`${line}-Code-${Math.random()}`}>{line}
              ))}

        </Panel>

    );
  }
}

ConsoleOutput.propTypes = {
  height: React.PropTypes.number,
  output: React.PropTypes.array,
  toggleConsole: React.PropTypes.func,
  show: React.PropTypes.bool,
};

export default ConsoleOutput;
<commit_msg>[DAWN] ConsoleOutput: Remove collapsibility, clean up styles (#281)<commit_after>import React from 'react';
import { Panel } from 'react-bootstrap';

class ConsoleOutput extends React.Component {
  constructor(props) {
    super(props);
    this.scrollToBottom = this.scrollToBottom.bind(this);
  }

  componentDidMount() {
    this.scrollToBottom();
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.output.size === 0 && nextProps.output.size > 0 && !this.props.show) {
      this.props.toggleConsole();
    }
  }

  componentDidUpdate() {
    this.scrollToBottom();
  }

  scrollToBottom() {
    this.messagesEnd.scrollIntoView({ behavior: 'smooth' });
  }

  render() {
    const height = `${String(this.props.height)}px`;
    return (

        <Panel
          style={{
            display: this.props.show ? 'block' : 'none',
            marginBottom: '0',
            borderRadius: '0',
          }}
        >

              {this.props.output.map(line => (
                <code key={`${line}-Code-${Math.random()}`}>{line}
              ))}

 { this.messagesEnd = el; }}
              />

        </Panel>

    );
  }
}

ConsoleOutput.propTypes = {
  height: React.PropTypes.number,
  output: React.PropTypes.array,
  toggleConsole: React.PropTypes.func,
  show: React.PropTypes.bool,
};

export default ConsoleOutput;
<|endoftext|>


<commit_before>/*
* RetargetMouseScroll JavaScript Library v0.0.2
* 2009-07-30
* By Eli Grey, http://eligrey.com
*
* http://github.com/eligrey/RetargetMouseScroll/tree/master
*
* Licensed under the X11/MIT License
*   See LICENSE.md or http://eligrey.com/blog/about/license
*/

/*! @source http://purl.eligrey.com/github/RetargetMouseScroll/blob/master/
 *          RetargetMouseScroll.js
 */

if (typeof this.RetargetMouseScroll !== "function") (function() {
	var mouseScrollEvents = ["DOMMouseScroll", "mousewheel"];

	function handleScroll (evt, targetWindow, preventDefault, scrollMultiplier) {
		if (preventDefault && evt.preventDefault)
			evt.preventDefault();

		var scrollAmount = evt.detail
		                   || (-evt.wheelDelta / 40); // convert wheelData to lines
		scrollAmount *= 19; // convert lines to pixels

		if (typeof scrollMultiplier === "number" && !isNaN(scrollMultiplier))
			scrollAmount *= scrollMultiplier;

		if (evt.wheelDeltaX || ("axis" in evt && "HORIZONTAL_AXIS" in evt && evt.axis == evt.HORIZONTAL_AXIS))
			// horizontal scroll
			targetWindow.scrollBy(scrollAmount, 0);
		else // vertical scroll
			targetWindow.scrollBy(0, scrollAmount);
	};

	this.RetargetMouseScroll = function (elem, targetWindow, preventDefault, scrollMultiplier) {
		if (!elem)
			elem = document;

		if (!targetWindow)
			targetWindow = window;

		if (typeof preventDefault !== "boolean")
			preventDefault = true;

		var addListener, removeListener, restoreFn,
		handler = function (evt) {
			evt = evt || window.event;
			handleScroll(evt, targetWindow, preventDefault, scrollMultiplier);
		};

		if (addListener = elem.addEventListener) {
			addListener.call(elem, mouseScrollEvents[0], handler, false);
			addListener.call(elem, mouseScrollEvents[1], handler, false);
		}
		else if (addListener = elem.attachEvent)
			addListener.call(elem, "on"+mouseScrollEvents[1], handler);

		if (removeListener = elem.removeEventListener)
			restoreFn = function () {
				removeListener.call(elem, mouseScrollEvents[0], handler, false);
				removeListener.call(elem, mouseScrollEvents[1], handler, false);
			};
		else if (removeListener = elem.detachEvent)
			restoreFn = function () {
				removeListener.call(elem, "on"+mouseScrollEvents[1], handler);
			};

		return {
			restore: restoreFn
		};
	};
}).call(this);
<commit_msg>Targets can now be DOM nodes or windows<commit_after>/*
* RetargetMouseScroll JavaScript Library v0.0.2
* 2009-07-30
* By Eli Grey, http://eligrey.com
*
* http://github.com/eligrey/RetargetMouseScroll/tree/master
*
* Licensed under the X11/MIT License
*   See LICENSE.md or http://eligrey.com/blog/about/license
*/

/*! @source http://purl.eligrey.com/github/RetargetMouseScroll/blob/master/
 *          RetargetMouseScroll.js
 */

if (typeof this.RetargetMouseScroll !== "function") (function() {
	var mouseScrollEvents = ["DOMMouseScroll", "mousewheel"];

	function handleScroll (evt, target, preventDefault, scrollMultiplier) {
		if (preventDefault && evt.preventDefault)
			evt.preventDefault();

		var scrollAmount = evt.detail
		                   || (-evt.wheelDelta / 40); // convert wheelData to lines
		scrollAmount *= 19; // convert lines to pixels

		if (typeof scrollMultiplier === "number" && !isNaN(scrollMultiplier))
			scrollAmount *= scrollMultiplier;

		if (evt.wheelDeltaX || ("axis" in evt && "HORIZONTAL_AXIS" in evt && evt.axis == evt.HORIZONTAL_AXIS))
			// horizontal scroll
			if (target.scrollBy)
				target.scrollBy(scrollAmount, 0);
			else
				target.scrollLeft += scrollAmount;
		else // vertical scroll
			if (target.scrollBy)
				target.scrollBy(0, scrollAmount);
			else
				target.scrollTop += scrollAmount;
	};

	this.RetargetMouseScroll = function (elem, target, preventDefault, scrollMultiplier) {
		if (!elem)
			elem = document;

		if (!target)
			target = window;

		if (typeof preventDefault !== "boolean")
			preventDefault = true;

		var addListener, removeListener, restoreFn,
		handler = function (evt) {
			evt = evt || window.event;
			handleScroll(evt, target, preventDefault, scrollMultiplier);
		};

		if (addListener = elem.addEventListener) {
			addListener.call(elem, mouseScrollEvents[0], handler, false);
			addListener.call(elem, mouseScrollEvents[1], handler, false);
		}
		else if (addListener = elem.attachEvent)
			addListener.call(elem, "on"+mouseScrollEvents[1], handler);

		if (removeListener = elem.removeEventListener)
			restoreFn = function () {
				removeListener.call(elem, mouseScrollEvents[0], handler, false);
				removeListener.call(elem, mouseScrollEvents[1], handler, false);
			};
		else if (removeListener = elem.detachEvent)
			restoreFn = function () {
				removeListener.call(elem, "on"+mouseScrollEvents[1], handler);
			};

		return {
			restore: restoreFn
		};
	};
}).call(this);
<|endoftext|>


<commit_before>/**
 * handles the output file created for data between
 * source and destination
 */
module.exports = function(opt, moduleCallback) {
  //options are required
  if (typeof(opt) == 'undefined') return moduleCallback('No options specified.');
  //setup and require
  var FILE = new Object(),
    fs = require('graceful-fs'),
    dir = opt.cfg.dirs.output;

  //filename stores the complete filename for writing to later
  FILE.filename = dir + opt.table + '.' + Math.round(Date.now() / 1000) + '.dat';

  //cleanup (remove) output file
  FILE.clean = function(callback) {
    //define callback
    callback = typeof(callback) == 'undefined' ? function() {
      return;
    } : callback;
    //delete file
    fs.unlink(FILE.filename, function(err) {
      if (err) return callback(err);
      callback(null, true);
    });
  };

  //append function - append data to file
  FILE.append = function(data, callback) {
    callback = typeof(callback) == 'undefined' ? function() {
      return;
    } : callback;
    //append data and return callback
    fs.appendFile(FILE.filename, data, function(err) {
      if (err) return callback(err);
      callback(null);
    });
  };

  //get first line for column titles

  //get first two lines of data for column definitions
  FILE.twoLines = function(callback) {
    callback = typeof(callback) == 'undefined' ? function() {
      return;
    } : callback;
    fs.readFile(FILE.filename, 'utf-8', function(err, data) {
      if (err) return callback(err);
      var two = data.split('\n').slice(0, 2);
      callback(null, two);
    });
  };

  //stream options
  FILE.createWriteStream = function() {
    return fs.createWriteStream(FILE.filename);
  };
  FILE.createReadStream = function() {
    return fs.createReadStream(FILE.filename);
  };

  //create file
  fs.open(FILE.filename, 'w', function(err, fd) {
    if (err) {
      console.log(err);
      return moduleCallback(err);
    }
    //close it now that it's created
    fs.close(fd, function(err) {
      if (err) {
        console.log(err);
        return moduleCallback(err);
      }
      moduleCallback(null, FILE);
    });
  });
};
<commit_msg>return file object for test manipulation<commit_after>/**
 * handles the output file created for data between
 * source and destination
 */
module.exports = function(opt, moduleCallback) {
  //options are required
  if (typeof(opt) == 'undefined') return moduleCallback('No options specified.');
  //setup and require
  var FILE = new Object(),
    fs = require('graceful-fs'),
    dir = opt.cfg.dirs.output;

  //filename stores the complete filename for writing to later
  FILE.filename = dir + opt.table + '.' + Math.round(Date.now() / 1000) + '.dat';

  //cleanup (remove) output file
  FILE.clean = function(callback) {
    //define callback
    callback = typeof(callback) == 'undefined' ? function() {
      return;
    } : callback;
    //delete file
    fs.unlink(FILE.filename, function(err) {
      if (err) return callback(err);
      callback(null, true);
    });
  };

  //append function - append data to file
  FILE.append = function(data, callback) {
    callback = typeof(callback) == 'undefined' ? function() {
      return;
    } : callback;
    //append data and return callback
    fs.appendFile(FILE.filename, data, function(err) {
      if (err) return callback(err);
      callback(null);
    });
  };

  //get first line for column titles

  //get first two lines of data for column definitions
  FILE.twoLines = function(callback) {
    callback = typeof(callback) == 'undefined' ? function() {
      return;
    } : callback;
    fs.readFile(FILE.filename, 'utf-8', function(err, data) {
      if (err) return callback(err);
      var two = data.split('\n').slice(0, 2);
      callback(null, two);
    });
  };

  //stream options
  FILE.createWriteStream = function() {
    return fs.createWriteStream(FILE.filename);
  };
  FILE.createReadStream = function() {
    return fs.createReadStream(FILE.filename);
  };

  //create file
  fs.open(FILE.filename, 'w', function(err, fd) {
    if (err) {
      console.log(err);
      return moduleCallback(err);
    }
    //close it now that it's created
    fs.close(fd, function(err) {
      if (err) {
        console.log(err);
        return moduleCallback(err);
      }
      moduleCallback(null, FILE);
    });
  });
  return FILE;
};
<|endoftext|>


<commit_before>var pagination = require('hexo-pagination');

hexo.extend.generator.register('category', function(locals){
  var config = this.config;
  var perPage = config.category_generator.per_page;
  var paginationDir = config.pagination_dir || 'page';

  return locals.categories.reduce(function(result, category){
    if (!category.length) return result;

    var posts = category.posts.sort('-date');
    var data = pagination(category.path, posts, {
      perPage: perPage,
      layout: ['category', 'archive', 'index'],
      format: paginationDir + '/%d/',
      data: {
        category: category.name
      }
    });

    return result.concat(data);
  }, []);
});
<commit_msg>Fix TypeError in category generator<commit_after>var pagination = require('hexo-pagination');

hexo.extend.generator.register('category', function(locals){
  var config = this.config;
  if (config.category_generator) {
    var perPage = config.category_generator.per_page;
  } else {
    var perPage = 10;
  }
  var paginationDir = config.pagination_dir || 'page';

  return locals.categories.reduce(function(result, category){
    if (!category.length) return result;

    var posts = category.posts.sort('-date');
    var data = pagination(category.path, posts, {
      perPage: perPage,
      layout: ['category', 'archive', 'index'],
      format: paginationDir + '/%d/',
      data: {
        category: category.name
      }
    });

    return result.concat(data);
  }, []);
});
<|endoftext|>