<commit_before>(function () {
    'use strict';
    var root = this;

    var removePunctuation = function (str) {
        var regExp;
        var regexes = [
            '!', // exclamationPoint
            '"', // doubleQuote
            '#', // numberSign
            '\\$', // dollarSign
            '%', // percentSign
            '&', // ampersand
            '\'', // singleQuote
            '\\(', // openParentheses
            '\\)', // closeParentheses
            '\\*', // asterisk
            '\\+', // plusSign
            ',', // comma
            '-', // hyphen
            '—', // emdash?
            '\\.', // period
            '/', // forwardSlash
            ':', // colon
            ';', // semicolon
            '<', // lessThan
            '=', // equalsSign
            '>', // greaterThan
            '\\?', // questionMark
            '@', // atSign
            '\\[', // openSquareBracket
            '\\\\', // backslash
            ']', // closeSquareBracket
            '\\^', // caret
            '_', // underscore
            '`', // backtick
            '{', // openCurlyBrace
            '\\|', // pipe
            '}', // closeCurlyBrace
            '~', // tilde
            '\t', // tab character
            '→', // arrow
            '✓', // checkMark
            '✔', // Mocha pass
            '✖', // Mocha fail
            '©', // copyright
            '·', // dot
            '“', // smart double quote left
            '”', // smart double quote right 1
            '″', // smart double quote right 2
            '’', // smart single quote right
            '¡',
            '¢',
            '£',
            '¤',
            '¥',
            '¦',
            '§',
            '¨',
            'ª',
            '«',
            '¬',
            '®',
            '¯',
            '°',
            '±',
            '²',
            '³',
            '´',
            'µ',
            '¶',
            '¸',
            '¹',
            'º',
            '»',
            '¼',
            '½',
            '¾',
            '¿',
            '‘',
            '‚',
            '„',
            '†',
            '‡',
            '•',
            '…',
            '‰',
            '€',
            '™',
            '➜',
            '⬆',
            '›',
            '👍',
            '😊'
        ];
        regexes = regexes.join('|');
        regExp = new RegExp(regexes, 'g');
        return str.replace(regExp, ' ');
    };

    // boilerplate: make removePunctuation available to both Node.js and the browser
    if (typeof exports !== 'undefined') {
        if (typeof module !== 'undefined' && module.exports) {
            exports = module.exports = removePunctuation;
        }
        exports.removePunctuation = removePunctuation;
    } else {
        root.removePunctuation = removePunctuation;
    }
}).call(this);
<commit_msg>removePunctuation: add characters 2017/03/21<commit_after>(function () {
    'use strict';
    var root = this;

    var removePunctuation = function (str) {
        var regExp;
        var regexes = [
            '!', // exclamationPoint
            '"', // doubleQuote
            '#', // numberSign
            '\\$', // dollarSign
            '%', // percentSign
            '&', // ampersand
            '\'', // singleQuote
            '\\(', // openParentheses
            '\\)', // closeParentheses
            '\\*', // asterisk
            '\\+', // plusSign
            ',', // comma
            '-', // hyphen
            '—', // emdash?
            '¯',
            '–',
            '\\.', // period
            '/', // forwardSlash
            ':', // colon
            ';', // semicolon
            '<', // lessThan
            '=', // equalsSign
            '>', // greaterThan
            '\\?', // questionMark
            '@', // atSign
            '\\[', // openSquareBracket
            '\\\\', // backslash
            ']', // closeSquareBracket
            '\\^', // caret
            '_', // underscore
            '`', // backtick
            '{', // openCurlyBrace
            '\\|', // pipe
            '}', // closeCurlyBrace
            '~', // tilde
            '\t', // tab character
            '→', // arrow
            '✓', // checkMark
            '✔', // Mocha pass
            '✖', // Mocha fail
            '©', // copyright
            '·', // dot
            '“', // smart double quote left
            '”', // smart double quote right 1
            '″', // smart double quote right 2
            '’', // smart single quote right
            '¡',
            '¢',
            '£',
            '¤',
            '¥',
            '¦',
            '§',
            '¨',
            'ª',
            '«',
            '¬',
            '®',
            '°',
            '±',
            '²',
            '³',
            '´',
            'µ',
            '¶',
            '¸',
            '¹',
            'º',
            '»',
            '¼',
            '½',
            '¾',
            '¿',
            '‘',
            '‚',
            '„',
            '†',
            '‡',
            '•',
            '…',
            '‰',
            '€',
            '™',
            '➜',
            '⬆',
            '›',
            '👍',
            '😊',
            '★',
            '☆'
        ];
        regexes = regexes.join('|');
        regExp = new RegExp(regexes, 'g');
        return str.replace(regExp, ' ');
    };

    // boilerplate: make removePunctuation available to both Node.js and the browser
    if (typeof exports !== 'undefined') {
        if (typeof module !== 'undefined' && module.exports) {
            exports = module.exports = removePunctuation;
        }
        exports.removePunctuation = removePunctuation;
    } else {
        root.removePunctuation = removePunctuation;
    }
}).call(this);
<|endoftext|>


<commit_before>require("dotenv").config();

var Metalsmith = require("metalsmith");

// 3rd party build scripts
var archive       = require("metalsmith-archive");
var collections   = require("metalsmith-collections");
var drafts        = require("metalsmith-drafts");
var ignore        = require("metalsmith-ignore");
var inPlace       = require("metalsmith-in-place");
var layouts       = require("metalsmith-layouts");
var markdown      = require("metalsmith-markdown");
var metallic      = require("metalsmith-metallic");
var paths         = require("metalsmith-paths");
var redirect      = require("metalsmith-redirect");
var rootPath      = require("metalsmith-rootpath");
var sass          = require("metalsmith-sass");

// first party build scripts
var helpers           = require("./lib/helpers");
var includes          = require("./lib/includes");
var inkplate          = require("./lib/inkplate");
var permalink         = require("./lib/permalink");
var relocateUploads   = require("./lib/relocate_uploads");
var rename            = require("./lib/rename");

// build state helpers
var startTime = Date.now();

var pipeline = Metalsmith(__dirname);
pipeline.destination(process.env.BUILD_DIR || "./build");

// misc
pipeline.use(ignore(["**/.DS_Store"]))

// content
pipeline.use(inkplate({
  extension: "md",
  apiKey: process.env.INKPLATE_API_KEY,
  host: process.env.INKPLATE_HOST,
  processPost: function(post) {
    return {
      collection: "posts",
      layout: "default.haml",
      title: post.title,
      type: "post",
      draft: !!(post.status !== "publish"),
      date: new Date(post.created_at),
      color: (post.custom_fields || {}).color,
      link: (post.custom_fields || {}).link
    };
  },
  processPage: function(page) {
    return {
      draft: !!(page.status !== "publish"),
      layout: "default.haml",
      type: "page",
      title: page.title
    };
  }
}));
pipeline.use(metallic());
pipeline.use(markdown());

// remove drafts in production
if (!process.env.INCLUDE_DRAFTS) {
  pipeline.use(drafts());
}

// structure
pipeline.use(collections({
  posts: {
    sortBy: "date",
    reverse: true
  }
}));
pipeline.use(archive({
  collections: ["\\d{4}\\/\\d{2}\\/\\d{2}\\/*"]
}));
pipeline.use(permalink());
pipeline.use(rootPath());
pipeline.use(paths());

// rendering
pipeline.use(sass({
  outputStyle: "compressed"
}));
pipeline.use(includes({
  directory: "includes",
  pattern: "**/*.haml",
  preserveWhitespace: true,
  matcher: "-# include (.*)"
}));
pipeline.use(helpers());
pipeline.use(inPlace({
  engine: "haml",
  pattern: ["**/*.haml"]
}));
pipeline.use(layouts({
  engine: "haml",
  directory: "layouts"
}));
pipeline.use(rename(/^(.*)\.haml$/i, "$1"));
pipeline.use(relocateUploads());

// redirects
pipeline.use(redirect(require("./redirects.json")));

// finalize
pipeline.build(function resolveBuild(error) {
  var endTime = Date.now();
  var elapsedSeconds = (endTime - startTime) / 100;

  if (error) {
    console.log(error);
    throw error;
  } else {
    process.stdin.write("Done building! Build time: " + elapsedSeconds + " seconds");
  }
});
<commit_msg>expose build directory cleaning in ENV<commit_after>require("dotenv").config();

var Metalsmith = require("metalsmith");

// 3rd party build scripts
var archive       = require("metalsmith-archive");
var collections   = require("metalsmith-collections");
var drafts        = require("metalsmith-drafts");
var ignore        = require("metalsmith-ignore");
var inPlace       = require("metalsmith-in-place");
var layouts       = require("metalsmith-layouts");
var markdown      = require("metalsmith-markdown");
var metallic      = require("metalsmith-metallic");
var paths         = require("metalsmith-paths");
var redirect      = require("metalsmith-redirect");
var rootPath      = require("metalsmith-rootpath");
var sass          = require("metalsmith-sass");

// first party build scripts
var helpers           = require("./lib/helpers");
var includes          = require("./lib/includes");
var inkplate          = require("./lib/inkplate");
var permalink         = require("./lib/permalink");
var relocateUploads   = require("./lib/relocate_uploads");
var rename            = require("./lib/rename");

// build state helpers
var startTime = Date.now();

var pipeline = Metalsmith(__dirname);
pipeline.destination(process.env.BUILD_DIR || "./build");
pipeline.clean(!process.env.SKIP_CLEAN);

// misc
pipeline.use(ignore(["**/.DS_Store"]))

// content
pipeline.use(inkplate({
  extension: "md",
  apiKey: process.env.INKPLATE_API_KEY,
  host: process.env.INKPLATE_HOST,
  processPost: function(post) {
    return {
      collection: "posts",
      layout: "default.haml",
      title: post.title,
      type: "post",
      draft: !!(post.status !== "publish"),
      date: new Date(post.created_at),
      color: (post.custom_fields || {}).color,
      link: (post.custom_fields || {}).link
    };
  },
  processPage: function(page) {
    return {
      draft: !!(page.status !== "publish"),
      layout: "default.haml",
      type: "page",
      title: page.title
    };
  }
}));
pipeline.use(metallic());
pipeline.use(markdown());

// remove drafts in production
if (!process.env.INCLUDE_DRAFTS) {
  pipeline.use(drafts());
}

// structure
pipeline.use(collections({
  posts: {
    sortBy: "date",
    reverse: true
  }
}));
pipeline.use(archive({
  collections: ["\\d{4}\\/\\d{2}\\/\\d{2}\\/*"]
}));
pipeline.use(permalink());
pipeline.use(rootPath());
pipeline.use(paths());

// rendering
pipeline.use(sass({
  outputStyle: "compressed"
}));
pipeline.use(includes({
  directory: "includes",
  pattern: "**/*.haml",
  preserveWhitespace: true,
  matcher: "-# include (.*)"
}));
pipeline.use(helpers());
pipeline.use(inPlace({
  engine: "haml",
  pattern: ["**/*.haml"]
}));
pipeline.use(layouts({
  engine: "haml",
  directory: "layouts"
}));
pipeline.use(rename(/^(.*)\.haml$/i, "$1"));
pipeline.use(relocateUploads());

// redirects
pipeline.use(redirect(require("./redirects.json")));

// finalize
pipeline.build(function resolveBuild(error) {
  var endTime = Date.now();
  var elapsedSeconds = (endTime - startTime) / 100;

  if (error) {
    console.log(error);
    throw error;
  } else {
    process.stdin.write("Done building! Build time: " + elapsedSeconds + " seconds");
  }
});
<|endoftext|>


<commit_before>function _sliderSimple(section) {
    $('#' + section + ' .right a').click(function()
    {
        var div = $('#' + section + ' .right').parent().parent().children('.slider-img').attr('id');
        $('#' + section + ' .left a').show();
        $('#' + div + ' div:visible').fadeOut(0)
                .next('div').fadeIn(0)
                .end();
        if ($('#' + div + ' div.img:visible').find('img').attr('alt') == $('#' + div + ' div.img:last').find('img').attr('alt')) {
            $(this).hide();
        }
    });

    $('#' + section + ' .left a').click(function()
    {
        var div = $('#' + section + ' .left').parent().parent().children('.slider-img').attr('id');
        $('#' + section + ' .right a').show();
        $('#' + div + ' div:visible').fadeOut(0)
                .prev('div').fadeIn(0)
                .end();
        if ($('#' + div + ' div.img:visible').find('img').attr('alt') == $('#' + div + ' div.img:first').find('img').attr('alt')) {
            $(this).hide();
        }
    });
}

function _sliderAvance(section) {
    $('#' + section + ' .btn-gallery a').hover(function() {
        $('#' + section + ' .btn-gallery a').removeClass('active');
        $(this).addClass('active');

        var rel = $(this).attr('rel');
        var div = $('#' + section + ' .btn-gallery').parent().parent().parent().children('.slider-img').attr('id');
        $('#' + div + ' div:visible').fadeOut(0);
        $('#' + div + ' div').eq(rel).fadeIn(0);
    });

//    $('.slider-view').hover(function() {
//        $('.btn-view').fadeIn(0);
//    }, function() {
//        $('.btn-view').fadeOut(0);
//    });

    $('.slider-view.plus, .btn-gallery a').click(function() {
        var div = $('.slider-view').parent().children('.slider-img').attr('id');
        var alt = $('#' + div + ' div:visible').find('img').attr('alt');
        $.ajax({
            type: 'GET',
            url: 'site/offices',
            data: 'floor=' + alt,
            before: function() {
//                $('#' + section + ' .slider').empty();
            },
            success: function(data) {
                $('#' + section + ' .slider').html(data);
                _sliderAvance(section);
            }
        });
    });

    $('.slider-view.minus').click(function() {
        var rel = $(this).find('a').attr('rel');
        $.ajax({
            type: 'GET',
            url: 'site/offices',
            before: function() {
//                $('#' + section + ' .slider').empty();
            },
            success: function(data) {
                $('#' + section + ' .slider').html(data).fadeIn(0);
                $('#' + section + ' .img').hide();
                $('#' + section + ' .slider-img div').eq(rel).show();
                $('#' + section + ' .btn-gallery a').removeClass('active');
                $('#' + section + ' .btn-list div').eq(rel).find('a').addClass('active');
                _sliderAvance(section);
            }
        });
    });
}

function _validateMail(email) {
    //Utilizamos una expresion regular
    var regex = /[\w-\.]{2,}@([\w-]{2,}\.)*([\w-]{2,}\.)[\w-]{2,4}/;

    //Se utiliza la funcion test() nativa de JavaScript
    if (regex.test(email.trim())) {
        return true;
    }
    else {
        return false;
    }
}

function _sendMail() {
    $('#btn-mail').click(function() {
        var name = $('#form-name').val();
        var mail = $('#form-mail').val();
        var phone = $('#form-phone').val();
        var subject = $('#form-subject').val();
        var message = $('#form-message').val();
        var text = 'Campos requeridos:\n\n';
        var send = true;

        if (name == "") {
            text = text.concat(" -- Nombre\n");
            send = false;
        }
        if (mail == "") {
            text = text.concat(" -- Correo\n");
            send = false;
        } else if(!_validateMail(mail)){
            text = text.concat(" -- Correo: La direccion de correo no es valida\n");
            send = false;
        }
        if (message == "") {
            text = text.concat(" -- Mensaje");
            send = false;
        }

        if (send) {
            var parameters = {
                "name": name,
                "mail": mail,
                "phone": phone,
                "subject": subject,
                "message": '
INFORMACION DE LA SOLICITUD
'
                        + '
'
                        + '
NOMBRE: ' + name + '
'
                        + '
EMAIL: ' + mail + '
'
                        + '
TELEFONO: ' + phone + '
'
                        + '
ASUNTO: ' + subject + '
'
                        + '
MENSAJE: ' + message + '
'
                        + '
'
                        + '

'
                        + '--------------------------------------------'
                        + '
Avenida Francisco de Miranda, Centro Lido,

Oficina 84-A1. Municipio Chacao

Caracas, Venezuela.

+58 212 954 0731

ahaconstructora@gmail.com
'

            };
            $.ajax({
                type: 'POST',
                url: 'site/email',
                data: parameters,
                success: function(data) {
                    $('#form-name').val("");
                    $('#form-mail').val("");
                    $('#form-phone').val("");
                    $('#form-subject').val("");
                    $('#form-message').val("");
                    if (data) {
                        alert("El correo fue enviado exitosamente.");
                    } else {
                        alert("Ocurrio un error inesperado.");
                    }
//                    console.log(data);
                },
                error: function() {
                    alert("Ocurrio un error inesperado.");
                }
            });
        } else {
            alert(text);
        }
    });
}

$(document).ready(function() {
    $('#slider1.slider-img div:gt(0)').hide();
    $('#sliderA.slider-img div:gt(0)').hide();
    _sliderSimple('project');
    _sliderAvance('offices');
    _sendMail();
//    setInterval(function () {
//        $('#slider-img div:first-child').fadeOut(0)
//                .next('div').fadeIn(1000)
//                .end().appendTo('#slider-img');
//    }, 4000);
});<commit_msg>change responsive<commit_after>function _sliderSimple(section) {
    $('#' + section + ' .right a').click(function()
    {
        var div = $('#' + section + ' .right').parent().parent().children('.slider-img').attr('id');
        $('#' + section + ' .left a').show();
        $('#' + div + ' div:visible').fadeOut(0)
                .next('div').fadeIn(0)
                .end();
        if ($('#' + div + ' div.img:visible').find('img').attr('alt') == $('#' + div + ' div.img:last').find('img').attr('alt')) {
            $(this).hide();
        }
    });

    $('#' + section + ' .left a').click(function()
    {
        var div = $('#' + section + ' .left').parent().parent().children('.slider-img').attr('id');
        $('#' + section + ' .right a').show();
        $('#' + div + ' div:visible').fadeOut(0)
                .prev('div').fadeIn(0)
                .end();
        if ($('#' + div + ' div.img:visible').find('img').attr('alt') == $('#' + div + ' div.img:first').find('img').attr('alt')) {
            $(this).hide();
        }
    });
}

function _sliderAvance(section) {
    $('#' + section + ' .btn-gallery a').hover(function() {
        $('#' + section + ' .btn-gallery a').removeClass('active');
        $(this).addClass('active');

        var rel = $(this).attr('rel');
        var div = $('#' + section + ' .btn-gallery').parent().parent().parent().children('.slider-img').attr('id');
        $('#' + div + ' div:visible').fadeOut(0);
        $('#' + div + ' div').eq(rel).fadeIn(0);
    });

//    $('.slider-view').hover(function() {
//        $('.btn-view').fadeIn(0);
//    }, function() {
//        $('.btn-view').fadeOut(0);
//    });

    $('.slider-view.plus, .btn-gallery a').click(function() {
        var div = $('.slider-view').parent().children('.slider-img').attr('id');
        var alt = $('#' + div + ' div:visible').find('img').attr('alt');
        $.ajax({
            type: 'GET',
            url: 'site/offices',
            data: 'floor=' + alt,
            before: function() {
//                $('#' + section + ' .slider').empty();
            },
            success: function(data) {
                $('#' + section + ' .slider').html(data);
                $('#' + section + ' .slider-img div:visible').fadeOut(0);
                $('#' + section + ' .slider-img div').eq(0).fadeIn(0);
                _sliderAvance(section);
            }
        });
    });

    $('.slider-view.minus').click(function() {
        var rel = $(this).find('a').attr('rel');
        $.ajax({
            type: 'GET',
            url: 'site/offices',
            before: function() {
//                $('#' + section + ' .slider').empty();
            },
            success: function(data) {
                $('#' + section + ' .slider').html(data).fadeIn(0);
                $('#' + section + ' .img').hide();
                $('#' + section + ' .slider-img div').eq(rel).show();
                $('#' + section + ' .btn-gallery a').removeClass('active');
                $('#' + section + ' .btn-list div').eq(rel).find('a').addClass('active');
                _sliderAvance(section);
            }
        });
    });
}

function _validateMail(email) {
    //Utilizamos una expresion regular
    var regex = /[\w-\.]{2,}@([\w-]{2,}\.)*([\w-]{2,}\.)[\w-]{2,4}/;

    //Se utiliza la funcion test() nativa de JavaScript
    if (regex.test(email.trim())) {
        return true;
    }
    else {
        return false;
    }
}

function _sendMail() {
    $('#btn-mail').click(function() {
        var name = $('#form-name').val();
        var mail = $('#form-mail').val();
        var phone = $('#form-phone').val();
        var subject = $('#form-subject').val();
        var message = $('#form-message').val();
        var text = 'Campos requeridos:\n\n';
        var send = true;

        if (name == "") {
            text = text.concat(" -- Nombre\n");
            send = false;
        }
        if (mail == "") {
            text = text.concat(" -- Correo\n");
            send = false;
        } else if(!_validateMail(mail)){
            text = text.concat(" -- Correo: La direccion de correo no es valida\n");
            send = false;
        }
        if (message == "") {
            text = text.concat(" -- Mensaje");
            send = false;
        }

        if (send) {
            var parameters = {
                "name": name,
                "mail": mail,
                "phone": phone,
                "subject": subject,
                "message": '
INFORMACION DE LA SOLICITUD
'
                        + '
'
                        + '
NOMBRE: ' + name + '
'
                        + '
EMAIL: ' + mail + '
'
                        + '
TELEFONO: ' + phone + '
'
                        + '
ASUNTO: ' + subject + '
'
                        + '
MENSAJE: ' + message + '
'
                        + '
'
                        + '

'
                        + '--------------------------------------------'
                        + '
Avenida Francisco de Miranda, Centro Lido,

Oficina 84-A1. Municipio Chacao

Caracas, Venezuela.

+58 212 954 0731

ahaconstructora@gmail.com
'

            };
            $.ajax({
                type: 'POST',
                url: 'site/email',
                data: parameters,
                success: function(data) {
                    $('#form-name').val("");
                    $('#form-mail').val("");
                    $('#form-phone').val("");
                    $('#form-subject').val("");
                    $('#form-message').val("");
                    if (data) {
                        alert("El correo fue enviado exitosamente.");
                    } else {
                        alert("Ocurrio un error inesperado.");
                    }
//                    console.log(data);
                },
                error: function() {
                    alert("Ocurrio un error inesperado.");
                }
            });
        } else {
            alert(text);
        }
    });
}

$(document).ready(function() {
    $('#slider1.slider-img div:gt(0)').hide();
    $('#sliderA.slider-img div:gt(0)').hide();
    _sliderSimple('project');
    _sliderAvance('offices');
    _sendMail();
//    setInterval(function () {
//        $('#slider-img div:first-child').fadeOut(0)
//                .next('div').fadeIn(1000)
//                .end().appendTo('#slider-img');
//    }, 4000);
});<|endoftext|>


<commit_before>'use strict';

import React, { Component } from 'react';
import ReactCSS from 'reactcss';

import colors from '../styles/variables/colors';
import 'normalize.css';
import '../fonts/work-sans/WorkSans.css!';
import '../styles/felony.css!';

import Header from './header/Header';
import FloatingButtonToggle from './floating-button/FloatingButtonToggle';

export class Felony extends Component {
  classes() {
    return {
      'default': {
        app: {
          Absolute: '0 0 0 0',
          background: colors.bgLight,
        },
      },
    };
  }

  render() {
    return (

        <FloatingButtonToggle />

    );
  }
}

export default ReactCSS(Felony);
<commit_msg>Add encrypt key list and styles to main<commit_after>'use strict';

import React, { Component } from 'react';
import ReactCSS from 'reactcss';

import colors from '../styles/variables/colors';
import 'normalize.css';
import '../fonts/work-sans/WorkSans.css!';
import '../styles/felony.css!';

import Header from './header/Header';
import EncryptKeyList from './encrypt/EncryptKeyList';
import FloatingButtonToggle from './floating-button/FloatingButtonToggle';

export class Felony extends Component {
  classes() {
    return {
      'default': {
        app: {
          Absolute: '0 0 0 0',
          background: colors.bgLight,
        },
        header: {
          position: 'fixed',
          top: 0,
          left: 0,
          right: 0,
        },
        encryptKeyList: {
          position: 'fixed',
          top: 78,
          left: 0,
          right: 0,
          bottom: 0,
          overflowY: 'scroll', // TODO: elastic scroll
        },
      },
    };
  }

  render() {
    return (

          <EncryptKeyList />

        <FloatingButtonToggle />

    );
  }
}

export default ReactCSS(Felony);
<|endoftext|>


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

const IPC = require("node-ipc").IPC;
const Ganache = require("ganache-core");
const path = require("path");
const debug = require("debug");

/*
 * Loggers
 */
const ipcDebug = debug("chain:ipc");

/*
 * Options
 */

// This script takes one argument: A strinified JSON object meant
// to be parsed and then passed to Ganache.server().
const args = process.argv.slice(2);
const ipcNetwork = args[0];
const base64OptionsString = args[1];
const optionsBuffer = Buffer.from(base64OptionsString, "base64");
let optionsString = optionsBuffer.toString();
let options;

try {
  options = JSON.parse(optionsString);
} catch (e) {
  throw new Error(
    "Fatal: Error parsing arguments; please contact the Truffle developers for help."
  );
}

/*
 * Logging
 */

// constructor
class Logger {
  constructor() {
    this.messages = [];

    this.nextSubscriberID = 1;
    this.subscribers = {};
  }

  // subscribe to log events with provided callback
  // sends prior unsent messages, as well as new messages
  // returns `unsubscribe` cleanup function
  subscribe(callback) {
    // flush messages
    const messages = this.messages;
    this.messages = [];
    messages.forEach(message => {
      callback(message);
    });

    // save subscriber
    const subscriberID = this.nextSubscriberID++;
    this.subscribers[subscriberID] = callback;

    // return cleanup func
    const unsubscribe = () => {
      delete this.subscribers[subscriberID];
    };

    return unsubscribe;
  }

  // log a message to be sent to all active subscribers
  // buffers if there are no active subscribers (to send on first subscribe)
  log(message) {
    const subscriberIDs = Object.keys(this.subscribers);
    if (subscriberIDs.length === 0) {
      this.messages.push(message);

      return;
    }

    subscriberIDs.forEach(subscriberID => {
      const callback = this.subscribers[subscriberID];

      callback(message);
    });
  }
}

/*
 * Supervisor
 */

// constructor - accepts an object to assign to `ipc.config`
class Supervisor {
  constructor(ipcConfig) {
    // init IPC
    this.ipc = new IPC();
    // set config
    Object.keys(ipcConfig).forEach(key => {
      this.ipc.config[key] = ipcConfig[key];
    });

    this.mixins = [];
  }

  // include mixin
  use(mixin) {
    this.mixins.push(mixin);
  }

  // dispatch event to all relevant mixins (ones that define `event` method)
  handle(event, args) {
    args = Array.prototype.slice.call(args);

    this.mixins.forEach(mixin => {
      if (mixin[event]) {
        mixin[event].apply(mixin, [this].concat(args));
      }
    });
  }

  // start the IPC server and hook up all the mixins
  start() {
    const ipc = this.ipc;

    // socket filename
    const dirname = ipc.config.socketRoot;
    const basename = `${ipc.config.appspace}${ipc.config.id}`;
    const servePath = path.join(dirname, basename);

    ipc.serve(servePath, function() {
      this.handle("start", arguments);

      ipc.server.on("connect", function() {
        this.handle("connect", arguments);
      });

      ipc.server.on("socket.disconnected", function() {
        this.handle("disconnect", arguments);
      });
    });

    ipc.server.start();
  }

  // external interface for mixin to emit socket events
  emit(socket, message, data, options = {}) {
    options.silent = options.silent || false;

    // possibly override silent
    const currentlySilent = this.ipc.config.silent;
    if (options.silent) {
      this.ipc.config.silent = true;
    }

    this.ipc.server.emit(socket, message, data);

    // reset
    this.ipc.config.silent = currentlySilent;
  }

  // external interface for mixin to exit
  exit() {
    this.ipc.server.stop();
    this.handle("exit", arguments);
  }
}

/*
 * Lifecycle
 * (quit on last connection)
 */
class LifecycleMixin {
  // start counting active connections
  start(_supervisor) {
    this.connections = 0;
  }

  // increment
  connect(_supervisor) {
    this.connections++;
  }

  // decrement - invoke supervisor exit if no connections remain
  disconnect(supervisor) {
    this.connections--;

    if (this.connections <= 0) {
      supervisor.exit();
    }
  }
}

/*
 * Ganache Server
 */

// constructor - accepts options for Ganache
class GanacheMixin {
  constructor(options) {
    this.ganache = Ganache.server(options);
  }

  // start Ganache and capture promise that resolves when ready
  start(_supervisor) {
    this.ready = new Promise((accept, reject) => {
      this.ganache.listen(options.port, options.hostname, (err, state) => {
        if (err) {
          reject(err);
        }

        accept(state);
      });
    });
  }

  // wait for Ganache to be ready then emit signal to client socket
  connect(supervisor, socket) {
    this.ready.then(() => {
      supervisor.emit(socket, "truffle.ready");
    });
  }

  // cleanup Ganache process on exit
  exit(_supervisor) {
    this.ganache.close(err => {
      if (err) {
        console.error(err.stack || err);
        process.exit(1);
      } else {
        process.exit();
      }
    });
  }
}

/*
 * Logging over IPC
 */

// constructor - takes Logger instance and message key (e.g. `truffle.ipc.log`)
class LoggerMixin {
  constructor(logger, message) {
    this.logger = logger;
    this.message = message;
  }

  // on connect, subscribe client socket to logger
  connect(supervisor, socket) {
    const unsubscribe = this.logger.subscribe(data => {
      supervisor.emit(socket, this.message, data, { silent: true });
    });

    socket.on("close", unsubscribe);
  }
}

/*
 * Process event handling
 */
process.on("uncaughtException", ({ stack }) => {
  console.error(stack);
  process.exit(1);
});

/*
 * Main
 */
const ipcLogger = new Logger();
const ganacheLogger = new Logger();

const supervisor = new Supervisor({
  appspace: "truffle.",
  id: ipcNetwork,
  retry: 1500,
  logger: ipcLogger.log.bind(ipcLogger)
});

ipcLogger.subscribe(ipcDebug);

options.logger = { log: ganacheLogger.log.bind(ganacheLogger) };

supervisor.use(new LifecycleMixin());
supervisor.use(new GanacheMixin(options));
supervisor.use(new LoggerMixin(ipcLogger, "truffle.ipc.log"));
supervisor.use(new LoggerMixin(ganacheLogger, "truffle.ganache.log"));
supervisor.start();
<commit_msg>set options.time as Date object before passing to ganache-core (truffle-environment/chain)<commit_after>#!/usr/bin/env node

const IPC = require("node-ipc").IPC;
const Ganache = require("ganache-core");
const path = require("path");
const debug = require("debug");

/*
 * Loggers
 */
const ipcDebug = debug("chain:ipc");

/*
 * Options
 */

// This script takes one argument: A strinified JSON object meant
// to be parsed and then passed to Ganache.server().
const args = process.argv.slice(2);
const ipcNetwork = args[0];
const base64OptionsString = args[1];
const optionsBuffer = Buffer.from(base64OptionsString, "base64");
let optionsString = optionsBuffer.toString();
let options;

try {
  options = JSON.parse(optionsString);
} catch (e) {
  throw new Error(
    "Fatal: Error parsing arguments; please contact the Truffle developers for help."
  );
}

options.time = new Date(options.time);

/*
 * Logging
 */

// constructor
class Logger {
  constructor() {
    this.messages = [];

    this.nextSubscriberID = 1;
    this.subscribers = {};
  }

  // subscribe to log events with provided callback
  // sends prior unsent messages, as well as new messages
  // returns `unsubscribe` cleanup function
  subscribe(callback) {
    // flush messages
    const messages = this.messages;
    this.messages = [];
    messages.forEach(message => {
      callback(message);
    });

    // save subscriber
    const subscriberID = this.nextSubscriberID++;
    this.subscribers[subscriberID] = callback;

    // return cleanup func
    const unsubscribe = () => {
      delete this.subscribers[subscriberID];
    };

    return unsubscribe;
  }

  // log a message to be sent to all active subscribers
  // buffers if there are no active subscribers (to send on first subscribe)
  log(message) {
    const subscriberIDs = Object.keys(this.subscribers);
    if (subscriberIDs.length === 0) {
      this.messages.push(message);

      return;
    }

    subscriberIDs.forEach(subscriberID => {
      const callback = this.subscribers[subscriberID];

      callback(message);
    });
  }
}

/*
 * Supervisor
 */

// constructor - accepts an object to assign to `ipc.config`
class Supervisor {
  constructor(ipcConfig) {
    // init IPC
    this.ipc = new IPC();
    // set config
    Object.keys(ipcConfig).forEach(key => {
      this.ipc.config[key] = ipcConfig[key];
    });

    this.mixins = [];
  }

  // include mixin
  use(mixin) {
    this.mixins.push(mixin);
  }

  // dispatch event to all relevant mixins (ones that define `event` method)
  handle(event, args) {
    args = Array.prototype.slice.call(args);

    this.mixins.forEach(mixin => {
      if (mixin[event]) {
        mixin[event].apply(mixin, [this].concat(args));
      }
    });
  }

  // start the IPC server and hook up all the mixins
  start() {
    const ipc = this.ipc;

    // socket filename
    const dirname = ipc.config.socketRoot;
    const basename = `${ipc.config.appspace}${ipc.config.id}`;
    const servePath = path.join(dirname, basename);

    ipc.serve(servePath, function() {
      this.handle("start", arguments);

      ipc.server.on("connect", function() {
        this.handle("connect", arguments);
      });

      ipc.server.on("socket.disconnected", function() {
        this.handle("disconnect", arguments);
      });
    });

    ipc.server.start();
  }

  // external interface for mixin to emit socket events
  emit(socket, message, data, options = {}) {
    options.silent = options.silent || false;

    // possibly override silent
    const currentlySilent = this.ipc.config.silent;
    if (options.silent) {
      this.ipc.config.silent = true;
    }

    this.ipc.server.emit(socket, message, data);

    // reset
    this.ipc.config.silent = currentlySilent;
  }

  // external interface for mixin to exit
  exit() {
    this.ipc.server.stop();
    this.handle("exit", arguments);
  }
}

/*
 * Lifecycle
 * (quit on last connection)
 */
class LifecycleMixin {
  // start counting active connections
  start(_supervisor) {
    this.connections = 0;
  }

  // increment
  connect(_supervisor) {
    this.connections++;
  }

  // decrement - invoke supervisor exit if no connections remain
  disconnect(supervisor) {
    this.connections--;

    if (this.connections <= 0) {
      supervisor.exit();
    }
  }
}

/*
 * Ganache Server
 */

// constructor - accepts options for Ganache
class GanacheMixin {
  constructor(options) {
    this.ganache = Ganache.server(options);
  }

  // start Ganache and capture promise that resolves when ready
  start(_supervisor) {
    this.ready = new Promise((accept, reject) => {
      this.ganache.listen(options.port, options.hostname, (err, state) => {
        if (err) {
          reject(err);
        }

        accept(state);
      });
    });
  }

  // wait for Ganache to be ready then emit signal to client socket
  connect(supervisor, socket) {
    this.ready.then(() => {
      supervisor.emit(socket, "truffle.ready");
    });
  }

  // cleanup Ganache process on exit
  exit(_supervisor) {
    this.ganache.close(err => {
      if (err) {
        console.error(err.stack || err);
        process.exit(1);
      } else {
        process.exit();
      }
    });
  }
}

/*
 * Logging over IPC
 */

// constructor - takes Logger instance and message key (e.g. `truffle.ipc.log`)
class LoggerMixin {
  constructor(logger, message) {
    this.logger = logger;
    this.message = message;
  }

  // on connect, subscribe client socket to logger
  connect(supervisor, socket) {
    const unsubscribe = this.logger.subscribe(data => {
      supervisor.emit(socket, this.message, data, { silent: true });
    });

    socket.on("close", unsubscribe);
  }
}

/*
 * Process event handling
 */
process.on("uncaughtException", ({ stack }) => {
  console.error(stack);
  process.exit(1);
});

/*
 * Main
 */
const ipcLogger = new Logger();
const ganacheLogger = new Logger();

const supervisor = new Supervisor({
  appspace: "truffle.",
  id: ipcNetwork,
  retry: 1500,
  logger: ipcLogger.log.bind(ipcLogger)
});

ipcLogger.subscribe(ipcDebug);

options.logger = { log: ganacheLogger.log.bind(ganacheLogger) };

supervisor.use(new LifecycleMixin());
supervisor.use(new GanacheMixin(options));
supervisor.use(new LoggerMixin(ipcLogger, "truffle.ipc.log"));
supervisor.use(new LoggerMixin(ganacheLogger, "truffle.ganache.log"));
supervisor.start();
<|endoftext|>


<commit_before>// 1. We should deal with the fact that nullable GraphQL fields can be null in responses
//    and set them to be empty strings. Same applies for any other optional property
// 2. We should convert empty string values back to undefined or null or whatever
//    the API’s contract is
// 3. Inputs can export parsing and formatting helpers used here. Our internal MoneyInput
//    for instance has a static MoneyInput.parseMoneyValue and MoneyInput.convertToMoneyValue
//    to be used here

// These empty choices are here so that Formik can render 5 input fields
const emptyChoices = [{ text: '' }, { text: '' }, { text: '' }, { text: '' }, { text: '' }];

export const responseToFormValues = response => ({
  id: response.id,
  type: response.type,
  wording: response.wording,
  imageUrl: response.imageUrl,
  imageFullUrl: response.imageFullUrl,
  secondaryWording: response.secondaryWording,
  choices: response.choices.length > 0 ? response.choices : emptyChoices,
});

/**
 * Transforms an array of choices [{ id: '1Ba', text: 'Lorem ipsum' }] into
 * an object for 'choices' field in updateQuestion mutation:
 * {create: [{ id: '1Ba', text: 'Lorem ipsum' }]
 * {update: [{ where: { id: '1Ba' }, data: { text: 'Lorem ipsum' } }]}
 * @param {Array<{id: String, text: String}>} choices - Choices array
 */
const choicesValuesToRequest = choices => {
  if (choices[0].id) {
    // [QuestionChoiceUpdateWithWhereUniqueNestedInput]
    return { update: choices.map(({ id, text }) => ({ where: { id }, data: { text } })) };
  }
  // QuestionChoiceCreateInput
  return { create: choices };
};

export const formValuesToRequest = values => ({
  type: values.type,
  wording: values.wording,
  imageUrl: values.imageUrl,
  secondaryWording: values.secondaryWording,
  choices: values.type === 'MULTIPLE_CHOICE' ? choicesValuesToRequest(values.choices) : null,
});
<commit_msg>Fix question choices' query mapping to support delete<commit_after>// 1. We should deal with the fact that nullable GraphQL fields can be null in responses
//    and set them to be empty strings. Same applies for any other optional property
// 2. We should convert empty string values back to undefined or null or whatever
//    the API’s contract is
// 3. Inputs can export parsing and formatting helpers used here. Our internal MoneyInput
//    for instance has a static MoneyInput.parseMoneyValue and MoneyInput.convertToMoneyValue
//    to be used here

// These empty choices are here so that Formik can render 5 input fields
const emptyChoices = [{ text: '' }, { text: '' }, { text: '' }, { text: '' }, { text: '' }];

export const responseToFormValues = response => ({
  id: response.id,
  type: response.type,
  wording: response.wording,
  imageUrl: response.imageUrl,
  imageFullUrl: response.imageFullUrl,
  secondaryWording: response.secondaryWording,
  choices: response.choices.length > 0 ? response.choices : emptyChoices,
});

/**
 * Transforms an array of choices [{ id: '1Ba', text: 'Lorem ipsum' }] into
 * an object for 'choices' field in updateQuestion mutation:
 *
 * {create: [{ id: '1Ba', text: 'Lorem ipsum' }]
 *
 * {delete: [{ id: '1Ba'}]
 *
 * {update: [{ where: { id: '1Ba' }, data: { text: 'Lorem ipsum' } }]}
 * @param {Array<{id: String, text: String}>} choices - Choices array
 * @param {String} type - Question type: MULTIPLE_CHOICE or OPEN_ENDED
 */
const choicesValuesToRequest = (choices, type) => {
  // Se as alternativas têm o atributo 'id', a questão já existe, e é de
  // Múltipla Escolha. Então precisamos atualizar as alternativas.
  if (choices[0].id && type === 'MULTIPLE_CHOICE') {
    // [QuestionChoiceUpdateWithWhereUniqueNestedInput]
    return { update: choices.map(({ id, text }) => ({ where: { id }, data: { text } })) };
  }
  // A questão era de Múltipla Escolha, mas o usuário trocou pra Discursiva.
  // Então precisamos excluir as alternativas.
  if (choices[0].id && type === 'OPEN_ENDED') {
    return { delete: choices.map(({ id }) => ({ id })) };
  }
  // A questão era Discursiva e foi mudada para Múltipla Escolha. Ou a questão está
  // sendo adicionada agora. De qualquer forma, precisamos criar as alternativas.
  if (!choices[0].id && type === 'MULTIPLE_CHOICE') {
    // QuestionChoiceCreateInput
    return { create: choices };
  }

  throw new Error(
    `Question 'type' should be 'MULTIPLE_CHOICE' or 'OPEN_ENDED'. The value '${type}' is invalid.`,
  );
};

export const formValuesToRequest = values => ({
  type: values.type,
  wording: values.wording,
  imageUrl: values.imageUrl,
  secondaryWording: values.secondaryWording,
  choices: choicesValuesToRequest(values.choices, values.type),
});
<|endoftext|>


<commit_before>var reemit = require("re-emitter/reemit")

var publish = require("./publish")
var subscribe = require("./subscribe")

module.exports = duplex

function duplex(client, channel, options) {
    var read = subscribe(client, channel, options)
    var write = publish(client, channel)

    read.write = write.write
    read.end = write.end

    reemit(write, read, ["error", "drain", "finish", "pipe"])

    return read
}
<commit_msg>support legacy readable / writable properties for 0.8 Stream.prototype.pipe<commit_after>var reemit = require("re-emitter/reemit")

var publish = require("./publish")
var subscribe = require("./subscribe")

module.exports = duplex

function duplex(client, channel, options) {
    var read = subscribe(client, channel, options)
    var write = publish(client, channel)

    read.write = write.write
    read.end = write.end
    read.writable = true
    read.readable = true

    reemit(write, read, ["error", "drain", "finish", "pipe"])

    return read
}
<|endoftext|>


<commit_before>var fs = require('fs')
  , EventEmitter = require('events').EventEmitter;

var chokidar = require('chokidar');

var Item = require('./lib/item.js');

// TODO: adding/removing dirs
// TODO: confirm storing complex data works (no reason to believe it doesn't)
// TODO: confirm providers work as expected
// TODO: provider calls are async, which can lead to ready being called before all providers have returned.  option to prevent this from happening?

function Voyeur(opts) {
  opts = opts || {};
  this.options = {
      saveDestination: './watched.json'
    , savePretty: true
    , saveEvery: 360000

    , autoProvide: true
    , defaultProvider: null
    , providerTimeout: 5000
    , providerTimeoutOutcome: 'warn'

    , returnExpired: true
    , defaultRevision: -Infinity
    , logger: null
  };
  for (var k in opts) {
    if (k in this.options) {
      this.options[k] = opts[k];
    }
    else {
      throw new Error('Invalid option "' + k + '"');
    }
  }

  if (!Item.isValidProvider(this.options.defaultProvider)) {
    throw new Error('Invalid defaultProvider. Must be null or a function that takes two arguments fn(item, callback): ' + toString.call(this.options.defaultProvider) + ' provided');
  }

  this._db = {};
  this._watchers = [];

  this.log = this.options.logger || nooplogger;
  this.log.debug('Initializing', this.options);
}

Voyeur.prototype = Object.create(EventEmitter.prototype);

Voyeur.prototype._error = function(err) {
  this.trigger('error', err);
};

Voyeur.prototype.trigger = function() {
  var _this = this
    , args = arguments;
  setImmediate(function() {
    _this.emit.apply(_this, args);
  });
};

Voyeur.prototype.start = function(pattern, options, callback) {
  var _this = this;
  callback = callback || function(err) { if (err) { _this._error(err); } };

  Object.freeze(_this.options);
  this.log.debug('Starting');

  fs.exists(_this.options.saveDestination, function(exists) {
    if (exists) {
      _this._load(_this.options.saveDestination, function(err) {
        if (err) {
          return _this._error(err);
        }
        _this._watch(pattern, options, callback);
        return;
      });
    }
    else {
      _this._watch(pattern, options, callback);
      return;
    }
  });

  if (_this.options.saveEvery) {
    setInterval(function() {
      _this.save(function(err) {
        if (err) {
          return _this._error(err);
        }
      });
    }, _this.options.saveEvery);
  }

  return _this;
};

Voyeur.prototype.shutdownSync = function() {
  this.saveSync();
  this.stopSync();
};

Voyeur.prototype.shutdown = function(callback) {
  var _this = this;
  _this.stop(function(err) {
    if (err) {
      return callback(err);
    }
    _this.save(callback);
  });
};

Voyeur.prototype.stop = function(callback) {
  this.stopSync();
  setImmediate(callback);
};

Voyeur.prototype.stopSync = function() {
  this._watchers.forEach(function(watcher) {
    watcher.close();
  });
};

Voyeur.prototype._load = function(destination, callback) {
  var _this = this;

  _this.log.debug('Loading', destination);

  fs.readFile(destination, function(err, data) {
    if (err) {
      return callback(err);
    }
    _this.import(JSON.parse(data));
    callback(null);
  });
};

// on osx 10.10.2 (at least) stats is unavailable from watcher:add event
// wrapping in setImmediate seems to fix, but should this poll? FIXME: ?
Voyeur.prototype._lastModFromStats = function(filepath, stats, callback) {
  setImmediate(function() {
    if (stats && stats.mtime && stats.mtime.getTime) {
      callback(null, stats.mtime.getTime());
    }
    else {
      fs.stat(filepath, function(err, stats) {
        if (err) {
          return callback(err);
        }
        callback(null, stats.mtime.getTime());
      });
    }
  });
};

Voyeur.prototype._watch = function(globPattern, globOptions, callback) {
  var _this = this;

  _this.log.debug('Watching', globPattern, globOptions);

  var watcher = chokidar.watch(globPattern, globOptions);
  _this._watchers.push(watcher);

  var ready = false;
  watcher
    .on('ready', function() {
      _this.log.debug('Watcher ready');
      ready = true;
      callback(null);
    })
    .on('error', function(err) {
      watcher.close();
      callback(err);
    })
    .on('add', function(filepath, stats) {
      _this.trigger('watcher:add', filepath, stats, watcher);
      _this._lastModFromStats(filepath, stats, function(err, lastMod) {
        if (err) {
          return _this._error(err);
        }
        if (ready || !_this.test(filepath, lastMod)) {
          _this.add(filepath, lastMod);
        }
      });
    })
    .on('change', function(filepath, stats) {
      _this.trigger('watcher:change', filepath, stats, watcher);
      _this._lastModFromStats(filepath, stats, function(err, lastMod) {
        if (err) {
          return _this._error(err);
        }
        _this.add(filepath, lastMod);
      });
    })
    .on('unlink', function(filepath) {
      _this.trigger('watcher:delete', filepath, watcher);
      _this.remove(filepath);
    });
};

Voyeur.prototype.import = function(db) {
  for (var relativePath in db) {
    var obj = db[relativePath];
    if (obj) {
      var item = this._create(relativePath, obj.revision, obj.data, false);
      if (obj.expired) {
        item.expired = true;
      }
      this.trigger('item:imported', item);
    }
  }
  return this;
};

Voyeur.prototype._create = function(relativePath, revision, data, providerFallback) {
  var item = this._db[relativePath] = new Item(relativePath, revision || this.options.defaultRevision, data);
  if (!Item.isValidProvider(data) && this.options.defaultProvider) {
    item.provider = this.options.defaultProvider;
  }
  if (!data && providerFallback && item.provider && this.options.autoProvide) { // if creating and no data is provided
    this._provide(item);
  }
  return item;
};

Voyeur.prototype.all = function() {
  return Object.create(this._db);
};

Voyeur.prototype._get = function(relativePath) {
  return this._db[relativePath];
};

Voyeur.prototype.get = function(relativePath) {
  var item = this._get(relativePath);
  return !item.expired || (item.expired && this.options.returnExpired) ? item : null;
};

Voyeur.prototype.add = function(relativePath, revision, data) {
  revision = revision || this.options.defaultRevision;
  if (!this._db[relativePath]) { // doesn't exist
    this.trigger('item:created', this._create(relativePath, revision, data, true));
  }
  else {
    this.update(relativePath, revision, data);
  }
  return this;
};

Voyeur.prototype.update = function(relativePath, revision, data) {
  revision = revision || this.options.defaultRevision;
  var status = this.test(relativePath, revision)
    , item = this._get(relativePath);
  if (true === status) {
    this.trigger('item:current', item);
  }
  else if (false === status) {
    var acknowledge = function acknowledgeItemExpired() {
      item.revision = revision;
      item.expired = false;
    };
    item.expired = true;
    this.trigger('item:expired', item, acknowledge);
    if (item.provider && this.options.autoProvide) {
      this._provide(item, acknowledge);
    }
  }
  else {
    throw new Error('Cannot update because "' + relativePath + '" does not exist');
  }
};

Voyeur.prototype.remove = function(relativePath) {
  // this.log.debug('remove', relativePath);
  if (this._db[relativePath]) {
    this.trigger('item:removed', this._get(relativePath));
    delete this._db[relativePath];
  }
  return this;
};

Voyeur.prototype._provide = function(item, callback) {
  var _this = this;
  callback = callback || function(err){
    if (err) {
      return _this._error(err);
    }
  };
  item.callProvider({
    timeout: _this.options.providerTimeout,
    timeoutOutcome: _this.options.providerTimeoutOutcome
  }, callback);
};

Voyeur.prototype.test = function(relativePath, revision) {
  revision = revision || this.options.defaultRevision;
  if (this._db[relativePath]) {
    return revision == this._db[relativePath].revision;
  }
  else {
    return;
  }
};

Voyeur.prototype.stringify = function() {
  return this.options.saveDestination ? JSON.stringify(this._db, null, 2) : JSON.stringify(this._db);
};

Voyeur.prototype.save = function(destination, callback) {
  if (typeof destination === 'function') {
    callback = destination;
    destination = null;
  }
  destination = destination || this.options.saveDestination;
  fs.writeFile(destination, this.stringify(), callback);
};

Voyeur.prototype.saveSync = function(destination) {
  destination = destination || this.options.saveDestination;
  this.log.debug('saveSync', destination);
  fs.writeFileSync(destination, this.stringify());
};

Voyeur.consoleLogger = {
    info: console.info
  , warn: console.warn
  , error: console.error
  , debug: console.log
  , log: console.log
};

var nooplogger = {
    info: function(){}
  , warn: function(){}
  , error: function(){}
  , debug: function(){}
  , log: function(){}
};

module.exports = Voyeur;
<commit_msg>make more readable<commit_after>var fs = require('fs')
  , EventEmitter = require('events').EventEmitter;

var chokidar = require('chokidar');

var Item = require('./lib/item.js');

// TODO: adding/removing dirs
// TODO: confirm storing complex data works (no reason to believe it doesn't)
// TODO: confirm providers work as expected
// TODO: provider calls are async, which can lead to ready being called before all providers have returned.  option to prevent this from happening?

function Voyeur(opts) {
  opts = opts || {};
  this.options = {
      saveDestination: './watched.json'
    , savePretty: true
    , saveEvery: 360000

    , autoProvide: true
    , defaultProvider: null
    , providerTimeout: 5000
    , providerTimeoutOutcome: 'warn'

    , returnExpired: true
    , defaultRevision: -Infinity
    , logger: null
  };
  for (var k in opts) {
    if (k in this.options) {
      this.options[k] = opts[k];
    }
    else {
      throw new Error('Invalid option "' + k + '"');
    }
  }

  if (!Item.isValidProvider(this.options.defaultProvider)) {
    throw new Error('Invalid defaultProvider. Must be null or a function that takes two arguments fn(item, callback): ' + toString.call(this.options.defaultProvider) + ' provided');
  }

  this._db = {};
  this._watchers = [];

  this.log = this.options.logger || nooplogger;
  this.log.debug('Initializing', this.options);
}

Voyeur.prototype = Object.create(EventEmitter.prototype);

Voyeur.prototype._error = function(err) {
  this.trigger('error', err);
};

Voyeur.prototype.trigger = function() {
  var _this = this
    , args = arguments;
  setImmediate(function() {
    _this.emit.apply(_this, args);
  });
};

Voyeur.prototype.start = function(pattern, options, callback) {
  var _this = this;
  callback = callback || function(err) { if (err) { _this._error(err); } };

  Object.freeze(_this.options);
  this.log.debug('Starting');

  fs.exists(_this.options.saveDestination, function(exists) {
    if (exists) {
      _this._load(_this.options.saveDestination, function(err) {
        if (err) {
          return _this._error(err);
        }
        _this._watch(pattern, options, callback);
        return;
      });
    }
    else {
      _this._watch(pattern, options, callback);
      return;
    }
  });

  if (_this.options.saveEvery) {
    setInterval(function() {
      _this.save(function(err) {
        if (err) {
          return _this._error(err);
        }
      });
    }, _this.options.saveEvery);
  }

  return _this;
};

Voyeur.prototype.shutdownSync = function() {
  this.saveSync();
  this.stopSync();
};

Voyeur.prototype.shutdown = function(callback) {
  var _this = this;
  _this.stop(function(err) {
    if (err) {
      return callback(err);
    }
    _this.save(callback);
  });
};

Voyeur.prototype.stop = function(callback) {
  this.stopSync();
  setImmediate(callback);
};

Voyeur.prototype.stopSync = function() {
  this._watchers.forEach(function(watcher) {
    watcher.close();
  });
};

Voyeur.prototype._load = function(destination, callback) {
  var _this = this;

  _this.log.debug('Loading', destination);

  fs.readFile(destination, function(err, data) {
    if (err) {
      return callback(err);
    }
    _this.import(JSON.parse(data));
    callback(null);
  });
};

// on osx 10.10.2 (at least) stats is unavailable from watcher:add event
// wrapping in setImmediate seems to fix, but should this poll? FIXME: ?
Voyeur.prototype._lastModFromStats = function(filepath, stats, callback) {
  setImmediate(function() {
    if (stats && stats.mtime && stats.mtime.getTime) {
      callback(null, stats.mtime.getTime());
    }
    else {
      fs.stat(filepath, function(err, stats) {
        if (err) {
          return callback(err);
        }
        callback(null, stats.mtime.getTime());
      });
    }
  });
};

Voyeur.prototype._watch = function(globPattern, globOptions, callback) {
  var _this = this;
  var ready = false;

  _this.log.debug('Watching', globPattern, globOptions);

  var watcher = chokidar.watch(globPattern, globOptions);
  _this._watchers.push(watcher);

  watcher.on('ready', function() {
    _this.log.debug('Watcher ready');
    ready = true;
    callback(null);
  });

  watcher.on('error', function(err) {
    watcher.close();
    callback(err);
  });

  watcher.on('add', function(filepath, stats) {
    _this.trigger('watcher:add', filepath, stats, watcher);
    _this._lastModFromStats(filepath, stats, function(err, lastMod) {
      if (err) {
        return _this._error(err);
      }
      if (ready || !_this.test(filepath, lastMod)) {
        _this.add(filepath, lastMod);
      }
    });
  });

  watcher.on('change', function(filepath, stats) {
    _this.trigger('watcher:change', filepath, stats, watcher);
    _this._lastModFromStats(filepath, stats, function(err, lastMod) {
      if (err) {
        return _this._error(err);
      }
      _this.add(filepath, lastMod);
    });
  });

  watcher.on('unlink', function(filepath) {
    _this.trigger('watcher:delete', filepath, watcher);
    _this.remove(filepath);
  });
};

Voyeur.prototype.import = function(db) {
  for (var relativePath in db) {
    var obj = db[relativePath];
    if (obj) {
      var item = this._create(relativePath, obj.revision, obj.data, false);
      if (obj.expired) {
        item.expired = true;
      }
      this.trigger('item:imported', item);
    }
  }
  return this;
};

Voyeur.prototype._create = function(relativePath, revision, data, providerFallback) {
  var item = this._db[relativePath] = new Item(relativePath, revision || this.options.defaultRevision, data);
  if (!Item.isValidProvider(data) && this.options.defaultProvider) {
    item.provider = this.options.defaultProvider;
  }
  if (!data && providerFallback && item.provider && this.options.autoProvide) { // if creating and no data is provided
    this._provide(item);
  }
  return item;
};

Voyeur.prototype.all = function() {
  return Object.create(this._db);
};

Voyeur.prototype._get = function(relativePath) {
  return this._db[relativePath];
};

Voyeur.prototype.get = function(relativePath) {
  var item = this._get(relativePath);
  return !item.expired || (item.expired && this.options.returnExpired) ? item : null;
};

Voyeur.prototype.add = function(relativePath, revision, data) {
  revision = revision || this.options.defaultRevision;
  if (!this._db[relativePath]) { // doesn't exist
    this.trigger('item:created', this._create(relativePath, revision, data, true));
  }
  else {
    this.update(relativePath, revision, data);
  }
  return this;
};

Voyeur.prototype.update = function(relativePath, revision, data) {
  revision = revision || this.options.defaultRevision;
  var status = this.test(relativePath, revision)
    , item = this._get(relativePath);
  if (true === status) {
    this.trigger('item:current', item);
  }
  else if (false === status) {
    var acknowledge = function acknowledgeItemExpired() {
      item.revision = revision;
      item.expired = false;
    };
    item.expired = true;
    this.trigger('item:expired', item, acknowledge);
    if (item.provider && this.options.autoProvide) {
      this._provide(item, acknowledge);
    }
  }
  else {
    throw new Error('Cannot update because "' + relativePath + '" does not exist');
  }
};

Voyeur.prototype.remove = function(relativePath) {
  // this.log.debug('remove', relativePath);
  if (this._db[relativePath]) {
    this.trigger('item:removed', this._get(relativePath));
    delete this._db[relativePath];
  }
  return this;
};

Voyeur.prototype._provide = function(item, callback) {
  var _this = this;
  callback = callback || function(err){
    if (err) {
      return _this._error(err);
    }
  };
  item.callProvider({
    timeout: _this.options.providerTimeout,
    timeoutOutcome: _this.options.providerTimeoutOutcome
  }, callback);
};

Voyeur.prototype.test = function(relativePath, revision) {
  revision = revision || this.options.defaultRevision;
  if (this._db[relativePath]) {
    return revision == this._db[relativePath].revision;
  }
  else {
    return;
  }
};

Voyeur.prototype.stringify = function() {
  return this.options.saveDestination ? JSON.stringify(this._db, null, 2) : JSON.stringify(this._db);
};

Voyeur.prototype.save = function(destination, callback) {
  if (typeof destination === 'function') {
    callback = destination;
    destination = null;
  }
  destination = destination || this.options.saveDestination;
  fs.writeFile(destination, this.stringify(), callback);
};

Voyeur.prototype.saveSync = function(destination) {
  destination = destination || this.options.saveDestination;
  this.log.debug('saveSync', destination);
  fs.writeFileSync(destination, this.stringify());
};

Voyeur.consoleLogger = {
    info: console.info
  , warn: console.warn
  , error: console.error
  , debug: console.log
  , log: console.log
};

var nooplogger = {
    info: function(){}
  , warn: function(){}
  , error: function(){}
  , debug: function(){}
  , log: function(){}
};

module.exports = Voyeur;
<|endoftext|>


<commit_before>// ==UserScript==
// @name        VK Code
// @namespace   vkcode
// @description VK Code Highlighter
// @author      Queyenth
// @include     *vk.com/im*
// @version     1
// @grant       none
// ==/UserScript==

// Replace 12 with any size you want
var FONT_SIZE = 'font-size: 10px';
// Replace monospace with your favourite font
var FONT_FAMILY = "font-family: 'monaco for powerline'";
//
var TAB_TO_SPACE = "  ";

// List of all themes: https://github.com/queyenth/vkcode/tree/gh-pages/highlight.js/styles
var THEME = 'mono-blue';

// Creating a new stylesheet
var sheet = (function() {
  var style = document.createElement("style");
  // WebKit hack
  style.appendChild(document.createTextNode(""));
  document.head.appendChild(style);

  return style.sheet;
})();

function loadScript(scriptSrc, callback) {
  var head = document.getElementsByTagName("head")[0];
  var js = document.createElement("script");
  js.type = "text/javascript";
  js.src = scriptSrc;

  js.onreadystatechange = callback;
  js.onload = callback;

  head.appendChild(js);
}

function loadCss(cssHref) {
  var head = document.getElementsByTagName("head")[0];
  var cssElement = document.createElement("link");
  cssElement.rel = "stylesheet";
  cssElement.href = cssHref;
  head.appendChild(cssElement);
}

function addCSSRule(sheet, selector, rules, index) {
  if ("insertRule" in sheet) {
    sheet.insertRule(selector + "{" + rules + "}", index);
  }
  else if ("addRule" in sheet) {
    sheet.addRule(selector, rules, index);
  }
}

function initCssRules() {
  addCSSRule(sheet, 'pre', FONT_FAMILY);
  addCSSRule(sheet, 'pre code', FONT_FAMILY);
  addCSSRule(sheet, 'pre', FONT_SIZE);
  addCSSRule(sheet, 'pre', 'margin: 0;');
  addCSSRule(sheet, '.hljs', 'padding: 1em !important;');
}

function parseMessage(block) {
  if ($(block).html().indexOf("</code>") === -1) $(block).html($(block).html() + "
");
  $(block).html($(block).html().replace("<code>
", "
").replace("</code>", "
"));
  $(block).html($(block).html().replace(/\\t( )*/g, TAB_TO_SPACE));
  // TODO: replace all smiles, and remove all links, << >> etc
}

function highlightBlock(block) {
  if ($(block).html().indexOf("<code>
") > -1) {
    parseMessage(block);
    hljs.highlightBlock($(block).children('pre').children('code')[0]);
    hljs.lineNumbersBlock($(block).children('pre').children('code')[0]);
  }
}

function getImFromTr(trblock) {
  return $(trblock).find('.im_msg_text');
}

function IMMutationObserver() {
  var observer = new MutationObserver(
    function(mutations) {
      mutations.forEach(function(mutation) {
        for (var i = 0; i < mutation.addedNodes.length; i++) {
          var msg = getImFromTr(mutation.addedNodes[i]);
          msg.each(function(i, block) {
            highlightBlock(block);
          });
        }
      });
    }
  );
  observer.observe($('.im_log_t tbody:visible')[0], {childList: true});
  return observer;
}

function highlightAllBlocksOnPage() {
  $('.im_msg_text').each(function(i, block) {
    highlightBlock(block);
  });
}

loadScript("https://code.jquery.com/jquery-2.1.4.min.js", function() {
  $(document).ready(function() {
    loadCss("https://queyenth.github.io/vkcode/highlight.js/styles/"+THEME+".css");
    initCssRules();
    loadScript("https://queyenth.github.io/vkcode/highlight.js/highlight.pack.js", function() {
      loadScript("https://queyenth.github.io/vkcode/highlight.js/highlightjs-line-numbers.min.js", function() {
        var observer = IMMutationObserver();
        hljs.configure({useBR: true, tabReplace: '  '});
        highlightAllBlocksOnPage();
        window.setTimeout(function() {
          $("#im_dialogs").on("click", ".dialogs_row", function() {
            console.log("pressed chat!");
          });
        }, 500);
        $(".im_tab, .im_tab_selected").on("click", function() {
          console.log("pressed chat!");
          window.setTimeout(function() {
            highlightAllBlocksOnPage();
            observer.disconnect();
            observer = IMMutationObserver();
          }, 500);
        });
      });
    });
  });
});
<commit_msg>Fixed #1<commit_after>// ==UserScript==
// @name        VK Code
// @namespace   vkcode
// @description VK Code Highlighter
// @author      Queyenth
// @include     *vk.com/*
// @version     1
// @grant       none
// ==/UserScript==

// Replace 12 with any size you want
var FONT_SIZE = 'font-size: 10px';
// Replace monospace with your favourite font
var FONT_FAMILY = "font-family: 'monaco for powerline'";
//
var TAB_TO_SPACE = "  ";

// List of all themes: https://github.com/queyenth/vkcode/tree/gh-pages/highlight.js/styles
//var THEME = 'agate';
//var THEME = 'androidstudio';
//var THEME = 'arta';
//var THEME = 'ascetic';
//var THEME = 'atelier-cave.dark';
//var THEME = 'atelier-cave.light';
//var THEME = 'atelier-dune.dark';
//var THEME = 'atelier-dune.light';
//var THEME = 'atelier-estuary.dark';
//var THEME = 'atelier-estuary.light';
//var THEME = 'atelier-forest.dark';
//var THEME = 'atelier-forest.light';
//var THEME = 'atelier-heath.dark';
//var THEME = 'atelier-heath.light';
//var THEME = 'atelier-lakeside.dark';
//var THEME = 'atelier-lakeside.light';
//var THEME = 'atelier-plateau.dark';
//var THEME = 'atelier-plateau.light';
//var THEME = 'atelier-savanna.dark';
//var THEME = 'atelier-savanna.light';
//var THEME = 'atelier-seaside.dark';
//var THEME = 'atelier-seaside.light';
//var THEME = 'atelier-sulphurpool.dark';
//var THEME = 'atelier-sulphurpool.light';
//var THEME = 'brown_paper';
//var THEME = 'brown_papersq.png';
//var THEME = 'codepen-embed';
//var THEME = 'color-brewer';
//var THEME = 'dark';
//var THEME = 'darkula';
//var THEME = 'default';
//var THEME = 'docco';
//var THEME = 'far';
//var THEME = 'foundation';
//var THEME = 'github';
//var THEME = 'github-gist';
//var THEME = 'googlecode';
//var THEME = 'hybrid';
//var THEME = 'idea';
//var THEME = 'ir_black';
//var THEME = 'kimbie.dark';
//var THEME = 'kimbie.light';
//var THEME = 'magula';
var THEME = 'mono-blue';
//var THEME = 'monokai';
//var THEME = 'monokai_sublime';
//var THEME = 'obsidian';
//var THEME = 'paraiso.dark';
//var THEME = 'paraiso.light';
//var THEME = 'pojoaque';
//var THEME = 'pojoaque.jpg';
//var THEME = 'railscasts';
//var THEME = 'rainbow';
//var THEME = 'school_book';
//var THEME = 'school_book.png';
//var THEME = 'solarized_dark';
//var THEME = 'solarized_light';
//var THEME = 'sunburst';
//var THEME = 'tomorrow';
//var THEME = 'tomorrow-night-blue';
//var THEME = 'tomorrow-night-bright';
//var THEME = 'tomorrow-night';
//var THEME = 'tomorrow-night-eighties';
//var THEME = 'vs';
//var THEME = 'xcode';
//var THEME = 'zenburn';

// Creating a new stylesheet
var sheet = (function() {
  var style = document.createElement("style");
  // WebKit hack
  style.appendChild(document.createTextNode(""));
  document.head.appendChild(style);

  return style.sheet;
})();

function loadScript(scriptSrc, callback) {
  var head = document.getElementsByTagName("head")[0];
  var js = document.createElement("script");
  js.type = "text/javascript";
  js.src = scriptSrc;

  js.onreadystatechange = callback;
  js.onload = callback;

  head.appendChild(js);
}

function loadCss(cssHref) {
  var head = document.getElementsByTagName("head")[0];
  var cssElement = document.createElement("link");
  cssElement.rel = "stylesheet";
  cssElement.href = cssHref;
  head.appendChild(cssElement);
}

function addCSSRule(sheet, selector, rules, index) {
  if ("insertRule" in sheet) {
    sheet.insertRule(selector + "{" + rules + "}", index);
  }
  else if ("addRule" in sheet) {
    sheet.addRule(selector, rules, index);
  }
}

function initCssRules() {
  addCSSRule(sheet, 'pre', FONT_FAMILY);
  addCSSRule(sheet, 'pre code', FONT_FAMILY);
  addCSSRule(sheet, 'pre', FONT_SIZE);
  addCSSRule(sheet, 'pre', 'margin: 0;');
  addCSSRule(sheet, '.hljs', 'padding: 1em !important;');
}

function createActualHTML(block) {
  $(block).html($(block).html().replace("<code>
", "
").replace("</code>", "
"));
}

function replaceTabs() {
  createActualHTML($('.im_editable')[0]);
  var block = $('.im_editable pre code');
  block.html(block.html().replace(/^ /g, ' '));
  // var lines = block.html().split(/
/g);
  // var firstLevel = lines[0].match(/
 /g).length();
  while (blocl.html().match(/
 /g) != null)
    block.html(block.replace(/
  /g, "
\t"))
  //alert("HI");
}

function parseMessage(block) {
  if ($(block).html().indexOf("</code>") === -1) $(block).html($(block).html() + "
");
  createActualHTML(block);
  $(block).html($(block).html().replace(/\\t( )*/g, TAB_TO_SPACE));
  // TODO: replace all smiles, and remove all links, << >> etc
}

function highlightBlock(block) {
  if ($(block).html().indexOf("<code>
") > -1) {
    parseMessage(block);
    hljs.highlightBlock($(block).children('pre').children('code')[0]);
    hljs.lineNumbersBlock($(block).children('pre').children('code')[0]);
  }
}

function getImFromTr(trblock) {
  return $(trblock).find('.im_msg_text');
}

function IMMutationObserver() {
  var observer = new MutationObserver(
    function(mutations) {
      mutations.forEach(function(mutation) {
        for (var i = 0; i < mutation.addedNodes.length; i++) {
          var msg = getImFromTr(mutation.addedNodes[i]);
          msg.each(function(i, block) {
            highlightBlock(block);
          });
        }
      });
    }
  );
  observer.observe($('.im_log_t tbody:visible')[0], {childList: true});
  return observer;
}

function highlightAllBlocksOnPage() {
  $('.im_msg_text').each(function(i, block) {
    highlightBlock(block);
  });
}

loadScript("https://code.jquery.com/jquery-2.1.4.min.js", function() {
  $(document).ready(function() {
    loadCss("https://queyenth.github.io/vkcode/highlight.js/styles/"+THEME+".css");
    initCssRules();
    loadScript("https://queyenth.github.io/vkcode/highlight.js/highlight.pack.js", function() {
      loadScript("https://queyenth.github.io/vkcode/highlight.js/highlightjs-line-numbers.min.js", function() {
        var checkIfChatPage = window.setInterval(function() {
          if ($(".im_tab_selected:visible").length) {
            var observer = IMMutationObserver();
            hljs.configure({useBR: true, tabReplace: '  '});
            highlightAllBlocksOnPage();
            window.setTimeout(function() {
              $("#im_dialogs").on("click", ".dialogs_row", function() {
                console.log("pressed chat!");
              });
            }, 500);
            $(".im_tab, .im_tab_selected").on("click", function() {
              console.log("pressed chat!");
              window.setTimeout(function() {
                highlightAllBlocksOnPage();
                observer.disconnect();
                observer = IMMutationObserver();
              }, 500);
            });
            $(".im_editable").on("keydown", function(event) {
              if (event.which == 13) {
                //event.preventDefault();
                replaceTabs();
              }
            });
          }
        }, 500);
      });
    });
  });
});
<|endoftext|>