<commit_before>"use strict";

class gsuiPanels {
	constructor( root ) {
		this.rootElement = root;
		this._cursorElem = document.createElement( "div" );
		this._cursorElem.className = "gsuiPanels-cursor";

		root.style.overflow = "hidden";
		root.querySelectorAll( ".gsuiPanels-extend" ).forEach( el => el.remove() );
		this._convertFlex( root.classList.contains( "gsuiPanels-x" )
			? "width" : "height", root );
		root.querySelectorAll( ".gsuiPanels-x" ).forEach( this._convertFlex.bind( this, "width" ) );
		root.querySelectorAll( ".gsuiPanels-y" ).forEach( this._convertFlex.bind( this, "height" ) );
		root.querySelectorAll( ".gsuiPanels-x > div + div" ).forEach( this._addExtend.bind( this, "width" ) );
		root.querySelectorAll( ".gsuiPanels-y > div + div" ).forEach( this._addExtend.bind( this, "height" ) );
	}

	// private:
	_getSize( el, dir ) {
		return el.getBoundingClientRect()[ dir ];
	}
	_convertFlex( dir, panPar ) {
		const pans = Array.from( panPar.children ),
			sizePans = pans.map( pan => this._getSize( pan, dir ) ),
			size = sizePans.reduce( ( n, pan ) => n + pan, 0 );

		pans.forEach( ( pan, i ) => {
			pan.style[ dir ] = sizePans[ i ] / size * 100 + "%";
			pan.style.flex = "none";
		} );
		pans[ pans.length - 1 ].style.flex = 1;
	}
	_addExtend( dir, pan ) {
		const extend = document.createElement( "div" ),
			pans = Array.from( pan.parentNode.children ),
			panBefore = pans.filter( el => (
				!el.classList.contains( "gsuiPanels-extend" ) &&
					pan.compareDocumentPosition( el ) & Node.DOCUMENT_POSITION_PRECEDING
			) ).reverse(),
			panAfter = pans.filter( el => (
				!el.classList.contains( "gsuiPanels-extend" ) && (
					pan === el ||
					pan.compareDocumentPosition( el ) & Node.DOCUMENT_POSITION_FOLLOWING
				)
			) );

		extend.className = "gsuiPanels-extend";
		extend.onmousedown = this._onmousedownExtend.bind( this, dir, extend, panBefore, panAfter );
		pan.append( extend );
	}
	_incrSizePans( dir, mov, pans ) {
		const parentsize = this._parentSize;

		return pans.reduce( ( mov, pan ) => {
			if ( Math.abs( mov ) > .1 ) {
				const style = getComputedStyle( pan ),
					size = this._getSize( pan, dir ),
					minsize = parseFloat( style[ "min-" + dir ] ) || 10,
					maxsize = parseFloat( style[ "max-" + dir ] ) || Infinity,
					newsizeCorrect = Math.max( minsize, Math.min( size + mov, maxsize ) );

				if ( Math.abs( newsizeCorrect - size ) >= .1 ) {
					pan.style.flex = "none";
					pan.style[ dir ] = newsizeCorrect / parentsize * 100 + "%";
					mov -= newsizeCorrect - size;
					if ( pan.onresizing ) {
						pan.onresizing( pan );
					}
				}
			}
			return mov;
		}, mov );
	}

	// events:
	_onmouseup() {
		this._cursorElem.remove();
		this._extend.classList.remove( "gsui-hover" );
		this.rootElement.classList.remove( "gsuiPanels-noselect" );
		this._panAfter[ this._panAfter.length - 1 ].style.flex = 1;
		delete gsuiPanels._focused;
	}
	_onmousemove( e ) {
		const dir = this._dir,
			px = ( dir === "width" ? e.pageX : e.pageY ) - this._pageN,
			mov = px - this._incrSizePans( dir, px, this._panBefore );

		if ( Math.abs( mov ) > .1 ) {
			this._incrSizePans( dir, -mov, this._panAfter );
		}
		this._pageN += mov;
	}
	_onmousedownExtend( dir, ext, panBefore, panAfter, e ) {
		gsuiPanels._focused = this;
		ext.classList.add( "gsui-hover" );
		this._cursorElem.style.cursor = dir === "width" ? "col-resize" : "row-resize";
		document.body.append( this._cursorElem );
		this.rootElement.classList.add( "gsuiPanels-noselect" );
		this._dir = dir;
		this._extend = ext;
		this._pageN = dir === "width" ? e.pageX : e.pageY;
		this._panBefore = panBefore;
		this._panAfter = panAfter;
		this._parent = ext.parentNode.parentNode;
		this._parentSize = Array.from( this._parent.children )
			.reduce( ( n, pan ) => (
				pan.classList.contains( "gsuiPanels-extend" )
					? n : n + this._getSize( pan, dir )
			), 0 );
	}
}

document.addEventListener( "mousemove", e => {
	gsuiPanels._focused && gsuiPanels._focused._onmousemove( e );
} );
document.addEventListener( "mouseup", e => {
	gsuiPanels._focused && gsuiPanels._focused._onmouseup( e );
} );
<commit_msg>gsuiPanels: fix the last pan to flex:1<commit_after>"use strict";

class gsuiPanels {
	constructor( root ) {
		this.rootElement = root;
		this._cursorElem = document.createElement( "div" );
		this._cursorElem.className = "gsuiPanels-cursor";

		root.style.overflow = "hidden";
		root.querySelectorAll( ".gsuiPanels-extend" ).forEach( el => el.remove() );
		this._convertFlex( root.classList.contains( "gsuiPanels-x" )
			? "width" : "height", root );
		root.querySelectorAll( ".gsuiPanels-x" ).forEach( this._convertFlex.bind( this, "width" ) );
		root.querySelectorAll( ".gsuiPanels-y" ).forEach( this._convertFlex.bind( this, "height" ) );
		root.querySelectorAll( ".gsuiPanels-x > div + div" ).forEach( this._addExtend.bind( this, "width" ) );
		root.querySelectorAll( ".gsuiPanels-y > div + div" ).forEach( this._addExtend.bind( this, "height" ) );
	}

	// private:
	_getSize( el, dir ) {
		return el.getBoundingClientRect()[ dir ];
	}
	_getChildren( el ) {
		return Array.from( el.children ).filter(
			el => !el.classList.contains( "gsuiPanels-extend" ) );
	}
	_convertFlex( dir, panPar ) {
		const pans = this._getChildren( panPar ),
			sizePans = pans.map( pan => this._getSize( pan, dir ) ),
			size = sizePans.reduce( ( n, pan ) => n + pan, 0 );

		pans.pop();
		pans.forEach( ( pan, i ) => {
			pan.style[ dir ] = sizePans[ i ] / size * 100 + "%";
			pan.style.flex = "none";
		} );
	}
	_addExtend( dir, pan ) {
		const extend = document.createElement( "div" ),
			pans = this._getChildren( pan.parentNode ),
			panBefore = pans.filter( el => (
				!el.classList.contains( "gsuiPanels-extend" ) &&
					pan.compareDocumentPosition( el ) & Node.DOCUMENT_POSITION_PRECEDING
			) ).reverse(),
			panAfter = pans.filter( ( el, i ) => (
				i < pans.length - 1 &&
				!el.classList.contains( "gsuiPanels-extend" ) && (
					pan === el ||
					pan.compareDocumentPosition( el ) & Node.DOCUMENT_POSITION_FOLLOWING
				)
			) );

		extend.className = "gsuiPanels-extend";
		extend.onmousedown = this._onmousedownExtend.bind( this, dir, extend, panBefore, panAfter );
		pan.append( extend );
	}
	_incrSizePans( dir, mov, pans ) {
		const parentsize = this._parentSize;

		return pans.reduce( ( mov, pan ) => {
			if ( Math.abs( mov ) > .1 ) {
				const style = getComputedStyle( pan ),
					size = this._getSize( pan, dir ),
					minsize = parseFloat( style[ "min-" + dir ] ) || 10,
					maxsize = parseFloat( style[ "max-" + dir ] ) || Infinity,
					newsizeCorrect = Math.max( minsize, Math.min( size + mov, maxsize ) );

				if ( Math.abs( newsizeCorrect - size ) >= .1 ) {
					pan.style.flex = "none";
					pan.style[ dir ] = newsizeCorrect / parentsize * 100 + "%";
					mov -= newsizeCorrect - size;
					if ( pan.onresizing ) {
						pan.onresizing( pan );
					}
				}
			}
			return mov;
		}, mov );
	}

	// events:
	_onmouseup() {
		this._cursorElem.remove();
		this._extend.classList.remove( "gsui-hover" );
		this.rootElement.classList.remove( "gsuiPanels-noselect" );
		delete gsuiPanels._focused;
	}
	_onmousemove( e ) {
		const dir = this._dir,
			px = ( dir === "width" ? e.pageX : e.pageY ) - this._pageN,
			mov = px - this._incrSizePans( dir, px, this._panBefore );

		if ( Math.abs( mov ) > .1 ) {
			this._incrSizePans( dir, -mov, this._panAfter );
		}
		this._pageN += mov;
	}
	_onmousedownExtend( dir, ext, panBefore, panAfter, e ) {
		gsuiPanels._focused = this;
		ext.classList.add( "gsui-hover" );
		this._cursorElem.style.cursor = dir === "width" ? "col-resize" : "row-resize";
		document.body.append( this._cursorElem );
		this.rootElement.classList.add( "gsuiPanels-noselect" );
		this._dir = dir;
		this._extend = ext;
		this._pageN = dir === "width" ? e.pageX : e.pageY;
		this._panBefore = panBefore;
		this._panAfter = panAfter;
		this._parent = ext.parentNode.parentNode;
		this._parentSize = this._getChildren( this._parent )
			.reduce( ( n, pan ) => (
				pan.classList.contains( "gsuiPanels-extend" )
					? n : n + this._getSize( pan, dir )
			), 0 );
	}
}

document.addEventListener( "mousemove", e => {
	gsuiPanels._focused && gsuiPanels._focused._onmousemove( e );
} );
document.addEventListener( "mouseup", e => {
	gsuiPanels._focused && gsuiPanels._focused._onmouseup( e );
} );
<|endoftext|>


<commit_before>(function () {
    'use strict';

    const path = require('path');
    const ngapimockid = _require('uuid').v4();
    const request = _require('then-request');
    const baseUrl = _require('url-join')(browser.baseUrl, 'ngapimock');

    const ProtractorMock = function () {
        function NgApimockHeader($http, ngApimockInstance) {
            $http.defaults.headers.common['ngapimockid'] = ngApimockInstance.ngapimockid;
        }

        NgApimockHeader.$inject = ['$http', 'ngApimockInstance'];

        angular.module('ngApimock', []);
        angular.module('ngApimock').constant('ngApimockInstance', arguments[0]);
        angular.module('ngApimock').run(NgApimockHeader)
    };

    /** Make sure that angular uses the ngapimock identifier for the requests. */
    browser.getProcessedConfig().then(function (config) {
        // As of protractor 5.0.0 the flag config.useAllAngular2AppRoots has been deprecated, to let protractor tell
        // ngApimock that Angular 2 is used a custom object needs to be provided with the angular version in it
        // See: https://github.com/angular/protractor/blob/master/CHANGELOG.md#features-2
        if (config.useAllAngular2AppRoots || ('ngApimockOpts' in config && config.ngApimockOpts.angularVersion > 1)) {
            // angular 2 does not have addMockModule support @see https://github.com/angular/protractor/issues/3092
            // fallback to cookie
            require('hooker').hook(browser, 'get', {
                post: function (result) {
                    return result.then(function () {
                        // Since protractor 5.0.0 the addCookie is an object, see
                        // https://github.com/angular/protractor/blob/master/CHANGELOG.md#500
                        try {
                            return browser.manage().addCookie({name: "ngapimockid", value: ngapimockid});
                        } catch (error) {
                            // Fallback protractor < 5.0.0
                            return browser.manage().addCookie('ngapimockid', ngapimockid);
                        }
                    });
                }
            });
        } else {
            browser.addMockModule('ngApimock', ProtractorMock, {'ngapimockid': ngapimockid})
        }
    });

    /**
     * Selects the given scenario for the mock matching the identifier.
     *
     * @param {Object | String} data The data object containing all the information for an expression or the name of the mock.
     * @param scenario The scenario that is selected to be returned when the api is called.
     * @return {Promise} the promise.
     */
    function selectScenario(data, scenario) {
        return _execute('PUT', '/mocks', {
            identifier: _getIdentifier(data),
            scenario: scenario || null
        }, 'Could not select scenario [' + scenario + ']');
    }

    /**
     * Sets the given delay time in milliseconds for the mock matching the identifier.
     * @param {Object | String} data The data object containing all the information for an expression or the name of the mock.
     * @param {number} delay The delay time in milliseconds.
     * @return {Promise} the promise.
     */
    function delayResponse(data, delay) {
        return _execute('PUT', '/mocks', {
            identifier: _getIdentifier(data),
            delay: delay || 0
        }, 'Could not delay the response');
    }

    /**
     * Sets the given echo indicator for the mock matching the identifier.
     * @param {Object | String} data The data object containing all the information for an expression or the name of the mock.
     * @param {boolean} echo The indicator echo request.
     * @return {Promise} the promise.
     */
    function echoRequest(data, echo) {
        return _execute('PUT', '/mocks', {
            identifier: _getIdentifier(data),
            echo: echo || false
        }, 'Could not echo the request');
    }

    /**
     * Selects the default scenario for each mock.
     * @return {Promise} the promise.
     */
    function setAllScenariosToDefault() {
        return _execute('PUT', '/mocks/defaults', undefined, 'Could not set scenarios to default');
    }

    /**
     * Selects passThrough scenario for each mock.
     * @return {Promise} the promise.
     */
    function setAllScenariosToPassThrough() {
        return _execute('PUT', '/mocks/passthroughs', undefined, 'Could not set scenarios to passthroughs');
    }

    /**
     * Add or Updates the given global key/value pair so it is accessible for when the response will returned.
     * @param key The key.
     * @param value The value.
     * @return {Promise} the promise.
     */
    function setGlobalVariable(key, value) {
        return _execute('PUT', '/variables', {
            key: key,
            value: value
        }, 'Could not add or update variable key [' + key + ' with value [' + value + ']');
    }

    /**
     * Add or Updates the given global key/value pairs so it is accessible for when the response will returned.
     * @param variables The variables.
     * @return {Promise} the promise.
     */
    function setGlobalVariables(variables) {
        return _execute('PUT', '/variables', {
            key: 'variables',
            value: variables
        }, 'Could not add or update variables');
    }

    /**
     * The deleteGlobalVariable function removes the global key/value pair.
     * @param key The key.
     * @return {Promise} the promise.
     */
    function deleteGlobalVariable(key) {
        return _execute('DELETE', '/variables/' + key, undefined, 'Could not delete variable with key [' + key + ']');
    }

    /**
     * Executes the api call with the provided information.
     * @param httpMethod The http method.
     * @param urlSuffix The url suffix.
     * @param options The options object.
     * @param errorMessage The error message.
     * @return {Promise} The promise.
     * @private
     */
    function _execute(httpMethod, urlSuffix, options, errorMessage) {
        const deferred = protractor.promise.defer(),
            opts = {
                headers: {
                    'Content-Type': 'application/json',
                    'ngapimockid': ngapimockid
                }
            };

        if (options !== undefined) {
            opts.json = options;
        }

        request(httpMethod, baseUrl + urlSuffix, opts).done(function (res) {
            if (res.statusCode !== 200) {
                deferred.reject(errorMessage);
            } else {
                deferred.fulfill();
            }
        });
        return deferred.promise;
    }

    /**
     * Adds the angular mock module that makes it possible to use the mocks.
     * @deprecated
     */
    function addMockModule() {
        console.log('addMockModule is no longer supported as of version 1.0.0, and will be removed in future versions');
    }

    /**
     * Removes the angular mock module that makes it possible to use the mocks.
     * @deprecated
     */
    function removeMockModule() {
        console.log('removeMockModule is no longer supported as of version 1.0.0, and will be removed in future versions');
    }

    /**
     * Resets the scenarios..
     * @deprecated Use setAllScenariosToDefault or setAllScenariosToPassThrough
     */
    function resetScenarios() {
        console.log('resetScenarios is no longer supported as of version 1.0.2, and will be removed in future versions.' +
            ' Use setAllScenariosToDefault or setAllScenariosToPassThrough');
    }

    /**
     * Resets the global variables to {}.
     * @deprecated
     */
    function resetGlobalVariables() {
        console.log('resetGlobalVariables is no longer supported as of version 1.0.0, and will be removed in future versions');
    }

    /**
     * Releases a hold mock.
     * @deprecated Use delayResponse.
     */
    function releaseMock() {
        console.log('releaseMock is no longer supported as of version 1.2.*, and will be removed in future versions.' +
            ' Use delay option instead.');
    }

    /**
     * Gets the identifier from the provided data object.
     * @param data The data object.
     * @return {string} identifier The identifier.
     * @private
     */
    function _getIdentifier(data) {
        let identifier;
        if (typeof data === 'string') { // name of the mock
            identifier = data;
        } else if (data.name) { // the data containing the name of the mock
            identifier = data.name;
        } else {
            identifier = data.expression + '$$' + data.method;
        }
        return identifier;
    }

    /**
     * Require the module by first looking under ng-apimock/node_modules and then in the base path.
     * @param dependency The dependency.
     * @return {*} result The result
     * @private
     */
    function _require(dependency) {
        let result;
        try {
            result = require(path.join('ng-apimock', 'node_modules', dependency));
        } catch (ex) {
            result = require(dependency)
        }
        return result;
    }

    /** This Protractor mock allows you to specify which scenario from your json api files you would like to use for your tests. */
    module.exports = {
        selectScenario: selectScenario,
        delayResponse: delayResponse,
        echoRequest: echoRequest,

        setAllScenariosToDefault: setAllScenariosToDefault,
        setAllScenariosToPassThrough: setAllScenariosToPassThrough,

        setGlobalVariable: setGlobalVariable,
        setGlobalVariables: setGlobalVariables,
        deleteGlobalVariable: deleteGlobalVariable,

        // deprecated
        releaseMock: releaseMock,
        addMockModule: addMockModule,
        removeMockModule: removeMockModule,
        resetScenarios: resetScenarios,
        resetGlobalVariables: resetGlobalVariables
    }
})();
<commit_msg>fix(protractor.mock): Add support for disabled selenium control flow<commit_after>(() => {
    'use strict';

    const path = require('path');
    const ngapimockid = _require('uuid').v4();
    const request = _require('then-request');
    const baseUrl = _require('url-join')(browser.baseUrl, 'ngapimock');

    let _handleRequest = function (httpMethod, urlSuffix, opts, errorMessage) {
        const deferred = protractor.promise.defer();
        request(httpMethod, baseUrl + urlSuffix, opts).done((res) => {
            if (res.statusCode !== 200) {
                deferred.reject(errorMessage);
            } else {
                deferred.fulfill();
            }
        });
        return deferred.promise;
    };

    const ProtractorMock = function () {
        function NgApimockHeader($http, ngApimockInstance) {
            $http.defaults.headers.common['ngapimockid'] = ngApimockInstance.ngapimockid;
        }

        NgApimockHeader.$inject = ['$http', 'ngApimockInstance'];

        angular.module('ngApimock', []);
        angular.module('ngApimock').constant('ngApimockInstance', arguments[0]);
        angular.module('ngApimock').run(NgApimockHeader)
    };

    /** Make sure that angular uses the ngapimock identifier for the requests. */
    browser.getProcessedConfig().then((config) => {
        // As of protractor 5.0.0 the flag config.useAllAngular2AppRoots has been deprecated, to let protractor tell
        // ngApimock that Angular 2 is used a custom object needs to be provided with the angular version in it
        // See: https://github.com/angular/protractor/blob/master/CHANGELOG.md#features-2
        if (config.useAllAngular2AppRoots || ('ngApimockOpts' in config && config.ngApimockOpts.angularVersion > 1)) {
            // angular 2 does not have addMockModule support @see https://github.com/angular/protractor/issues/3092
            // fallback to cookie
            require('hooker').hook(browser, 'get', {
                post: function (result) {
                    return result.then(function () {
                        // Since protractor 5.0.0 the addCookie is an object, see
                        // https://github.com/angular/protractor/blob/master/CHANGELOG.md#500
                        try {
                            return browser.manage().addCookie({name: "ngapimockid", value: ngapimockid});
                        } catch (error) {
                            // Fallback protractor < 5.0.0
                            return browser.manage().addCookie('ngapimockid', ngapimockid);
                        }
                    });
                }
            });
        } else {
            browser.addMockModule('ngApimock', ProtractorMock, {'ngapimockid': ngapimockid})
        }

        if (config.SELENIUM_PROMISE_MANAGER === false) {
            _handleRequest = function (httpMethod, urlSuffix, opts, errorMessage) {
                return new Promise((resolve, reject) => {
                    request(httpMethod, baseUrl + urlSuffix, opts).done((res) => {
                        return res.statusCode === 200 ? resolve() : reject(errorMessage);
                    });
                });
            }
        }
    });

    /**
     * Selects the given scenario for the mock matching the identifier.
     *
     * @param {Object | String} data The data object containing all the information for an expression or the name of the mock.
     * @param scenario The scenario that is selected to be returned when the api is called.
     * @return {Promise} the promise.
     */
    function selectScenario(data, scenario) {
        return _execute('PUT', '/mocks', {
            identifier: _getIdentifier(data),
            scenario: scenario || null
        }, 'Could not select scenario [' + scenario + ']');
    }

    /**
     * Sets the given delay time in milliseconds for the mock matching the identifier.
     * @param {Object | String} data The data object containing all the information for an expression or the name of the mock.
     * @param {number} delay The delay time in milliseconds.
     * @return {Promise} the promise.
     */
    function delayResponse(data, delay) {
        return _execute('PUT', '/mocks', {
            identifier: _getIdentifier(data),
            delay: delay || 0
        }, 'Could not delay the response');
    }

    /**
     * Sets the given echo indicator for the mock matching the identifier.
     * @param {Object | String} data The data object containing all the information for an expression or the name of the mock.
     * @param {boolean} echo The indicator echo request.
     * @return {Promise} the promise.
     */
    function echoRequest(data, echo) {
        return _execute('PUT', '/mocks', {
            identifier: _getIdentifier(data),
            echo: echo || false
        }, 'Could not echo the request');
    }

    /**
     * Selects the default scenario for each mock.
     * @return {Promise} the promise.
     */
    function setAllScenariosToDefault() {
        return _execute('PUT', '/mocks/defaults', undefined, 'Could not set scenarios to default');
    }

    /**
     * Selects passThrough scenario for each mock.
     * @return {Promise} the promise.
     */
    function setAllScenariosToPassThrough() {
        return _execute('PUT', '/mocks/passthroughs', undefined, 'Could not set scenarios to passthroughs');
    }

    /**
     * Add or Updates the given global key/value pair so it is accessible for when the response will returned.
     * @param key The key.
     * @param value The value.
     * @return {Promise} the promise.
     */
    function setGlobalVariable(key, value) {
        return _execute('PUT', '/variables', {
            key: key,
            value: value
        }, 'Could not add or update variable key [' + key + ' with value [' + value + ']');
    }

    /**
     * Add or Updates the given global key/value pairs so it is accessible for when the response will returned.
     * @param variables The variables.
     * @return {Promise} the promise.
     */
    function setGlobalVariables(variables) {
        return _execute('PUT', '/variables', {
            key: 'variables',
            value: variables
        }, 'Could not add or update variables');
    }

    /**
     * The deleteGlobalVariable function removes the global key/value pair.
     * @param key The key.
     * @return {Promise} the promise.
     */
    function deleteGlobalVariable(key) {
        return _execute('DELETE', '/variables/' + key, undefined, 'Could not delete variable with key [' + key + ']');
    }

    /**
     * Executes the api call with the provided information.
     * @param httpMethod The http method.
     * @param urlSuffix The url suffix.
     * @param options The options object.
     * @param errorMessage The error message.
     * @return {Promise} The promise.
     * @private
     */
    function _execute(httpMethod, urlSuffix, options, errorMessage) {
        const opts = {
            headers: {
                'Content-Type': 'application/json',
                'ngapimockid': ngapimockid
            }
        };

        if (options !== undefined) {
            opts.json = options;
        }

        return _handleRequest(httpMethod, urlSuffix, opts, errorMessage);
    }

    /**
     * Adds the angular mock module that makes it possible to use the mocks.
     * @deprecated
     */
    function addMockModule() {
        console.log('addMockModule is no longer supported as of version 1.0.0, and will be removed in future versions');
    }

    /**
     * Removes the angular mock module that makes it possible to use the mocks.
     * @deprecated
     */
    function removeMockModule() {
        console.log('removeMockModule is no longer supported as of version 1.0.0, and will be removed in future versions');
    }

    /**
     * Resets the scenarios..
     * @deprecated Use setAllScenariosToDefault or setAllScenariosToPassThrough
     */
    function resetScenarios() {
        console.log('resetScenarios is no longer supported as of version 1.0.2, and will be removed in future versions.' +
            ' Use setAllScenariosToDefault or setAllScenariosToPassThrough');
    }

    /**
     * Resets the global variables to {}.
     * @deprecated
     */
    function resetGlobalVariables() {
        console.log('resetGlobalVariables is no longer supported as of version 1.0.0, and will be removed in future versions');
    }

    /**
     * Releases a hold mock.
     * @deprecated Use delayResponse.
     */
    function releaseMock() {
        console.log('releaseMock is no longer supported as of version 1.2.*, and will be removed in future versions.' +
            ' Use delay option instead.');
    }

    /**
     * Gets the identifier from the provided data object.
     * @param data The data object.
     * @return {string} identifier The identifier.
     * @private
     */
    function _getIdentifier(data) {
        let identifier;
        if (typeof data === 'string') { // name of the mock
            identifier = data;
        } else if (data.name) { // the data containing the name of the mock
            identifier = data.name;
        } else {
            identifier = data.expression + '$$' + data.method;
        }
        return identifier;
    }

    /**
     * Require the module by first looking under ng-apimock/node_modules and then in the base path.
     * @param dependency The dependency.
     * @return {*} result The result
     * @private
     */
    function _require(dependency) {
        let result;
        try {
            result = require(path.join('ng-apimock', 'node_modules', dependency));
        } catch (ex) {
            result = require(dependency)
        }
        return result;
    }

    /** This Protractor mock allows you to specify which scenario from your json api files you would like to use for your tests. */
    module.exports = {
        selectScenario: selectScenario,
        delayResponse: delayResponse,
        echoRequest: echoRequest,

        setAllScenariosToDefault: setAllScenariosToDefault,
        setAllScenariosToPassThrough: setAllScenariosToPassThrough,

        setGlobalVariable: setGlobalVariable,
        setGlobalVariables: setGlobalVariables,
        deleteGlobalVariable: deleteGlobalVariable,

        // deprecated
        releaseMock: releaseMock,
        addMockModule: addMockModule,
        removeMockModule: removeMockModule,
        resetScenarios: resetScenarios,
        resetGlobalVariables: resetGlobalVariables
    }
})();
<|endoftext|>


<commit_before>import React, { PureComponent } from 'react';
import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';

const data = [
  {
    month: '2015.01',
    a: 4000,
    b: 2400,
    c: 2400,
  },
  {
    month: '2015.02',
    a: 3000,
    b: 1398,
    c: 2210,
  },
  {
    month: '2015.03',
    a: 2000,
    b: 9800,
    c: 2290,
  },
  {
    month: '2015.04',
    a: 2780,
    b: 3908,
    c: 2000,
  },
  {
    month: '2015.05',
    a: 1890,
    b: 4800,
    c: 2181,
  },
  {
    month: '2015.06',
    a: 2390,
    b: 3800,
    c: 2500,
  },
  {
    month: '2015.07',
    a: 3490,
    b: 4300,
    c: 2100,
  },
];

const toPercent = (decimal, fixed = 0) => `${(decimal * 100).toFixed(fixed)}%`;

const getPercent = (value, total) => {
  const ratio = total > 0 ? value / total : 0;

  return toPercent(ratio, 2);
};

const renderTooltipContent = (o) => {
  const { payload, label } = o;
  const total = payload.reduce((result, entry) => result + entry.value, 0);

  return (

{`${label} (Total: ${total})`}

        {payload.map((entry, index) => (
          <li key={`item-${index}`} style={{ color: entry.color }}>
            {`${entry.name}: ${entry.value}(${getPercent(entry.value, total)})`}

        ))}

  );
};

export default class Example extends PureComponent {
  static demoUrl = 'https://codesandbox.io/s/percent-stacked-area-chart-pelcs';

  render() {
    return (
      <ResponsiveContainer width="100%" height="100%">
        <AreaChart
          width={500}
          height={400}
          data={data}
          stackOffset="expand"
          margin={{
            top: 10,
            right: 30,
            left: 0,
            bottom: 0,
          }}
        >
          <CartesianGrid strokeDasharray="3 3" />
          <XAxis dataKey="month" />
          <YAxis tickFormatter={toPercent} />
          <Tooltip content={renderTooltipContent} />
          <Area type="monotone" dataKey="a" stackId="1" stroke="#8884d8" fill="#8884d8" />
          <Area type="monotone" dataKey="b" stackId="1" stroke="#82ca9d" fill="#82ca9d" />
          <Area type="monotone" dataKey="c" stackId="1" stroke="#ffc658" fill="#ffc658" />
        </AreaChart>
      </ResponsiveContainer>
    );
  }
}
<commit_msg>fix: fix tick labels<commit_after>import React, { PureComponent } from 'react';
import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';

const data = [
  {
    month: '2015.01',
    a: 4000,
    b: 2400,
    c: 2400,
  },
  {
    month: '2015.02',
    a: 3000,
    b: 1398,
    c: 2210,
  },
  {
    month: '2015.03',
    a: 2000,
    b: 9800,
    c: 2290,
  },
  {
    month: '2015.04',
    a: 2780,
    b: 3908,
    c: 2000,
  },
  {
    month: '2015.05',
    a: 1890,
    b: 4800,
    c: 2181,
  },
  {
    month: '2015.06',
    a: 2390,
    b: 3800,
    c: 2500,
  },
  {
    month: '2015.07',
    a: 3490,
    b: 4300,
    c: 2100,
  },
];

const toPercent = (decimal, fixed = 0) => `${(decimal * 100).toFixed(fixed)}%`;

const getPercent = (value, total) => {
  const ratio = total > 0 ? value / total : 0;

  return toPercent(ratio, 2);
};

const renderTooltipContent = (o) => {
  const { payload, label } = o;
  const total = payload.reduce((result, entry) => result + entry.value, 0);

  return (

{`${label} (Total: ${total})`}

        {payload.map((entry, index) => (
          <li key={`item-${index}`} style={{ color: entry.color }}>
            {`${entry.name}: ${entry.value}(${getPercent(entry.value, total)})`}

        ))}

  );
};

export default class Example extends PureComponent {
  static demoUrl = 'https://codesandbox.io/s/percent-stacked-area-chart-pelcs';

  render() {
    return (
      <ResponsiveContainer width="100%" height="100%">
        <AreaChart
          width={500}
          height={400}
          data={data}
          stackOffset="expand"
          margin={{
            top: 10,
            right: 30,
            left: 0,
            bottom: 0,
          }}
        >
          <CartesianGrid strokeDasharray="3 3" />
          <XAxis dataKey="month" />
          <YAxis tickFormatter={(value, index) => toPercent(value)} />
          <Tooltip content={renderTooltipContent} />
          <Area type="monotone" dataKey="a" stackId="1" stroke="#8884d8" fill="#8884d8" />
          <Area type="monotone" dataKey="b" stackId="1" stroke="#82ca9d" fill="#82ca9d" />
          <Area type="monotone" dataKey="c" stackId="1" stroke="#ffc658" fill="#ffc658" />
        </AreaChart>
      </ResponsiveContainer>
    );
  }
}
<|endoftext|>


<commit_before><commit_msg>Fix getting min/max in getCol method<commit_after><|endoftext|>


<commit_before>const $ = window.jQuery

const createLink = require('../helpers').createLink

module.exports.process = function process () {
  if (location.pathname.split('/').slice(-1)[0].match(/stack[\d.-]*\.yaml/)) {
    stackyaml()
  }
}

function stackyaml () {
  var depsOpen = false

  $('.blob-code-inner').each((_, elem) => {
    elem = $(elem)
    let line = elem.text().trim()

    if (line.match('packages:') || line.match('extra-deps:')) {
      depsOpen = true
      return
    }

    if (depsOpen && line.match(/^- *[\w-]+[\d.]*$/)) {
      let link = elem.find('.pl-s').eq(0)
      let moduleName = link.text().trim()

      let url = `https://hackage.haskell.org/package/${moduleName}`
      createLink(elem.get(0), moduleName, url)
    }

    if (!line.match(/^- /)) {
      depsOpen = false
    }
  })
}
<commit_msg>pubspec.yaml<commit_after>const $ = window.jQuery

const darturl = require('./dart').darturl

const createLink = require('../helpers').createLink

module.exports.process = function process () {
  if (window.pathdata.last.match(/stack[\d.-]*\.yaml/)) {
    stackyaml()
  } else {
    switch (window.pathdata.last) {
      case 'pubspec.yaml':
        pubspecyaml()
        break
    }
  }
}

function stackyaml () {
  // haskell
  var depsOpen = false

  $('.blob-code-inner').each((_, elem) => {
    elem = $(elem)
    let line = elem.text().trim()

    if (line.match('packages:') || line.match('extra-deps:')) {
      depsOpen = true
      return
    }

    if (depsOpen && line.match(/^- *[\w-]+[\d.]*$/)) {
      let link = elem.find('.pl-s').eq(0)
      let moduleName = link.text().trim()

      let url = `https://hackage.haskell.org/package/${moduleName}`
      createLink(elem.get(0), moduleName, url)
    }

    if (!line.match(/^- /)) {
      depsOpen = false
    }
  })
}

function pubspecyaml () {
  // dart
  var depsOpen = false

  $('.blob-code-inner').each((_, elem) => {
    elem = $(elem)
    let rawline = elem.text()

    if (rawline.match(/^dependencies:/) || rawline.match(/^dev_dependencies:/)) {
      depsOpen = true
      return
    }

    if (depsOpen && rawline.match(/^ +[\w_]*:/)) {
      let link = elem.find('.pl-ent').eq(0)
      let moduleName = link.text().trim()

      darturl(moduleName)
        .catch(() => url => `pub.dartlang.org/api/packages/${moduleName}`)
        .then(url => createLink(link.get(0), moduleName, url))
    }

    if (!rawline.match(/^ /)) {
      depsOpen = false
    }
  })
}
<|endoftext|>


<commit_before>module.exports = function bufferIndexOf(buf,search,offset){
  offset = offset||0

  var m = 0;
  var s = -1;
  for(var i=offset;i<buf.length;++i){
    if(buf[i] != search[m]){
      s = -1;
      // <-- go back
      // match abc to aabc
      // 'aabc'
      // 'aab'
      //    ^ no match
      // a'abc'
      //   ^ set index here now and look at these again.
      //   'abc' yay!
      i -= m-1
      m = 0;
    }

    if(buf[i] == search[m]) {
      if(s == -1) s = i;
      ++m;
      if(m == search.length) break;
    }
  }

  if (s > -1 && buf.length - s < search.length) return -1;
  return s;
}

module.exports.bm = function bm(buf,search,offset){
  var m  = 0, j = 0
  var table = []

  var ret = -1;
  for(var i=offset||0;i<buf.length;++i){
    console.log('i',i)

    table[i] = [[i,0]]
    if(buf[i] === search[0]) {
      for(j = search.length-1;j>0;--j){
        table[i].push([i+j,j])
        console.log('j',j)
        if(buf[i+j] !== search[j]) {

          //i += j
          j = -1
          break
        }
      }
      if(j === 0) {
        ret = i
        break
      }
    }
  }

  console.log(table)
  renderTable(table,buf,search)
  return ret
}

var chalk = require('chalk')
function renderTable(table,buf,search){
  var s = ''

  console.log('-----')
  console.log('search:',search)
  console.log('-----')
  console.log(buf+'')

  table.forEach(function(a){
    if(!a) return;// console.log('')
    a.forEach(function(v){
      if(!v) return;
      var pad = ''
      while(pad.length < v[0]){
        pad += ' '
      }
      if(search[v[1]] === buf[v[0]]) console.log(pad+chalk.green(search[v[1]]))
      else console.log(pad+chalk.red(search[v[1]]))

    })
  })
  console.log('-----')
}
<commit_msg>forgot to delete bm example from index when i moved it<commit_after>module.exports = function bufferIndexOf(buf,search,offset){
  offset = offset||0

  var m = 0;
  var s = -1;
  for(var i=offset;i<buf.length;++i){
    if(buf[i] != search[m]){
      s = -1;
      // <-- go back
      // match abc to aabc
      // 'aabc'
      // 'aab'
      //    ^ no match
      // a'abc'
      //   ^ set index here now and look at these again.
      //   'abc' yay!
      i -= m-1
      m = 0;
    }

    if(buf[i] == search[m]) {
      if(s == -1) s = i;
      ++m;
      if(m == search.length) break;
    }
  }

  if (s > -1 && buf.length - s < search.length) return -1;
  return s;
}

<|endoftext|>


<commit_before>const RopeSequence = require("rope-sequence")
const {Mapping} = require("../transform")

// FIXME stop relying on timing or take timestamps as input?

// ProseMirror's history isn't simply a way to roll back to a previous
// state, because ProseMirror supports applying changes without adding
// them to the history (for example during collaboration).
//
// To this end, each 'Branch' (one for the undo history and one for
// the redo history) keeps an array of 'Items', which can optionally
// hold a step (an actual undoable change), and always hold a position
// map (which is needed to move changes below them to apply to the
// current document).
//
// An item that has both a step and a selection token field is the
// start of an 'event' -- a group of changes that will be undone or
// redone at once. (It stores only a token, since that way we don't
// have to provide a document until the selection is actually applied,
// which is useful when compressing.)

// Used to schedule history compression
const max_empty_items = 500

class Branch {
  constructor(items, eventCount) {
    this.items = items
    this.eventCount = eventCount
  }

  // : (Node, bool, ?Item) → ?{transform: Transform, selection: SelectionToken}
  // Pop the latest event off the branch's history and apply it
  // to a document transform.
  popEvent(state, preserveItems) {
    if (this.eventCount == 0) return null

    let end = this.items.length
    for (;; end--) {
      let next = this.items.get(end - 1)
      if (next.selection) { --end; break }
    }

    let remap, mapFrom
    if (preserveItems) {
      remap = this.remapping(end, this.items.length)
      mapFrom = remap.maps.length
    }
    let transform = state.tr
    let selection, remaining
    let addAfter = [], addBefore = []

    this.items.forEach((item, i) => {
      if (!item.step) {
        if (!remap) {
          remap = this.remapping(end, i + 1)
          mapFrom = remap.maps.length
        }
        mapFrom--
        addBefore.push(item)
        return
      }

      if (remap) {
        addBefore.push(new Item(item.map))
        let step = item.step.map(remap.slice(mapFrom)), map

        if (step && transform.maybeStep(step).doc) {
          map = transform.mapping.maps[transform.mapping.maps.length - 1]
          addAfter.push(new Item(map, null, null, addAfter.length + addBefore.length))
        }
        mapFrom--
        if (map) remap.appendMap(map, mapFrom)
      } else {
        transform.maybeStep(item.step)
      }

      if (item.selection) {
        selection = remap ? item.selection.type.mapToken(item.selection, remap.slice(mapFrom)) : item.selection
        remaining = new Branch(this.items.slice(0, end).append(addBefore.reverse().concat(addAfter)), this.eventCount - 1)
        return false
      }
    }, this.items.length, 0)

    return {remaining, transform, selection}
  }

  // : (Transform, Selection, Object)
  // Create a new branch with the given transform added.
  addTransform(transform, selection, histOptions) {
    let newItems = [], eventCount = this.eventCount + (selection ? 1 : 0)
    let oldItems = this.items, lastItem = !histOptions.preserveItems && oldItems.length ? oldItems.get(oldItems.length - 1) : null

    for (let i = 0; i < transform.steps.length; i++) {
      let step = transform.steps[i].invert(transform.docs[i])
      let item = new Item(transform.mapping.maps[i], step, selection), merged
      if (merged = lastItem && lastItem.merge(item)) {
        item = merged
        if (i) newItems.pop()
        else oldItems = oldItems.slice(0, oldItems.length - 1)
      }
      newItems.push(item)
      selection = null
      if (!histOptions.preserveItems) lastItem = item
    }
    let overflow = this.eventCount - histOptions.depth
    if (overflow > DEPTH_OVERFLOW) oldItems = cutOffEvents(oldItems, overflow)
    return new Branch(oldItems.append(newItems), eventCount)
  }

  remapping(from, to) {
    let maps = [], mirrors = []
    this.items.forEach((item, i) => {
      if (item.mirrorOffset != null) {
        let mirrorPos = i - item.mirrorOffset
        if (mirrorPos >= from) mirrors.push(maps.length - item.mirrorOffset, maps.length)
      }
      maps.push(item.map)
    }, from, to)
    return new Mapping(maps, mirrors)
  }

  addMaps(array) {
    if (this.eventCount == 0) return this
    return new Branch(this.items.append(array.map(map => new Item(map))), this.eventCount)
  }

  // : ([PosMap], Transform, [number])
  // When the collab module receives remote changes, the history has
  // to know about those, so that it can adjust the steps that were
  // rebased on top of the remote changes, and include the position
  // maps for the remote changes in its array of items.
  rebased(rebasedTransform, rebasedCount) {
    if (!this.eventCount) return this

    let rebasedItems = [], start = this.items.length - rebasedCount, startPos = 0
    if (start < 0) {
      startPos = -start
      start = 0
    }

    let mapping = rebasedTransform.mapping
    let newUntil = rebasedTransform.steps.length

    let iRebased = startPos
    this.items.forEach(item => {
      let pos = mapping.getMirror(iRebased++)
      if (pos == null) return
      newUntil = Math.min(newUntil, pos)
      let map = mapping.maps[pos]
      if (item.step) {
        let step = rebasedTransform.steps[pos].invert(rebasedTransform.docs[pos])
        let selection = item.selection &&
            item.selection.type.mapToken(item.selection, mapping.slice(iRebased - 1, pos))
        rebasedItems.push(new Item(map, step, selection))
      } else {
        rebasedItems.push(new Item(map))
      }
    }, start)

    let newMaps = []
    for (let i = rebasedCount; i < newUntil; i++)
      newMaps.push(new Item(mapping.maps[i]))
    let items = this.items.slice(0, start).append(newMaps).append(rebasedItems)
    let branch = new Branch(items, this.eventCount) // FIXME might update event count
    if (branch.emptyItemCount() > max_empty_items)
      branch = branch.compress(this.items.length - rebasedItems.length)
    return branch
  }

  emptyItemCount() {
    let count = 0
    this.items.forEach(item => { if (!item.step) count++ })
    return count
  }

  // Compressing a branch means rewriting it to push the air (map-only
  // items) out. During collaboration, these naturally accumulate
  // because each remote change adds one. The `upto` argument is used
  // to ensure that only the items below a given level are compressed,
  // because `rebased` relies on a clean, untouched set of items in
  // order to associate old items with rebased steps.
  compress(upto = this.items.length) {
    let remap = this.remapping(0, upto), mapFrom = remap.maps.length
    let items = [], events = 0
    this.items.forEach((item, i) => {
      if (i >= upto) {
        items.push(item)
      } else if (item.step) {
        let step = item.step.map(remap.slice(mapFrom)), map = step && step.posMap()
        mapFrom--
        if (map) remap.appendMap(map, mapFrom)
        if (step) {
          let selection = item.selection && item.selection.type.mapToken(item.selection, remap.slice(mapFrom))
          if (selection) events++
          let newItem = new Item(map.invert(), step, selection), merged, last = items.length - 1
          if (merged = items.length && items[last].merge(newItem))
            items[last] = merged
          else
            items.push(newItem)
        }
      } else if (item.map) {
        mapFrom--
      }
    }, this.items.length, 0)
    return new Branch(RopeSequence.from(items.reverse()), events)
  }
}

Branch.empty = new Branch(RopeSequence.empty, 0)

function cutOffEvents(items, n) {
  let cutPoint
  items.forEach((item, i) => {
    if (item.selection && (--n == 0)) {
      cutPoint = i
      return false
    }
  })
  return items.slice(cutPoint)
}

class Item {
  constructor(map, step, selection, mirrorOffset) {
    this.map = map
    this.step = step
    this.selection = selection
    this.mirrorOffset = mirrorOffset
  }

  merge(other) {
    if (this.step && other.step && !other.selection) {
      let step = other.step.merge(this.step)
      if (step) return new Item(step.posMap().invert(), step, this.selection)
    }
  }
}

// ;; An undo/redo history manager for an editor instance.
class HistoryState {
  constructor(done, undone, prevMap) {
    this.done = done
    this.undone = undone
    this.prevMap = prevMap
  }

  // :: number
  // The amount of undoable events available.
  get undoDepth() { return this.done.eventCount }

  // :: number
  // The amount of redoable events available.
  get redoDepth() { return this.undone.eventCount }
}
exports.HistoryState = HistoryState

const defaults = {
  depth: 100,
  preserveItems: false
}
const DEPTH_OVERFLOW = 20

// : (EditorState, Transform, Selection, Object)
// Record a transformation in undo history.
function recordTransform(state, action, options) {
  let cur = state.history, transform = action.transform
  if (action.historyState) {
    return action.historyState
  } else if (transform.steps.length == 0) {
    return cur
  } else if (action.addToHistory !== false) {
    // Group transforms that occur in quick succession into one event.
    let newGroup = !isAdjacentToLastStep(transform, cur.prevMap, cur.done)
    return new HistoryState(cur.done.addTransform(transform, newGroup ? state.selection.token : null, options),
                            Branch.empty, transform.mapping.maps[transform.steps.length - 1])
  } else if (action.rebased) {
    // Used by the collab module to tell the history that some of its
    // content has been rebased.
    return new HistoryState(cur.done.rebased(transform, action.rebased),
                            cur.undone.rebased(transform, action.rebased),
                            cur.prevMap && transform.mapping.maps[transform.steps.length - 1])
  } else {
    return new HistoryState(cur.done.addMaps(transform.mapping.maps),
                            cur.undone.addMaps(transform.mapping.maps),
                            cur.prevMap)
  }
}

function isAdjacentToLastStep(transform, prevMap, done) {
  if (!prevMap) return false
  let firstMap = transform.mapping.maps[0], adjacent = false
  if (!firstMap) return true
  firstMap.forEach((start, end) => {
    done.items.forEach(item => {
      if (item.step) {
        prevMap.forEach((_start, _end, rStart, rEnd) => {
          if (start <= rEnd && end >= rStart) adjacent = true
        })
        return false
      } else {
        start = item.map.invert().map(start, -1)
        end = item.map.invert().map(end, 1)
      }
    }, done.items.length, 0)
  })
  return adjacent
}

// : (EditorState, bool, Object) → Object
// Apply the latest event from one branch to the document and optionally
// shift the event onto the other branch. Returns true when an event could
// be shifted.
function histAction(state, redo, histOptions) {
  let cur = state.history
  let pop = (redo ? cur.undone : cur.done).popEvent(state, histOptions.preserveItems)

  let selectionBeforeTransform = state.selection
  let selection = pop.selection.type.fromToken(pop.selection, pop.transform.doc)
  let added = (redo ? cur.done : cur.undone).addTransform(pop.transform, selectionBeforeTransform.token, histOptions)

  let newHist = new HistoryState(redo ? added : pop.remaining, redo ? pop.remaining : added, null)
  return pop.transform.action({selection, historyState: newHist, scrollIntoView: true})
}

// :: (Object) → Plugin
// A plugin that enables the undo history for an editor. Has the
// effect of setting the editor's `history` property to an instance of
// `History`. Takes the following options:
//
// **`depth`**`: number`
//   : The amount of history events that are collected before the
//     oldest events are discarded. Defaults to 100.
//
// **`preserveItems`**`: bool`
//   : Whether to throw away undone items. Needs to be true to use the
//     history together with the collaborative editing plugin.
exports.history = function(config) {
  let options = {}
  for (let prop in defaults) options[prop] = config && config.hasOwnProperty(prop) ? config[prop] : defaults[prop]

  return {
    stateFields: {
      history: {
        init() {
          return new HistoryState(Branch.empty, Branch.empty, null)
        },
        applyAction(state, action) {
          if (action.type == "transform")
            return recordTransform(state, action, options)
          if (action.type == "historyClose")
            return new HistoryState(state.history.done, state.history.undone, null)
          return state.history
        }
      }
    },

    undo(state, onAction) {
      if (!state.history || state.history.undoDepth == 0) return false
      if (onAction) onAction(histAction(state, false, options))
      return true
    },

    redo(state, onAction) {
      if (!state.history || state.history.redoDepth == 0) return false
      if (onAction) onAction(histAction(state, true, options))
      return true
    }
  }
}
<commit_msg>Get rid of selection token type, just use JSON representation<commit_after>const RopeSequence = require("rope-sequence")
const {Mapping} = require("../transform")
const {Selection} = require("../state")

// FIXME stop relying on timing or take timestamps as input?

// ProseMirror's history isn't simply a way to roll back to a previous
// state, because ProseMirror supports applying changes without adding
// them to the history (for example during collaboration).
//
// To this end, each 'Branch' (one for the undo history and one for
// the redo history) keeps an array of 'Items', which can optionally
// hold a step (an actual undoable change), and always hold a position
// map (which is needed to move changes below them to apply to the
// current document).
//
// An item that has both a step and a selection JSON representation is
// the start of an 'event' -- a group of changes that will be undone
// or redone at once. (It stores only the JSON, since that way we don't
// have to provide a document until the selection is actually applied,
// which is useful when compressing.)

// Used to schedule history compression
const max_empty_items = 500

class Branch {
  constructor(items, eventCount) {
    this.items = items
    this.eventCount = eventCount
  }

  // : (Node, bool, ?Item) → ?{transform: Transform, selection: Object}
  // Pop the latest event off the branch's history and apply it
  // to a document transform.
  popEvent(state, preserveItems) {
    if (this.eventCount == 0) return null

    let end = this.items.length
    for (;; end--) {
      let next = this.items.get(end - 1)
      if (next.selection) { --end; break }
    }

    let remap, mapFrom
    if (preserveItems) {
      remap = this.remapping(end, this.items.length)
      mapFrom = remap.maps.length
    }
    let transform = state.tr
    let selection, remaining
    let addAfter = [], addBefore = []

    this.items.forEach((item, i) => {
      if (!item.step) {
        if (!remap) {
          remap = this.remapping(end, i + 1)
          mapFrom = remap.maps.length
        }
        mapFrom--
        addBefore.push(item)
        return
      }

      if (remap) {
        addBefore.push(new Item(item.map))
        let step = item.step.map(remap.slice(mapFrom)), map

        if (step && transform.maybeStep(step).doc) {
          map = transform.mapping.maps[transform.mapping.maps.length - 1]
          addAfter.push(new Item(map, null, null, addAfter.length + addBefore.length))
        }
        mapFrom--
        if (map) remap.appendMap(map, mapFrom)
      } else {
        transform.maybeStep(item.step)
      }

      if (item.selection) {
        selection = remap ? Selection.mapJSON(item.selection, remap.slice(mapFrom)) : item.selection
        remaining = new Branch(this.items.slice(0, end).append(addBefore.reverse().concat(addAfter)), this.eventCount - 1)
        return false
      }
    }, this.items.length, 0)

    return {remaining, transform, selection}
  }

  // : (Transform, Selection, Object)
  // Create a new branch with the given transform added.
  addTransform(transform, selection, histOptions) {
    let newItems = [], eventCount = this.eventCount + (selection ? 1 : 0)
    let oldItems = this.items, lastItem = !histOptions.preserveItems && oldItems.length ? oldItems.get(oldItems.length - 1) : null

    for (let i = 0; i < transform.steps.length; i++) {
      let step = transform.steps[i].invert(transform.docs[i])
      let item = new Item(transform.mapping.maps[i], step, selection), merged
      if (merged = lastItem && lastItem.merge(item)) {
        item = merged
        if (i) newItems.pop()
        else oldItems = oldItems.slice(0, oldItems.length - 1)
      }
      newItems.push(item)
      selection = null
      if (!histOptions.preserveItems) lastItem = item
    }
    let overflow = this.eventCount - histOptions.depth
    if (overflow > DEPTH_OVERFLOW) oldItems = cutOffEvents(oldItems, overflow)
    return new Branch(oldItems.append(newItems), eventCount)
  }

  remapping(from, to) {
    let maps = [], mirrors = []
    this.items.forEach((item, i) => {
      if (item.mirrorOffset != null) {
        let mirrorPos = i - item.mirrorOffset
        if (mirrorPos >= from) mirrors.push(maps.length - item.mirrorOffset, maps.length)
      }
      maps.push(item.map)
    }, from, to)
    return new Mapping(maps, mirrors)
  }

  addMaps(array) {
    if (this.eventCount == 0) return this
    return new Branch(this.items.append(array.map(map => new Item(map))), this.eventCount)
  }

  // : ([PosMap], Transform, [number])
  // When the collab module receives remote changes, the history has
  // to know about those, so that it can adjust the steps that were
  // rebased on top of the remote changes, and include the position
  // maps for the remote changes in its array of items.
  rebased(rebasedTransform, rebasedCount) {
    if (!this.eventCount) return this

    let rebasedItems = [], start = this.items.length - rebasedCount, startPos = 0
    if (start < 0) {
      startPos = -start
      start = 0
    }

    let mapping = rebasedTransform.mapping
    let newUntil = rebasedTransform.steps.length

    let iRebased = startPos
    this.items.forEach(item => {
      let pos = mapping.getMirror(iRebased++)
      if (pos == null) return
      newUntil = Math.min(newUntil, pos)
      let map = mapping.maps[pos]
      if (item.step) {
        let step = rebasedTransform.steps[pos].invert(rebasedTransform.docs[pos])
        let selection = item.selection && Selection.mapJSON(item.selection, mapping.slice(iRebased - 1, pos))
        rebasedItems.push(new Item(map, step, selection))
      } else {
        rebasedItems.push(new Item(map))
      }
    }, start)

    let newMaps = []
    for (let i = rebasedCount; i < newUntil; i++)
      newMaps.push(new Item(mapping.maps[i]))
    let items = this.items.slice(0, start).append(newMaps).append(rebasedItems)
    let branch = new Branch(items, this.eventCount) // FIXME might update event count
    if (branch.emptyItemCount() > max_empty_items)
      branch = branch.compress(this.items.length - rebasedItems.length)
    return branch
  }

  emptyItemCount() {
    let count = 0
    this.items.forEach(item => { if (!item.step) count++ })
    return count
  }

  // Compressing a branch means rewriting it to push the air (map-only
  // items) out. During collaboration, these naturally accumulate
  // because each remote change adds one. The `upto` argument is used
  // to ensure that only the items below a given level are compressed,
  // because `rebased` relies on a clean, untouched set of items in
  // order to associate old items with rebased steps.
  compress(upto = this.items.length) {
    let remap = this.remapping(0, upto), mapFrom = remap.maps.length
    let items = [], events = 0
    this.items.forEach((item, i) => {
      if (i >= upto) {
        items.push(item)
      } else if (item.step) {
        let step = item.step.map(remap.slice(mapFrom)), map = step && step.posMap()
        mapFrom--
        if (map) remap.appendMap(map, mapFrom)
        if (step) {
          let selection = item.selection && Selection.mapJSON(item.selection, remap.slice(mapFrom))
          if (selection) events++
          let newItem = new Item(map.invert(), step, selection), merged, last = items.length - 1
          if (merged = items.length && items[last].merge(newItem))
            items[last] = merged
          else
            items.push(newItem)
        }
      } else if (item.map) {
        mapFrom--
      }
    }, this.items.length, 0)
    return new Branch(RopeSequence.from(items.reverse()), events)
  }
}

Branch.empty = new Branch(RopeSequence.empty, 0)

function cutOffEvents(items, n) {
  let cutPoint
  items.forEach((item, i) => {
    if (item.selection && (--n == 0)) {
      cutPoint = i
      return false
    }
  })
  return items.slice(cutPoint)
}

class Item {
  constructor(map, step, selection, mirrorOffset) {
    this.map = map
    this.step = step
    this.selection = selection
    this.mirrorOffset = mirrorOffset
  }

  merge(other) {
    if (this.step && other.step && !other.selection) {
      let step = other.step.merge(this.step)
      if (step) return new Item(step.posMap().invert(), step, this.selection)
    }
  }
}

// ;; An undo/redo history manager for an editor instance.
class HistoryState {
  constructor(done, undone, prevMap) {
    this.done = done
    this.undone = undone
    this.prevMap = prevMap
  }

  // :: number
  // The amount of undoable events available.
  get undoDepth() { return this.done.eventCount }

  // :: number
  // The amount of redoable events available.
  get redoDepth() { return this.undone.eventCount }
}
exports.HistoryState = HistoryState

const defaults = {
  depth: 100,
  preserveItems: false
}
const DEPTH_OVERFLOW = 20

// : (EditorState, Transform, Selection, Object)
// Record a transformation in undo history.
function recordTransform(state, action, options) {
  let cur = state.history, transform = action.transform
  if (action.historyState) {
    return action.historyState
  } else if (transform.steps.length == 0) {
    return cur
  } else if (action.addToHistory !== false) {
    // Group transforms that occur in quick succession into one event.
    let newGroup = !isAdjacentToLastStep(transform, cur.prevMap, cur.done)
    return new HistoryState(cur.done.addTransform(transform, newGroup ? state.selection.toJSON() : null, options),
                            Branch.empty, transform.mapping.maps[transform.steps.length - 1])
  } else if (action.rebased) {
    // Used by the collab module to tell the history that some of its
    // content has been rebased.
    return new HistoryState(cur.done.rebased(transform, action.rebased),
                            cur.undone.rebased(transform, action.rebased),
                            cur.prevMap && transform.mapping.maps[transform.steps.length - 1])
  } else {
    return new HistoryState(cur.done.addMaps(transform.mapping.maps),
                            cur.undone.addMaps(transform.mapping.maps),
                            cur.prevMap)
  }
}

function isAdjacentToLastStep(transform, prevMap, done) {
  if (!prevMap) return false
  let firstMap = transform.mapping.maps[0], adjacent = false
  if (!firstMap) return true
  firstMap.forEach((start, end) => {
    done.items.forEach(item => {
      if (item.step) {
        prevMap.forEach((_start, _end, rStart, rEnd) => {
          if (start <= rEnd && end >= rStart) adjacent = true
        })
        return false
      } else {
        start = item.map.invert().map(start, -1)
        end = item.map.invert().map(end, 1)
      }
    }, done.items.length, 0)
  })
  return adjacent
}

// : (EditorState, bool, Object) → Object
// Apply the latest event from one branch to the document and optionally
// shift the event onto the other branch. Returns true when an event could
// be shifted.
function histAction(state, redo, histOptions) {
  let cur = state.history
  let pop = (redo ? cur.undone : cur.done).popEvent(state, histOptions.preserveItems)

  let selectionBeforeTransform = state.selection
  let selection = Selection.fromJSON(pop.transform.doc, pop.selection)
  let added = (redo ? cur.done : cur.undone).addTransform(pop.transform, selectionBeforeTransform.toJSON(), histOptions)

  let newHist = new HistoryState(redo ? added : pop.remaining, redo ? pop.remaining : added, null)
  return pop.transform.action({selection, historyState: newHist, scrollIntoView: true})
}

// :: (Object) → Plugin
// A plugin that enables the undo history for an editor. Has the
// effect of setting the editor's `history` property to an instance of
// `History`. Takes the following options:
//
// **`depth`**`: number`
//   : The amount of history events that are collected before the
//     oldest events are discarded. Defaults to 100.
//
// **`preserveItems`**`: bool`
//   : Whether to throw away undone items. Needs to be true to use the
//     history together with the collaborative editing plugin.
exports.history = function(config) {
  let options = {}
  for (let prop in defaults) options[prop] = config && config.hasOwnProperty(prop) ? config[prop] : defaults[prop]

  return {
    stateFields: {
      history: {
        init() {
          return new HistoryState(Branch.empty, Branch.empty, null)
        },
        applyAction(state, action) {
          if (action.type == "transform")
            return recordTransform(state, action, options)
          if (action.type == "historyClose")
            return new HistoryState(state.history.done, state.history.undone, null)
          return state.history
        }
      }
    },

    undo(state, onAction) {
      if (!state.history || state.history.undoDepth == 0) return false
      if (onAction) onAction(histAction(state, false, options))
      return true
    },

    redo(state, onAction) {
      if (!state.history || state.history.redoDepth == 0) return false
      if (onAction) onAction(histAction(state, true, options))
      return true
    }
  }
}
<|endoftext|>


<commit_before>'use strict'
var estraverse = require('estraverse')

// Node type unknown to estraverse
var keys = {
	ParenthesizedExpression: ['expression'],
}

// Gathered strings
var ss

function block(a, level) {
	if (a.type === 'BlockStatement') {
		ss.push(' ')
		emit(a, level)
	} else {
		ss.push('\n')
		indent(level + 1)
		emit(a, level + 1)
	}
}

function blockEnd(a, level) {
	if (a.type === 'BlockStatement')
		ss.push(' ')
	else {
		ss.push('\n')
		indent(level)
	}
}

function comment(a, level) {
	if (!a.comments)
		return
	ss.push('\n')
	for (var c of a.comments) {
		indent(level)
		if (c.type === 'Line') {
			ss.push('//')
			if (c.value[0] !== ' ')
				ss.push(' ')
			ss.push(c.value)
		} else
			ss.push('/*' + c.value + '*/')
		ss.push('\n')
	}
}

function emit(a, level) {
	switch (a.type) {
	case 'ArrayExpression':
		switch (a.elements.length) {
		case 0:
			ss.push('[]')
			break
		case 1:
			ss.push('[')
			emit(a.elements[0])
			ss.push(']')
			break
		default:
			ss.push('[\n')
			for (var b of a.elements) {
				comment(b, level + 1)
				indent(level + 1)
				emit(b, level + 1)
				ss.push(',\n')
			}
			indent(level)
			ss.push(']')
			break
		}
		break
	case 'ArrowFunctionExpression':
		if (a.params.length === 1)
			emit(a.params[0], level)
		else
			params(a.params, level)
		ss.push(' => ')
		if (a.body.type === 'BlockStatement')
			block(a.body, level)
		else
			emit(a.body, level)
		break
	case 'AssignmentExpression':
	case 'BinaryExpression':
	case 'LogicalExpression':
		emit(a.left, level)
		ss.push(' ' + a.operator + ' ')
		emit(a.right, level)
		break
	case 'AssignmentPattern':
		emit(a.left, level)
		ss.push('=')
		emit(a.right, level)
		break
	case 'BlockStatement':
		ss.push('{\n')
		for (var b of a.body) {
			comment(b, level + 1)
			stmt(b, level + 1)
		}
		indent(level)
		ss.push('}')
		break
	case 'BreakStatement':
		ss.push('break')
		if (a.label)
			ss.push(' ' + a.label.name)
		break
	case 'CallExpression':
		emit(a.callee, level)
		params(a.arguments, level)
		break
	case 'ConditionalExpression':
		emit(a.test, level)
		ss.push(' ? ')
		emit(a.consequent, level)
		ss.push(' : ')
		emit(a.alternate, level)
		break
	case 'ContinueStatement':
		ss.push('continue')
		if (a.label)
			ss.push(' ' + a.label.name)
		break
	case 'DoWhileStatement':
		ss.push('do')
		block(a.body, level)
		blockEnd(a.body, level)
		ss.push('while (')
		emit(a.test, level)
		ss.push(')')
		break
	case 'EmptyStatement':
		ss.push(';')
		break
	case 'ExpressionStatement':
		emit(a.expression, level)
		break
	case 'ForInStatement':
		ss.push('for (')
		forInit(a.left, level)
		ss.push(' in ')
		emit(a.right, level)
		ss.push(')')
		block(a.body, level)
		break
	case 'ForOfStatement':
		ss.push('for (')
		forInit(a.left, level)
		ss.push(' of ')
		emit(a.right, level)
		ss.push(')')
		block(a.body, level)
		break
	case 'ForStatement':
		ss.push('for (')
		if (a.init)
			forInit(a.init, level)
		ss.push(';')
		if (a.test) {
			ss.push(' ')
			emit(a.test, level)
		}
		ss.push(';')
		if (a.update) {
			ss.push(' ')
			emit(a.update, level)
		}
		ss.push(')')
		block(a.body, level)
		break
	case 'FunctionDeclaration':
		ss.push('function ' + a.id.name)
		params(a.params, level)
		block(a.body, level)
		break
	case 'FunctionExpression':
		ss.push('function ')
		if (a.id)
			ss.push(a.id.name)
		params(a.params, level)
		block(a.body, level)
		break
	case 'Identifier':
		ss.push(a.name)
		break
	case 'IfStatement':
		ss.push('if (')
		emit(a.test, level)
		ss.push(')')
		block(a.consequent, level)
		if (a.alternate) {
			blockEnd(a.consequent, level)
			ss.push('else')
			block(a.alternate, level)
		}
		break
	case 'LabeledStatement':
		ss.push(a.label.name + ':\n')
		level++
		indent(level)
		emit(a.body, level)
		break
	case 'Literal':
		if (typeof (a.value) === 'string') {
			var q = "'"
			if (a.value.indexOf(q) >= 0)
				q = '"'
			ss.push(q)
			for (var c of a.value)
				switch (c) {
				case '\b':
					ss.push('\\b')
					break
				case '\t':
					ss.push('\\t')
					break
				case '\n':
					ss.push('\\n')
					break
				case '\v':
					ss.push('\\v')
					break
				case '\f':
					ss.push('\\f')
					break
				case '\r':
					ss.push('\\r')
					break
				case '\\':
					ss.push('\\\\')
					break
				case q:
					ss.push('\\')
					ss.push(q)
					break
				default:
					var n = c.charCodeAt(0)
					if (32 <= n && n <= 126) {
						ss.push(c)
						break
					}
					if (n < 0x100) {
						ss.push('\\x')
						ss.push(hex(n, 2))
						break
					}
					ss.push('\\u')
					ss.push(hex(n, 4))
					break
				}
			ss.push(q)
			break
		}
		ss.push(a.raw)
		break
	case 'MemberExpression':
		emit(a.object, level)
		if (a.computed) {
			ss.push('[')
			emit(a.property, level)
			ss.push(']')
		} else {
			ss.push('.')
			emit(a.property, level)
		}
		break
	case 'NewExpression':
		ss.push('new ')
		emit(a.callee, level)
		params(a.arguments, level)
		break
	case 'ObjectExpression':
		if (!a.properties.length) {
			ss.push('{}')
			break
		}
		ss.push('{\n')
		for (var b of a.properties) {
			comment(b, level + 1)
			indent(level + 1)
			emit(b, level + 1)
			ss.push(',\n')
		}
		indent(level)
		ss.push('}')
		break
	case 'ParenthesizedExpression':
		ss.push('(')
		emit(a.expression, level)
		ss.push(')')
		break
	case 'Program':
		for (var b of a.body) {
			comment(b, 0)
			stmt(b, 0)
		}
		break
	case 'Property':
		if (a.key.type === 'Identifier' && a.value.type === 'Identifier' && a.key.name === a.value.name) {
			ss.push(a.key.name)
			break
		}
		if (a.value.type === 'FunctionExpression') {
			ss.push(a.key.name)
			params(a.value.params, level)
			block(a.value.body, level)
			break
		}
		emit(a.key, level)
		ss.push(': ')
		emit(a.value, level)
		break
	case 'ReturnStatement':
		ss.push('return')
		if (a.argument) {
			ss.push(' ')
			emit(a.argument, level)
		}
		break
	case 'SequenceExpression':
		for (var i = 0; i < a.expressions.length; i++) {
			if (i)
				ss.push(', ')
			emit(a.expressions[i], level)
		}
		break
	case 'SpreadElement':
		ss.push('...')
		emit(a.argument, level)
		break
	case 'SwitchStatement':
		ss.push('switch (')
		emit(a.discriminant, level)
		ss.push(') {\n')
		for (var c of a.cases) {
			comment(c, level)
			indent(level)
			if (c.test) {
				ss.push('case ')
				emit(c.test, level)
			} else
				ss.push('default')
			ss.push(':\n')
			for (var b of c.consequent) {
				comment(b, level + 1)
				indent(level + 1)
				emit(b, level + 1)
				ss.push('\n')
			}
		}
		indent(level)
		ss.push('}')
		break
	case 'ThisExpression':
		ss.push('this')
		break
	case 'ThrowStatement':
		ss.push('throw ')
		emit(a.argument, level)
		break
	case 'TryStatement':
		ss.push('try')
		block(a.block, level)
		if (a.handler) {
			ss.push(' catch (')
			emit(a.handler.param, level)
			ss.push(')')
			block(a.handler.body, level)
		}
		if (a.finalizer) {
			ss.push(' finally ')
			block(a.finalizer, level)
		}
		break
	case 'UnaryExpression':
		ss.push(a.operator)
		if (a.operator.search(/[a-z]/) >= 0)
			ss.push(' ')
		emit(a.argument, level)
		break
	case 'UpdateExpression':
		if (a.prefix) {
			ss.push(a.operator)
			emit(a.argument, level)
		} else {
			emit(a.argument, level)
			ss.push(a.operator)
		}
		break
	case 'VariableDeclaration':
		variableDeclaration(a, level)
		break
	case 'VariableDeclarator':
		ss.push(a.id.name)
		if (a.init) {
			ss.push(' = ')
			emit(a.init, level)
		}
		break
	case 'WhileStatement':
		ss.push('while (')
		emit(a.test, level)
		ss.push(')')
		block(a.body, level)
		break
	default:
		console.assert(false, a)
		break
	}
}

function forInit(a, level) {
	if (a.type === 'VariableDeclaration')
		variableDeclaration(a, level)
	else
		emit(a, level)
}

function hex(n, size) {
	var s = n.toString(16)
	while (s.length < size)
		s = '0' + s
	return s
}

function indent(level) {
	while (level--)
		ss.push('\t')
}

function params(a, level) {
	ss.push('(')
	if (a.some(b => b.type === 'ArrowFunctionExpression' && b.body.type === 'BlockStatement' || b.type === 'FunctionExpression')) {
		ss.push('\n')
		level++
		for (var i = 0; i < a.length; i++) {
			if (i)
				ss.push(',\n')
			indent(level)
			emit(a[i], level)
		}
	} else
		for (var i = 0; i < a.length; i++) {
			if (i)
				ss.push(', ')
			emit(a[i], level)
		}
	ss.push(')')
}

function run(a) {
	ss = []

	// Emit
	emit(a, 0)
	var text = ss.join('')

	// #!
	text = a.hashbang + '\n\n' + text

	// Only one consecutive blank line
	text = text.replace(/\n\n+/g, '\n\n')

	// Don't start with blank line
	text = text.replace(/^\n+/, '')

	// End with exactly one newline
	return text.replace(/\n*$/, '\n')
}

function stmt(a, level) {
	if (a.type === 'FunctionDeclaration')
		ss.push('\n')
	indent(level)
	emit(a, level)
	ss.push('\n')
	if (a.type === 'FunctionDeclaration')
		ss.push('\n')
}

function variableDeclaration(a, level) {
	ss.push('var ')
	for (var i = 0; i < a.declarations.length; i++) {
		if (i)
			ss.push(', ')
		emit(a.declarations[i], level)
	}
}

exports.run = run
<commit_msg>arrays<commit_after>'use strict'
var estraverse = require('estraverse')

// Node type unknown to estraverse
var keys = {
	ParenthesizedExpression: ['expression'],
}

// Gathered strings
var ss

function block(a, level) {
	if (a.type === 'BlockStatement') {
		ss.push(' ')
		emit(a, level)
	} else {
		ss.push('\n')
		indent(level + 1)
		emit(a, level + 1)
	}
}

function blockEnd(a, level) {
	if (a.type === 'BlockStatement')
		ss.push(' ')
	else {
		ss.push('\n')
		indent(level)
	}
}

function comment(a, level) {
	if (!a.comments)
		return
	ss.push('\n')
	for (var c of a.comments) {
		indent(level)
		if (c.type === 'Line') {
			ss.push('//')
			if (c.value[0] !== ' ')
				ss.push(' ')
			ss.push(c.value)
		} else
			ss.push('/*' + c.value + '*/')
		ss.push('\n')
	}
}

function emit(a, level) {
	switch (a.type) {
	case 'ArrayExpression':
		if (a.elements.every(isAtom)) {
			ss.push('[')
			for (var i = 0; i < a.elements.length; i++) {
				if (i)
					ss.push(', ')
				emit(a.elements[i])
			}
			ss.push(']')
			break
		}
		ss.push('[\n')
		for (var b of a.elements) {
			comment(b, level + 1)
			indent(level + 1)
			emit(b, level + 1)
			ss.push(',\n')
		}
		indent(level)
		ss.push(']')
		break
	case 'ArrowFunctionExpression':
		if (a.params.length === 1)
			emit(a.params[0], level)
		else
			params(a.params, level)
		ss.push(' => ')
		if (a.body.type === 'BlockStatement')
			block(a.body, level)
		else
			emit(a.body, level)
		break
	case 'AssignmentExpression':
	case 'BinaryExpression':
	case 'LogicalExpression':
		emit(a.left, level)
		ss.push(' ' + a.operator + ' ')
		emit(a.right, level)
		break
	case 'AssignmentPattern':
		emit(a.left, level)
		ss.push('=')
		emit(a.right, level)
		break
	case 'BlockStatement':
		ss.push('{\n')
		for (var b of a.body) {
			comment(b, level + 1)
			stmt(b, level + 1)
		}
		indent(level)
		ss.push('}')
		break
	case 'BreakStatement':
		ss.push('break')
		if (a.label)
			ss.push(' ' + a.label.name)
		break
	case 'CallExpression':
		emit(a.callee, level)
		params(a.arguments, level)
		break
	case 'ConditionalExpression':
		emit(a.test, level)
		ss.push(' ? ')
		emit(a.consequent, level)
		ss.push(' : ')
		emit(a.alternate, level)
		break
	case 'ContinueStatement':
		ss.push('continue')
		if (a.label)
			ss.push(' ' + a.label.name)
		break
	case 'DoWhileStatement':
		ss.push('do')
		block(a.body, level)
		blockEnd(a.body, level)
		ss.push('while (')
		emit(a.test, level)
		ss.push(')')
		break
	case 'EmptyStatement':
		ss.push(';')
		break
	case 'ExpressionStatement':
		emit(a.expression, level)
		break
	case 'ForInStatement':
		ss.push('for (')
		forInit(a.left, level)
		ss.push(' in ')
		emit(a.right, level)
		ss.push(')')
		block(a.body, level)
		break
	case 'ForOfStatement':
		ss.push('for (')
		forInit(a.left, level)
		ss.push(' of ')
		emit(a.right, level)
		ss.push(')')
		block(a.body, level)
		break
	case 'ForStatement':
		ss.push('for (')
		if (a.init)
			forInit(a.init, level)
		ss.push(';')
		if (a.test) {
			ss.push(' ')
			emit(a.test, level)
		}
		ss.push(';')
		if (a.update) {
			ss.push(' ')
			emit(a.update, level)
		}
		ss.push(')')
		block(a.body, level)
		break
	case 'FunctionDeclaration':
		ss.push('function ' + a.id.name)
		params(a.params, level)
		block(a.body, level)
		break
	case 'FunctionExpression':
		ss.push('function ')
		if (a.id)
			ss.push(a.id.name)
		params(a.params, level)
		block(a.body, level)
		break
	case 'Identifier':
		ss.push(a.name)
		break
	case 'IfStatement':
		ss.push('if (')
		emit(a.test, level)
		ss.push(')')
		block(a.consequent, level)
		if (a.alternate) {
			blockEnd(a.consequent, level)
			ss.push('else')
			block(a.alternate, level)
		}
		break
	case 'LabeledStatement':
		ss.push(a.label.name + ':\n')
		level++
		indent(level)
		emit(a.body, level)
		break
	case 'Literal':
		if (typeof (a.value) === 'string') {
			var q = "'"
			if (a.value.indexOf(q) >= 0)
				q = '"'
			ss.push(q)
			for (var c of a.value)
				switch (c) {
				case '\b':
					ss.push('\\b')
					break
				case '\t':
					ss.push('\\t')
					break
				case '\n':
					ss.push('\\n')
					break
				case '\v':
					ss.push('\\v')
					break
				case '\f':
					ss.push('\\f')
					break
				case '\r':
					ss.push('\\r')
					break
				case '\\':
					ss.push('\\\\')
					break
				case q:
					ss.push('\\')
					ss.push(q)
					break
				default:
					var n = c.charCodeAt(0)
					if (32 <= n && n <= 126) {
						ss.push(c)
						break
					}
					if (n < 0x100) {
						ss.push('\\x')
						ss.push(hex(n, 2))
						break
					}
					ss.push('\\u')
					ss.push(hex(n, 4))
					break
				}
			ss.push(q)
			break
		}
		ss.push(a.raw)
		break
	case 'MemberExpression':
		emit(a.object, level)
		if (a.computed) {
			ss.push('[')
			emit(a.property, level)
			ss.push(']')
		} else {
			ss.push('.')
			emit(a.property, level)
		}
		break
	case 'NewExpression':
		ss.push('new ')
		emit(a.callee, level)
		params(a.arguments, level)
		break
	case 'ObjectExpression':
		if (!a.properties.length) {
			ss.push('{}')
			break
		}
		ss.push('{\n')
		for (var b of a.properties) {
			comment(b, level + 1)
			indent(level + 1)
			emit(b, level + 1)
			ss.push(',\n')
		}
		indent(level)
		ss.push('}')
		break
	case 'ParenthesizedExpression':
		ss.push('(')
		emit(a.expression, level)
		ss.push(')')
		break
	case 'Program':
		for (var b of a.body) {
			comment(b, 0)
			stmt(b, 0)
		}
		break
	case 'Property':
		if (a.key.type === 'Identifier' && a.value.type === 'Identifier' && a.key.name === a.value.name) {
			ss.push(a.key.name)
			break
		}
		if (a.value.type === 'FunctionExpression') {
			ss.push(a.key.name)
			params(a.value.params, level)
			block(a.value.body, level)
			break
		}
		emit(a.key, level)
		ss.push(': ')
		emit(a.value, level)
		break
	case 'ReturnStatement':
		ss.push('return')
		if (a.argument) {
			ss.push(' ')
			emit(a.argument, level)
		}
		break
	case 'SequenceExpression':
		for (var i = 0; i < a.expressions.length; i++) {
			if (i)
				ss.push(', ')
			emit(a.expressions[i], level)
		}
		break
	case 'SpreadElement':
		ss.push('...')
		emit(a.argument, level)
		break
	case 'SwitchStatement':
		ss.push('switch (')
		emit(a.discriminant, level)
		ss.push(') {\n')
		for (var c of a.cases) {
			comment(c, level)
			indent(level)
			if (c.test) {
				ss.push('case ')
				emit(c.test, level)
			} else
				ss.push('default')
			ss.push(':\n')
			for (var b of c.consequent) {
				comment(b, level + 1)
				indent(level + 1)
				emit(b, level + 1)
				ss.push('\n')
			}
		}
		indent(level)
		ss.push('}')
		break
	case 'ThisExpression':
		ss.push('this')
		break
	case 'ThrowStatement':
		ss.push('throw ')
		emit(a.argument, level)
		break
	case 'TryStatement':
		ss.push('try')
		block(a.block, level)
		if (a.handler) {
			ss.push(' catch (')
			emit(a.handler.param, level)
			ss.push(')')
			block(a.handler.body, level)
		}
		if (a.finalizer) {
			ss.push(' finally ')
			block(a.finalizer, level)
		}
		break
	case 'UnaryExpression':
		ss.push(a.operator)
		if (a.operator.search(/[a-z]/) >= 0)
			ss.push(' ')
		emit(a.argument, level)
		break
	case 'UpdateExpression':
		if (a.prefix) {
			ss.push(a.operator)
			emit(a.argument, level)
		} else {
			emit(a.argument, level)
			ss.push(a.operator)
		}
		break
	case 'VariableDeclaration':
		variableDeclaration(a, level)
		break
	case 'VariableDeclarator':
		ss.push(a.id.name)
		if (a.init) {
			ss.push(' = ')
			emit(a.init, level)
		}
		break
	case 'WhileStatement':
		ss.push('while (')
		emit(a.test, level)
		ss.push(')')
		block(a.body, level)
		break
	default:
		console.assert(false, a)
		break
	}
}

function forInit(a, level) {
	if (a.type === 'VariableDeclaration')
		variableDeclaration(a, level)
	else
		emit(a, level)
}

function hex(n, size) {
	var s = n.toString(16)
	while (s.length < size)
		s = '0' + s
	return s
}

function indent(level) {
	while (level--)
		ss.push('\t')
}

function isAtom(a) {
	switch (a.type) {
	case 'Identifier':
	case 'Literal':
	case 'This':
		return true
	}
}

function params(a, level) {
	ss.push('(')
	if (a.some(b => b.type === 'ArrowFunctionExpression' && b.body.type === 'BlockStatement' || b.type === 'FunctionExpression')) {
		ss.push('\n')
		level++
		for (var i = 0; i < a.length; i++) {
			if (i)
				ss.push(',\n')
			indent(level)
			emit(a[i], level)
		}
	} else
		for (var i = 0; i < a.length; i++) {
			if (i)
				ss.push(', ')
			emit(a[i], level)
		}
	ss.push(')')
}

function run(a) {
	ss = []

	// Emit
	emit(a, 0)
	var text = ss.join('')

	// #!
	text = a.hashbang + '\n\n' + text

	// Only one consecutive blank line
	text = text.replace(/\n\n+/g, '\n\n')

	// Don't start with blank line
	text = text.replace(/^\n+/, '')

	// End with exactly one newline
	return text.replace(/\n*$/, '\n')
}

function stmt(a, level) {
	if (a.type === 'FunctionDeclaration')
		ss.push('\n')
	indent(level)
	emit(a, level)
	ss.push('\n')
	if (a.type === 'FunctionDeclaration')
		ss.push('\n')
}

function variableDeclaration(a, level) {
	ss.push('var ')
	for (var i = 0; i < a.declarations.length; i++) {
		if (i)
			ss.push(', ')
		emit(a.declarations[i], level)
	}
}

exports.run = run
<|endoftext|>


<commit_before>var assume = require('assume');
var jsone = require('../src/');

suite('misc', function() {
  test('custom builtin', function() {
    let my_builtin = (x, y) => Math.sqrt(x * x + y * y);

    assume(jsone({$eval: 'my_builtin(3, 4)'}, {my_builtin})).eql(5);
  });

  test('time doesn\'t change mid-evaluation (operator)', function() {
    let template = [...Array(1000).keys()].map(() => ({$fromNow: ''}));
    let result = new Set(jsone(template, {}));

    assume(result.size).eql(1);
  });

  test('time doesn\'t change mid-evaluation (builtin)', function() {
    let template = [...Array(1000).keys()].map(() => ({$eval: 'fromNow("")'}));
    let result = new Set(jsone(template, {}));

    assume(result.size).eql(1);
  });
});
<commit_msg>Added small test to test/misc_test.js that checks that the now builtin returns a string rather than a datetime.<commit_after>var assume = require('assume');
var jsone = require('../src/');

suite('misc', function() {
  test('custom builtin', function() {
    let my_builtin = (x, y) => Math.sqrt(x * x + y * y);

    assume(jsone({$eval: 'my_builtin(3, 4)'}, {my_builtin})).eql(5);
  });

  test('time doesn\'t change mid-evaluation (operator)', function() {
    let template = [...Array(1000).keys()].map(() => ({$fromNow: ''}));
    let result = new Set(jsone(template, {}));

    assume(result.size).eql(1);
  });

  test('time doesn\'t change mid-evaluation (builtin)', function() {
    let template = [...Array(1000).keys()].map(() => ({$eval: 'fromNow("")'}));
    let result = new Set(jsone(template, {}));

    assume(result.size).eql(1);
  });

  test('now builtin returns a string', function() {
    assume(typeof jsone({$eval: 'now'}, {})).eql(typeof "string");
  });
});
<|endoftext|>


<commit_before><commit_msg>added version comment<commit_after><|endoftext|>


<commit_before>// index.js
var config = require('./config');
var getsoda = require('./getsoda');
var insertrow = require('./insertrow');
var Promise = require("bluebird");

getsoda()
.then(function(responsedata) {
    return responsedata;
})
.each(function(record){
    insertrow(record);
    return 0;
})
.catch(function(e) {
    console.log('Error: ' + e)
})

<commit_msg>.then function does nothing.<commit_after>// index.js
var config = require('./config');
var getsoda = require('./getsoda');
var insertrow = require('./insertrow');
var Promise = require("bluebird");

getsoda()
.each(function(record){
    insertrow(record);
    return 0;
})
.catch(function(e) {
    console.log('Error: ' + e)
})

<|endoftext|>


<commit_before>'use strict';

var secrets = require('../secrets');

module.exports = {
	db: process.env.MONGOHQ_URL || process.env.MONGOLAB_URI || 'mongodb://localhost/im-dev',
	usehttp: true, // should a non encrypted server be launched?
	usessl: true, // should an encrypted server be launced?
	port: process.env.PORT || 3000,
	sslport: process.env.SSLPORT || 443,
	key_file: './config/cert/rodekruis-key.pem',
	cert_file: './config/cert/rodekruis-cert.pem',
	app: {
		title: 'Rode Kruis Digital Operations Center'
	},
	assets: {
		lib: {
			css: [
				'public/lib/bootstrap/dist/css/bootstrap.min.css',
				'public/lib/bootstrap/dist/css/bootstrap-theme.min.css',
				'public/lib/leaflet-dist/leaflet.css',
				'public/lib/cartodb/cartodb.css',
				'public/lib/jquery-ui/themes/smoothness/jquery-ui.min.css',
				'public/lib/angular-centered/angular-centered.css',
				'public/lib/angular-ui-dashboard/dist/angular-ui-dashboard.css',
				'public/lib/ng-grid/ng-grid.min.css',
				'public/lib/select2/select2.css',
				//'public/lib/select2-bootstrap-css/select2-bootstrap.css',
				'public/lib/forms-angular/css/forms-angular-bs3.less',
				'public/lib/angular-carousel/dist/angular-carousel.min.css',
				'public/lib/leaflet-search/dist/leaflet-search.min.css',
				'public/lib/angular-busy/dist/angular-busy.min.css',
				'public/lib/leaflet-gps/dist/leaflet-gps.min.css'

			],
			js: [
				'public/lib/jquery/jquery.min.js',
				'public/lib/jquery-ui/ui/minified/jquery-ui.min.js',
				'public/lib/lodash/dist/lodash.min.js',
				'public/lib/angular/angular.min.js',
				'public/lib/angular-lodash/angular-lodash.js',
				'public/lib/angular-route/angular-route.min.js',
				'public/lib/angular-resource/angular-resource.min.js',
				'public/lib/angular-cookies/angular-cookies.min.js',
				'public/lib/angular-animate/angular-animate.min.js',
				'public/lib/angular-touch/angular-touch.min.js',
				'public/lib/angular-sanitize/angular-sanitize.min.js',
				'public/lib/angular-ui-router/release/angular-ui-router.min.js',
				'public/lib/angular-ui-utils/ui-utils.min.js',
				'public/lib/angular-bootstrap/ui-bootstrap-tpls.min.js',
				'public/lib/angular-leaflet/dist/angular-leaflet-directive.min.js',
				'public/lib/cartodb/cartodb.js',
				'public/lib/cartodb/activelayers.js',
				'public/lib/angular-centered/angular-centered.js',
				'public/lib/angular-deckgrid/angular-deckgrid.js',
				//'public/lib/smart-table/Smart-Table.min.js',
				'public/lib/angular-ui-sortable/sortable.min.js',
				'public/lib/angular-ui-dashboard/dist/angular-ui-dashboard.js',
				'public/lib/angular-ui-date/src/date.js',
				'public/lib/angular-ui-bootstrap-bower/ui-bootstrap-tpls.min.js',
				'public/lib/ngInfiniteScroll/build/ng-infinite-scroll.min.js',
				'public/lib/jspdf/dist/jspdf.min.js',
				'public/lib/ng-grid/build/ng-grid.min.js',
				'public/lib/angular-elastic/elastic.js',
				'public/lib/angular-ui-select2/src/select2.js',
				'public/lib/ckeditor/ckeditor.js',
				'public/lib/ng-ckeditor/ng-ckeditor.min.js',
				'public/lib/forms-angular/forms-angular.min.js',
				'public/lib/angular-carousel/dist/angular-carousel.min.js',
				'https://maps.googleapis.com/maps/api/js?v=3&sensor=true',
				'public/lib/leaflet-search/dist/leaflet-search.min.js',
				'public/lib/Leaflet.NonTiledLayer/NonTiledLayer.js',
				'public/lib/Leaflet.NonTiledLayer/NonTiledLayer.WMS.js',
				'public/lib/leaflet-betterwms/L.TileLayer.BetterWMS.js',
				'public/lib/Leaflet.WMS.GetLegendGraphic/leaflet-wms-getlegendgraphic.js',
				'public/lib/azgs-leaflet/js/lib/less-1.2.2.min.js',
				'public/lib/azgs-leaflet/js/lib/jade.js',
				'public/lib/leaflet.ajax/dist/leaflet.ajax.min.js',
				'public/lib/azgs-leaflet/js/azgs-leaflet/GeoJSON.WFS.js',
				'public/lib/azgs-leaflet/js/azgs-leaflet/GeoJSON.WFS.ClickResponder.js',
				'public/lib/angular-busy/dist/angular-busy.min.js',
				'public/lib/leaflet-gps/dist/leaflet-gps.min.js'
			]
		},
		css: 'public/dist/application.min.css',
		js: 'public/dist/application.min.js'
	},
	facebook: {
		clientID: process.env.FACEBOOK_ID || 'APP_ID',
		clientSecret: process.env.FACEBOOK_SECRET || 'APP_SECRET',
		callbackURL: 'http://localhost:3000/auth/facebook/callback'
	},
	twitter: {
		clientID: process.env.TWITTER_KEY || 'CONSUMER_KEY',
		clientSecret: process.env.TWITTER_SECRET || 'CONSUMER_SECRET',
		callbackURL: 'http://localhost:3000/auth/twitter/callback'
	},
	google: {
		clientID: process.env.GOOGLE_ID || 'APP_ID',
		clientSecret: process.env.GOOGLE_SECRET || 'APP_SECRET',
		callbackURL: 'http://localhost:3000/auth/google/callback'
	},
	linkedin: {
		clientID: process.env.LINKEDIN_ID || 'APP_ID',
		clientSecret: process.env.LINKEDIN_SECRET || 'APP_SECRET',
		callbackURL: 'http://localhost:3000/auth/linkedin/callback'
	},
	azure: {
		clientID: secrets.azure.clientID,
		clientSecret: secrets.azure.clientSecret,
		tenantId: secrets.azure.tenantId,
		resource: 'https://graph.windows.net',
		redirectURL: 'http://digidoc.rodekruis.nl/auth/azure/callback',
		redirectURLSSL: 'https://digidoc.rodekruis.nl/auth/azure/callback'
	}
};<commit_msg>change ports<commit_after>'use strict';

var secrets = require('../secrets');

module.exports = {
	db: process.env.MONGOHQ_URL || process.env.MONGOLAB_URI || 'mongodb://localhost/im-dev',
	usehttp: true, // should a non encrypted server be launched?
	usessl: true, // should an encrypted server be launced?
	port: process.env.PORT || 3000,
	sslport: process.env.SSLPORT || 444,
	key_file: './config/cert/rodekruis-key.pem',
	cert_file: './config/cert/rodekruis-cert.pem',
	app: {
		title: 'Rode Kruis Digital Operations Center'
	},
	assets: {
		lib: {
			css: [
				'public/lib/bootstrap/dist/css/bootstrap.min.css',
				'public/lib/bootstrap/dist/css/bootstrap-theme.min.css',
				'public/lib/leaflet-dist/leaflet.css',
				'public/lib/cartodb/cartodb.css',
				'public/lib/jquery-ui/themes/smoothness/jquery-ui.min.css',
				'public/lib/angular-centered/angular-centered.css',
				'public/lib/angular-ui-dashboard/dist/angular-ui-dashboard.css',
				'public/lib/ng-grid/ng-grid.min.css',
				'public/lib/select2/select2.css',
				//'public/lib/select2-bootstrap-css/select2-bootstrap.css',
				'public/lib/forms-angular/css/forms-angular-bs3.less',
				'public/lib/angular-carousel/dist/angular-carousel.min.css',
				'public/lib/leaflet-search/dist/leaflet-search.min.css',
				'public/lib/angular-busy/dist/angular-busy.min.css',
				'public/lib/leaflet-gps/dist/leaflet-gps.min.css'

			],
			js: [
				'public/lib/jquery/jquery.min.js',
				'public/lib/jquery-ui/ui/minified/jquery-ui.min.js',
				'public/lib/lodash/dist/lodash.min.js',
				'public/lib/angular/angular.min.js',
				'public/lib/angular-lodash/angular-lodash.js',
				'public/lib/angular-route/angular-route.min.js',
				'public/lib/angular-resource/angular-resource.min.js',
				'public/lib/angular-cookies/angular-cookies.min.js',
				'public/lib/angular-animate/angular-animate.min.js',
				'public/lib/angular-touch/angular-touch.min.js',
				'public/lib/angular-sanitize/angular-sanitize.min.js',
				'public/lib/angular-ui-router/release/angular-ui-router.min.js',
				'public/lib/angular-ui-utils/ui-utils.min.js',
				'public/lib/angular-bootstrap/ui-bootstrap-tpls.min.js',
				'public/lib/angular-leaflet/dist/angular-leaflet-directive.min.js',
				'public/lib/cartodb/cartodb.js',
				'public/lib/cartodb/activelayers.js',
				'public/lib/angular-centered/angular-centered.js',
				'public/lib/angular-deckgrid/angular-deckgrid.js',
				//'public/lib/smart-table/Smart-Table.min.js',
				'public/lib/angular-ui-sortable/sortable.min.js',
				'public/lib/angular-ui-dashboard/dist/angular-ui-dashboard.js',
				'public/lib/angular-ui-date/src/date.js',
				'public/lib/angular-ui-bootstrap-bower/ui-bootstrap-tpls.min.js',
				'public/lib/ngInfiniteScroll/build/ng-infinite-scroll.min.js',
				'public/lib/jspdf/dist/jspdf.min.js',
				'public/lib/ng-grid/build/ng-grid.min.js',
				'public/lib/angular-elastic/elastic.js',
				'public/lib/angular-ui-select2/src/select2.js',
				'public/lib/ckeditor/ckeditor.js',
				'public/lib/ng-ckeditor/ng-ckeditor.min.js',
				'public/lib/forms-angular/forms-angular.min.js',
				'public/lib/angular-carousel/dist/angular-carousel.min.js',
				'https://maps.googleapis.com/maps/api/js?v=3&sensor=true',
				'public/lib/leaflet-search/dist/leaflet-search.min.js',
				'public/lib/Leaflet.NonTiledLayer/NonTiledLayer.js',
				'public/lib/Leaflet.NonTiledLayer/NonTiledLayer.WMS.js',
				'public/lib/leaflet-betterwms/L.TileLayer.BetterWMS.js',
				'public/lib/Leaflet.WMS.GetLegendGraphic/leaflet-wms-getlegendgraphic.js',
				'public/lib/azgs-leaflet/js/lib/less-1.2.2.min.js',
				'public/lib/azgs-leaflet/js/lib/jade.js',
				'public/lib/leaflet.ajax/dist/leaflet.ajax.min.js',
				'public/lib/azgs-leaflet/js/azgs-leaflet/GeoJSON.WFS.js',
				'public/lib/azgs-leaflet/js/azgs-leaflet/GeoJSON.WFS.ClickResponder.js',
				'public/lib/angular-busy/dist/angular-busy.min.js',
				'public/lib/leaflet-gps/dist/leaflet-gps.min.js'
			]
		},
		css: 'public/dist/application.min.css',
		js: 'public/dist/application.min.js'
	},
	facebook: {
		clientID: process.env.FACEBOOK_ID || 'APP_ID',
		clientSecret: process.env.FACEBOOK_SECRET || 'APP_SECRET',
		callbackURL: 'http://localhost:3000/auth/facebook/callback'
	},
	twitter: {
		clientID: process.env.TWITTER_KEY || 'CONSUMER_KEY',
		clientSecret: process.env.TWITTER_SECRET || 'CONSUMER_SECRET',
		callbackURL: 'http://localhost:3000/auth/twitter/callback'
	},
	google: {
		clientID: process.env.GOOGLE_ID || 'APP_ID',
		clientSecret: process.env.GOOGLE_SECRET || 'APP_SECRET',
		callbackURL: 'http://localhost:3000/auth/google/callback'
	},
	linkedin: {
		clientID: process.env.LINKEDIN_ID || 'APP_ID',
		clientSecret: process.env.LINKEDIN_SECRET || 'APP_SECRET',
		callbackURL: 'http://localhost:3000/auth/linkedin/callback'
	},
	azure: {
		clientID: secrets.azure.clientID,
		clientSecret: secrets.azure.clientSecret,
		tenantId: secrets.azure.tenantId,
		resource: 'https://graph.windows.net',
		redirectURL: 'http://digidoc.rodekruis.nl/auth/azure/callback',
		redirectURLSSL: 'https://digidoc.rodekruis.nl/auth/azure/callback'
	}
};<|endoftext|>