<commit_before>/**
 * Dependency of CSS editing plugins like CSS Snippets or CSS Controls
 * @author Lea Verou
 * MIT License
 */

(function(){

var dummy = document.createElement('div');

var self = window.CSSEdit = {
	isCSSValid: function(code) {
		var declarationCount = code.split(':').length - 1;

		dummy.removeAttribute('style');
		dummy.setAttribute('style', code);

		return declarationCount > 0 && dummy.style.length >= declarationCount;
	},

	setupSubjects: function(subjects) {
		for (var i=0; i<subjects.length; i++) {
			var subject = subjects[i];

			subject.setAttribute('data-originalstyle', subject.getAttribute('style') || '');
			subject.setAttribute('data-originalcssText', subject.style.cssText || '');
		}
	},

	getSubjects: function(element) {
		var selector = element.getAttribute('data-subject'),
			subjects;

		if(selector) {
			subjects = self.util.toArray(document.querySelectorAll(selector)) || [];
		}
		else {
			subjects = element.hasAttribute('data-subject')? [element] : [];
		}

		if(/^(input|textarea)$/i.test(element.nodeName)) {
			// If no subject specified, it will be the slide
			if(!subjects.length) {
				// Find containing slide
				var slide = SlideShow.getSlide(element.parentNode);

				subjects = [slide? slide : element];
			}
		}
		else {
			subjects.unshift(element);
		}

		return subjects;
	},

	updateStyle: function(subjects, code, originalAttribute) {
		code = code? StyleFix.fix(code.trim()) : '';

		if(!code || self.isCSSValid(code)) {
			dummy.setAttribute('style', code);

			var appliedCode = dummy.style.cssText,
			    properties = appliedCode.match(/\b[a-z-]+(?=:)/gi),
			    propRegex = [];

			if(code) {
				for(var i=0; i<properties.length; i++) {
					properties[i] = self.util.camelCase(properties[i]);
				}
			}

			for (var i=0; i<subjects.length; i++) {
				var element = subjects[i],
					prevStyle = element.getAttribute('style');

				if(prevStyle && prevStyle !== 'null') {
					if(code) {
						for(var j=0; j<properties.length; j++) {
							element.style[properties[i]] = null;
						}
					}

					element.setAttribute('style', (element.getAttribute(originalAttribute) || '') + '; ' + code);
				}
				else {
					element.setAttribute('style', code);
				}
			}

			return true;
		}
		else {
			return false;
		}
	},

	elastic: function(textarea) {
		if(!/^textarea$/i.test(textarea.nodeName)
			|| !('rows' in textarea)
			|| textarea.classList.contains('dont-resize')) {
			return;
		}

		self.util.adjustHeight(textarea);

		textarea.addEventListener('keyup', function(evt) {
			if(evt.keyCode == 13) {
				self.util.adjustHeight(this);
			}
		}, false);

		textarea.addEventListener('input', function(evt) {
			self.util.adjustHeight(this);
		}, false);
	},

	util: {
		camelCase: function(str) {
			return str.replace(/-(.)/g, function($0, $1) { return $1.toUpperCase() })
		},

		toArray: function(collection) {
			return Array.prototype.slice.apply(collection);
		},

		adjustHeight: function(textarea) {
			textarea.rows = textarea.value.split(/\r\n?|\n/).length;

			textarea.style.fontSize = Math.min(100, Math.max(100 - textarea.rows * 5, 65)) + '%';
		}
	}
 };

 })()<commit_msg>Added scoped attribute for snippets, to scope them to current slide<commit_after>/**
 * Dependency of CSS editing plugins like CSS Snippets or CSS Controls
 * @author Lea Verou
 * MIT License
 */

(function(){

var dummy = document.createElement('div');

var self = window.CSSEdit = {
	isCSSValid: function(code) {
		var declarationCount = code.split(':').length - 1;

		dummy.removeAttribute('style');
		dummy.setAttribute('style', code);

		return declarationCount > 0 && dummy.style.length >= declarationCount;
	},

	setupSubjects: function(subjects) {
		for (var i=0; i<subjects.length; i++) {
			var subject = subjects[i];

			subject.setAttribute('data-originalstyle', subject.getAttribute('style') || '');
			subject.setAttribute('data-originalcssText', subject.style.cssText || '');
		}
	},

	getSubjects: function(element) {
		var selector = element.getAttribute('data-subject'),
			subjects,
			scoped = element.hasAttribute('data-scoped');

		if (scoped) {
			var slideId = SlideShow.getSlide(element.parentNode).id;
			selector = '#' + slideId + ' ' + selector;
		}

		if (selector) {
			subjects = self.util.toArray(document.querySelectorAll(selector)) || [];
		}
		else {
			subjects = element.hasAttribute('data-subject')? [element] : [];
		}

		if (/^(input|textarea)$/i.test(element.nodeName)) {
			// If no subject specified, it will be the slide
			if(!subjects.length) {
				// Find containing slide
				var slide = SlideShow.getSlide(element.parentNode);

				subjects = [slide? slide : element];
			}
		}
		else {
			subjects.unshift(element);
		}

		return subjects;
	},

	updateStyle: function(subjects, code, originalAttribute) {
		code = code? StyleFix.fix(code.trim()) : '';

		if(!code || self.isCSSValid(code)) {
			dummy.setAttribute('style', code);

			var appliedCode = dummy.style.cssText,
			    properties = appliedCode.match(/\b[a-z-]+(?=:)/gi),
			    propRegex = [];

			if(code) {
				for(var i=0; i<properties.length; i++) {
					properties[i] = self.util.camelCase(properties[i]);
				}
			}

			for (var i=0; i<subjects.length; i++) {
				var element = subjects[i],
					prevStyle = element.getAttribute('style');

				if(prevStyle && prevStyle !== 'null') {
					if(code) {
						for(var j=0; j<properties.length; j++) {
							element.style[properties[i]] = null;
						}
					}

					element.setAttribute('style', (element.getAttribute(originalAttribute) || '') + '; ' + code);
				}
				else {
					element.setAttribute('style', code);
				}
			}

			return true;
		}
		else {
			return false;
		}
	},

	elastic: function(textarea) {
		if(!/^textarea$/i.test(textarea.nodeName)
			|| !('rows' in textarea)
			|| textarea.classList.contains('dont-resize')) {
			return;
		}

		self.util.adjustHeight(textarea);

		textarea.addEventListener('keyup', function(evt) {
			if(evt.keyCode == 13) {
				self.util.adjustHeight(this);
			}
		}, false);

		textarea.addEventListener('input', function(evt) {
			self.util.adjustHeight(this);
		}, false);
	},

	util: {
		camelCase: function(str) {
			return str.replace(/-(.)/g, function($0, $1) { return $1.toUpperCase() })
		},

		toArray: function(collection) {
			return Array.prototype.slice.apply(collection);
		},

		adjustHeight: function(textarea) {
			textarea.rows = textarea.value.split(/\r\n?|\n/).length;

			textarea.style.fontSize = Math.min(100, Math.max(100 - textarea.rows * 5, 65)) + '%';
		}
	}
 };

 })()<|endoftext|>


<commit_before>'use strict';
const Hoek = require('hoek');
const Mongoose = require('mongoose');

const defaults = {
	host: '127.0.0.1',
	port: 27017,
	db: 'Hapilizer',
	username: '',
	password: ''
};

exports.register = function (server, options, next) {
	let settings = Hoek.applyToDefaults(defaults, options);

	Mongoose.connection.on('error', (error) => {
		next(error);
	});

	Mongoose.connection.once('open', () => {
		next();
	});

	Mongoose.connection.once('disconnected', () => {
		Mongoose.connection.removeAllListeners('error');
	});

	let credentials = '';
	if (settings.username !== '' && settings.password !== '') {
		credentials = settings.username + ':' + settings.password + '@';
	}

	Mongoose.connect('mongodb://' + credentials + settings.host + ':' + settings.port + '/' + settings.db);
};

exports.register.attributes = {
	name: 'Mongoose'
};<commit_msg>mongoose connector cleanup<commit_after>'use strict';
const Hoek = require('hoek');
const Mongoose = require('mongoose');

const defaults = {
	host: '127.0.0.1',
	port: 27017,
	db: 'Hapilizer',
	username: '',
	password: ''
};

exports.register = function (server, options, next) {
	const connection = Mongoose.connection;
	const settings = Hoek.applyToDefaults(defaults, options);

	// setup handlers
	connection.once('open', () => next());
	connection.once('error', (error) => next(error));
	connection.once('disconnected', () => connection.removeAllListeners('error'));

	// generate credentials
	let credentials = '';
	if (settings.username !== '' && settings.password !== '') {
		credentials = settings.username + ':' + settings.password + '@';
	}
	let connectionURI = 'mongodb://' + credentials + settings.host + ':' + settings.port + '/' + settings.db;

	// connect to database
	Mongoose.connect(connectionURI);
};

exports.register.attributes = {
	name: 'Mongoose'
};<|endoftext|>


<commit_before>'use strict';
/**
 * Summoner plugin
 *
 * Watches for @mentions and replies with a canned response
 *
 * @module summoner
 * @author Accalia
 * @license MIT
 */

const internals = {
    browser: null,
    configuration: exports.defaultConfig,
    timeouts: {},
    interval: null,
    events: null
};
exports.internals = internals;

/**
 * Default plugin configuration
 */
exports.defaultConfig = {
    /**
     * Required delay before posting another reply in the same topic.
     *
     * @default
     * @type {Number}
     */
    cooldown: 60 * 1000,
    /**
     * Messages to select reply from.
     *
     * @default
     * @type {string[]}
     */
    messages: [
        '@%username% has summoned me, and so I appear.',
        'Yes master %name%, I shall appear as summoned.',
        'Yes mistress %name%, I shall appear as summoned.'
    ],
    /**
     * Extended help message
     */
    extendedHelp: 'Respond to @mentions with a randomly selected preconfigured phrase'
};

/**
 * Respond to @mentions
 *
 * @param {external.notifications.Notification} _ Notification recieved (ignored)
 * @param {external.topics.Topic} topic Topic trigger post belongs to
 * @param {external.posts.CleanedPost} post Post that triggered notification
 */
exports.mentionHandler = function mentionHandler(_, topic, post) {
    const now = Date.now();
    if (internals.timeouts[topic.id] && internals.timeouts[topic.id] > now) {
        return;
    }
    const index = Math.floor(Math.random() * internals.configuration.messages.length),
        reply = internals.configuration.messages[index].replace(/%(\w+)%/g, (__, key) => {
            let value = post[key] || '%' + key + '%';
            if (typeof value !== 'string') {
                value = JSON.stringify(value);
            }
            return value;
        }).replace(/(^|\W)@(\w+)\b/g, '$1@$2');
    internals.timeouts[topic.id] = now + internals.configuration.cooldown;
    internals.browser.createPost(topic.id, post.post_number, reply, () => 0);
};

/**
 * Prepare Plugin prior to login
 *
 * @param {*} plugConfig Plugin specific configuration
 * @param {Config} config Overall Bot Configuration
 * @param {externals.events.SockEvents} events EventEmitter used for the bot
 * @param {Browser} browser Web browser for communicating with discourse
 */
exports.prepare = function prepare(plugConfig, config, events, browser) {
    if (Array.isArray(plugConfig)) {
        plugConfig = {
            messages: plugConfig
        };
    }
    if (plugConfig === null || typeof plugConfig !== 'object') {
        plugConfig = {};
    }
    internals.events = events;
    internals.browser = browser;
    internals.configuration = config.mergeObjects(true, exports.defaultConfig, plugConfig);
    events.onNotification('mentioned', exports.mentionHandler);
    events.registerHelp('summoner', internals.extendedHelp, () => 0);
};

/**
 * Start the plugin after login
 */
exports.start = function start() {};

/**
 * Stop the plugin prior to exit or reload
 */
exports.stop = function stop() {};
<commit_msg>add docs link<commit_after>'use strict';
/**
 * Summoner plugin
 *
 * Watches for @mentions and replies with a canned response
 *
 * @module summoner
 * @author Accalia
 * @license MIT
 */

const internals = {
    browser: null,
    configuration: exports.defaultConfig,
    timeouts: {},
    interval: null,
    events: null
};
exports.internals = internals;

/**
 * Default plugin configuration
 */
exports.defaultConfig = {
    /**
     * Required delay before posting another reply in the same topic.
     *
     * @default
     * @type {Number}
     */
    cooldown: 60 * 1000,
    /**
     * Messages to select reply from.
     *
     * @default
     * @type {string[]}
     */
    messages: [
        '@%username% has summoned me, and so I appear.',
        'Yes master %name%, I shall appear as summoned.',
        'Yes mistress %name%, I shall appear as summoned.'
    ],
    /**
     * Extended help message
     */
    extendedHelp: 'Respond to @mentions with a randomly selected preconfigured phrase.\n\nFor more information see ' +
        'the [full docs](https://sockbot.readthedocs.org/en/latest/Plugins/summoner/)'
};

/**
 * Respond to @mentions
 *
 * @param {external.notifications.Notification} _ Notification recieved (ignored)
 * @param {external.topics.Topic} topic Topic trigger post belongs to
 * @param {external.posts.CleanedPost} post Post that triggered notification
 */
exports.mentionHandler = function mentionHandler(_, topic, post) {
    const now = Date.now();
    if (internals.timeouts[topic.id] && internals.timeouts[topic.id] > now) {
        return;
    }
    const index = Math.floor(Math.random() * internals.configuration.messages.length),
        reply = internals.configuration.messages[index].replace(/%(\w+)%/g, (__, key) => {
            let value = post[key] || '%' + key + '%';
            if (typeof value !== 'string') {
                value = JSON.stringify(value);
            }
            return value;
        }).replace(/(^|\W)@(\w+)\b/g, '$1@$2');
    internals.timeouts[topic.id] = now + internals.configuration.cooldown;
    internals.browser.createPost(topic.id, post.post_number, reply, () => 0);
};

/**
 * Prepare Plugin prior to login
 *
 * @param {*} plugConfig Plugin specific configuration
 * @param {Config} config Overall Bot Configuration
 * @param {externals.events.SockEvents} events EventEmitter used for the bot
 * @param {Browser} browser Web browser for communicating with discourse
 */
exports.prepare = function prepare(plugConfig, config, events, browser) {
    if (Array.isArray(plugConfig)) {
        plugConfig = {
            messages: plugConfig
        };
    }
    if (plugConfig === null || typeof plugConfig !== 'object') {
        plugConfig = {};
    }
    internals.events = events;
    internals.browser = browser;
    internals.configuration = config.mergeObjects(true, exports.defaultConfig, plugConfig);
    events.onNotification('mentioned', exports.mentionHandler);
    events.registerHelp('summoner', internals.extendedHelp, () => 0);
};

/**
 * Start the plugin after login
 */
exports.start = function start() {};

/**
 * Stop the plugin prior to exit or reload
 */
exports.stop = function stop() {};
<|endoftext|>


<commit_before>var jsdiff = require("diff");

function TopicLogPlugin(bot) {
	var self = this;
	self.name = "topiclog";
	self.help = "Topic logger plugin";
	self.depend = ["cmd"];

	self.topiclog = {};

	self.load = function(data) {
		if (data) {
			self.topiclog = data;
			for (var channel in self.topiclog) {
				var chanlog = self.topiclog[channel];
				for (var i = 0; i < chanlog.length; i++)
					chanlog[i].time = new Date(chanlog[i].time);
			}
		}
	};

	self.save = function() {
		return self.topiclog;
	};

	self.events = {
		"topic": function(channel, topic, nick, message) {
			var chanlog = self.topiclog[channel];
			if (chanlog === undefined || chanlog[chanlog.length - 1].topic != topic) {
				var entry = {};
				if (message.command == "333") {
					var match = message.args[2].match(/^([_a-zA-Z0-9\[\]\\`^{}|-]*)(!([^@]+)@(.*))?$/);
					entry = {
						"nick": match[1],
						"user": match[3],
						"host": match[4],
						"topic": topic,
						"time": new Date(parseInt(message.args[3]) * 1000)
					};
				}
				else
				{
					entry = {
						"nick": nick,
						"user": message.user,
						"host": message.host,
						"topic": topic,
						"time": new Date()
					};
				}

				if (chanlog === undefined)
					self.topiclog[channel] = [entry];
				else
					self.topiclog[channel].push(entry);
			}
		},

		"join": function(channel, nick) {
			if (nick == bot.nick)
				bot.send("TOPIC", channel);
		},

		"cmd#topicdiff": function(nick, to, args) {
			var chanlog = self.topiclog[to];
			if (chanlog.length >= 2)
			{
				var diff = jsdiff.diffWords(chanlog[chanlog.length - 2].topic, chanlog[chanlog.length - 1].topic);

				var str = "";
				diff.forEach(function(part) {
					if (part.added)
						str += "\x033{+" + part.value + "+}";
					else if (part.removed)
						str += "\x034[-" + part.value + "-]";
					else
						str += "\x0f" + part.value;
				});

				bot.say(to, "Topic diff: " + str);
			}
			else
				bot.say(to, "Cannot find topic diff with less than 2 known topics");
		}
	}
}

module.exports = TopicLogPlugin;
<commit_msg>Ability to list previous channel topics from log<commit_after>var jsdiff = require("diff");

function TopicLogPlugin(bot) {
	var self = this;
	self.name = "topiclog";
	self.help = "Topic logger plugin";
	self.depend = ["cmd"];

	self.topiclog = {};

	self.load = function(data) {
		if (data) {
			self.topiclog = data;
			for (var channel in self.topiclog) {
				var chanlog = self.topiclog[channel];
				for (var i = 0; i < chanlog.length; i++)
					chanlog[i].time = new Date(chanlog[i].time);
			}
		}
	};

	self.save = function() {
		return self.topiclog;
	};

	self.events = {
		"topic": function(channel, topic, nick, message) {
			var chanlog = self.topiclog[channel];
			if (chanlog === undefined || chanlog[chanlog.length - 1].topic != topic) {
				var entry = {};
				if (message.command == "333") {
					var match = message.args[2].match(/^([_a-zA-Z0-9\[\]\\`^{}|-]*)(!([^@]+)@(.*))?$/);
					entry = {
						"nick": match[1],
						"user": match[3],
						"host": match[4],
						"topic": topic,
						"time": new Date(parseInt(message.args[3]) * 1000)
					};
				}
				else
				{
					entry = {
						"nick": nick,
						"user": message.user,
						"host": message.host,
						"topic": topic,
						"time": new Date()
					};
				}

				if (chanlog === undefined)
					self.topiclog[channel] = [entry];
				else
					self.topiclog[channel].push(entry);
			}
		},

		"join": function(channel, nick) {
			if (nick == bot.nick)
				bot.send("TOPIC", channel);
		},

		"cmd#topics": function(nick, to, args) {
			var chanlog = self.topiclog[to];

			for (var i = -3; i < 0; i++) {
				var entry = chanlog[chanlog.length + i];
				if (entry)
				{
					bot.notice(nick, "Topic in " + to + " by " + entry.nick + " at " + entry.time.toUTCString() + ": " + entry.topic);
				}
			}
		},

		"cmd#topicdiff": function(nick, to, args) {
			var chanlog = self.topiclog[to];
			if (chanlog.length >= 2)
			{
				var diff = jsdiff.diffWords(chanlog[chanlog.length - 2].topic, chanlog[chanlog.length - 1].topic);

				var str = "";
				diff.forEach(function(part) {
					if (part.added)
						str += "\x033{+" + part.value + "+}";
					else if (part.removed)
						str += "\x034[-" + part.value + "-]";
					else
						str += "\x0f" + part.value;
				});

				bot.say(to, "Topic diff: " + str);
			}
			else
				bot.say(to, "Cannot find topic diff with less than 2 known topics");
		}
	}
}

module.exports = TopicLogPlugin;
<|endoftext|>


<commit_before>/*global describe it beforeEach afterEach*/
"use strict";
"use server";
"use mocha";

require("c9/inline-mocha")(module);
if (typeof define === "undefined") {
    require("amd-loader");
    require("../../test/setup_paths");
}

var assert = require("assert-diff");
var urls = require("./urls");
var url = require("url");
var sinon = require("sinon");

describe("urls", function() {

    this.timeout(15000);

    it("can do basic domain substitution in settings", function() {
        var settings = {
            domains: ["c9.io"],
            preview: {
                baseUrl: "https://preview.$DOMAIN"
            },
            ide: {
                baseUrlPattern: "https://ide.$DOMAIN"
            }
        };
        urls.replaceDomains(settings, "cloud9beta.com");
        assert.equal(settings.primaryDomain, "cloud9beta.com");
        assert.equal(settings.preview.baseUrl, "https://preview.cloud9beta.com");
        assert.equal(settings.ide.baseUrlPattern, "https://ide.$DOMAIN");
    });

    it("can do basic domain substitution in settings a list of domains", function() {
        var settings = {
            domains: ["c9.io"],
            preview: {
                baseUrl: "https://preview.$DOMAIN"
            },
            ide: {
                baseUrlPattern: "https://ide.$DOMAIN"
            }
        };
        urls.replaceDomains(settings, "cloud9beta.com,cs50.me");
        assert.equal(settings.primaryDomain, "cloud9beta.com");
        assert.deepEqual(settings.domains, ["cloud9beta.com", "cs50.me"]);
        assert.equal(settings.preview.baseUrl, "https://preview.cloud9beta.com");
        assert.equal(settings.ide.baseUrlPattern, "https://ide.$DOMAIN");
    });

    it("behaves like an architect plugin", function(next) {
        urls({}, { "error.logger": urls.mockErrorLogger }, function(err, result) {
            assert(!err, err);
            assert(result.urls.getBaseUrl);
            next();
        });
    });

    it("can get the base url for a request", function() {
        var mockRequest = {
            host: "preview.c9.io"
        };
        var baseUrl = urls.getBaseUrl(mockRequest, "https://preview.$DOMAIN", "https://ide.$DOMAIN");
        assert.equal(baseUrl, "https://ide.c9.io");
    });

    it("can get the base url for a request with root domain source", function() {
        var mockRequest = {
            host: "c9.io"
        };
        var baseUrl = urls.getBaseUrl(mockRequest, "https://$DOMAIN", "https://ide.$DOMAIN");
        assert.equal(baseUrl, "https://ide.c9.io");
    });

    it("can get the base url for a request with root domain target", function() {
        var mockRequest = {
            host: "preview.cloud9beta.com"
        };
        var baseUrl = urls.getBaseUrl(mockRequest, "https://preview.$DOMAIN", "https://$DOMAIN");
        assert.equal(baseUrl, "https://cloud9beta.com");
    });

    it("gracefully copes with source domain mismatch", function() {
        var mockRequest = {
            host: "preview.cloud9beta.com"
        };
        urls.mockErrorLogger.log = sinon.spy();
        var baseUrl = urls.getBaseUrl(mockRequest, "https://ide.$DOMAIN", "https://$DOMAIN");
        assert.equal(baseUrl, "https://c9.io");
        assert(urls.mockErrorLogger.log.called);
    });

    it("can get the base url in dogfooding mode", function() {
        var mockRequest = {
            host: "newclient-lennartcl.c9.io"
        };
        var baseUrl = urls.getBaseUrl(mockRequest, "https://$DOMAIN", "https://ide.$DOMAIN");
        assert.equal(baseUrl, "https://ide.newclient-lennartcl.c9.io");
    });

    it("can get the base url in dogfooding mode (2)", function() {
        var mockRequest = {
            host: "preview.newclient-lennartcl.c9.io"
        };
        var baseUrl = urls.getBaseUrl(mockRequest, "https://preview.$DOMAIN", "https://ide.$DOMAIN");
        assert.equal(baseUrl, "https://ide.newclient-lennartcl.c9.io");
    });

    it("even works with URL objects", function() {
        var input = url.parse("https://preview.newclient-lennartcl.c9.io");
        var baseUrl = urls.getBaseUrl(input, "https://preview.$DOMAIN", "https://ide.$DOMAIN");
        assert.equal(baseUrl, "https://ide.newclient-lennartcl.c9.io");
    });

    it("even works with strings", function() {
        var input = "https://preview.newclient-lennartcl.c9.io";
        var baseUrl = urls.getBaseUrl(input, "https://preview.$DOMAIN", "https://ide.$DOMAIN");
        assert.equal(baseUrl, "https://ide.newclient-lennartcl.c9.io");
    });

    it("targetBaseUrlPattern is optional", function() {
        var input = "https://preview.newclient-lennartcl.c9.io";
        var baseUrl = urls.getBaseUrl(input, "https://preview.$DOMAIN");
        assert.equal(baseUrl, "https://preview.newclient-lennartcl.c9.io");
    });

    it("should split domains", function() {
        var domains = ["c9.io", "c9users.io", "cs50.io"];
        assert.deepEqual(urls.splitDomain("fjakobs-ace.c9.io", domains), {
            domainName: "c9.io",
            subDomains: "fjakobs-ace",
            port: ""
        });
        assert.deepEqual(urls.splitDomain("preview.c9users.io", domains), {
            domainName: "c9users.io",
            subDomains: "preview",
            port: ""
        });
        assert.deepEqual(urls.splitDomain("fjakobs.ace.cs50.io", domains), {
            domainName: "cs50.io",
            subDomains: "fjakobs.ace",
            port: ""
        });
        assert.deepEqual(urls.splitDomain("fjakobs.ace.cs50.io:8081", domains), {
            domainName: "cs50.io",
            subDomains: "fjakobs.ace",
            port: "8081"
        });
    });
});<commit_msg>reorder files<commit_after>/*global describe it beforeEach afterEach*/
"use strict";
"use server";
"use mocha";

require("c9/inline-mocha")(module);
if (typeof define === "undefined") {
    require("amd-loader");
    require("./setup_paths");
}

var assert = require("assert-diff");
var urls = require("./urls");
var url = require("url");
var sinon = require("sinon");

describe("urls", function() {

    this.timeout(15000);

    it("can do basic domain substitution in settings", function() {
        var settings = {
            domains: ["c9.io"],
            preview: {
                baseUrl: "https://preview.$DOMAIN"
            },
            ide: {
                baseUrlPattern: "https://ide.$DOMAIN"
            }
        };
        urls.replaceDomains(settings, "cloud9beta.com");
        assert.equal(settings.primaryDomain, "cloud9beta.com");
        assert.equal(settings.preview.baseUrl, "https://preview.cloud9beta.com");
        assert.equal(settings.ide.baseUrlPattern, "https://ide.$DOMAIN");
    });

    it("can do basic domain substitution in settings a list of domains", function() {
        var settings = {
            domains: ["c9.io"],
            preview: {
                baseUrl: "https://preview.$DOMAIN"
            },
            ide: {
                baseUrlPattern: "https://ide.$DOMAIN"
            }
        };
        urls.replaceDomains(settings, "cloud9beta.com,cs50.me");
        assert.equal(settings.primaryDomain, "cloud9beta.com");
        assert.deepEqual(settings.domains, ["cloud9beta.com", "cs50.me"]);
        assert.equal(settings.preview.baseUrl, "https://preview.cloud9beta.com");
        assert.equal(settings.ide.baseUrlPattern, "https://ide.$DOMAIN");
    });

    it("behaves like an architect plugin", function(next) {
        urls({}, { "error.logger": urls.mockErrorLogger }, function(err, result) {
            assert(!err, err);
            assert(result.urls.getBaseUrl);
            next();
        });
    });

    it("can get the base url for a request", function() {
        var mockRequest = {
            host: "preview.c9.io"
        };
        var baseUrl = urls.getBaseUrl(mockRequest, "https://preview.$DOMAIN", "https://ide.$DOMAIN");
        assert.equal(baseUrl, "https://ide.c9.io");
    });

    it("can get the base url for a request with root domain source", function() {
        var mockRequest = {
            host: "c9.io"
        };
        var baseUrl = urls.getBaseUrl(mockRequest, "https://$DOMAIN", "https://ide.$DOMAIN");
        assert.equal(baseUrl, "https://ide.c9.io");
    });

    it("can get the base url for a request with root domain target", function() {
        var mockRequest = {
            host: "preview.cloud9beta.com"
        };
        var baseUrl = urls.getBaseUrl(mockRequest, "https://preview.$DOMAIN", "https://$DOMAIN");
        assert.equal(baseUrl, "https://cloud9beta.com");
    });

    it("gracefully copes with source domain mismatch", function() {
        var mockRequest = {
            host: "preview.cloud9beta.com"
        };
        urls.mockErrorLogger.log = sinon.spy();
        var baseUrl = urls.getBaseUrl(mockRequest, "https://ide.$DOMAIN", "https://$DOMAIN");
        assert.equal(baseUrl, "https://c9.io");
        assert(urls.mockErrorLogger.log.called);
    });

    it("can get the base url in dogfooding mode", function() {
        var mockRequest = {
            host: "newclient-lennartcl.c9.io"
        };
        var baseUrl = urls.getBaseUrl(mockRequest, "https://$DOMAIN", "https://ide.$DOMAIN");
        assert.equal(baseUrl, "https://ide.newclient-lennartcl.c9.io");
    });

    it("can get the base url in dogfooding mode (2)", function() {
        var mockRequest = {
            host: "preview.newclient-lennartcl.c9.io"
        };
        var baseUrl = urls.getBaseUrl(mockRequest, "https://preview.$DOMAIN", "https://ide.$DOMAIN");
        assert.equal(baseUrl, "https://ide.newclient-lennartcl.c9.io");
    });

    it("even works with URL objects", function() {
        var input = url.parse("https://preview.newclient-lennartcl.c9.io");
        var baseUrl = urls.getBaseUrl(input, "https://preview.$DOMAIN", "https://ide.$DOMAIN");
        assert.equal(baseUrl, "https://ide.newclient-lennartcl.c9.io");
    });

    it("even works with strings", function() {
        var input = "https://preview.newclient-lennartcl.c9.io";
        var baseUrl = urls.getBaseUrl(input, "https://preview.$DOMAIN", "https://ide.$DOMAIN");
        assert.equal(baseUrl, "https://ide.newclient-lennartcl.c9.io");
    });

    it("targetBaseUrlPattern is optional", function() {
        var input = "https://preview.newclient-lennartcl.c9.io";
        var baseUrl = urls.getBaseUrl(input, "https://preview.$DOMAIN");
        assert.equal(baseUrl, "https://preview.newclient-lennartcl.c9.io");
    });

    it("should split domains", function() {
        var domains = ["c9.io", "c9users.io", "cs50.io"];
        assert.deepEqual(urls.splitDomain("fjakobs-ace.c9.io", domains), {
            domainName: "c9.io",
            subDomains: "fjakobs-ace",
            port: ""
        });
        assert.deepEqual(urls.splitDomain("preview.c9users.io", domains), {
            domainName: "c9users.io",
            subDomains: "preview",
            port: ""
        });
        assert.deepEqual(urls.splitDomain("fjakobs.ace.cs50.io", domains), {
            domainName: "cs50.io",
            subDomains: "fjakobs.ace",
            port: ""
        });
        assert.deepEqual(urls.splitDomain("fjakobs.ace.cs50.io:8081", domains), {
            domainName: "cs50.io",
            subDomains: "fjakobs.ace",
            port: "8081"
        });
    });
});<|endoftext|>


<commit_before>const
   URL      = require( 'url'     ),
   FS       = require( 'fs'      ),
   MIME     = require( '../mime' ),

   PUBLIC   = process.env.npm_package_config_public,
   INDEX    = process.env.npm_package_config_index,

   OK       = 200,
   NOTFOUND = 404,

   SUCC     = 'File %s (length: %d B)" successfully served.',
   FAIL     = 'File %s not found, status %d served.';

module.exports = function( req, res ) {
   let
      page = URL.parse( req.url ).pathname,
      file = ( page === '/' ) ? INDEX : page,
      path = PUBLIC + file;

   FS.access( path, FS.constants.R_OK, ( error ) => {
      if ( !error ) {
         FS.stat( path, ( error, stats ) => {
            if ( !error ) {
               stream = FS.createReadStream( path ),
               type   = MIME.lookup( path );
               res.writeHead( OK, {
                  'Content-Length': stats.size,
                  'Content-Type':   type
               });
               stream.pipe( res );
               console.log( SUCC, file, stats.size );
            } else {
               res.statusCode = NOTFOUND;
               res.end();
               console.log( FAIL, file, NOTFOUND );
            };
         });
      } else {
         res.statusCode = NOTFOUND;
         res.end();
         console.log( FAIL, file, NOTFOUND );
      };
   });
};
<commit_msg>Update index.js<commit_after>const
   URL      = require( 'url'     ),
   FS       = require( 'fs'      ),
   MIME     = require( '../mime' ),

   PUBLIC   = process.env.npm_package_config_public,
   INDEX    = '/' + process.env.npm_package_config_index,

   OK       = 200,
   NOTFOUND = 404,

   SUCC     = 'File %s (length: %d B)" successfully served.',
   FAIL     = 'File %s not found, status %d served.';

module.exports = function( req, res ) {
   let
      page = URL.parse( req.url ).pathname,
      file = ( page === '/' ) ? INDEX : page,
      path = PUBLIC + file;

   FS.access( path, FS.constants.R_OK, ( error ) => {
      if ( !error ) {
         FS.stat( path, ( error, stats ) => {
            if ( !error ) {
               stream = FS.createReadStream( path ),
               type   = MIME.lookup( path );
               res.writeHead( OK, {
                  'Content-Length': stats.size,
                  'Content-Type':   type
               });
               stream.pipe( res );
               console.log( SUCC, file, stats.size );
            } else {
               res.statusCode = NOTFOUND;
               res.end();
               console.log( FAIL, file, NOTFOUND );
            };
         });
      } else {
         res.statusCode = NOTFOUND;
         res.end();
         console.log( FAIL, file, NOTFOUND );
      };
   });
};
<|endoftext|>


<commit_before>Symbol.EmitTypeWarnings = false;

Symbol.prototype.initMetaData = function(){
    this._meta = {
        parameters: [],
        returns: {}
    };
    Object.defineProperty(this, "meta", {
        get : function(){
            return this._meta;
        },
    });
};

Symbol.Undefined = new Symbol(Symbol.UNDEFINED, "undefined");

/**
 * Register symbol meta-type information for last assignation operation
 * @param newValue {object} actual value that will be assigned to the symbol
 */
Symbol.prototype.updateMetaData = function(newValue){
    Symbol._updateMetaData(this.name, this._meta, newValue, "Symbol");
};

/**
 * Helper function to register (type,count) pairs in meta-type dictionaries
 * @param symbolName {string} Name of the symbol that will be used if a warning is emmited
 * @param dictionary {object<string,number>} An object used as dictionary where the key is the typename and the value is the number of ocurrences.
 */
Symbol._updateMetaData = function(symbolName, dictionary, newValue, errorStartString){
    var type = typeof(newValue);
    if(dictionary[type] === undefined)
    {
        if(Symbol.EmitTypeWarnings && Object.keys(dictionary).length >= 1)
        {
            console.warn(errorStartString + " \"" + symbolName + "\" takes more than one type in their lifetime.");
        }
        dictionary[type] = 1;
    }
    else
    {
        dictionary[type]++;
    }
};

FunctionSymbol.prototype.initMetaData = Symbol.prototype.initMetaData;

/**
 * Register actual arguments type information in Function meta-type information
 * @param actualArguments {Array<Result>} An array with the results of evaluation of each actual argument
 * @return {void}
 */
FunctionSymbol.prototype.registerCallStart = function(actualArguments){
    var n;
    var types;
    var actualArgumentValue;

    for(n = 0; n < actualArguments.length; n++)
    {
        types = this._meta.parameters[n];
        if(types === undefined)
        {
            types = {};
            this._meta.parameters[n] = types;
        }
        actualArgumentValue = actualArguments[n].value;
        Symbol._updateMetaData(this.name, types, actualArgumentValue, "Parameter " + n + " of function");
    }
};

/**
 * Register return value type information in Function meta-type information
 * @param returnResult {Result} The Result object that last function call generated
 * @return {void}
 */
FunctionSymbol.prototype.registerCallReturn = function(returnResult){
    Symbol._updateMetaData(this.name, this._meta.returns, returnResult.value, "Return type");
};

/**
 * Merges the result returned by a meta function call with the function call context.
 * @param {Result} result Result object returned by the meta function call
 * @param {*} callExpressionAst Original Esprima call expression node.
 */
FirstPass.prototype.mergeMetaCallResult = function(result, callExpressionAst){
    // resolve to value if it's a symbol
    result.makeValue();
    var resultValue = result.value;

    if(resultValue !== null)
    {
        for (var attr in resultValue)
        {
            if (resultValue.hasOwnProperty(attr)) callExpressionAst[attr] = resultValue[attr];
        }
    }
};

FirstPass.prototype.findTemplateIds = function(ast, list, parentAst, propertyName){
    if(list === undefined) list = [];

    if(ast !== null)
    {
        if(ast.type === "Identifier" && ast.name.indexOf("$") === 0)
        {
            list.push({ id: ast, parent: parentAst, property: propertyName });
        }
        else
        {
            for(var i in ast)
            {
                if(typeof(ast[i]) === "object") this.findTemplateIds(ast[i], list, ast, i);
            }
        }
    }
    return list;
};

FirstPass.prototype.callAstConstruction = function(callExpressionAst, argumentsAst, state){
    var ast = null;
    var idsToReplace, i, id, idData, symbol;
    if(argumentsAst.length === 1)
    {
        ast = argumentsAst[0];

        // replace $id in template with symbols in context
        idsToReplace = this.findTemplateIds(ast);
        for(i in idsToReplace)
        {
            idData = idsToReplace[i];
            id = idData.id.name.substring(1);

            symbol = state.getSymbol(id);
            if(symbol.isUndefined())
            {
                console.warn(PumaScript.Loc(idData.id) + 'Template parameter not found in scope "$' + id + '".');
            }
            else
            {
                idData.parent[idData.property] = symbol.value;
            }
        }
    }
    else
    {
        return defaultResult;
    }
    return new Result(true, ast);
};

/**
 * Find AST nodes by type attribute. Type attribute must use the same names than Esprima parser.
 * Returns an array with all the nodes. An empty array if none is found.
 *
 * @param {Object} ast AST node to search on.
 * @param {string} typeName The value of "type" property of the nodes to lookup
 * @retrun {Array}
 */
function pumaFindByType(ast, typeName){
    var internalPumaFindByType = function(ast, typeName, list){
        if(ast !== null)
        {
            if(ast.type === typeName)
            {
                list.push(ast);
            }
            else
            {
                for(var i in ast)
                {
                    if(typeof(ast[i]) === "object") internalPumaFindByType(ast[i], typeName, list);
                }
            }
        }
        return list;
    };
    return internalPumaFindByType(ast, typeName, []);
}

/**
 * Find nodes inside an AST node. This method search using a chain of properties passed in "propertyChain" argument. A sample call is pumaFindByProperty("left.id.name", "foo") that will look for nodes with "left" properties which "id.name" sub-property has value "foo".
 * Returns an Array with all nodes matched with the property expression.
 *
 * @param {Object} ast AST node to search on.
 * @param {string} propertyChain A string with the chain of properties to look for. Link properties with a dot like in "id.name" will look for a property "id" with a sub property "name".
 * @param {*} value Value that will be compared with properties' value.
 * @param {Function=} compareFunction Optional comparison function. It must take two arguments "function(propertyValue, value){}" and return true when values matches. The second argument is the value passed as parameter.
 * @return {Array}
 */
function pumaFindByProperty(ast, propertyChain, value, compareFunction){
    var propertyList = propertyChain.split('.');
    var propertyLength = propertyList.length;
    var matchLength = propertyLength - 1;

    function matchProperty(ast, propertyList, value){
        var innerAst = ast;
        for(var i = 0; i < propertyLength; i++)
        {
            if(innerAst === null || innerAst === undefined) return false;
            innerAst = innerAst[propertyList[i]];
            if(i === matchLength && compareFunction === undefined && innerAst === value) return true;
            if(i === matchLength && compareFunction !== undefined && compareFunction(innerAst, value)) return true;
        }
        return false;
    }

    function internalPumaFindByProperty(ast, propertyList, value, list, compareFunction){
        if(ast !== null)
        {
            if(matchProperty(ast, propertyList, value, compareFunction))
            {
                list.push(ast);
            }
            else
            {
                for(var i in ast)
                {
                    if(typeof(ast[i]) === "object") internalPumaFindByProperty(ast[i], propertyList, value, list, compareFunction);
                }
            }
        }
        return list;
    }
    return internalPumaFindByProperty(ast, propertyList, value, [], compareFunction);
}
<commit_msg>fixed bug in "pumaAst" function<commit_after>Symbol.EmitTypeWarnings = false;

Symbol.prototype.initMetaData = function(){
    this._meta = {
        parameters: [],
        returns: {}
    };
    Object.defineProperty(this, "meta", {
        get : function(){
            return this._meta;
        },
    });
};

Symbol.Undefined = new Symbol(Symbol.UNDEFINED, "undefined");

/**
 * Register symbol meta-type information for last assignation operation
 * @param newValue {object} actual value that will be assigned to the symbol
 */
Symbol.prototype.updateMetaData = function(newValue){
    Symbol._updateMetaData(this.name, this._meta, newValue, "Symbol");
};

/**
 * Helper function to register (type,count) pairs in meta-type dictionaries
 * @param symbolName {string} Name of the symbol that will be used if a warning is emmited
 * @param dictionary {object<string,number>} An object used as dictionary where the key is the typename and the value is the number of ocurrences.
 */
Symbol._updateMetaData = function(symbolName, dictionary, newValue, errorStartString){
    var type = typeof(newValue);
    if(dictionary[type] === undefined)
    {
        if(Symbol.EmitTypeWarnings && Object.keys(dictionary).length >= 1)
        {
            console.warn(errorStartString + " \"" + symbolName + "\" takes more than one type in their lifetime.");
        }
        dictionary[type] = 1;
    }
    else
    {
        dictionary[type]++;
    }
};

FunctionSymbol.prototype.initMetaData = Symbol.prototype.initMetaData;

/**
 * Register actual arguments type information in Function meta-type information
 * @param actualArguments {Array<Result>} An array with the results of evaluation of each actual argument
 * @return {void}
 */
FunctionSymbol.prototype.registerCallStart = function(actualArguments){
    var n;
    var types;
    var actualArgumentValue;

    for(n = 0; n < actualArguments.length; n++)
    {
        types = this._meta.parameters[n];
        if(types === undefined)
        {
            types = {};
            this._meta.parameters[n] = types;
        }
        actualArgumentValue = actualArguments[n].value;
        Symbol._updateMetaData(this.name, types, actualArgumentValue, "Parameter " + n + " of function");
    }
};

/**
 * Register return value type information in Function meta-type information
 * @param returnResult {Result} The Result object that last function call generated
 * @return {void}
 */
FunctionSymbol.prototype.registerCallReturn = function(returnResult){
    Symbol._updateMetaData(this.name, this._meta.returns, returnResult.value, "Return type");
};

/**
 * Merges the result returned by a meta function call with the function call context.
 * @param {Result} result Result object returned by the meta function call
 * @param {*} callExpressionAst Original Esprima call expression node.
 */
FirstPass.prototype.mergeMetaCallResult = function(result, callExpressionAst){
    // resolve to value if it's a symbol
    result.makeValue();
    var resultValue = result.value;

    if(resultValue !== null)
    {
        for (var attr in resultValue)
        {
            if (resultValue.hasOwnProperty(attr)) callExpressionAst[attr] = resultValue[attr];
        }
    }
};

FirstPass.prototype.findTemplateIds = function(ast, list, parentAst, propertyName){
    if(list === undefined) list = [];

    if(ast !== null)
    {
        if(ast.type === "Identifier" && ast.name.indexOf("$") === 0)
        {
            list.push({ id: ast, parent: parentAst, property: propertyName });
        }
        else
        {
            for(var i in ast)
            {
                if(typeof(ast[i]) === "object") this.findTemplateIds(ast[i], list, ast, i);
            }
        }
    }
    return list;
};

FirstPass.prototype.callAstConstruction = function(callExpressionAst, argumentsAst, state){
    var ast = null;
    var idsToReplace, i, id, idData, symbol;
    if(argumentsAst.length === 1)
    {
        ast = argumentsAst[0];
        // clone the ast
        ast = jQuery.extend(true, {}, ast);

        // replace $id in template with symbols in context
        idsToReplace = this.findTemplateIds(ast);
        for(i in idsToReplace)
        {
            idData = idsToReplace[i];
            id = idData.id.name.substring(1);

            symbol = state.getSymbol(id);
            if(symbol.isUndefined())
            {
                console.warn(PumaScript.Loc(idData.id) + 'Template parameter not found in scope "$' + id + '".');
            }
            else
            {
                idData.parent[idData.property] = symbol.value;
            }
        }
    }
    else
    {
        return defaultResult;
    }
    return new Result(true, ast);
};

/**
 * Find AST nodes by type attribute. Type attribute must use the same names than Esprima parser.
 * Returns an array with all the nodes. An empty array if none is found.
 *
 * @param {Object} ast AST node to search on.
 * @param {string} typeName The value of "type" property of the nodes to lookup
 * @retrun {Array}
 */
function pumaFindByType(ast, typeName){
    var internalPumaFindByType = function(ast, typeName, list){
        if(ast !== null)
        {
            if(ast.type === typeName)
            {
                list.push(ast);
            }
            else
            {
                for(var i in ast)
                {
                    if(typeof(ast[i]) === "object") internalPumaFindByType(ast[i], typeName, list);
                }
            }
        }
        return list;
    };
    return internalPumaFindByType(ast, typeName, []);
}

/**
 * Find nodes inside an AST node. This method search using a chain of properties passed in "propertyChain" argument. A sample call is pumaFindByProperty("left.id.name", "foo") that will look for nodes with "left" properties which "id.name" sub-property has value "foo".
 * Returns an Array with all nodes matched with the property expression.
 *
 * @param {Object} ast AST node to search on.
 * @param {string} propertyChain A string with the chain of properties to look for. Link properties with a dot like in "id.name" will look for a property "id" with a sub property "name".
 * @param {*} value Value that will be compared with properties' value.
 * @param {Function=} compareFunction Optional comparison function. It must take two arguments "function(propertyValue, value){}" and return true when values matches. The second argument is the value passed as parameter.
 * @return {Array}
 */
function pumaFindByProperty(ast, propertyChain, value, compareFunction){
    var propertyList = propertyChain.split('.');
    var propertyLength = propertyList.length;
    var matchLength = propertyLength - 1;

    function matchProperty(ast, propertyList, value){
        var innerAst = ast;
        for(var i = 0; i < propertyLength; i++)
        {
            if(innerAst === null || innerAst === undefined) return false;
            innerAst = innerAst[propertyList[i]];
            if(i === matchLength && compareFunction === undefined && innerAst === value) return true;
            if(i === matchLength && compareFunction !== undefined && compareFunction(innerAst, value)) return true;
        }
        return false;
    }

    function internalPumaFindByProperty(ast, propertyList, value, list, compareFunction){
        if(ast !== null)
        {
            if(matchProperty(ast, propertyList, value, compareFunction))
            {
                list.push(ast);
            }
            else
            {
                for(var i in ast)
                {
                    if(typeof(ast[i]) === "object") internalPumaFindByProperty(ast[i], propertyList, value, list, compareFunction);
                }
            }
        }
        return list;
    }
    return internalPumaFindByProperty(ast, propertyList, value, [], compareFunction);
}
<|endoftext|>


<commit_before>const https = require('https');
const fs = require('fs');
const spawnSync = require('child_process').spawnSync;

var options = {
  hostname: 'api.github.com',
  port: 443,
  path: '/repos/GeekyAnts/native-base-docs/branches',
  method: 'GET',
  headers: {
    'User-Agent': 'Mozilla /5.0 (Compatible MSIE 9.0;Windows NT 6.1;WOW64; Trident/5.0)',
    'Accept': 'application/vnd.github.v3+json'
  }
};

var populateBookJson = (branches) => {

  spawnSync('git', ['checkout', 'master'], {stdio: 'inherit'});

  const bookJsonContents = require('./book.json');

  bookJsonContents.pluginsConfig.versions.options = [];

  for(let i=0; i<branches.length; i++) {
    if(branches[i].name === 'master') {
      bookJsonContents.pluginsConfig.versions.options.push({
          value: 'http://rawgit.com/GeekyAnts/native-base-docs/latest/_book/index.html',
          text: branches[i].name
      });
    } else {
      bookJsonContents.pluginsConfig.versions.options.push({
          value: 'http://rawgit.com/GeekyAnts/native-base-docs/' + branches[i].name + '/_book/index.html',
          text: branches[i].name
      });
    }
  }

  bookJsonContents.pluginsConfig.versions.options.push({
    value: 'http://rawgit.com/GeekyAnts/native-base-docs/master/_book/index.html',
    text: '-- select version --',
    selected: false
  });

  fs.writeFileSync(__dirname + '/book.json', JSON.stringify(bookJsonContents, null, 4), {encoding: 'utf8'});

  spawnSync('gitbook', ['build'], {stdio: 'inherit'});
  spawnSync('git', ['add', 'book.json'], {stdio: 'inherit'});
  spawnSync('git', ['add', '_book'], {stdio: 'inherit'});
  spawnSync('git', ['commit', '-m', 'rebuild book with all versions'], {stdio: 'inherit'});
  spawnSync('git', ['push', 'origin', 'master'], {stdio: 'inherit'});
}

var req = https.request(options, (res) => {

  var responseData = '';

  res.setEncoding('utf8');

  res.on('data', (chunk) => {
    responseData += chunk;
  });

  res.on('end', function () {
    try {
      console.log('responseData', responseData);
      populateBookJson(JSON.parse(responseData));
    } catch(err) {
      console.log('error: ', err);
    }
  });
});

req.on('error', (e) => {
  console.error(e);
});
req.end();
<commit_msg>changes<commit_after>'use strict';

const https = require('https');
const fs = require('fs');
const spawnSync = require('child_process').spawnSync;

var options = {
  hostname: 'api.github.com',
  port: 443,
  path: '/repos/GeekyAnts/native-base-docs/branches',
  method: 'GET',
  headers: {
    'User-Agent': 'Mozilla /5.0 (Compatible MSIE 9.0;Windows NT 6.1;WOW64; Trident/5.0)',
    'Accept': 'application/vnd.github.v3+json'
  }
};

var populateBookJson = (branches) => {

  spawnSync('git', ['checkout', 'master'], {stdio: 'inherit'});

  const bookJsonContents = require('./book.json');

  bookJsonContents.pluginsConfig.versions.options = [];

  for(let i=0; i<branches.length; i++) {
    if(branches[i].name === 'master') {
      bookJsonContents.pluginsConfig.versions.options.push({
          value: 'http://rawgit.com/GeekyAnts/native-base-docs/master/_book/index.html',
          text: 'latest'
      });
    } else {
      bookJsonContents.pluginsConfig.versions.options.push({
          value: 'http://rawgit.com/GeekyAnts/native-base-docs/' + branches[i].name + '/_book/index.html',
          text: branches[i].name
      });
    }
  }

  bookJsonContents.pluginsConfig.versions.options.push({
    value: 'http://rawgit.com/GeekyAnts/native-base-docs/master/_book/index.html',
    text: '-- select version --',
    selected: false
  });

  fs.writeFileSync(__dirname + '/book.json', JSON.stringify(bookJsonContents, null, 4), {encoding: 'utf8'});

  spawnSync('gitbook', ['build'], {stdio: 'inherit'});
  spawnSync('git', ['add', 'book.json'], {stdio: 'inherit'});
  spawnSync('git', ['add', '_book'], {stdio: 'inherit'});
  spawnSync('git', ['commit', '-m', 'rebuild book with all versions'], {stdio: 'inherit'});
  spawnSync('git', ['push', 'origin', 'master'], {stdio: 'inherit'});
}

var req = https.request(options, (res) => {

  var responseData = '';

  res.setEncoding('utf8');

  res.on('data', (chunk) => {
    responseData += chunk;
  });

  res.on('end', function () {
    try {
      console.log('responseData', responseData);
      populateBookJson(JSON.parse(responseData));
    } catch(err) {
      console.log('error: ', err);
    }
  });
});

req.on('error', (e) => {
  console.error(e);
});
req.end();
<|endoftext|>


<commit_before>const deleteButton = document.querySelector('.delete-circle');
const searchInput = document.querySelector('.search');
const tabList = document.querySelector('.tab-list');

function initializeTabs() {
  let tabs;
  return () => {
    if (typeof tabs === 'undefined') {
      tabs = browser.tabs.query({ currentWindow: true });
    }
    return tabs;
  };
}

const getAllTabs = initializeTabs();

{
  // Initialize tabs
  populateTabList();
  // Set a timeout on focus so input is focused on popup
  setTimeout(() => {
    searchInput.focus();
  }, 250);
}

// Any (non-navigating) keydown should activate the search field,
window.addEventListener('keydown', handleKeyDown);
searchInput.addEventListener('change', updateSearch);
searchInput.addEventListener('keyup', updateSearch);
deleteButton.addEventListener('click', clearInput);

function handleKeyDown(event) {
  switch (event.key) {
    case "Tab":
    case "ArrowDown":
    case "ArrowUp":
      event.preventDefault();
    case "ArrowRight":
    case "ArrowLeft":
      navigateResults(event.key);
      break;
    case "Enter":
      if (document.activeElement.nodeName === "INPUT") {
        tabList.querySelector('.tab-object').focus();
      }
      switchActiveTab(document.activeElement.dataset.id);
      break;
    case "Escape":
      // This only works in chrome, in firefox it always closes the window
      if (searchInput.value.length === 0) {
        window.close();
      } else {
        clearInput();
      }
      break;
    default:
      searchInput.focus();
      break;
  }
}

function navigateResults(direction) {
  if (document.activeElement.nodeName === 'INPUT') {
    document.querySelector('.tab-object').focus();
    return;
  }

  switch (direction) {
    case "Tab":
    case "ArrowRight":
    case "ArrowDown":
      const nextSibling = document.activeElement.nextElementSibling;
      if (nextSibling) {
        nextSibling.focus();
      } else {
        // Return to top if next !exist
        tabList.querySelector('.tab-object').focus();
      }
      break;
    case "ArrowLeft":
    case "ArrowUp":
      const prevSibling = document.activeElement.previousElementSibling;
      if (prevSibling) {
        prevSibling.focus()
      } else {
        searchInput.focus();
      };
      break;
  }
}

function updateSearch(event) {
  // If input is empty hide the button
  if (searchInput.value.length === 0) {
    deleteButton.classList.add('hidden');
  } else {
    deleteButton.classList.remove('hidden');
  }

  const query = event.target.value.toLowerCase();
  const tabFilter = (tab) => {
    // Check if tab has the query in title, url
    const queryInTitle = tab.title.toLowerCase().includes(query);
    const queryInUrl = tab.url.toLowerCase().includes(query);
    return (queryInTitle || queryInUrl);
  };
  return getAllTabs()
    .then(tabArray => tabArray.filter(tabFilter))
    .then(injectTabsInList);
}

function injectTabsInList(tabArray) {
  const noResult = `

      <object type="image/svg+xml" data="/assets/alert-circle.svg">
      </object>
      No tabs found.

  `;
  const wasNoResult = tabList.querySelectorAll('.tab-object').length === 0;
  const showNoResult = tabArray.length === 0;

  // Don't update dom if we're going to show no results again
  if (wasNoResult && showNoResult) return;

  tabList.innerHTML = showNoResult
    ? noResult
    : tabArray.map(tabToTag).join('');

  // Attach event listeners here
  if (!showNoResult) {
    const tabObjectNodes = [...tabList.querySelectorAll('.tab-object')];
    tabObjectNodes.forEach((node) => {
      node.addEventListener('click', switchTabs, true);
    });
  }
}

function tabToTag(tab) {
  const favIconLink = tab.favIconUrl && !isChromeLink(tab.favIconUrl)
    ? tab.favIconUrl
    : '/assets/file.svg';
  // Just check if it's a url for now so we can shorten it
  const title = isURL(tab.title)
    ? getBasePath(tab.title)
    : tab.title;
  return `

        ${title}

${tab.url}

  `;
}

function shortenString(str) {
  return str.length >= 120
    ? str.slice(0, 90) + '...'
    : str;
}

function isChromeLink(src) {
  return /chrome:\/\//.test(src);
}

function isURL(src) {
  return /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/.test(src);
}

function getBasePath(src) {
  const url = new URL(src);
  return url.origin;
}

function switchTabs() {
  // this: should be the tab-object node
  const tabId = this.dataset.id;
  switchActiveTab(tabId);
}

function switchActiveTab(id) {
  const numId = parseInt(id);
  browser.tabs.update(numId, { active: true });
  window.close();
}

function clearInput() {
  searchInput.value = '';
  populateTabList();
}

function populateTabList() {
  getAllTabs().then(injectTabsInList);
}

// To switch tabs
// onClick -> tabs.update(tab.id, { active: true })
<commit_msg>Create nodes manually instead of writing over innerHTML<commit_after>const deleteButton = document.querySelector('.delete-circle');
const searchInput = document.querySelector('.search');
const tabList = document.querySelector('.tab-list');

function initializeTabs() {
  const tabs = browser.tabs.query({ currentWindow: true });
  return () => {
    return tabs;
  };
}

const getAllTabs = initializeTabs();

// Initialize tabs
populateTabList();
// Set a timeout on focus so input is focused on popup
setTimeout(() => {
  searchInput.focus();
}, 250);

// Any (non-navigating) keydown should activate the search field,
window.addEventListener('keydown', handleKeyDown);
searchInput.addEventListener('change', updateSearch);
searchInput.addEventListener('keyup', updateSearch);
deleteButton.addEventListener('click', clearInput);

function handleKeyDown(event) {
  switch (event.key) {
    case "Tab":
    case "ArrowDown":
    case "ArrowUp":
      event.preventDefault();
    case "ArrowRight":
    case "ArrowLeft":
      navigateResults(event.key);
      break;
    case "Enter":
      if (document.activeElement.nodeName === "INPUT") {
        tabList.querySelector('.tab-object').focus();
      }
      switchActiveTab(document.activeElement.dataset.id);
      break;
    case "Escape":
      // This only works in chrome, in firefox it always closes the window
      if (searchInput.value.length === 0) {
        window.close();
      } else {
        clearInput();
      }
      break;
    default:
      searchInput.focus();
      break;
  }
}

function navigateResults(direction) {
  if (document.activeElement.nodeName === 'INPUT') {
    document.querySelector('.tab-object').focus();
    return;
  }

  switch (direction) {
    case "Tab":
    case "ArrowRight":
    case "ArrowDown":
      const nextSibling = document.activeElement.nextElementSibling;
      if (nextSibling) {
        nextSibling.focus();
      } else {
        // Return to top if next !exist
        tabList.querySelector('.tab-object').focus();
      }
      break;
    case "ArrowLeft":
    case "ArrowUp":
      const prevSibling = document.activeElement.previousElementSibling;
      if (prevSibling) {
        prevSibling.focus()
      } else {
        searchInput.focus();
      };
      break;
  }
}

function updateSearch(event) {
  // If input is empty hide the button
  if (searchInput.value.length === 0) {
    deleteButton.classList.add('hidden');
  } else {
    deleteButton.classList.remove('hidden');
  }

  const query = event.target.value.toLowerCase();
  const tabFilter = (tab) => {
    // Check if tab has the query in title, url
    const queryInTitle = tab.title.toLowerCase().includes(query);
    const queryInUrl = tab.url.toLowerCase().includes(query);
    return (queryInTitle || queryInUrl);
  };
  return getAllTabs()
    .then(tabArray => tabArray.filter(tabFilter))
    .then(injectTabsInList);
}

function injectTabsInList(tabArray) {
  const wasNoResult = tabList.querySelectorAll('.tab-object').length === 0;
  const showNoResult = tabArray.length === 0;
  // Don't update dom if we're going to show no results again
  if (wasNoResult && showNoResult) return;

  clearChildren(tabList);

  // Add nodes to tabList & attach event listeners
  if (showNoResult) {
    tabList.appendChild(noResultNode());
  } else {
    tabArray.map(tabToTag).forEach(tabNode => {
    tabNode.addEventListener('click', switchTabs, true);
    tabList.appendChild(tabNode);
    });
  }
}

function tabToTag({ favIconUrl, title, id, url }) {
  const fallBackSvg = '/assets/file.svg';
  const favIconLink = favIconUrl && !isChromeLink(favIconUrl)
    ? favIconUrl
    : fallBackSvg;
  // Just check if it's a url for now so we can shorten it
  const tabTitle = isURL(title)
    ? getBasePath(title)
    : title;
  // Create the parent div
  //

  const tabObjectNode = document.createElement('div');
  tabObjectNode.setAttribute('data-id', id);
  tabObjectNode.setAttribute('tabindex', '0');
  tabObjectNode.classList.add('tab-object');

  // favicon
  //
  const favIconNode = document.createElement('img');
  favIconNode.setAttribute('src', favIconLink);
  favIconNode.onerror = function(event) {
    this.src = fallBackSvg;
  };

  // tab-info
  //

  //      ${title}
  //
${url}

  //

  const tabInfoNode = document.createElement('div');
  tabInfoNode.setAttribute('class', 'tab-info');

  const titleNode = document.createElement('strong');
  titleNode.appendChild(document.createTextNode(tabTitle));

  const urlNode = document.createElement('p');
  urlNode.appendChild(document.createTextNode(url));

  tabInfoNode.appendChild(titleNode);
  tabInfoNode.appendChild(urlNode);

  tabObjectNode.appendChild(favIconNode);
  tabObjectNode.appendChild(tabInfoNode);

  return tabObjectNode;
}

function noResultNode() {
  // tab-info
  //

  //      ${title}
  //
${url}

  //

  const noResultNode = document.createElement('div');
  noResultNode.classList.add('no-result');

  const alertCircleNode = document.createElement('object');
  alertCircleNode.setAttribute('type', 'image/svg+xml');
  alertCircleNode.setAttribute('data', '/assets/alert-circle.svg');

  const strongMsgNode = document.createElement('strong');
  strongMsgNode.appendChild(document.createTextNode('No tabs found'));

  noResultNode.appendChild(alertCircleNode);
  noResultNode.appendChild(strongMsgNode);
  return noResultNode;
}

function clearChildren(node) {
  while (node.firstChild) {
    node.removeChild(node.firstChild);
  };
}

function shortenString(str) {
  return str.length >= 120
    ? str.slice(0, 90) + '...'
    : str;
}

function isChromeLink(src) {
  return /chrome:\/\//.test(src);
}

function isURL(src) {
  return /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/.test(src);
}

function getBasePath(src) {
  const url = new URL(src);
  return url.origin;
}

function switchTabs() {
  // this: should be the tab-object node
  const tabId = this.dataset.id;
  switchActiveTab(tabId);
}

function switchActiveTab(id) {
  const numId = parseInt(id);
  browser.tabs.update(numId, { active: true });
  window.close();
}

function clearInput() {
  searchInput.value = '';
  populateTabList();
}

function populateTabList() {
  getAllTabs().then(injectTabsInList);
}

// To switch tabs
// onClick -> tabs.update(tab.id, { active: true })
<|endoftext|>


<commit_before>/* eslint-env node, jest */

const shogi = require('./index.js');
const Slack = require('../lib/slackMock.js');

let slack = null;

beforeEach(() => {
	slack = new Slack();
	process.env.CHANNEL_SANDBOX = slack.fakeChannel;
	shogi(slack);
});

describe('shogi', () => {
	it('responds to "素数大富豪"', async () => {
		const {username, text} = await slack.getResponseTo('素数大富豪');

		expect(username).toBe('primebot');
		expect(text).toContain('手札');
	});
});
<commit_msg>Mock achievemnts<commit_after>/* eslint-env node, jest */

const shogi = require('./index.js');
const Slack = require('../lib/slackMock.js');

jest.mock('../achievements/index.ts');

let slack = null;

beforeEach(() => {
	slack = new Slack();
	process.env.CHANNEL_SANDBOX = slack.fakeChannel;
	shogi(slack);
});

describe('shogi', () => {
	it('responds to "素数大富豪"', async () => {
		const {username, text} = await slack.getResponseTo('素数大富豪');

		expect(username).toBe('primebot');
		expect(text).toContain('手札');
	});
});
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016 Petr Gotthard <petr.gotthard@centrum.cz>
 * All rights reserved.
 * Distributed under the terms of the MIT License. See the LICENSE file.
 */
var myApp = angular.module('myApp', ['ng-admin', 'uiGmapgoogle-maps']);
myApp.config(['NgAdminConfigurationProvider', function (nga) {
    var admin = nga.application('Server Admin').baseApiUrl('/');

    var applications = nga.entity('applications')
        .identifier(nga.field('name'));
    var users = nga.entity('users')
        .identifier(nga.field('name'));
    var gateways = nga.entity('gateways')
        .identifier(nga.field('mac'));
    var devices = nga.entity('devices')
        .identifier(nga.field('deveui'));
    var links = nga.entity('links')
        .identifier(nga.field('devaddr'));

    // ---- users
    users.listView().fields([
        nga.field('name').isDetailLink(true)
    ]);
    users.creationView().fields([
        nga.field('name'),
        nga.field('pass', 'password')
    ]);
    users.editionView().fields(users.creationView().fields());
    // add to the admin application
    admin.addEntity(users);

    // ---- gateways
    gateways.listView().fields([
        nga.field('mac').label('MAC').isDetailLink(true),
        nga.field('netid').label('NetID')
    ]);
    gateways.creationView().fields([
        nga.field('mac').label('MAC')
            .attributes({ placeholder: 'e.g. 0123456789ABCDEF' })
            .validation({ required: true, pattern: '[A-Za-z0-9]{16}' }),
        nga.field('netid').label('NetID')
            .attributes({ placeholder: 'e.g. 0123AB' })
            .validation({ required: true, pattern: '[A-Za-z0-9]{6}' }),
        nga.field('gpspos', 'template')
            .validation({required: true })
            .label('Location')
            .template('<map location="value"></map>'),
        nga.field('gpsalt', 'number').label('Altitude')
    ]);
    gateways.editionView().fields(gateways.creationView().fields());
    // add to the admin application
    admin.addEntity(gateways);

    // ---- devices
    devices.listView().fields([
        nga.field('deveui').label('DevEUI').isDetailLink(true),
        nga.field('app').label('Application'),
        nga.field('appid').label('AppID'),
        nga.field('appeui').label('AppEUI'),
        nga.field('appkey').label('AppKey'),
        nga.field('link', 'reference')
            .targetEntity(links)
            .targetField(nga.field('devaddr'))
    ]);
    devices.creationView().fields([
        nga.field('deveui').label('DevEUI')
            .attributes({ placeholder: 'e.g. 0123456789ABCDEF' })
            .validation({ required: true, pattern: '[A-Za-z0-9]{16}' }),
        nga.field('app', 'reference').label('Application')
            .targetEntity(applications)
            .targetField(nga.field('name'))
            .validation({ required: true }),
        nga.field('appid').label('AppID'),
        nga.field('appeui').label('AppEUI')
            .attributes({ placeholder: 'e.g. 0123456789ABCDEF' })
            .validation({ required: true, pattern: '[A-Za-z0-9]{16}' }),
        nga.field('appkey').label('AppKey')
            .attributes({ placeholder: 'e.g. FEDCBA9876543210FEDCBA9876543210' })
            .validation({ required: true, pattern: '[A-Za-z0-9]{32}' }),
        nga.field('link')
            .attributes({ placeholder: 'e.g. ABC12345' })
            .validation({ pattern: '[A-Za-z0-9]{32}' })
    ]);
    devices.editionView().fields(devices.creationView().fields());
    // add to the admin application
    admin.addEntity(devices);

    // ---- links
    links.listView().fields([
        nga.field('devaddr').label('DevAddr').isDetailLink(true),
        nga.field('app').label('Application'),
        nga.field('appid').label('AppID'),
        nga.field('nwkskey').label('NwkSKey'),
        nga.field('appskey').label('AppSKey'),
        nga.field('fcntup', 'number').label('FCnt Up'),
        nga.field('fcntdown', 'number').label('FCnt Down')
    ]);
    links.creationView().fields([
        nga.field('devaddr').label('DevAddr')
            .attributes({ placeholder: 'e.g. ABC12345' })
            .validation({ required: true, pattern: '[A-Za-z0-9]{8}' }),
        nga.field('app', 'reference').label('Application')
            .targetEntity(applications)
            .targetField(nga.field('name'))
            .validation({ required: true }),
        nga.field('appid').label('AppID'),
        nga.field('nwkskey').label('NwkSKey')
            .attributes({ placeholder: 'e.g. FEDCBA9876543210FEDCBA9876543210' })
            .validation({ required: true, pattern: '[A-Za-z0-9]{32}' }),
        nga.field('appskey').label('AppSKey')
            .attributes({ placeholder: 'e.g. FEDCBA9876543210FEDCBA9876543210' })
            .validation({ required: true, pattern: '[A-Za-z0-9]{32}' }),
        nga.field('fcntup', 'number').label('FCnt Up')
            .defaultValue(0),
        nga.field('fcntdown', 'number').label('FCnt Down')
            .defaultValue(0)
    ]);
    links.editionView().fields(links.creationView().fields());
    // add to the admin application
    admin.addEntity(links);

    // ---- dashboard
    admin.dashboard(nga.dashboard()
        .addCollection(nga.collection(devices)
            .fields([
                nga.field('deveui').label('DevEUI').isDetailLink(true)
            ])
        )
        .addCollection(nga.collection(links)
            .fields([
                nga.field('devaddr').label('DevAddr').isDetailLink(true)
            ])
        )
    );

    // attach the admin application to the DOM and execute it
    nga.configure(admin);
}]);
// http://stackoverflow.com/questions/35895411/ng-admin-and-google-maps
myApp.directive('map', [function () {
return {
    restrict: 'E',
    scope: {
        value: '=location',
    },
    link: function($scope, uiGmapIsReady) {
        if ($scope.value == undefined) {
            $scope.value = { lat: 48.88, lon: 14.12};
        }
        $scope.map = { center: { latitude: $scope.value.lat, longitude: $scope.value.lon }, zoom: 4 };
        $scope.marker = {
            id: 0,
            coords: {
                latitude: $scope.value.lat,
                longitude: $scope.value.lon
            },
            options: { draggable: true },
            events: {
                dragend: function (marker, eventName, args) {
                    $scope.value = { lat: marker.getPosition().lat(), lon: marker.getPosition().lng() };
                }
            }
        };
    },
    template:
    `

            <ui-gmap-google-map center="map.center" zoom="map.zoom" draggable="true" options="options" pan=true refresh="true">
                <ui-gmap-marker coords="marker.coords" options="marker.options" events="marker.events" idkey="marker.id">
                </ui-gmap-marker>
            </ui-gmap-google-map>

    `
};}]);
myApp.config(function (uiGmapGoogleMapApiProvider) {
    uiGmapGoogleMapApiProvider.configure({
        key: '',
        v: '3',
        libraries: 'visualization'
    });
});
<commit_msg>The DevAdd is only 8 bytes long.<commit_after>/*
 * Copyright (c) 2016 Petr Gotthard <petr.gotthard@centrum.cz>
 * All rights reserved.
 * Distributed under the terms of the MIT License. See the LICENSE file.
 */
var myApp = angular.module('myApp', ['ng-admin', 'uiGmapgoogle-maps']);
myApp.config(['NgAdminConfigurationProvider', function (nga) {
    var admin = nga.application('Server Admin').baseApiUrl('/');

    var applications = nga.entity('applications')
        .identifier(nga.field('name'));
    var users = nga.entity('users')
        .identifier(nga.field('name'));
    var gateways = nga.entity('gateways')
        .identifier(nga.field('mac'));
    var devices = nga.entity('devices')
        .identifier(nga.field('deveui'));
    var links = nga.entity('links')
        .identifier(nga.field('devaddr'));

    // ---- users
    users.listView().fields([
        nga.field('name').isDetailLink(true)
    ]);
    users.creationView().fields([
        nga.field('name'),
        nga.field('pass', 'password')
    ]);
    users.editionView().fields(users.creationView().fields());
    // add to the admin application
    admin.addEntity(users);

    // ---- gateways
    gateways.listView().fields([
        nga.field('mac').label('MAC').isDetailLink(true),
        nga.field('netid').label('NetID')
    ]);
    gateways.creationView().fields([
        nga.field('mac').label('MAC')
            .attributes({ placeholder: 'e.g. 0123456789ABCDEF' })
            .validation({ required: true, pattern: '[A-Za-z0-9]{16}' }),
        nga.field('netid').label('NetID')
            .attributes({ placeholder: 'e.g. 0123AB' })
            .validation({ required: true, pattern: '[A-Za-z0-9]{6}' }),
        nga.field('gpspos', 'template')
            .validation({required: true })
            .label('Location')
            .template('<map location="value"></map>'),
        nga.field('gpsalt', 'number').label('Altitude')
    ]);
    gateways.editionView().fields(gateways.creationView().fields());
    // add to the admin application
    admin.addEntity(gateways);

    // ---- devices
    devices.listView().fields([
        nga.field('deveui').label('DevEUI').isDetailLink(true),
        nga.field('app').label('Application'),
        nga.field('appid').label('AppID'),
        nga.field('appeui').label('AppEUI'),
        nga.field('appkey').label('AppKey'),
        nga.field('link', 'reference')
            .targetEntity(links)
            .targetField(nga.field('devaddr'))
    ]);
    devices.creationView().fields([
        nga.field('deveui').label('DevEUI')
            .attributes({ placeholder: 'e.g. 0123456789ABCDEF' })
            .validation({ required: true, pattern: '[A-Za-z0-9]{16}' }),
        nga.field('app', 'reference').label('Application')
            .targetEntity(applications)
            .targetField(nga.field('name'))
            .validation({ required: true }),
        nga.field('appid').label('AppID'),
        nga.field('appeui').label('AppEUI')
            .attributes({ placeholder: 'e.g. 0123456789ABCDEF' })
            .validation({ required: true, pattern: '[A-Za-z0-9]{16}' }),
        nga.field('appkey').label('AppKey')
            .attributes({ placeholder: 'e.g. FEDCBA9876543210FEDCBA9876543210' })
            .validation({ required: true, pattern: '[A-Za-z0-9]{32}' }),
        nga.field('link')
            .attributes({ placeholder: 'e.g. ABC12345' })
            .validation({ pattern: '[A-Za-z0-9]{8}' })
    ]);
    devices.editionView().fields(devices.creationView().fields());
    // add to the admin application
    admin.addEntity(devices);

    // ---- links
    links.listView().fields([
        nga.field('devaddr').label('DevAddr').isDetailLink(true),
        nga.field('app').label('Application'),
        nga.field('appid').label('AppID'),
        nga.field('nwkskey').label('NwkSKey'),
        nga.field('appskey').label('AppSKey'),
        nga.field('fcntup', 'number').label('FCnt Up'),
        nga.field('fcntdown', 'number').label('FCnt Down')
    ]);
    links.creationView().fields([
        nga.field('devaddr').label('DevAddr')
            .attributes({ placeholder: 'e.g. ABC12345' })
            .validation({ required: true, pattern: '[A-Za-z0-9]{8}' }),
        nga.field('app', 'reference').label('Application')
            .targetEntity(applications)
            .targetField(nga.field('name'))
            .validation({ required: true }),
        nga.field('appid').label('AppID'),
        nga.field('nwkskey').label('NwkSKey')
            .attributes({ placeholder: 'e.g. FEDCBA9876543210FEDCBA9876543210' })
            .validation({ required: true, pattern: '[A-Za-z0-9]{32}' }),
        nga.field('appskey').label('AppSKey')
            .attributes({ placeholder: 'e.g. FEDCBA9876543210FEDCBA9876543210' })
            .validation({ required: true, pattern: '[A-Za-z0-9]{32}' }),
        nga.field('fcntup', 'number').label('FCnt Up')
            .defaultValue(0),
        nga.field('fcntdown', 'number').label('FCnt Down')
            .defaultValue(0)
    ]);
    links.editionView().fields(links.creationView().fields());
    // add to the admin application
    admin.addEntity(links);

    // ---- dashboard
    admin.dashboard(nga.dashboard()
        .addCollection(nga.collection(devices)
            .fields([
                nga.field('deveui').label('DevEUI').isDetailLink(true)
            ])
        )
        .addCollection(nga.collection(links)
            .fields([
                nga.field('devaddr').label('DevAddr').isDetailLink(true)
            ])
        )
    );

    // attach the admin application to the DOM and execute it
    nga.configure(admin);
}]);
// http://stackoverflow.com/questions/35895411/ng-admin-and-google-maps
myApp.directive('map', [function () {
return {
    restrict: 'E',
    scope: {
        value: '=location',
    },
    link: function($scope, uiGmapIsReady) {
        if ($scope.value == undefined) {
            $scope.value = { lat: 48.88, lon: 14.12};
        }
        $scope.map = { center: { latitude: $scope.value.lat, longitude: $scope.value.lon }, zoom: 4 };
        $scope.marker = {
            id: 0,
            coords: {
                latitude: $scope.value.lat,
                longitude: $scope.value.lon
            },
            options: { draggable: true },
            events: {
                dragend: function (marker, eventName, args) {
                    $scope.value = { lat: marker.getPosition().lat(), lon: marker.getPosition().lng() };
                }
            }
        };
    },
    template:
    `

            <ui-gmap-google-map center="map.center" zoom="map.zoom" draggable="true" options="options" pan=true refresh="true">
                <ui-gmap-marker coords="marker.coords" options="marker.options" events="marker.events" idkey="marker.id">
                </ui-gmap-marker>
            </ui-gmap-google-map>

    `
};}]);
myApp.config(function (uiGmapGoogleMapApiProvider) {
    uiGmapGoogleMapApiProvider.configure({
        key: '',
        v: '3',
        libraries: 'visualization'
    });
});
<|endoftext|>


<commit_before>var projects = {

	"smart facebook birthday assistant": {
		"image":"https://avatars3.githubusercontent.com/u/22071699?v=3&s=200",
		"team":"lannisters sucks",
		"link":"https://github.com/sameer2800/IIITA_HACKS"

	},

	"<project-name>":{
                      "image":"https://avatars3.githubusercontent.com/u/22071699?v=3&s=200",
                      "team":"IIIT-A Hacks",
                      "link":"https://github.com/iiitahacks"
                  },
         "Gather":{
                      "image":"https://avatars3.githubusercontent.com/u/22071699?v=3&s=200",
                      "team":"checkmate",
                      "link":"https://github.com/magician03/gather"
                  }

}
<commit_msg>Add KrayZ<commit_after>var projects = {

	"smart facebook birthday assistant": {
		"image":"https://avatars3.githubusercontent.com/u/22071699?v=3&s=200",
		"team":"lannisters sucks",
		"link":"https://github.com/sameer2800/IIITA_HACKS"

	},

	"<project-name>":{
                      "image":"https://avatars3.githubusercontent.com/u/22071699?v=3&s=200",
                      "team":"IIIT-A Hacks",
                      "link":"https://github.com/iiitahacks"
                  },
         "Gather":{
                      "image":"https://avatars3.githubusercontent.com/u/22071699?v=3&s=200",
                      "team":"checkmate",
                      "link":"https://github.com/magician03/gather"
                  },
          "KrayZ":{
                      "image":"https://openclipart.org/image/800px/svg_to_png/227918/Video-Game-Controller-Icon.png"",
                      "team":"Krayz",
                      "link":"https://github.com/indreshattri/KrayZ"
                  }

}
<|endoftext|>


<commit_before>var div = React.createFactory('div');

var WeatherTitle = React.createFactory(React.createClass({
    render: function() {
        return div(null,
                React.DOM.h3(null, this.props.city)
        );
    }
}));

var WeatherIcon = React.createFactory(React.createClass({
    getWeatherIconFromConditionCode: function(code) {
        var iconMap = [
            'wi-tornado', //
            'wi-day-thunderstorm', //
            'wi-hurricane', //
            'wi-thunderstorm', //
            'wi-thunderstorm', //
            'wi-sleet', //
            'wi-sleet', //
            'wi-sleet', //
            'wi-rain-mix', //
            'wi-rain-mix', //
            'wi-rain', //
            'wi-rain-mix', //
            'wi-rain-mix', //
            'wi-sprinkle', //
            'wi-snow', //
            'wi-snow-wind', //
            'wi-snow', //
            'wi-hail', //
            'wi-sleet', //
            'wi-dust', //
            'wi-fog', //
            'wi-day-haze', //
            'wi-smoke', //
            'wi-windy', //
            'wi-windy', //
            'wi-snowflake-cold', //
            'wi-cloudy', //
            'wi-night-alt-cloudy', //
            'wi-day-cloudy', //
            'night-partly-cloudy', //
            'wi-day-cloudy', //
            'wi-night-clear', //
            'wi-day-sunny', //
            'wi-night-clear', //
            'wi-day-sunny', //
            'wi-day-hail', //
            'wi-hot', //
            'wi-thunderstorm', //
            'wi-storm-showers', //
            'wi-storm-showers', //
            'wi-showers', //
            'wi-snow', //
            'wi-sprinkle', //
            'wi-snow', //
            'wi-cloudy', //
            'wi-thunderstorm', //
            'wi-snow', //
            'wi-thunderstorm', //
        ];

        var iconName;
        if (code < iconMap.length) {
            iconName = iconMap[code];
        } else {
            // Not found
            iconName = 'wi-alien';
        }
        return 'wi ' + iconName;
    },
    render: function() {
        return div(null,
            React.DOM.i({className: this.getWeatherIconFromConditionCode(this.props.conditionCode), style: {fontSize: this.props.fontSize}})
        );
    }
}));

var WeatherTemperature = React.createFactory(React.createClass({
    getDefaultProps: function() {
        return {
            weatherClassName: '',
        };
    },
    render: function() {
        return React.DOM.span({className: 'weatherTemperature ' + this.props.weatherClassName, style: {fontSize: this.props.fontSize}}, this.props.temperature + String.fromCharCode(176) + this.props.units);
    }
}));

var WeatherInfo = React.createFactory(React.createClass({
    render: function() {
        return div({className:'row', id: 'weatherInfo'},
            div({className: 'row'},
                div({className: 'col-xs-offset-5 col-xs-1'},
                    WeatherIcon({conditionCode: this.props.condition.code, fontSize: '5em'})
                ),
                div({className: 'col-xs-1'},
                    WeatherTemperature({temperature: this.props.condition.temp, units: this.props.units, fontSize: '5em'})
                )
            ),
            div({className: 'row'},
                div({className: 'col-xs-offset-5 col-xs-2'},
                    React.DOM.h4(null, this.props.condition.text)
                )
            )
        );
    }
}));

var WeatherDate = React.createFactory(React.createClass({
    render: function() {
        return div({className: 'weatherInfo'},
            React.DOM.h4(null, this.props.pubDate)
        );
    }
}));

var YahooAttribution = React.createFactory(React.createClass({
    render: function() {
        return div(null,
            React.DOM.a({href: this.props.link, target: '_blank'},
                React.DOM.h5(null, 'Weather provided by Yahoo')
            ),
            React.DOM.a({href: 'https://www.yahoo.com/?ilc=401', target: '_blank'},
                React.DOM.img({src: 'https://poweredby.yahoo.com/white.png', width: '134', height: '29'})
            )
        );
    }
}));

var WeatherForecast = React.createFactory(React.createClass({
    render: function() {
        var forecastProps = this.props;
        var forecastComponents = this.props.forecast.map(function(forecastItem) {
            return div({className: 'row'},
                div({className: 'col-xs-offset-4 col-xs-1'},
                    React.DOM.h3(null, forecastItem.day)
                ),
                div({className: 'col-xs-1'},
                    WeatherIcon({conditionCode: forecastItem.code, fontSize: '2em'})
                ),
                div({className: 'col-xs-1'},
                    WeatherTemperature({temperature: forecastItem.high, units: forecastProps.units, fontSize: '2em', weatherClassName: 'weatherTempHigh'})
                ),
                div({className: 'col-xs-1'},
                    WeatherTemperature({temperature: forecastItem.low, units: forecastProps.units, fontSize: '2em', weatherClassName: 'weatherTempLow'})
                )
            );
        });
        return div({className: 'WeatherForecastRow'},
            React.DOM.h3(null, '5 Day Forecast'),
            forecastComponents
        );
    }
}));

var WeatherApp = React.createFactory(React.createClass({
    createYahooWeatherUrl: function(city, units) {
        var encodedCity = escape(city);
        var url = "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D'" + encodedCity + "')and%20u='" + units.toLowerCase() + "'&format=json";

        return url;
    },
    retrieveWeatherData: function() {
        console.log('retrieve weather data');

        var url = this.createYahooWeatherUrl(this.state.city, this.state.units);
        $.get(url, function(result) {
            this.setState({weatherData: result.query.results.channel});
        }.bind(this));
    },
    getInitialState: function() {
        return {
            weatherData: null,
            units: 'c',
            city: 'warrington, uk'
        };
    },
    componentDidMount: function() {
        this.retrieveWeatherData();
        setInterval(this.retrieveWeatherData, this.props.pollInterval);
    },
    render: function() {
        if (this.state.weatherData) {
            return div(null,
                // Weather Title
                WeatherTitle({
                    city: this.state.weatherData.location.city,
                    country: this.state.weatherData.location.country,
                }),
                // Weather Info
                WeatherInfo({
                    condition: this.state.weatherData.item.condition,
                    units: this.state.weatherData.units.temperature
                }),
                // Date
                WeatherDate({pubDate: this.state.weatherData.item.pubDate}),
                // 5 day forecast
                WeatherForecast({
                    forecast: this.state.weatherData.item.forecast,
                    units: this.state.weatherData.units.temperature
                }),
                // Attribution
                YahooAttribution({link: this.state.weatherData.link})
            );
        } else {
            return div(null, React.DOM.i({className: 'fa fa-5x fa-refresh fa-spin'}));
        }
    }
}));

React.render(
    WeatherApp({pollInterval: 30000}),
    document.getElementById('mainDiv')
);<commit_msg>Added city property to main WeatherApp.<commit_after>var div = React.createFactory('div');

var WeatherTitle = React.createFactory(React.createClass({
    render: function() {
        return div(null,
                React.DOM.h3(null, this.props.city)
        );
    }
}));

var WeatherIcon = React.createFactory(React.createClass({
    getWeatherIconFromConditionCode: function(code) {
        var iconMap = [
            'wi-tornado', //
            'wi-day-thunderstorm', //
            'wi-hurricane', //
            'wi-thunderstorm', //
            'wi-thunderstorm', //
            'wi-sleet', //
            'wi-sleet', //
            'wi-sleet', //
            'wi-rain-mix', //
            'wi-rain-mix', //
            'wi-rain', //
            'wi-rain-mix', //
            'wi-rain-mix', //
            'wi-sprinkle', //
            'wi-snow', //
            'wi-snow-wind', //
            'wi-snow', //
            'wi-hail', //
            'wi-sleet', //
            'wi-dust', //
            'wi-fog', //
            'wi-day-haze', //
            'wi-smoke', //
            'wi-windy', //
            'wi-windy', //
            'wi-snowflake-cold', //
            'wi-cloudy', //
            'wi-night-alt-cloudy', //
            'wi-day-cloudy', //
            'night-partly-cloudy', //
            'wi-day-cloudy', //
            'wi-night-clear', //
            'wi-day-sunny', //
            'wi-night-clear', //
            'wi-day-sunny', //
            'wi-day-hail', //
            'wi-hot', //
            'wi-thunderstorm', //
            'wi-storm-showers', //
            'wi-storm-showers', //
            'wi-showers', //
            'wi-snow', //
            'wi-sprinkle', //
            'wi-snow', //
            'wi-cloudy', //
            'wi-thunderstorm', //
            'wi-snow', //
            'wi-thunderstorm', //
        ];

        var iconName;
        if (code < iconMap.length) {
            iconName = iconMap[code];
        } else {
            // Not found
            iconName = 'wi-alien';
        }
        return 'wi ' + iconName;
    },
    render: function() {
        return div(null,
            React.DOM.i({className: this.getWeatherIconFromConditionCode(this.props.conditionCode), style: {fontSize: this.props.fontSize}})
        );
    }
}));

var WeatherTemperature = React.createFactory(React.createClass({
    getDefaultProps: function() {
        return {
            weatherClassName: '',
        };
    },
    render: function() {
        return React.DOM.span({className: 'weatherTemperature ' + this.props.weatherClassName, style: {fontSize: this.props.fontSize}}, this.props.temperature + String.fromCharCode(176) + this.props.units);
    }
}));

var WeatherInfo = React.createFactory(React.createClass({
    render: function() {
        return div({className:'row', id: 'weatherInfo'},
            div({className: 'row'},
                div({className: 'col-xs-offset-5 col-xs-1'},
                    WeatherIcon({conditionCode: this.props.condition.code, fontSize: '5em'})
                ),
                div({className: 'col-xs-1'},
                    WeatherTemperature({temperature: this.props.condition.temp, units: this.props.units, fontSize: '5em'})
                )
            ),
            div({className: 'row'},
                div({className: 'col-xs-offset-5 col-xs-2'},
                    React.DOM.h4(null, this.props.condition.text)
                )
            )
        );
    }
}));

var WeatherDate = React.createFactory(React.createClass({
    render: function() {
        return div({className: 'weatherInfo'},
            React.DOM.h4(null, this.props.pubDate)
        );
    }
}));

var YahooAttribution = React.createFactory(React.createClass({
    render: function() {
        return div(null,
            React.DOM.a({href: this.props.link, target: '_blank'},
                React.DOM.h5(null, 'Weather provided by Yahoo')
            ),
            React.DOM.a({href: 'https://www.yahoo.com/?ilc=401', target: '_blank'},
                React.DOM.img({src: 'https://poweredby.yahoo.com/white.png', width: '134', height: '29'})
            )
        );
    }
}));

var WeatherForecast = React.createFactory(React.createClass({
    render: function() {
        var forecastProps = this.props;
        var forecastComponents = this.props.forecast.map(function(forecastItem) {
            return div({className: 'row'},
                div({className: 'col-xs-offset-4 col-xs-1'},
                    React.DOM.h3(null, forecastItem.day)
                ),
                div({className: 'col-xs-1'},
                    WeatherIcon({conditionCode: forecastItem.code, fontSize: '2em'})
                ),
                div({className: 'col-xs-1'},
                    WeatherTemperature({temperature: forecastItem.high, units: forecastProps.units, fontSize: '2em', weatherClassName: 'weatherTempHigh'})
                ),
                div({className: 'col-xs-1'},
                    WeatherTemperature({temperature: forecastItem.low, units: forecastProps.units, fontSize: '2em', weatherClassName: 'weatherTempLow'})
                )
            );
        });
        return div({className: 'WeatherForecastRow'},
            React.DOM.h3(null, '5 Day Forecast'),
            forecastComponents
        );
    }
}));

var WeatherApp = React.createFactory(React.createClass({
    createYahooWeatherUrl: function(city, units) {
        var encodedCity = escape(city);
        var url = "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D'" + encodedCity + "')and%20u='" + units.toLowerCase() + "'&format=json";

        return url;
    },
    retrieveWeatherData: function() {
        console.log('retrieve weather data');

        var url = this.createYahooWeatherUrl(this.state.city, this.state.units);
        $.get(url, function(result) {
            this.setState({weatherData: result.query.results.channel});
        }.bind(this));
    },
    getInitialState: function() {
        return {
            weatherData: null,
            units: 'c',
            city: this.props.city
        };
    },
    componentDidMount: function() {
        this.retrieveWeatherData();
        setInterval(this.retrieveWeatherData, this.props.pollInterval);
    },
    render: function() {
        if (this.state.weatherData) {
            return div(null,
                // Weather Title
                WeatherTitle({
                    city: this.state.weatherData.location.city,
                    country: this.state.weatherData.location.country,
                }),
                // Weather Info
                WeatherInfo({
                    condition: this.state.weatherData.item.condition,
                    units: this.state.weatherData.units.temperature
                }),
                // Date
                WeatherDate({pubDate: this.state.weatherData.item.pubDate}),
                // 5 day forecast
                WeatherForecast({
                    forecast: this.state.weatherData.item.forecast,
                    units: this.state.weatherData.units.temperature
                }),
                // Attribution
                YahooAttribution({link: this.state.weatherData.link})
            );
        } else {
            return div(null, React.DOM.i({className: 'fa fa-5x fa-refresh fa-spin'}));
        }
    }
}));

React.render(
    WeatherApp({pollInterval: 30000, city: 'Manchester, UK'}),
    document.getElementById('mainDiv')
);<|endoftext|>