<commit_before>var textPlugin = require('text');
//var nj = require('nunjucks/browser/nunjucks');
var nj = require('nunjucks');
var precompileGlobal = require('nunjucks/src/precompile-global');
var compiler = require('nunjucks/src/compiler'),
    Environment = nj.Environment;

var path = require('path');

if (typeof window === 'undefined') {
    global.window = {};
    global.__nodeEnv__ = true;
}

exports.translate = function(load) {
    var SystemJSLoader = this;

    var lang = '';
    if ('njOptions' in this && 'locale' in this.njOptions)
        lang = this.njOptions.locale;
    var tpl = load.source;

    var basePath = _calclulateParentOfTplDir(load.address).replace(this.baseURL, ''),
        fileName = path.basename(load.address).slice(0, -5);

    return _loadDictFile.call(this, path.join(basePath, 'loc', lang, fileName + '.loc'), !!lang)
    .then(function(file) {
        return new Promise(function(resolve, reject) {
            var dict = _parseDictFile(file);

            if (!_isNunjucksTpl(tpl)) {
                //console.log('simple html');
                tpl = textPlugin.translate(load);
                if (dict)
                    tpl = _localizeTpl(tpl, dict);
                resolve(tpl);
            }

            if (dict)
                tpl = _localizeTpl(tpl, dict);

            //tpl = _cleanTplFromCommonJsFormat(tpl);
            var name = _resolvePathToDir(load.address);
            /*
            console.log('name:', name);
            console.log('tpl:', load.source);
            */
            var precompiled = _precompile(tpl, name);
            var precompiledJsStr = precompileGlobal([precompiled])

            resolve(precompiledJsStr);
        });
    });
}

function _isNunjucksTpl(text) {
    return text.indexOf('{{') !== -1 || text.indexOf('{%') !== -1;
}
function _parseDictFile(file) {
    if (!file) return {};

    var out = {};
    file.split('\n').forEach(function(str) {
        if (!str) return true;
        str = str.split('=');
        out[ str[0].trim() ] = str[1].trim();
    });
    return out;
}
function _loadDictFile(requestURI, isLocalize) {
    if (!isLocalize) {
        return new Promise(function(resolve) {
            resolve('');
        });
    }

    var SystemJSLoader = this;
    return new Promise(function(resolve, reject) {
        SystemJSLoader.import(requestURI + '!text').then(function(file) {
            resolve(file);
        }).catch(function() {
            resolve('');
        });
    });
}
function _localizeTpl(tpl, dict) {
    tpl.matchAll(/\[\[(.+?)\]\]/g).forEach(function(matched) {
        var key = matched[1].trim();
        if (key in dict) {
            tpl = tpl.replace(matched[0], dict[key])
        } else {
            tpl = tpl.replace(matched[0], key);
        }
    });
    return tpl;

    debugger
    for (var key in dict) {
        var ptn = new RegExp('\\[\\[\\s*?' + key + '\\s*?\\]\\]');
        tpl = tpl.replace(ptn, dict[key]);
        if (!tpl) throw new Error('Error at localization ' + key);
    }
    return tpl;
}

// this snippet from origin nunjucks code base
// https://github.com/mozilla/nunjucks/blob/v2.1.0/src/precompile.js#L113
function _precompile(str, name, env) {
    env = env || new Environment([]);

    var asyncFilters = env.asyncFilters;
    var extensions = env.extensionsList;
    var template;

    try {
        template = compiler.compile(str,
                                    asyncFilters,
                                    extensions,
                                    name,
                                    env.opts);
    }
    catch(err) {
        console.log(err);
        //throw lib.prettifyError(name, false, err);
    }

    return { name: name, template: template };
}
function _resolvePathToDir(filePath, resolveToDir) {
    resolveToDir = resolveToDir || 'tpl';

    var fileName = path.basename(filePath),
        dirs = path.dirname(filePath).split('/');

    var out = [];
    var folder = null;
    while (dirs.length) {
        folder = dirs.pop();
        if (folder == 'tpl') break;

        out.push(folder);
    }

    return (out.length? out.reverse().join('/') + '/': '') + fileName;
}
function _calclulateParentOfTplDir(dir) {
    var dir = dir.split('/');
    while (dir.length)
        if (dir.pop() == 'tpl') break;
    if (!dir.length)
        throw new Error("tpl dir doesn't found");
    return dir.join('/') + '/';
}
String.prototype.matchAll = function(regexp) {
    var matches = [];
    this.replace(regexp, function() {
        var arr = ([]).slice.call(arguments, 0);
        var extras = arr.splice(-2);
        arr.index = extras[0];
        arr.input = extras[1];
        matches.push(arr);
    });
    return matches.length ? matches : null;
};
<commit_msg>use only key localization<commit_after>var textPlugin = require('text');
//var nj = require('nunjucks/browser/nunjucks');
var nj = require('nunjucks');
var precompileGlobal = require('nunjucks/src/precompile-global');
var compiler = require('nunjucks/src/compiler'),
    Environment = nj.Environment;

var path = require('path');

if (typeof window === 'undefined') {
    global.window = {};
    global.__nodeEnv__ = true;
}

exports.translate = function(load) {
    var SystemJSLoader = this;

    var lang = '';
    if ('njOptions' in this && 'locale' in this.njOptions)
        lang = this.njOptions.locale;
    var tpl = load.source;

    var basePath = _calclulateParentOfTplDir(load.address).replace(this.baseURL, ''),
        fileName = path.basename(load.address).slice(0, -5);

    return _loadDictFile.call(this, path.join(basePath, 'loc', lang, fileName + '.loc'), !!lang)
    .then(function(file) {
        return new Promise(function(resolve, reject) {
            var dict = _parseDictFile(file);

            if (!_isNunjucksTpl(tpl)) {
                //console.log('simple html');
                tpl = textPlugin.translate(load);
                if (dict)
                    tpl = _localizeTpl(tpl, dict);
                resolve(tpl);
            }

            if (dict)
                tpl = _localizeTpl(tpl, dict);

            //tpl = _cleanTplFromCommonJsFormat(tpl);
            var name = _resolvePathToDir(load.address);
            /*
            console.log('name:', name);
            console.log('tpl:', load.source);
            */
            var precompiled = _precompile(tpl, name);
            var precompiledJsStr = precompileGlobal([precompiled])

            resolve(precompiledJsStr);
        });
    });
}

function _isNunjucksTpl(text) {
    return text.indexOf('{{') !== -1 || text.indexOf('{%') !== -1;
}
function _parseDictFile(file) {
    if (!file) return {};

    var out = {};
    file.split('\n').forEach(function(str) {
        if (!str) return true;
        str = str.split('=');
        out[ str[0].trim() ] = str[1].trim();
    });
    return out;
}
function _loadDictFile(requestURI, isLocalize) {
    if (!isLocalize) {
        return new Promise(function(resolve) {
            resolve('');
        });
    }

    var SystemJSLoader = this;
    return new Promise(function(resolve, reject) {
        SystemJSLoader.import(requestURI + '!text').then(function(file) {
            resolve(file);
        }).catch(function() {
            resolve('');
        });
    });
}
function _localizeTpl(tpl, dict) {
    for (var key in dict) {
        var ptn = new RegExp('\\[\\[\\s*?' + key + '\\s*?\\]\\]');
        tpl = tpl.replace(ptn, dict[key]);
        if (!tpl) throw new Error('Error at localization ' + key);
    }
    return tpl;
}

// this snippet from origin nunjucks code base
// https://github.com/mozilla/nunjucks/blob/v2.1.0/src/precompile.js#L113
function _precompile(str, name, env) {
    env = env || new Environment([]);

    var asyncFilters = env.asyncFilters;
    var extensions = env.extensionsList;
    var template;

    try {
        template = compiler.compile(str,
                                    asyncFilters,
                                    extensions,
                                    name,
                                    env.opts);
    }
    catch(err) {
        console.log(err);
        //throw lib.prettifyError(name, false, err);
    }

    return { name: name, template: template };
}
function _resolvePathToDir(filePath, resolveToDir) {
    resolveToDir = resolveToDir || 'tpl';

    var fileName = path.basename(filePath),
        dirs = path.dirname(filePath).split('/');

    var out = [];
    var folder = null;
    while (dirs.length) {
        folder = dirs.pop();
        if (folder == 'tpl') break;

        out.push(folder);
    }

    return (out.length? out.reverse().join('/') + '/': '') + fileName;
}
function _calclulateParentOfTplDir(dir) {
    var dir = dir.split('/');
    while (dir.length)
        if (dir.pop() == 'tpl') break;
    if (!dir.length)
        throw new Error("tpl dir doesn't found");
    return dir.join('/') + '/';
}
<|endoftext|>


<commit_before>var rp = require('request-promise');
var _ = require('lodash');
var Promise = require('bluebird');
var geocode = require('geocoder');
var zips = [];
rp("https://seeclickfix.com/api/v2/issues?place_url=hampton&state=VA&per_page=20&page=1")
   .then(function(body) {
		var list = JSON.parse(body).issues;
		var lat = _.pluck(list, 'lat');
		var lng = _.pluck(list, 'lng');

		var lat_lng = { //make an object to return to next async func.
			lat: lat,
			lng: lng
		};
		console.log('lats \n' + lat_lng.lat + '\n longs \n' + lat_lng.lng);

		return lat_lng;
   })
   	.then(function(lat_lng) {
   		var getzips = function(lat, lng) {
   		return new Promise(function(resolve, reject) {
   			geocode.reverseGeocode(lat, lng, function(err, data) {
      			if (err) { reject(err);}
			 	 var result = (data.results[0].address_components[6].short_name);
		      		console.log('result', result);
					zips.push(result);
		      		resolve(result);
		      		resolve(zips);
		      		zips = _.union(zips);
		      		console.log('zip codes',zips);
		   				 	});
		   				});
		   			}

		   		 lat_lng.lat.map(function(_,index) {
   					return getzips(lat_lng.lat[index],lat_lng.lng[index])
				});
   	})
   	.finally(function(){
   		console.log('We are finally done here ');

  })
   	.catch(console.error);

   		<commit_msg>Added use strict<commit_after>"use strict";

var rp = require('request-promise');
var _ = require('lodash');
var Promise = require('bluebird');
var geocode = require('geocoder');
var zips = [];
rp("https://seeclickfix.com/api/v2/issues?place_url=hampton&state=VA&per_page=20&page=1")
   .then(function(body) {
		var list = JSON.parse(body).issues;
		var lat = _.pluck(list, 'lat');
		var lng = _.pluck(list, 'lng');

		var lat_lng = { //make an object to return to next async func.
			lat: lat,
			lng: lng
		};
		console.log('lats \n' + lat_lng.lat + '\n longs \n' + lat_lng.lng);

		return lat_lng;
   })
   	.then(function(lat_lng) {
   		var getzips = function(lat, lng) {
   		return new Promise(function(resolve, reject) {
   			geocode.reverseGeocode(lat, lng, function(err, data) {
      			if (err) { reject(err);}
			 	 var result = (data.results[0].address_components[6].short_name);
		      		console.log('result', result);
					zips.push(result);
		      		resolve(result);
		      		resolve(zips);
		      		zips = _.union(zips);
		      		console.log('zip codes',zips);
		   				 	});
		   				});
		   			}

		   		 lat_lng.lat.map(function(_,index) {
   					return getzips(lat_lng.lat[index],lat_lng.lng[index])

				});
   	})
   	.finally(function(){
   		console.log('We are finally done here ');

  })
   	.catch(console.error);

   		<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011, Yahoo! Inc.  All rights reserved.
 * Copyright (c) 2012, Log-Normal, Inc.  All rights reserved.
 * Copyrights licensed under the BSD License. See the accompanying LICENSE.txt file for terms.
 */

// This is the Round Trip Time plugin.  Abbreviated to RT
// the parameter is the window
(function(w) {

var d=w.document;

BOOMR = BOOMR || {};
BOOMR.plugins = BOOMR.plugins || {};

// private object
var impl = {
	complete: false,	//! Set when this plugin has completed

	timers: {},		//! Custom timers that the developer can use
				// Format for each timer is { start: XXX, end: YYY, delta: YYY-XXX }
	cookie: 'RT',		//! Name of the cookie that stores the start time and referrer
	cookie_exp:600,		//! Cookie expiry in seconds
	strict_referrer: true,	//! By default, don't beacon if referrers don't match.
				// If set to false, beacon both referrer values and let
				// the back end decide

	navigationType: 0,
	navigationStart: undefined,
	responseStart: undefined,

	// The start method is fired on page unload.  It is called with the scope
	// of the BOOMR.plugins.RT object
	start: function() {
		var t_end, t_start = new Date().getTime();

		// Disable use of RT cookie by setting its name to a falsy value
		if(!this.cookie) {
			return this;
		}

		// We use document.URL instead of location.href because of a bug in safari 4
		// where location.href is URL decoded
		if(!BOOMR.utils.setCookie(this.cookie,
						{ s: t_start, r: d.URL.replace(/#.*/, '') },
						this.cookie_exp)
		) {
			BOOMR.error("cannot set start cookie", "rt");
			return this;
		}

		t_end = new Date().getTime();
		if(t_end - t_start > 50) {
			// It took > 50ms to set the cookie
			// The user Most likely has cookie prompting turned on so
			// t_start won't be the actual unload time
			// We bail at this point since we can't reliably tell t_done
			BOOMR.utils.removeCookie(this.cookie);

			// at some point we may want to log this info on the server side
			BOOMR.error("took more than 50ms to set cookie... aborting: "
					+ t_start + " -> " + t_end, "rt");
		}

		return this;
	},

	initNavTiming: function() {
		var ti, p, source;

		if(this.navigationStart) {
			return;
		}

		// Get start time from WebTiming API see:
		// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html
		// http://blogs.msdn.com/b/ie/archive/2010/06/28/measuring-web-page-performance.aspx
		// http://blog.chromium.org/2010/07/do-you-know-how-slow-your-web-page-is.html
		p = w.performance || w.msPerformance || w.webkitPerformance || w.mozPerformance;

		if(p && p.navigation) {
			this.navigationType = p.navigation.type;
		}

		if(p && p.timing) {
			ti = p.timing;
		}
		else if(w.chrome && w.chrome.csi && w.chrome.csi().startE) {
			// Older versions of chrome also have a timing API that's sort of documented here:
			// http://ecmanaut.blogspot.com/2010/06/google-bom-feature-ms-since-pageload.html
			// source here:
			// http://src.chromium.org/viewvc/chrome/trunk/src/chrome/renderer/loadtimes_extension_bindings.cc?view=markup
			ti = {
				navigationStart: w.chrome.csi().startE
			};
			source = "csi";
		}
		else if(w.gtbExternal && w.gtbExternal.startE()) {
			// The Google Toolbar exposes navigation start time similar to old versions of chrome
			// This would work for any browser that has the google toolbar installed
			ti = {
				navigationStart: w.gtbExternal.startE()
			};
			source = 'gtb';
		}

		if(ti) {
			// Always use navigationStart since it falls back to fetchStart (not with redirects)
			// If not set, we leave t_start alone so that timers that depend
			// on it don't get sent back.  Never use requestStart since if
			// the first request fails and the browser retries, it will contain
			// the value for the new request.
			BOOMR.addVar("rt.start", source || "navigation");
			this.navigationStart = ti.navigationStart || ti.fetchStart || undefined;
			this.responseStart = ti.responseStart || undefined;

			// bug in Firefox 7 & 8 https://bugzilla.mozilla.org/show_bug.cgi?id=691547
			if(navigator.userAgent.match(/Firefox\/[78]\./)) {
				this.navigationStart = ti.unloadEventStart || ti.fetchStart || undefined;
			}
		}
		else {
			BOOMR.warn("This browser doesn't support the WebTiming API", "rt");
		}

		return;
	},

	domloaded: function() {
		BOOMR.plugins.RT.endTimer("t_domloaded");
	}
};

BOOMR.plugins.RT = {
	// Methods

	init: function(config) {
		impl.complete = false;
		impl.timers = {};

		BOOMR.utils.pluginConfig(impl, config, "RT",
					["cookie", "cookie_exp", "strict_referrer"]);

		BOOMR.subscribe("page_ready", this.done, null, this);
		BOOMR.subscribe("dom_loaded", impl.domloaded, null, impl);
		BOOMR.subscribe("page_unload", impl.start, null, impl);

		if(BOOMR.t_start) {
			// How long does it take Boomerang to load up and execute
			this.startTimer('boomerang', BOOMR.t_start);
			this.endTimer('boomerang', BOOMR.t_end);	// t_end === null defaults to current time

			// How long did it take till Boomerang started
			this.endTimer('boomr_fb', BOOMR.t_start);
		}

		return this;
	},

	startTimer: function(timer_name, time_value) {
		if(timer_name) {
			if (timer_name === 't_page') {
				this.endTimer('t_resp', time_value);
			}
			impl.timers[timer_name] = {start: (typeof time_value === "number" ? time_value : new Date().getTime())};
			impl.complete = false;
		}

		return this;
	},

	endTimer: function(timer_name, time_value) {
		if(timer_name) {
			impl.timers[timer_name] = impl.timers[timer_name] || {};
			if(!("end" in impl.timers[timer_name])) {
				impl.timers[timer_name].end =
						(typeof time_value === "number" ? time_value : new Date().getTime());
			}
		}

		return this;
	},

	setTimer: function(timer_name, time_delta) {
		if(timer_name) {
			impl.timers[timer_name] = { delta: time_delta };
		}

		return this;
	},

	// Called when the page has reached a "usable" state.  This may be when the
	// onload event fires, or it could be at some other moment during/after page
	// load when the page is usable by the user
	done: function() {
		var t_start, r, r2,
		    subcookies, basic_timers = { t_done: 1, t_resp: 1, t_page: 1},
		    ntimers = 0, t_name, timer, t_other=[];

		if(impl.complete) {
			return this;
		}

		impl.initNavTiming();

		if(
			(d.webkitVisibilityState && d.webkitVisibilityState === "prerender")
			||
			(d.msVisibilityState && d.msVisibilityState === 3)
		) {
			// This means that onload fired through a pre-render.  We'll capture this
			// time, but wait for t_done until after the page has become either visible
			// or hidden (ie, it moved out of the pre-render state)
			// http://code.google.com/chrome/whitepapers/pagevisibility.html
			// http://www.w3.org/TR/2011/WD-page-visibility-20110602/
			// http://code.google.com/chrome/whitepapers/prerender.html

			this.startTimer("t_load", impl.navigationStart);
			this.endTimer("t_load");		// this will measure actual onload time for a prerendered page
			this.startTimer("t_prerender", impl.navigationStart);
			this.startTimer("t_postrender");	// time from prerender to visible or hidden

			BOOMR.subscribe("visibility_changed", this.done, null, this);

			return this;
		}

		// If the dev has already called endTimer, then this call will do nothing
		// else, it will stop the page load timer
		this.endTimer("t_done");

		if(impl.responseStart) {
			// Use NavTiming API to figure out resp latency and page time
			// t_resp will use the cookie if available or fallback to NavTiming
			this.endTimer("t_resp", impl.responseStart);
			if(impl.timers.t_load) {
				this.setTimer("t_page", impl.timers.t_load.end - impl.responseStart);
			}
			else {
				this.setTimer("t_page", new Date().getTime() - impl.responseStart);
			}
		}
		else if(impl.timers.hasOwnProperty('t_page')) {
			// If the dev has already started t_page timer, we can end it now as well
			this.endTimer("t_page");
		}

		// If a prerender timer was started, we can end it now as well
		if(impl.timers.hasOwnProperty('t_postrender')) {
			this.endTimer("t_postrender");
			this.endTimer("t_prerender");
		}

		// A beacon may be fired automatically on page load or if the page dev fires
		// it manually with their own timers.  It may not always contain a referrer
		// (eg: XHR calls).  We set default values for these cases

		r = r2 = d.referrer.replace(/#.*/, '');

		// If impl.cookie is not set, the dev does not want to use cookie time
		if(impl.cookie) {
			subcookies = BOOMR.utils.getSubCookies(BOOMR.utils.getCookie(impl.cookie));
			BOOMR.utils.removeCookie(impl.cookie);

			if(subcookies && subcookies.s && subcookies.r) {
				r = subcookies.r;
				if(!impl.strict_referrer || r === r2) {
					t_start = parseInt(subcookies.s, 10);
				}
			}
		}

		if(t_start && impl.navigationType != 2) {	// 2 is TYPE_BACK_FORWARD but the constant may not be defined across browsers
			BOOMR.addVar("rt.start", "cookie");	// if the user hit the back button, referrer will match, and cookie will match
		}						// but will have time of previous page start, so t_done will be wrong
		else {
			t_start = impl.navigationStart;
		}

		// make sure old variables don't stick around
		BOOMR.removeVar('t_done', 't_page', 't_resp', 'r', 'r2', 'rt.bstart', 'rt.end');

		BOOMR.addVar('rt.bstart', BOOMR.t_start);
		BOOMR.addVar('rt.end', impl.timers.t_done.end);

		for(t_name in impl.timers) {
			if(!impl.timers.hasOwnProperty(t_name)) {
				continue;
			}

			timer = impl.timers[t_name];

			// if delta is a number, then it was set using setTimer
			// if not, then we have to calculate it using start & end
			if(typeof timer.delta !== "number") {
				if(typeof timer.start !== "number") {
					timer.start = t_start;
				}
				timer.delta = timer.end - timer.start;
			}

			// If the caller did not set a start time, and if there was no start cookie
			// then timer.delta will be NaN, in which case we discard it.
			if(isNaN(timer.delta)) {
				continue;
			}

			if(basic_timers.hasOwnProperty(t_name)) {
				BOOMR.addVar(t_name, timer.delta);
			}
			else {
				t_other.push(t_name + '|' + timer.delta);
			}
			ntimers++;
		}

		if(ntimers) {
			BOOMR.addVar("r", r);

			if(r2 !== r) {
				BOOMR.addVar("r2", r2);
			}

			if(t_other.length) {
				BOOMR.addVar("t_other", t_other.join(','));
			}
		}

		impl.timers = {};
		impl.complete = true;

		BOOMR.sendBeacon();	// we call sendBeacon() anyway because some other plugin
					// may have blocked waiting for RT to complete
		return this;
	},

	is_complete: function() { return impl.complete; }

};

}(window));
// End of RT plugin

<commit_msg>Move cookie init code to separate function<commit_after>/*
 * Copyright (c) 2011, Yahoo! Inc.  All rights reserved.
 * Copyright (c) 2012, Log-Normal, Inc.  All rights reserved.
 * Copyrights licensed under the BSD License. See the accompanying LICENSE.txt file for terms.
 */

// This is the Round Trip Time plugin.  Abbreviated to RT
// the parameter is the window
(function(w) {

var d=w.document;

BOOMR = BOOMR || {};
BOOMR.plugins = BOOMR.plugins || {};

// private object
var impl = {
	complete: false,	//! Set when this plugin has completed

	timers: {},		//! Custom timers that the developer can use
				// Format for each timer is { start: XXX, end: YYY, delta: YYY-XXX }
	cookie: 'RT',		//! Name of the cookie that stores the start time and referrer
	cookie_exp:600,		//! Cookie expiry in seconds
	strict_referrer: true,	//! By default, don't beacon if referrers don't match.
				// If set to false, beacon both referrer values and let
				// the back end decide

	navigationType: 0,
	navigationStart: undefined,
	responseStart: undefined,
	t_start: undefined,
	r: undefined,
	r2: undefined,

	initFromCookie: function() {
		var subcookies;

		// A beacon may be fired automatically on page load or if the page dev fires
		// it manually with their own timers.  It may not always contain a referrer
		// (eg: XHR calls).  We set default values for these cases

		this.r = this.r2 = d.referrer.replace(/#.*/, '');

		if(!this.cookie) {
			return;
		}

		subcookies = BOOMR.utils.getSubCookies(BOOMR.utils.getCookie(impl.cookie));

		if(!subcookies) {
			return;
		}

		if(subcookies && subcookies.s && subcookies.r) {
			this.r = subcookies.r;
			if(!this.strict_referrer || this.r === this.r2) {
				this.t_start = parseInt(subcookies.s, 10);
			}
		}

	},

	// The start method is fired on page unload.  It is called with the scope
	// of the BOOMR.plugins.RT object
	start: function() {
		var t_end, t_start = new Date().getTime();

		// Disable use of RT cookie by setting its name to a falsy value
		if(!this.cookie) {
			return this;
		}

		// We use document.URL instead of location.href because of a bug in safari 4
		// where location.href is URL decoded
		if(!BOOMR.utils.setCookie(this.cookie,
						{ s: t_start, r: d.URL.replace(/#.*/, '') },
						this.cookie_exp)
		) {
			BOOMR.error("cannot set start cookie", "rt");
			return this;
		}

		t_end = new Date().getTime();
		if(t_end - t_start > 50) {
			// It took > 50ms to set the cookie
			// The user Most likely has cookie prompting turned on so
			// t_start won't be the actual unload time
			// We bail at this point since we can't reliably tell t_done
			BOOMR.utils.removeCookie(this.cookie);

			// at some point we may want to log this info on the server side
			BOOMR.error("took more than 50ms to set cookie... aborting: "
					+ t_start + " -> " + t_end, "rt");
		}

		return this;
	},

	initNavTiming: function() {
		var ti, p, source;

		if(this.navigationStart) {
			return;
		}

		// Get start time from WebTiming API see:
		// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html
		// http://blogs.msdn.com/b/ie/archive/2010/06/28/measuring-web-page-performance.aspx
		// http://blog.chromium.org/2010/07/do-you-know-how-slow-your-web-page-is.html
		p = w.performance || w.msPerformance || w.webkitPerformance || w.mozPerformance;

		if(p && p.navigation) {
			this.navigationType = p.navigation.type;
		}

		if(p && p.timing) {
			ti = p.timing;
		}
		else if(w.chrome && w.chrome.csi && w.chrome.csi().startE) {
			// Older versions of chrome also have a timing API that's sort of documented here:
			// http://ecmanaut.blogspot.com/2010/06/google-bom-feature-ms-since-pageload.html
			// source here:
			// http://src.chromium.org/viewvc/chrome/trunk/src/chrome/renderer/loadtimes_extension_bindings.cc?view=markup
			ti = {
				navigationStart: w.chrome.csi().startE
			};
			source = "csi";
		}
		else if(w.gtbExternal && w.gtbExternal.startE()) {
			// The Google Toolbar exposes navigation start time similar to old versions of chrome
			// This would work for any browser that has the google toolbar installed
			ti = {
				navigationStart: w.gtbExternal.startE()
			};
			source = 'gtb';
		}

		if(ti) {
			// Always use navigationStart since it falls back to fetchStart (not with redirects)
			// If not set, we leave t_start alone so that timers that depend
			// on it don't get sent back.  Never use requestStart since if
			// the first request fails and the browser retries, it will contain
			// the value for the new request.
			BOOMR.addVar("rt.start", source || "navigation");
			this.navigationStart = ti.navigationStart || ti.fetchStart || undefined;
			this.responseStart = ti.responseStart || undefined;

			// bug in Firefox 7 & 8 https://bugzilla.mozilla.org/show_bug.cgi?id=691547
			if(navigator.userAgent.match(/Firefox\/[78]\./)) {
				this.navigationStart = ti.unloadEventStart || ti.fetchStart || undefined;
			}
		}
		else {
			BOOMR.warn("This browser doesn't support the WebTiming API", "rt");
		}

		return;
	},

	domloaded: function() {
		BOOMR.plugins.RT.endTimer("t_domloaded");
	}
};

BOOMR.plugins.RT = {
	// Methods

	init: function(config) {
		impl.complete = false;
		impl.timers = {};

		BOOMR.utils.pluginConfig(impl, config, "RT",
					["cookie", "cookie_exp", "strict_referrer"]);

		BOOMR.subscribe("page_ready", this.done, null, this);
		BOOMR.subscribe("dom_loaded", impl.domloaded, null, impl);
		BOOMR.subscribe("page_unload", impl.start, null, impl);

		if(BOOMR.t_start) {
			// How long does it take Boomerang to load up and execute
			this.startTimer('boomerang', BOOMR.t_start);
			this.endTimer('boomerang', BOOMR.t_end);	// t_end === null defaults to current time

			// How long did it take till Boomerang started
			this.endTimer('boomr_fb', BOOMR.t_start);
		}

		return this;
	},

	startTimer: function(timer_name, time_value) {
		if(timer_name) {
			if (timer_name === 't_page') {
				this.endTimer('t_resp', time_value);
			}
			impl.timers[timer_name] = {start: (typeof time_value === "number" ? time_value : new Date().getTime())};
			impl.complete = false;
		}

		return this;
	},

	endTimer: function(timer_name, time_value) {
		if(timer_name) {
			impl.timers[timer_name] = impl.timers[timer_name] || {};
			if(!("end" in impl.timers[timer_name])) {
				impl.timers[timer_name].end =
						(typeof time_value === "number" ? time_value : new Date().getTime());
			}
		}

		return this;
	},

	setTimer: function(timer_name, time_delta) {
		if(timer_name) {
			impl.timers[timer_name] = { delta: time_delta };
		}

		return this;
	},

	// Called when the page has reached a "usable" state.  This may be when the
	// onload event fires, or it could be at some other moment during/after page
	// load when the page is usable by the user
	done: function() {
		var basic_timers = { t_done: 1, t_resp: 1, t_page: 1},
		    ntimers = 0, t_name, timer, t_other=[];

		if(impl.complete) {
			return this;
		}

		impl.initNavTiming();

		if(
			(d.webkitVisibilityState && d.webkitVisibilityState === "prerender")
			||
			(d.msVisibilityState && d.msVisibilityState === 3)
		) {
			// This means that onload fired through a pre-render.  We'll capture this
			// time, but wait for t_done until after the page has become either visible
			// or hidden (ie, it moved out of the pre-render state)
			// http://code.google.com/chrome/whitepapers/pagevisibility.html
			// http://www.w3.org/TR/2011/WD-page-visibility-20110602/
			// http://code.google.com/chrome/whitepapers/prerender.html

			this.startTimer("t_load", impl.navigationStart);
			this.endTimer("t_load");		// this will measure actual onload time for a prerendered page
			this.startTimer("t_prerender", impl.navigationStart);
			this.startTimer("t_postrender");	// time from prerender to visible or hidden

			BOOMR.subscribe("visibility_changed", this.done, null, this);

			return this;
		}

		// If the dev has already called endTimer, then this call will do nothing
		// else, it will stop the page load timer
		this.endTimer("t_done");

		if(impl.responseStart) {
			// Use NavTiming API to figure out resp latency and page time
			// t_resp will use the cookie if available or fallback to NavTiming
			this.endTimer("t_resp", impl.responseStart);
			if(impl.timers.t_load) {
				this.setTimer("t_page", impl.timers.t_load.end - impl.responseStart);
			}
			else {
				this.setTimer("t_page", new Date().getTime() - impl.responseStart);
			}
		}
		else if(impl.timers.hasOwnProperty('t_page')) {
			// If the dev has already started t_page timer, we can end it now as well
			this.endTimer("t_page");
		}

		// If a prerender timer was started, we can end it now as well
		if(impl.timers.hasOwnProperty('t_postrender')) {
			this.endTimer("t_postrender");
			this.endTimer("t_prerender");
		}

		impl.initFromCookie();

		if(impl.t_start && impl.navigationType != 2) {	// 2 is TYPE_BACK_FORWARD but the constant may not be defined across browsers
			BOOMR.addVar("rt.start", "cookie");	// if the user hit the back button, referrer will match, and cookie will match
		}						// but will have time of previous page start, so t_done will be wrong
		else {
			impl.t_start = impl.navigationStart;
		}

		// make sure old variables don't stick around
		BOOMR.removeVar('t_done', 't_page', 't_resp', 'r', 'r2', 'rt.bstart', 'rt.end');

		BOOMR.addVar('rt.bstart', BOOMR.t_start);
		BOOMR.addVar('rt.end', impl.timers.t_done.end);

		for(t_name in impl.timers) {
			if(!impl.timers.hasOwnProperty(t_name)) {
				continue;
			}

			timer = impl.timers[t_name];

			// if delta is a number, then it was set using setTimer
			// if not, then we have to calculate it using start & end
			if(typeof timer.delta !== "number") {
				if(typeof timer.start !== "number") {
					timer.start = impl.t_start;
				}
				timer.delta = timer.end - timer.start;
			}

			// If the caller did not set a start time, and if there was no start cookie
			// then timer.delta will be NaN, in which case we discard it.
			if(isNaN(timer.delta)) {
				continue;
			}

			if(basic_timers.hasOwnProperty(t_name)) {
				BOOMR.addVar(t_name, timer.delta);
			}
			else {
				t_other.push(t_name + '|' + timer.delta);
			}
			ntimers++;
		}

		if(ntimers) {
			BOOMR.addVar("r", impl.r);

			if(r2 !== r) {
				BOOMR.addVar("r2", impl.r2);
			}

			if(t_other.length) {
				BOOMR.addVar("t_other", t_other.join(','));
			}
		}

		impl.timers = {};
		impl.complete = true;

		BOOMR.sendBeacon();	// we call sendBeacon() anyway because some other plugin
					// may have blocked waiting for RT to complete
		return this;
	},

	is_complete: function() { return impl.complete; }

};

}(window));
// End of RT plugin

<|endoftext|>


<commit_before>const CACHE_NAME = 'neutron-v1';
const urlsToCache = [
  './',
  '/(index)',
  '/styles/main.css',
  '/styles/bootstrap.min.css',
  '/images/3246305.jpg',
  '/index.19fb4943df0cf427704a.bundle.js',
  '/manifest.1487ea393e348f6eea30.bundle.js',
  '/scripts/loadsw.js',
  '/scripts/bootstrap.min.js',
  '/scripts/jquery-3.1.1.slim.min.js',
  '/scripts/tether.min.js',
];

self.addEventListener('install', function(event) {
  // Perform install steps
  console.log('Installing SW!');
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(function(cache) {
        console.log('Opened cache');
        return cache.addAll(urlsToCache);
      })
  );
});

this.addEventListener('activate', function(event) {
  const cacheWhitelist = [CACHE_NAME];

  event.waitUntil(
    caches.keys().then(function(keyList) {
      return Promise.all(keyList.map(function(key) {
        if (cacheWhitelist.indexOf(key) === -1) {
          return caches.delete(key);
        }
      }));
    })
  );
});

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request)
      .then(function(response) {
        // Cache hit - return response
        if (response) {
          return response;
        }

        // IMPORTANT: Clone the request. Since we are consuming this
        // once by cache and once by the browser for fetch, we need
        // to clone the response.
        var fetchRequest = event.request.clone();

        return fetch(fetchRequest).then(
          function(response) {
            // Check if we received a valid response
            if(!response || response.status !== 200 || response.type !== 'basic') {
              return response;
            }

            // We want the browser to consume the response
            // as well as the cache consuming the response, we need
            // to clone it so we have two streams.
            var responseToCache = response.clone();

            caches.open(CACHE_NAME)
              .then(function(cache) {
                cache.put(event.request, responseToCache);
              });

            return response;
          }
        );
      })
    );
});
<commit_msg>removed './' from sw<commit_after>const CACHE_NAME = 'neutron-v1';
const urlsToCache = [
  '/(index)',
  '/styles/main.css',
  '/styles/bootstrap.min.css',
  '/images/3246305.jpg',
  '/index.19fb4943df0cf427704a.bundle.js',
  '/manifest.1487ea393e348f6eea30.bundle.js',
  '/scripts/loadsw.js',
  '/scripts/bootstrap.min.js',
  '/scripts/jquery-3.1.1.slim.min.js',
  '/scripts/tether.min.js',
];

self.addEventListener('install', function(event) {
  // Perform install steps
  console.log('Installing SW!');
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(function(cache) {
        console.log('Opened cache');
        return cache.addAll(urlsToCache);
      })
  );
});

this.addEventListener('activate', function(event) {
  const cacheWhitelist = [CACHE_NAME];

  event.waitUntil(
    caches.keys().then(function(keyList) {
      return Promise.all(keyList.map(function(key) {
        if (cacheWhitelist.indexOf(key) === -1) {
          return caches.delete(key);
        }
      }));
    })
  );
});

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request)
      .then(function(response) {
        // Cache hit - return response
        if (response) {
          return response;
        }

        // IMPORTANT: Clone the request. Since we are consuming this
        // once by cache and once by the browser for fetch, we need
        // to clone the response.
        var fetchRequest = event.request.clone();

        return fetch(fetchRequest).then(
          function(response) {
            // Check if we received a valid response
            if(!response || response.status !== 200 || response.type !== 'basic') {
              return response;
            }

            // We want the browser to consume the response
            // as well as the cache consuming the response, we need
            // to clone it so we have two streams.
            var responseToCache = response.clone();

            caches.open(CACHE_NAME)
              .then(function(cache) {
                cache.put(event.request, responseToCache);
              });

            return response;
          }
        );
      })
    );
});
<|endoftext|>


<commit_before>var VERSION = "1.0.16";
var CACHE_NAME = 'fireworks-cache-v' + VERSION;
var urlsToCache = [
  'index.html',
  'elements/card.html',
  'elements/counter.html',
  'elements/elements.html',
  'elements/game.html',
  'elements/gamecontroller.html',
  'elements/player.html',
  'elements/routing.html',
  'images/board.jpg',
  'images/bombicon.jpg',
  'images/fireworks.png',
  'images/back.jpg',
  'images/jake.jpg',
  'images/hinticon.jpg',
  'scripts/app.js',
  'styles/app-theme.html',
  'styles/main.css'
];

self.addEventListener('install', function(event) {
  self.skipWaiting();
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(function(cache) {
        console.log('Opened cache');
        return cache.addAll(urlsToCache);
      })
  );
});

self.addEventListener('fetch', function(event) {
  var regex = /client\/version$/;
  if (event.request.url.match(regex)) {
    event.respondWith(new Response(VERSION, {
          headers: {'Content-Type': 'text/plain'}
    }));
  }
  else {
    event.respondWith(
      caches.match(event.request)
        .then(function(response) {
          // Cache hit - return response
          if (response) {
            return response;
          }

          // IMPORTANT: Clone the request. A request is a stream and
          // can only be consumed once. Since we are consuming this
          // once by cache and once by the browser for fetch, we need
          // to clone the response.
          var fetchRequest = event.request.clone();

          return fetch(fetchRequest).then(
            function(response) {
              // Check if we received a valid response
              if(!response || response.status !== 200 || response.type !== 'basic' || event.request.method == 'POST') {
                return response;
              }

              // IMPORTANT: Clone the response. A response is a stream
              // and because we want the browser to consume the response
              // as well as the cache consuming the response, we need
              // to clone it so we have two streams.
              var responseToCache = response.clone();

              caches.open(CACHE_NAME)
                .then(function(cache) {
                  cache.put(event.request, responseToCache);
                });

              return response;
            }
          );
        })
      );
  }
});

self.addEventListener('activate', function(event) {

  var cacheWhitelist = [CACHE_NAME];

  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        cacheNames.map(function(cacheName) {
          if (cacheWhitelist.indexOf(cacheName) === -1) {
            return caches.delete(cacheName);
          }
        })
      );
    })
  );
});

importScripts('https://www.gstatic.com/firebasejs/3.5.2/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/3.5.2/firebase-messaging.js');
firebase.initializeApp({
  'messagingSenderId': '168641906858'
});

const messaging = firebase.messaging();

messaging.setBackgroundMessageHandler(function(payload) {
  console.log('Received background message ', payload);
  // Customize notification here
  const notificationTitle = "Fireworks - it's your turn!";
  const notificationOptions = {
    body: 'Other players are waiting for you! Take your turn.',
    icon: '/firebase-logo.png',
    click_action: 'https://fellyeah.dlinkddns.com:80/#!/games/' + payload.data.Game
  };

  return self.registration.showNotification(notificationTitle,
      notificationOptions);
});<commit_msg>Updated version<commit_after>var VERSION = "1.0.17";
var CACHE_NAME = 'fireworks-cache-v' + VERSION;
var urlsToCache = [
  'index.html',
  'elements/card.html',
  'elements/counter.html',
  'elements/elements.html',
  'elements/game.html',
  'elements/gamecontroller.html',
  'elements/player.html',
  'elements/routing.html',
  'images/board.jpg',
  'images/bombicon.jpg',
  'images/fireworks.png',
  'images/back.jpg',
  'images/jake.jpg',
  'images/hinticon.jpg',
  'scripts/app.js',
  'styles/app-theme.html',
  'styles/main.css'
];

self.addEventListener('install', function(event) {
  self.skipWaiting();
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(function(cache) {
        console.log('Opened cache');
        return cache.addAll(urlsToCache);
      })
  );
});

self.addEventListener('fetch', function(event) {
  var regex = /client\/version$/;
  if (event.request.url.match(regex)) {
    event.respondWith(new Response(VERSION, {
          headers: {'Content-Type': 'text/plain'}
    }));
  }
  else {
    event.respondWith(
      caches.match(event.request)
        .then(function(response) {
          // Cache hit - return response
          if (response) {
            return response;
          }

          // IMPORTANT: Clone the request. A request is a stream and
          // can only be consumed once. Since we are consuming this
          // once by cache and once by the browser for fetch, we need
          // to clone the response.
          var fetchRequest = event.request.clone();

          return fetch(fetchRequest).then(
            function(response) {
              // Check if we received a valid response
              if(!response || response.status !== 200 || response.type !== 'basic' || event.request.method == 'POST') {
                return response;
              }

              // IMPORTANT: Clone the response. A response is a stream
              // and because we want the browser to consume the response
              // as well as the cache consuming the response, we need
              // to clone it so we have two streams.
              var responseToCache = response.clone();

              caches.open(CACHE_NAME)
                .then(function(cache) {
                  cache.put(event.request, responseToCache);
                });

              return response;
            }
          );
        })
      );
  }
});

self.addEventListener('activate', function(event) {

  var cacheWhitelist = [CACHE_NAME];

  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        cacheNames.map(function(cacheName) {
          if (cacheWhitelist.indexOf(cacheName) === -1) {
            return caches.delete(cacheName);
          }
        })
      );
    })
  );
});

importScripts('https://www.gstatic.com/firebasejs/3.5.2/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/3.5.2/firebase-messaging.js');
firebase.initializeApp({
  'messagingSenderId': '168641906858'
});

const messaging = firebase.messaging();

messaging.setBackgroundMessageHandler(function(payload) {
  console.log('Received background message ', payload);
  // Customize notification here
  const notificationTitle = "Fireworks - it's your turn!";
  const notificationOptions = {
    body: 'Other players are waiting for you! Take your turn.',
    icon: '/firebase-logo.png',
    click_action: 'https://fellyeah.dlinkddns.com:80/#!/games/' + payload.data.Game
  };

  return self.registration.showNotification(notificationTitle,
      notificationOptions);
});
<|endoftext|>


<commit_before>'use strict';
const path = require('path');
const typescript = require('typescript');
const buffer = require('vinyl-buffer');
const source = require('vinyl-source-stream');
const browserify = require('browserify');
const gulp = require('gulp');
const runSequence = require('run-sequence').use(gulp);
const plumber = require('gulp-plumber');
const sourcemaps = require('gulp-sourcemaps');
const stylish = require('gulp-tslint-stylish');
const tslint = require('gulp-tslint');
const gulpTypescript = require('gulp-typescript');
const babel = require('gulp-babel');
const gulpIf = require('gulp-if');
const uglify = require('gulp-uglify');

module.exports = opts => {
    opts = opts || {};
    opts.lint = opts.lint || ['src/**/*.ts'];
    opts.umd = opts.umd || {
        src: ['src/**/*.ts', '!src/test/**', '!src/public/js/**'],
        dest: 'lib/',
        configPath: 'src/tsconfig.json'
    };
    opts.browserify = opts.browserify || {};
    opts.browserify.files = opts.browserify.files || [{
        src: 'src/public/js/app.ts',
        dest: 'lib/public/js/'
    }];
    opts.browserify.configPath = opts.browserify.configPath || 'src/public/js/tsconfig.json';

    let project = {};
    let releaseProject = {};
    try {
        project = gulpTypescript.createProject(opts.umd.configPath, {
            typescript
        });
        releaseProject = gulpTypescript.createProject(opts.umd.configPath, {
            removeComments: true,
            typescript
        });
    } catch (e) {
    }
    let browserifyProject = releaseProject;
    try {
        browserifyProject = require('../' + opts.browserify.configPath).compilerOptions;
    } catch (e) {
        browserifyProject = project.config.compilerOptions;
    }
    browserifyProject.typescript = typescript;

    gulp.task('ts:build', callback => {
        runSequence('ts:lint', 'ts:compile', callback);
    });
    gulp.task('ts:release', callback => {
        runSequence('ts:lint', 'ts:release-compile', callback);
    });

    gulp.task('ts:lint', () => {
        return gulp.src(opts.lint)
            .pipe(plumber({ errorHandler: errorHandler }))
            .pipe(tslint())
            .pipe(tslint.report(stylish, {
                emitError: false,
                sort: true,
                bell: false
            }));
    });

    const babelOptions = {
        plugins: [
            'transform-es2015-destructuring',
            'transform-es2015-modules-commonjs'
        ]
    };

    gulp.task('ts:compile:umd', () => {
        return gulp.src(opts.umd.src)
            .pipe(plumber({ errorHandler: errorHandler }))
            .pipe(sourcemaps.init())
            .pipe(gulpTypescript(project))
            .pipe(babel(babelOptions))
            .pipe(sourcemaps.write())
            .pipe(gulp.dest(opts.umd.dest));
    });

    gulp.task('ts:release-compile:umd', () => {
        return gulp.src(opts.umd.src)
            .pipe(plumber())
            .pipe(gulpTypescript(releaseProject))
            .pipe(babel(babelOptions))
            .pipe(gulp.dest(opts.umd.dest));
    });

    gulp.task('ts:compile:browserify', createBrowserify(true));
    gulp.task('ts:release-compile:browserify', createBrowserify(false));
    function createBrowserify(debug) {
        return () => {
            return Promise.all(opts.browserify.files.map(x => {
                return new Promise((resolve, reject) => {
                    let basename = path.basename(x.src);
                    let outputName = basename.replace(new RegExp(path.extname(basename) + '$'), '.js');
                    browserify({
                        entries: [x.src],
                        removeComments: !debug,
                        debug: debug
                    })
                        .plugin('tsify', browserifyProject)
                        .plugin('babelify', { presets: ['es2015'] })
                        .bundle()
                        .on('error', err => {
                            console.error(err.message);
                            reject();
                        })
                        .pipe(source(outputName))
                        .pipe(gulpIf(!debug, buffer()))
                        .pipe(gulpIf(!debug, uglify()))
                        .pipe(gulp.dest(x.dest))
                        .on('end', resolve);
                })
            }));
        };
    }

    gulp.task('ts:compile', ['ts:compile:umd', 'ts:compile:browserify']);

    gulp.task('ts:release-compile', ['ts:release-compile:umd', 'ts:release-compile:browserify']);
};

function errorHandler(e) {
    console.error(e.toString());
    if (e.codeFrame != null) {
        console.error(e.codeFrame);
    }
}
<commit_msg>Update<commit_after>'use strict';
const path = require('path');
const typescript = require('typescript');
const buffer = require('vinyl-buffer');
const source = require('vinyl-source-stream');
const browserify = require('browserify');
const gulp = require('gulp');
const runSequence = require('run-sequence').use(gulp);
const plumber = require('gulp-plumber');
const sourcemaps = require('gulp-sourcemaps');
const stylish = require('gulp-tslint-stylish');
const tslint = require('gulp-tslint');
const gulpTypescript = require('gulp-typescript');
const babel = require('gulp-babel');
const gulpIf = require('gulp-if');
const uglify = require('gulp-uglify');

module.exports = opts => {
    opts = opts || {};
    opts.lint = opts.lint || ['src/**/*.ts'];
    opts.umd = opts.umd || {
        src: ['src/**/*.ts', '!src/test/**', '!src/public/js/**'],
        dest: 'lib/',
        configPath: 'src/tsconfig.json'
    };
    opts.browserify = opts.browserify || {};
    opts.browserify.files = opts.browserify.files || [{
        src: 'src/public/js/app.ts',
        dest: 'lib/public/js/'
    }];
    opts.browserify.configPath = opts.browserify.configPath || 'src/public/js/tsconfig.json';

    let project = {};
    let releaseProject = {};
    try {
        project = gulpTypescript.createProject(opts.umd.configPath, {
            typescript
        });
        releaseProject = gulpTypescript.createProject(opts.umd.configPath, {
            removeComments: true,
            typescript
        });
    } catch (e) {
    }
    let browserifyProject;
    try {
        browserifyProject = require('../' + opts.browserify.configPath).compilerOptions;
    } catch (e) {
        browserifyProject = project.config.compilerOptions;
    }

    gulp.task('ts:build', callback => {
        runSequence('ts:lint', 'ts:compile', callback);
    });
    gulp.task('ts:release', callback => {
        runSequence('ts:lint', 'ts:release-compile', callback);
    });

    gulp.task('ts:lint', () => {
        return gulp.src(opts.lint)
            .pipe(plumber({ errorHandler: errorHandler }))
            .pipe(tslint())
            .pipe(tslint.report(stylish, {
                emitError: false,
                sort: true,
                bell: false
            }));
    });

    const babelOptions = {
        plugins: [
            'transform-es2015-destructuring',
            'transform-es2015-modules-commonjs'
        ]
    };

    gulp.task('ts:compile:umd', createUmd(true));
    gulp.task('ts:release-compile:umd', createUmd(false));
    function createUmd(debug) {
        return () => gulp.src(opts.umd.src)
            .pipe(plumber({ errorHandler: errorHandler }))
            .pipe(gulpIf(debug, sourcemaps.init()))
            .pipe(gulpTypescript(project))
            .pipe(babel(babelOptions))
            .pipe(gulpIf(debug, sourcemaps.write()))
            .pipe(gulp.dest(opts.umd.dest));
    }

    gulp.task('ts:compile:browserify', createBrowserify(true));
    gulp.task('ts:release-compile:browserify', createBrowserify(false));
    function createBrowserify(debug) {
        let files = opts.browserify.files;
        return () => Promise.all(files.map(x => new Promise((resolve, reject) => {
            let basename = path.basename(x.src);
            let outputName = basename.replace(
                new RegExp(path.extname(basename) + '$'), '.js');
            browserify({
                entries: x.src,
                removeComments: !debug,
                debug: debug
            })
                .plugin('tsify', browserifyProject)
                .bundle()
                .on('error', err => {
                    console.error(err.toString());
                    reject();
                })
                .pipe(source(outputName))
                .pipe(gulpIf(!debug, buffer()))
                .pipe(gulpIf(!debug, uglify()))
                .pipe(gulp.dest(x.dest))
                .on('end', resolve);
        })));
    }

    gulp.task('ts:compile', ['ts:compile:umd', 'ts:compile:browserify']);

    gulp.task('ts:release-compile', ['ts:release-compile:umd', 'ts:release-compile:browserify']);
};

function errorHandler(e) {
    console.error(e.toString());
    if (e.codeFrame != null) {
        console.error(e.codeFrame);
    }
}
<|endoftext|>


<commit_before>$(document).ready(function () {
	$("#parseButton").click(function () {
		var example = window.ReverseRegexThing.parse($("#regex").val());
		$("
").text(example).prependTo($("#exampleOutput"));
	});
});<commit_msg>Added support for supplying pattern as GET param.<commit_after>$(document).ready(function () {
	$("#parseButton").click(function () {
		var example = window.ReverseRegexThing.parse($("#regex").val());
		$("
").text(example).prependTo($("#exampleOutput"));
	});

	if (window.location.search) {
		var getItems = window.location.search.substr(1).split('&');
		var getParameters = {};
		for (var i = 0; i < getItems.length; i++) {
			var keyVal = getItems[i].split('=');
			getParameters[keyval[0]] = keyVal[1];
		}

		if (getParameters["pattern"]) {
			$("#regex").val(decodeURIComponent(getParameters["pattern"]));
		}
	}
});
<|endoftext|>


<commit_before>var gd = require('node-gd');
var fs = require('fs');
var path = require('path');

var images = './img/';

function imagelinethick(img, x1, y1, x2, y2, color, thick)
{
    if (thick == undefined) { thick = 1; }

    if (thick == 1) {
        return img.line(x1, y1, x2, y2, color);
    }
    var t = thick / 2.0 - 0.5;
    if (x1 == x2 || y1 == y2) {
        return img.filledRectangle(Math.round(Math.min(x1, x2) - t), Math.round(Math.min(y1, y2) - t), Math.round(Math.max(x1, x2) + t), Math.round(Math.max(y1, y2) + t), color);
    }

    var k = (y2 - y1) / (x2 - x1); //y = kx + q
    var a = t / Math.sqrt(1 + Math.pow(k, 2));
    var points = [
        Math.round(x1 - (1+k)*a), Math.round(y1 + (1-k)*a),
        Math.round(x1 - (1-k)*a), Math.round(y1 - (1+k)*a),
        Math.round(x2 + (1+k)*a), Math.round(y2 - (1-k)*a),
        Math.round(x2 + (1-k)*a), Math.round(y2 + (1+k)*a),
    ];
    img.filledPolygon(points, color);
    img.polygon(points, color);
}

exports.clock = function(req, res, next) {

    var gear1 = gd.createFromPng(path.join(images, 'gear1.png')),
	   gear2 = gd.createFromPng(path.join(images, 'gear2.png')),
	   gear3 = gd.createFromPng(path.join(images, 'gear3.png')),
	   clock = gd.createFromPng(path.join(images, 'clock3.png')),

	   img = gd.createFromPng(path.join(images, 'clock3.png'));

	img.alphaBlending(1);
	img.setAntiAliased(1);

	var almostblack = img.colorallocate(1, 1, 1),
	   black = img.colorallocate(0, 0, 0),
	   white = img.colorallocate(255, 255, 255),
	   clear = img.colorallocatealpha(255, 255, 255, 0),
	   dark = img.colorallocate(113, 101, 79);

	img.colorTransparent(img, white);
	clock.colorTransparent(clock, white);
	gear1.colorTransparent(gear1, white);
	gear2.colorTransparent(gear2, white);
	gear3.colorTransparent(gear3, white);

    var date = new Date(),
        minute = date.getMinutes(),
        second = date.getSeconds(),
        hour = date.getHours();
    minute += (second / 60)

    var gear1_diag = 2 * Math.sqrt(Math.pow(0.5 * gear1.width, 2) + Math.pow(0.5 * gear1.height, 2)),
        gear1_ang = ((minute + hour * 60) * 30),
        gear1_rot = gd.createTrueColor(gear1_diag, gear1_diag),
        gear2_diag = 2 * Math.sqrt(Math.pow(0.5 * gear2.width, 2) + Math.pow(0.5 * gear2.height, 2)),
        gear2_ang = -(minute * 60),
        gear2_rot = gd.createTrueColor(gear2_diag, gear2_diag),
        gear3_diag = 2 * Math.sqrt(Math.pow(0.5 * gear3.width, 2) + Math.pow(0.5 * gear3.height, 2)),
        gear3_ang = (minute * 120),
        gear3_rot = gd.createTrueColor(gear3_diag, gear3_diag);

    //img.copyRotated(dest, dstX, dstY, srcX, srcY, srcW, srcH, angle);
	gear1.copyRotated(gear1_rot,
        (gear1_diag - gear1.width) / 2,
        (gear1_diag - gear1.height) / 2,
        0, 0,
        gear1.width,
        gear1.height,
        gear1_ang);
	gear2.copyRotated(gear2_rot,
        (gear2_diag - gear2.width) / 2,
        (gear2_diag - gear2.height) / 2,
        0, 0,
        gear2.width,
        gear2.height,
        gear2_ang);
    gear3.copyRotated(gear3_rot,
        (gear3_diag - gear3.width) / 2,
        (gear3_diag - gear3.height) / 2,
        0, 0,
        gear3.width,
        gear3.height,
        gear3_ang);

	offset1 = (gear1_rot.width - gear1.width) / 2;
	offset2 = (gear2_rot.width - gear2.width) / 2;
	offset3 = (gear3_rot.width - gear3.width) / 2;

    //img.copyMerge(dest, dstX, dstY, srcX, srcY, width, height, pct);
	gear1.copyMerge(img, 54 - offset1, 7 - offset1, 0, 0, gear1.width, gear1.height, 100);
	gear2.copyMerge(img, 77 - offset2, 40 - offset2, 0, 0, gear2.width, gear2.height, 100);
	gear3.copyMerge(img, 8 - offset3, 45 - offset3, 0, 0, gear3.width, gear3.height, 100);

	clock.copymerge(img, 0, 0, 0, 0, 100, 100, 100);

	for (i = 0; i < 50; i++) {
		x1 = 50 + 30 * Math.cos(((i / 50) * 2 * Math.PI + (Math.PI * 0.5)));
		y1 = 51 + 30 * Math.sin(((i / 50) * 2 * Math.PI + (Math.PI * 0.5)));
		x2 = 50 + 33 * Math.cos(((i / 50) * 2 * Math.PI + (Math.PI * 0.5)));
		y2 = 51 + 33 * Math.sin(((i / 50) * 2 * Math.PI + (Math.PI * 0.5)));

	imagelinethick(img, x1, y1, x2, y2, dark, 0.1);
	}

	for (i = 0; i < 10; i++) {
		x1 = 50 + 28 * Math.cos(((i / 10) * 2 * Math.PI + (Math.PI * 0.5)));
		y1 = 51 + 28 * Math.sin(((i / 10) * 2 * Math.PI + (Math.PI * 0.5)));
		x2 = 50 + 33 * Math.cos(((i / 10) * 2 * Math.PI + (Math.PI * 0.5)));
		y2 = 51 + 33 * Math.sin(((i / 10) * 2 * Math.PI + (Math.PI * 0.5)));

	imagelinethick(img, x1, y1, x2, y2, black, 2);
	}
	imagelinethick(img, 50, 18, 50, 33, black, 2);

	x = 50 + -25 * Math.cos(((minute / 60) * 2 * Math.PI) + Math.PI / 2);
	y = 52 + -25 * Math.sin(((minute / 60) * 2 * Math.PI) + Math.PI / 2);

	x2 = 50 + -16 * Math.cos(((minute / 60) * 2 * Math.PI) + Math.PI / 2);
	y2 = 52 + -16 * Math.sin(((minute / 60) * 2 * Math.PI) + Math.PI / 2);

	x3 = 50 + -9 * Math.cos(((minute / 60) * 2 * Math.PI) + Math.PI / 2);
	y3 = 52 + -9 * Math.sin(((minute / 60) * 2 * Math.PI) + Math.PI / 2);

	imagelinethick(img, 50, 52 , x, y, black, 2);
	imagelinethick(img, 50, 52 , x2, y2, black, 3);
	imagelinethick(img, 50, 52 , x3, y3, black, 4);

    //Save to a file and then read it back because pngPtr() doesn't work for some reason
    img.savePng('./temp2');
    var dat = fs.readFileSync('./temp2');

    res.set('Content-Type', 'image/png');
    res.end(dat, 'binary');
    img.destroy();
}<commit_msg>Use proper capitalization on colorAllocate<commit_after>var gd = require('node-gd');
var fs = require('fs');
var path = require('path');

var images = './img/';

function imagelinethick(img, x1, y1, x2, y2, color, thick)
{
    if (thick == undefined) { thick = 1; }

    if (thick == 1) {
        return img.line(x1, y1, x2, y2, color);
    }
    var t = thick / 2.0 - 0.5;
    if (x1 == x2 || y1 == y2) {
        return img.filledRectangle(Math.round(Math.min(x1, x2) - t), Math.round(Math.min(y1, y2) - t), Math.round(Math.max(x1, x2) + t), Math.round(Math.max(y1, y2) + t), color);
    }

    var k = (y2 - y1) / (x2 - x1); //y = kx + q
    var a = t / Math.sqrt(1 + Math.pow(k, 2));
    var points = [
        Math.round(x1 - (1+k)*a), Math.round(y1 + (1-k)*a),
        Math.round(x1 - (1-k)*a), Math.round(y1 - (1+k)*a),
        Math.round(x2 + (1+k)*a), Math.round(y2 - (1-k)*a),
        Math.round(x2 + (1-k)*a), Math.round(y2 + (1+k)*a),
    ];
    img.filledPolygon(points, color);
    img.polygon(points, color);
}

exports.clock = function(req, res, next) {

    var gear1 = gd.createFromPng(path.join(images, 'gear1.png')),
	   gear2 = gd.createFromPng(path.join(images, 'gear2.png')),
	   gear3 = gd.createFromPng(path.join(images, 'gear3.png')),
	   clock = gd.createFromPng(path.join(images, 'clock3.png')),

	   img = gd.createFromPng(path.join(images, 'clock3.png'));

	img.alphaBlending(1);
	img.setAntiAliased(1);

	var almostblack = img.colorAllocate(1, 1, 1),
	   black = img.colorAllocate(0, 0, 0),
	   white = img.colorAllocate(255, 255, 255),
	   clear = img.colorAllocatealpha(255, 255, 255, 0),
	   dark = img.colorAllocate(113, 101, 79);

	img.colorTransparent(img, white);
	clock.colorTransparent(clock, white);
	gear1.colorTransparent(gear1, white);
	gear2.colorTransparent(gear2, white);
	gear3.colorTransparent(gear3, white);

    var date = new Date(),
        minute = date.getMinutes(),
        second = date.getSeconds(),
        hour = date.getHours();
    minute += (second / 60)

    var gear1_diag = 2 * Math.sqrt(Math.pow(0.5 * gear1.width, 2) + Math.pow(0.5 * gear1.height, 2)),
        gear1_ang = ((minute + hour * 60) * 30),
        gear1_rot = gd.createTrueColor(gear1_diag, gear1_diag),
        gear2_diag = 2 * Math.sqrt(Math.pow(0.5 * gear2.width, 2) + Math.pow(0.5 * gear2.height, 2)),
        gear2_ang = -(minute * 60),
        gear2_rot = gd.createTrueColor(gear2_diag, gear2_diag),
        gear3_diag = 2 * Math.sqrt(Math.pow(0.5 * gear3.width, 2) + Math.pow(0.5 * gear3.height, 2)),
        gear3_ang = (minute * 120),
        gear3_rot = gd.createTrueColor(gear3_diag, gear3_diag);

    //img.copyRotated(dest, dstX, dstY, srcX, srcY, srcW, srcH, angle);
	gear1.copyRotated(gear1_rot,
        (gear1_diag - gear1.width) / 2,
        (gear1_diag - gear1.height) / 2,
        0, 0,
        gear1.width,
        gear1.height,
        gear1_ang);
	gear2.copyRotated(gear2_rot,
        (gear2_diag - gear2.width) / 2,
        (gear2_diag - gear2.height) / 2,
        0, 0,
        gear2.width,
        gear2.height,
        gear2_ang);
    gear3.copyRotated(gear3_rot,
        (gear3_diag - gear3.width) / 2,
        (gear3_diag - gear3.height) / 2,
        0, 0,
        gear3.width,
        gear3.height,
        gear3_ang);

	offset1 = (gear1_rot.width - gear1.width) / 2;
	offset2 = (gear2_rot.width - gear2.width) / 2;
	offset3 = (gear3_rot.width - gear3.width) / 2;

    //img.copyMerge(dest, dstX, dstY, srcX, srcY, width, height, pct);
	gear1.copyMerge(img, 54 - offset1, 7 - offset1, 0, 0, gear1.width, gear1.height, 100);
	gear2.copyMerge(img, 77 - offset2, 40 - offset2, 0, 0, gear2.width, gear2.height, 100);
	gear3.copyMerge(img, 8 - offset3, 45 - offset3, 0, 0, gear3.width, gear3.height, 100);

	clock.copymerge(img, 0, 0, 0, 0, 100, 100, 100);

	for (i = 0; i < 50; i++) {
		x1 = 50 + 30 * Math.cos(((i / 50) * 2 * Math.PI + (Math.PI * 0.5)));
		y1 = 51 + 30 * Math.sin(((i / 50) * 2 * Math.PI + (Math.PI * 0.5)));
		x2 = 50 + 33 * Math.cos(((i / 50) * 2 * Math.PI + (Math.PI * 0.5)));
		y2 = 51 + 33 * Math.sin(((i / 50) * 2 * Math.PI + (Math.PI * 0.5)));

	imagelinethick(img, x1, y1, x2, y2, dark, 0.1);
	}

	for (i = 0; i < 10; i++) {
		x1 = 50 + 28 * Math.cos(((i / 10) * 2 * Math.PI + (Math.PI * 0.5)));
		y1 = 51 + 28 * Math.sin(((i / 10) * 2 * Math.PI + (Math.PI * 0.5)));
		x2 = 50 + 33 * Math.cos(((i / 10) * 2 * Math.PI + (Math.PI * 0.5)));
		y2 = 51 + 33 * Math.sin(((i / 10) * 2 * Math.PI + (Math.PI * 0.5)));

	imagelinethick(img, x1, y1, x2, y2, black, 2);
	}
	imagelinethick(img, 50, 18, 50, 33, black, 2);

	x = 50 + -25 * Math.cos(((minute / 60) * 2 * Math.PI) + Math.PI / 2);
	y = 52 + -25 * Math.sin(((minute / 60) * 2 * Math.PI) + Math.PI / 2);

	x2 = 50 + -16 * Math.cos(((minute / 60) * 2 * Math.PI) + Math.PI / 2);
	y2 = 52 + -16 * Math.sin(((minute / 60) * 2 * Math.PI) + Math.PI / 2);

	x3 = 50 + -9 * Math.cos(((minute / 60) * 2 * Math.PI) + Math.PI / 2);
	y3 = 52 + -9 * Math.sin(((minute / 60) * 2 * Math.PI) + Math.PI / 2);

	imagelinethick(img, 50, 52 , x, y, black, 2);
	imagelinethick(img, 50, 52 , x2, y2, black, 3);
	imagelinethick(img, 50, 52 , x3, y3, black, 4);

    //Save to a file and then read it back because pngPtr() doesn't work for some reason
    img.savePng('./temp2');
    var dat = fs.readFileSync('./temp2');

    res.set('Content-Type', 'image/png');
    res.end(dat, 'binary');
    img.destroy();
}<|endoftext|>


<commit_before>module.exports = function (app, db, common) {

  // This could become a middleware in an ideal reality.
  //
  // Ecmascript 6 would make this easier...
  // let [ fields, start, size, sort ] = handle_parameters(req);
  function handle_parameters (req, full, callback) {
    if (req.params.server == null) {
      req.params.server = undefined;
    }

    if (req.params.version == null) {
      req.params.version = undefined;
    }

    var fields;
    if (full) {
        fields = ((req.query.fields == null ? '' : req.query.fields.split(',')));
    } else {
        fields = ((req.query.fields == null ? 'slug,plugin_name,description' : req.query.fields).split(','));
    }
    var start = req.query.start == null ? undefined : parseInt(req.query.start);
    var size = req.query.size == null ? undefined : parseInt(req.query.size);
    var sort = req.query.sort == null ? 'slug' : req.query.sort;

    return callback(fields, start, size, sort);
  }

  function geninfo (req, res, next) {
    handle_parameters(req, false, function (fields, start, size, sort) {
      common.list_geninfo(size, function (callback) {
        res.send(callback);
        next();
      });
    });
  }

  function plugin_list (req, res, next) {
    handle_parameters(req, false, function (fields, start, size, sort) {
      common.list_plugins(req.params.server, fields, sort, start, size, function (callback) {
        if (callback == null) {
          res.send(400, {
            "error": "invalid params"
          });
          return next();
        }
        res.send(callback);
        next();
      });
    });
  }

  function plugin_details (req, res, next) {
    handle_parameters(req, true, function (fields, start, size, sort) {
      common.plugin_details(req.params.server, req.params.slug, req.params.version, fields, function (data) {
        if (data == null) {
          res.send(404, "Plugin Does Not Exist");
          return next();
        }

        if (size != undefined && data['versions'] != null) {
          data['versions'].length = size;
        }

        res.send(data);
        next();
      });
    });
  }

  function author_plugins (req, res, next) {
    handle_parameters(req, false, function (fields, start, size, sort) {
      common.list_author_plugins(req.params.server, req.params.name, fields, sort, start, size, function (callback) {
        if (callback == null) {
          res.send(400, {
            "error": "invalid author"
          });
          return next();
        }
        res.send(callback);
        next();
      });
    });
  }

  function category_plugins (req, res, next) {
    handle_parameters(req, false, function (fields, start, size, sort) {
      common.list_category_plugins(req.params.server, req.params.name, fields, sort, start, size, function (callback) {
        if (callback == null) {
          res.send(400, {
            "error": "invalid category"
          });
          return next();
        }
        res.send(callback);
        next();
      });
    });
  }

  app.get('/3', function (req, res, next) {
    geninfo(req, res, next);
  });

  app.get('/3/geninfo', function (req, res, next) {
    geninfo(req, res, next);
  });

  app.get('/3/geninfo/:idnum', function (req, res, next) {
    common.get_geninfo(req.params.idnum, function (callback) {
      res.send(callback);
      next();
    });
  });

  app.get('/3/plugins', function (req, res, next) {
    plugin_list(req, res, next);
  });

  app.get('/3/plugins/:server', function (req, res, next) {
    plugin_list(req, res, next);
  });

  app.get('/3/plugins/:server/:slug', function (req, res, next) {
    plugin_details(req, res, next);
  });

  app.get('/3/plugins/:server/:slug/:version', function (req, res, next) {
    plugin_details(req, res, next);
  });

  app.get('/3/plugins/:server/:slug/:version/download', function (req, res, next) {
    common.plugin_details(req.params.server, req.params.slug, req.params.version, [], function (data) {
      if (data == null) {
        res.send(404, "Plugin Does Not Exist");
        return next();
      }

      if (req.params.version.toLowerCase() == "latest") {
        res.header('Location', data['versions'][0]['download']);
        res.send(302);
        return next();
      } else {
        for (var i = 0, il = data['versions'].length; i < il; i++) {
          if (data['versions'][i]['version'] == req.params.version) {
            res.header('Location', data['versions'][i]['download']);
            res.send(302);
            return next();
          }
        }
      }

      res.send(404, {"error": "could not find version"});
      next();
    });
  });

  app.get('/3/authors', function (req, res, next) {
    common.list_authors(function (callback) {
      res.send(callback);
      next();
    });
  });

  app.get('/3/authors/:name', function (req, res, next) {
    author_plugins(req, res, next);
  });

  app.get('/3/authors/:server/:name', function (req, res, next) {
    author_plugins(req, res, next);
  });

  app.get('/3/categories', function (req, res, next) {
    common.list_categories(function (callback) {
      res.send(callback);
      next();
    });
  });

  app.get('/3/categories/:name', function (req, res, next) {
    category_plugins(req, res, next);
  });

  app.get('/3/categories/:server/:name', function (req, res, next) {
    category_plugins(req, res, next);
  });

  app.post('/3/updates', function (req, res, next) {
    var slugs = (req.params.slugs == null ? '' : req.params.slugs).split(',');
    var server = req.params.server == null ? 'bukkit' : req.params.server;
    var hashes = (req.params.hashes == null ? '' : req.params.hashes).split(',');
    var filenames = (req.params.filenames == null ? '' : req.params.filenames).split(',');
    common.plugins_up_to_date(slugs, hashes, filenames, server, function (callback) {
      res.send(callback);
      next();
    });
  });

  app.get('/3/updates', function (req, res, next) {
    var slugs = (req.query.slugs == null ? '' : req.query.slugs).split(',');
    var server = req.query.server == null ? 'bukkit' : req.query.server;
    var hashes = (req.query.hashes == null ? '' : req.query.hashes).split(',');
    var filenames = (req.query.filenames == null ? '' : req.query.filenames).split(',');
    common.plugins_up_to_date(slugs, hashes, filenames, server, function (callback) {
      res.send(callback);
      next();
    });
  });

  function search (req, res, next) {
    var filters = []

    if (req.method == 'GET') {
      var fields = ((req.query.fields == null ? 'slug,plugin_name,description' : req.query.fields).split(','));
      var start = req.query.start == null ? undefined : parseInt(req.query.start);
      var size = req.query.size == null ? undefined : parseInt(req.query.size);
      var sort = req.query.sort == null ? 'slug' : req.query.sort;
      var field = req.params[0];
      var value = req.params[2];
      filters = [{
        'field': field,
        'action': req.params[1],
        'value': value
      }];
    } else {
      var filters = req.params.filters == null ? [] : JSON.parse(req.params.filters);
      var fields = ((req.params.fields == null ? 'slug,plugin_name,description' : req.params.fields).split(','));
      var start = req.params.start == null ? undefined : parseInt(req.params.start);
      var size = req.params.size == null ? undefined : parseInt(req.params.size);
      var sort = req.params.sort == null ? 'slug' : req.params.sort;
    }

    common.plugin_search(filters, fields, sort, start, size, false, function (callback) {
      if (callback == null) {
        res.send(400, {
          "error": "invalid search"
        });
        return next();
      }

      res.send(callback);
      next();
    });
  }

  app.post('/3/search', function (req, res, next) {
    search(req, res, next);
  });

  app.get(/^\/3\/search\/([a-zA-Z0-9_\.~-]+)\/(\=|\!\=|\<|\<\=|\>|\>\=|[a-z]+)\/([a-zA-Z0-9_\.~-]+)/, function (req, res, next) {
    search(req, res, next);
  });
}<commit_msg>Unify error messages<commit_after>module.exports = function (app, db, common) {

  // This could become a middleware in an ideal reality.
  //
  // Ecmascript 6 would make this easier...
  // let [ fields, start, size, sort ] = handle_parameters(req);
  function handle_parameters (req, full, callback) {
    if (req.params.server == null) {
      req.params.server = undefined;
    }

    if (req.params.version == null) {
      req.params.version = undefined;
    }

    var fields;
    if (full) {
        fields = ((req.query.fields == null ? '' : req.query.fields.split(',')));
    } else {
        fields = ((req.query.fields == null ? 'slug,plugin_name,description' : req.query.fields).split(','));
    }
    var start = req.query.start == null ? undefined : parseInt(req.query.start);
    var size = req.query.size == null ? undefined : parseInt(req.query.size);
    var sort = req.query.sort == null ? 'slug' : req.query.sort;

    return callback(fields, start, size, sort);
  }

  function geninfo (req, res, next) {
    handle_parameters(req, false, function (fields, start, size, sort) {
      common.list_geninfo(size, function (callback) {
        res.send(callback);
        next();
      });
    });
  }

  function plugin_list (req, res, next) {
    handle_parameters(req, false, function (fields, start, size, sort) {
      common.list_plugins(req.params.server, fields, sort, start, size, function (callback) {
        if (callback == null) {
          res.send(400, {
            "error": "invalid params"
          });
          return next();
        }
        res.send(callback);
        next();
      });
    });
  }

  function plugin_details (req, res, next) {
    handle_parameters(req, true, function (fields, start, size, sort) {
      common.plugin_details(req.params.server, req.params.slug, req.params.version, fields, function (data) {
        if (data == null) {
          res.send(404, { "error" : "Plugin Does Not Exist" });
          return next();
        }

        if (size != undefined && data['versions'] != null) {
          data['versions'].length = size;
        }

        res.send(data);
        next();
      });
    });
  }

  function author_plugins (req, res, next) {
    handle_parameters(req, false, function (fields, start, size, sort) {
      common.list_author_plugins(req.params.server, req.params.name, fields, sort, start, size, function (callback) {
        if (callback == null) {
          res.send(400, {
            "error": "invalid author"
          });
          return next();
        }
        res.send(callback);
        next();
      });
    });
  }

  function category_plugins (req, res, next) {
    handle_parameters(req, false, function (fields, start, size, sort) {
      common.list_category_plugins(req.params.server, req.params.name, fields, sort, start, size, function (callback) {
        if (callback == null) {
          res.send(400, {
            "error": "invalid category"
          });
          return next();
        }
        res.send(callback);
        next();
      });
    });
  }

  app.get('/3', function (req, res, next) {
    geninfo(req, res, next);
  });

  app.get('/3/geninfo', function (req, res, next) {
    geninfo(req, res, next);
  });

  app.get('/3/geninfo/:idnum', function (req, res, next) {
    common.get_geninfo(req.params.idnum, function (callback) {
      res.send(callback);
      next();
    });
  });

  app.get('/3/plugins', function (req, res, next) {
    plugin_list(req, res, next);
  });

  app.get('/3/plugins/:server', function (req, res, next) {
    plugin_list(req, res, next);
  });

  app.get('/3/plugins/:server/:slug', function (req, res, next) {
    plugin_details(req, res, next);
  });

  app.get('/3/plugins/:server/:slug/:version', function (req, res, next) {
    plugin_details(req, res, next);
  });

  app.get('/3/plugins/:server/:slug/:version/download', function (req, res, next) {
    common.plugin_details(req.params.server, req.params.slug, req.params.version, [], function (data) {
      if (data == null) {
        res.send(404, { "error" : "Plugin Does Not Exist" });
        return next();
      }

      if (req.params.version.toLowerCase() == "latest") {
        res.header('Location', data['versions'][0]['download']);
        res.send(302);
        return next();
      } else {
        for (var i = 0, il = data['versions'].length; i < il; i++) {
          if (data['versions'][i]['version'] == req.params.version) {
            res.header('Location', data['versions'][i]['download']);
            res.send(302);
            return next();
          }
        }
      }

      res.send(404, {"error": "could not find version"});
      next();
    });
  });

  app.get('/3/authors', function (req, res, next) {
    common.list_authors(function (callback) {
      res.send(callback);
      next();
    });
  });

  app.get('/3/authors/:name', function (req, res, next) {
    author_plugins(req, res, next);
  });

  app.get('/3/authors/:server/:name', function (req, res, next) {
    author_plugins(req, res, next);
  });

  app.get('/3/categories', function (req, res, next) {
    common.list_categories(function (callback) {
      res.send(callback);
      next();
    });
  });

  app.get('/3/categories/:name', function (req, res, next) {
    category_plugins(req, res, next);
  });

  app.get('/3/categories/:server/:name', function (req, res, next) {
    category_plugins(req, res, next);
  });

  app.post('/3/updates', function (req, res, next) {
    var slugs = (req.params.slugs == null ? '' : req.params.slugs).split(',');
    var server = req.params.server == null ? 'bukkit' : req.params.server;
    var hashes = (req.params.hashes == null ? '' : req.params.hashes).split(',');
    var filenames = (req.params.filenames == null ? '' : req.params.filenames).split(',');
    common.plugins_up_to_date(slugs, hashes, filenames, server, function (callback) {
      res.send(callback);
      next();
    });
  });

  app.get('/3/updates', function (req, res, next) {
    var slugs = (req.query.slugs == null ? '' : req.query.slugs).split(',');
    var server = req.query.server == null ? 'bukkit' : req.query.server;
    var hashes = (req.query.hashes == null ? '' : req.query.hashes).split(',');
    var filenames = (req.query.filenames == null ? '' : req.query.filenames).split(',');
    common.plugins_up_to_date(slugs, hashes, filenames, server, function (callback) {
      res.send(callback);
      next();
    });
  });

  function search (req, res, next) {
    var filters = []

    if (req.method == 'GET') {
      var fields = ((req.query.fields == null ? 'slug,plugin_name,description' : req.query.fields).split(','));
      var start = req.query.start == null ? undefined : parseInt(req.query.start);
      var size = req.query.size == null ? undefined : parseInt(req.query.size);
      var sort = req.query.sort == null ? 'slug' : req.query.sort;
      var field = req.params[0];
      var value = req.params[2];
      filters = [{
        'field': field,
        'action': req.params[1],
        'value': value
      }];
    } else {
      var filters = req.params.filters == null ? [] : JSON.parse(req.params.filters);
      var fields = ((req.params.fields == null ? 'slug,plugin_name,description' : req.params.fields).split(','));
      var start = req.params.start == null ? undefined : parseInt(req.params.start);
      var size = req.params.size == null ? undefined : parseInt(req.params.size);
      var sort = req.params.sort == null ? 'slug' : req.params.sort;
    }

    common.plugin_search(filters, fields, sort, start, size, false, function (callback) {
      if (callback == null) {
        res.send(400, {
          "error": "invalid search"
        });
        return next();
      }

      res.send(callback);
      next();
    });
  }

  app.post('/3/search', function (req, res, next) {
    search(req, res, next);
  });

  app.get(/^\/3\/search\/([a-zA-Z0-9_\.~-]+)\/(\=|\!\=|\<|\<\=|\>|\>\=|[a-z]+)\/([a-zA-Z0-9_\.~-]+)/, function (req, res, next) {
    search(req, res, next);
  });
}<|endoftext|>


<commit_before>// m16_001 #375
//
casper.test.begin('m16_001 #375 all full text links for this bib work', 6, function suite(test) {
casper.echo("Test environment: "+SERVER);
var USECASE='/item/9243519';
var ENTITY=SERVER+USECASE;
	casper.start(ENTITY, function() {
	test.assertTextExists('National Poultry Improvement Plan','verified title');
	test.assertTextExists('US GovPubs Online' , 'verified WRLC holdings');
	test.assertTextExists('Available Online through Mason' , 'verified GM holdings');
	test.assertTextExists('INTERNET' , 'verified GT holdings');
	test.assertSelectorHasText('button' , 'Full text online');
    test.assertElementCount('button',3,'three buttons found');
    }).run(function() {
        test.done();
    });
});
<commit_msg>updated match criteria per issue 947<commit_after>// m16_001 #375
//
casper.test.begin('m16_001 #375 all full text links for this bib work', 6, function suite(test) {
casper.echo("Test environment: "+SERVER);
var USECASE='/item/9243519';
var ENTITY=SERVER+USECASE;
	casper.start(ENTITY, function() {
	test.assertTextExists('National Poultry Improvement Plan','verified title');
	test.assertTextExists('US GovPubs Online' , 'verified WRLC holdings');
	test.assertTextExists('Available Online through Mason' , 'verified GM holdings');
	test.assertTextExists('Online' , 'verified GT holdings');
	test.assertSelectorHasText('button' , 'Full text online');
    test.assertElementCount('button',3,'three buttons found');
    }).run(function() {
        test.done();
    });
});
<|endoftext|>


<commit_before>Ext.define('CustomApp', {
    extend: 'Rally.app.App',
    componentCls: 'app',

    items: [
        {
            xtype: 'container',
            itemId: 'releaseFilter'
        },
        {
            xtype: 'container',
            itemId: 'grid'
        }
    ],

    launch: function() {

        this.down('#releaseFilter').add({
            xtype: 'rallyreleasecombobox',
            itemId: 'releaseComboBox',
            fieldLabel: 'Select Release: ',
            width: 310,
            labelWidth: 100,
            listeners: {
                ready: this._onReleaseComboboxLoad,
                change: this._onComboBoxChange,
                scope: this
            }
        });
    },

    _onComboBoxChange: function(comboBox) {
        this._defectRecords = [];
        this._onReleaseComboboxLoad(comboBox);
    },

    _onReleaseComboboxLoad: function(comboBox) {
        this.releaseComboBox = this.down('#releaseComboBox');

        Ext.create('Rally.data.WsapiDataStore', {
            model: 'Defect',
            autoLoad: true,
            fetch: ['FormattedID', 'Name', 'Owner', 'DisplayName', 'UserName', 'RevisionHistory'],
            filters: [this.releaseComboBox.getQueryFromSelected()],
            sorters: [{
                property: 'FormattedID',
                direction: 'ASC'
            }],
            listeners: {
                load: this._onDefectDataLoaded,
                scope: this
            }
        });
    },

    _onDefectDataLoaded: function(store, data) {
        this._customRecords = [];
        Ext.Array.each(data, function(defect, index) {
            this._customRecords.push({
                _ref: defect.get('_ref'),
                FormattedID: defect.get('FormattedID'),
                Name: defect.get('Name'),
                ClosedBy: 'not loaded',
                DateClosed: 'not loaded',
                RevisionID: Rally.util.Ref.getOidFromRef(defect.get('RevisionHistory')),
                RevisionNumber: 'not loaded'
            });
        }, this);

        this._getRevisionHistory(data);
    },

    _getRevisionHistory: function(defectList) {
        this._currentDefectList = Ext.clone(defectList);
        this._defectIndex = 0;
        var me = this, count;
        if (defectList.length > 0) {
            Ext.Array.each(defectList, function(defect) {
                this._revisionModel = Rally.data.ModelFactory.getModel({
                    type: 'RevisionHistory',
                    scope: this,
                    success: function(model) {
                        model.load(Rally.util.Ref.getOidFromRef(this._currentDefectList[this._defectIndex].get('RevisionHistory')),{
                            scope: this,
                            success: function(record, operation) {
                                record.getCollection('Revisions').load({
                                    fetch: true,
                                    scope: this,
                                    callback: function(revisions, operation, success) {
                                        Ext.Array.each(revisions, function(revision, revisionIndex) {
                                            if (revision.data.Description.search("CLOSED DATE added") !== -1) {
                                                Ext.Array.each(this._customRecords, function(customDefect) {
                                                    if (customDefect.RevisionID === record.internalId) {
                                                        customDefect.RevisionNumber = revision.get('RevisionNumber');
                                                        customDefect.DateClosed = revision.get('CreationDate');
                                                        customDefect.ClosedBy = revision.get('User')._refObjectName;
                                                        return false;
                                                    }
                                                }, this);
                                                return false;
                                            } else if (revisionIndex === (revisions.length-1)) {
                                                Ext.Array.each(this._customRecords, function(customDefect) {
                                                    if (customDefect && (customDefect.RevisionID === record.internalId)) {
                                                        Ext.Array.remove(this._customRecords, customDefect);
                                                        console.log('removed non-closed record: ' + customDefect.FormattedID);
                                                    }
                                                }, this);
                                            }
                                        }, this);
                                        this._buildGrid();
                                    }
                                });
                            }
                        });
                        this._defectIndex += 1;
                    }
                });
                return count;
            }, this);
        } else {
            this._buildGrid();
        }
    },

    _buildGrid: function() {
        var customStore = Ext.create('Rally.data.custom.Store', {
            data: this._customRecords,
            pageSize: this._customRecords.length
        });

        if (!this.grid) {
            this.grid = this.down('#grid').add({
                xtype: 'rallygrid',
                store: customStore,
                showPagingToolbar: false,
                columnCfgs: [
                    {text: 'Formatted ID', dataIndex: 'FormattedID', flex: 1, xtype: 'templatecolumn',
                        tpl: Ext.create('Rally.ui.renderer.template.FormattedIDTemplate')},
                    {text: 'Name', dataIndex: 'Name', flex: 2},
                    {text: 'Date Closed', dataIndex: 'DateClosed', flex: 2},
                    {text: 'Revision Number', dataIndex: 'RevisionNumber', flex: 1},
                    {text: 'Closed By', dataIndex: 'ClosedBy', flex: 1}
                ]
            });
        } else {
            this.grid.reconfigure(customStore);
        }
    },

    getOptions: function() {
        return [
            {
                text: 'Print',
                handler: this._onButtonPressed,
                scope: this
            }
        ];
    },

    _onButtonPressed: function() {
        var title = this.down('#releaseComboBox').getRawValue(),
            options;

        // code to get the style that we added in the app.css file
        var css = document.getElementsByTagName('style')[0].innerHTML;

        options = "toolbar=1,menubar=1,scrollbars=yes,scrolling=yes,resizable=yes,width=1000,height=500";
        var printWindow = window.open('', '', options);

        var doc = printWindow.document;

        var grid = this.down('#grid');

        doc.write('' + '<title>' + title + '</title>');

        doc.write('');
        doc.write('
Release: ' + title + '

');
        doc.write(grid.getEl().dom.innerHTML);
        doc.write('');
        doc.close();

        this._injectCSS(printWindow);

        printWindow.print();

    },

    _injectContent: function(html, elementType, attributes, container, printWindow){
        elementType = elementType || 'div';
        container = container || printWindow.document.getElementsByTagName('body')[0];

        var element = printWindow.document.createElement(elementType);

        Ext.Object.each(attributes, function(key, value){
            if (key === 'class') {
                element.className = value;
            } else {
                element.setAttribute(key, value);
            }
        });

        if(html){
            element.innerHTML = html;
        }

        return container.appendChild(element);
    },

    _injectCSS: function(printWindow){
        //find all the stylesheets on the current page and inject them into the new page
        Ext.each(Ext.query('link'), function(stylesheet){
                this._injectContent('', 'link', {
                rel: 'stylesheet',
                href: stylesheet.href,
                type: 'text/css'
            }, printWindow.document.getElementsByTagName('head')[0], printWindow);
        }, this);

    }
});<commit_msg>did some cosmetic work<commit_after>Ext.define('CustomApp', {
    extend: 'Rally.app.App',
    componentCls: 'app',

    items: [
        {
            xtype: 'container',
            itemId: 'releaseFilter'
        },
        {
            xtype: 'container',
            itemId: 'grid'
        }
    ],

    launch: function() {

        this.down('#releaseFilter').add({
            xtype: 'rallyreleasecombobox',
            itemId: 'releaseComboBox',
            fieldLabel: 'Select Release: ',
            width: 310,
            labelWidth: 100,
            listeners: {
                ready: this._onReleaseComboboxLoad,
                change: this._onComboBoxChange,
                scope: this
            }
        });
    },

    _onComboBoxChange: function(comboBox) {
        this._defectRecords = [];
        this._onReleaseComboboxLoad(comboBox);
    },

    _onReleaseComboboxLoad: function(comboBox) {
        this.releaseComboBox = this.down('#releaseComboBox');

        Ext.create('Rally.data.WsapiDataStore', {
            model: 'Defect',
            autoLoad: true,
            fetch: ['FormattedID', 'Name', 'Owner', 'DisplayName', 'UserName', 'RevisionHistory'],
            filters: [this.releaseComboBox.getQueryFromSelected()],
            sorters: [{
                property: 'FormattedID',
                direction: 'ASC'
            }],
            listeners: {
                load: this._onDefectDataLoaded,
                scope: this
            }
        });
    },

    _onDefectDataLoaded: function(store, data) {
        this._customRecords = [];
        Ext.Array.each(data, function(defect, index) {
            this._customRecords.push({
                _ref: defect.get('_ref'),
                FormattedID: defect.get('FormattedID'),
                Name: defect.get('Name'),
                ClosedBy: 'not loaded',
                DateClosed: 'not loaded',
                RevisionID: Rally.util.Ref.getOidFromRef(defect.get('RevisionHistory')),
                RevisionNumber: 'not loaded'
            });
        }, this);

        this._getRevisionHistory(data);
    },

    _getRevisionHistory: function(defectList) {
        this._currentDefectList = Ext.clone(defectList);
        this._defectIndex = 0;
        var me = this, count;
        if (defectList.length > 0) {
            Ext.Array.each(defectList, function(defect) {
                this._revisionModel = Rally.data.ModelFactory.getModel({
                    type: 'RevisionHistory',
                    scope: this,
                    success: function(model) {
                        model.load(Rally.util.Ref.getOidFromRef(this._currentDefectList[this._defectIndex].get('RevisionHistory')),{
                            scope: this,
                            success: function(record, operation) {
                                record.getCollection('Revisions').load({
                                    fetch: true,
                                    scope: this,
                                    callback: function(revisions, operation, success) {
                                        Ext.Array.each(revisions, function(revision, revisionIndex) {
                                            if (revision.data.Description.search("CLOSED DATE added") !== -1) {
                                                Ext.Array.each(this._customRecords, function(customDefect) {
                                                    if (customDefect.RevisionID === record.internalId) {
                                                        customDefect.RevisionNumber = revision.get('RevisionNumber');
                                                        customDefect.DateClosed = revision.get('CreationDate');
                                                        customDefect.ClosedBy = revision.get('User')._refObjectName;
                                                        return false;
                                                    }
                                                }, this);
                                                return false;
                                            } else if (revisionIndex === (revisions.length-1)) {
                                                Ext.Array.each(this._customRecords, function(customDefect) {
                                                    if (customDefect && (customDefect.RevisionID === record.internalId)) {
                                                        Ext.Array.remove(this._customRecords, customDefect);
                                                    }
                                                }, this);
                                            }
                                        }, this);
                                        this._buildGrid();
                                    }
                                });
                            }
                        });
                        this._defectIndex += 1;
                    }
                });
                return count;
            }, this);
        } else {
            this._buildGrid();
        }
    },

    _buildGrid: function() {
        var customStore = Ext.create('Rally.data.custom.Store', {
            data: this._customRecords,
            pageSize: this._customRecords.length
        });

        if (!this.grid) {
            this.grid = this.down('#grid').add({
                xtype: 'rallygrid',
                store: customStore,
                showPagingToolbar: false,
                columnCfgs: [
                    {text: 'Formatted ID', dataIndex: 'FormattedID', flex: 1, xtype: 'templatecolumn',
                        tpl: Ext.create('Rally.ui.renderer.template.FormattedIDTemplate')},
                    {text: 'Name', dataIndex: 'Name', flex: 2},
                    {text: 'Date Closed', dataIndex: 'DateClosed', flex: 2},
                    {text: 'Revision Number', dataIndex: 'RevisionNumber', flex: 1},
                    {text: 'Closed By', dataIndex: 'ClosedBy', flex: 1}
                ]
            });
        } else {
            this.grid.reconfigure(customStore);
        }
    },

    getOptions: function() {
        return [
            {
                text: 'Print',
                handler: this._onButtonPressed,
                scope: this
            }
        ];
    },

    _onButtonPressed: function() {
        var title = this.down('#releaseComboBox').getRawValue(),
            options = "toolbar=1,menubar=1,scrollbars=yes,scrolling=yes,resizable=yes,width=1000,height=500";

        // code to get the style that we added in the app.css file
        var css = document.getElementsByTagName('style')[0].innerHTML;

        var printWindow = window.open('', '', options);

        var doc = printWindow.document;

        var grid = this.down('#grid');

        doc.write('' + '<title>' + title + '</title>');

        doc.write('');
        doc.write('
Release: ' + title + '

');
        doc.write(grid.getEl().dom.innerHTML);
        doc.write('');
        doc.close();

        this._injectCSS(printWindow);

        printWindow.print();

    },

    _injectContent: function(html, elementType, attributes, container, printWindow){
        elementType = elementType || 'div';
        container = container || printWindow.document.getElementsByTagName('body')[0];

        var element = printWindow.document.createElement(elementType);

        Ext.Object.each(attributes, function(key, value){
            if (key === 'class') {
                element.className = value;
            } else {
                element.setAttribute(key, value);
            }
        });

        if(html){
            element.innerHTML = html;
        }

        return container.appendChild(element);
    },

    _injectCSS: function(printWindow){
        //find all the stylesheets on the current page and inject them into the new page
        Ext.each(Ext.query('link'), function(stylesheet){
                this._injectContent('', 'link', {
                rel: 'stylesheet',
                href: stylesheet.href,
                type: 'text/css'
            }, printWindow.document.getElementsByTagName('head')[0], printWindow);
        }, this);

    }
});<|endoftext|>