<commit_before>// Config
var main = require('../main.js');
var app = main.app();
var server = main.server();
var mongoose = main.mongoose();
var open = false;
var timeout = setTimeout(function() {
			console.log('exiting');
			process.exit();
		}, 3000);
// Module to test
var testProject = process.env.CUSTOM_COV ?
	require('../lib-cov/project/abstractedProject.js')
	: require('../lib/project/abstractedProject.js');

// For testing purposes
var expected;
var result;

// Mocks
var request = Object;
var response = Object;
response.res = [];
response.send = function(resp) {
	response.res.push(resp);
};

module.exports = {
	setUp: function(callback) {
		clearTimeout(timeout);
		if (open === true) {
			callback();
			return;
		}
		try {
			mongoose.connection.on('open', function() {
				open = true;
				callback();
			});
		} catch (err) {
			console.log(err);
		}
	},

	tearDown : function(callback) {
		timeout = setTimeout(function() {
			console.log('exiting');
			process.exit();
		}, 3000);
		callback();
	},

	testCreateProject: function(test) {
		// test.expect(11);

		// Object to create
		request.body = {'heading':'testHeading', 'description':'testDesc', 'owner': 'testOwner', 'users': ['testUser1', 'testUser2', 'testUser3']};

		// Function being tested
		testProject.createProject(app, mongoose, request, response);
		var pResult = response.res.pop();
		expected = 'testHeading';
		result = pResult.name;
		test.equal(expected, result);

		expected = 'testDesc';
		result = pResult.description;
		test.equal(expected, result);

		expected = false;
		result = pResult.deleted;
		test.equal(expected, result);

		expected = 0;
		result = pResult.children.length;
		test.equal(expected, result);

		expected = 'testOwner';
		result = pResult.owner;
		test.equal(expected, result);

		expected = 3;
		result = pResult.users.length;
		test.equal(expected, result);

		expected = 'testUser1';
		result = pResult.users[0];
		test.equal(expected, result);

		expected = 'testUser3';
		result = pResult.users[2];
		test.equal(expected, result);

		request.body = {'heading':'testHeading', 'description':'testDesc', 'owner': '', 'users': ['testUser1', 'testUser2', 'testUser3']};
		testProject.createProject(app, mongoose, request, response);

		pResult = response.res.pop();
		expected = false;
		result = pResult;
		test.equal(expected, result);

		request.body = {'heading':'testHeading2', 'description':'testDesc2', 'owner': 'testOwner', 'users': ['testUser1', 'testUser3']};
		testProject.createProject(app, mongoose, request, response);

		pResult = response.res.pop();
		expected = 'testHeading2';
		result = pResult.name;
		test.equal(expected, result);

		expected = 'testDesc2';
		result = pResult.description;
		test.equal(expected, result);

		request.body = {'heading':'testHeading3', 'description':'testDesc4', 'owner': 'testOwner', 'users': ['testUser1', 'testUser3']};
		testProject.createProject(app, mongoose, request, response);
		response.res.pop();
		request.body = {'heading':'testHeading4', 'description':'testDesc5', 'owner': 'testOwner', 'users': ['testUser1', 'testUser3']};
		testProject.createProject(app, mongoose, request, response);
		response.res.pop();

		test.done();
	},

	testGetAllProjects: function(test) {
		testProject.getAllProjects(app, mongoose, request, response, function(res) {
			var tmp = response.res.pop();
			expected = 4;
			result = tmp.length;
			test.equal(expected, result);

			expected = 'testHeading';
			result = tmp[0].name;
			test.equal(expected, result);

			expected = 'testHeading2';
			result = tmp[1].name;
			test.equal(expected, result);

			expected = 'testHeading3';
			result = tmp[2].name;
			test.equal(expected, result);

			expected = 'testHeading4';
			result = tmp[3].name;
			test.equal(expected, result);
			test.done();
		});
	},

	testGetProject: function(test) {
		request.body = {'heading': 'testHeading'};
		testProject.getProject(app, mongoose, request, response, function(res) {
			result = response.res.pop()[0];

			expected = 'testHeading';
			test.equal(expected, result.name);

			expected = 'testDesc';
			test.equal(expected, result.description);

			expected = 'testOwner';
			test.equal(expected, result.owner);
			expected = 3;
			test.equal(expected, result.users.length);

			expected = 'testUser1';
			test.equal(expected, result.users[0]);
			request.body = {'heading':'testConflictHeading', 'description':'testConflictDesc', 'owner': 'testConflictOwner', 'users': ['testUser3']};
			testProject.createProject(app, mongoose, request, response, function() {
				request.body = {'heading':'testHeading'};
				testProject.getProject(app, mongoose, request, response, function(res) {

					test.done();
				});
			});
		});
	}

};
<commit_msg>Further tests<commit_after>// Config
var main = require('../main.js');
var app = main.app();
var server = main.server();
var mongoose = main.mongoose();
var open = false;
var timeout = setTimeout(function() {
			console.log('exiting');
			process.exit();
		}, 3000);
// Module to test
var testProject = process.env.CUSTOM_COV ?
	require('../lib-cov/project/abstractedProject.js')
	: require('../lib/project/abstractedProject.js');

// For testing purposes
var expected;
var result;

// Mocks
var request = Object;
var response = Object;
response.res = [];
response.send = function(resp) {
	response.res.push(resp);
};

module.exports = {
	setUp: function(callback) {
		clearTimeout(timeout);
		if (open === true) {
			callback();
			return;
		}
		try {
			mongoose.connection.on('open', function() {
				open = true;
				callback();
			});
		} catch (err) {
			console.log(err);
		}
	},

	tearDown : function(callback) {
		timeout = setTimeout(function() {
			console.log('exiting');
			process.exit();
		}, 3000);
		callback();
	},

	testCreateProject: function(test) {
		// test.expect(11);

		// Object to create
		request.body = {'heading':'testHeading', 'description':'testDesc', 'owner': 'testOwner', 'users': ['testUser1', 'testUser2', 'testUser3']};

		// Function being tested
		testProject.createProject(app, mongoose, request, response);
		var pResult = response.res.pop();
		expected = 'testHeading';
		result = pResult.name;
		test.equal(expected, result);

		expected = 'testDesc';
		result = pResult.description;
		test.equal(expected, result);

		expected = false;
		result = pResult.deleted;
		test.equal(expected, result);

		expected = 0;
		result = pResult.children.length;
		test.equal(expected, result);

		expected = 'testOwner';
		result = pResult.owner;
		test.equal(expected, result);

		expected = 3;
		result = pResult.users.length;
		test.equal(expected, result);

		expected = 'testUser1';
		result = pResult.users[0];
		test.equal(expected, result);

		expected = 'testUser3';
		result = pResult.users[2];
		test.equal(expected, result);

		request.body = {'heading':'testHeading', 'description':'testDesc', 'owner': '', 'users': ['testUser1', 'testUser2', 'testUser3']};
		testProject.createProject(app, mongoose, request, response);

		pResult = response.res.pop();
		expected = false;
		result = pResult;
		test.equal(expected, result);

		request.body = {'heading':'testHeading2', 'description':'testDesc2', 'owner': 'testOwner', 'users': ['testUser1', 'testUser3']};
		testProject.createProject(app, mongoose, request, response);

		pResult = response.res.pop();
		expected = 'testHeading2';
		result = pResult.name;
		test.equal(expected, result);

		expected = 'testDesc2';
		result = pResult.description;
		test.equal(expected, result);

		request.body = {'heading':'testHeading3', 'description':'testDesc4', 'owner': 'testOwner', 'users': ['testUser1', 'testUser3']};
		testProject.createProject(app, mongoose, request, response);
		response.res.pop();
		request.body = {'heading':'testHeading4', 'description':'testDesc5', 'owner': 'testOwner', 'users': ['testUser1', 'testUser3']};
		testProject.createProject(app, mongoose, request, response);
		response.res.pop();

		test.done();
	},

	testGetAllProjects: function(test) {
		testProject.getAllProjects(app, mongoose, request, response, function(res) {
			var tmp = response.res.pop();
			expected = 4;
			result = tmp.length;
			test.equal(expected, result);

			expected = 'testHeading';
			result = tmp[0].name;
			test.equal(expected, result);

			expected = 'testHeading2';
			result = tmp[1].name;
			test.equal(expected, result);

			expected = 'testHeading3';
			result = tmp[2].name;
			test.equal(expected, result);

			expected = 'testHeading4';
			result = tmp[3].name;
			test.equal(expected, result);
			test.done();
		});
	},

	testGetProject: function(test) {
		request.body = {'heading': 'testHeading'};
		testProject.getProject(app, mongoose, request, response, function(res) {
			result = response.res.pop()[0];

			expected = 'testHeading';
			test.equal(expected, result.name);

			expected = 'testDesc';
			test.equal(expected, result.description);

			expected = 'testOwner';
			test.equal(expected, result.owner);
			expected = 3;
			test.equal(expected, result.users.length);

			expected = 'testUser1';
			test.equal(expected, result.users[0]);
			request.body = {'heading':'testConflictHeading', 'description':'testConflictDesc', 'owner': 'testConflictOwner', 'users': ['testUser3']};
			testProject.createProject(app, mongoose, request, response, function() {
				request.body = {'heading':'testHeading'};
				testProject.getProject(app, mongoose, request, response, function(res) {
					expected = 2;
					test.equal(expected, response.res.length);
					test.done();
				});
			});
		});
	}

};
<|endoftext|>


<commit_before>!function ($) {

    /* MODAL POPOVER PUBLIC CLASS DEFINITION
     * =============================== */

    var ModalPopover = function (element, options) {
        this.options = options;
        this.$element = $(element)
            .delegate('[data-dismiss="modal-popup"]', 'click.dismiss.modal-popup', $.proxy(this.hide, this));
        this.options.remote && this.$element.find('.popover-content').load(this.options.remote);
        this.$parent = options.$parent; // todo make sure parent is specified
    }

    /* NOTE: MODAL POPOVER EXTENDS BOOTSTRAP-MODAL.js
     ========================================== */

    ModalPopover.prototype = $.extend({}, $.fn.modal.Constructor.prototype, {

        constructor:ModalPopover,

        getPosition:function () {
            var $element = this.$parent;
            return $.extend({}, ($element.offset()), {
                width:$element[0].offsetWidth, height:$element[0].offsetHeight
            });
        },

        show:function () {

            var $dialog = this.$element;
            $dialog.css({ top:0, left:0, display:'block', 'z-index':1050 });

            var placement = typeof this.options.placement == 'function' ?
                this.options.placement.call(this, $tip[0], this.$element[0]) :
                this.options.placement;

            var pos = this.getPosition();

            var actualWidth = $dialog[0].offsetWidth;
            var actualHeight = $dialog[0].offsetHeight;

            var tp;
            switch (placement) {
                case 'bottom':
                    tp = {top:pos.top + pos.height, left:pos.left + pos.width / 2 - actualWidth / 2}
                    break;
                case 'top':
                    tp = {top:pos.top - actualHeight, left:pos.left + pos.width / 2 - actualWidth / 2}
                    break;
                case 'left':
                    tp = {top:pos.top + pos.height / 2 - actualHeight / 2, left:pos.left - actualWidth}
                    break;
                case 'right':
                    tp = {top:pos.top + pos.height / 2 - actualHeight / 2, left:pos.left + pos.width}
                    break;
            }

            $dialog
                .css(tp)
                .addClass(placement)
                .addClass('in');

            $.fn.modal.Constructor.prototype.show.call(this, arguments); // super
        },

        /** todo entire function was copied just to set the background to 'none'.  need a better way */
        backdrop:function (callback) {
            var that = this
                , animate = this.$element.hasClass('fade') ? 'fade' : ''

            if (this.isShown && this.options.backdrop) {
                var doAnimate = $.support.transition && animate

                this.$backdrop = $('
')
                    .appendTo(document.body)

                if (this.options.backdrop != 'static') {
                    this.$backdrop.click($.proxy(this.hide, this))
                }

                if (doAnimate) this.$backdrop[0].offsetWidth // force reflow

                this.$backdrop.addClass('in')

                doAnimate ?
                    this.$backdrop.one($.support.transition.end, callback) :
                    callback()

            } else if (!this.isShown && this.$backdrop) {
                this.$backdrop.removeClass('in')

                $.support.transition && this.$element.hasClass('fade') ?
                    this.$backdrop.one($.support.transition.end, $.proxy(this.removeBackdrop, this)) :
                    this.removeBackdrop()

            } else if (callback) {
                callback()
            }
        }

    });

    /* MODAL POPOVER PLUGIN DEFINITION
     * ======================= */

    $.fn.modalPopover = function (option) {
        return this.each(function () {
            var $this = $(this);
            var data = $this.data('modal-popover');
            var options = $.extend({}, $.fn.modalPopover.defaults, $this.data(), typeof option == 'object' && option);
            options['$parent'] = option.$parent || $this;

            if (!data) $this.data('modal-popover', (data = new ModalPopover(this, options)))

            if (typeof option == 'string') data[option]()
            else if (options.show) data.show()
        })
    }

    $.fn.modalPopover.Constructor = ModalPopover

    $.fn.modalPopover.defaults = $.extend({}, $.fn.modal.defaults, {
        placement:'right',
        keyboard: true
    });

    $(function () {
        $('body').on('click.modal-popover.data-api', '[data-toggle="modal-popover"]', function (e) {
            var $this = $(this);
            var href = $this.attr('href');
            var $dialog = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))); //strip for ie7
            var option = $dialog.data('modal-popover') ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $dialog.data(), $this.data());
            option['$parent'] = $this;

            e.preventDefault();

            $dialog
                .modalPopover(option)
                .one('hide', function () {
                    $this.focus()
                })
        })
    })

}(window.jQuery);<commit_msg>iphone support<commit_after>!function ($) {

    /* MODAL POPOVER PUBLIC CLASS DEFINITION
     * =============================== */

    var ModalPopover = function (element, options) {
        this.options = options;
        this.$element = $(element)
            .delegate('[data-dismiss="modal-popup"]', 'click.dismiss.modal-popup', $.proxy(this.hide, this));
        this.options.remote && this.$element.find('.popover-content').load(this.options.remote);
        this.$parent = options.$parent; // todo make sure parent is specified
    }

    /* NOTE: MODAL POPOVER EXTENDS BOOTSTRAP-MODAL.js
     ========================================== */

    ModalPopover.prototype = $.extend({}, $.fn.modal.Constructor.prototype, {

        constructor:ModalPopover,

        getPosition:function () {
            var $element = this.$parent;
            return $.extend({}, ($element.offset()), {
                width:$element[0].offsetWidth, height:$element[0].offsetHeight
            });
        },

        show:function () {
            var $dialog = this.$element;
            $dialog.css({ top:0, left:0, display:'block', 'z-index':1050 });

            var placement = typeof this.options.placement == 'function' ?
                this.options.placement.call(this, $tip[0], this.$element[0]) :
                this.options.placement;

            var pos = this.getPosition();

            var actualWidth = $dialog[0].offsetWidth;
            var actualHeight = $dialog[0].offsetHeight;

            var tp;
            switch (placement) {
                case 'bottom':
                    tp = {top:pos.top + pos.height, left:pos.left + pos.width / 2 - actualWidth / 2}
                    break;
                case 'top':
                    tp = {top:pos.top - actualHeight, left:pos.left + pos.width / 2 - actualWidth / 2}
                    break;
                case 'left':
                    tp = {top:pos.top + pos.height / 2 - actualHeight / 2, left:pos.left - actualWidth}
                    break;
                case 'right':
                    tp = {top:pos.top + pos.height / 2 - actualHeight / 2, left:pos.left + pos.width}
                    break;
            }

            $dialog
                .css(tp)
                .addClass(placement)
                .addClass('in');

            $.fn.modal.Constructor.prototype.show.call(this, arguments); // super
        },

        /** todo entire function was copied just to set the background to 'none'.  need a better way */
        backdrop:function (callback) {
            var that = this
                , animate = this.$element.hasClass('fade') ? 'fade' : ''

            if (this.isShown && this.options.backdrop) {
                var doAnimate = $.support.transition && animate

                this.$backdrop = $('
')
                    .appendTo(document.body)

                if (this.options.backdrop != 'static') {
                    this.$backdrop.click($.proxy(this.hide, this))
                }

                if (doAnimate) this.$backdrop[0].offsetWidth // force reflow

                this.$backdrop.addClass('in')

                doAnimate ?
                    this.$backdrop.one($.support.transition.end, callback) :
                    callback()

            } else if (!this.isShown && this.$backdrop) {
                this.$backdrop.removeClass('in')

                $.support.transition && this.$element.hasClass('fade') ?
                    this.$backdrop.one($.support.transition.end, $.proxy(this.removeBackdrop, this)) :
                    this.removeBackdrop()

            } else if (callback) {
                callback()
            }
        }

    });

    /* MODAL POPOVER PLUGIN DEFINITION
     * ======================= */

    $.fn.modalPopover = function (option) {
        return this.each(function () {
            console.log(['this', this])
            var $this = $(this);
            var data = $this.data('modal-popover');
            var options = $.extend({}, $.fn.modalPopover.defaults, $this.data(), typeof option == 'object' && option);
            // todo need to replace 'parent' with 'target'
            options['$parent'] = (data && data.$parent) || option.$parent || $(options.target);
            console.log(options)

            if (!data) $this.data('modal-popover', (data = new ModalPopover(this, options)))

            if (typeof option == 'string') data[option]()
        })
    }

    $.fn.modalPopover.Constructor = ModalPopover

    $.fn.modalPopover.defaults = $.extend({}, $.fn.modal.defaults, {
        placement:'right',
        keyboard: true
    });

    $(function () {
        $('body').on('click.modal-popover.data-api', '[data-toggle="modal-popover"]', function (e) {
            var $this = $(this);
            var href = $this.attr('href');
            var $dialog = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))); //strip for ie7
            var option = $dialog.data('modal-popover') ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $dialog.data(), $this.data());
            option['$parent'] = $this;

            e.preventDefault();

            $dialog
                .modalPopover(option)
                .modalPopover('show')
                .one('hide', function () {
                    $this.focus()
                })
        })
    })

}(window.jQuery);
//<|endoftext|>


<commit_before>var http = require('http');

var enProceso = 0,
    hechas = 0,
    errores = 0,
    HOST_PROV = 'relay2',
    HOST_SRV = 'relay2',
    PORT = 3001,
    EXPIRATION_DELAY = 86400,
    PAYLOAD = new Array(1024).join('*');

http.globalAgent.maxSockets = 20000;

//pesadito(5000);
superProvision(20000);
//forever();

function forever() {
    'use strict';
    pesadito(300, forever);
}
function pesadito(num, cb) {
    'use strict';

    console.time('pesadito');

    for (var i = 0; i < num; i += 1) {
        doPop(String(i), 30, printStats);
    }

    function printStats() {
        console.log('en_proceso %d, hechas %d, errores %d', enProceso, hechas,
            errores);
        if (enProceso === 0) {
            console.timeEnd('pesadito');
            if (cb) {
                cb();
            }
        }
    }
}

function superProvision(num) {
    'use strict';
    var queue;

    var superProv = {};

    superProv.payload = new Array(1024).join('*');
    superProv.queue = [];

    for (var i = 0; i < num; i++) {
        queue = String(i);
        superProv.queue.push({id: "q0"});
    }
    superProv.priority = 'H';
    superProv.expirationDelay = EXPIRATION_DELAY;
    superProv.callback = null;

    console.time('superProvision');

    doSuperPush(superProv, function () {
        console.timeEnd('superProvision');
    });

}

function doPop(queue, timeout, cb) {
    'use strict';
    var options = { host: HOST_SRV, port: PORT, path: '/queue/' + queue + '/pop?timeout=' + timeout, method: 'POST'};

    postObj(options, null, cb);
}

function doPush(queue, message, cb) {
    'use strict';
    var options = { host: HOST_PROV, port: PORT, path: '/trans'};
    var trans = { 'callback': 'http://localhost:8888/',
        payload: PAYLOAD, priority: 'H',
        'queue': [
            {'id': queue}
        ], 'expirationDelay': EXPIRATION_DELAY };

    postObj(options, trans, cb);
}

function doSuperPush(superData, cb) {
    'use strict';
    var options = { host: HOST_PROV, port: PORT, path: '/trans'};

    postObj(options, superData, cb);
}

function postObj(options, content, cb) {
    'use strict';

    var data = '';
    options = options || {};
    options.host = options.host || 'relayA';
    options.method = options.method || 'POST';
    options.headers = options.headers || {};

    if (options.method === 'POST') {
        options.headers['content-type'] = 'application/json';
    }

    var req = http.request(options, function (res) {

        var o; //returned object from request
        //console.log('STATUS: ' + res.statusCode);
        //console.log('HEADERS: ' + JSON.stringify(res.headers));
        res.setEncoding('utf8');
        res.on('data', function (chunk) {
            data += chunk;
            //console.log('data ' + data);
        });
        res.on('end', function () {

            console.log('end ' + data);
            enProceso--;
            hechas++;
            cb();
        });
    });

    req.on('error', function (e) {
        console.log(e);
        errores++;
        enProceso--;
        cb();
    });

    if (content !== null && typeof content !== "undefined") {
        // write data to request body
        req.write(JSON.stringify(content));
    }
    req.end();

    enProceso++;
}

<commit_msg>little silly changes<commit_after>var http = require('http');

var enProceso = 0,
    hechas = 0,
    errores = 0,
    HOST_PROV = 'relay2',
    HOST_SRV = 'relay2',
    PORT = 3001,
    EXPIRATION_DELAY = 86400,
    PAYLOAD = new Array(1024).join('*');

http.globalAgent.maxSockets = 20000;

//pesadito(5000);
superProvision(50000);
//forever();

function forever() {
    'use strict';
    pesadito(300, forever);
}
function pesadito(num, cb) {
    'use strict';

    console.time('pesadito');

    for (var i = 0; i < num; i += 1) {
        doPop(String(i), 30, printStats);
    }

    function printStats() {
        console.log('en_proceso %d, hechas %d, errores %d', enProceso, hechas,
            errores);
        if (enProceso === 0) {
            console.timeEnd('pesadito');
            if (cb) {
                cb();
            }
        }
    }
}

function superProvision(num) {
    'use strict';
    var queue;

    var superProv = {};

    superProv.payload = new Array(1024).join('*');
    superProv.queue = [];

    for (var i = 0; i < num; i++) {
        queue = String(i);
        superProv.queue.push({id: "q0"});
    }
    superProv.priority = 'H';
    superProv.expirationDelay = EXPIRATION_DELAY;
    superProv.callback = null;

    console.time('superProvision');

    doSuperPush(superProv, function () {
        console.timeEnd('superProvision');
    });

}

function doPop(queue, timeout, cb) {
    'use strict';
    var options = { host: HOST_SRV, port: PORT, path: '/queue/' + queue + '/pop?timeout=' + timeout, method: 'POST'};

    postObj(options, null, cb);
}

function doPush(queue, message, cb) {
    'use strict';
    var options = { host: HOST_PROV, port: PORT, path: '/trans'};
    var trans = { 'callback': 'http://localhost:8888/',
        payload: PAYLOAD, priority: 'H',
        'queue': [
            {'id': queue}
        ], 'expirationDelay': EXPIRATION_DELAY };

    postObj(options, trans, cb);
}

function doSuperPush(superData, cb) {
    'use strict';
    var options = { host: HOST_PROV, port: PORT, path: '/trans'};

    postObj(options, superData, cb);
}

function postObj(options, content, cb) {
    'use strict';

    var data = '';
    options = options || {};
    options.host = options.host || 'relayA';
    options.method = options.method || 'POST';
    options.headers = options.headers || {};

    if (options.method === 'POST') {
        options.headers['content-type'] = 'application/json';
    }

    var req = http.request(options, function (res) {

        var o; //returned object from request
        //console.log('STATUS: ' + res.statusCode);
        //console.log('HEADERS: ' + JSON.stringify(res.headers));
        res.setEncoding('utf8');
        res.on('data', function (chunk) {
            data += chunk;
            //console.log('data ' + data);
        });
        res.on('end', function () {

            console.log('end ' + data);
            enProceso--;
            hechas++;
            cb();
        });
    });

    req.on('error', function (e) {
        console.log(e);
        errores++;
        enProceso--;
        cb();
    });

    if (content !== null && typeof content !== "undefined") {
        // write data to request body
        req.write(JSON.stringify(content));
    }
    req.end();

    enProceso++;
}

<|endoftext|>


<commit_before>import m from 'mithril';
import _ from 'underscore';
import postgrest from 'mithril-postgrest';
import models from '../models';
import h from '../h';
import projectDataTable from './project-data-table';
import projectDataChart from './project-data-chart';
import UserFollowBtn from './user-follow-btn';
import userVM from '../vms/user-vm';

const projectContributions = {
    controller(args) {
        const contributionsPerDay = m.prop([]),
            listVM = postgrest.paginationVM(models.contributor),
            filterStats = postgrest.filtersVM({
                project_id: 'eq'
            }),
            filterVM = postgrest.filtersVM({
                project_id: 'eq'
            }),
            groupedCollection = (collection = []) => {
                let grouped = [
                      []
                    ],
                    group = 0;

                _.map(collection, (item, index) => {
                    if (grouped[group].length >= 3) {
                        group += 1;
                        grouped[group] = [];
                    }

                    grouped[group].push(item);
                });

                return grouped;
            },
            contributionsStats = m.prop({});

        filterVM.project_id(args.project().project_id);
        filterStats.project_id(args.project().project_id);

        if (!listVM.collection().length) {
            listVM.firstPage(filterVM.parameters());
        }
        // TODO: Abstract table fetch and contruction logic to contributions-vm to avoid insights.js duplicated code.
        const lContributionsPerDay = postgrest.loader(models.projectContributionsPerDay.getRowOptions(filterStats.parameters()));
        lContributionsPerDay.load().then(contributionsPerDay);

        const contributionsPerLocationTable = [
            ['Estado', 'Apoios', 'R$ apoiados (% do total)']
        ];
        const buildPerLocationTable = contributions => (!_.isEmpty(contributions)) ? _.map(_.first(contributions).source, (contribution) => {
            const column = [];

            column.push(contribution.state_acronym || 'Outro/other');
            column.push(contribution.total_contributions);
            column.push([contribution.total_contributed, [// Adding row with custom comparator => read project-data-table description
                m(`input[type="hidden"][value="${contribution.total_contributed}"`),
                'R$ ',
                h.formatNumber(contribution.total_contributed, 2, 3),
                m('span.w-hidden-small.w-hidden-tiny', ` (${contribution.total_on_percentage.toFixed(2)}%)`)
            ]]);
            return contributionsPerLocationTable.push(column);
        }) : [];

        const lContributionsPerLocation = postgrest.loader(models.projectContributionsPerLocation.getRowOptions(filterStats.parameters()));
        lContributionsPerLocation.load().then(buildPerLocationTable);

        const lContributionsStats = postgrest.loader(models.projectContributiorsStat.getRowOptions(filterStats.parameters()));
        lContributionsStats.load().then(data => contributionsStats(_.first(data)));

        return {
            listVM,
            filterVM,
            groupedCollection,
            lContributionsStats,
            contributionsPerLocationTable,
            lContributionsPerLocation,
            contributionsPerDay,
            lContributionsPerDay,
            contributionsStats
        };
    },
    view(ctrl, args) {
        const list = ctrl.listVM,
            stats = ctrl.contributionsStats(),
            groupedCollection = ctrl.groupedCollection(list.collection());

        return m('#project_contributions', m('#contributions_top', [
            m('.section.w-section',
              m('.w-container',
                m('.w-row', ctrl.lContributionsStats() ? h.loader() : !_.isEmpty(stats) ? [
                    m('.u-marginbottom-20.u-text-center-small-only.w-col.w-col-6', [
                        m('.fontsize-megajumbo',
                          stats.total
                         ),
                        m('.fontsize-large',
                          'pessoas apoiam este projeto'
                         )
                    ]),
                    m('.w-col.w-col-6',
                      m('.card.card-terciary.u-radius',
                        m('.w-row', [
                            m('.u-marginbottom-20.w-col.w-col-6.w-col-small-6', [
                                m('.fontweight-semibold.u-marginbottom-10',
                                  'Apoiadores novos'
                                 ),
                                m('.fontsize-largest.u-marginbottom-10',
                                  `${Math.floor(stats.new_percent)}%`
                                 ),
                                m('.fontsize-smallest',
                                  'apoiadores que nunca tinham apoiado um projeto no Catarse'
                                 )
                            ]),
                            m('.w-col.w-col-6.w-col-small-6', [
                                m('.divider.u-marginbottom-20.w-hidden-main.w-hidden-medium.w-hidden-small'),
                                m('.fontweight-semibold.u-marginbottom-10',
                                  'Apoiadores recorrentes'
                                 ),
                                m('.fontsize-largest.u-marginbottom-10',
                                  `${Math.ceil(stats.returning_percent)}%`
                                 ),
                                m('.fontsize-smallest',
                                  'apoiadores que já tinham apoiado um projeto no Catarse'
                                 )
                            ])
                        ])
                       )
                     )
                ] : '')
               )
             ),
            m('.divider.w-section'),
            m('.section.w-section', m('.w-container', [
                m('.fontsize-large.fontweight-semibold.u-marginbottom-40.u-text-center', 'Apoiadores'),
                m('.project-contributions.w-clearfix', _.map(groupedCollection, (group, idx) => m('.w-row', _.map(group, contribution => m('.project-contribution-item.w-col.w-col-4', [
                        // here new card
                    m('.card.card-backer.u-marginbottom-20.u-radius.u-text-center', [
                        m(`a[href="/users/${contribution.user_id}"][style="display: block;"]`, {
                            onclick: h.analytics.event({
                                cat: 'project_view',
                                act: 'project_backer_link',
                                lbl: contribution.user_id,
                                project: args.project()
                            })
                        }, [
                            m(`img.thumb.u-marginbottom-10.u-round[src="${!_.isEmpty(contribution.data.profile_img_thumbnail) ? contribution.data.profile_img_thumbnail : '/assets/catarse_bootstrap/user.jpg'}"]`)
                        ]),
                        m(`a.fontsize-base.fontweight-semibold.lineheigh-tight.link-hidden-dark[href="/users/${contribution.user_id}"]`, {
                            onclick: h.analytics.event({
                                cat: 'project_view',
                                act: 'project_backer_link',
                                lbl: contribution.user_id,
                                project: args.project()
                            })
                        }, userVM.displayName(contribution.data)),
                        m('.fontcolor-secondary.fontsize-smallest.u-marginbottom-10', `${h.selfOrEmpty(contribution.data.city)}, ${h.selfOrEmpty(contribution.data.state)}`),
                        m('.fontsize-smaller', [
                            m('span.fontweight-semibold', contribution.data.total_contributed_projects), ' apoiados  |  ',
                            m('span.fontweight-semibold', contribution.data.total_published_projects), ' criado'
                        ]),
                        m('.btn-bottom-card.w-row', [
                            m('.w-col.w-col-3.w-col-small-4.w-col-tiny-3'),
                            m('.w-col.w-col-6.w-col-small-4.w-col-tiny-6', [
                                m(UserFollowBtn, { follow_id: contribution.user_id, following: contribution.is_follow })
                            ]),
                            m('.w-col.w-col-3.w-col-small-4.w-col-tiny-3')
                        ])
                    ])
                        // new card
                ]))))),
                m('.w-row.u-marginbottom-40.u-margintop-20', [
                    m('.w-col.w-col-2.w-col-push-5', [!list.isLoading() ?
                                                      list.isLastPage() ? '' : m('button#load-more.btn.btn-medium.btn-terciary', {
                                                          onclick: list.nextPage
                                                      }, 'Carregar mais') : h.loader(),
                    ])
                ])
            ]))
        ]),
                 m('.before-footer.bg-gray.section.w-section', m('.w-container', [
                     m('.w-row.u-marginbottom-60', [
                         m('.w-col.w-col-12.u-text-center', {
                             style: {
                                 'min-height': '300px'
                             }
                         }, [!ctrl.lContributionsPerDay() ? m.component(projectDataChart, {
                             collection: ctrl.contributionsPerDay,
                             label: 'R$ arrecadados por dia',
                             dataKey: 'total_amount',
                             xAxis: item => h.momentify(item.paid_at),
                             emptyState: 'Apoios não contabilizados'
                         }) : h.loader()]),
                     ]),
                     m('.w-row',
                       m('.w-col.w-col-12.u-text-center', [
                           m('.fontweight-semibold.u-marginbottom-10.fontsize-large.u-text-center', 'De onde vem os apoios'),
                           (!ctrl.lContributionsPerLocation() ? !_.isEmpty(_.rest(ctrl.contributionsPerLocationTable)) ? m.component(projectDataTable, {
                               table: ctrl.contributionsPerLocationTable,
                               defaultSortIndex: -2
                           }) : '' : h.loader())
                       ])
                      )
                 ])));
    }
};

export default projectContributions;
<commit_msg>fix contribution box style [#144340783]<commit_after>import m from 'mithril';
import _ from 'underscore';
import postgrest from 'mithril-postgrest';
import models from '../models';
import h from '../h';
import projectDataTable from './project-data-table';
import projectDataChart from './project-data-chart';
import UserFollowBtn from './user-follow-btn';
import userVM from '../vms/user-vm';

const projectContributions = {
    controller(args) {
        const contributionsPerDay = m.prop([]),
            listVM = postgrest.paginationVM(models.contributor),
            filterStats = postgrest.filtersVM({
                project_id: 'eq'
            }),
            filterVM = postgrest.filtersVM({
                project_id: 'eq'
            }),
            groupedCollection = (collection = []) => {
                let grouped = [
                      []
                    ],
                    group = 0;

                _.map(collection, (item, index) => {
                    if (grouped[group].length >= 3) {
                        group += 1;
                        grouped[group] = [];
                    }

                    grouped[group].push(item);
                });

                return grouped;
            },
            contributionsStats = m.prop({});

        filterVM.project_id(args.project().project_id);
        filterStats.project_id(args.project().project_id);

        if (!listVM.collection().length) {
            listVM.firstPage(filterVM.parameters());
        }
        // TODO: Abstract table fetch and contruction logic to contributions-vm to avoid insights.js duplicated code.
        const lContributionsPerDay = postgrest.loader(models.projectContributionsPerDay.getRowOptions(filterStats.parameters()));
        lContributionsPerDay.load().then(contributionsPerDay);

        const contributionsPerLocationTable = [
            ['Estado', 'Apoios', 'R$ apoiados (% do total)']
        ];
        const buildPerLocationTable = contributions => (!_.isEmpty(contributions)) ? _.map(_.first(contributions).source, (contribution) => {
            const column = [];

            column.push(contribution.state_acronym || 'Outro/other');
            column.push(contribution.total_contributions);
            column.push([contribution.total_contributed, [// Adding row with custom comparator => read project-data-table description
                m(`input[type="hidden"][value="${contribution.total_contributed}"`),
                'R$ ',
                h.formatNumber(contribution.total_contributed, 2, 3),
                m('span.w-hidden-small.w-hidden-tiny', ` (${contribution.total_on_percentage.toFixed(2)}%)`)
            ]]);
            return contributionsPerLocationTable.push(column);
        }) : [];

        const lContributionsPerLocation = postgrest.loader(models.projectContributionsPerLocation.getRowOptions(filterStats.parameters()));
        lContributionsPerLocation.load().then(buildPerLocationTable);

        const lContributionsStats = postgrest.loader(models.projectContributiorsStat.getRowOptions(filterStats.parameters()));
        lContributionsStats.load().then(data => contributionsStats(_.first(data)));

        return {
            listVM,
            filterVM,
            groupedCollection,
            lContributionsStats,
            contributionsPerLocationTable,
            lContributionsPerLocation,
            contributionsPerDay,
            lContributionsPerDay,
            contributionsStats
        };
    },
    view(ctrl, args) {
        const list = ctrl.listVM,
            stats = ctrl.contributionsStats(),
            groupedCollection = ctrl.groupedCollection(list.collection());

        return m('#project_contributions', m('#contributions_top', [
            m('.section.w-section',
              m('.w-container',
                m('.w-row', ctrl.lContributionsStats() ? h.loader() : !_.isEmpty(stats) ? [
                    m('.u-marginbottom-20.u-text-center-small-only.w-col.w-col-6', [
                        m('.fontsize-megajumbo',
                          stats.total
                         ),
                        m('.fontsize-large',
                          'pessoas apoiam este projeto'
                         )
                    ]),
                    m('.w-col.w-col-6',
                      m('.card.card-terciary.u-radius',
                        m('.w-row', [
                            m('.u-marginbottom-20.w-col.w-sub-col.w-col-6.w-col-small-6', [
                                m('.fontweight-semibold.u-marginbottom-10',
                                  'Apoiadores novos'
                                 ),
                                m('.fontsize-largest.u-marginbottom-10',
                                  `${Math.floor(stats.new_percent)}%`
                                 ),
                                m('.fontsize-smallest',
                                  'apoiadores que nunca tinham apoiado um projeto no Catarse'
                                 )
                            ]),
                            m('.w-col.w-sub-col.w-col-6.w-col-small-6', [
                                m('.divider.u-marginbottom-20.w-hidden-main.w-hidden-medium.w-hidden-small'),
                                m('.fontweight-semibold.u-marginbottom-10',
                                  'Apoiadores recorrentes'
                                 ),
                                m('.fontsize-largest.u-marginbottom-10',
                                  `${Math.ceil(stats.returning_percent)}%`
                                 ),
                                m('.fontsize-smallest',
                                  'apoiadores que já tinham apoiado um projeto no Catarse'
                                 )
                            ])
                        ])
                       )
                     )
                ] : '')
               )
             ),
            m('.divider.w-section'),
            m('.section.w-section', m('.w-container', [
                m('.fontsize-large.fontweight-semibold.u-marginbottom-40.u-text-center', 'Apoiadores'),
                m('.project-contributions.w-clearfix', _.map(groupedCollection, (group, idx) => m('.w-row', _.map(group, contribution => m('.project-contribution-item.w-col.w-col-4', [
                        // here new card
                    m('.card.card-backer.u-marginbottom-20.u-radius.u-text-center', [
                        m(`a[href="/users/${contribution.user_id}"][style="display: block;"]`, {
                            onclick: h.analytics.event({
                                cat: 'project_view',
                                act: 'project_backer_link',
                                lbl: contribution.user_id,
                                project: args.project()
                            })
                        }, [
                            m(`img.thumb.u-marginbottom-10.u-round[src="${!_.isEmpty(contribution.data.profile_img_thumbnail) ? contribution.data.profile_img_thumbnail : '/assets/catarse_bootstrap/user.jpg'}"]`)
                        ]),
                        m(`a.fontsize-base.fontweight-semibold.lineheigh-tight.link-hidden-dark[href="/users/${contribution.user_id}"]`, {
                            onclick: h.analytics.event({
                                cat: 'project_view',
                                act: 'project_backer_link',
                                lbl: contribution.user_id,
                                project: args.project()
                            })
                        }, userVM.displayName(contribution.data)),
                        m('.fontcolor-secondary.fontsize-smallest.u-marginbottom-10', `${h.selfOrEmpty(contribution.data.city)}, ${h.selfOrEmpty(contribution.data.state)}`),
                        m('.fontsize-smaller', [
                            m('span.fontweight-semibold', contribution.data.total_contributed_projects), ' apoiados  |  ',
                            m('span.fontweight-semibold', contribution.data.total_published_projects), ' criado'
                        ]),
                        m('.btn-bottom-card.w-row', [
                            m('.w-col.w-col-3.w-col-small-4.w-col-tiny-3'),
                            m('.w-col.w-col-6.w-col-small-4.w-col-tiny-6', [
                                m(UserFollowBtn, { follow_id: contribution.user_id, following: contribution.is_follow })
                            ]),
                            m('.w-col.w-col-3.w-col-small-4.w-col-tiny-3')
                        ])
                    ])
                        // new card
                ]))))),
                m('.w-row.u-marginbottom-40.u-margintop-20', [
                    m('.w-col.w-col-2.w-col-push-5', [!list.isLoading() ?
                                                      list.isLastPage() ? '' : m('button#load-more.btn.btn-medium.btn-terciary', {
                                                          onclick: list.nextPage
                                                      }, 'Carregar mais') : h.loader(),
                    ])
                ])
            ]))
        ]),
                 m('.before-footer.bg-gray.section.w-section', m('.w-container', [
                     m('.w-row.u-marginbottom-60', [
                         m('.w-col.w-col-12.u-text-center', {
                             style: {
                                 'min-height': '300px'
                             }
                         }, [!ctrl.lContributionsPerDay() ? m.component(projectDataChart, {
                             collection: ctrl.contributionsPerDay,
                             label: 'R$ arrecadados por dia',
                             dataKey: 'total_amount',
                             xAxis: item => h.momentify(item.paid_at),
                             emptyState: 'Apoios não contabilizados'
                         }) : h.loader()]),
                     ]),
                     m('.w-row',
                       m('.w-col.w-col-12.u-text-center', [
                           m('.fontweight-semibold.u-marginbottom-10.fontsize-large.u-text-center', 'De onde vem os apoios'),
                           (!ctrl.lContributionsPerLocation() ? !_.isEmpty(_.rest(ctrl.contributionsPerLocationTable)) ? m.component(projectDataTable, {
                               table: ctrl.contributionsPerLocationTable,
                               defaultSortIndex: -2
                           }) : '' : h.loader())
                       ])
                      )
                 ])));
    }
};

export default projectContributions;
<|endoftext|>


<commit_before>// Delay function execution, return promise for delayed function result

'use strict';

var apply    = Function.prototype.apply
  , callable = require('es5-ext/object/valid-callable')
  , deferred = require('../../deferred')

  , delayed;

delayed = function (fn, args, resolve, reject) {
	var value;
	try {
		value = apply.call(fn, this, args);
	} catch (e) {
		reject(e);
		return;
	}
	resolve(value);
};

module.exports = function (timeout) {
	var fn, result;
	fn = callable(this);
	result = function () {
		var def = deferred();
		setTimeout(delayed.bind(this, fn, arguments, def.resolve, def.reject),
			timeout);
		return def.promise;
	};
	result.returnsPromise = true;
	return result;
};
<commit_msg>Improve delay possibility span<commit_after>// Delay function execution, return promise for delayed function result

'use strict';

var callable      = require('es5-ext/object/valid-callable')
  , nextTick      = require('next-tick')
  , ensureTimeout = require('timers-ext/valid-timeout')
  , deferred      = require('../../deferred')

  , apply    = Function.prototype.apply
  , delayed;

delayed = function (fn, args, resolve, reject) {
	var value;
	try {
		value = apply.call(fn, this, args);
	} catch (e) {
		reject(e);
		return;
	}
	resolve(value);
};

module.exports = function (timeout) {
	var fn, result, delay;
	fn = callable(this);
	if (timeout == null) {
		delay = nextTick;
	} else {
		timeout = ensureTimeout(timeout);
		delay = setTimeout;
	}
	result = function () {
		var def = deferred();
		delay(delayed.bind(this, fn, arguments, def.resolve, def.reject), timeout);
		return def.promise;
	};
	result.returnsPromise = true;
	return result;
};
<|endoftext|>


<commit_before>let has_init = false

chrome.browserAction.onClicked.addListener(function (tab) {
  if (has_init) return

  chrome.tabs.insertCSS(tab.id, { file: 'toolbar/bundle.css' })

  chrome.tabs.executeScript(tab.id, { file: 'web-components.polyfill.js' })
  chrome.tabs.executeScript(tab.id, { file: 'toolbar/bundle.js' })
  chrome.tabs.executeScript(tab.id, { file: 'toolbar/inject.js' })

  has_init = true
})<commit_msg>fixes bug where can only be launched once<commit_after>let init_map = {}

chrome.browserAction.onClicked.addListener(function (tab) {
  if (init_map[tab.id]) return

  chrome.tabs.insertCSS(tab.id, { file: 'toolbar/bundle.css' })

  chrome.tabs.executeScript(tab.id, { file: 'web-components.polyfill.js' })
  chrome.tabs.executeScript(tab.id, { file: 'toolbar/bundle.js' })
  chrome.tabs.executeScript(tab.id, { file: 'toolbar/inject.js' })

  init_map[tab.id] = true
})<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';

import { Provider } from 'react-redux';

import { Actions } from './actions.js';

import { SearchIcons } from './dialogs/searchIcons/searchIcons.js';
import { SearchIconsConfiguration } from './dialogs/searchIcons/searchIconsConfiguration.js';

import { store } from './store.js';

const Main = function () {
    return (

            <Provider store={store}>
                <Actions />
                <SearchIcons />
                <SearchIconsConfiguration />
            </Provider>

    );
};

window.reactMain = function () {
    ReactDOM.render(
        ,
        document.getElementsByClassName('magicss-command-palette-root')[0]
    );
};

window.reactMain();
<commit_msg>Minor update to React 18 syntax<commit_after>import React from 'react';
import { createRoot } from 'react-dom/client';

import { Provider } from 'react-redux';

import { Actions } from './actions.js';

import { SearchIcons } from './dialogs/searchIcons/searchIcons.js';
import { SearchIconsConfiguration } from './dialogs/searchIcons/searchIconsConfiguration.js';

import { store } from './store.js';

const Main = function () {
    return (

            <Provider store={store}>
                <Actions />
                <SearchIcons />
                <SearchIconsConfiguration />
            </Provider>

    );
};

window.reactMain = function () {
    // https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html
    const container = document.getElementsByClassName('magicss-command-palette-root')[0];
    const root = createRoot(container); // createRoot(container!) if you use TypeScript

    root.render();
};

window.reactMain();
<|endoftext|>


<commit_before>const lazyImportsBlacklist = require('./lazy-imports-blacklist');

let hasWarnedJsxRename = false;

module.exports = function(api, options = {}) {
  const { web = {}, native = {} } = options;

  const bundler = api.caller(getBundler);
  const isWebpack = bundler === 'webpack';
  let platform = api.caller(getPlatform);

  // If the `platform` prop is not defined then this must be a custom config that isn't
  // defining a platform in the babel-loader. Currently this may happen with Next.js + Expo web.
  if (!platform && isWebpack) {
    platform = 'web';
  }

  const platformOptions =
    platform === 'web'
      ? { disableImportExportTransform: true, ...web }
      : { disableImportExportTransform: false, ...native };

  // Note that if `options.lazyImports` is not set (i.e., `null` or `undefined`),
  // `metro-react-native-babel-preset` will handle it.
  const lazyImportsOption = options && options.lazyImports;

  const extraPlugins = [];

  if ('useTransformReactJsxExperimental' in platformOptions && !hasWarnedJsxRename) {
    // https://github.com/expo/expo/pull/13945#pullrequestreview-724327024
    hasWarnedJsxRename = true;
    console.warn(
      'Warning: useTransformReactJsxExperimental has been renamed to useTransformReactJSXExperimental (capitalized JSX) in react-native@0.64.0'
    );
  }

  // Set true to disable `@babel/plugin-transform-react-jsx`
  // we override this logic outside of the metro preset so we can add support for
  // React 17 automatic JSX transformations.
  // If the logic for `useTransformReactJSXExperimental` ever changes in `metro-react-native-babel-preset`
  // then this block should be updated to reflect those changes.
  if (!platformOptions.useTransformReactJSXExperimental) {
    extraPlugins.push([
      require('@babel/plugin-transform-react-jsx'),
      {
        // Defaults to `classic`, pass in `automatic` for auto JSX transformations.
        runtime: options && options.jsxRuntime,
      },
    ]);
    // Purposefully not adding the deprecated packages:
    // `@babel/plugin-transform-react-jsx-self` and `@babel/plugin-transform-react-jsx-source`
    // back to the preset.
  }

  return {
    presets: [
      [
        // We use `require` here instead of directly using the package name because we want to
        // specifically use the `metro-react-native-babel-preset` installed by this package (ex:
        // `babel-preset-expo/node_modules/`). This way the preset will not change unintentionally.
        // Reference: https://github.com/expo/expo/pull/4685#discussion_r307143920
        require('metro-react-native-babel-preset'),
        {
          // Defaults to undefined, set to something truthy to disable `@babel/plugin-transform-react-jsx-self` and `@babel/plugin-transform-react-jsx-source`.
          withDevTools: platformOptions.withDevTools,
          // Defaults to undefined, set to `true` to disable `@babel/plugin-transform-flow-strip-types`
          disableFlowStripTypesTransform: platformOptions.disableFlowStripTypesTransform,
          // Defaults to undefined, set to `false` to disable `@babel/plugin-transform-runtime`
          enableBabelRuntime: platformOptions.enableBabelRuntime,
          // Defaults to `'default'`, can also use `'hermes-canary'`
          unstable_transformProfile: platformOptions.unstable_transformProfile,
          // Set true to disable `@babel/plugin-transform-react-jsx` and
          // the deprecated packages `@babel/plugin-transform-react-jsx-self`, and `@babel/plugin-transform-react-jsx-source`.
          //
          // Otherwise, you'll sometime get errors like the following (starting in Expo SDK 43, React Native 64, React 17):
          //
          // TransformError App.js: /path/to/App.js: Duplicate __self prop found. You are most likely using the deprecated transform-react-jsx-self Babel plugin.
          // Both __source and __self are automatically set when using the automatic jsxRuntime. Please remove transform-react-jsx-source and transform-react-jsx-self from your Babel config.
          useTransformReactJSXExperimental: true,

          disableImportExportTransform: platformOptions.disableImportExportTransform,
          lazyImportExportTransform:
            lazyImportsOption === true
              ? importModuleSpecifier => {
                  // Do not lazy-initialize packages that are local imports (similar to `lazy: true`
                  // behavior) or are in the blacklist.
                  return !(
                    importModuleSpecifier.includes('./') ||
                    lazyImportsBlacklist.has(importModuleSpecifier)
                  );
                }
              : // Pass the option directly to `metro-react-native-babel-preset`, which in turn
                // passes it to `babel-plugin-transform-modules-commonjs`
                lazyImportsOption,
        },
      ],
    ],
    plugins: [
      ...extraPlugins,
      getAliasPlugin(),
      [require.resolve('@babel/plugin-proposal-decorators'), { legacy: true }],
      platform === 'web' && [require.resolve('babel-plugin-react-native-web')],
      isWebpack && platform !== 'web' && [require.resolve('./plugins/disable-ambiguous-requires')],
    ].filter(Boolean),
  };
};

function getAliasPlugin() {
  const aliases = {};

  if (hasModule('@expo/vector-icons')) {
    aliases['react-native-vector-icons'] = '@expo/vector-icons';
  }

  if (Object.keys(aliases).length) {
    return [
      require.resolve('babel-plugin-module-resolver'),
      {
        alias: aliases,
      },
    ];
  }
  return null;
}

function hasModule(name) {
  try {
    return !!require.resolve(name);
  } catch (error) {
    if (error.code === 'MODULE_NOT_FOUND' && error.message.includes(name)) {
      return false;
    }
    throw error;
  }
}

function getPlatform(caller) {
  return caller && caller.platform;
}

/**
 * Get the name of the `bundler`.
 *
 * @param {*} caller
 */
function getBundler(caller) {
  if (!caller) return null;

  const { bundler, name } = caller;

  if (!bundler) {
    if (name === 'metro') {
      // This is a hack to determine if metro is being used.
      return 'metro';
    } else if (name === 'next-babel-turbo-loader') {
      // NextJS 11
      return 'webpack';
    } else if (name === 'babel-loader') {
      // expo/webpack-config, gatsby, storybook, and next.js <10
      return 'webpack';
    }
  }
  // Perhaps we should add a check to log once when an unexpected bundler is being used.
  return bundler || null;
}
<commit_msg>[babel-preset-expo] Overwrite the object rest spread plugin (#13984)<commit_after>const lazyImportsBlacklist = require('./lazy-imports-blacklist');

let hasWarnedJsxRename = false;

module.exports = function(api, options = {}) {
  const { web = {}, native = {} } = options;

  const bundler = api.caller(getBundler);
  const isWebpack = bundler === 'webpack';
  let platform = api.caller(getPlatform);

  // If the `platform` prop is not defined then this must be a custom config that isn't
  // defining a platform in the babel-loader. Currently this may happen with Next.js + Expo web.
  if (!platform && isWebpack) {
    platform = 'web';
  }

  const platformOptions =
    platform === 'web'
      ? { disableImportExportTransform: true, ...web }
      : { disableImportExportTransform: false, ...native };

  // Note that if `options.lazyImports` is not set (i.e., `null` or `undefined`),
  // `metro-react-native-babel-preset` will handle it.
  const lazyImportsOption = options && options.lazyImports;

  const extraPlugins = [];

  if ('useTransformReactJsxExperimental' in platformOptions && !hasWarnedJsxRename) {
    // https://github.com/expo/expo/pull/13945#pullrequestreview-724327024
    hasWarnedJsxRename = true;
    console.warn(
      'Warning: useTransformReactJsxExperimental has been renamed to useTransformReactJSXExperimental (capitalized JSX) in react-native@0.64.0'
    );
  }

  // Set true to disable `@babel/plugin-transform-react-jsx`
  // we override this logic outside of the metro preset so we can add support for
  // React 17 automatic JSX transformations.
  // If the logic for `useTransformReactJSXExperimental` ever changes in `metro-react-native-babel-preset`
  // then this block should be updated to reflect those changes.
  if (!platformOptions.useTransformReactJSXExperimental) {
    extraPlugins.push([
      require('@babel/plugin-transform-react-jsx'),
      {
        // Defaults to `classic`, pass in `automatic` for auto JSX transformations.
        runtime: options && options.jsxRuntime,
      },
    ]);
    // Purposefully not adding the deprecated packages:
    // `@babel/plugin-transform-react-jsx-self` and `@babel/plugin-transform-react-jsx-source`
    // back to the preset.
  }

  return {
    presets: [
      [
        // We use `require` here instead of directly using the package name because we want to
        // specifically use the `metro-react-native-babel-preset` installed by this package (ex:
        // `babel-preset-expo/node_modules/`). This way the preset will not change unintentionally.
        // Reference: https://github.com/expo/expo/pull/4685#discussion_r307143920
        require('metro-react-native-babel-preset'),
        {
          // Defaults to undefined, set to something truthy to disable `@babel/plugin-transform-react-jsx-self` and `@babel/plugin-transform-react-jsx-source`.
          withDevTools: platformOptions.withDevTools,
          // Defaults to undefined, set to `true` to disable `@babel/plugin-transform-flow-strip-types`
          disableFlowStripTypesTransform: platformOptions.disableFlowStripTypesTransform,
          // Defaults to undefined, set to `false` to disable `@babel/plugin-transform-runtime`
          enableBabelRuntime: platformOptions.enableBabelRuntime,
          // Defaults to `'default'`, can also use `'hermes-canary'`
          unstable_transformProfile: platformOptions.unstable_transformProfile,
          // Set true to disable `@babel/plugin-transform-react-jsx` and
          // the deprecated packages `@babel/plugin-transform-react-jsx-self`, and `@babel/plugin-transform-react-jsx-source`.
          //
          // Otherwise, you'll sometime get errors like the following (starting in Expo SDK 43, React Native 64, React 17):
          //
          // TransformError App.js: /path/to/App.js: Duplicate __self prop found. You are most likely using the deprecated transform-react-jsx-self Babel plugin.
          // Both __source and __self are automatically set when using the automatic jsxRuntime. Please remove transform-react-jsx-source and transform-react-jsx-self from your Babel config.
          useTransformReactJSXExperimental: true,

          disableImportExportTransform: platformOptions.disableImportExportTransform,
          lazyImportExportTransform:
            lazyImportsOption === true
              ? importModuleSpecifier => {
                  // Do not lazy-initialize packages that are local imports (similar to `lazy: true`
                  // behavior) or are in the blacklist.
                  return !(
                    importModuleSpecifier.includes('./') ||
                    lazyImportsBlacklist.has(importModuleSpecifier)
                  );
                }
              : // Pass the option directly to `metro-react-native-babel-preset`, which in turn
                // passes it to `babel-plugin-transform-modules-commonjs`
                lazyImportsOption,
        },
      ],
    ],
    plugins: [
      getObjectRestSpreadPlugin(),
      ...extraPlugins,
      getAliasPlugin(),
      [require.resolve('@babel/plugin-proposal-decorators'), { legacy: true }],
      platform === 'web' && [require.resolve('babel-plugin-react-native-web')],
      isWebpack && platform !== 'web' && [require.resolve('./plugins/disable-ambiguous-requires')],
    ].filter(Boolean),
  };
};

function getAliasPlugin() {
  const aliases = {};

  if (hasModule('@expo/vector-icons')) {
    aliases['react-native-vector-icons'] = '@expo/vector-icons';
  }

  if (Object.keys(aliases).length) {
    return [
      require.resolve('babel-plugin-module-resolver'),
      {
        alias: aliases,
      },
    ];
  }
  return null;
}

/**
 * metro-react-native-babel-preset configures this plugin with `{ loose: true }`, which breaks all
 * getters and setters in spread objects. We need to add this plugin ourself without that option.
 * @see https://github.com/expo/expo/pull/11960#issuecomment-887796455
 */
function getObjectRestSpreadPlugin() {
  return [require.resolve('@babel/plugin-proposal-object-rest-spread'), { loose: false }];
}

function hasModule(name) {
  try {
    return !!require.resolve(name);
  } catch (error) {
    if (error.code === 'MODULE_NOT_FOUND' && error.message.includes(name)) {
      return false;
    }
    throw error;
  }
}

function getPlatform(caller) {
  return caller && caller.platform;
}

/**
 * Get the name of the `bundler`.
 *
 * @param {*} caller
 */
function getBundler(caller) {
  if (!caller) return null;

  const { bundler, name } = caller;

  if (!bundler) {
    if (name === 'metro') {
      // This is a hack to determine if metro is being used.
      return 'metro';
    } else if (name === 'next-babel-turbo-loader') {
      // NextJS 11
      return 'webpack';
    } else if (name === 'babel-loader') {
      // expo/webpack-config, gatsby, storybook, and next.js <10
      return 'webpack';
    }
  }
  // Perhaps we should add a check to log once when an unexpected bundler is being used.
  return bundler || null;
}
<|endoftext|>


<commit_before>import { string, arr } from "lively.lang";
import { lessPosition, lessEqPosition, eqPosition, maxPosition, minPosition } from "./position.js";
import { Range } from "./range.js";
import { StyleRange } from "./style.js";

const newline = "\n",
      newlineLength = newline.length;

export default class TextDocument {

  static fromString(string) {
    var doc = new TextDocument();
    doc.textString = string;
    return doc;
  }

  static get newline() { return newline; }
  static get newlineLength() { return newlineLength; }
  static parseIntoLines(text) { return text.split(this.newline); }

  constructor(lines = [], styleRanges = []) {
    this.lines = lines;
    this._styleRanges = [];
    this._styleRangesByLine = [];
    styleRanges.map(range => this.addStyleRange(range));
  }

  get textString() { return this.lines.join(TextDocument.newline); }
  set textString(string) { this.lines = TextDocument.parseIntoLines(string); }
  get stringLength() { return this.textString.length; }

  get endPosition() {
    var lines = this.lines, length = lines.length;
    return length ? {
      row: lines.length-1,
      column: lines[lines.length-1].length
    } : {row: 0, column: 0}
  }

  get styleRanges() { return this._styleRanges }

  // NOTE: assumes provided styleRanges are non-overlapping
  set styleRanges(styleRanges) {
    this._styleRanges = styleRanges;
    this._styleRangesByLine = this.lines.map(ea => []);
    styleRanges.forEach(({style, start, end}) => {
      for (let row = start.row; row <= end.row; row++) {
        let text = this.lines[row],
            startCol = row === start.row ? start.column : 0,
            endCol = row === end.row ? end.column : text.length,
            styleRange = StyleRange.fromPositions(style, {row, column: startCol}, {row, column: endCol});
        this._styleRangesByLine[row].push(styleRange);
      }
    });
  }

  addStyleRange(range) {
    this._styleRanges = StyleRange.mergeInto(this._styleRanges, range);
    for (let row = range.start.row; row <= range.end.row; row++) {
      this.updateLineStyleRanges(row);
    }
    // TODO: Consolidate/deduplicate ranges
  }

  clearStyleRanges() { this._styleRanges = []; }

  updateLineStyleRanges(row) {
    let { styleRanges } = this,
        text = this.getLine(row),
        start = { row, column: 0 },
        end = { row, column: text ? text.length : 0 },
        lineRange = Range.fromPositions(start, end),
        lineStyleRanges = [];
    styleRanges.forEach(ea => {
      let { style, range } = ea,
          intersection = lineRange.intersect(range);
      if (intersection.start.row === lineRange.start.row)
        lineStyleRanges.push(new StyleRange(style, intersection));
    });
    this._styleRangesByLine[row] = Range.sort(lineStyleRanges);
  }

  get styleRangesByLine() { return this._styleRangesByLine; }

  getLine(row) {
    var safeRow = Math.min(Math.max(0, row), this.lines.length-1);
    return this.lines[safeRow];
  }

  positionToIndex(pos, startRow = 0) {
    let {row, column} = this.clipPositionToLines(pos),
        index = 0,
        lines = this.lines,
        maxLength = lines.length-1;
    for (var i = startRow; i < row; i++)
      index += lines[i].length + (i === maxLength ? 0 : TextDocument.newlineLength);
    return index + column;
  }

  indexToPosition(index, startRow = 0) {
    // TextDocument.fromString("hello\nworld").indexToPosition(8)
    if (index < 0) index = 0;
    var lines = this.lines;
    if (lines.length === 0) return {row: 0, column: 0};
    for (var i = startRow, l = lines.length; i < l; i++) {
      index -= lines[i].length + TextDocument.newlineLength;
      if (index < 0)
        return {row: i, column: index + lines[i].length + TextDocument.newlineLength};
    }
    return {row: l-1, column: lines[l-1].length};
  }

  clipPositionToLines({row, column}) {
    let lines = this.lines,
        nLines = lines.length;

    if (nLines === 0) return {row: 0, column: 0};

    if (row < 0) row = 0;
    else if (row >= nLines) row = nLines-1;

    if (column < 0) column = 0;
    else if (column > lines[row].length) column = lines[row].length;

    return {row, column}
  }

  textInRange({start, end}) {
    start = this.clipPositionToLines(start);
    end = this.clipPositionToLines(end);
    if (lessPosition(end, start)) [start, end] = [end, start];

    let {row, column} = start,
        {row: endRow, column: endColumn} = end,
        lines = this.lines;

    if (row === endRow)
      return column === endColumn ?
        "" : lines[row].slice(column, endColumn);

    let result = lines[row].slice(column);
    for (let i = row+1; i < endRow; i++)
      result += TextDocument.newline + lines[i];
    return result + TextDocument.newline + lines[endRow].slice(0, endColumn);
  }

  setTextInRange(string, range) {
    var {start, end} = range;
    this.remove(range);
    return this.insert(string, start);
  }

  insert(string, pos) {
    let {lines, styleRanges} = this,
        {row, column} = pos,
        line = lines[row],
        insertionLines = TextDocument.parseIntoLines(string);

    if (!line) line = lines[row] = "";

    if (column > line.length)
        line += " ".repeat(column - line.length);

    let end = {row, column},
        before = line.slice(0, column),
        after = line.slice(column),
        firstLine = insertionLines.shift() || "";

    end.column += firstLine.length;
    lines[row] = before + firstLine;

    for (var i = 0; i < insertionLines.length; i++) {
      end.row++;
      end.column = insertionLines[i].length;
      lines.splice(row+1+i, 0, insertionLines[i]);
      this._styleRangesByLine.splice(row+1+i, 0, []);
    }

    lines[row + insertionLines.length] = lines[row + insertionLines.length] + after;

    let insertionRange = {start: pos, end};
    styleRanges.forEach(ea => ea.onInsert(insertionRange));
    for (let row = pos.row; row <= end.row; row++) {
      this.updateLineStyleRanges(row);
    }
    return insertionRange;
  }

  remove({start, end}) {
    var {lines, styleRanges} = this;
    if (!lines.length) return;

    if (lessPosition(end, start)) [start, end] = [end, start];

    let {row: fromRow, column: fromCol} = maxPosition(start, {column: 0, row: 0}),
        {row: toRow, column: toCol} = minPosition(end, this.endPosition);

    if (fromCol < 0) fromCol = 0;
    if (toCol < 0) toCol = 0;

    lines[fromRow] = lines[fromRow].slice(0, fromCol) + lines[toRow].slice(toCol);
    lines.splice(fromRow+1, toRow - fromRow);
    this._styleRangesByLine.splice(fromRow+1, toRow - fromRow);

    styleRanges.forEach(ea => ea.onDelete({start, end}));
    this._styleRanges = styleRanges.filter(ea => !ea.isEmpty());
    this.updateLineStyleRanges(fromRow);
  }

  wordsOfLine(row) {
    var line = this.lines[row] || "",
        words = [], word,
        isWordDelimiter = char => /[^a-z0-9_]/i.test(char);

    for (var i = 0; i < line.length; i++) {
      if (isWordDelimiter(line[i])) {
        if (word) {
          word.range.end.column = i;
          words.push(word);
          word = null;
        }
      } else {
        word = (word || {index: words.length, string: "", range: {start: {row, column: i}, end: {row, column: i}}});
        word.string += line[i];
      }
    }
    if (word) { word.range.end.column = i; words.push(word); }
    return words;
  }

  wordAt({row, column}, words = this.wordsOfLine(row)) {
    return words.find(ea => {
      var {range: {start: {column: startCol}, end: {column: endCol}}} = ea;
      return startCol <= column && column <= endCol;
    }) || {range: {start: {column, row}, end: {column, row}}, string: ""};
  }

  wordLeft(pos) {
    var {row, column} = pos,
        words = this.wordsOfLine(row);

    // nothing on this line, find previous word of a line above
    if (!words.length || lessEqPosition(pos, words[0].range.start)) {
      while (--row >= 0) {
        words = this.wordsOfLine(row);
        if (words.length) return arr.last(words);
      }
      return {range: {start: pos, end: pos}, string: ""};
    }

    var word = this.wordAt(pos);
    // if there is a word at pos and pos = beginning of word we return the word
    // to the left, otherwise word
    if (word.string)
      return eqPosition(word.range.start, pos) ? words[word.index-1] : word;

    // no word at pos, find the next left word next to pos
    return words.slice().reverse().find(word => word.range.end.column <= column) || {range: {start: pos, end: pos}, string: ""};
  }

  wordRight(pos) {
    var {column, row} = pos,
        words = this.wordsOfLine(pos.row);
    if (!words.length || lessEqPosition(arr.last(words).range.end, pos)) {
      while (++row < this.lines.length) {
        words = this.wordsOfLine(row);
        if (words.length) return words[0];
      }
      return {range: {start: pos, end: pos}, string: ""};
    }
    var word = this.wordAt(pos);
    if (word.string) {
      return eqPosition(word.range.end, pos) ? words[word.index+1] : word;
    }
    return words.find(word => word.range.start.column >= column) || {range: {start: pos, end: pos}, string: ""};
  }

  scanForward(startPos, matchFn) {
    var {
          endPosition: {row: endRow, column: endColumn},
          lines
        } = this,
        {row, column} = startPos

    // first line
    for (let col = column, line = lines[row]; col < line.length; col++) {
      let char = line[col], pos = {row, column: col},
          result = matchFn(char, pos);
      if (result) return result;
    }

    // the rest
    for (let r = row+1; r < lines.length; r++) {
      let line = lines[r];
      for (let col = 0; col < line.length; col++) {
        let char = line[col], pos = {row: r, column: col},
            result = matchFn(char, pos);
        if (result) return result;
      }
    }

    return null;
  }

  scanBackward(startPos, matchFn) {
    var lines = this.lines,
        {row, column} = startPos

    // first line
    for (let col = column-1, line = lines[row]; col >= 0; col--) {
      let char = line[col], pos = {row, column: col},
          result = matchFn(char, pos);
      if (result) return result;
    }

    // the rest
    for (let r = row-1; r >= 0; r--) {
      let line = lines[r];
      for (let col = line.length-1; col >= 0; col--) {
        let char = line[col], pos = {row: r, column: col},
            result = matchFn(char, pos);
        if (result) return result;
      }
    }

    return null;
  }

  copy() { return new TextDocument(this.lines.slice()); }

  toString() { return `TextDocument(${string.truncate(this.textString, 60)})`; }
}
<commit_msg>text: fix styleRanges initialization<commit_after>import { string, arr } from "lively.lang";
import { lessPosition, lessEqPosition, eqPosition, maxPosition, minPosition } from "./position.js";
import { Range } from "./range.js";
import { StyleRange } from "./style.js";

const newline = "\n",
      newlineLength = newline.length;

export default class TextDocument {

  static fromString(string) {
    var doc = new TextDocument();
    doc.textString = string;
    return doc;
  }

  static get newline() { return newline; }
  static get newlineLength() { return newlineLength; }
  static parseIntoLines(text) { return text.split(this.newline); }

  constructor(lines = [], styleRanges = []) {
    this.lines = lines;
    this._styleRanges = [];
    this._styleRangesByLine = [];
    styleRanges.map(range => this.addStyleRange(range));
  }

  get textString() { return this.lines.join(TextDocument.newline); }
  set textString(string) { this.lines = TextDocument.parseIntoLines(string); }
  get stringLength() { return this.textString.length; }

  get endPosition() {
    var lines = this.lines, length = lines.length;
    return length ? {
      row: lines.length-1,
      column: lines[lines.length-1].length
    } : {row: 0, column: 0}
  }

  get styleRanges() { return this._styleRanges }

  // NOTE: assumes provided styleRanges are non-overlapping
  set styleRanges(styleRanges) {
    this._styleRanges = styleRanges;
    this._styleRangesByLine = this.lines.map(ea => []);
    styleRanges.forEach(({style, start, end}) => {
      for (let row = start.row; row <= end.row; row++) {
        let text = this.lines[row],
            startCol = row === start.row ? start.column : 0,
            endCol = row === end.row ? end.column : text.length,
            styleRange = StyleRange.fromPositions(style, {row, column: startCol}, {row, column: endCol});
        if (!this._styleRangesByLine[row]) this._styleRangesByLine[row] = [];
        this._styleRangesByLine[row].push(styleRange);
      }
    });
  }

  addStyleRange(range) {
    this._styleRanges = StyleRange.mergeInto(this._styleRanges, range);
    for (let row = range.start.row; row <= range.end.row; row++) {
      this.updateLineStyleRanges(row);
    }
    // TODO: Consolidate/deduplicate ranges
  }

  clearStyleRanges() { this._styleRanges = []; }

  updateLineStyleRanges(row) {
    let { styleRanges } = this,
        text = this.getLine(row),
        start = { row, column: 0 },
        end = { row, column: text ? text.length : 0 },
        lineRange = Range.fromPositions(start, end),
        lineStyleRanges = [];
    styleRanges.forEach(ea => {
      let { style, range } = ea,
          intersection = lineRange.intersect(range);
      if (intersection.start.row === lineRange.start.row)
        lineStyleRanges.push(new StyleRange(style, intersection));
    });
    this._styleRangesByLine[row] = Range.sort(lineStyleRanges);
  }

  get styleRangesByLine() { return this._styleRangesByLine; }

  getLine(row) {
    var safeRow = Math.min(Math.max(0, row), this.lines.length-1);
    return this.lines[safeRow];
  }

  positionToIndex(pos, startRow = 0) {
    let {row, column} = this.clipPositionToLines(pos),
        index = 0,
        lines = this.lines,
        maxLength = lines.length-1;
    for (var i = startRow; i < row; i++)
      index += lines[i].length + (i === maxLength ? 0 : TextDocument.newlineLength);
    return index + column;
  }

  indexToPosition(index, startRow = 0) {
    // TextDocument.fromString("hello\nworld").indexToPosition(8)
    if (index < 0) index = 0;
    var lines = this.lines;
    if (lines.length === 0) return {row: 0, column: 0};
    for (var i = startRow, l = lines.length; i < l; i++) {
      index -= lines[i].length + TextDocument.newlineLength;
      if (index < 0)
        return {row: i, column: index + lines[i].length + TextDocument.newlineLength};
    }
    return {row: l-1, column: lines[l-1].length};
  }

  clipPositionToLines({row, column}) {
    let lines = this.lines,
        nLines = lines.length;

    if (nLines === 0) return {row: 0, column: 0};

    if (row < 0) row = 0;
    else if (row >= nLines) row = nLines-1;

    if (column < 0) column = 0;
    else if (column > lines[row].length) column = lines[row].length;

    return {row, column}
  }

  textInRange({start, end}) {
    start = this.clipPositionToLines(start);
    end = this.clipPositionToLines(end);
    if (lessPosition(end, start)) [start, end] = [end, start];

    let {row, column} = start,
        {row: endRow, column: endColumn} = end,
        lines = this.lines;

    if (row === endRow)
      return column === endColumn ?
        "" : lines[row].slice(column, endColumn);

    let result = lines[row].slice(column);
    for (let i = row+1; i < endRow; i++)
      result += TextDocument.newline + lines[i];
    return result + TextDocument.newline + lines[endRow].slice(0, endColumn);
  }

  setTextInRange(string, range) {
    var {start, end} = range;
    this.remove(range);
    return this.insert(string, start);
  }

  insert(string, pos) {
    let {lines, styleRanges} = this,
        {row, column} = pos,
        line = lines[row],
        insertionLines = TextDocument.parseIntoLines(string);

    if (!line) line = lines[row] = "";

    if (column > line.length)
        line += " ".repeat(column - line.length);

    let end = {row, column},
        before = line.slice(0, column),
        after = line.slice(column),
        firstLine = insertionLines.shift() || "";

    end.column += firstLine.length;
    lines[row] = before + firstLine;

    for (var i = 0; i < insertionLines.length; i++) {
      end.row++;
      end.column = insertionLines[i].length;
      lines.splice(row+1+i, 0, insertionLines[i]);
      this._styleRangesByLine.splice(row+1+i, 0, []);
    }

    lines[row + insertionLines.length] = lines[row + insertionLines.length] + after;

    let insertionRange = {start: pos, end};
    styleRanges.forEach(ea => ea.onInsert(insertionRange));
    for (let row = pos.row; row <= end.row; row++) {
      this.updateLineStyleRanges(row);
    }
    return insertionRange;
  }

  remove({start, end}) {
    var {lines, styleRanges} = this;
    if (!lines.length) return;

    if (lessPosition(end, start)) [start, end] = [end, start];

    let {row: fromRow, column: fromCol} = maxPosition(start, {column: 0, row: 0}),
        {row: toRow, column: toCol} = minPosition(end, this.endPosition);

    if (fromCol < 0) fromCol = 0;
    if (toCol < 0) toCol = 0;

    lines[fromRow] = lines[fromRow].slice(0, fromCol) + lines[toRow].slice(toCol);
    lines.splice(fromRow+1, toRow - fromRow);
    this._styleRangesByLine.splice(fromRow+1, toRow - fromRow);

    styleRanges.forEach(ea => ea.onDelete({start, end}));
    this._styleRanges = styleRanges.filter(ea => !ea.isEmpty());
    this.updateLineStyleRanges(fromRow);
  }

  wordsOfLine(row) {
    var line = this.lines[row] || "",
        words = [], word,
        isWordDelimiter = char => /[^a-z0-9_]/i.test(char);

    for (var i = 0; i < line.length; i++) {
      if (isWordDelimiter(line[i])) {
        if (word) {
          word.range.end.column = i;
          words.push(word);
          word = null;
        }
      } else {
        word = (word || {index: words.length, string: "", range: {start: {row, column: i}, end: {row, column: i}}});
        word.string += line[i];
      }
    }
    if (word) { word.range.end.column = i; words.push(word); }
    return words;
  }

  wordAt({row, column}, words = this.wordsOfLine(row)) {
    return words.find(ea => {
      var {range: {start: {column: startCol}, end: {column: endCol}}} = ea;
      return startCol <= column && column <= endCol;
    }) || {range: {start: {column, row}, end: {column, row}}, string: ""};
  }

  wordLeft(pos) {
    var {row, column} = pos,
        words = this.wordsOfLine(row);

    // nothing on this line, find previous word of a line above
    if (!words.length || lessEqPosition(pos, words[0].range.start)) {
      while (--row >= 0) {
        words = this.wordsOfLine(row);
        if (words.length) return arr.last(words);
      }
      return {range: {start: pos, end: pos}, string: ""};
    }

    var word = this.wordAt(pos);
    // if there is a word at pos and pos = beginning of word we return the word
    // to the left, otherwise word
    if (word.string)
      return eqPosition(word.range.start, pos) ? words[word.index-1] : word;

    // no word at pos, find the next left word next to pos
    return words.slice().reverse().find(word => word.range.end.column <= column) || {range: {start: pos, end: pos}, string: ""};
  }

  wordRight(pos) {
    var {column, row} = pos,
        words = this.wordsOfLine(pos.row);
    if (!words.length || lessEqPosition(arr.last(words).range.end, pos)) {
      while (++row < this.lines.length) {
        words = this.wordsOfLine(row);
        if (words.length) return words[0];
      }
      return {range: {start: pos, end: pos}, string: ""};
    }
    var word = this.wordAt(pos);
    if (word.string) {
      return eqPosition(word.range.end, pos) ? words[word.index+1] : word;
    }
    return words.find(word => word.range.start.column >= column) || {range: {start: pos, end: pos}, string: ""};
  }

  scanForward(startPos, matchFn) {
    var {
          endPosition: {row: endRow, column: endColumn},
          lines
        } = this,
        {row, column} = startPos

    // first line
    for (let col = column, line = lines[row]; col < line.length; col++) {
      let char = line[col], pos = {row, column: col},
          result = matchFn(char, pos);
      if (result) return result;
    }

    // the rest
    for (let r = row+1; r < lines.length; r++) {
      let line = lines[r];
      for (let col = 0; col < line.length; col++) {
        let char = line[col], pos = {row: r, column: col},
            result = matchFn(char, pos);
        if (result) return result;
      }
    }

    return null;
  }

  scanBackward(startPos, matchFn) {
    var lines = this.lines,
        {row, column} = startPos

    // first line
    for (let col = column-1, line = lines[row]; col >= 0; col--) {
      let char = line[col], pos = {row, column: col},
          result = matchFn(char, pos);
      if (result) return result;
    }

    // the rest
    for (let r = row-1; r >= 0; r--) {
      let line = lines[r];
      for (let col = line.length-1; col >= 0; col--) {
        let char = line[col], pos = {row: r, column: col},
            result = matchFn(char, pos);
        if (result) return result;
      }
    }

    return null;
  }

  copy() { return new TextDocument(this.lines.slice()); }

  toString() { return `TextDocument(${string.truncate(this.textString, 60)})`; }
}
<|endoftext|>


<commit_before>var os = require('os');
var path = require('path');
var mout = require('mout');
var rc = require('./util/rc');
var paths = require('./util/paths');

// Guess proxy defined in the env
/*jshint camelcase: false*/
var proxy = process.env.HTTP_PROXY
    || process.env.http_proxy
    || null;

var httpsProxy = process.env.HTTPS_PROXY
    || process.env.https_proxy
    || process.env.HTTP_PROXY
    || process.env.http_proxy
    || null;
/*jshint camelcase: true*/

//-------------

function Config(cwd) {
    this._cwd = cwd || process.cwd();
    this._config = {};
}

Config.prototype.load = function () {
    var runtimeConfig;

    runtimeConfig = rc('bower', {
        'cwd': this._cwd,
        'directory': 'bower_components',
        'registry': 'https://bower.herokuapp.com',
        'shorthand-resolver': 'git://github.com/{{owner}}/{{package}}.git',
        'tmp': os.tmpdir ? os.tmpdir() : os.tmpDir(),
        'proxy': proxy,
        'https-proxy': httpsProxy,
        'timeout': 60000,
        'ca': null,
        'strict-ssl': true,
        'user-agent': 'node/' + process.version + ' ' + process.platform + ' ' + process.arch,
        'git': 'git',
        'color': true,
        'interactive': false,
        'storage': {
            packages: path.join(paths.cache, 'packages'),
            links: path.join(paths.data, 'links'),
            completion: path.join(paths.data, 'completion'),
            registry: path.join(paths.cache, 'registry'),
            git: path.join(paths.data, 'git')
        }
    }, this._cwd);

    // Some backwards compatible things..
    runtimeConfig['shorthand-resolver'] = runtimeConfig['shorthand-resolver']
    .replace(/\{\{\{/g, '{{')
    .replace(/\}\}\}/g, '}}');

    // Generate config based on the rc, making every key camelCase
    this._config = {};
    mout.object.forOwn(runtimeConfig, function (value, key) {
        key = key.replace(/_/g, '-');
        this._config[mout.string.camelCase(key)] = value;
    }, this);

    return this;
};

Config.prototype.get = function (key) {
    // TODO
};

Config.prototype.set = function (key, value) {
    // TODO
    return this;
};

Config.prototype.del = function (key, value) {
    // TODO
    return this;
};

Config.prototype.save = function (where, callback) {
    // TODO
};

Config.prototype.toObject = function () {
    return mout.lang.deepClone(this._config);
};

Config.create = function (cwd) {
    return new Config(cwd);
};

Config.read = function (cwd) {
    var config = new Config(cwd);
    return config.load().toObject();
};

module.exports = Config;
<commit_msg>Remove git config.<commit_after>var os = require('os');
var path = require('path');
var mout = require('mout');
var rc = require('./util/rc');
var paths = require('./util/paths');

// Guess proxy defined in the env
/*jshint camelcase: false*/
var proxy = process.env.HTTP_PROXY
    || process.env.http_proxy
    || null;

var httpsProxy = process.env.HTTPS_PROXY
    || process.env.https_proxy
    || process.env.HTTP_PROXY
    || process.env.http_proxy
    || null;
/*jshint camelcase: true*/

//-------------

function Config(cwd) {
    this._cwd = cwd || process.cwd();
    this._config = {};
}

Config.prototype.load = function () {
    var runtimeConfig;

    runtimeConfig = rc('bower', {
        'cwd': this._cwd,
        'directory': 'bower_components',
        'registry': 'https://bower.herokuapp.com',
        'shorthand-resolver': 'git://github.com/{{owner}}/{{package}}.git',
        'tmp': os.tmpdir ? os.tmpdir() : os.tmpDir(),
        'proxy': proxy,
        'https-proxy': httpsProxy,
        'timeout': 60000,
        'ca': null,
        'strict-ssl': true,
        'user-agent': 'node/' + process.version + ' ' + process.platform + ' ' + process.arch,
        'color': true,
        'interactive': false,
        'storage': {
            packages: path.join(paths.cache, 'packages'),
            links: path.join(paths.data, 'links'),
            completion: path.join(paths.data, 'completion'),
            registry: path.join(paths.cache, 'registry'),
            git: path.join(paths.data, 'git')
        }
    }, this._cwd);

    // Some backwards compatible things..
    runtimeConfig['shorthand-resolver'] = runtimeConfig['shorthand-resolver']
    .replace(/\{\{\{/g, '{{')
    .replace(/\}\}\}/g, '}}');

    // Generate config based on the rc, making every key camelCase
    this._config = {};
    mout.object.forOwn(runtimeConfig, function (value, key) {
        key = key.replace(/_/g, '-');
        this._config[mout.string.camelCase(key)] = value;
    }, this);

    return this;
};

Config.prototype.get = function (key) {
    // TODO
};

Config.prototype.set = function (key, value) {
    // TODO
    return this;
};

Config.prototype.del = function (key, value) {
    // TODO
    return this;
};

Config.prototype.save = function (where, callback) {
    // TODO
};

Config.prototype.toObject = function () {
    return mout.lang.deepClone(this._config);
};

Config.create = function (cwd) {
    return new Config(cwd);
};

Config.read = function (cwd) {
    var config = new Config(cwd);
    return config.load().toObject();
};

module.exports = Config;
<|endoftext|>