<commit_before>
import $logger from 'beaver-logger/client';

import { PayPalCheckout } from '../components';
import xcomponent from 'xcomponent/src';
import { isEligible } from './eligibility';
import { loadScript } from '../lib';
import { config } from '../config';

const PROD_BASE_URL = 'https://www.paypal.com/checkoutnow';
const BUTTON_JS_URL = '//www.paypalobjects.com/api/button.js';

let buttonJS;

/*  Global State
    ------------

    The legacy integration used global window.paypal.checkout.* methods which kept (essentially) global state
    regarding open windows, component, etc.

    Since we're emulating that integration, we have to store a little bit of global state, including the currently
    active component and any config that needs to be persisted from the setup() call.
*/

let env = 'production';

let LOG_PREFIX = `ppxo_legacy`;

function logDebug(event, payload = {}) {
    $logger.debug(`${LOG_PREFIX}_${event}`, payload);
}

function logInfo(event, payload = {}) {
    $logger.info(`${LOG_PREFIX}_${event}`, payload);
}

function logWarning(event, payload = {}) {
    $logger.warn(`${LOG_PREFIX}_${event}`, payload);
}

function logError(event, payload = {}) {
    $logger.error(`${LOG_PREFIX}_${event}`, payload);
}

function loadButtonJS() {

    if (buttonJS) {
        return buttonJS;
    }

    logDebug(`buttonjs_load`);

    buttonJS = loadScript(BUTTON_JS_URL);

    return buttonJS.then(result => {
        logDebug(`buttonjs_load_success`);
        return result;
    }).catch(err => {
        logError(`buttonjs_load_error`, { error: err.stack || err.toString() });
        throw err;
    });
}

function redirect(url) {
    logInfo(`redirect`, { url });
    window.location = url;
}

function matchToken(token) {
    return token && token.match(/^(EC-)?[A-Z0-9]{17}$/);
}

/*  Parse Token
    -----------

    We are passed either a token, or a url containing the token. In order to run the new checkout component we need to
    strip out the token from the url in order to pass it down as a prop
*/

function parseToken(token) {

    if (!token) {
        return;
    }

    // We may get lucky and be passed a token straight off the bar

    if (token.match(/^(EC-)?[A-Z0-9]{17}$/)) {
        return token;
    }

    // Otherwise strip the token from the url we're sent

    let match = token.match(/token=((EC-)?[A-Z0-9]{17})/);

    if (match) {
        return match[1];
    }
}

function getFullpageRedirectUrl(token) {
    let baseUrl = env && PayPalCheckout.envUrls[env] || PROD_BASE_URL;
    let url = matchToken(token) ? `${baseUrl}?token=${token}` : token;
    return url;
}

/*  Get Token
    ---------

    Normally in the component world, getToken would be a user-provided function which passes a callback, and expects
    that callback to be called with either an error, or an EC token.

    In our case, we can emulate these callback calls by setting over the startFlow and closeFlow globals, and using
    them as our success and failure cases.

    Note: this method is set to `precall: true` mode. This means that it will be called the moment the component is
    inited on the page. This means that the moment we initialize, we're ready to start accepting a token via one of the
    global methods.
*/

function getPaymentToken(resolve, reject) {

    function reset() {

        // Once our callback has been called, we can set the global methods to their original values

        window.paypal.checkout.initXO = initXO;
        window.paypal.checkout.startFlow = startFlow;
        window.paypal.checkout.closeFlow = closeFlow;
    }

    // We don't want initXO to do anything during this process. We've already opened the window so we're good to go.

    window.paypal.checkout.initXO = function() {
        logDebug(`paymenttoken_initxo`);
    };

    // startFlow is our 'success' case - we get a token, and we can pass it back to the caller

    window.paypal.checkout.startFlow = (token) => {
        logDebug(`paymenttoken_startflow`, { token });

        reset();

        let ecToken = parseToken(token);

        if (!ecToken) {
            logError(`paymenttoken_startflow_notoken`, { token });
            throw new Error(`Expected "${token}" passed to window.paypal.checkout.startFlow to contain express-checkout payment token`);
        }

        if (!isEligible()) {
            logDebug(`paymenttoken_startflow_ineligible`, { token: ecToken });
            return redirect(getFullpageRedirectUrl(token));
        }

        if (matchToken(token)) {
            logDebug(`paymenttoken_startflow_tokenpassed`, { token });
        } else {
            logDebug(`paymenttoken_startflow_urlpassed`, { token });
            this.updateProps({
                url: token
            });
        }

        resolve(ecToken);
    };

    // closeFlow is our 'error' case - we can call our callback with an error

    window.paypal.checkout.closeFlow = () => {
        logWarning(`paymenttoken_closeflow`);

        reset();

        reject(new Error('Close Flow Called'));

        // We also want to close the component at this point, to preserve the original legacy behavior

        this.close();
    };
}

function renderButton(id, container, options) {

    let buttonDom = window.paypal.button.create(id, {
        lc:    options.locale || `${config.locale.lang}_${config.locale.country}`,
        color: options.color  || 'gold',
        shape: options.shape  || 'pill',
        size:  options.size   || 'small'
    }, {
        label: 'checkout',
        type: 'button'
    });

    document.getElementById(container).appendChild(buttonDom.el);

    handleClick(buttonDom.el.childNodes[0], options);
}

function renderButtons(id, options) {

    return loadButtonJS().then(() => {

        if (options.container) {

            if (options.container instanceof Array) {
                options.container.forEach(container => {
                    renderButton(id, container, options);
                });

            } else {
                renderButton(id, options.container, options);
            }
        }

        if (options.buttons instanceof Array) {

            options.buttons.forEach(button => {
                renderButton(id, button.container, button);
            });
        }
    });
}

function urlWillRedirectPage(url) {

    if (url.indexOf('#') === -1) {
        return true;
    }

    if (url.split('#')[0] === window.location.href.split('#')[0]) {
        return false;
    }

    return true;
}

/*  Init PayPal Checkout
    --------------------

    Initialize the PayPalCheckout component with some standard props:

    - Pass in env from global state (saved during setup() call)
    - Return to success url on payment authorize
    - Return to cancel url on cancel
*/

function initPayPalCheckout(props = {}) {

    logInfo(`init_checkout`);

    PayPalCheckout.autocloseParentTemplate = false;

    return PayPalCheckout.init({

        env,

        paymentToken: getPaymentToken,

        onPaymentAuthorize({ returnUrl }) {

            logInfo(`payment_authorized`);

            if (!urlWillRedirectPage(returnUrl)) {
                this.closeParentTemplate();
            }

            return redirect(returnUrl);
        },

        onPaymentCancel({ cancelUrl }) {

            logInfo(`payment_canceled`);

            if (!urlWillRedirectPage(cancelUrl)) {
                logInfo(`hash_change_close_overlay`);
                this.closeParentTemplate();
            }

            return redirect(cancelUrl);
        },

        fallback(url) {
            logInfo(`fallback`, { url });
            redirect(url);
        },

        ...props
    });
}

function handleClick(button, options) {

    if (!isEligible()) {
        return;
    }

    button.addEventListener('click', event => {

        if (options.condition instanceof Function && !options.condition.call()) {
            logDebug(`button_click_condition_disabled`);
            return;
        }

        logInfo(`button_click`);

        if (options.click) {
            logDebug(`button_clickhandler`);

            event.preventDefault();
            initPayPalCheckout().render();
            options.click.call();

        } else {
            logDebug(`button_hijack`);

            initPayPalCheckout({
                paymentToken: xcomponent.CONSTANTS.PROP_DEFER_TO_URL
            }).renderHijack(button.form);
        }
    });
}

/*  Setup
    -----

    Emulate window.paypal.checkout.setup.

    The purpose of this method is to:

    - Set up configuration for the incontext flow
    - Render a button to initiate the checkout window
*/

function setup(id, options = {}) {
    logInfo(`setup`);

    env = options.environment;

    renderButtons(id, options);
}

/*  Init XO
    -------

    Emulate paypal.checkout.initXO

    Normally this would be used only to open the checkout page. But here we can just kick off the whole flow, since
    getToken will handle loading the token into the window for us.
*/

function initXO() {

    logDebug(`initxo`);

    if (!isEligible()) {
        return;
    }

    initPayPalCheckout().render();
}

/*  Start Flow
    ----------

    Emulate paypal.checkout.startFlow

    Normally this would be used to load the url into the browser after the window has already been opened. Again, we
    can just kick off the whole flow here, on the off chance that a merchant calls us on button click. Normally this
    method will have been patched over in getToken.
*/

function startFlow(token) {

    logDebug(`startflow`, { token });

    let ecToken = parseToken(token);

    if (!ecToken) {
        logWarning(`startflow_notoken`);
        throw new Error(`Expected "${token}" passed to window.paypal.checkout.startFlow to contain express-checkout payment token`);
    }

    if (!isEligible()) {
        logDebug(`startflow_ineligible`);
        return redirect(getFullpageRedirectUrl(token));
    }

    initPayPalCheckout({
        url: matchToken(token) ? null : token,
        paymentToken: ecToken
    }).render();
}

/*  Close Flow
    ----------

    Emulate paypal.checkout.closeFlow

    Close the component in case of any error on the merchant side.
*/

function closeFlow() {
    logDebug(`closeflow`);

    console.warn('Checkout is not open, can not be closed');
}

/*  On Document Ready
    -----------------

    Call the callback when the document is ready, or immediately if the document has already loaded
*/

let documentLoaded = document.readyState === 'complete' || document.readyState === 'loaded';

function onDocumentReady(method) {

    if (documentLoaded) {
        return method();
    }

    return document.addEventListener('DOMContentLoaded', event => {
        documentLoaded = true;
        return method();
    });
}

/*  PayPal Checkout Ready
    ---------------------

    Call window.paypalCheckoutReady on document ready, if it has been defined by the merchant
*/

if (window.paypalCheckoutReady instanceof Function) {
    logDebug(`paypal_checkout_ready_passed`);
    onDocumentReady(() => {
        logDebug(`paypal_checkout_ready`);
        window.paypalCheckoutReady();
    });
}

/*  Scan for buttons
    ----------------

    Scan for any buttons on the page with a data-paypal-button attribute and auto-attach the PaypalCheckout component to them
*/

onDocumentReady(() => {

    if (!isEligible()) {
        return;
    }

    let buttons = Array.prototype.slice.call(document.querySelectorAll('[data-paypal-button]'));

    if (buttons && buttons.length) {
        logDebug(`data_paypal_button`, { number: buttons.length });
    }

    for (let button of buttons) {

        let buttonEnv = button.attributes['data-env'] && button.attributes['data-env'].value;

        if (!env && button.attributes['data-sandbox']) {
            buttonEnv = 'sandbox';
        }

        button.addEventListener('click', event => {

            let target = button.form ? button.form : button;

            initPayPalCheckout({
                env: buttonEnv,
                paymentToken: xcomponent.CONSTANTS.PROP_DEFER_TO_URL
            }).renderHijack(target);
        });
    }
});

/*  paypal.checkout
    ---------------

    Set paypal.checkout global functions to support legacy integrations
*/

window.paypal = window.paypal || {};
window.paypal.checkout = window.paypal.checkout || {};

window.paypal.checkout.setup = setup;
window.paypal.checkout.initXO = initXO;
window.paypal.checkout.startFlow = startFlow;
window.paypal.checkout.closeFlow = closeFlow;
<commit_msg>Log error messaging when eventing is used.<commit_after>
import $logger from 'beaver-logger/client';

import { PayPalCheckout } from '../components';
import xcomponent from 'xcomponent/src';
import { isEligible } from './eligibility';
import { loadScript } from '../lib';
import { config } from '../config';

const PROD_BASE_URL = 'https://www.paypal.com/checkoutnow';
const BUTTON_JS_URL = '//www.paypalobjects.com/api/button.js';

let buttonJS;

/*  Global State
    ------------

    The legacy integration used global window.paypal.checkout.* methods which kept (essentially) global state
    regarding open windows, component, etc.

    Since we're emulating that integration, we have to store a little bit of global state, including the currently
    active component and any config that needs to be persisted from the setup() call.
*/

let env = 'production';

let LOG_PREFIX = `ppxo_legacy`;

function logDebug(event, payload = {}) {
    $logger.debug(`${LOG_PREFIX}_${event}`, payload);
}

function logInfo(event, payload = {}) {
    $logger.info(`${LOG_PREFIX}_${event}`, payload);
}

function logWarning(event, payload = {}) {
    $logger.warn(`${LOG_PREFIX}_${event}`, payload);
}

function logError(event, payload = {}) {
    $logger.error(`${LOG_PREFIX}_${event}`, payload);
}

function loadButtonJS() {

    if (buttonJS) {
        return buttonJS;
    }

    logDebug(`buttonjs_load`);

    buttonJS = loadScript(BUTTON_JS_URL);

    return buttonJS.then(result => {
        logDebug(`buttonjs_load_success`);
        return result;
    }).catch(err => {
        logError(`buttonjs_load_error`, { error: err.stack || err.toString() });
        throw err;
    });
}

function redirect(url) {
    logInfo(`redirect`, { url });
    window.location = url;
}

function matchToken(token) {
    return token && token.match(/^(EC-)?[A-Z0-9]{17}$/);
}

/*  Parse Token
    -----------

    We are passed either a token, or a url containing the token. In order to run the new checkout component we need to
    strip out the token from the url in order to pass it down as a prop
*/

function parseToken(token) {

    if (!token) {
        return;
    }

    // We may get lucky and be passed a token straight off the bar

    if (token.match(/^(EC-)?[A-Z0-9]{17}$/)) {
        return token;
    }

    // Otherwise strip the token from the url we're sent

    let match = token.match(/token=((EC-)?[A-Z0-9]{17})/);

    if (match) {
        return match[1];
    }
}

function getFullpageRedirectUrl(token) {
    let baseUrl = env && PayPalCheckout.envUrls[env] || PROD_BASE_URL;
    let url = matchToken(token) ? `${baseUrl}?token=${token}` : token;
    return url;
}

/*  Get Token
    ---------

    Normally in the component world, getToken would be a user-provided function which passes a callback, and expects
    that callback to be called with either an error, or an EC token.

    In our case, we can emulate these callback calls by setting over the startFlow and closeFlow globals, and using
    them as our success and failure cases.

    Note: this method is set to `precall: true` mode. This means that it will be called the moment the component is
    inited on the page. This means that the moment we initialize, we're ready to start accepting a token via one of the
    global methods.
*/

function getPaymentToken(resolve, reject) {

    function reset() {

        // Once our callback has been called, we can set the global methods to their original values

        window.paypal.checkout.initXO = initXO;
        window.paypal.checkout.startFlow = startFlow;
        window.paypal.checkout.closeFlow = closeFlow;
    }

    // We don't want initXO to do anything during this process. We've already opened the window so we're good to go.

    window.paypal.checkout.initXO = function() {
        logDebug(`paymenttoken_initxo`);
    };

    // startFlow is our 'success' case - we get a token, and we can pass it back to the caller

    window.paypal.checkout.startFlow = (token) => {
        logDebug(`paymenttoken_startflow`, { token });

        reset();

        let ecToken = parseToken(token);

        if (!ecToken) {
            logError(`paymenttoken_startflow_notoken`, { token });
            throw new Error(`Expected "${token}" passed to window.paypal.checkout.startFlow to contain express-checkout payment token`);
        }

        if (!isEligible()) {
            logDebug(`paymenttoken_startflow_ineligible`, { token: ecToken });
            return redirect(getFullpageRedirectUrl(token));
        }

        if (matchToken(token)) {
            logDebug(`paymenttoken_startflow_tokenpassed`, { token });
        } else {
            logDebug(`paymenttoken_startflow_urlpassed`, { token });
            this.updateProps({
                url: token
            });
        }

        resolve(ecToken);
    };

    // closeFlow is our 'error' case - we can call our callback with an error

    window.paypal.checkout.closeFlow = () => {
        logWarning(`paymenttoken_closeflow`);

        reset();

        reject(new Error('Close Flow Called'));

        // We also want to close the component at this point, to preserve the original legacy behavior

        this.close();
    };
}

function renderButton(id, container, options) {

    let buttonDom = window.paypal.button.create(id, {
        lc:    options.locale || `${config.locale.lang}_${config.locale.country}`,
        color: options.color  || 'gold',
        shape: options.shape  || 'pill',
        size:  options.size   || 'small'
    }, {
        label: 'checkout',
        type: 'button'
    });

    document.getElementById(container).appendChild(buttonDom.el);

    handleClick(buttonDom.el.childNodes[0], options);
}

function renderButtons(id, options) {

    return loadButtonJS().then(() => {

        if (options.container) {

            if (options.container instanceof Array) {
                options.container.forEach(container => {
                    renderButton(id, container, options);
                });

            } else {
                renderButton(id, options.container, options);
            }
        }

        if (options.buttons instanceof Array) {

            options.buttons.forEach(button => {
                renderButton(id, button.container, button);
            });
        }
    });
}

function urlWillRedirectPage(url) {

    if (url.indexOf('#') === -1) {
        return true;
    }

    if (url.split('#')[0] === window.location.href.split('#')[0]) {
        return false;
    }

    return true;
}

/*  Init PayPal Checkout
    --------------------

    Initialize the PayPalCheckout component with some standard props:

    - Pass in env from global state (saved during setup() call)
    - Return to success url on payment authorize
    - Return to cancel url on cancel
*/

function initPayPalCheckout(props = {}) {

    logInfo(`init_checkout`);

    PayPalCheckout.autocloseParentTemplate = false;

    return PayPalCheckout.init({

        env,

        paymentToken: getPaymentToken,

        onPaymentAuthorize({ returnUrl }) {

            logInfo(`payment_authorized`);

            if (!urlWillRedirectPage(returnUrl)) {
                this.closeParentTemplate();
            }

            return redirect(returnUrl);
        },

        onPaymentCancel({ cancelUrl }) {

            logInfo(`payment_canceled`);

            if (!urlWillRedirectPage(cancelUrl)) {
                logInfo(`hash_change_close_overlay`);
                this.closeParentTemplate();
            }

            return redirect(cancelUrl);
        },

        fallback(url) {
            logInfo(`fallback`, { url });
            redirect(url);
        },

        ...props
    });
}

function handleClick(button, options) {

    if (!isEligible()) {
        return;
    }

    button.addEventListener('click', event => {

        if (options.condition instanceof Function && !options.condition.call()) {
            logDebug(`button_click_condition_disabled`);
            return;
        }

        logInfo(`button_click`);

        if (options.click) {
            logDebug(`button_clickhandler`);

            event.preventDefault();
            initPayPalCheckout().render();
            options.click.call();

        } else {
            logDebug(`button_hijack`);

            initPayPalCheckout({
                paymentToken: xcomponent.CONSTANTS.PROP_DEFER_TO_URL
            }).renderHijack(button.form);
        }
    });
}

/*  Setup
    -----

    Emulate window.paypal.checkout.setup.

    The purpose of this method is to:

    - Set up configuration for the incontext flow
    - Render a button to initiate the checkout window
*/

function setup(id, options = {}) {
    logInfo(`setup`);

    env = options.environment;

    renderButtons(id, options);
}

/*  Init XO
    -------

    Emulate paypal.checkout.initXO

    Normally this would be used only to open the checkout page. But here we can just kick off the whole flow, since
    getToken will handle loading the token into the window for us.
*/

function initXO() {

    logDebug(`initxo`);

    if (!isEligible()) {
        return;
    }

    initPayPalCheckout().render();
}

/*  Start Flow
    ----------

    Emulate paypal.checkout.startFlow

    Normally this would be used to load the url into the browser after the window has already been opened. Again, we
    can just kick off the whole flow here, on the off chance that a merchant calls us on button click. Normally this
    method will have been patched over in getToken.
*/

function startFlow(token) {

    logDebug(`startflow`, { token });

    let ecToken = parseToken(token);

    if (!ecToken) {
        logWarning(`startflow_notoken`);
        throw new Error(`Expected "${token}" passed to window.paypal.checkout.startFlow to contain express-checkout payment token`);
    }

    if (!isEligible()) {
        logDebug(`startflow_ineligible`);
        return redirect(getFullpageRedirectUrl(token));
    }

    initPayPalCheckout({
        url: matchToken(token) ? null : token,
        paymentToken: ecToken
    }).render();
}

/*  Close Flow
    ----------

    Emulate paypal.checkout.closeFlow

    Close the component in case of any error on the merchant side.
*/

function closeFlow() {
    logDebug(`closeflow`);

    console.warn('Checkout is not open, can not be closed');
}

/*  On Document Ready
    -----------------

    Call the callback when the document is ready, or immediately if the document has already loaded
*/

let documentLoaded = document.readyState === 'complete' || document.readyState === 'loaded';

function onDocumentReady(method) {

    if (documentLoaded) {
        return method();
    }

    return document.addEventListener('DOMContentLoaded', event => {
        documentLoaded = true;
        return method();
    });
}

/*  PayPal Checkout Ready
    ---------------------

    Call window.paypalCheckoutReady on document ready, if it has been defined by the merchant
*/

if (window.paypalCheckoutReady instanceof Function) {
    logDebug(`paypal_checkout_ready_passed`);
    onDocumentReady(() => {
        logDebug(`paypal_checkout_ready`);
        window.paypalCheckoutReady();
    });
}

/*  Scan for buttons
    ----------------

    Scan for any buttons on the page with a data-paypal-button attribute and auto-attach the PaypalCheckout component to them
*/

onDocumentReady(() => {

    if (!isEligible()) {
        return;
    }

    let buttons = Array.prototype.slice.call(document.querySelectorAll('[data-paypal-button]'));

    if (buttons && buttons.length) {
        logDebug(`data_paypal_button`, { number: buttons.length });
    }

    for (let button of buttons) {

        let buttonEnv = button.attributes['data-env'] && button.attributes['data-env'].value;

        if (!env && button.attributes['data-sandbox']) {
            buttonEnv = 'sandbox';
        }

        button.addEventListener('click', event => {

            let target = button.form ? button.form : button;

            initPayPalCheckout({
                env: buttonEnv,
                paymentToken: xcomponent.CONSTANTS.PROP_DEFER_TO_URL
            }).renderHijack(target);
        });
    }
});

/*  paypal.checkout
    ---------------

    Set paypal.checkout global functions to support legacy integrations
*/

window.paypal = window.paypal || {};
window.paypal.checkout = window.paypal.checkout || {};

window.paypal.checkout.setup = setup;
window.paypal.checkout.initXO = initXO;
window.paypal.checkout.startFlow = startFlow;
window.paypal.checkout.closeFlow = closeFlow;

window.paypal.checkout.events = {
    on(name) {
        logError(`eventing_unsupported`, { name });
    }
};
<|endoftext|>


<commit_before>/*
 *
 * Diff to HTML (diff2html.js)
 * Author: rtfpessoa
 * Date: Friday 29 August 2014
 * Last Update: Sunday 2 February 2015
 *
 * Diff command:
 *   git diff
 */

(function (window) {
    var ClassVariable;

    ClassVariable = (function () {

        var LINE_TYPE = {
            INSERTS: "d2h-ins",
            DELETES: "d2h-del",
            CONTEXT: "d2h-cntx",
            INFO: "d2h-info"
        };

        function Diff2Html() {
        }

        /*
         * Generates pretty html from string diff input
         */
        Diff2Html.prototype.getPrettyHtmlFromDiff = function (diffInput) {
            var diffJson = generateDiffJson(diffInput);
            return generateJsonHtml(diffJson);
        };

        /*
         * Generates json object from string diff input
         */
        Diff2Html.prototype.getJsonFromDiff = function (diffInput) {
            return generateDiffJson(diffInput);
        };

        /*
         * Generates pretty html from a json object
         */
        Diff2Html.prototype.getPrettyHtmlFromJson = function (diffJson) {
            return generateJsonHtml(diffJson);
        };

        /*
         * Generates pretty side by side html from string diff input
         */
        Diff2Html.prototype.getPrettySideBySideHtmlFromDiff = function (diffInput) {
            var diffJson = generateDiffJson(diffInput);
            return generateSideBySideJsonHtml(diffJson);
        };

        /*
         * Generates pretty side by side html from a json object
         */
        Diff2Html.prototype.getPrettySideBySideHtmlFromJson = function (diffJson) {
            return generateSideBySideJsonHtml(diffJson);
        };

        var generateDiffJson = function (diffInput) {
            var files = [],
                currentFile = null,
                currentBlock = null,
                oldLine = null,
                newLine = null;

            var saveBlock = function () {
                /* add previous block(if exists) before start a new file */
                if (currentBlock) {
                    currentFile.blocks.push(currentBlock);
                    currentBlock = null;
                }
            };

            var saveFile = function () {
                /*
                 * add previous file(if exists) before start a new one
                 * if it has name (to avoid binary files errors)
                 */
                if (currentFile && currentFile.newName) {
                    files.push(currentFile);
                    currentFile = null;
                }
            };

            var startFile = function () {
                saveBlock();
                saveFile();

                /* create file structure */
                currentFile = {};
                currentFile.blocks = [];
                currentFile.deletedLines = 0;
                currentFile.addedLines = 0;
            };

            var startBlock = function (line) {
                saveBlock();

                var values = /^@@ -(\d+),\d+ \+(\d+),\d+ @@.*/.exec(line) ||
                    /^@@@ -(\d+),\d+ -\d+,\d+ \+(\d+),\d+ @@@.*/.exec(line) ||
                    [0, 0, 0];

                oldLine = values[1];
                newLine = values[2];

                /* create block metadata */
                currentBlock = {};
                currentBlock.lines = [];
                currentBlock.oldStartLine = oldLine;
                currentBlock.newStartLine = newLine;
                currentBlock.header = line;
            };

            var createLine = function (line) {
                var currentLine = {};
                currentLine.content = line;

                /* fill the line data */
                if (startsWith(line, "+") || startsWith(line, " +")) {
                    currentFile.addedLines++;

                    currentLine.type = LINE_TYPE.INSERTS;
                    currentLine.oldNumber = null;
                    currentLine.newNumber = newLine++;

                    currentBlock.lines.push(currentLine);

                } else if (startsWith(line, "-") || startsWith(line, " -")) {
                    currentFile.deletedLines++;

                    currentLine.type = LINE_TYPE.DELETES;
                    currentLine.oldNumber = oldLine++;
                    currentLine.newNumber = null;

                    currentBlock.lines.push(currentLine);

                } else {
                    currentLine.type = LINE_TYPE.CONTEXT;
                    currentLine.oldNumber = oldLine++;
                    currentLine.newNumber = newLine++;

                    currentBlock.lines.push(currentLine);
                }
            };

            var diffLines = diffInput.split("\n");
            diffLines.forEach(function (line) {
                // Unmerged paths, and possibly other non-diffable files
                // https://github.com/scottgonzalez/pretty-diff/issues/11
                // Also, remove some useless lines
                if (!line || startsWith(line, "*") ||
                    startsWith(line, "new") || startsWith(line, "index")) {
                    return;
                }

                var values = [];
                if (startsWith(line, "diff")) {
                    startFile();
                } else if (currentFile && !currentFile.oldName && (values = /^--- a\/(\S+).*$/.exec(line))) {
                    currentFile.oldName = values[1];
                } else if (currentFile && !currentFile.newName && (values = /^\+\+\+ b\/(\S+).*$/.exec(line))) {
                    currentFile.newName = values[1];

                    var fileSplit = currentFile.newName.split(".");
                    currentFile.language = fileSplit[fileSplit.length - 1];
                } else if (currentFile && startsWith(line, "@@")) {
                    startBlock(line);
                } else if (currentBlock) {
                    createLine(line);
                }
            });

            saveBlock();
            saveFile();

            return files;
        };

        /*
         * Line By Line HTML
         */

        var generateJsonHtml = function (diffFiles) {
            return "
\n" +
                diffFiles.map(function (file) {
                    return "
\n" +
                        "
\n" +
                        "
\n" +
                        "         +" + file.addedLines + "\n" +
                        "         -" + file.deletedLines + "\n" +
                        "
\n" +
                        "
" + getDiffName(file.oldName, file.newName) + "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "         " + generateFileHtml(file) +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n";
                }).join("\n") +
                "
\n";
        };

        var generateFileHtml = function (file) {
            return file.blocks.map(function (block) {

                var lines = "
\n" +
                    "  	\n" +
                    "  " +
                    "
" + escape(block.header) + "
" +
                    "  	\n" +
                    "
\n";

                for (var i = 0; i < block.lines.length; i++) {
                    var prevLine = block.lines[i - 1];
                    var line = block.lines[i];
                    var newLine = block.lines[i + 1];
                    var nextNewLine = block.lines[i + 2];

                    var isOppositeTypeTwoLineBlock =
                        line.type == LINE_TYPE.DELETES &&
                        newLine && newLine.type == LINE_TYPE.INSERTS &&
                        (!nextNewLine || nextNewLine && nextNewLine.type != LINE_TYPE.INSERTS) &&
                        (!prevLine || prevLine && prevLine.type != LINE_TYPE.DELETES);

                    var escapedLine = escape(line.content);

                    if (isOppositeTypeTwoLineBlock) {
                        var nextEscapedLine = escape(newLine.content);

                        var diff = diffHighlight(escapedLine, nextEscapedLine);

                        lines += generateLineHtml(line.type, line.oldNumber, line.newNumber, diff.o) +
                        generateLineHtml(newLine.type, newLine.oldNumber, newLine.newNumber, diff.n);

                        i++;
                    } else {
                        lines += generateLineHtml(line.type, line.oldNumber, line.newNumber, escapedLine);
                    }
                }

                return lines;
            }).join("\n");
        };

        var generateLineHtml = function (type, oldNumber, newNumber, content) {
            return "
\n" +
                "  " +
                "
" + valueOrEmpty(oldNumber) + "
" +
                "
" + valueOrEmpty(newNumber) + "
" +
                "  	\n" +
                "  " +
                "
" + content + "
" +
                "  	\n" +
                "
\n";
        };

        /*
         * Side By Side HTML (work in progress)
         */

        var generateSideBySideJsonHtml = function (diffFiles) {
            return "
\n" +
                diffFiles.map(function (file) {
                    var diffs = generateSideBySideFileHtml(file);

                    return "
\n" +
                        "
\n" +
                        "
\n" +
                        "         +" + file.addedLines + "\n" +
                        "         -" + file.deletedLines + "\n" +
                        "
\n" +
                        "
" + getDiffName(file.oldName, file.newName) + "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "           " + diffs.left +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "           " + diffs.right +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n";
                }).join("\n") +
                "
\n";
        };

        var generateSideBySideFileHtml = function (file) {
            var fileHtml = {};
            fileHtml.left = "";
            fileHtml.right = "";

            file.blocks.forEach(function (block) {

                fileHtml.left += "
\n" +
                "  	\n" +
                "  " +
                "
" + escape(block.header) + "
" +
                "  	\n" +
                "
\n";

                fileHtml.right += "
\n" +
                "  	\n" +
                "  " +
                "

" +
                "  	\n" +
                "
\n";

                for (var i = 0; i < block.lines.length; i++) {
                    var prevLine = block.lines[i - 1];
                    var line = block.lines[i];
                    var newLine = block.lines[i + 1];
                    var nextNewLine = block.lines[i + 2];

                    var isOpositeTypeTwoLineBlock = line.type == LINE_TYPE.DELETES && newLine && newLine.type == LINE_TYPE.INSERTS &&
                        (!nextNewLine || nextNewLine && nextNewLine.type != LINE_TYPE.INSERTS) &&
                        (!prevLine || prevLine && prevLine.type != LINE_TYPE.DELETES);

                    var escapedLine = escape(line.content);

                    if (isOpositeTypeTwoLineBlock) {
                        var nextEscapedLine = escape(newLine.content);

                        var diff = diffHighlight(escapedLine, nextEscapedLine);

                        fileHtml.left += generateSingleLineHtml(line.type, line.oldNumber, diff.o);
                        fileHtml.right += generateSingleLineHtml(newLine.type, newLine.newNumber, diff.n);

                        i++;
                    } else if (line.type == LINE_TYPE.DELETES) {
                        fileHtml.left += generateSingleLineHtml(line.type, line.oldNumber, escapedLine);
                        fileHtml.right += generateSingleLineHtml(LINE_TYPE.CONTEXT, "", "", "");
                    } else if (line.type == LINE_TYPE.INSERTS) {
                        fileHtml.left += generateSingleLineHtml(LINE_TYPE.CONTEXT, "", "", "");
                        fileHtml.right += generateSingleLineHtml(line.type, line.newNumber, escapedLine);
                    } else {
                        fileHtml.left += generateSingleLineHtml(line.type, line.oldNumber, escapedLine);
                        fileHtml.right += generateSingleLineHtml(line.type, line.newNumber, escapedLine);
                    }
                }

            });

            return fileHtml;
        };

        var generateSingleLineHtml = function (type, number, content) {
            return "
\n" +
                "    " + number + "	\n" +
                "    " +
                "
" + content + "
" +
                "    	\n" +
                "
\n";
        };

        /*
         * HTML Helpers
         */

        var getDiffName = function (oldFilename, newFilename) {
            if (oldFilename && newFilename && oldFilename !== newFilename) {
                return oldFilename + " -> " + newFilename;
            } else if (newFilename) {
                return newFilename;
            } else if (oldFilename) {
                return oldFilename;
            } else {
                return "Unknown filename";
            }
        };

        var removeIns = function (line) {
            return line.replace(/(((.|\n)*?)<\/ins>)/g, "");
        };

        var removeDel = function (line) {
            return line.replace(/(((.|\n)*?)<\/del>)/g, "");
        };

        /*
         * Utils
         */

        function escape(str) {
            return str.slice(0)
                .replace(/&/g, "&")
                .replace(/</g, "<")
                .replace(/>/g, ">")
                .replace(/\t/g, "    ");
        }

        function startsWith(str, start) {
            return str.indexOf(start) === 0;
        }

        function valueOrEmpty(value) {
            return value ? value : "";
        }

        function diffHighlight(diffLine1, diffLine2) {
            /* remove the initial -/+ to avoid always having diff in the first char */
            var highlightedLine = diffString(diffLine1.substr(1), diffLine2.substr(1));

            return {
                o: diffLine1.charAt(0) + removeIns(highlightedLine),
                n: diffLine2.charAt(0) + removeDel(highlightedLine)
            }
        }

        /* singleton pattern */
        var instance;
        return {
            getInstance: function () {
                if (instance === undefined) {
                    instance = new Diff2Html();
                    /* Hide the constructor so the returned objected can't be new'd */
                    instance.constructor = null;
                }
                return instance;
            }
        };

    })();

    window.Diff2Html = ClassVariable.getInstance();
    return window.Diff2Html;

})(window);
<commit_msg>Handle deleted files<commit_after>/*
 *
 * Diff to HTML (diff2html.js)
 * Author: rtfpessoa
 * Date: Friday 29 August 2014
 * Last Update: Sunday 2 February 2015
 *
 * Diff command:
 *   git diff
 */

(function (window) {
    var ClassVariable;

    ClassVariable = (function () {

        var LINE_TYPE = {
            INSERTS: "d2h-ins",
            DELETES: "d2h-del",
            CONTEXT: "d2h-cntx",
            INFO: "d2h-info"
        };

        function Diff2Html() {
        }

        /*
         * Generates pretty html from string diff input
         */
        Diff2Html.prototype.getPrettyHtmlFromDiff = function (diffInput) {
            var diffJson = generateDiffJson(diffInput);
            return generateJsonHtml(diffJson);
        };

        /*
         * Generates json object from string diff input
         */
        Diff2Html.prototype.getJsonFromDiff = function (diffInput) {
            return generateDiffJson(diffInput);
        };

        /*
         * Generates pretty html from a json object
         */
        Diff2Html.prototype.getPrettyHtmlFromJson = function (diffJson) {
            return generateJsonHtml(diffJson);
        };

        /*
         * Generates pretty side by side html from string diff input
         */
        Diff2Html.prototype.getPrettySideBySideHtmlFromDiff = function (diffInput) {
            var diffJson = generateDiffJson(diffInput);
            return generateSideBySideJsonHtml(diffJson);
        };

        /*
         * Generates pretty side by side html from a json object
         */
        Diff2Html.prototype.getPrettySideBySideHtmlFromJson = function (diffJson) {
            return generateSideBySideJsonHtml(diffJson);
        };

        var generateDiffJson = function (diffInput) {
            var files = [],
                currentFile = null,
                currentBlock = null,
                oldLine = null,
                newLine = null;

            var saveBlock = function () {
                /* add previous block(if exists) before start a new file */
                if (currentBlock) {
                    currentFile.blocks.push(currentBlock);
                    currentBlock = null;
                }
            };

            var saveFile = function () {
                /*
                 * add previous file(if exists) before start a new one
                 * if it has name (to avoid binary files errors)
                 */
                if (currentFile && currentFile.newName) {
                    files.push(currentFile);
                    currentFile = null;
                }
            };

            var startFile = function () {
                saveBlock();
                saveFile();

                /* create file structure */
                currentFile = {};
                currentFile.blocks = [];
                currentFile.deletedLines = 0;
                currentFile.addedLines = 0;
            };

            var startBlock = function (line) {
                saveBlock();

                var values = /^@@ -(\d+),\d+ \+(\d+),\d+ @@.*/.exec(line) ||
                    /^@@@ -(\d+),\d+ -\d+,\d+ \+(\d+),\d+ @@@.*/.exec(line) ||
                    [0, 0, 0];

                oldLine = values[1];
                newLine = values[2];

                /* create block metadata */
                currentBlock = {};
                currentBlock.lines = [];
                currentBlock.oldStartLine = oldLine;
                currentBlock.newStartLine = newLine;
                currentBlock.header = line;
            };

            var createLine = function (line) {
                var currentLine = {};
                currentLine.content = line;

                /* fill the line data */
                if (startsWith(line, "+") || startsWith(line, " +")) {
                    currentFile.addedLines++;

                    currentLine.type = LINE_TYPE.INSERTS;
                    currentLine.oldNumber = null;
                    currentLine.newNumber = newLine++;

                    currentBlock.lines.push(currentLine);

                } else if (startsWith(line, "-") || startsWith(line, " -")) {
                    currentFile.deletedLines++;

                    currentLine.type = LINE_TYPE.DELETES;
                    currentLine.oldNumber = oldLine++;
                    currentLine.newNumber = null;

                    currentBlock.lines.push(currentLine);

                } else {
                    currentLine.type = LINE_TYPE.CONTEXT;
                    currentLine.oldNumber = oldLine++;
                    currentLine.newNumber = newLine++;

                    currentBlock.lines.push(currentLine);
                }
            };

            var diffLines = diffInput.split("\n");
            diffLines.forEach(function (line) {
                // Unmerged paths, and possibly other non-diffable files
                // https://github.com/scottgonzalez/pretty-diff/issues/11
                // Also, remove some useless lines
                if (!line || startsWith(line, "*") ||
                    startsWith(line, "new") || startsWith(line, "index")) {
                    return;
                }

                var values = [];
                if (startsWith(line, "diff")) {
                    startFile();
                } else if (currentFile && !currentFile.oldName && (values = /^--- a\/(\S+).*$/.exec(line))) {
                    currentFile.oldName = values[1];
                } else if (currentFile && !currentFile.newName && (values = /^\+\+\+ [b]?\/(\S+).*$/.exec(line))) {
                    currentFile.newName = values[1];

                    var fileSplit = currentFile.newName.split(".");
                    currentFile.language = fileSplit[fileSplit.length - 1];
                } else if (currentFile && startsWith(line, "@@")) {
                    startBlock(line);
                } else if (currentBlock) {
                    createLine(line);
                }
            });

            saveBlock();
            saveFile();

            return files;
        };

        /*
         * Line By Line HTML
         */

        var generateJsonHtml = function (diffFiles) {
            return "
\n" +
                diffFiles.map(function (file) {
                    return "
\n" +
                        "
\n" +
                        "
\n" +
                        "         +" + file.addedLines + "\n" +
                        "         -" + file.deletedLines + "\n" +
                        "
\n" +
                        "
" + getDiffName(file.oldName, file.newName) + "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "         " + generateFileHtml(file) +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n";
                }).join("\n") +
                "
\n";
        };

        var generateFileHtml = function (file) {
            return file.blocks.map(function (block) {

                var lines = "
\n" +
                    "  	\n" +
                    "  " +
                    "
" + escape(block.header) + "
" +
                    "  	\n" +
                    "
\n";

                for (var i = 0; i < block.lines.length; i++) {
                    var prevLine = block.lines[i - 1];
                    var line = block.lines[i];
                    var newLine = block.lines[i + 1];
                    var nextNewLine = block.lines[i + 2];

                    var isOppositeTypeTwoLineBlock =
                        line.type == LINE_TYPE.DELETES &&
                        newLine && newLine.type == LINE_TYPE.INSERTS &&
                        (!nextNewLine || nextNewLine && nextNewLine.type != LINE_TYPE.INSERTS) &&
                        (!prevLine || prevLine && prevLine.type != LINE_TYPE.DELETES);

                    var escapedLine = escape(line.content);

                    if (isOppositeTypeTwoLineBlock) {
                        var nextEscapedLine = escape(newLine.content);

                        var diff = diffHighlight(escapedLine, nextEscapedLine);

                        lines += generateLineHtml(line.type, line.oldNumber, line.newNumber, diff.o) +
                        generateLineHtml(newLine.type, newLine.oldNumber, newLine.newNumber, diff.n);

                        i++;
                    } else {
                        lines += generateLineHtml(line.type, line.oldNumber, line.newNumber, escapedLine);
                    }
                }

                return lines;
            }).join("\n");
        };

        var generateLineHtml = function (type, oldNumber, newNumber, content) {
            return "
\n" +
                "  " +
                "
" + valueOrEmpty(oldNumber) + "
" +
                "
" + valueOrEmpty(newNumber) + "
" +
                "  	\n" +
                "  " +
                "
" + content + "
" +
                "  	\n" +
                "
\n";
        };

        /*
         * Side By Side HTML (work in progress)
         */

        var generateSideBySideJsonHtml = function (diffFiles) {
            return "
\n" +
                diffFiles.map(function (file) {
                    var diffs = generateSideBySideFileHtml(file);

                    return "
\n" +
                        "
\n" +
                        "
\n" +
                        "         +" + file.addedLines + "\n" +
                        "         -" + file.deletedLines + "\n" +
                        "
\n" +
                        "
" + getDiffName(file.oldName, file.newName) + "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "           " + diffs.left +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "           " + diffs.right +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n" +
                        "
\n";
                }).join("\n") +
                "
\n";
        };

        var generateSideBySideFileHtml = function (file) {
            var fileHtml = {};
            fileHtml.left = "";
            fileHtml.right = "";

            file.blocks.forEach(function (block) {

                fileHtml.left += "
\n" +
                "  	\n" +
                "  " +
                "
" + escape(block.header) + "
" +
                "  	\n" +
                "
\n";

                fileHtml.right += "
\n" +
                "  	\n" +
                "  " +
                "

" +
                "  	\n" +
                "
\n";

                for (var i = 0; i < block.lines.length; i++) {
                    var prevLine = block.lines[i - 1];
                    var line = block.lines[i];
                    var newLine = block.lines[i + 1];
                    var nextNewLine = block.lines[i + 2];

                    var isOpositeTypeTwoLineBlock = line.type == LINE_TYPE.DELETES && newLine && newLine.type == LINE_TYPE.INSERTS &&
                        (!nextNewLine || nextNewLine && nextNewLine.type != LINE_TYPE.INSERTS) &&
                        (!prevLine || prevLine && prevLine.type != LINE_TYPE.DELETES);

                    var escapedLine = escape(line.content);

                    if (isOpositeTypeTwoLineBlock) {
                        var nextEscapedLine = escape(newLine.content);

                        var diff = diffHighlight(escapedLine, nextEscapedLine);

                        fileHtml.left += generateSingleLineHtml(line.type, line.oldNumber, diff.o);
                        fileHtml.right += generateSingleLineHtml(newLine.type, newLine.newNumber, diff.n);

                        i++;
                    } else if (line.type == LINE_TYPE.DELETES) {
                        fileHtml.left += generateSingleLineHtml(line.type, line.oldNumber, escapedLine);
                        fileHtml.right += generateSingleLineHtml(LINE_TYPE.CONTEXT, "", "", "");
                    } else if (line.type == LINE_TYPE.INSERTS) {
                        fileHtml.left += generateSingleLineHtml(LINE_TYPE.CONTEXT, "", "", "");
                        fileHtml.right += generateSingleLineHtml(line.type, line.newNumber, escapedLine);
                    } else {
                        fileHtml.left += generateSingleLineHtml(line.type, line.oldNumber, escapedLine);
                        fileHtml.right += generateSingleLineHtml(line.type, line.newNumber, escapedLine);
                    }
                }

            });

            return fileHtml;
        };

        var generateSingleLineHtml = function (type, number, content) {
            return "
\n" +
                "    " + number + "	\n" +
                "    " +
                "
" + content + "
" +
                "    	\n" +
                "
\n";
        };

        /*
         * HTML Helpers
         */

        var getDiffName = function (oldFilename, newFilename) {
            if (oldFilename && newFilename && oldFilename !== newFilename) {
                return oldFilename + " -> " + newFilename;
            } else if (newFilename) {
                return newFilename;
            } else if (oldFilename) {
                return oldFilename;
            } else {
                return "Unknown filename";
            }
        };

        var removeIns = function (line) {
            return line.replace(/(((.|\n)*?)<\/ins>)/g, "");
        };

        var removeDel = function (line) {
            return line.replace(/(((.|\n)*?)<\/del>)/g, "");
        };

        /*
         * Utils
         */

        function escape(str) {
            return str.slice(0)
                .replace(/&/g, "&")
                .replace(/</g, "<")
                .replace(/>/g, ">")
                .replace(/\t/g, "    ");
        }

        function startsWith(str, start) {
            return str.indexOf(start) === 0;
        }

        function valueOrEmpty(value) {
            return value ? value : "";
        }

        function diffHighlight(diffLine1, diffLine2) {
            /* remove the initial -/+ to avoid always having diff in the first char */
            var highlightedLine = diffString(diffLine1.substr(1), diffLine2.substr(1));

            return {
                o: diffLine1.charAt(0) + removeIns(highlightedLine),
                n: diffLine2.charAt(0) + removeDel(highlightedLine)
            }
        }

        /* singleton pattern */
        var instance;
        return {
            getInstance: function () {
                if (instance === undefined) {
                    instance = new Diff2Html();
                    /* Hide the constructor so the returned objected can't be new'd */
                    instance.constructor = null;
                }
                return instance;
            }
        };

    })();

    window.Diff2Html = ClassVariable.getInstance();
    return window.Diff2Html;

})(window);
<|endoftext|>


<commit_before>// we define a __exec for globally-scoped execution
// used by module format implementations
var __exec;

(function() {

  // System clobbering protection (mostly for Traceur)
  var curSystem;
  var callCounter = 0;
  function preExec(loader) {
    if (callCounter == 0) {
      curSystem = __global.System;
    }
    callCounter++;
    __global.System = loader;
  }
  function postExec() {
    callCounter--;
    if (callCounter == 0) {
      __global.System = curSystem;
    }
  }

  var hasBtoa = typeof btoa != 'undefined';

  function getSource(load) {
    var lastLineIndex = load.source.lastIndexOf('\n');

    return load.source
        // adds the sourceURL comment if not already present
        + (load.source.substr(lastLineIndex, 15) != '\n//# sourceURL='
          ? '\n//# sourceURL=' + load.address + (load.metadata.sourceMap ? '!transpiled' : '') : '')
        // add sourceMappingURL if load.metadata.sourceMap is set
        + (load.metadata.sourceMap && hasBtoa &&
          '\n//# sourceMappingURL=data:application/json;base64,' + btoa(unescape(encodeURIComponent(load.metadata.sourceMap))) || '')
  }

  // Web Worker and Chrome Extensions use original ESML eval
  // this may lead to some global module execution differences (eg var not defining onto global)
  if (isWorker || isBrowser && window.chrome && window.chrome.extension) {
    __exec = function(load) {
      if (load.metadata.integrity)
        throw new Error('Subresource integrity checking is not supported in Web Workers or Chrome Extensions.');
      try {
        preExec(this);
        new Function(getSource(load)).call(__global);
        postExec();
      }
      catch(e) {
        throw addToError(e, 'Evaluating ' + load.address);
      }
    };
  }

  // use script injection eval to get identical global script behaviour
  else if (typeof document != 'undefined') {
    var head;

    var scripts = document.getElementsByTagName('script');
    $__curScript = scripts[scripts.length - 1];

    __exec = function(load) {
      if (!head)
        head = document.head || document.body || document.documentElement;

      var script = document.createElement('script');
      script.text = getSource(load);
      var onerror = window.onerror;
      var e;
      window.onerror = function(_e) {
        e = addToError(_e, 'Evaluating ' + load.address);
      }
      preExec(this);

      if (load.metadata.integrity)
        script.setAttribute('integrity', load.metadata.integrity);
      if (load.metadata.nonce)
        script.setAttribute('nonce', load.metadata.nonce);

      head.appendChild(script);
      head.removeChild(script);
      postExec();
      window.onerror = onerror;
      if (e)
        throw e;
    }
  }
  else {
    // global scoped eval for node
    var vmModule = 'vm';
    var vm = require(vmModule);
    __exec = function(load) {
      if (load.metadata.integrity)
        throw new Error('Subresource integrity checking is unavailable in Node.');
      try {
        preExec(this);
        vm.runInThisContext(getSource(load));
        postExec();
      }
      catch(e) {
        throw addToError(e.toString(), 'Evaluating ' + load.address);
      }
    };
  }

})();<commit_msg>Revert "preExec/postExec fix for #800"<commit_after>// we define a __exec for globally-scoped execution
// used by module format implementations
var __exec;

(function() {

  // System clobbering protection (mostly for Traceur)
  var curSystem;
  function preExec(loader) {
    curSystem = __global.System;
    __global.System = loader;
  }
  function postExec() {
    __global.System = curSystem;
  }

  var hasBtoa = typeof btoa != 'undefined';

  function getSource(load) {
    var lastLineIndex = load.source.lastIndexOf('\n');

    return load.source
        // adds the sourceURL comment if not already present
        + (load.source.substr(lastLineIndex, 15) != '\n//# sourceURL='
          ? '\n//# sourceURL=' + load.address + (load.metadata.sourceMap ? '!transpiled' : '') : '')
        // add sourceMappingURL if load.metadata.sourceMap is set
        + (load.metadata.sourceMap && hasBtoa &&
          '\n//# sourceMappingURL=data:application/json;base64,' + btoa(unescape(encodeURIComponent(load.metadata.sourceMap))) || '')
  }

  // Web Worker and Chrome Extensions use original ESML eval
  // this may lead to some global module execution differences (eg var not defining onto global)
  if (isWorker || isBrowser && window.chrome && window.chrome.extension) {
    __exec = function(load) {
      if (load.metadata.integrity)
        throw new Error('Subresource integrity checking is not supported in Web Workers or Chrome Extensions.');
      try {
        preExec(this);
        new Function(getSource(load)).call(__global);
        postExec();
      }
      catch(e) {
        throw addToError(e, 'Evaluating ' + load.address);
      }
    };
  }

  // use script injection eval to get identical global script behaviour
  else if (typeof document != 'undefined') {
    var head;

    var scripts = document.getElementsByTagName('script');
    $__curScript = scripts[scripts.length - 1];

    __exec = function(load) {
      if (!head)
        head = document.head || document.body || document.documentElement;

      var script = document.createElement('script');
      script.text = getSource(load);
      var onerror = window.onerror;
      var e;
      window.onerror = function(_e) {
        e = addToError(_e, 'Evaluating ' + load.address);
      }
      preExec(this);

      if (load.metadata.integrity)
        script.setAttribute('integrity', load.metadata.integrity);
      if (load.metadata.nonce)
        script.setAttribute('nonce', load.metadata.nonce);

      head.appendChild(script);
      head.removeChild(script);
      postExec();
      window.onerror = onerror;
      if (e)
        throw e;
    }
  }
  else {
    // global scoped eval for node
    var vmModule = 'vm';
    var vm = require(vmModule);
    __exec = function(load) {
      if (load.metadata.integrity)
        throw new Error('Subresource integrity checking is unavailable in Node.');
      try {
        preExec(this);
        vm.runInThisContext(getSource(load));
        postExec();
      }
      catch(e) {
        throw addToError(e.toString(), 'Evaluating ' + load.address);
      }
    };
  }

})();<|endoftext|>


<commit_before>'use strict'
var EthJSTX = require('ethereumjs-tx')
var EthJSBlock = require('ethereumjs-block')
var ethJSUtil = require('ethereumjs-util')
var BN = ethJSUtil.BN

function TxRunner (executionContext, vmaccounts, opts) {
  this.executionContext = executionContext
  this.web3 = executionContext.web3()
  this.vm = executionContext.vm()
  this.queueTxs = opts.queueTxs
  this.personalMode = opts.personalMode
  this.blockNumber = 0
  if (this.executionContext.isVM()) {
    this.blockNumber = 1150000 // The VM is running in Homestead mode, which started at this block.
  }
  this.running = false
  this.pendingTxs = []
  this.vmaccounts = vmaccounts
}

TxRunner.prototype.rawRun = function (args, cb) {
  this.pendingTxs.push({tx: args, cb: cb})
  this.execute()
}

TxRunner.prototype.execute = function () {
  var self = this
  if (this.running || this.pendingTxs.length === 0) {
    return
  }
  var args = this.pendingTxs[0].tx
  var cb = this.pendingTxs[0].cb
  this.pendingTxs.shift()
  var callback = function (error, result) {
    cb(error, result)
    self.running = false
    self.execute()
  }

  this.running = true
  var from = args.from
  var to = args.to
  var data = args.data
  if (data.slice(0, 2) !== '0x') {
    data = '0x' + data
  }
  var value = args.value
  var gasLimit = args.gasLimit

  var tx
  if (!self.executionContext.isVM()) {
    tx = {
      from: from,
      to: to,
      data: data,
      value: value
    }
    if (args.useCall) {
      tx.gas = gasLimit
      self.web3.eth.call(tx, function (error, result) {
        callback(error, {
          result: result,
          transactionHash: result.transactionHash
        })
      })
    } else {
      self.web3.eth.estimateGas(tx, function (err, gasEstimation) {
        if (err) {
          return callback(err, gasEstimation)
        }
        self.web3.eth.getBlock('latest', function (err, block) {
          if (err) {
            return callback(err)
          } else {
            // NOTE: estimateGas very likely will return a large limit if execution of the code failed
            //       we want to be able to run the code in order to debug and find the cause for the failure
            var blockGasLimit = Math.floor(block.gasLimit - block.gasLimit / 1024)
            tx.gas = blockGasLimit < gasEstimation ? blockGasLimit : gasEstimation

            if (tx.gas > gasLimit) {
              return callback('Gas required exceeds limit: ' + tx.gas)
            }

            var sendTransaction = self.personalMode ? self.web3.personal.sendTransaction : self.web3.eth.sendTransaction
            sendTransaction(tx, function (err, resp) {
              if (err) {
                return callback(err, resp)
              }

              tryTillResponse(self.web3, resp, callback)
            })
          }
        })
      })
    }
  } else {
    try {
      var account = self.vmaccounts[from]
      if (!account) {
        return cb('Invalid account selected')
      }
      tx = new EthJSTX({
        nonce: new BN(account.nonce++),
        gasPrice: new BN(1),
        gasLimit: new BN(gasLimit, 10),
        to: to,
        value: new BN(value, 10),
        data: new Buffer(data.slice(2), 'hex')
      })
      tx.sign(account.privateKey)

      const coinbases = [ '0x0e9281e9c6a0808672eaba6bd1220e144c9bb07a', '0x8945a1288dc78a6d8952a92c77aee6730b414778', '0x94d76e24f818426ae84aa404140e8d5f60e10e7e' ]
      const difficulties = [ new BN('69762765929000', 10), new BN('70762765929000', 10), new BN('71762765929000', 10) ]
      var block = new EthJSBlock({
        header: {
          timestamp: new Date().getTime() / 1000 | 0,
          number: self.blockNumber,
          coinbase: coinbases[self.blockNumber % coinbases.length],
          difficulty: difficulties[self.blockNumber % difficulties.length],
          gasLimit: new BN(gasLimit, 10).imuln(2)
        },
        transactions: [],
        uncleHeaders: []
      })
      if (!args.useCall) {
        ++self.blockNumber
      } else {
        self.vm.stateManager.checkpoint()
      }

      self.vm.runTx({block: block, tx: tx, skipBalance: true, skipNonce: true}, function (err, result) {
        if (args.useCall) {
          self.vm.stateManager.revert(function () {})
        }
        callback(err, {
          result: result,
          transactionHash: ethJSUtil.bufferToHex(new Buffer(tx.hash()))
        })
      })
    } catch (e) {
      callback(e, null)
    }
  }
}

function tryTillResponse (web3, txhash, done) {
  web3.eth.getTransactionReceipt(txhash, function (err, result) {
    if (!err && !result) {
      // Try again with a bit of delay
      setTimeout(function () { tryTillResponse(web3, txhash, done) }, 500)
    } else {
      done(err, {
        result: result,
        transactionHash: result.transactionHash
      })
    }
  })
}

module.exports = TxRunner
<commit_msg>disable gas estimation<commit_after>'use strict'
var EthJSTX = require('ethereumjs-tx')
var EthJSBlock = require('ethereumjs-block')
var ethJSUtil = require('ethereumjs-util')
var BN = ethJSUtil.BN

function TxRunner (executionContext, vmaccounts, opts) {
  this.executionContext = executionContext
  this.web3 = executionContext.web3()
  this.vm = executionContext.vm()
  this.queueTxs = opts.queueTxs
  this.personalMode = opts.personalMode
  this.blockNumber = 0
  if (this.executionContext.isVM()) {
    this.blockNumber = 1150000 // The VM is running in Homestead mode, which started at this block.
  }
  this.running = false
  this.pendingTxs = []
  this.vmaccounts = vmaccounts
}

TxRunner.prototype.rawRun = function (args, cb) {
  this.pendingTxs.push({tx: args, cb: cb})
  this.execute()
}

TxRunner.prototype.execute = function () {
  var self = this
  if (this.running || this.pendingTxs.length === 0) {
    return
  }
  var args = this.pendingTxs[0].tx
  var cb = this.pendingTxs[0].cb
  this.pendingTxs.shift()
  var callback = function (error, result) {
    cb(error, result)
    self.running = false
    self.execute()
  }

  this.running = true
  var from = args.from
  var to = args.to
  var data = args.data
  if (data.slice(0, 2) !== '0x') {
    data = '0x' + data
  }
  var value = args.value
  var gasLimit = args.gasLimit

  var tx
  if (!self.executionContext.isVM()) {
    tx = {
      from: from,
      to: to,
      data: data,
      value: value
    }
    if (args.useCall) {
      tx.gas = gasLimit
      self.web3.eth.call(tx, function (error, result) {
        callback(error, {
          result: result,
          transactionHash: result.transactionHash
        })
      })
    } else {
      self.web3.eth.estimateGas(tx, function (err, gasEstimation) {
        if (err) {
          return callback(err, gasEstimation)
        }
        self.web3.eth.getBlock('latest', function (err, block) {
          if (err) {
            return callback(err)
          } else {
            // NOTE: estimateGas very likely will return a large limit if execution of the code failed
            //       we want to be able to run the code in order to debug and find the cause for the failure
            var blockGasLimit = Math.floor(block.gasLimit - block.gasLimit / 1024)
            // tx.gas = blockGasLimit < gasEstimation ? blockGasLimit : gasEstimation
            tx.gas = blockGasLimit // that's temporary, uncomment when the following is fixed https://github.com/ethereum/go-ethereum/issues/3653

            /* same as above
            if (tx.gas > gasLimit) {
              return callback('Gas required exceeds limit: ' + tx.gas)
            }
            */

            var sendTransaction = self.personalMode ? self.web3.personal.sendTransaction : self.web3.eth.sendTransaction
            sendTransaction(tx, function (err, resp) {
              if (err) {
                return callback(err, resp)
              }

              tryTillResponse(self.web3, resp, callback)
            })
          }
        })
      })
    }
  } else {
    try {
      var account = self.vmaccounts[from]
      if (!account) {
        return cb('Invalid account selected')
      }
      tx = new EthJSTX({
        nonce: new BN(account.nonce++),
        gasPrice: new BN(1),
        gasLimit: new BN(gasLimit, 10),
        to: to,
        value: new BN(value, 10),
        data: new Buffer(data.slice(2), 'hex')
      })
      tx.sign(account.privateKey)

      const coinbases = [ '0x0e9281e9c6a0808672eaba6bd1220e144c9bb07a', '0x8945a1288dc78a6d8952a92c77aee6730b414778', '0x94d76e24f818426ae84aa404140e8d5f60e10e7e' ]
      const difficulties = [ new BN('69762765929000', 10), new BN('70762765929000', 10), new BN('71762765929000', 10) ]
      var block = new EthJSBlock({
        header: {
          timestamp: new Date().getTime() / 1000 | 0,
          number: self.blockNumber,
          coinbase: coinbases[self.blockNumber % coinbases.length],
          difficulty: difficulties[self.blockNumber % difficulties.length],
          gasLimit: new BN(gasLimit, 10).imuln(2)
        },
        transactions: [],
        uncleHeaders: []
      })
      if (!args.useCall) {
        ++self.blockNumber
      } else {
        self.vm.stateManager.checkpoint()
      }

      self.vm.runTx({block: block, tx: tx, skipBalance: true, skipNonce: true}, function (err, result) {
        if (args.useCall) {
          self.vm.stateManager.revert(function () {})
        }
        callback(err, {
          result: result,
          transactionHash: ethJSUtil.bufferToHex(new Buffer(tx.hash()))
        })
      })
    } catch (e) {
      callback(e, null)
    }
  }
}

function tryTillResponse (web3, txhash, done) {
  web3.eth.getTransactionReceipt(txhash, function (err, result) {
    if (!err && !result) {
      // Try again with a bit of delay
      setTimeout(function () { tryTillResponse(web3, txhash, done) }, 500)
    } else {
      done(err, {
        result: result,
        transactionHash: result.transactionHash
      })
    }
  })
}

module.exports = TxRunner
<|endoftext|>


<commit_before>var express = require("express"),
    redis = require("redis").createClient(),
    RedisStore = require("connect-redis")(express),
    app = express();

// send redis errors to console
redis.on("error", function(err) {
    console.error(err);
});

// default configuration
app.set("port", 1007);

// serve static assets from public folder
app.use(express.static("public"));

// enable cookies
app.use(express.cookieParser());

// session middle-ware using redis for storage
app.use(express.session({
    secret: "the secret ingredient is love, dammit",
    store: new RedisStore({client: redis})
}));

// redirect homepage to appropriate static asset
app.get("/", function(req, rsp) {
    rsp.redirect("/tacdom.html");
});

// begin listening
app.listen(app.get("port"));<commit_msg>service for creating a new commander<commit_after>var express = require("express"),
    redis = require("redis").createClient(),
    RedisStore = require("connect-redis")(express),
    app = express();

// send redis errors to console
redis.on("error", function(err) {
    console.error(err);
});

// default configuration
app.set("port", 1007);

// serve static assets from public folder
app.use(express.static("public"));

// enable cookies
app.use(express.cookieParser());

// session middle-ware using redis for storage
app.use(express.session({
    secret: "the secret ingredient is love, dammit",
    store: new RedisStore({client: redis})
}));

// enable parsed post data
app.use(express.bodyParser());

// redirect homepage to appropriate static asset
app.get("/", function(req, rsp) {
    rsp.redirect("/tacdom.html");
});

// unit data
app.get("/unit/:id", function(req, rsp) {
    var host = req.headers.host + ":" + app.get("port"),
        baseUri = "//" + host;

    redis.hgetall(baseUri + req.url, function(err, reply) {
        if (err) {
            rsp.status(404);
            rsp.end();
        } else {
            rsp.setHeader("Content-Type", "application/json");
            rsp.end(JSON.stringify(reply));
        }
    });
});

// create a new commander for the current session
app.post("/commander", function(req, rsp) {
    var host = req.headers.host + ":" + app.get("port"),
        baseUri = "//" + host,
        idUri = "/id",
        name = req.body.name,
        commander = {
            id: null, uri: "/unit/", name: name,
            job: "commander",
            hea: 10, atk: 2, def: 2, spd: 2,
            hp: 10, act: 2,
            weap_dmg: 1, weap_rng: 1,
            special: "command"
        };

    if (!name) {
        rsp.status(500);
        rsp.end();
        return;
    }

    redis.incr(baseUri + idUri, function(err, reply) {
        // TODO: handle err
        commander.id = reply;
        commander.uri += reply;
        redis.hmset(baseUri + commander.uri, commander, function(err, reply) {
            // TODO: handle err
            rsp.redirect(303, commander.uri);
        });
    });
});

// begin listening
app.listen(app.get("port"));<|endoftext|>


<commit_before>/*global require:true*/
/*global window:true*/

(function(exports) {
	"use strict";
	var fs = require( "fs" );
	var RSVP = require('./rsvp');
	var img_stats = require( './img-stats' );

	var createHTMLDoc = function( htmlpreviewbody , asyncCSSFile , o ){
		var noscriptpreview = '<link href="' + o.fallbackcss + '" rel="stylesheet">',
			asyncCSSpreview, doc;

		asyncCSSpreview = asyncCSSFile + '\ngrunticon( [ "'+ o.datacss +'", "'+ o.pngdatacss +'", "'+ o.fallbackcss +'" ] );';

		doc = fs.read( o.previewFilePath );
		doc = doc.replace( /\n\t" + noscriptpreview );
		doc = doc.replace( /<\/body>/, htmlpreviewbody.join( "\n\t" ) + "\n" );

		return doc;
	};

	exports.getStats = function( imagedata , isSvg , filename , dir ){

		var p = new RSVP.Promise();

		var data = {};

		if( isSvg ) {
			// get svg element's dimensions so we can set the viewport dims later
			var frag = window.document.createElement( "div" );
			frag.innerHTML = imagedata;
			var svgelem = frag.querySelector( "svg" );
			data.width = svgelem.getAttribute( "width" );
			data.height = svgelem.getAttribute( "height" );
			data.type = "SVG";

			p.resolve( data );
		} else {
			img_stats.stats( dir + filename , function( data ){
				data.width = data.width + 'px';
				data.height = data.height + 'px';
				data.type = data.type;
				p.resolve( data );
			});
		}
		return p;
	}; //getStats

	exports.render = function( imagedata , filename , pngRegex , svgRegex , isSvg , width , height , type , o) {
		var renderp = new RSVP.Promise();

		var page = require( "webpage" ).create();

		// set page viewport size to svg dimensions
		page.viewportSize = {  width: parseFloat(width), height: parseFloat(height) };

		// open svg file in webkit to make a png
		page.open(  o.inputdir + filename, function( status ){
			if( status === "success" ){
				var res = {};
				var filenamenoext = filename.replace( isSvg ? svgRegex : pngRegex, "" );
				var prefix = o.cssprefix + filenamenoext;
				var pngdatauri = "'data:image/png;base64,";
				var svgdatauri = "'data:image/svg+xml;charset=US-ASCII,";
				var pngimgstring = page.renderBase64( "png" );
				var getPNGDataCSSRule = function( prefix , pngimgstring ){
					if (pngimgstring.length <= 32768) {
						// create png data URI
						return "." + prefix + " { background-image: url(" +  pngdatauri + "); background-repeat: no-repeat; }";
					} else {
						return "/* Using an external URL reference because this image would have a data URI of " +
							pngimgstring.length +
							" characters, which is greater than the maximum of 32768 allowed by IE8. */\n" +
							"." + prefix + " { background-image: url(" + o.pngout + filenamenoext + ".png" + "); background-repeat: no-repeat; }";
					}
				}; //getPNGDataCSSRule
				var buildSVGDataURI = function( imagedata ){
					// get base64 of svg file
					return encodeURIComponent( imagedata
						//strip newlines and tabs
						.replace( /[\n\r]/gmi, "" )
						.replace( /\t/gmi, " " )
						//strip comments
						.replace(/<\!\-\-(.*(?=\-\->))\-\->/gmi, "")
						//replace
						.replace(/'/gmi, "\\i") ) +
						// close string
						"'";
				}; //buildSVGDataURI

				if( isSvg ) {
					svgdatauri += buildSVGDataURI( imagedata );
				}

				pngdatauri += pngimgstring + "'";

				// create png file
				page.render( o.outputdir + o.pngout + filenamenoext + ".png" );

				// add rules to svg data css file

				res.pngcssrule = '.' + prefix + " { background-image: url(" + o.pngout + filenamenoext + ".png" + "); background-repeat: no-repeat; }";
				res.htmlmarkup = '
.' + prefix + ':

';
				res.datacssrule = "." + prefix + " { background-image: url(" + ( isSvg ? svgdatauri : pngdatauri ) + "); background-repeat: no-repeat; }";
				res.pngdatacssrule = getPNGDataCSSRule( prefix , pngimgstring );

				// process the next svg
				renderp.resolve( res );
			} else {
				renderp.reject();
			}
		} ); //page.open
		return renderp;
	}; // render

	// files have all been processed. write the css and html files and return
	exports.writeCSS = function( dataarr , o ){
		var pngcssrules = [],
			pngdatacssrules = [],
			datacssrules = [],
			htmlpreviewbody = [],
			htmldoc, filesnippet, noscript, asyncCSSFile, asyncCSS;

		noscript = '<link href="' + o.cssbasepath + o.outputdir + o.fallbackcss + '" rel="stylesheet">';
		// make the preview HTML file and asyncCSS loader file
		asyncCSSFile = fs.read( o.asyncCSSpath );
		// add custom function call to asyncCSS
		asyncCSS = asyncCSSFile + '\ngrunticon( [ "' + o.cssbasepath + o.outputdir + o.datacss +'", "' + o.cssbasepath + o.outputdir + o.pngdatacss +'", "' + o.cssbasepath + o.outputdir + o.fallbackcss +'" ] );';

		// Load data arrays for writing
		dataarr.forEach( function( dataset ){
			pngcssrules.push( dataset.pngcssrule );
			pngdatacssrules.push( dataset.pngdatacssrule );
			datacssrules.push( dataset.datacssrule );
			htmlpreviewbody.push( dataset.htmlmarkup );
		});

		htmldoc = createHTMLDoc( htmlpreviewbody , asyncCSSFile , o );
		filesnippet = "\n\n" + noscript;

		// write the preview html file
		fs.write( o.outputdir + o.previewHTMLFilePath, htmldoc );

		// write CSS files
		fs.write( o.outputdir + o.fallbackcss, pngcssrules.join( "\n\n" ) );
		fs.write( o.outputdir + o.pngdatacss, pngdatacssrules.join( "\n\n" ) );
		fs.write( o.outputdir + o.datacss, datacssrules.join( "\n\n" ) );

		// overwrite the snippet HTML
		fs.write( o.asyncCSSpath , filesnippet );
	};

	// process an svg file from the source directory
	exports.processFile = function( filename , o ){
		var promise = new RSVP.Promise();
		var self = this;

		var svgRegex = /\.svg$/i,
			pngRegex = /\.png$/i,
			isSvg = filename.match( svgRegex ),
			isPng = filename.match( pngRegex );

		var imagedata = fs.read(  o.inputdir + filename ) || "";

		// kill the ".svg" or ".png" at the end of the filename

		self.getStats( imagedata , isSvg, filename , o.inputdir )
		.then( function( data ){
			return self.render( imagedata , filename , pngRegex , svgRegex , isSvg , data.width, data.height , data.type , o );
		})
		.then( function( res ){
			promise.resolve( res );
		});

		return promise;
	}; // end of processFile
}(typeof exports === 'object' && exports || this));
<commit_msg>More slight refactors<commit_after>/*global require:true*/
/*global window:true*/

(function(exports) {
	"use strict";
	var fs = require( "fs" );
	var RSVP = require('./rsvp');
	var img_stats = require( './img-stats' );

	var createHTMLDoc = function( htmlpreviewbody , asyncCSSFile , o ){
		var noscriptpreview = '<link href="' + o.fallbackcss + '" rel="stylesheet">',
			asyncCSSpreview, doc;

		asyncCSSpreview = asyncCSSFile + '\ngrunticon( [ "'+ o.datacss +'", "'+ o.pngdatacss +'", "'+ o.fallbackcss +'" ] );';

		doc = fs.read( o.previewFilePath );
		doc = doc.replace( /\n\t" + noscriptpreview );
		doc = doc.replace( /<\/body>/, htmlpreviewbody.join( "\n\t" ) + "\n" );

		return doc;
	};

	exports.getStats = function( imagedata , isSvg , filename , dir ){

		var p = new RSVP.Promise();

		var data = {};

		if( isSvg ) {
			// get svg element's dimensions so we can set the viewport dims later
			var frag = window.document.createElement( "div" );
			frag.innerHTML = imagedata;
			var svgelem = frag.querySelector( "svg" );
			data.width = svgelem.getAttribute( "width" );
			data.height = svgelem.getAttribute( "height" );
			data.type = "SVG";

			p.resolve( data );
		} else {
			img_stats.stats( dir + filename , function( data ){
				data.width = data.width + 'px';
				data.height = data.height + 'px';
				data.type = data.type;
				p.resolve( data );
			});
		}
		return p;
	}; //getStats

	exports.createCSSRules = function( imagedata , pngimgstring , filenamenoext , isSvg , width , height , o ){
		// add rules to svg data css file
		var res = {};
		var prefix = o.cssprefix + filenamenoext;
		var pngdatauri = "'data:image/png;base64,";
		var svgdatauri = "'data:image/svg+xml;charset=US-ASCII,";

		var buildSVGDataURI = function( imagedata ){
			// get base64 of svg file
			return encodeURIComponent( imagedata
				//strip newlines and tabs
				.replace( /[\n\r]/gmi, "" )
				.replace( /\t/gmi, " " )
				//strip comments
				.replace(/<\!\-\-(.*(?=\-\->))\-\->/gmi, "")
				//replace
				.replace(/'/gmi, "\\i") ) +
				// close string
				"'";
		}; //buildSVGDataURI

		var getPNGDataCSSRule = function( prefix , pngimgstring ){
			if (pngimgstring.length <= 32768) {
				// create png data URI
				return "." + prefix + " { background-image: url(" +  pngdatauri + "); background-repeat: no-repeat; }";
			} else {
				return "/* Using an external URL reference because this image would have a data URI of " +
					pngimgstring.length +
					" characters, which is greater than the maximum of 32768 allowed by IE8. */\n" +
					"." + prefix + " { background-image: url(" + o.pngout + filenamenoext + ".png" + "); background-repeat: no-repeat; }";
			}
		}; //getPNGDataCSSRule
		if( isSvg ) {
			svgdatauri += buildSVGDataURI( imagedata );
		}

		pngdatauri += pngimgstring + "'";

		res.pngcssrule = '.' + prefix + " { background-image: url(" + o.pngout + filenamenoext + ".png" + "); background-repeat: no-repeat; }";
		res.htmlmarkup = '
.' + prefix + ':

';
		res.datacssrule = "." + prefix + " { background-image: url(" + ( isSvg ? svgdatauri : pngdatauri ) + "); background-repeat: no-repeat; }";
		res.pngdatacssrule = getPNGDataCSSRule( prefix , pngimgstring );

		return res;
	};

	exports.render = function( imagedata , filename , filenamenoext , isSvg , width , height , type , o) {
		var renderp = new RSVP.Promise();
		var self = this;
		var page = require( "webpage" ).create();
		// set page viewport size to svg dimensions
		page.viewportSize = {  width: parseFloat(width), height: parseFloat(height) };
		// open svg file in webkit to make a png
		page.open(  o.inputdir + filename, function( status ){
			if( status === "success" ){
				var pngimgstring = page.renderBase64( "png" );
				// create png file
				page.render( o.outputdir + o.pngout + filenamenoext + ".png" );
				// process the next svg
				renderp.resolve( self.createCSSRules( imagedata , pngimgstring , filenamenoext , isSvg , width , height , o ) );
			} else {
				renderp.reject();
			}
		} ); //page.open
		return renderp;
	}; // render

	// files have all been processed. write the css and html files and return
	exports.writeCSS = function( dataarr , o ){
		var pngcssrules = [],
			pngdatacssrules = [],
			datacssrules = [],
			htmlpreviewbody = [],
			htmldoc, filesnippet, noscript, asyncCSSFile, asyncCSS;

		noscript = '<link href="' + o.cssbasepath + o.outputdir + o.fallbackcss + '" rel="stylesheet">';
		// make the preview HTML file and asyncCSS loader file
		asyncCSSFile = fs.read( o.asyncCSSpath );
		// add custom function call to asyncCSS
		asyncCSS = asyncCSSFile + '\ngrunticon( [ "' + o.cssbasepath + o.outputdir + o.datacss +'", "' + o.cssbasepath + o.outputdir + o.pngdatacss +'", "' + o.cssbasepath + o.outputdir + o.fallbackcss +'" ] );';

		// Load data arrays for writing
		dataarr.forEach( function( dataset ){
			pngcssrules.push( dataset.pngcssrule );
			pngdatacssrules.push( dataset.pngdatacssrule );
			datacssrules.push( dataset.datacssrule );
			htmlpreviewbody.push( dataset.htmlmarkup );
		});

		htmldoc = createHTMLDoc( htmlpreviewbody , asyncCSSFile , o );
		filesnippet = "\n\n" + noscript;

		// write the preview html file
		fs.write( o.outputdir + o.previewHTMLFilePath, htmldoc );

		// write CSS files
		fs.write( o.outputdir + o.fallbackcss, pngcssrules.join( "\n\n" ) );
		fs.write( o.outputdir + o.pngdatacss, pngdatacssrules.join( "\n\n" ) );
		fs.write( o.outputdir + o.datacss, datacssrules.join( "\n\n" ) );

		// overwrite the snippet HTML
		fs.write( o.asyncCSSpath , filesnippet );
	};

	// process an svg file from the source directory
	exports.processFile = function( filename , o ){
		var promise = new RSVP.Promise();
		var self = this;

		var svgRegex = /\.svg$/i,
			pngRegex = /\.png$/i,
			isSvg = filename.match( svgRegex ),
			isPng = filename.match( pngRegex );

		var imagedata = fs.read(  o.inputdir + filename ) || "";

		// kill the ".svg" or ".png" at the end of the filename
		var filenamenoext = filename.replace( isSvg ? svgRegex : pngRegex, "" );

		self.getStats( imagedata , isSvg, filename , o.inputdir )
		.then( function( data ){
			return self.render( imagedata , filename , filenamenoext , isSvg , data.width, data.height , data.type , o );
		})
		.then( function( res ){
			promise.resolve( res );
		});

		return promise;
	}; // end of processFile
}(typeof exports === 'object' && exports || this));
<|endoftext|>


<commit_before>// var sort_column = undefined;
// (document.querySelectorAll("th")).forEach((element, indx) => { if (element.textContent == "Path") {sort_column = indx} } );
var sort_column = 2;

let new_directory_name = document.getElementById("name");
let files = document.getElementById("files");

var url_base = window.location;
var current_path;
var editable = undefined;

async function refresh_list() {

    function compareValues(a, b) {
        if (a.value === b.value) {
          return 0;
        } else {
          return a.value < b.value ? -1 : 1;
        }
    }

    current_path = window.location.hash.substr(1);
    if (current_path == "") {
        current_path = "/";
    }
    // Do the fetch first because the browser will prompt for credentials.
    const response = await fetch(new URL("/fs" + current_path, url_base),
        {
            headers: {
                "Accept": "application/json"
            },
            credentials: "include"
        }
    );
    const data = await response.json();
    var new_children = [];
    var title = document.querySelector("title");
    title.textContent = current_path;
    var path = document.querySelector("#path");
    path.textContent = current_path;
    var template = document.querySelector('#row');

    if (editable === undefined) {
        const status = await fetch(new URL("/fs/", url_base),
            {
                method: "OPTIONS",
                credentials: "include"
            }
        );
        editable = status.headers.get("Access-Control-Allow-Methods").includes("DELETE");
        new_directory_name.disabled = !editable;
        files.disabled = !editable;
        if (!editable) {
            let usbwarning = document.querySelector("#usbwarning");
            usbwarning.style.display = "block";
        }
    }

    var dirCells = [];
    var dataCells = [];
    var index = 0;

    if (window.location.path != "/fs/") {
        var clone = template.content.cloneNode(true);
        var td = clone.querySelectorAll("td");
        td[0].textContent = "🗀";
        var path = clone.querySelector("a");
        let parent = new URL("..", "file://" + current_path);
        path.href = "#" + parent.pathname;
        path.textContent = "..";
        // Remove the delete button
        td[4].replaceChildren();

        var sortdata = {};
        sortdata.value = "..";
        sortdata.index = index;
        dirCells.push(sortdata);
        index += 1;

        new_children.push(clone);
    }

    for (const f of data) {
        // Clone the new row and insert it into the table
        var clone = template.content.cloneNode(true);
        var td = clone.querySelectorAll("td");
        var icon = "⬇";
        var file_path = current_path + f.name;
        let api_url = new URL("/fs" + file_path, url_base);
        let edit_url = "/edit/#" + file_path;
        if (f.directory) {
            file_path = "#" + file_path + "/";
            api_url += "/";
        } else {
            file_path = api_url;
        }

        if (f.directory) {
            icon = "🗀";
        } else if(f.name.endsWith(".txt") ||
                  f.name.endsWith(".py") ||
                  f.name.endsWith(".js") ||
                  f.name.endsWith(".json")) {
            icon = "🖹";
        } else if (f.name.endsWith(".html")) {
            icon = "🌐";
        }
        td[0].textContent = icon;
        td[1].textContent = f.file_size;
        var path = clone.querySelector("a");
        path.href = file_path;
        path.textContent = f.name;
        td[3].textContent = (new Date(f.modified_ns / 1000000)).toLocaleString();
        var delete_button = clone.querySelector("button.delete");
        delete_button.value = api_url;
        delete_button.disabled = !editable;
        delete_button.onclick = del;

        if (editable && !f.directory) {
            edit_url = new URL(edit_url, url_base);
            let edit_link = clone.querySelector(".edit_link");
            edit_link.href = edit_url
        }

        var dataCell = td[sort_column];

        var sortdata = {};
        sortdata.value = dataCell.textContent.toLowerCase().trim();
        sortdata.index = index;
        if (!f.directory) {
            dataCells.push(sortdata);
            index += 1;
        } else {
            dirCells.push(sortdata);
            index += 1;
        }

        new_children.push(clone);
    }

    dirCells.sort(compareValues);
    dataCells.sort(compareValues);

    var tbody = document.querySelector("tbody");

    // remove rows
    while (tbody.firstChild) {
      tbody.removeChild(tbody.lastChild);
    }

    // add sorted rows
    for (var i = 0; i < dirCells.length; i += 1) {
      tbody.appendChild(new_children[dirCells[i].index]);
    }
    for (var i = 0; i < dataCells.length; i += 1) {
      tbody.appendChild(new_children[dataCells[i].index]);
    }
}

async function find_devices() {
    const version_response = await fetch("/cp/version.json");
    if (version_response.ok) {
        url_base = new URL("/", window.location).href;
    } else {
        // TODO: Remove this when we've settled things. It is only used when this file isn't hosted
        // by a CP device.
        const response = await fetch("http://circuitpython.local/cp/devices.json");
        let url = new URL("/", response.url);
        url_base = url.href;
        const data = await response.json();
    }
    refresh_list();
}

async function mkdir(e) {
    const response = await fetch(
        new URL("/fs" + current_path + new_directory_name.value + "/", url_base),
        {
            method: "PUT",
            headers: {
                'X-Timestamp': Date.now()
            }
        }
    );
    if (response.ok) {
        refresh_list();
        new_directory_name.value = "";
        mkdir_button.disabled = true;
    }
}

async function upload(e) {
    for (const file of files.files) {
        let file_path = new URL("/fs" + current_path + file.name, url_base);
        const response = await fetch(file_path,
            {
                method: "PUT",
                headers: {
                    'Content-Type': 'application/octet-stream',
                    'X-Timestamp': file.lastModified
                },
                body: file
            }
        )
        if (response.ok) {
            refresh_list();
            files.value = "";
            upload_button.disabled = true;
        }
    }
}

async function del(e) {
    let fn = new URL(e.target.value);
    var prompt = "Delete " + fn.pathname.substr(3);
    if (e.target.value.endsWith("/")) {
        prompt += " and all of its contents?";
    } else {
        prompt += "?";
    }
    if (confirm(prompt)) {
        const response = await fetch(e.target.value,
            {
                method: "DELETE"
            }
        )
        if (response.ok) {
            refresh_list();
        }
    }
}

find_devices();

let mkdir_button = document.getElementById("mkdir");
mkdir_button.onclick = mkdir;

let upload_button = document.getElementById("upload");
upload_button.onclick = upload;

upload_button.disabled = files.files.length == 0;

files.onchange = () => {
    upload_button.disabled = files.files.length == 0;
}

mkdir_button.disabled = new_directory_name.value.length == 0;

new_directory_name.oninput = () => {
    mkdir_button.disabled = new_directory_name.value.length == 0;
}

window.onhashchange = refresh_list;
<commit_msg>Posted to wrong directory :/<commit_after><|endoftext|>


<commit_before>import Express from 'express';
import Api from './server/api';
require('dotenv').config();

// Setup the app...
var app = new Express;
var api = new Api;

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

app.get('/',  (req, res) => {
  if(req.query.code)
  {
    // we have the code now we can try to auth
    //console.log('Code: '+req.query.code);
    api.setCode(req.query.code);
    api.setResonse(res);

    // get the access code
    api.getAccessCode();

   //console.log('username: '+api.username);

   //res.status(200).json({ status: 'OK' });

  } else {
    res.status(500).json({ error: 'No Code. Can not auth' });
  }
});

app.listen(3004, function () {
  console.log('This app listening on port 3004!')
})
<commit_msg>Cleaned up and formatted code<commit_after>import Express from 'express';
import Api from './server/api';
require('dotenv').config();

// Setup the app...
var app = new Express;
var api = new Api;

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

app.get('/',  (req, res) => {
  if(req.query.code)
  {
    // we have the code now we can try to auth
    //console.log('Code: '+req.query.code);
    api.setCode(req.query.code);
    api.setResonse(res);

    // get the access code
    api.getAccessCode();

  } else {
    res.status(500).json({ error: 'No Code. Can not auth' });
  }
});

app.listen(3004, function () {
  console.log('This app listening on port 3004!')
})
<|endoftext|>