<commit_before>exports.localization = {
    en: {
        CHAT_WITH_US: 'Chat with us',
        NAME: 'Name',
        EMAIL: 'E-mail',
        START_CONVERSATION: 'Start conversation',
        NEW_MESSAGE: 'New message',
        NO_USERS_ONLINE: 'Currently there are no users online to help you. Leave a message and we will get back to you ASAP! Sorry!',
        CONVERSATION_HISTORY: 'Conversation history',
        JUST_WRITE: 'Just write...',
        PROBLEM_CONNECTING_TO_SERVER: 'We got a problem connecting to the server!',
        ERROR_FILL_ALL_FIELDS: 'Please fill the fields with valid name and email.',
        CONNECTING_TO_SERVER: 'Connecting to the server...',
        SERVER_OFFLINE: 'Server is now offline!',
        USER_IS_TYPING: 'User is typing...',
        UPLOADING_FILE: 'Uploading file',
        ERROR_UPLOADING_FILE: 'Error uploading the file!',
        ATTACH_FILE: 'Attach a file',
        USER_OFFLINE: 'Looks like internet is gone!',
        USER_ONLINE: 'We are back!',
        MUTE: 'Mute conversation',
        CLOSE: 'Close conversation',
        MINIMIZE: 'Minimize conversation',
        TITLE: 'Support',
        POWERED_BY: 'Powered by  Prud.io'
    },
    pt: {
        CHAT_WITH_US: 'Fale connosco',
        NAME: 'Nome',
        EMAIL: 'E-mail',
        START_CONVERSATION: 'Iniciar conversa',
        NEW_MESSAGE: 'Nova mensagem',
        NO_USERS_ONLINE: 'Desculpe! Neste momento não existem utilizadores online para ajuda-lo. Deixe uma mensagem e tentaremos entrar em contacto o mais rápido possivel!',
        CONVERSATION_HISTORY: 'Histórico da conversa',
        JUST_WRITE: 'Escreva aqui...',
        PROBLEM_CONNECTING_TO_SERVER: 'Ocorreu um problema ao efectuar a ligação ao servidor!',
        ERROR_FILL_ALL_FIELDS: 'Por favor preencha os campos com um nome e e-mail válido.',
        CONNECTING_TO_SERVER: 'A ligar ao servidor...',
        SERVER_OFFLINE: 'Servidor está desligado!',
        USER_IS_TYPING: 'A escrever...',
        UPLOADING_FILE: 'Anexando ficheiro',
        ERROR_UPLOADING_FILE: 'Erro ao anexar ficheiro!',
        ATTACH_FILE: 'Anexar um ficheiro',
        USER_OFFLINE: 'Parece que a internet foi abaixo!',
        USER_ONLINE: 'Estamos de volta!',
        MUTE: 'Silenciar conversa',
        CLOSE: 'Fechar conversa',
        MINIMIZE: 'Minimizar conversa',
        TITLE: 'Suporte',
        POWERED_BY: 'Desenvolvido por  Prud.io'
    },
    de: {
        CHAT_WITH_US: 'Chatten Sie mit uns',
        NAME: 'Name',
        EMAIL: 'E-Mail',
        START_CONVERSATION: 'Starten Sie einen Chat',
        NEW_MESSAGE: 'Neue Nachricht',
        NO_USERS_ONLINE: 'Zur Zeit ist niemand online um Ihnen zu helfen. Hinterlassen Sie eine Nachricht und wir melden uns sobald wie möglich bei Ihnen.',
        CONVERSATION_HISTORY: 'Nachrichtenverlauf',
        JUST_WRITE: 'Hier schreiben...',
        PROBLEM_CONNECTING_TO_SERVER: 'Die Verbindung zum Server ist fehlgeschlagen.',
        ERROR_FILL_ALL_FIELDS: 'Bitte füllen Sie die Felder mit einem Namen und einer gültigen E-Mail Adresse aus.',
        CONNECTING_TO_SERVER: 'Verbinde zum Server...',
        SERVER_OFFLINE: 'Server ist offline.',
        USER_IS_TYPING: 'Benutzer schreibt...',
        UPLOADING_FILE: 'Datei wird hochgeladen',
        ERROR_UPLOADING_FILE: 'Das Hochladen ist fehlgeschlagen',
        ATTACH_FILE: 'Datei hochladen',
        USER_OFFLINE: 'Keine Internetverbindung',
        USER_ONLINE: 'Internetverbindung wieder vorhanden',
        MUTE: 'Chat stummschalten',
        CLOSE: 'Chat schliessen',
        MINIMIZE: 'Chat minimieren',
        TITLE: 'Support',
        POWERED_BY: ' Prud.io'
    },
    es: {
        CHAT_WITH_US: 'Habla con nosotros',
        NAME: 'Nombre',
        EMAIL: 'E-mail',
        START_CONVERSATION: 'Iniciar una conversación',
        NEW_MESSAGE: 'Nuevo mensaje',
        NO_USERS_ONLINE: 'Perdon! Actualmente no hay miembros en línea para ayudarle. Deja un mensaje y trataremos de ponernos en contacto lo antes posible!',
        CONVERSATION_HISTORY: 'Historial de la conversación',
        JUST_WRITE: 'Escriba aqui...',
        PROBLEM_CONNECTING_TO_SERVER: 'Hubo un problema al conectar con el servidor!',
        ERROR_FILL_ALL_FIELDS: 'Por favor, rellene los campos con un nombre y una dirección de correo electrónico válida.',
        CONNECTING_TO_SERVER: 'Conectando con el servidor...',
        SERVER_OFFLINE: 'Servidor está apagado!',
        USER_IS_TYPING: 'El usuario está escribiendo...',
        UPLOADING_FILE: 'Enviando fichero',
        ERROR_UPLOADING_FILE: 'Error al adjuntar fichero!',
        ATTACH_FILE: 'Adjuntar un fichero',
        USER_OFFLINE: 'La internet se ha ido',
        USER_ONLINE: 'Estamos de vuelta!',
        MUTE: 'Silenciar conversación',
        CLOSE: 'Cerrar conversación',
        MINIMIZE: 'Minimizar conversación',
        TITLE: 'Soporte',
        POWERED_BY: 'Desarrollado por  Prud.io'
    },
    fr: {
        CHAT_WITH_US: 'Chattez avec nous',
        NAME: 'Nom',
        EMAIL: 'E-mail',
        START_CONVERSATION: 'Démarrez une conversation',
        NEW_MESSAGE: 'Nouveau message',
        NO_USERS_ONLINE: 'Désolé! Actuellement aucun membre en ligne pour vous aider. laissez un message et nous reviendrons vers vous dès que possible!',
        CONVERSATION_HISTORY: 'L\'historique des conversations',
        JUST_WRITE: 'Écrivez ici ...',
        PROBLEM_CONNECTING_TO_SERVER: 'Problème de connexion au serveur!',
        ERROR_FILL_ALL_FIELDS: 'S\'il vous plaît remplir les champs avec un nom et une adresse email valide.',
        CONNECTING_TO_SERVER: 'Connexion au serveur...',
        SERVER_OFFLINE: 'Server est hors ligne!',
        USER_IS_TYPING: 'l\'utilisateur est en train de taper...',
        UPLOADING_FILE: 'Envoi de fichier',
        ERROR_UPLOADING_FILE: 'Une erreur est survenue durant l\'envoi du fichier!',
        ATTACH_FILE: 'Joindre un fichier',
        USER_OFFLINE: 'Pas de connexion internet',
        USER_ONLINE: 'Nous sommes de retour!',
        MUTE: 'Mettre en sourdine',
        CLOSE: 'Fermer la conversation',
        MINIMIZE: 'Réduire la conversation',
        TITLE: 'Soutien',
        POWERED_BY: 'Propulsé par  Prud.io'
    },
    tr: {
        CHAT_WITH_US: 'Bizimle Konuşun',
        NAME: 'Ad',
        EMAIL: 'E-posta',
        START_CONVERSATION: 'Görüşme başlat',
        NEW_MESSAGE: 'Yeni mesaj',
        NO_USERS_ONLINE: 'Şu anda size yardımcı olabilecek çevrimiçi kullanıcı mevcut değil. Lütfen bir mesaj bırakın, size en kısa zamanda dönüş yapacağız. Üzgünüz.',
        CONVERSATION_HISTORY: 'Görüşme Tarihçesi',
        JUST_WRITE: 'Buraya yazın...',
        PROBLEM_CONNECTING_TO_SERVER: 'Sunucuya bağlanırken bir sorun oluştu!',
        ERROR_FILL_ALL_FIELDS: 'Lütfen tüm alanları geçerli bir isim ve e-posta ile doldurun.',
        CONNECTING_TO_SERVER: 'Sunucuya bağlanılıyor...',
        SERVER_OFFLINE: 'Sunucu şu anda çevrimdışı!',
        USER_IS_TYPING: 'Kullanıcı yazıyor...',
        UPLOADING_FILE: 'Dosya sunucuya yükleniyor',
        ERROR_UPLOADING_FILE: 'Sunucuya dosya yüklenirken hata oluştu!',
        ATTACH_FILE: 'Dosya Ekle',
        USER_OFFLINE: 'Görünüşe göre internet gitti!',
        USER_ONLINE: 'Geri geldik!',
        MUTE: 'Görüşmeyi sessize al',
        CLOSE: 'Görüşmeyi kapat',
        MINIMIZE: 'Görüşmeyi aşağıya indir',
        TITLE: 'Destek',
        POWERED_BY: ' Prud.io ile çalışmaktadır.'
    },
    ro: {
        CHAT_WITH_US: 'Discută cu noi',
        NAME: 'Nume',
        EMAIL: 'E-mail',
        START_CONVERSATION: 'Pornește conversație',
        NEW_MESSAGE: 'Mesaj Nou',
        NO_USERS_ONLINE: 'Momentan nu este online nici un utilizator care să te ajute. Lasă un mesaj și te vom contacta în curând!',
        CONVERSATION_HISTORY: 'Istoric Conversații',
        JUST_WRITE: 'Scrie aici...',
        PROBLEM_CONNECTING_TO_SERVER: 'A apărut o eroare de conectare la server!',
        ERROR_FILL_ALL_FIELDS: 'Completati câmpurile cu name și email valide.',
        CONNECTING_TO_SERVER: 'Se conectează la server...',
        SERVER_OFFLINE: 'Serverul nu este disponibil!',
        USER_IS_TYPING: 'Utilizatorul scrie...',
        UPLOADING_FILE: 'Încărcare fișier',
        ERROR_UPLOADING_FILE: 'Eroare de încărcare a fișierului!',
        ATTACH_FILE: ' Atașază un fișier',
        USER_OFFLINE: 'Conexiune la Internet indisponibilă!',
        USER_ONLINE: 'Ne-am întors!',
        MUTE: 'Fără Sonor',
        CLOSE: 'Închide conversația',
        MINIMIZE: 'Minimizează conversația',
        TITLE: 'Asistență',
        POWERED_BY: 'Dezvoltat de  Prud.io'
    }
};
<commit_msg>little fixes<commit_after>exports.localization = {
    en: {
        CHAT_WITH_US: 'Chat with us',
        NAME: 'Name',
        EMAIL: 'E-mail',
        START_CONVERSATION: 'Start conversation',
        NEW_MESSAGE: 'New message',
        NO_USERS_ONLINE: 'Currently there are no users online to help you. Leave a message and we will get back to you ASAP! Sorry!',
        CONVERSATION_HISTORY: 'Conversation history',
        JUST_WRITE: 'Just write...',
        PROBLEM_CONNECTING_TO_SERVER: 'We got a problem connecting to the server!',
        ERROR_FILL_ALL_FIELDS: 'Please fill the fields with valid name and email.',
        CONNECTING_TO_SERVER: 'Connecting to the server...',
        SERVER_OFFLINE: 'Server is now offline!',
        USER_IS_TYPING: 'User is typing...',
        UPLOADING_FILE: 'Uploading file',
        ERROR_UPLOADING_FILE: 'Error uploading the file!',
        ATTACH_FILE: 'Attach a file',
        USER_OFFLINE: 'Looks like internet is gone!',
        USER_ONLINE: 'We are back!',
        MUTE: 'Mute conversation',
        CLOSE: 'Close conversation',
        MINIMIZE: 'Minimize conversation',
        TITLE: 'Support',
        POWERED_BY: 'Powered by  Prud.io'
    },
    pt: {
        CHAT_WITH_US: 'Fale conosco',
        NAME: 'Nome',
        EMAIL: 'E-mail',
        START_CONVERSATION: 'Iniciar conversa',
        NEW_MESSAGE: 'Nova mensagem',
        NO_USERS_ONLINE: 'Desculpe! Neste momento não existem utilizadores online para ajudá-lo. Deixe uma mensagem e tentaremos entrar em contacto o mais rápido possível!',
        CONVERSATION_HISTORY: 'Histórico da conversa',
        JUST_WRITE: 'Escreva aqui...',
        PROBLEM_CONNECTING_TO_SERVER: 'Ocorreu um problema ao efectuar a ligação ao servidor!',
        ERROR_FILL_ALL_FIELDS: 'Por favor preencha os campos com um nome e e-mail válido.',
        CONNECTING_TO_SERVER: 'A ligar ao servidor...',
        SERVER_OFFLINE: 'Servidor está desligado!',
        USER_IS_TYPING: 'A escrever...',
        UPLOADING_FILE: 'Anexando ficheiro',
        ERROR_UPLOADING_FILE: 'Erro ao anexar ficheiro!',
        ATTACH_FILE: 'Anexar um ficheiro',
        USER_OFFLINE: 'Parece que a internet foi abaixo!',
        USER_ONLINE: 'Estamos de volta!',
        MUTE: 'Silenciar conversa',
        CLOSE: 'Fechar conversa',
        MINIMIZE: 'Minimizar conversa',
        TITLE: 'Suporte',
        POWERED_BY: 'Desenvolvido por  Prud.io'
    },
    de: {
        CHAT_WITH_US: 'Chatten Sie mit uns',
        NAME: 'Name',
        EMAIL: 'E-Mail',
        START_CONVERSATION: 'Starten Sie einen Chat',
        NEW_MESSAGE: 'Neue Nachricht',
        NO_USERS_ONLINE: 'Zur Zeit ist niemand online um Ihnen zu helfen. Hinterlassen Sie eine Nachricht und wir melden uns sobald wie möglich bei Ihnen.',
        CONVERSATION_HISTORY: 'Nachrichtenverlauf',
        JUST_WRITE: 'Hier schreiben...',
        PROBLEM_CONNECTING_TO_SERVER: 'Die Verbindung zum Server ist fehlgeschlagen.',
        ERROR_FILL_ALL_FIELDS: 'Bitte füllen Sie die Felder mit einem Namen und einer gültigen E-Mail Adresse aus.',
        CONNECTING_TO_SERVER: 'Verbinde zum Server...',
        SERVER_OFFLINE: 'Server ist offline.',
        USER_IS_TYPING: 'Benutzer schreibt...',
        UPLOADING_FILE: 'Datei wird hochgeladen',
        ERROR_UPLOADING_FILE: 'Das Hochladen ist fehlgeschlagen',
        ATTACH_FILE: 'Datei hochladen',
        USER_OFFLINE: 'Keine Internetverbindung',
        USER_ONLINE: 'Internetverbindung wieder vorhanden',
        MUTE: 'Chat stummschalten',
        CLOSE: 'Chat schliessen',
        MINIMIZE: 'Chat minimieren',
        TITLE: 'Support',
        POWERED_BY: ' Prud.io'
    },
    es: {
        CHAT_WITH_US: 'Habla con nosotros',
        NAME: 'Nombre',
        EMAIL: 'E-mail',
        START_CONVERSATION: 'Iniciar una conversación',
        NEW_MESSAGE: 'Nuevo mensaje',
        NO_USERS_ONLINE: 'Perdon! Actualmente no hay miembros en línea para ayudarle. Deja un mensaje y trataremos de ponernos en contacto lo antes posible!',
        CONVERSATION_HISTORY: 'Historial de la conversación',
        JUST_WRITE: 'Escriba aqui...',
        PROBLEM_CONNECTING_TO_SERVER: 'Hubo un problema al conectar con el servidor!',
        ERROR_FILL_ALL_FIELDS: 'Por favor, rellene los campos con un nombre y una dirección de correo electrónico válida.',
        CONNECTING_TO_SERVER: 'Conectando con el servidor...',
        SERVER_OFFLINE: 'Servidor está apagado!',
        USER_IS_TYPING: 'El usuario está escribiendo...',
        UPLOADING_FILE: 'Enviando fichero',
        ERROR_UPLOADING_FILE: 'Error al adjuntar fichero!',
        ATTACH_FILE: 'Adjuntar un fichero',
        USER_OFFLINE: 'La internet se ha ido',
        USER_ONLINE: 'Estamos de vuelta!',
        MUTE: 'Silenciar conversación',
        CLOSE: 'Cerrar conversación',
        MINIMIZE: 'Minimizar conversación',
        TITLE: 'Soporte',
        POWERED_BY: 'Desarrollado por  Prud.io'
    },
    fr: {
        CHAT_WITH_US: 'Chattez avec nous',
        NAME: 'Nom',
        EMAIL: 'E-mail',
        START_CONVERSATION: 'Démarrez une conversation',
        NEW_MESSAGE: 'Nouveau message',
        NO_USERS_ONLINE: 'Désolé! Actuellement aucun membre en ligne pour vous aider. laissez un message et nous reviendrons vers vous dès que possible!',
        CONVERSATION_HISTORY: 'L\'historique des conversations',
        JUST_WRITE: 'Écrivez ici ...',
        PROBLEM_CONNECTING_TO_SERVER: 'Problème de connexion au serveur!',
        ERROR_FILL_ALL_FIELDS: 'S\'il vous plaît remplir les champs avec un nom et une adresse email valide.',
        CONNECTING_TO_SERVER: 'Connexion au serveur...',
        SERVER_OFFLINE: 'Server est hors ligne!',
        USER_IS_TYPING: 'l\'utilisateur est en train de taper...',
        UPLOADING_FILE: 'Envoi de fichier',
        ERROR_UPLOADING_FILE: 'Une erreur est survenue durant l\'envoi du fichier!',
        ATTACH_FILE: 'Joindre un fichier',
        USER_OFFLINE: 'Pas de connexion internet',
        USER_ONLINE: 'Nous sommes de retour!',
        MUTE: 'Mettre en sourdine',
        CLOSE: 'Fermer la conversation',
        MINIMIZE: 'Réduire la conversation',
        TITLE: 'Soutien',
        POWERED_BY: 'Propulsé par  Prud.io'
    },
    tr: {
        CHAT_WITH_US: 'Bizimle Konuşun',
        NAME: 'Ad',
        EMAIL: 'E-posta',
        START_CONVERSATION: 'Görüşme başlat',
        NEW_MESSAGE: 'Yeni mesaj',
        NO_USERS_ONLINE: 'Şu anda size yardımcı olabilecek çevrimiçi kullanıcı mevcut değil. Lütfen bir mesaj bırakın, size en kısa zamanda dönüş yapacağız. Üzgünüz.',
        CONVERSATION_HISTORY: 'Görüşme Tarihçesi',
        JUST_WRITE: 'Buraya yazın...',
        PROBLEM_CONNECTING_TO_SERVER: 'Sunucuya bağlanırken bir sorun oluştu!',
        ERROR_FILL_ALL_FIELDS: 'Lütfen tüm alanları geçerli bir isim ve e-posta ile doldurun.',
        CONNECTING_TO_SERVER: 'Sunucuya bağlanılıyor...',
        SERVER_OFFLINE: 'Sunucu şu anda çevrimdışı!',
        USER_IS_TYPING: 'Kullanıcı yazıyor...',
        UPLOADING_FILE: 'Dosya sunucuya yükleniyor',
        ERROR_UPLOADING_FILE: 'Sunucuya dosya yüklenirken hata oluştu!',
        ATTACH_FILE: 'Dosya Ekle',
        USER_OFFLINE: 'Görünüşe göre internet gitti!',
        USER_ONLINE: 'Geri geldik!',
        MUTE: 'Görüşmeyi sessize al',
        CLOSE: 'Görüşmeyi kapat',
        MINIMIZE: 'Görüşmeyi aşağıya indir',
        TITLE: 'Destek',
        POWERED_BY: ' Prud.io ile çalışmaktadır.'
    },
    ro: {
        CHAT_WITH_US: 'Discută cu noi',
        NAME: 'Nume',
        EMAIL: 'E-mail',
        START_CONVERSATION: 'Pornește conversație',
        NEW_MESSAGE: 'Mesaj Nou',
        NO_USERS_ONLINE: 'Momentan nu este online nici un utilizator care să te ajute. Lasă un mesaj și te vom contacta în curând!',
        CONVERSATION_HISTORY: 'Istoric Conversații',
        JUST_WRITE: 'Scrie aici...',
        PROBLEM_CONNECTING_TO_SERVER: 'A apărut o eroare de conectare la server!',
        ERROR_FILL_ALL_FIELDS: 'Completati câmpurile cu name și email valide.',
        CONNECTING_TO_SERVER: 'Se conectează la server...',
        SERVER_OFFLINE: 'Serverul nu este disponibil!',
        USER_IS_TYPING: 'Utilizatorul scrie...',
        UPLOADING_FILE: 'Încărcare fișier',
        ERROR_UPLOADING_FILE: 'Eroare de încărcare a fișierului!',
        ATTACH_FILE: ' Atașază un fișier',
        USER_OFFLINE: 'Conexiune la Internet indisponibilă!',
        USER_ONLINE: 'Ne-am întors!',
        MUTE: 'Fără Sonor',
        CLOSE: 'Închide conversația',
        MINIMIZE: 'Minimizează conversația',
        TITLE: 'Asistență',
        POWERED_BY: 'Dezvoltat de  Prud.io'
    }
};
<|endoftext|>


<commit_before>/**
 * Created by Islam on 11.12.2016.
 */

module.exports = function drawReact(canvas, x, y, w, h, params){
	var ctx = canvas.getContext('2d');

	ctx.save();

	if(params.fillStyle){
		ctx.fillStyle = params.fillStyle;
		ctx.fillRect(x, y, w, h);
	}

	if(params.lineWidth !== 0){
		ctx.lineWidth = params.lineWidth || 2;
		ctx.strokeStyle = params.strokeStyle || "white";
		ctx.strokeRect(x, y, w, h);
	}

	ctx.restore();
};<commit_msg>fix drawRect<commit_after>/**
 * Created by Islam on 11.12.2016.
 */

module.exports = function drawReact(canvas, x, y, w, h, params){
	var ctx = canvas.getContext('2d');
	params = params || {};

	ctx.save();

	if(params.fillStyle){
		ctx.fillStyle = params.fillStyle;
		ctx.fillRect(x, y, w, h);
	}

	if(params.lineWidth !== 0){
		ctx.lineWidth = params.lineWidth || 2;
		ctx.strokeStyle = params.strokeStyle || "white";
		ctx.strokeRect(x, y, w, h);
	}

	ctx.restore();
};<|endoftext|>


<commit_before>// Depending on the exact usage, QUnit could be in one of several places, this
// function handles finding it.
module.exports = function requireQUnit( resolve = require.resolve ) {
	try {

		// First we attempt to find QUnit relative to the current working directory.
		const localQUnitPath = resolve( "qunit", { paths: [ process.cwd() ] } );
		delete require.cache[ localQUnitPath ];
		return require( localQUnitPath );
	} catch ( e ) {
		try {

			// Second, we use the globally installed QUnit
			delete require.cache[ resolve( "../../qunit/qunit" ) ];
			// eslint-disable-next-line node/no-missing-require, node/no-unpublished-require
			return require( "../../qunit/qunit" );
		} catch ( e ) {
			if ( e.code === "MODULE_NOT_FOUND" ) {

				// Finally, we use the local development version of QUnit
				delete require.cache[ resolve( "../../dist/qunit" ) ];
				// eslint-disable-next-line node/no-missing-require, node/no-unpublished-require
				return require( "../../dist/qunit" );
			}

			throw e;
		}
	}
};
<commit_msg>CLI: Fix 'qunit' require error on Node 10 if qunit.json exists<commit_after>// Depending on the exact usage, QUnit could be in one of several places, this
// function handles finding it.
module.exports = function requireQUnit( resolve = require.resolve ) {
	try {

		// First we attempt to find QUnit relative to the current working directory.
		const localQUnitPath = resolve( "qunit", {

			// Support: Node 10. Explicitly check "node_modules" to avoid a bug.
			// Fixed in Node 12+. See https://github.com/nodejs/node/issues/35367.
			paths: [ process.cwd() + "/node_modules", process.cwd() ]
		} );
		delete require.cache[ localQUnitPath ];
		return require( localQUnitPath );
	} catch ( e ) {
		try {

			// Second, we use the globally installed QUnit
			delete require.cache[ resolve( "../../qunit/qunit" ) ];
			// eslint-disable-next-line node/no-missing-require, node/no-unpublished-require
			return require( "../../qunit/qunit" );
		} catch ( e ) {
			if ( e.code === "MODULE_NOT_FOUND" ) {

				// Finally, we use the local development version of QUnit
				delete require.cache[ resolve( "../../dist/qunit" ) ];
				// eslint-disable-next-line node/no-missing-require, node/no-unpublished-require
				return require( "../../dist/qunit" );
			}

			throw e;
		}
	}
};
<|endoftext|>


<commit_before>/**
 * Created by chengfulin on 2015/4/13.
 */
/// TODO: currently, we only care about where a variable is defined and where it's used, which means we do not need to know what kind or which definition the variable has.
/// TODO: also, as a static analysis tool, we cannot handle dynamic or semantic issues yet (e.g., object property, array element, object reference)
var walkes = require('walkes'),
    Set = require('../analyses').Set,
    Def = require('./def'),
    Scope = require('./scope'),
    Range = require('./range'),
    varDefFactory = require('./vardeffactory'),
    defFactory = require('./deffactory'),
    Map = require('core-js/es6/map');

/**
 * Get KILL set
 * @param cfgNode
 * @param cfgWrapper
 * @returns Set of variable whose definition was redefined in this node
 * @constructor
 */
module.exports.KILL = function (cfgNode, cfgWrapper) {
    'use strict';
    var variables = new Set();
    walkes(cfgNode.astNode, {
        AssignmentExpression: function (node, recurse) {
            var killedVar = cfgWrapper.getVarByName(node.left.name);
            if (!!killedVar) {
                variables.add(killedVar);
            }
            if (node.right.type === 'AssignmentExpression') {/// Sequential assignment
                recurse(node.right);
            }
        },
        UpdateExpression: function (node) {
            var killedVar = cfgWrapper.getVarByName(node.argument.name);
            if (!!killedVar) {
                variables.add(killedVar);
            }
        }
    });
    return variables;
};

/**
 * Get GEN set
 * @param cfgNode
 * @param cfgWrapper
 * @returns {Map}
 * @constructor
 */
module.exports.GEN = function (cfgNode, cfgWrapper) {
    'use strict';
    var generatedVarDef = new Set(),
        sameDefVars = new Set();
    walkes(cfgNode.astNode, {
        AssignmentExpression: function (node, recurse) {
            var definedVar = cfgWrapper.getVarByName(node.left.name);
            if (!!definedVar) {
                sameDefVars.add(definedVar);
                if (node.right.type === 'AssignmentExpression') {
                    recurse(node.right);
                } else {
                    sameDefVars.forEach(function (defined) {
                        generatedVarDef.add(
                            varDefFactory.create(
                                defined,
                                defFactory.create(
                                    cfgNode.cfgId,
                                    Def.LITERAL_TYPE,
                                    node.right.range,
                                    cfgWrapper.getScope()
                                )
                            )
                        );
                    });
                    sameDefVars = new Set();
                }
            }
        },
        UpdateExpression: function (node) {
            var definedVar = cfgWrapper.getVarByName(node.argument.name);
            if (!!definedVar) {
                generatedVarDef.add(
                    varDefFactory.create(
                        definedVar,
                        defFactory.create(
                            cfgNode.cfgId,
                            Def.LITERAL_TYPE,
                            node.range,
                            cfgWrapper.getScope()
                        )
                    )
                );
            }
        },
        VariableDeclaration: function (node, recurse) {
            node.declarations.forEach(function (declarator) {
                recurse(declarator);
            });
        },
        VariableDeclarator: function (node, recurse) {
            var definedVar = cfgWrapper.getVarByName(node.id.name);
            if (!!definedVar) {
                sameDefVars.add(definedVar);
                if (!!node.init) {
                    if (node.init.type === 'AssignmentExpression') {
                        recurse(node.init);
                    } else {
                        generatedVarDef.add(
                            varDefFactory.create(
                                definedVar,
                                defFactory.create(
                                    cfgNode.cfgId,
                                    Def.LITERAL_TYPE,
                                    node.init.range,
                                    cfgWrapper.getScope()
                                )
                            )
                        );
                    }
                }
            }
        }
    });
    return generatedVarDef;
};

/**
 * Get used variables at the node
 * @param cfgNode a node of CFG
 * @param cfgWrapper
 * @constructor
 * @returns Set of variable names used at this node
 */
module.exports.USE = function (cfgNode, cfgWrapper) {
    'use strict';
    var cuseVars = new Set(),
        puseVars = new Set(),
        isPUse = false;
    walkes(cfgNode.astNode, {
        AssignmentExpression: function (node, recurse) {
            if (node.right.type === 'AssignmentExpression') {
                /// handle sequential assignment
                recurse(node.right.left);
            }
            recurse(node.right);
        },
        BinaryExpression: function (node, recurse) {
            /// Both operand are used
            if (!!cfgNode.true && !!cfgNode.false) {
                isPUse = true;
            }
            recurse(node.left);
            recurse(node.right);
            isPUse = false;
        },
        CallExpression: function (node, recurse) {
            if (!!cfgNode.true && !!cfgNode.false) {
                isPUse = true;
            }
            recurse(node.callee);
            /// for the function arguments
            node.arguments.forEach(recurse);
            isPUse = false;
        },
        VariableDeclaration: function (node, recurse) {
            node.declarations.forEach(recurse);
        },
        VariableDeclarator: function (node, recurse) {
            if (!!node.init && node.init.type === 'AssignmentExpression') {
                /// e.g., var answer = var1 = var2;
                /// USE = {var1, var2}
                recurse(node.init.left);
            }
            recurse(node.init);
        },
        UpdateExpression: function (node, recurse) {
            recurse(node.argument);
        },
        NewExpression: function (node, recurse) {
            recurse(node.callee);
        },
        UnaryExpression: function (node, recurse) {
            if (!!cfgNode.true && !!cfgNode.false) {
                isPUse = true;
            }
            recurse(node.argument);
            isPUse = false;
        },
        SwitchCase: function (node, recurse) {
            isPUse = true;
            /// handle expression in switch statement
            if (!!node.test && !!cfgNode.parent && cfgNode.parent.type === 'SwitchStatement') {
                recurse(cfgNode.parent.discriminant);
            }
        },
        ConditionalExpression: function (node, recurse) {
            isPUse = true;
            recurse(node.test);
            isPUse = false;
            recurse(node.consequent);
            recurse(node.alternate);
        },
        Identifier: function (node) {
            /// Ignore statement with identifier only
            if (cfgNode.astNode.type !== 'Identifier') {
                var usedVar = cfgWrapper.getVarByName(node.name);
                if (!!usedVar) {
                    if (!isPUse) {
                        cuseVars.add(usedVar);
                    } else {
                        puseVars.add(usedVar);
                    }
                }
            }
        }
    });
    return {cuse: cuseVars, puse: puseVars};
};<commit_msg>Fix the bug of switch case<commit_after>/**
 * Created by chengfulin on 2015/4/13.
 */
/// TODO: currently, we only care about where a variable is defined and where it's used, which means we do not need to know what kind or which definition the variable has.
/// TODO: also, as a static analysis tool, we cannot handle dynamic or semantic issues yet (e.g., object property, array element, object reference)
var walkes = require('walkes'),
    Set = require('../analyses').Set,
    Def = require('./def'),
    Scope = require('./scope'),
    Range = require('./range'),
    varDefFactory = require('./vardeffactory'),
    defFactory = require('./deffactory'),
    Map = require('core-js/es6/map');

/**
 * Get KILL set
 * @param cfgNode
 * @param cfgWrapper
 * @returns Set of variable whose definition was redefined in this node
 * @constructor
 */
module.exports.KILL = function (cfgNode, cfgWrapper) {
    'use strict';
    var variables = new Set();
    walkes(cfgNode.astNode, {
        AssignmentExpression: function (node, recurse) {
            var killedVar = cfgWrapper.getVarByName(node.left.name);
            if (!!killedVar) {
                variables.add(killedVar);
            }
            if (node.right.type === 'AssignmentExpression') {/// Sequential assignment
                recurse(node.right);
            }
        },
        UpdateExpression: function (node) {
            var killedVar = cfgWrapper.getVarByName(node.argument.name);
            if (!!killedVar) {
                variables.add(killedVar);
            }
        },
        SwitchCase: function () {}
    });
    return variables;
};

/**
 * Get GEN set
 * @param cfgNode
 * @param cfgWrapper
 * @returns {Map}
 * @constructor
 */
module.exports.GEN = function (cfgNode, cfgWrapper) {
    'use strict';
    var generatedVarDef = new Set(),
        sameDefVars = new Set();
    walkes(cfgNode.astNode, {
        AssignmentExpression: function (node, recurse) {
            var definedVar = cfgWrapper.getVarByName(node.left.name);
            if (!!definedVar) {
                sameDefVars.add(definedVar);
                if (node.right.type === 'AssignmentExpression') {
                    recurse(node.right);
                } else {
                    sameDefVars.forEach(function (defined) {
                        generatedVarDef.add(
                            varDefFactory.create(
                                defined,
                                defFactory.create(
                                    cfgNode.cfgId,
                                    Def.LITERAL_TYPE,
                                    node.right.range,
                                    cfgWrapper.getScope()
                                )
                            )
                        );
                    });
                    sameDefVars = new Set();
                }
            }
        },
        UpdateExpression: function (node) {
            var definedVar = cfgWrapper.getVarByName(node.argument.name);
            if (!!definedVar) {
                generatedVarDef.add(
                    varDefFactory.create(
                        definedVar,
                        defFactory.create(
                            cfgNode.cfgId,
                            Def.LITERAL_TYPE,
                            node.range,
                            cfgWrapper.getScope()
                        )
                    )
                );
            }
        },
        VariableDeclaration: function (node, recurse) {
            node.declarations.forEach(function (declarator) {
                recurse(declarator);
            });
        },
        VariableDeclarator: function (node, recurse) {
            var definedVar = cfgWrapper.getVarByName(node.id.name);
            if (!!definedVar) {
                sameDefVars.add(definedVar);
                if (!!node.init) {
                    if (node.init.type === 'AssignmentExpression') {
                        recurse(node.init);
                    } else {
                        generatedVarDef.add(
                            varDefFactory.create(
                                definedVar,
                                defFactory.create(
                                    cfgNode.cfgId,
                                    Def.LITERAL_TYPE,
                                    node.init.range,
                                    cfgWrapper.getScope()
                                )
                            )
                        );
                    }
                }
            }
        },
        SwitchCase: function () {}
    });
    return generatedVarDef;
};

/**
 * Get used variables at the node
 * @param cfgNode a node of CFG
 * @param cfgWrapper
 * @constructor
 * @returns Set of variable names used at this node
 */
module.exports.USE = function (cfgNode, cfgWrapper) {
    'use strict';
    var cuseVars = new Set(),
        puseVars = new Set(),
        isPUse = false;
    walkes(cfgNode.astNode, {
        AssignmentExpression: function (node, recurse) {
            if (node.right.type === 'AssignmentExpression') {
                /// handle sequential assignment
                recurse(node.right.left);
            } else {
                var selfAssignmentOp = ['+=', '-=', '*=', '/=', '%='];
                if (selfAssignmentOp.indexOf(node.operator) !== -1) {
                    recurse(node.left);
                }
            }
            recurse(node.right);
        },
        BinaryExpression: function (node, recurse) {
            /// Both operand are used
            if (!!cfgNode.true && !!cfgNode.false) {
                isPUse = true;
            }
            recurse(node.left);
            recurse(node.right);
            isPUse = false;
        },
        CallExpression: function (node, recurse) {
            if (!!cfgNode.true && !!cfgNode.false) {
                isPUse = true;
            }
            recurse(node.callee);
            /// for the function arguments
            node.arguments.forEach(recurse);
            isPUse = false;
        },
        VariableDeclaration: function (node, recurse) {
            node.declarations.forEach(recurse);
        },
        VariableDeclarator: function (node, recurse) {
            if (!!node.init && node.init.type === 'AssignmentExpression') {
                /// e.g., var answer = var1 = var2;
                /// USE = {var1, var2}
                recurse(node.init.left);
            }
            recurse(node.init);
        },
        UpdateExpression: function (node, recurse) {
            recurse(node.argument);
        },
        NewExpression: function (node, recurse) {
            recurse(node.callee);
        },
        UnaryExpression: function (node, recurse) {
            if (!!cfgNode.true && !!cfgNode.false) {
                isPUse = true;
            }
            recurse(node.argument);
            isPUse = false;
        },
        SwitchCase: function (node, recurse) {
            isPUse = true;
            /// handle expression in switch statement
            if (!!node.test && !!cfgNode.parent && cfgNode.parent.type === 'SwitchStatement') {
                recurse(cfgNode.parent.discriminant);
            }
        },
        ConditionalExpression: function (node, recurse) {
            isPUse = true;
            recurse(node.test);
            isPUse = false;
            recurse(node.consequent);
            recurse(node.alternate);
        },
        Identifier: function (node) {
            /// Ignore statement with identifier only
            if (cfgNode.astNode.type !== 'Identifier') {
                var usedVar = cfgWrapper.getVarByName(node.name);
                if (!!usedVar) {
                    if (!isPUse) {
                        cuseVars.add(usedVar);
                    } else {
                        puseVars.add(usedVar);
                    }
                }
            }
        }
    });
    return {cuse: cuseVars, puse: puseVars};
};<|endoftext|>


<commit_before>var fs = require('fs'),
    jsdom = require('jsdom'),
    addScript = require('./test_util').addScript;

function dump_nodes(window) {
    var nodes = window.force.nodes();
    for(var i = 0 ; i < nodes.length; ++i) {
        console.log('nodes[' + nodes[i].id + '/' + nodes[i].type + '].[xy] = (' + nodes[i].x + ',' + nodes[i].y + ')');
    }
}

function dump_graphviz(force) {
    var i;
    var nodes = force.nodes();
    var links = force.links();
    var q = function(s) {
        if (s.search(' ') == -1) {
            return s;
        }
        return '"' + s + '"';
    };

    console.log('digraph {');
    for (i = 0 ; i < nodes.length; ++i) {
        if (nodes[i].type == 'bubble') {
            console.log(' BUBBLE;');
        } else {
            console.log(' ' + q(nodes[i].name) + ';');
        }
    }
    for (i = 0 ; i < links.length; ++i) {
        var link = links[i];
        console.log(' ' + q(link.__src.name) + ' -> ' + q(link.__dst.name) + ' [label=' + link.name + '];');
    }
    console.log('}');
}

function run_tests(settings) {
    var document = jsdom.jsdom('');
    var window = document.parentWindow;

    window.console.log = console.log; // slightly evil
    window.process = process; // more evil
    window.is_node = true;
    if (settings.created) {
        settings.created(undefined, window);
    }
    debugger
    addScript(window, '../src/external/require.js')
        .load_next('../src/app.js')
        .done(function () {
            console.log('test harness: starting script loading with requirejs');
            window.require.config(window.rhizi_require_config);
            window.requirejs(['main'], function(main) {
                console.log('test harness: main loaded');
                main.main();
                if (settings.done) {
                    settings.done(undefined, window);
                }
                process.quit();
            });
        });
    //window.setInterval(function() { console.log('.'); return true; }, 100);
}

function reset(window) {
    window.require('rz_core').graph.clear();
}

function nodes(window) {
    return window.require('rz_core').force.nodes().map(function (n) {
        return n.name;
    });
}

function links(window) {
    return window.require('rz_core').force.links().map(function (l) {
        debugger;
        return [l.__src.name, l.__dst.name, l.name];
    });
}

exports.run_tests = run_tests;
exports.dump_graphviz = dump_graphviz;
exports.reset = reset;
exports.links = links;
exports.nodes = nodes;
<commit_msg>client-tests: small change, not working yet (i.e. still broken)<commit_after>var fs = require('fs'),
    jsdom = require('jsdom'),
    addScript = require('./test_util').addScript;

function dump_nodes(window) {
    var nodes = window.force.nodes();
    for(var i = 0 ; i < nodes.length; ++i) {
        console.log('nodes[' + nodes[i].id + '/' + nodes[i].type + '].[xy] = (' + nodes[i].x + ',' + nodes[i].y + ')');
    }
}

function dump_graphviz(force) {
    var i;
    var nodes = force.nodes();
    var links = force.links();
    var q = function(s) {
        if (s.search(' ') == -1) {
            return s;
        }
        return '"' + s + '"';
    };

    console.log('digraph {');
    for (i = 0 ; i < nodes.length; ++i) {
        if (nodes[i].type == 'bubble') {
            console.log(' BUBBLE;');
        } else {
            console.log(' ' + q(nodes[i].name) + ';');
        }
    }
    for (i = 0 ; i < links.length; ++i) {
        var link = links[i];
        console.log(' ' + q(link.__src.name) + ' -> ' + q(link.__dst.name) + ' [label=' + link.name + '];');
    }
    console.log('}');
}

function run_tests(settings) {
    var document = jsdom.jsdom('');
    var window = document.parentWindow;

    window.console.log = console.log; // slightly evil
    window.process = process; // more evil
    window.is_node = true;
    if (settings.created) {
        settings.created(undefined, window);
    }
    debugger
    addScript(window, '../client/require.js')
        .load_next('../client/app.js')
        .done(function () {
            console.log('test harness: starting script loading with requirejs');
            console.dir(window.require);
            window.require.config(window.rhizi_require_config);
            window.requirejs(['main'], function(main) {
                console.log('test harness: main loaded');
                main.main();
                if (settings.done) {
                    settings.done(undefined, window);
                }
                process.quit();
            });
        });
    //window.setInterval(function() { console.log('.'); return true; }, 100);
}

function reset(window) {
    window.require('rz_core').graph.clear();
}

function nodes(window) {
    return window.require('rz_core').force.nodes().map(function (n) {
        return n.name;
    });
}

function links(window) {
    return window.require('rz_core').force.links().map(function (l) {
        debugger;
        return [l.__src.name, l.__dst.name, l.name];
    });
}

exports.run_tests = run_tests;
exports.dump_graphviz = dump_graphviz;
exports.reset = reset;
exports.links = links;
exports.nodes = nodes;
<|endoftext|>


<commit_before>// Get Parameters from some url
var getUrlParameter = function getUrlParameter(sPageURL) {
    var url = sPageURL.split('?');
    var obj = {};
    if (url.length == 2) {
      var sURLVariables = url[1].split('&'),
          sParameterName,
          i;
      for (i = 0; i < sURLVariables.length; i++) {
          sParameterName = sURLVariables[i].split('=');
          obj[sParameterName[0]] = sParameterName[1];
      }
      return obj;
    } else {
      return undefined;
    }
};

// Execute actions on images generated from Markdown pages
var images = $("div#body-inner img").not(".inline");
// Wrap image inside a featherlight (to get a full size view in a popup)
images.wrap(function(){
  var image =$(this);
  if (!image.parent("a").length) {
    return "";
  }
});

// Change styles, depending on parameters set to the image
images.each(function(index){
  var image = $(this)
  var o = getUrlParameter(image[0].src);
  if (typeof o !== "undefined") {
    var h = o["height"];
    var w = o["width"];
    var c = o["classes"];
    image.css("width", function() {
      if (typeof w !== "undefined") {
        return w;
      } else {
        return "auto";
      }
    });
    image.css("height", function() {
      if (typeof h !== "undefined") {
        return h;
      } else {
        return "auto";
      }
    });
    if (typeof c !== "undefined") {
      var classes = c.split(',');
      for (i = 0; i < classes.length; i++) {
        image.addClass(classes[i]);
      }
    }
  }
});

// Stick the top to the top of the screen when  scrolling
$(document).ready(function(){
  $("#top-bar").sticky({topSpacing:0, zIndex: 1000});
});

jQuery(document).ready(function() {
  // Add link button for every
  var text, clip = new Clipboard('.anchor');
  $("h1~h2,h1~h3,h1~h4,h1~h5,h1~h6").append(function(index, html){
    var element = $(this);
    var url = document.location.origin + document.location.pathname;
    var link = url + "#"+element[0].id;
    return " " +
      "" +
      ""
    ;
  });

  $(".anchor").on('mouseleave', function(e) {
    $(this).attr('aria-label', null).removeClass('tooltipped tooltipped-s tooltipped-w');
  });

  clip.on('success', function(e) {
      e.clearSelection();
      $(e.trigger).attr('aria-label', 'Link copied to clipboard!').addClass('tooltipped tooltipped-s');
  });

});

// append the content to https://github.com/apache/incubator-shardingsphere-doc/blob/master/document/current/themes/hugo-theme-learn/static/js/learn.js
// Let menu of document collapsible
jQuery(document).ready(function(){
    $("#sidebar .topics ul").hide();
    $("#sidebar .topics .active").show().parentsUntil(".topics").show();
    $("#sidebar .topics li" ).each(function(){
          var that=$(this);
          if(that.children("ul").size()){
    	      that.children("a").prop("href","javascript:void(0)")
          }
    });
    $("#sidebar .topics li").click(function(event){
        event.stopPropagation();
        var that=$(this);
        that.children("ul").toggle();
    });
});
<commit_msg>revert ##323 because the collapsible is conflict with show page original content<commit_after>// Get Parameters from some url
var getUrlParameter = function getUrlParameter(sPageURL) {
    var url = sPageURL.split('?');
    var obj = {};
    if (url.length == 2) {
      var sURLVariables = url[1].split('&'),
          sParameterName,
          i;
      for (i = 0; i < sURLVariables.length; i++) {
          sParameterName = sURLVariables[i].split('=');
          obj[sParameterName[0]] = sParameterName[1];
      }
      return obj;
    } else {
      return undefined;
    }
};

// Execute actions on images generated from Markdown pages
var images = $("div#body-inner img").not(".inline");
// Wrap image inside a featherlight (to get a full size view in a popup)
images.wrap(function(){
  var image =$(this);
  if (!image.parent("a").length) {
    return "";
  }
});

// Change styles, depending on parameters set to the image
images.each(function(index){
  var image = $(this)
  var o = getUrlParameter(image[0].src);
  if (typeof o !== "undefined") {
    var h = o["height"];
    var w = o["width"];
    var c = o["classes"];
    image.css("width", function() {
      if (typeof w !== "undefined") {
        return w;
      } else {
        return "auto";
      }
    });
    image.css("height", function() {
      if (typeof h !== "undefined") {
        return h;
      } else {
        return "auto";
      }
    });
    if (typeof c !== "undefined") {
      var classes = c.split(',');
      for (i = 0; i < classes.length; i++) {
        image.addClass(classes[i]);
      }
    }
  }
});

// Stick the top to the top of the screen when  scrolling
$(document).ready(function(){
  $("#top-bar").sticky({topSpacing:0, zIndex: 1000});
});

jQuery(document).ready(function() {
  // Add link button for every
  var text, clip = new Clipboard('.anchor');
  $("h1~h2,h1~h3,h1~h4,h1~h5,h1~h6").append(function(index, html){
    var element = $(this);
    var url = document.location.origin + document.location.pathname;
    var link = url + "#"+element[0].id;
    return " " +
      "" +
      ""
    ;
  });

  $(".anchor").on('mouseleave', function(e) {
    $(this).attr('aria-label', null).removeClass('tooltipped tooltipped-s tooltipped-w');
  });

  clip.on('success', function(e) {
      e.clearSelection();
      $(e.trigger).attr('aria-label', 'Link copied to clipboard!').addClass('tooltipped tooltipped-s');
  });

});
<|endoftext|>


<commit_before>var AWS = require('aws-sdk')
var $db
var $lastQuery = null;

module.exports = function config ( $config ) {
	if ($config)
		AWS.config.update($config)

	this.client = $db = new AWS.DynamoDB()

	this.table = function( $tableName ) {
		var $ddb = new DynamoDB()

		$ddb.table($tableName)
		return $ddb
	}
	this.getClient = function() {
		return this.client
	}

	this.getLastQuery = function() {
		return $lastQuery
	}

	return this
}

function DynamoDB() {
	var $this = this
	this.select = []
	this.whereKey = {}
	this.whereOther = {}
	this.limit_value = null
	this.index = null
	this.direction = null
	this.LastEvaluatedKey = null
	this.ExclusiveStartKey = null
	this.ConsistentRead = false

	this.table = function($tableName) {
		this.table = $tableName;
		return this;
	}

	this.select = function() {
		this.select = []

		for (var i = 0; i < arguments.length; i++)
			this.select.push(arguments[i])

		return this;
	}

	this.addSelect = function($field) {
		this.select.push($field)
		return this
	}

	this.consistentRead = function( $value ) {
		if ($value === undefined ) {
			this.ConsistentRead = true
			return this
		}

		if ($value)
			this.ConsistentRead = true
		else
			this.ConsistentRead = false

		return this
	}

	this.where = function($key,$value1,$value2) {
		if ($value2 === undefined) {
			this.whereKey[$key] = {'S' : $value1};

			if (typeof $value1 == "number")
				this.whereKey[$key] = {'N' : ($value1).toString() };

		} else {
			this.whereOther[$key] = {
				type: 'S',
				value: $value2,
				operator: $value1
			};
		}

		return this;
	}
	this.limit = function($limit) {
		this.limit_value = $limit;
		return this;
	}

	this.insert = function(item, callback) {
		$db.describeTable({
			TableName: this.table
		},function(err,data) {
			if (err)
				return callback(err, false)

			var $expected = {}
			for (var i in data.Table.KeySchema ) {
				$expected[data.Table.KeySchema[i].AttributeName ] = { Exists: false }
			}

			$db.putItem({
				TableName: $this.table,
				Item: $this.anormalizeItem(item),
				Expected: $expected
			}, function(err,data) {
				if (err)
					return callback(err, false)

				callback( err, data )
			})
		})
	}

	this.update = function($attrz, callback, $action ) {
		$db.describeTable({
			TableName: this.table
		},function(err,data) {
			if (err)
				return callback(err, false)

			var $expected = {}
			for (var i in data.Table.KeySchema )
				$expected[ data.Table.KeySchema[i].AttributeName ] = {
					Exists: true,
					Value: $this.whereKey[ data.Table.KeySchema[i].AttributeName ]
				}

			$to_update = {}
			for (var $k in $attrz) {
				if ($attrz.hasOwnProperty($k)) {
					var $type = 'S';
					if (typeof $attrz[$k] == 'number')
						$type = 'N';
				}
				$to_update[$k] = { Action: $action ? $action : 'PUT' }
				$to_update[$k]['Value'] = {}
				$to_update[$k]['Value'][$type] = $attrz[$k].toString()
			}
			var thisQuery = {
				TableName: $this.table,
				Key: $this.whereKey,
				AttributeUpdates : $to_update,
				Expected: $expected
			}
			$lastQuery = thisQuery
			$db.updateItem( thisQuery, function(err,data) {
				if (err)
					return callback(err, false)

				callback( err, data )
			})
		})
	}

	this.increment = function($attrz, callback ) {
		this.update($attrz, callback, 'ADD' )
	}

	this.delete = function($attrz, callback ) {
		if (typeof $attrz == 'function') {
			// delete entire item, $attrz is actually the callback
			$db.deleteItem({
				TableName: this.table,
				Key: this.whereKey
			}, function(err,data) {
				if (err)
					return $attrz(err, false)

				$attrz( err, data )
			})
		} else {
			// delete attributes
			$to_delete = {};
			for (var $i = 0; $i < $attrz.length;$i++) {
				$to_delete[$attrz[$i]] = {
					Action: 'DELETE'
				}
			}
			$db.updateItem({
				TableName: this.table,
				Key: this.whereKey,
				AttributeUpdates : $to_delete
			}, function(err,data) {
				if (err)
					return callback(err, false)

				callback( err, data )
			})
		}
	}

	this.get = function(callback) {
		var thisQuery = {
			TableName: this.table,
			Key: this.whereKey,
			ConsistentRead: this.ConsistentRead
		}

		if (this.select.length)
			thisQuery['AttributesToGet'] = this.select;

		$db.getItem( thisQuery, function(err,data) {
			if (err)
				return callback(err, false)

			callback(err, $this.normalizeItem(data.Item))
		})
	}

	this.query = function(callback) {

		var thisQuery = {
			TableName: this.table,
			KeyConditions: $this.anormalizeQuery(),
			ConsistentRead: this.ConsistentRead
		}
		if (this.limit_value !== null)
			thisQuery['Limit'] = this.limit_value;

		if (this.direction !== null) {
			if (this.direction == 'DESC')
				thisQuery['ScanIndexForward'] = false;
		}
		if ( this.index !== null )
			thisQuery['IndexName'] = this.index;

		if (this.select.length)
			thisQuery['AttributesToGet'] = this.select;

		if ( this.ExclusiveStartKey !== null )
			thisQuery['ExclusiveStartKey'] = this.ExclusiveStartKey;

		$lastQuery = thisQuery
		$db.query( thisQuery , function(err,data) {
			if (err)
				return callback(err, false)

			$this.LastEvaluatedKey = data.LastEvaluatedKey === undefined ? null : data.LastEvaluatedKey
			callback(err, $this.normalizeList(data.Items))
		})

		return this
	}

	// helper functions ...
	this.anormalizeQuery = function() {
		var anormal = {}
		for (var key in this.whereKey) {
			if (this.whereKey.hasOwnProperty(key)) {
					anormal[key] = {
						ComparisonOperator: 'EQ',
						AttributeValueList: [ this.whereKey[key] ]
					}
			}
		}
		for (var key in this.whereOther) {
			if (this.whereOther.hasOwnProperty(key)) {
					var whereVal = {}
					whereVal[this.whereOther[key].type] = this.whereOther[key].value;
					var type =
					anormal[key] = {
						ComparisonOperator: this.whereOther[key].operator,
						AttributeValueList: [ whereVal ]
					}
			}
		}
		return anormal;
	}

	this.anormalizeList = function(list) {
		var $ret = []
		for (var $i in list) {
			$ret.push(this.anormalizeItem(list[$i]))
		}
		return $ret;
	}

	this.anormalizeItem = function(item) {
		var anormal = {}
		for (var key in item) {
			if (item.hasOwnProperty(key)) {
					if (typeof item[key] == 'number') {
						anormal[key] = {'N' : item[key].toString() }
					}
					if (typeof item[key] == 'string') {
						anormal[key] = {'S' : item[key] }
					}
			}
		}
		return anormal;
	}

	this.normalizeList = function($items) {
		var $list = []
		for (var i in $items) {
			$list.push(this.normalizeItem($items[i]))
		}
		return $list;
	}
	this.normalizeItem = function($item) {
		var normal = {}
		for (var key in $item) {
			if ($item.hasOwnProperty(key)) {
				if ($item[key].hasOwnProperty('S'))
					normal[key] = $item[key]['S']

				if ($item[key].hasOwnProperty('N'))
					normal[key] = parseInt($item[key]['N'])
			}
		}
		return normal;
	}
}

<commit_msg>descending()<commit_after>var AWS = require('aws-sdk')
var $db
var $lastQuery = null;

module.exports = function config ( $config ) {
	if ($config)
		AWS.config.update($config)

	this.client = $db = new AWS.DynamoDB()

	this.table = function( $tableName ) {
		var $ddb = new DynamoDB()

		$ddb.table($tableName)
		return $ddb
	}
	this.getClient = function() {
		return this.client
	}

	this.getLastQuery = function() {
		return $lastQuery
	}

	return this
}

function DynamoDB() {
	var $this = this
	this.select = []
	this.whereKey = {}
	this.whereOther = {}
	this.limit_value = null
	this.IndexName = null
	this.ScanIndexForward = true
	this.LastEvaluatedKey = null
	this.ExclusiveStartKey = null
	this.ConsistentRead = false

	this.table = function($tableName) {
		this.table = $tableName;
		return this;
	}

	this.select = function() {
		this.select = []

		for (var i = 0; i < arguments.length; i++)
			this.select.push(arguments[i])

		return this;
	}

	this.addSelect = function($field) {
		this.select.push($field)
		return this
	}

	this.consistentRead = function( $value ) {
		if ($value === undefined ) {
			this.ConsistentRead = true
			return this
		}

		if ($value)
			this.ConsistentRead = true
		else
			this.ConsistentRead = false

		return this
	}

	this.descending = function( ) {
		this.ScanIndexForward = false
	}

	this.where = function($key,$value1,$value2) {
		if ($value2 === undefined) {
			this.whereKey[$key] = {'S' : $value1};

			if (typeof $value1 == "number")
				this.whereKey[$key] = {'N' : ($value1).toString() };

		} else {
			this.whereOther[$key] = {
				type: 'S',
				value: $value2,
				operator: $value1
			};
		}

		return this;
	}
	this.limit = function($limit) {
		this.limit_value = $limit;
		return this;
	}

	this.insert = function(item, callback) {
		$db.describeTable({
			TableName: this.table
		},function(err,data) {
			if (err)
				return callback(err, false)

			var $expected = {}
			for (var i in data.Table.KeySchema ) {
				$expected[data.Table.KeySchema[i].AttributeName ] = { Exists: false }
			}

			$db.putItem({
				TableName: $this.table,
				Item: $this.anormalizeItem(item),
				Expected: $expected
			}, function(err,data) {
				if (err)
					return callback(err, false)

				callback( err, data )
			})
		})
	}

	this.update = function($attrz, callback, $action ) {
		$db.describeTable({
			TableName: this.table
		},function(err,data) {
			if (err)
				return callback(err, false)

			var $expected = {}
			for (var i in data.Table.KeySchema )
				$expected[ data.Table.KeySchema[i].AttributeName ] = {
					Exists: true,
					Value: $this.whereKey[ data.Table.KeySchema[i].AttributeName ]
				}

			$to_update = {}
			for (var $k in $attrz) {
				if ($attrz.hasOwnProperty($k)) {
					var $type = 'S';
					if (typeof $attrz[$k] == 'number')
						$type = 'N';
				}
				$to_update[$k] = { Action: $action ? $action : 'PUT' }
				$to_update[$k]['Value'] = {}
				$to_update[$k]['Value'][$type] = $attrz[$k].toString()
			}
			var thisQuery = {
				TableName: $this.table,
				Key: $this.whereKey,
				AttributeUpdates : $to_update,
				Expected: $expected
			}
			$lastQuery = thisQuery
			$db.updateItem( thisQuery, function(err,data) {
				if (err)
					return callback(err, false)

				callback( err, data )
			})
		})
	}

	this.increment = function($attrz, callback ) {
		this.update($attrz, callback, 'ADD' )
	}

	this.delete = function($attrz, callback ) {
		if (typeof $attrz == 'function') {
			// delete entire item, $attrz is actually the callback
			$db.deleteItem({
				TableName: this.table,
				Key: this.whereKey
			}, function(err,data) {
				if (err)
					return $attrz(err, false)

				$attrz( err, data )
			})
		} else {
			// delete attributes
			$to_delete = {};
			for (var $i = 0; $i < $attrz.length;$i++) {
				$to_delete[$attrz[$i]] = {
					Action: 'DELETE'
				}
			}
			$db.updateItem({
				TableName: this.table,
				Key: this.whereKey,
				AttributeUpdates : $to_delete
			}, function(err,data) {
				if (err)
					return callback(err, false)

				callback( err, data )
			})
		}
	}

	this.get = function(callback) {
		var thisQuery = {
			TableName: this.table,
			Key: this.whereKey,
			ConsistentRead: this.ConsistentRead
		}

		if (this.select.length)
			thisQuery['AttributesToGet'] = this.select;

		$db.getItem( thisQuery, function(err,data) {
			if (err)
				return callback(err, false)

			callback(err, $this.normalizeItem(data.Item))
		})
	}

	this.query = function(callback) {

		var thisQuery = {
			TableName: this.table,
			KeyConditions: $this.anormalizeQuery(),
			ConsistentRead: this.ConsistentRead
		}
		if (this.limit_value !== null)
			thisQuery['Limit'] = this.limit_value;

		if (this.ScanIndexForward !== true) {
				thisQuery['ScanIndexForward'] = false;
		}
		if ( this.IndexName !== null )
			thisQuery['IndexName'] = this.IndexName;

		if (this.select.length)
			thisQuery['AttributesToGet'] = this.select;

		if ( this.ExclusiveStartKey !== null )
			thisQuery['ExclusiveStartKey'] = this.ExclusiveStartKey;

		$lastQuery = thisQuery
		$db.query( thisQuery , function(err,data) {
			if (err)
				return callback(err, false)

			$this.LastEvaluatedKey = data.LastEvaluatedKey === undefined ? null : data.LastEvaluatedKey
			callback(err, $this.normalizeList(data.Items))
		})

		return this
	}

	// helper functions ...
	this.anormalizeQuery = function() {
		var anormal = {}
		for (var key in this.whereKey) {
			if (this.whereKey.hasOwnProperty(key)) {
					anormal[key] = {
						ComparisonOperator: 'EQ',
						AttributeValueList: [ this.whereKey[key] ]
					}
			}
		}
		for (var key in this.whereOther) {
			if (this.whereOther.hasOwnProperty(key)) {
					var whereVal = {}
					whereVal[this.whereOther[key].type] = this.whereOther[key].value;
					var type =
					anormal[key] = {
						ComparisonOperator: this.whereOther[key].operator,
						AttributeValueList: [ whereVal ]
					}
			}
		}
		return anormal;
	}

	this.anormalizeList = function(list) {
		var $ret = []
		for (var $i in list) {
			$ret.push(this.anormalizeItem(list[$i]))
		}
		return $ret;
	}

	this.anormalizeItem = function(item) {
		var anormal = {}
		for (var key in item) {
			if (item.hasOwnProperty(key)) {
					if (typeof item[key] == 'number') {
						anormal[key] = {'N' : item[key].toString() }
					}
					if (typeof item[key] == 'string') {
						anormal[key] = {'S' : item[key] }
					}
			}
		}
		return anormal;
	}

	this.normalizeList = function($items) {
		var $list = []
		for (var i in $items) {
			$list.push(this.normalizeItem($items[i]))
		}
		return $list;
	}
	this.normalizeItem = function($item) {
		var normal = {}
		for (var key in $item) {
			if ($item.hasOwnProperty(key)) {
				if ($item[key].hasOwnProperty('S'))
					normal[key] = $item[key]['S']

				if ($item[key].hasOwnProperty('N'))
					normal[key] = parseInt($item[key]['N'])
			}
		}
		return normal;
	}
}

<|endoftext|>


<commit_before>'use strict';

var inherit = require('util').inherits,
  Scope = require('./scope'),
  EventEmitter = require('events').EventEmitter;

/**
 *
 * The DysLexer keeps some states, which are actually pretty generic.
 *
 */
function DysLexer(rootScope) {

  this.chars = {};
  this.current = 0;

  // not totally correct, ah well..
  // also do not count \r as character, it has 2 chars
  // for eol.
  // TODO: should override comma as custom,
  // not as default overhere
  this.eol = ['\n','\r', ','];

  this.scopeChar = 0;

  // default token endings
  // a scope can overwrite this temporarily
  this.tokenEnding = ['\n','\t',' '];

  // Tokens
  this.lastToken = undefined;

  // token cache
  this.tokens = [];

  // will remember all tokens in sync mode.
  this._tokens = [];

  this.token = '';

  // the last character that triggered a scope change.
  this.scoper = undefined;

  // first level matchers
  this.level = { };

  // only rebuild for logging
  this.line = '';

  // Hm, ok how to specify the root scope
  // I won't to move these addScope's out of here.
  // the current scope, in between quotes is the second scope.
  //this.lastScope = this.scope = 'RootScope';
  this.scope = this.rootScope = rootScope;

  // keep track of where we are,
  // with possibility to go back
  // bit wild but works.
  this.track = [this.scope];

}

inherit(DysLexer, EventEmitter);

// err... :-)
DysLexer.Scope = Scope;

DysLexer.prototype.reset = function() {

  this.chars = {};
  this.current = 0;

  this.scopeChar = 0;

  // Tokens
  this.lastToken = undefined;
  this.tokens = []; // will only be remembered per line/segment

  // will remember all tokens in sync mode.
  this._tokens = [];

  this.token = '';

  // the last character that triggered a scope change.
  this.scoper = undefined;

  // only rebuild for logging
  this.line = '';

  this.scope = this.rootScope;

  this.track = [this.scope];

};

DysLexer.prototype.addScope = function(scope) {

  this.level[scope.name] = new scope(this);

};

// goes to last scope
DysLexer.prototype.back = function(c) {
  this.toScope(this.track.pop(), c);
};

DysLexer.prototype.toScope = function(scope, c) {

  // Still useful in debug mode
  //console.log('------ ' + scope + '------');
  this.emit('scopeSwitch', {
    from: this.scope,
    to: scope
  });

  //this.lastScope = this.scope;
  this.track.push(this.scope);

  // Not used...
  this.level[scope].setParent(
    this.level[this.scope]
  );

  // check structure of the scope we left
  this.checkStructure(this.scope);

  // register the current scope
  this.scope = scope;

  // inform what char did the scope
  this.scoper = c;

  // char at which this was scoped
  this.scopeChar = this.current;

  // reset token list
  this.level[this.scope].tokens = [];

  // notify new scope we have entered.
  this.level[this.scope].onEnter();
};

DysLexer.prototype.next = function() {

  var c = this.chars[this.current];

  this.line += c;

  // debug
  // console.log(this.scope, ':', c);

  if(this.level[this.scope].rules[c]) {

    // this can cause weird behaviour if the rule itself
    // is redirecting the scope, which happens..
    // it means within this function this.scope is switched...
    this.level[this.scope].rules[c](c);

  } else if(this.level[this.scope].rules['**']) {
    // '**' will run whenever there is not already a match
    this.level[this.scope].rules['**'](c);
  }
  // Ok the above character matching could have switches the scope
  // it's actually the only job the character matching has...
  // but that character matching has a purpose.
  // however because we have switches scopes at _this_ exact point
  // the character will be re-considered by the other scope
  // that's the code following below.

  // it the scope has set it's own tokenEndings..
  if(this.level[this.scope].tokenEnding.length) {

    this.token += c;

    if(this.level[this.scope].tokenEnding.indexOf(c) >= 0 &&
     // trick to catch the first ' which is not escaped
     // it's the first
     // Ok, this makes a big difference.
     // if we save the token in the other scope
     // this one will never happen.
     // right hand is set with tokenEnding
     // where left hand is set with the character matchin
     // that's not so good.
     // so switching should be done from within
     // the character matching I think.
     // that will go ok, I hope.
     this.token.length > 1 &&
    !this.isEscaped()) {

      this.fireToken();

    }

  } else if(
    this.tokenEnding.indexOf(c) === -1 &&
    this.eol.indexOf(c) === -1) {

    // default behaviour, build the token
    this.token += c;

  } else if(
     // don't act if the scope took control
     this.level[this.scope].tokenEnding.length === 0 &&
     this.tokenEnding.indexOf(c) >= 0) {

    this.fireToken();
  }

  // So the same should happen here as onToken, but we got to watch
  // out that we do not have duplicate tokenEnding chars and eol chars.
  if(
    // note, much responsibility for the scope.
    // should take care of it's own ending.
    !this.level[this.scope].tokenEnding.length &&
    this.eol.indexOf(c) >= 0) {

    // fire last token
    this.fireToken();

    for(var s in this.level) {

      if(this.level.hasOwnProperty(s)) {
        this.level[s].onLineEnd();

        // do not emit lines without tokens. (empty ones)
        if(this.tokens.length) {
          this.emit('lineTokens', this.tokens, this.line);

          if(this.sync) {
            // array of tokens per line
            this._tokens.push(this.tokens);
          }

        }

        this.tokens = [];

        this.line = '';

        // reset generic stuff from the scope.
        this.level[s].onLineStart();
      }
    }
  }

  this.current++;

};

DysLexer.prototype.fireToken = function() {

  if(this.token) {

    if(typeof this.level[this.scope].tokensExpected === 'undefined') {
      throw new Error('tokensExpected is not set for ' + this.scope);
    }

    // ok how to solve that chaining problem.
    if(this.level[this.scope].tokensExpected <
       this.level[this.scope].tokens.length) {
      throw new Error([
        'Unexpected token count for',
        this.scope,
        'expected',
        this.level[this.scope].tokensExpected,
        'instead of',
        this.level[this.scope].tokens.length,
        'tokens\n\n\t',
        JSON.stringify(this.level[this.scope].tokens, null, 2),
        '\n'
      ].join(' '));
    }

    var realScope = this.scope;

    // Really switch this scope to root scope
    this.scope = this.rootScope;

    if(!this.level[this.rootScope].onToken(this.token)) {

      this.scope = realScope;
      if(this.scope !== this.rootScope) {
        this.level[this.scope].onToken(this.token);
      }

    }

    // reset token
    this.token = '';

  }

};

DysLexer.prototype.isEscaped = function() {

  // leave room to escape the choice.
  if(this.level[this.scope].escape) {

    if(this.chars[this.current - 1] === '\\') {
      return true;
    }

  }

  return false;
};

// TODO: should check whether the token was handled
// or at least make sure that when we fire a token
// it is in sync with what we got presented back.
// This way we can detect unhandled tokens.
DysLexer.prototype.present = function(name, data) {

  // maybe force validation to be present.
  if(this.level[this.scope].validate) {
    var reg = this.level[this.scope].validate[name];
    if(typeof reg === 'string') reg = new RegExp(reg); // ...
    if(reg && !reg.test(data)) {
      throw new Error([
        'Invalid',
        name,
        'token does not match',
        reg.toString(),
        '\n\n\t',
        data,
        '\n'
      ].join(' '));
    }
  }

  // Note: this relies on the scopes emitting the tokens back.
  // It does not contain each and every token emitted by this matcher.
  this.lastToken = {
    name: name,
    scope: this.scope,
    value: data,
    start: this.scopeChar,
    end: this.current
  };

  // remember token
  this.tokens.push(this.lastToken);

  this.emit('token', this.lastToken);

  // push token for this scope
  this.level[this.scope].tokens.push(this.lastToken);

  // if we've reached the token count, go back a level (or to root maybe)
  if(this.level[this.scope].tokensExpected ===
    this.level[this.scope].tokens.length) {

    // ok this works but is a bit ugly...
    this.toScope(this.rootScope);
  }

};

function compare(array1, array2) {

  var i, l;

  // if the other array is a falsy value, return
  if (!array2) return false;

  // compare lengths - can save a lot of time
  if (array1.length !== array2.length) return false;

  for (i = 0, l = array1.length; i < l; i++) {
    // Check if we have nested arrays
    if (array1[i] instanceof Array && array2[i] instanceof Array) {
      // recurse into the nested arrays
      if (!array1[i].compare(array2[i])) return false;
    } else if (array1[i] !== array2[i]) {
      return false;
    }
  }
  return true;
}

DysLexer.prototype.start = function(str, sync) {
  var i, scope;

  // TODO: temp fix
  str = str + '\n';

  // will remember all _tokens
  this.sync = sync;

  this.chars = str.split('');

  if(!this.rootScope) {
    throw new Error('Initial Root Scope required');
  }

  // notify all, we've started
  for(scope in this.level) {
    if(this.level.hasOwnProperty(scope)) {
      this.level[scope].onLineStart();
    }
  }

  // TODO: this way next makes no sense... :-)
  for(i = 0; i < this.chars.length; i++) {
    this.next();
  }

  this.emit('end');

  return (sync) ? this._tokens : null;

};

DysLexer.prototype.readChunk = function(str) {

  this.reset();
  this.start(str.toString());

};

// TODO: I want also to check partial structure.
// per token length, now only the end result is checked.
// not during token building for one scope.
DysLexer.prototype.checkStructure = function(scope) {

  var s = this.level[scope];

  // output to structure
  var tokens = s.tokens.map(function(t) { return t.name; });

  // nice, left hand is never checked..
  // because it's always empty, still true?
  if(tokens.length) {

    // Check if it matches any of the structures.
    if(s.structure.length) {

      var match = false;
      for(var str in s.structure) {
        if(compare(tokens, s.structure[str])) {
          match = true;
          break;
        }
      }
      if(!match) {
        throw new Error([
          'Structure mismatch for',
          scope,
          JSON.stringify(tokens),
          'did not match any of',
          JSON.stringify(s.structure),
          '\n\n\t',
          JSON.stringify(s.tokens)
        ].join(' '));
      }

      this.emit('structure', {
        scope: scope,
        tokens: tokens
      });

    }

  }

};

module.exports = DysLexer;
<commit_msg>do not run rootScope if scope has it's own tokenEndings + fix start & end numbering<commit_after>'use strict';

var inherit = require('util').inherits,
  Scope = require('./scope'),
  EventEmitter = require('events').EventEmitter;

/**
 *
 * The DysLexer keeps some states, which are actually pretty generic.
 *
 */
function DysLexer(rootScope) {

  this.chars = {};
  this.current = 0;

  // not totally correct, ah well..
  // also do not count \r as character, it has 2 chars
  // for eol.
  // TODO: should override comma as custom,
  // not as default overhere
  this.eol = ['\n','\r', ','];

  this.scopeChar = 0;

  // default token endings
  // a scope can overwrite this temporarily
  this.tokenEnding = ['\n','\t',' '];

  // Tokens
  this.lastToken = undefined;

  // token cache
  this.tokens = [];

  // will remember all tokens in sync mode.
  this._tokens = [];

  // char at which the current token started
  this.tokenStart = 0;

  this.token = '';

  // the last character that triggered a scope change.
  this.scoper = undefined;

  // char at which the current scope started
  this.scopeStart = 0;

  // first level matchers
  this.level = { };

  // only rebuild for logging
  this.line = '';

  this.scope = this.rootScope = rootScope;

  // keep track of where we are,
  // with possibility to go back
  // bit wild but works.
  this.track = [this.scope];

}

inherit(DysLexer, EventEmitter);

DysLexer.Scope = Scope;

DysLexer.prototype.reset = function() {

  this.chars = {};
  this.current = 0;

  this.scopeChar = 0;

  // Tokens
  this.lastToken = undefined;

  // will only be remembered per line/segment
  this.tokens = [];

  // will remember all tokens in sync mode.
  this._tokens = [];

  this.token = '';

  // the last character that triggered a scope change.
  this.scoper = undefined;

  // line is rebuild for logging
  this.line = '';

  this.scope = this.rootScope;

  this.track = [this.scope];

};

DysLexer.prototype.addScope = function(scope) {

  this.level[scope.name] = new scope(this);

};

// goes to last scope
DysLexer.prototype.back = function(c) {
  this.toScope(this.track.pop(), c);
};

DysLexer.prototype.toScope = function(scope, c) {

  // Still useful in debug mode
  //console.log('------ ' + scope + '------');
  this.emit('scopeSwitch', {
    from: this.scope,
    to: scope
  });

  //this.lastScope = this.scope;
  this.track.push(this.scope);

  // Not used...
  this.level[scope].setParent(
    this.level[this.scope]
  );

  // check structure of the scope we left
  this.checkStructure(this.scope);

  // register the current scope
  this.scope = scope;

  // inform what char did the scope
  this.scoper = c;

  // char at which this was scoped
  this.scopeChar = this.current;

  // reset token list
  this.level[this.scope].tokens = [];

  // notify new scope we have entered.
  this.level[this.scope].onEnter();
};

DysLexer.prototype.next = function() {

  var c = this.chars[this.current];

  this.line += c;

  // debug
  // console.log(this.scope, ':', c);

  if(this.level[this.scope].rules[c]) {

    // this can cause weird behaviour if the rule itself
    // is redirecting the scope, which happens..
    // it means within this function this.scope is switched...
    this.level[this.scope].rules[c](c);

  } else if(this.level[this.scope].rules['**']) {
    // '**' will run whenever there is not already a match
    this.level[this.scope].rules['**'](c);
  }
  // Ok the above character matching could have switched the scope
  // it's actually the only job the character matching has...
  // but that character matching has a purpose.
  // however because we have switched scopes at _this_ exact point
  // the character will be re-considered by the other scope
  // that's the code following below.

  // it the scope has set it's own tokenEndings..
  if(this.level[this.scope].tokenEnding.length) {

    if(!this.tokenStart) this.tokenStart = this.current;
    this.token += c;

    if(this.level[this.scope].tokenEnding.indexOf(c) >= 0 &&
     // trick to catch the first ' which is not escaped
     // it's the first
     // Ok, this makes a big difference.
     // if we save the token in the other scope
     // this one will never happen.
     // right hand is set with tokenEnding
     // where left hand is set with the character matchin
     // that's not so good.
     // so switching should be done from within
     // the character matching I think.
     // that will go ok, I hope.
     this.token.length > 1 &&
    !this.isEscaped()) {

      this.fireToken();

    }

  } else if(
    this.tokenEnding.indexOf(c) === -1 &&
    this.eol.indexOf(c) === -1) {

    // default behaviour, build the token
    if(!this.tokenStart) this.tokenStart = this.current;
    this.token += c;

  } else if(
     // don't act if the scope took control
     this.level[this.scope].tokenEnding.length === 0 &&
     this.tokenEnding.indexOf(c) >= 0) {

    this.fireToken();
  }

  // So the same should happen here as onToken, but we got to watch
  // out that we do not have duplicate tokenEnding chars and eol chars.
  if(
    // note, much responsibility for the scope.
    // should take care of it's own ending.
    !this.level[this.scope].tokenEnding.length &&
    this.eol.indexOf(c) >= 0) {

    // fire last token
    this.fireToken();

    for(var s in this.level) {

      if(this.level.hasOwnProperty(s)) {
        this.level[s].onLineEnd();

        // do not emit lines without tokens. (empty ones)
        if(this.tokens.length) {
          this.emit('lineTokens', this.tokens, this.line);

          if(this.sync) {
            // array of tokens per line
            this._tokens.push(this.tokens);
          }

        }

        this.tokens = [];

        this.line = '';

        // reset generic stuff from the scope.
        this.level[s].onLineStart();
      }
    }
  }

  this.current++;

};

DysLexer.prototype.fireToken = function() {

  if(this.token) {

    if(typeof this.level[this.scope].tokensExpected === 'undefined') {
      throw new Error('tokensExpected is not set for ' + this.scope);
    }

    // ok how to solve that chaining problem.
    if(this.level[this.scope].tokensExpected <
       this.level[this.scope].tokens.length) {
      throw new Error([
        'Unexpected token count for',
        this.scope,
        'expected',
        this.level[this.scope].tokensExpected,
        'instead of',
        this.level[this.scope].tokens.length,
        'tokens\n\n\t',
        JSON.stringify(this.level[this.scope].tokens, null, 2),
        '\n'
      ].join(' '));
    }

    var realScope = this.scope;

    // Really switch this scope to root scope
    this.scope = this.rootScope;

    // If the scope has set it's own token ending
    // do not run the rootScope 'scanner' if that's the case
    if(this.level[realScope].tokenEnding.length ||
       // runs only if the above didn't match, which is important.
       !this.level[this.rootScope].onToken(this.token)) {

      this.scope = realScope;
      if(this.scope !== this.rootScope) {
        this.level[this.scope].onToken(this.token);
      }

    }

    // reset token
    this.token = '';

    // reset token start
    this.tokenStart = undefined;

  }

};

DysLexer.prototype.isEscaped = function() {

  // leave room to escape the choice.
  if(this.level[this.scope].escape) {

    if(this.chars[this.current - 1] === '\\') {
      return true;
    }

  }

  return false;
};

// TODO: should check whether the token was handled
// or at least make sure that when we fire a token
// it is in sync with what we got presented back.
// This way we can detect unhandled tokens.
DysLexer.prototype.present = function(name, data) {

  // maybe force validation to be present.
  if(this.level[this.scope].validate) {
    var reg = this.level[this.scope].validate[name];
    if(typeof reg === 'string') reg = new RegExp(reg); // ...
    if(reg && !reg.test(data)) {
      throw new Error([
        'Invalid',
        name,
        'token does not match',
        reg.toString(),
        '\n\n\t',
        data,
        '\n'
      ].join(' '));
    }
  }

  // Note: this relies on the scopes emitting the tokens back.
  // It does not contain each and every token emitted by this matcher.
  this.lastToken = {
    name: name,
    scope: this.scope,
    value: data,
    scopeChar: this.scopeChar,
    start: this.tokenStart,
    end: this.current
  };

  // remember token
  this.tokens.push(this.lastToken);

  this.emit('token', this.lastToken);

  // push token for this scope
  this.level[this.scope].tokens.push(this.lastToken);

  // if we've reached the token count, go back a level (or to root maybe)
  if(this.level[this.scope].tokensExpected ===
    this.level[this.scope].tokens.length) {

    // ok this works but is a bit ugly...
    this.toScope(this.rootScope);
  }

};

function compare(array1, array2) {

  var i, l;

  // if the other array is a falsy value, return
  if (!array2) return false;

  // compare lengths - can save a lot of time
  if (array1.length !== array2.length) return false;

  for (i = 0, l = array1.length; i < l; i++) {
    // Check if we have nested arrays
    if (array1[i] instanceof Array && array2[i] instanceof Array) {
      // recurse into the nested arrays
      if (!array1[i].compare(array2[i])) return false;
    } else if (array1[i] !== array2[i]) {
      return false;
    }
  }
  return true;
}

DysLexer.prototype.start = function(str, sync) {
  var i, scope;

  // TODO: temp fix
  str = str + '\n';

  // will remember all _tokens
  this.sync = sync;

  this.chars = str.split('');

  if(!this.rootScope) {
    throw new Error('Initial Root Scope required');
  }

  // notify all, we've started
  for(scope in this.level) {
    if(this.level.hasOwnProperty(scope)) {
      this.level[scope].onLineStart();
    }
  }

  // TODO: this way next makes no sense... :-)
  for(i = 0; i < this.chars.length; i++) {
    this.next();
  }

  this.emit('end');

  return (sync) ? this._tokens : null;

};

DysLexer.prototype.readChunk = function(str) {

  this.reset();
  this.start(str.toString());

};

// TODO: I want also to check partial structure.
// per token length, now only the end result is checked.
// not during token building for one scope.
DysLexer.prototype.checkStructure = function(scope) {

  var s = this.level[scope];

  // output to structure
  var tokens = s.tokens.map(function(t) { return t.name; });

  // nice, left hand is never checked..
  // because it's always empty, still true?
  if(tokens.length) {

    // Check if it matches any of the structures.
    if(s.structure.length) {

      var match = false;
      for(var str in s.structure) {
        if(compare(tokens, s.structure[str])) {
          match = true;
          break;
        }
      }
      if(!match) {
        throw new Error([
          'Structure mismatch for',
          scope,
          JSON.stringify(tokens),
          'did not match any of',
          JSON.stringify(s.structure),
          '\n\n\t',
          JSON.stringify(s.tokens)
        ].join(' '));
      }

      this.emit('structure', {
        scope: scope,
        tokens: tokens
      });

    }

  }

};

module.exports = DysLexer;
<|endoftext|>


<commit_before>'use strict';

var playback = require('../../main/playback'),
  delay = require('lodash-node/modern/functions/delay'),
  defer = require('lodash-node/modern/functions/defer'),
  identity = require('lodash-node/modern/utilities/identity'),
  defaults = require('lodash-node/modern/objects/defaults'),
  describe = jasmine.getEnv().describe,
  beforeEach = jasmine.getEnv().beforeEach,
  afterEach = jasmine.getEnv().afterEach,
  it = jasmine.getEnv().it,
  ONE_HOUR = 1000 * 60 * 60,
  ONE_SECOND = 1000;

describe('Mixtube Playback', function() {

  var _stageElmt,
    _entries = Object.freeze(
      ['0KSOMA3QBU0', 'NUsoVlDFqZg', 'o3mP3mJDL2k', '7-7knsP2n5w', 'hiP14ED28CA', '2vjPBrBU-TM']
        .map(function(videoId) {
          return {id: videoId, provider: 'youtube'};
        }));

  function buildNextEntryProducer(entries) {
    return function arrayBasedNextEntryProducer(entry) {
      var idx = entries.indexOf(entry);
      if (idx === -1 || idx + 1 === entries.length) {
        return null;
      }

      return entries[idx + 1];
    }
  }

  function playbackWithDefaults(inter) {
    inter = inter || identity;

    var defaultTransitionDuration = 2000;

    var defaultConfig = {
      elementProducer: function defaultElementProducer() {
        var elmt = document.createElement('div');
        elmt.classList.add('player-wrapper');
        _stageElmt.appendChild(elmt);
        return elmt;
      },
      // special case where the entry is directly the video (easier for test)
      videoProducer: identity,
      nextEntryProducer: buildNextEntryProducer(_entries),
      transitionDuration: defaultTransitionDuration,
      comingNext: function defaultComingNext(currentVideo, nextVideo) {
        console.group('comingNext called');
        console.log({current: currentVideo, next: nextVideo});
        console.groupEnd();
      },
      loadFailed: function logLoadingErrorWarning(entry, error) {
        console.group('Skipped a entry because of an load error');
        console.warn({entry: entry, error: error});
        console.groupEnd();
      },
      debug: {
        mediaDuration: (2 * defaultTransitionDuration + 2000) / 1000,
        mediaQuality: 'low'
      }
    };

    return playback(defaults({}, inter(defaultConfig), defaultConfig));
  }

  beforeEach(function() {
    _stageElmt = document.createElement('div');
    _stageElmt.classList.add('stage');
    document.body.appendChild(_stageElmt);
  });

  afterEach(function() {
    document.body.removeChild(_stageElmt);
  });

  it('plays a playlist', function(done) {

    var pb = playbackWithDefaults(function() {
      return {
        stateChanged: function(prevState, state) {
          if (state === playback.States.stopped) {
            done();
          }
        }
      };
    });

    pb.skip(_entries[0]);
    pb.play();

  }, ONE_HOUR);

  it('plays the the last skipped to video when skip occurred while paused', function(done) {

    var pb = playbackWithDefaults(function() {
      return {
        stateChanged: function(prevState, state) {
          if (state === playback.States.stopped) {
            done();
          }
        }
      };
    });

    pb.play();
    pb.skip(_entries[0]);

    delay(function() {
      pb.pause();

      delay(function() {
        pb.skip(_entries[3]);
        pb.play();

        delay(function() {
          pb.skip(_entries[4]);
        }, ONE_SECOND);
      }, ONE_SECOND);
    }, ONE_SECOND);

  }, ONE_HOUR);

  it('skips over a video that failed to load', function(done) {

    var entries = _entries.slice(0, 3);
    entries[1].id = 'brokenVideoId';

    var pb = playbackWithDefaults(function() {
      return {
        nextEntryProducer: buildNextEntryProducer(entries),
        stateChanged: function(prevState, state) {
          if (state === playback.States.stopped) {
            done();
          }
        }
      };
    });

    pb.skip(_entries[0]);
    pb.play();

  }, ONE_HOUR);

});<commit_msg>cleaned integration tests and added "expectations"<commit_after>/* global jasmine */

'use strict';

var playback = require('../../main/playback'),
  delay = require('lodash-node/modern/functions/delay'),
  defer = require('lodash-node/modern/functions/defer'),
  identity = require('lodash-node/modern/utilities/identity'),
  defaults = require('lodash-node/modern/objects/defaults'),
  last = require('lodash-node/modern/arrays/last'),
  describe = jasmine.getEnv().describe,
  beforeEach = jasmine.getEnv().beforeEach,
  afterEach = jasmine.getEnv().afterEach,
  it = jasmine.getEnv().it,
  expect = jasmine.getEnv().expect,
  ONE_HOUR = 1000 * 60 * 60,
  ONE_SECOND = 1000;

describe('Mixtube Playback', function() {

  var _stageElmt,
    _entries = Object.freeze(
      ['0KSOMA3QBU0', 'NUsoVlDFqZg', 'o3mP3mJDL2k', '7-7knsP2n5w', 'hiP14ED28CA', '2vjPBrBU-TM']
        .map(function(videoId) {
          return {id: videoId, provider: 'youtube'};
        }));

  function buildNextEntryProducer(entries) {
    return function arrayBasedNextEntryProducer(entry) {
      var idx = entries.indexOf(entry);
      if (idx === -1 || idx + 1 === entries.length) {
        return null;
      }

      return entries[idx + 1];
    };
  }

  function playbackWithDefaults(inter) {
    inter = inter || identity;

    var defaultTransitionDuration = 2000;

    var defaultConfig = {
      elementProducer: function defaultElementProducer() {
        var elmt = document.createElement('div');
        elmt.classList.add('player-wrapper');
        _stageElmt.appendChild(elmt);
        return elmt;
      },
      // special case where the entry is directly the video (easier for test)
      videoProducer: identity,
      nextEntryProducer: buildNextEntryProducer(_entries),
      transitionDuration: defaultTransitionDuration,
      comingNext: jasmine.createSpy('comingNextSpy').and.callFake(
        function defaultComingNext(currentVideo, nextVideo) {
          console.group('comingNext called');
          console.log({current: currentVideo, next: nextVideo});
          console.groupEnd();
        }),
      loadFailed: jasmine.createSpy('loadFailedSpy').and.callFake(
        function logLoadingErrorWarning(entry, error) {
          console.group('Skipped a entry because of an load error');
          console.warn({entry: entry, error: error});
          console.groupEnd();
        }),
      debug: {
        mediaDuration: (2 * defaultTransitionDuration + 2000) / 1000,
        mediaQuality: 'low'
      }
    };

    return playback(defaults({}, inter(defaultConfig), defaultConfig));
  }

  beforeEach(function() {
    _stageElmt = document.createElement('div');
    _stageElmt.classList.add('stage');
    document.body.appendChild(_stageElmt);
  });

  afterEach(function() {
    document.body.removeChild(_stageElmt);
  });

  it('plays a playlist', function(done) {

    var comingNextSpy,
      pb = playbackWithDefaults(function(defaultConfig) {
        comingNextSpy = defaultConfig.comingNext;

        return {
          stateChanged: function(prevState, state) {
            if (state === playback.States.stopped) {
              runChecks();
              done();
            }
          }
        };
      });

    pb.skip(_entries[0]);
    pb.play();

    function runChecks() {
      expect(comingNextSpy.calls.count()).toEqual(_entries.length);
    }

  }, ONE_HOUR);

  it('plays the last skipped to video when skip occurred while paused', function(done) {

    var comingNextSpy,
      pb = playbackWithDefaults(function(defaultConfig) {
        comingNextSpy = defaultConfig.comingNext;

        return {
          stateChanged: function(prevState, state) {
            if (state === playback.States.stopped) {
              runChecks();
              done();
            }
          }
        };
      });

    pb.play();
    pb.skip(_entries[0]);

    delay(function() {
      pb.pause();

      delay(function() {
        pb.skip(_entries[3]);
        pb.play();

        delay(function() {
          pb.skip(last(_entries));
        }, ONE_SECOND);
      }, ONE_SECOND);
    }, ONE_SECOND);

    function runChecks() {
      expect(comingNextSpy.calls.mostRecent().args[0].id).toEqual(last(_entries).id);
    }

  }, ONE_HOUR);

  it('skips over a video that failed to load', function(done) {

    var entries = _entries.slice(0, 3);
    entries[1].id = 'brokenVideoId';

    var loadFailedSpy,
      pb = playbackWithDefaults(function(defaultConfig) {
        loadFailedSpy = defaultConfig.loadFailed;

        return {
          nextEntryProducer: buildNextEntryProducer(entries),
          stateChanged: function(prevState, state) {
            if (state === playback.States.stopped) {
              runChecks();
              done();
            }
          }
        };
      });

    pb.skip(_entries[0]);
    pb.play();

    function runChecks() {
      expect(loadFailedSpy).toHaveBeenCalled();
      expect(loadFailedSpy.calls.count()).toEqual(1);
    }

  }, ONE_HOUR);

});<|endoftext|>


<commit_before>import * as authActions from '../auth/actions';
import {register} from '../dispatcher';
import User from './user';
import {userCursor} from '../state';

export const dispatchToken = register(({action, data}) => {

  switch (action) {
    // See how user store can handle auth action.
    case authActions.login:
      userCursor(user => {
        const userData = data;
        return user
          .set('data', new User(userData))
          .setIn(['isLoggedIn'], true);
      });
      break;
  }

});

<commit_msg>#268 - changed setIn to set<commit_after>import * as authActions from '../auth/actions';
import {register} from '../dispatcher';
import User from './user';
import {userCursor} from '../state';

export const dispatchToken = register(({action, data}) => {

  switch (action) {
    // See how user store can handle auth action.
    case authActions.login:
      userCursor(user => {
        const userData = data;
        return user
          .set('data', new User(userData))
          .set('isLoggedIn', true);
      });
      break;
  }

});

<|endoftext|>


<commit_before>// Copyright 2016 the project authors as listed in the AUTHORS file.
// All rights reserved. Use of this source code is governed by the
// license that can be found in the LICENSE file.
const fs = require('fs');
const path = require('path');
const twilio = require('twilio');

var listeners = new Array();

module.exports.LOG_INFO = 0
module.exports.LOG_WARN = 1;
module.exports.LOG_ERROR = 2;

var sendSMS = function(config, message) {
  // send sms message indicating alarm has been triggered
  var twilioClient = new twilio.RestClient(config.twilio.accountSID, config.twilio.accountAuthToken);
  twilioClient.sendMessage({
    to: config.twilio.toNumber,
    from: config.twilio.fromNumber,
    body: message
  }, function(err, message) {
    if (err) {
      module.exports.logMessage(config, 'Failed to send sms:' + err.message, module.exports.LOG_INFO);
    } else {
      module.exports.logMessage(config, 'SMS Sent:' + message.sid, module.exports.LOG_INFO);
    }
  });
}

module.exports.addListener = function(listener) {
  listeners.push(listener);
}

module.exports.removeListner = function(listener) {
  for (var i = 0; i < listeners.length; i++) {
    if (listeners[i] === listener) {
      listeners.splice(i,1);
    }
  }
}

module.exports.logMessage = function(config, message, level) {
  if (level === module.exports.LOG_ERROR) {
    if (config.twilio.sendError) {
      sendSMS(config, message, level);
    }
  }

  // no point to provide error function as we won't do
  // anything in case of an error
  var formattedMessage = level + ':' + new Date() + ': ' + message;
  fs.appendFile(module.exports.getLogFileName(config), formattedMessage + '\n');

  // notify the listeners
  for (var i = 0; i < listeners.length; i++) {
    listeners[i](formattedMessage);
  }
}

var logFileName;
module.exports.getLogFileName = function(config) {
  if (logFileName === undefined) {
    logFileName = path.join(config.eventLogPrefix, 'event_log.txt');
  }
  return logFileName;
}
<commit_msg>cleanup lib/eventLog<commit_after>// Copyright 2016 the project authors as listed in the AUTHORS file.
// All rights reserved. Use of this source code is governed by the
// license that can be found in the LICENSE file.

const fs = require('fs');
const path = require('path');
const twilio = require('twilio');

// array of listeners that are also informed of
// messages logged
var listeners = new Array();

// log levels
module.exports.LOG_INFO = 0
module.exports.LOG_WARN = 1;
module.exports.LOG_ERROR = 2;

/**
 * Sends an sms message using the twillio info in config
 *
 * @param config - object with configuration data
 * @param message - sms messasge to be sent
 */
var sendSMS = function(config, message) {
  // send sms message indicating alarm has been triggered
  var twilioClient = new twilio.RestClient(config.twilio.accountSID, config.twilio.accountAuthToken);
  twilioClient.sendMessage({
    to: config.twilio.toNumber,
    from: config.twilio.fromNumber,
    body: message
  }, function(err, message) {
    if (err) {
      module.exports.logMessage(config, 'Failed to send sms:' + err.message, module.exports.LOG_WARN);
    } else {
      module.exports.logMessage(config, 'SMS Sent:' + message.sid, module.exports.LOG_INFO);
    }
  });
}

/**
 * Add listener to list of listeners informed
 * when a message is logged
 *
 * @param listener - listener to be added
 */
module.exports.addListener = function(listener) {
  listeners.push(listener);
}

/**
 * Remove listener from list of listeners informed
 * when a message is logged
 *
 * @param listener - listener to be added
 */
module.exports.removeListner = function(listener) {
  for (var i = 0; i < listeners.length; i++) {
    if (listeners[i] === listener) {
      listeners.splice(i,1);
    }
  }
}

/**
 * Log a message and optionally if at LOG_ERROR
 * level send an sms alert
 *
 * @param config - object with configuration data
 * @param messaege - message to be logged
 * @param level - level one of LOG_ERROR, LOG_WARN or
 *                LOG_INFO
 */
module.exports.logMessage = function(config, message, level) {
  if (level === module.exports.LOG_ERROR) {
    if (config.twilio.sendError) {
      sendSMS(config, message, level);
    }
  }

  // no point to provide error function as we won't do
  // anything in case of an error
  var formattedMessage = level + ':' + new Date() + ': ' + message;
  fs.appendFile(module.exports.getLogFileName(config), formattedMessage + '\n');

  // notify the listeners
  for (var i = 0; i < listeners.length; i++) {
    listeners[i](formattedMessage);
  }
}

var logFileName;
/**
 * get the name of the log file to write logs to
 *
 * @param config - object with configuration data
 */
module.exports.getLogFileName = function(config) {
  if (logFileName === undefined) {
    logFileName = path.join(config.eventLogPrefix, 'event_log.txt');
  }
  return logFileName;
}
<|endoftext|>