<commit_before>var Tokenizer = require("./Tokenizer.js");

/*
	Options:

	xmlMode: Disables the special behavior for script/style tags (false by default)
	lowerCaseAttributeNames: call .toLowerCase for each attribute name (true if xmlMode is `false`)
	lowerCaseTags: call .toLowerCase for each tag name (true if xmlMode is `false`)
*/

/*
	Callbacks:

	oncdataend,
	oncdatastart,
	onclosetag,
	oncomment,
	oncommentend,
	onerror,
	onopentag,
	onprocessinginstruction,
	onreset,
	ontext
*/

var formTags = {
	input: true,
	option: true,
	optgroup: true,
	select: true,
	button: true,
	datalist: true,
	textarea: true
};

var openImpliesClose = {
	tr      : { tr:true, th:true, td:true },
	th      : { th:true },
	td      : { thead:true, th:true, td:true },
	body    : { head:true, link:true, script:true },
	li      : { li:true },
	p       : { p:true },
	h1      : { p:true },
	h2      : { p:true },
	h3      : { p:true },
	h4      : { p:true },
	h5      : { p:true },
	h6      : { p:true },
	select  : formTags,
	input   : formTags,
	output  : formTags,
	button  : formTags,
	datalist: formTags,
	textarea: formTags,
	option  : { option:true },
	optgroup: { optgroup:true }
};

var voidElements = {
	__proto__: null,
	area: true,
	base: true,
	basefont: true,
	br: true,
	col: true,
	command: true,
	embed: true,
	frame: true,
	hr: true,
	img: true,
	input: true,
	isindex: true,
	keygen: true,
	link: true,
	meta: true,
	param: true,
	source: true,
	track: true,
	wbr: true,

	//common self closing svg elements
	path: true,
	circle: true,
	ellipse: true,
	line: true,
	rect: true,
	use: true,
	stop: true,
	polyline: true,
	polygone: true
};

var re_nameEnd = /\s|\//;

function Parser(cbs, options){
	this._options = options || {};
	this._cbs = cbs || {};

	this._tagname = "";
	this._attribname = "";
	this._attribvalue = "";
	this._attribs = null;
	this._stack = [];

	this.startIndex = 0;
	this.endIndex = null;

	this._lowerCaseTagNames = "lowerCaseTags" in this._options ?
									!!this._options.lowerCaseTags :
									!this._options.xmlMode;
	this._lowerCaseAttributeNames = "lowerCaseAttributeNames" in this._options ?
									!!this._options.lowerCaseAttributeNames :
									!this._options.xmlMode;

	this._tokenizer = new Tokenizer(this._options, this);

	if(this._cbs.onparserinit) this._cbs.onparserinit(this);
}

require("util").inherits(Parser, require("events").EventEmitter);

Parser.prototype._updatePosition = function(initialOffset){
	if(this.endIndex === null){
		if(this._tokenizer._sectionStart <= initialOffset){
			this.startIndex = 0;
		} else {
			this.startIndex = this._tokenizer._sectionStart - initialOffset;
		}
	}
	else this.startIndex = this.endIndex + 1;
	this.endIndex = this._tokenizer.getAbsoluteIndex();
};

//Tokenizer event handlers
Parser.prototype.ontext = function(data){
	this._updatePosition(1);
	this.endIndex--;

	if(this._cbs.ontext) this._cbs.ontext(data);
};

Parser.prototype.onopentagname = function(name){
	if(this._lowerCaseTagNames){
		name = name.toLowerCase();
	}

	this._tagname = name;

	if(!this._options.xmlMode && name in openImpliesClose) {
		for(
			var el;
			(el = this._stack[this._stack.length - 1]) in openImpliesClose[name];
			this.onclosetag(el)
		);
	}

	if(this._options.xmlMode || !(name in voidElements)){
		this._stack.push(name);
	}

	if(this._cbs.onopentagname) this._cbs.onopentagname(name);
	if(this._cbs.onopentag) this._attribs = {};
};

Parser.prototype.onopentagend = function(){
	this._updatePosition(1);

	if(this._attribs){
		if(this._cbs.onopentag) this._cbs.onopentag(this._tagname, this._attribs);
		this._attribs = null;
	}

	if(!this._options.xmlMode && this._cbs.onclosetag && this._tagname in voidElements){
		this._cbs.onclosetag(this._tagname);
	}

	this._tagname = "";
};

Parser.prototype.onclosetag = function(name){
	this._updatePosition(1);

	if(this._lowerCaseTagNames){
		name = name.toLowerCase();
	}

	if(this._stack.length && (!(name in voidElements) || this._options.xmlMode)){
		var pos = this._stack.lastIndexOf(name);
		if(pos !== -1){
			if(this._cbs.onclosetag){
				pos = this._stack.length - pos;
				while(pos--) this._cbs.onclosetag(this._stack.pop());
			}
			else this._stack.length = pos;
		} else if(name === "p" && !this._options.xmlMode){
			this.onopentagname(name);
			this._closeCurrentTag();
		}
	} else if(!this._options.xmlMode && (name === "br" || name === "p")){
		this.onopentagname(name);
		this._closeCurrentTag();
	}
};

Parser.prototype.onselfclosingtag = function(){
	if(this._options.xmlMode || this._options.recognizeSelfClosing){
		this._closeCurrentTag();
	} else {
		this.onopentagend();
	}
};

Parser.prototype._closeCurrentTag = function(){
	var name = this._tagname;

	this.onopentagend();

	//self-closing tags will be on the top of the stack
	//(cheaper check than in onclosetag)
	if(this._stack[this._stack.length - 1] === name){
		if(this._cbs.onclosetag){
			this._cbs.onclosetag(name);
		}
		this._stack.pop();
	}
};

Parser.prototype.onattribname = function(name){
	if(this._lowerCaseAttributeNames){
		name = name.toLowerCase();
	}
	this._attribname = name;
};

Parser.prototype.onattribdata = function(value){
	this._attribvalue += value;
};

Parser.prototype.onattribend = function(){
	if(this._cbs.onattribute) this._cbs.onattribute(this._attribname, this._attribvalue);
	if(
		this._attribs &&
		!Object.prototype.hasOwnProperty.call(this._attribs, this._attribname)
	){
		this._attribs[this._attribname] = this._attribvalue;
	}
	this._attribname = "";
	this._attribvalue = "";
};

Parser.prototype._getInstructionName = function(value){
	var idx = value.search(re_nameEnd),
	    name = idx < 0 ? value : value.substr(0, idx);

	if(this._lowerCaseTagNames){
		name = name.toLowerCase();
	}

	return name;
};

Parser.prototype.ondeclaration = function(value){
	if(this._cbs.onprocessinginstruction){
		var name = this._getInstructionName(value);
		this._cbs.onprocessinginstruction("!" + name, "!" + value);
	}
};

Parser.prototype.onprocessinginstruction = function(value){
	if(this._cbs.onprocessinginstruction){
		var name = this._getInstructionName(value);
		this._cbs.onprocessinginstruction("?" + name, "?" + value);
	}
};

Parser.prototype.oncomment = function(value){
	this._updatePosition(4);

	if(this._cbs.oncomment) this._cbs.oncomment(value);
	if(this._cbs.oncommentend) this._cbs.oncommentend();
};

Parser.prototype.oncdata = function(value){
	this._updatePosition(1);

	if(this._options.xmlMode || this._options.recognizeCDATA){
		if(this._cbs.oncdatastart) this._cbs.oncdatastart();
		if(this._cbs.ontext) this._cbs.ontext(value);
		if(this._cbs.oncdataend) this._cbs.oncdataend();
	} else {
		this.oncomment("[CDATA[" + value + "]]");
	}
};

Parser.prototype.onerror = function(err){
	if(this._cbs.onerror) this._cbs.onerror(err);
};

Parser.prototype.onend = function(){
	if(this._cbs.onclosetag){
		for(
			var i = this._stack.length;
			i > 0;
			this._cbs.onclosetag(this._stack[--i])
		);
	}
	if(this._cbs.onend) this._cbs.onend();
};

//Resets the parser to a blank state, ready to parse a new HTML document
Parser.prototype.reset = function(){
	if(this._cbs.onreset) this._cbs.onreset();
	this._tokenizer.reset();

	this._tagname = "";
	this._attribname = "";
	this._attribs = null;
	this._stack = [];

	if(this._cbs.onparserinit) this._cbs.onparserinit(this);
};

//Parses a complete HTML document and pushes it to the handler
Parser.prototype.parseComplete = function(data){
	this.reset();
	this.end(data);
};

Parser.prototype.write = function(chunk){
	this._tokenizer.write(chunk);
};

Parser.prototype.end = function(chunk){
	this._tokenizer.end(chunk);
};

Parser.prototype.pause = function(){
	this._tokenizer.pause();
};

Parser.prototype.resume = function(){
	this._tokenizer.resume();
};

//alias for backwards compat
Parser.prototype.parseChunk = Parser.prototype.write;
Parser.prototype.done = Parser.prototype.end;

module.exports = Parser;
<commit_msg>Fixed typo<commit_after>var Tokenizer = require("./Tokenizer.js");

/*
	Options:

	xmlMode: Disables the special behavior for script/style tags (false by default)
	lowerCaseAttributeNames: call .toLowerCase for each attribute name (true if xmlMode is `false`)
	lowerCaseTags: call .toLowerCase for each tag name (true if xmlMode is `false`)
*/

/*
	Callbacks:

	oncdataend,
	oncdatastart,
	onclosetag,
	oncomment,
	oncommentend,
	onerror,
	onopentag,
	onprocessinginstruction,
	onreset,
	ontext
*/

var formTags = {
	input: true,
	option: true,
	optgroup: true,
	select: true,
	button: true,
	datalist: true,
	textarea: true
};

var openImpliesClose = {
	tr      : { tr:true, th:true, td:true },
	th      : { th:true },
	td      : { thead:true, th:true, td:true },
	body    : { head:true, link:true, script:true },
	li      : { li:true },
	p       : { p:true },
	h1      : { p:true },
	h2      : { p:true },
	h3      : { p:true },
	h4      : { p:true },
	h5      : { p:true },
	h6      : { p:true },
	select  : formTags,
	input   : formTags,
	output  : formTags,
	button  : formTags,
	datalist: formTags,
	textarea: formTags,
	option  : { option:true },
	optgroup: { optgroup:true }
};

var voidElements = {
	__proto__: null,
	area: true,
	base: true,
	basefont: true,
	br: true,
	col: true,
	command: true,
	embed: true,
	frame: true,
	hr: true,
	img: true,
	input: true,
	isindex: true,
	keygen: true,
	link: true,
	meta: true,
	param: true,
	source: true,
	track: true,
	wbr: true,

	//common self closing svg elements
	path: true,
	circle: true,
	ellipse: true,
	line: true,
	rect: true,
	use: true,
	stop: true,
	polyline: true,
	polygon: true
};

var re_nameEnd = /\s|\//;

function Parser(cbs, options){
	this._options = options || {};
	this._cbs = cbs || {};

	this._tagname = "";
	this._attribname = "";
	this._attribvalue = "";
	this._attribs = null;
	this._stack = [];

	this.startIndex = 0;
	this.endIndex = null;

	this._lowerCaseTagNames = "lowerCaseTags" in this._options ?
									!!this._options.lowerCaseTags :
									!this._options.xmlMode;
	this._lowerCaseAttributeNames = "lowerCaseAttributeNames" in this._options ?
									!!this._options.lowerCaseAttributeNames :
									!this._options.xmlMode;

	this._tokenizer = new Tokenizer(this._options, this);

	if(this._cbs.onparserinit) this._cbs.onparserinit(this);
}

require("util").inherits(Parser, require("events").EventEmitter);

Parser.prototype._updatePosition = function(initialOffset){
	if(this.endIndex === null){
		if(this._tokenizer._sectionStart <= initialOffset){
			this.startIndex = 0;
		} else {
			this.startIndex = this._tokenizer._sectionStart - initialOffset;
		}
	}
	else this.startIndex = this.endIndex + 1;
	this.endIndex = this._tokenizer.getAbsoluteIndex();
};

//Tokenizer event handlers
Parser.prototype.ontext = function(data){
	this._updatePosition(1);
	this.endIndex--;

	if(this._cbs.ontext) this._cbs.ontext(data);
};

Parser.prototype.onopentagname = function(name){
	if(this._lowerCaseTagNames){
		name = name.toLowerCase();
	}

	this._tagname = name;

	if(!this._options.xmlMode && name in openImpliesClose) {
		for(
			var el;
			(el = this._stack[this._stack.length - 1]) in openImpliesClose[name];
			this.onclosetag(el)
		);
	}

	if(this._options.xmlMode || !(name in voidElements)){
		this._stack.push(name);
	}

	if(this._cbs.onopentagname) this._cbs.onopentagname(name);
	if(this._cbs.onopentag) this._attribs = {};
};

Parser.prototype.onopentagend = function(){
	this._updatePosition(1);

	if(this._attribs){
		if(this._cbs.onopentag) this._cbs.onopentag(this._tagname, this._attribs);
		this._attribs = null;
	}

	if(!this._options.xmlMode && this._cbs.onclosetag && this._tagname in voidElements){
		this._cbs.onclosetag(this._tagname);
	}

	this._tagname = "";
};

Parser.prototype.onclosetag = function(name){
	this._updatePosition(1);

	if(this._lowerCaseTagNames){
		name = name.toLowerCase();
	}

	if(this._stack.length && (!(name in voidElements) || this._options.xmlMode)){
		var pos = this._stack.lastIndexOf(name);
		if(pos !== -1){
			if(this._cbs.onclosetag){
				pos = this._stack.length - pos;
				while(pos--) this._cbs.onclosetag(this._stack.pop());
			}
			else this._stack.length = pos;
		} else if(name === "p" && !this._options.xmlMode){
			this.onopentagname(name);
			this._closeCurrentTag();
		}
	} else if(!this._options.xmlMode && (name === "br" || name === "p")){
		this.onopentagname(name);
		this._closeCurrentTag();
	}
};

Parser.prototype.onselfclosingtag = function(){
	if(this._options.xmlMode || this._options.recognizeSelfClosing){
		this._closeCurrentTag();
	} else {
		this.onopentagend();
	}
};

Parser.prototype._closeCurrentTag = function(){
	var name = this._tagname;

	this.onopentagend();

	//self-closing tags will be on the top of the stack
	//(cheaper check than in onclosetag)
	if(this._stack[this._stack.length - 1] === name){
		if(this._cbs.onclosetag){
			this._cbs.onclosetag(name);
		}
		this._stack.pop();
	}
};

Parser.prototype.onattribname = function(name){
	if(this._lowerCaseAttributeNames){
		name = name.toLowerCase();
	}
	this._attribname = name;
};

Parser.prototype.onattribdata = function(value){
	this._attribvalue += value;
};

Parser.prototype.onattribend = function(){
	if(this._cbs.onattribute) this._cbs.onattribute(this._attribname, this._attribvalue);
	if(
		this._attribs &&
		!Object.prototype.hasOwnProperty.call(this._attribs, this._attribname)
	){
		this._attribs[this._attribname] = this._attribvalue;
	}
	this._attribname = "";
	this._attribvalue = "";
};

Parser.prototype._getInstructionName = function(value){
	var idx = value.search(re_nameEnd),
	    name = idx < 0 ? value : value.substr(0, idx);

	if(this._lowerCaseTagNames){
		name = name.toLowerCase();
	}

	return name;
};

Parser.prototype.ondeclaration = function(value){
	if(this._cbs.onprocessinginstruction){
		var name = this._getInstructionName(value);
		this._cbs.onprocessinginstruction("!" + name, "!" + value);
	}
};

Parser.prototype.onprocessinginstruction = function(value){
	if(this._cbs.onprocessinginstruction){
		var name = this._getInstructionName(value);
		this._cbs.onprocessinginstruction("?" + name, "?" + value);
	}
};

Parser.prototype.oncomment = function(value){
	this._updatePosition(4);

	if(this._cbs.oncomment) this._cbs.oncomment(value);
	if(this._cbs.oncommentend) this._cbs.oncommentend();
};

Parser.prototype.oncdata = function(value){
	this._updatePosition(1);

	if(this._options.xmlMode || this._options.recognizeCDATA){
		if(this._cbs.oncdatastart) this._cbs.oncdatastart();
		if(this._cbs.ontext) this._cbs.ontext(value);
		if(this._cbs.oncdataend) this._cbs.oncdataend();
	} else {
		this.oncomment("[CDATA[" + value + "]]");
	}
};

Parser.prototype.onerror = function(err){
	if(this._cbs.onerror) this._cbs.onerror(err);
};

Parser.prototype.onend = function(){
	if(this._cbs.onclosetag){
		for(
			var i = this._stack.length;
			i > 0;
			this._cbs.onclosetag(this._stack[--i])
		);
	}
	if(this._cbs.onend) this._cbs.onend();
};

//Resets the parser to a blank state, ready to parse a new HTML document
Parser.prototype.reset = function(){
	if(this._cbs.onreset) this._cbs.onreset();
	this._tokenizer.reset();

	this._tagname = "";
	this._attribname = "";
	this._attribs = null;
	this._stack = [];

	if(this._cbs.onparserinit) this._cbs.onparserinit(this);
};

//Parses a complete HTML document and pushes it to the handler
Parser.prototype.parseComplete = function(data){
	this.reset();
	this.end(data);
};

Parser.prototype.write = function(chunk){
	this._tokenizer.write(chunk);
};

Parser.prototype.end = function(chunk){
	this._tokenizer.end(chunk);
};

Parser.prototype.pause = function(){
	this._tokenizer.pause();
};

Parser.prototype.resume = function(){
	this._tokenizer.resume();
};

//alias for backwards compat
Parser.prototype.parseChunk = Parser.prototype.write;
Parser.prototype.done = Parser.prototype.end;

module.exports = Parser;
<|endoftext|>


<commit_before>
define([
    'flight/lib/component',
    '../withPopover',
    'util/vertex/formatters',
    'util/withDataRequest',
    'd3'
], function(
    defineComponent,
    withPopover,
    F,
    withDataRequest,
    d3) {
    'use strict';

    return defineComponent(PropertyInfo, withPopover, withDataRequest);

    function PropertyInfo() {

        this.defaultAttrs({
            deleteButtonSelector: '.btn-danger',
            editButtonSelector: '.btn-edit',
            addButtonSelector: '.btn-add',
            replyButtonSelector: '.reply',
            justificationValueSelector: 'a'
        });

        this.before('initialize', function(node, config) {
            config.template = 'propertyInfo/template';
            if (config.property) {
                config.isComment = config.property.name === 'http://lumify.io/comment#entry';
                config.isCommentCreator = config.isComment &&
                    config.property.metadata &&
                    config.property.metadata['http://lumify.io#modifiedBy'] === lumifyData.currentUser.id;
                config.canEdit = config.isComment ?
                    config.isCommentCreator :
                    true;
                config.canDelete = config.canEdit && config.property.name !== 'http://lumify.io#visibilityJson';
            }
            config.hideDialog = true;
        });

        this.after('initialize', function() {
            var self = this;

            this.after('setupWithTemplate', function() {
                this.dataRequest('config', 'properties')
                    .done(function(config) {
                        var splitRegex = /\s*,\s*/,
                            metadataDisplay =
                                config['properties.metadata.propertyNamesDisplay'].split(splitRegex).map(i18n),
                            metadataType =
                                config['properties.metadata.propertyNamesType'].split(splitRegex);

                        self.metadataProperties =
                            config['properties.metadata.propertyNames'].split(splitRegex);

                        if (self.metadataProperties.length !== metadataDisplay.length ||
                            self.metadataProperties.length !== metadataType.length) {
                            throw new Error('Metadata properties must have display names and types');
                        }
                        self.metadataPropertiesDisplayMap = _.object(self.metadataProperties, metadataDisplay);
                        self.metadataPropertiesTypeMap = _.object(self.metadataProperties, metadataType);

                        self.on(self.popover, 'click', {
                            deleteButtonSelector: self.onDelete,
                            editButtonSelector: self.onEdit,
                            addButtonSelector: self.onAdd,
                            replyButtonSelector: self.onReply,
                            justificationValueSelector: self.teardown
                        });

                        self.contentRoot = d3.select(self.popover.get(0))
                            .select('.popover-content');
                        self.update();

                        self.on(document, 'verticesUpdated', self.onVerticesUpdated);
                    });
            });
        });

        this.update = function() {
            var vertexId = this.attr.data.id,
                property = _.first(F.vertex.props(this.attr.data, this.attr.property.name, this.attr.property.key)),
                positionDialog = this.positionDialog.bind(this),
                displayNames = this.metadataPropertiesDisplayMap,
                displayTypes = this.metadataPropertiesTypeMap,
                isComment = property.name === 'http://lumify.io/comment#entry',
                metadata = _.chain(this.metadataProperties || [])
                    .map(function(name) {
                        if ('metadata' in property) {
                            if (name in property.metadata) {
                                return [name, property.metadata[name]];
                            }
                        }
                        if (name in property) {
                            return [name, property[name]];
                        }
                    })
                    .compact()
                    .filter(function(m) {
                        if (m[0] === 'http://lumify.io#confidence' && isComment) {
                            return false;
                        }
                        return true;
                    })
                    .value()
                row = this.contentRoot.select('table')
                    .selectAll('tr')
                    .data(metadata)
                    .call(function() {
                        this.enter()
                            .append('tr')
                            .call(function() {
                                this.append('td').attr('class', 'property-name');
                                this.append('td').attr('class', 'property-value');
                            });
                    });

            this.contentRoot.selectAll('tr')
                .call(function() {
                    var self = this;

                    this.select('td.property-name').text(function(d) {
                        return displayNames[d[0]];
                    });

                    var valueElement = self.select('td.property-value')
                        .each(function(d) {
                            var self = this,
                                $self = $(this),
                                typeName = displayTypes[d[0]],
                                formatter = F.vertex.metadata[typeName],
                                formatterAsync = F.vertex.metadata[typeName + 'Async'],
                                value = d[1];

                            if (formatter) {
                                formatter(this, value);
                            } else if (formatterAsync) {
                                formatterAsync(self, value, property, vertexId)
                                    .catch(function() {
                                        d3.select(self).text(i18n('popovers.property_info.error', value));
                                    })
                                    .finally(positionDialog);
                                d3.select(this).text(i18n('popovers.property_info.loading'));
                            } else {
                                console.warn('No metadata type formatter: ' + typeName);
                                d3.select(this).text(value);
                            }
                        });
                })

                // Hide blank metadata
                .each(function(d) {
                    $(this).toggle($(this).find('.property-value').text() !== '');
                });

            // Justification
            var justification = [];
            if (property.metadata &&
                (property.metadata._justificationMetadata || property.metadata._sourceMetadata)) {
                justification.push(true);
            }

            var table = this.contentRoot.select('table'),
                justificationRow = this.contentRoot.selectAll('.justification')

            justificationRow
                .data(justification)
                .call(function() {
                    this.enter()
                        .call(function() {
                            this.insert('div', 'button').attr('class', 'justification')
                                .call(function() {
                                    this.append('div')
                                        .attr('class', 'property-name property-justification')
                                        .text(i18n('popovers.property_info.justification'));
                                    this.append('div')
                                        .attr('class', 'justificationValue');
                                });
                        });
                    this.exit().remove();

                    var node = this.select('.justificationValue').node();
                    if (node) {
                        require(['util/vertex/justification/viewer'], function(JustificationViewer) {
                            $(node).teardownAllComponents();
                            JustificationViewer.attachTo(node, {
                                justificationMetadata: property.metadata._justificationMetadata,
                                sourceMetadata: property.metadata._sourceMetadata
                            });
                            positionDialog();
                        });
                    }
                })

            row.exit().remove();

            this.dialog.show();
            positionDialog();
        };

        this.onVerticesUpdated = function(event, data) {
            var vertex = _.findWhere(data.vertices, {
                    id: this.attr.data.id
                }),
                property = vertex && _.findWhere(vertex.properties, {
                    name: this.attr.property.name,
                    key: this.attr.property.key
                });
            if (vertex && !property) {
                this.teardown();
            } else if (property) {
                this.attr.data = vertex;
                this.update();
            }
        };

        this.onReply = function() {
            var metadata = this.attr.property.metadata['http://lumify.io/comment#path'],
                path = (metadata ? (metadata + '/') : '') + this.attr.property.key;

            this.trigger('editProperty', {
                path: path
            });
            this.teardown();
        };

        this.onAdd = function() {
            this.trigger('editProperty', {
                property: _.omit(this.attr.property, 'key')
            });
            this.teardown();
        };

        this.onEdit = function() {
            this.trigger('editProperty', {
                property: this.attr.property
            });
            this.teardown();
        };

        this.onDelete = function(e) {
            e.stopPropagation();
            var button = this.popover.find('.btn-danger').addClass('loading').attr('disabled', true);
            this.trigger('deleteProperty', {
                property: _.pick(this.attr.property, 'name', 'key')
            });
        };
    }
});
<commit_msg>Fix property info for visibility<commit_after>
define([
    'flight/lib/component',
    '../withPopover',
    'util/vertex/formatters',
    'util/withDataRequest',
    'd3'
], function(
    defineComponent,
    withPopover,
    F,
    withDataRequest,
    d3) {
    'use strict';

    return defineComponent(PropertyInfo, withPopover, withDataRequest);

    function PropertyInfo() {

        this.defaultAttrs({
            deleteButtonSelector: '.btn-danger',
            editButtonSelector: '.btn-edit',
            addButtonSelector: '.btn-add',
            replyButtonSelector: '.reply',
            justificationValueSelector: 'a'
        });

        this.before('initialize', function(node, config) {
            config.template = 'propertyInfo/template';
            if (config.property) {
                config.isComment = config.property.name === 'http://lumify.io/comment#entry';
                config.isCommentCreator = config.isComment &&
                    config.property.metadata &&
                    config.property.metadata['http://lumify.io#modifiedBy'] === lumifyData.currentUser.id;
                config.canEdit = config.isComment ?
                    config.isCommentCreator :
                    true;
                config.canDelete = config.canEdit && config.property.name !== 'http://lumify.io#visibilityJson';
            }
            config.hideDialog = true;
        });

        this.after('initialize', function() {
            var self = this;

            this.after('setupWithTemplate', function() {
                this.dataRequest('config', 'properties')
                    .done(function(config) {
                        var splitRegex = /\s*,\s*/,
                            metadataDisplay =
                                config['properties.metadata.propertyNamesDisplay'].split(splitRegex).map(i18n),
                            metadataType =
                                config['properties.metadata.propertyNamesType'].split(splitRegex);

                        self.metadataProperties =
                            config['properties.metadata.propertyNames'].split(splitRegex);

                        if (self.metadataProperties.length !== metadataDisplay.length ||
                            self.metadataProperties.length !== metadataType.length) {
                            throw new Error('Metadata properties must have display names and types');
                        }
                        self.metadataPropertiesDisplayMap = _.object(self.metadataProperties, metadataDisplay);
                        self.metadataPropertiesTypeMap = _.object(self.metadataProperties, metadataType);

                        self.on(self.popover, 'click', {
                            deleteButtonSelector: self.onDelete,
                            editButtonSelector: self.onEdit,
                            addButtonSelector: self.onAdd,
                            replyButtonSelector: self.onReply,
                            justificationValueSelector: self.teardown
                        });

                        self.contentRoot = d3.select(self.popover.get(0))
                            .select('.popover-content');
                        self.update();

                        self.on(document, 'verticesUpdated', self.onVerticesUpdated);
                    });
            });
        });

        this.update = function() {
            var vertexId = this.attr.data.id,
                property = this.attr.property.name === 'http://lumify.io#visibilityJson' ?
                    _.first(F.vertex.props(this.attr.data, this.attr.property.name)) :
                    _.first(F.vertex.props(this.attr.data, this.attr.property.name, this.attr.property.key)),
                positionDialog = this.positionDialog.bind(this),
                displayNames = this.metadataPropertiesDisplayMap,
                displayTypes = this.metadataPropertiesTypeMap,
                isComment = property.name === 'http://lumify.io/comment#entry',
                metadata = _.chain(this.metadataProperties || [])
                    .map(function(name) {
                        if ('metadata' in property) {
                            if (name in property.metadata) {
                                return [name, property.metadata[name]];
                            }
                        }
                        if (name in property) {
                            return [name, property[name]];
                        }
                    })
                    .compact()
                    .filter(function(m) {
                        if (property.name === 'http://lumify.io#visibilityJson' &&
                            m[0] === 'sandboxStatus') {
                            return false;
                        }
                        if (m[0] === 'http://lumify.io#confidence' && isComment) {
                            return false;
                        }
                        return true;
                    })
                    .value()
                row = this.contentRoot.select('table')
                    .selectAll('tr')
                    .data(metadata)
                    .call(function() {
                        this.enter()
                            .append('tr')
                            .call(function() {
                                this.append('td').attr('class', 'property-name');
                                this.append('td').attr('class', 'property-value');
                            });
                    });

            this.contentRoot.selectAll('tr')
                .call(function() {
                    var self = this;

                    this.select('td.property-name').text(function(d) {
                        return displayNames[d[0]];
                    });

                    var valueElement = self.select('td.property-value')
                        .each(function(d) {
                            var self = this,
                                $self = $(this),
                                typeName = displayTypes[d[0]],
                                formatter = F.vertex.metadata[typeName],
                                formatterAsync = F.vertex.metadata[typeName + 'Async'],
                                value = d[1];

                            if (formatter) {
                                formatter(this, value);
                            } else if (formatterAsync) {
                                formatterAsync(self, value, property, vertexId)
                                    .catch(function() {
                                        d3.select(self).text(i18n('popovers.property_info.error', value));
                                    })
                                    .finally(positionDialog);
                                d3.select(this).text(i18n('popovers.property_info.loading'));
                            } else {
                                console.warn('No metadata type formatter: ' + typeName);
                                d3.select(this).text(value);
                            }
                        });
                })

                // Hide blank metadata
                .each(function(d) {
                    $(this).toggle($(this).find('.property-value').text() !== '');
                });

            // Justification
            var justification = [];
            if (property.metadata &&
                (property.metadata._justificationMetadata || property.metadata._sourceMetadata)) {
                justification.push(true);
            }

            var table = this.contentRoot.select('table'),
                justificationRow = this.contentRoot.selectAll('.justification')

            justificationRow
                .data(justification)
                .call(function() {
                    this.enter()
                        .call(function() {
                            this.insert('div', 'button').attr('class', 'justification')
                                .call(function() {
                                    this.append('div')
                                        .attr('class', 'property-name property-justification')
                                        .text(i18n('popovers.property_info.justification'));
                                    this.append('div')
                                        .attr('class', 'justificationValue');
                                });
                        });
                    this.exit().remove();

                    var node = this.select('.justificationValue').node();
                    if (node) {
                        require(['util/vertex/justification/viewer'], function(JustificationViewer) {
                            $(node).teardownAllComponents();
                            JustificationViewer.attachTo(node, {
                                justificationMetadata: property.metadata._justificationMetadata,
                                sourceMetadata: property.metadata._sourceMetadata
                            });
                            positionDialog();
                        });
                    }
                })

            row.exit().remove();

            this.dialog.show();
            positionDialog();
        };

        this.onVerticesUpdated = function(event, data) {
            var vertex = _.findWhere(data.vertices, {
                    id: this.attr.data.id
                }),
                property = vertex && _.findWhere(vertex.properties, {
                    name: this.attr.property.name,
                    key: this.attr.property.key
                });
            if (vertex && !property) {
                this.teardown();
            } else if (property) {
                this.attr.data = vertex;
                this.update();
            }
        };

        this.onReply = function() {
            var metadata = this.attr.property.metadata['http://lumify.io/comment#path'],
                path = (metadata ? (metadata + '/') : '') + this.attr.property.key;

            this.trigger('editProperty', {
                path: path
            });
            this.teardown();
        };

        this.onAdd = function() {
            this.trigger('editProperty', {
                property: _.omit(this.attr.property, 'key')
            });
            this.teardown();
        };

        this.onEdit = function() {
            this.trigger('editProperty', {
                property: this.attr.property
            });
            this.teardown();
        };

        this.onDelete = function(e) {
            e.stopPropagation();
            var button = this.popover.find('.btn-danger').addClass('loading').attr('disabled', true);
            this.trigger('deleteProperty', {
                property: _.pick(this.attr.property, 'name', 'key')
            });
        };
    }
});
<|endoftext|>


<commit_before><commit_msg>Bugfix.<commit_after><|endoftext|>


<commit_before>// time.js

(function($){

$(document).ready(handle);
$(document).bind("DOMNodeInserted", handle);

function handle(event) {
	var now = new Date();
	var target = event.target ? event.target : document;
	var time = $(target.getElementsByTagName('time'));
	if ($(target).is('time')) {
		time = time.add(target);
	}
	time.each(function(i, node) {
		changeDateLocale(node, now);
	});
}

function changeDateLocale(node, now) {
	var node = $(node);
	if (!node.attr("datetime")) {
		var ie8 = false;
		var text = node.text();
		if (!text && node[0].nextSibling && node[0].nextSibling.nodeValue) {
			text = node[0].nextSibling.nodeValue;
			ie8 = true;
		}
		if (!text) return;
		var timestamp = parseDateTime(text, now);
		if (!isNaN(timestamp)) {
			node.attr("content", text);
			node.attr("datetime", text);
			var date = new Date(timestamp);
			if ((date.getHours() > 0 || date.getMinutes() > 0) && /^\s*(\d{4})-?(\d{2})-?(\d{2})\s*$/.exec(text)) {
				date = new Date(parseDateTime(text + "T00:00:00"));
			}
			var formatted = null;
			if (node.is(".abbreviated")) {
				formatted = local(date, now, node);
			} else if (node.is(".datetime")) {
				formatted =  date.toLocaleString();
			} else if (node.is(".datetime-local")) {
				formatted = local(date, now);
			} else if (node.is(".date")) {
				formatted = date.toLocaleDateString();
			} else if (node.is(".month")) {
				formatted = month(date);
			} else if (node.is(".year")) {
				formatted = date.getFullYear();
			} else if (node.is(".time")) {
				formatted = date.toLocaleTimeString();
			} else if (text.indexOf('T') < 0) {
				formatted = date.toLocaleDateString();
			} else {
				formatted = date.toString();
			}
			if (ie8) {
				node[0].nextSibling.nodeValue = formatted;
			} else {
				node.text(formatted);
			}
		}
	}
}

function parseDateTime(text, now) {
	if (/^\s*([\d]+\-?){1,2}\s*$/.exec(text))
		return NaN;
    var struct = /(?:(\d{4})-?(\d{2})-?(\d{2}))?(?:[T ]?(\d{2}):?(\d{2}):?(\d{2})(?:\.(\d{3,}))?)?(?:(Z)|([+\-])(\d{2})(?::?(\d{2}))?)?/.exec(text);
	if (!struct)
		return Date.parse(text);
    var minutesOffset = 0;
    if (struct[8] !== 'Z' && struct[9]) {
        minutesOffset = +struct[10] * 60 + (+struct[11]);
        if (struct[9] === '+') {
            minutesOffset = 0 - minutesOffset;
        }
    }
	if (struct[1]) {
		if (struct[4] || struct[5] || struct[6]) {
			if (struct[8] || struct[9]) {
	        	timestamp = Date.UTC(+struct[1], +struct[2] - 1, +struct[3], +struct[4], +struct[5] + minutesOffset, +struct[6], 0);
			} else {
	        	timestamp = new Date(+struct[1], +struct[2] - 1, +struct[3], +struct[4], +struct[5], +struct[6], 0).getTime();
			}
		} else if (struct[8] || struct[9]) {
        	timestamp = Date.UTC(+struct[1], +struct[2] - 1, +struct[3], 0, minutesOffset, 0, 0);
		} else {
        	timestamp = new Date(+struct[1], +struct[2] - 1, +struct[3]).getTime();
		}
	} else if (struct[4] || struct[5] || struct[6]) {
		if (struct[8] || struct[9]) {
        	timestamp = Date.UTC(now.getFullYear(), now.getMonth(), now.getDate(), +struct[4], +struct[5] + minutesOffset, +struct[6], 0);
		} else {
        	timestamp = new Date(now.getFullYear(), now.getMonth(), now.getDate(), +struct[4], +struct[5], +struct[6], 0).getTime();
		}
	}
	return timestamp;
}

function local(date, now, node) {
	var locale = '';
	var minutes = '';
	if (!node || !node.is('.date') && !node.is('.month')) {
		if (date.getMinutes() >= 10) {
			minutes = ':' + date.getMinutes();
		} else if (!node || date.getHours() > 0 || date.getMinutes() > 0) {
			minutes = ':0' + date.getMinutes();
		}
		if (date.getHours() > 12) {
			locale = (date.getHours() - 12) + minutes + " pm";
		} else if (date.getHours() == 12) {
			locale = "12" + minutes + " pm";
		} else if (date.getHours() > 0) {
			locale = date.getHours() + minutes + " am";
		} else if (minutes) {
			locale = "12" + minutes + " am";
		}
	}
	if (!node || !node.is('.time')) {
		if (!node || locale == '' || date.getDate() != now.getDate() || date.getMonth() != now.getMonth() || date.getFullYear() != now.getFullYear()) {
			if (locale) {
				locale += ", ";
			}
			var month = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][date.getMonth()];
			if (!node || !node.is('.month')) {
				locale += date.getDate() + ' ';
			}
			locale += month;
			if (!node || date.getFullYear() != now.getFullYear()) {
				locale += ' ' + date.getFullYear();
			}
		}
	}
	return locale;
}

function month(date) {
	var month = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][date.getMonth()];
	return month + ' ' + date.getFullYear();
}

})(window.jQuery);

<commit_msg>Use 24 hours time<commit_after>// time.js

(function($){

$(document).ready(handle);
$(document).bind("DOMNodeInserted", handle);

function handle(event) {
	var now = new Date();
	var target = event.target ? event.target : document;
	var time = $(target.getElementsByTagName('time'));
	if ($(target).is('time')) {
		time = time.add(target);
	}
	time.each(function(i, node) {
		changeDateLocale(node, now);
	});
}

function changeDateLocale(node, now) {
	var node = $(node);
	if (!node.attr("datetime")) {
		var ie8 = false;
		var text = node.text();
		if (!text && node[0].nextSibling && node[0].nextSibling.nodeValue) {
			text = node[0].nextSibling.nodeValue;
			ie8 = true;
		}
		if (!text) return;
		var timestamp = parseDateTime(text, now);
		if (!isNaN(timestamp)) {
			node.attr("content", text);
			node.attr("datetime", text);
			var date = new Date(timestamp);
			if ((date.getHours() > 0 || date.getMinutes() > 0) && /^\s*(\d{4})-?(\d{2})-?(\d{2})\s*$/.exec(text)) {
				date = new Date(parseDateTime(text + "T00:00:00"));
			}
			var formatted = null;
			if (node.is(".abbreviated")) {
				formatted = local(date, now, node);
			} else if (node.is(".datetime")) {
				formatted =  date.toLocaleString();
			} else if (node.is(".datetime-local")) {
				formatted = local(date, now);
			} else if (node.is(".date")) {
				formatted = date.toLocaleDateString();
			} else if (node.is(".month")) {
				formatted = month(date);
			} else if (node.is(".year")) {
				formatted = date.getFullYear();
			} else if (node.is(".time")) {
				formatted = date.toLocaleTimeString();
			} else if (text.indexOf('T') < 0) {
				formatted = date.toLocaleDateString();
			} else {
				formatted = date.toString();
			}
			if (ie8) {
				node[0].nextSibling.nodeValue = formatted;
			} else {
				node.text(formatted);
			}
		}
	}
}

function parseDateTime(text, now) {
	if (/^\s*([\d]+\-?){1,2}\s*$/.exec(text))
		return NaN;
    var struct = /(?:(\d{4})-?(\d{2})-?(\d{2}))?(?:[T ]?(\d{2}):?(\d{2}):?(\d{2})(?:\.(\d{3,}))?)?(?:(Z)|([+\-])(\d{2})(?::?(\d{2}))?)?/.exec(text);
	if (!struct)
		return Date.parse(text);
    var minutesOffset = 0;
    if (struct[8] !== 'Z' && struct[9]) {
        minutesOffset = +struct[10] * 60 + (+struct[11]);
        if (struct[9] === '+') {
            minutesOffset = 0 - minutesOffset;
        }
    }
	if (struct[1]) {
		if (struct[4] || struct[5] || struct[6]) {
			if (struct[8] || struct[9]) {
	        	timestamp = Date.UTC(+struct[1], +struct[2] - 1, +struct[3], +struct[4], +struct[5] + minutesOffset, +struct[6], 0);
			} else {
	        	timestamp = new Date(+struct[1], +struct[2] - 1, +struct[3], +struct[4], +struct[5], +struct[6], 0).getTime();
			}
		} else if (struct[8] || struct[9]) {
        	timestamp = Date.UTC(+struct[1], +struct[2] - 1, +struct[3], 0, minutesOffset, 0, 0);
		} else {
        	timestamp = new Date(+struct[1], +struct[2] - 1, +struct[3]).getTime();
		}
	} else if (struct[4] || struct[5] || struct[6]) {
		if (struct[8] || struct[9]) {
        	timestamp = Date.UTC(now.getFullYear(), now.getMonth(), now.getDate(), +struct[4], +struct[5] + minutesOffset, +struct[6], 0);
		} else {
        	timestamp = new Date(now.getFullYear(), now.getMonth(), now.getDate(), +struct[4], +struct[5], +struct[6], 0).getTime();
		}
	}
	return timestamp;
}

function local(date, now, node) {
	var locale = '';
	var minutes = '';
	if (!node || !node.is('.date') && !node.is('.month')) {
		if (date.getMinutes() >= 10) {
			minutes = ':' + date.getMinutes();
		} else if (!node || date.getHours() > 0 || date.getMinutes() > 0) {
			minutes = ':0' + date.getMinutes();
		}
		if (date.getHours() >= 10) {
			locale = date.getHours() + minutes;
		} else if (date.getHours() > 0) {
			locale = "0" + date.getHours() + minutes;
		} else if (minutes) {
			locale = "00" + minutes;
		}
	}
	if (!node || !node.is('.time')) {
		if (!node || locale == '' || date.getDate() != now.getDate() || date.getMonth() != now.getMonth() || date.getFullYear() != now.getFullYear()) {
			if (locale) {
				locale += ", ";
			}
			var month = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][date.getMonth()];
			if (!node || !node.is('.month')) {
				locale += date.getDate() + ' ';
			}
			locale += month;
			if (!node || date.getFullYear() != now.getFullYear()) {
				locale += ' ' + date.getFullYear();
			}
		}
	}
	return locale;
}

function month(date) {
	var month = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][date.getMonth()];
	return month + ' ' + date.getFullYear();
}

})(window.jQuery);

<|endoftext|>


<commit_before><commit_msg>[PIE-15] Adding the File path field.<commit_after><|endoftext|>


<commit_before>import { Provider, Repository, Branch } from './repository-provider';

const github = require('github-basic');
const octonode = require('octonode');

export class GithubProvider extends Provider {
  static get repositoryClass() {
    return GithubRepository;
  }

  static get branchClass() {
    return GithubBranch;
  }

  constructor(token) {
    super();

    const client = octonode.client(token);

    Object.defineProperty(this, 'options', {
      value: {
        auth: {
          type: 'oauth',
          token
        }
      }
    });

    Object.defineProperty(this, 'client', { value: client });
  }
}

export class GithubRepository extends Repository {
  constructor(provider, name) {
    super(provider, name);
    Object.defineProperty(this, 'user', { value: name.split(/\//)[0] });
  }

  get options() {
    return this.provider.options;
  }

  async branches() {
    return new Promise((resolve, reject) => {
      this.provider.client.repo(this.name).branches((err, data) => {
        if (err) {
          reject(err);
        } else {
          data.forEach(d => {
            const b = new this.provider.constructor.branchClass(this, d.name);
            this._branches.set(b.name, b);
          });
          resolve(this._branches);
        }
      });
    });
  }

  async createBranch(name, from = 'master') {
    const res = await github.json(
      'get',
      `/repos/${this.name}/git/refs/heads/${from}`,
      {},
      this.options
    );

    const nb = await github.json(
      'post',
      `/repos/${this.name}/git/refs`,
      {
        ref: `refs/heads/${name}`,
        sha: res.body.object.sha
      },
      this.options
    );

    const b = new this.provider.constructor.branchClass(this, name);
    this._branches.set(b.name, b);
    return b;
  }

  createPullRequest(from, to, msg) {
    return github.json(
      'post',
      `/repos/${to.user}/${to.repo}/pulls`,
      {
        title: msg.title,
        body: msg.body,
        base: from.branch,
        head: to.branch
      },
      this.options
    );
  }
}

export class GithubBranch extends Branch {
  get options() {
    return this.provider.options;
  }

  async writeBlob(blob) {
    const path = blob.path.replace(/\\/g, '/').replace(/^\//, '');
    const mode = blob.mode || '100644';
    const type = blob.type || 'blob';

    const res = await github.json(
      'post',
      `/repos/${this.repository.name}/git/blobs`,
      {
        content:
          typeof blob.content === 'string'
            ? blob.content
            : blob.content.toString('base64'),
        encoding: typeof blob.content === 'string' ? 'utf-8' : 'base64'
      },
      this.options
    );

    return {
      path,
      mode,
      type,
      sha: res.body.sha
    };
  }

  async commit(message, blobs, options = {}) {
    const updates = await Promise.all(blobs.map(b => this.writeBlob(b)));

    let res = await github.json(
      'get',
      `/repos/${this.repository.name}/git/refs/heads/${this.name}`,
      {},
      this.options
    );
    const shaLatestCommit = res.body.object.sha;

    console.log(`latest commit: ${shaLatestCommit}`);

    res = await github.json(
      'get',
      `/repos/${this.repository.name}/commits/${shaLatestCommit}`,
      {},
      this.options
    );

    console.log(res);

    console.log(`*** 4 ***`);

    const shaBaseTree = res.body.tree.sha;
    res = await github.json(
      'post',
      `/repos/${this.repository.name}/git/trees`,
      {
        tree: updates,
        base_tree: shaBaseTree
      },
      this.options
    );

    console.log(`*** 5 ***`);

    const shaNewTree = res.body.sha;
    res = await github.json(
      'post',
      `/repos/${this.repository.name}/git/commits`,
      {
        message,
        tree: shaNewTree,
        parents: [shaLatestCommit]
      },
      this.options
    );

    console.log(`*** 6 ***`);

    const shaNewCommit = res.body.sha;
    return github.json(
      'patch',
      `/repos/${this.repository.name}/git/refs/heads/${this.name}`,
      {
        sha: shaNewCommit,
        force: options.force || false
      },
      this.options
    );
  }

  content(path, options = {}) {
    return new Promise((resolve, reject) =>
      this.repository.client
        .repo(this.repository.name)
        .contents(path, (err, status, body) => {
          if (err) {
            if (options.ignoreMissing) {
              resolve('');
            } else {
              reject(new Error(`${path}: ${err}`));
            }
          } else {
            const b = Buffer.from(status.content, 'base64');
            resolve(b.toString());
          }
        })
    );
  }
}
<commit_msg>fix: commit<commit_after>import { Provider, Repository, Branch } from './repository-provider';

const github = require('github-basic');
const octonode = require('octonode');

export class GithubProvider extends Provider {
  static get repositoryClass() {
    return GithubRepository;
  }

  static get branchClass() {
    return GithubBranch;
  }

  constructor(token) {
    super();

    const client = octonode.client(token);

    Object.defineProperty(this, 'options', {
      value: {
        auth: {
          type: 'oauth',
          token
        }
      }
    });

    Object.defineProperty(this, 'client', { value: client });
  }
}

export class GithubRepository extends Repository {
  constructor(provider, name) {
    super(provider, name);
    Object.defineProperty(this, 'user', { value: name.split(/\//)[0] });
  }

  get options() {
    return this.provider.options;
  }

  async branches() {
    return new Promise((resolve, reject) => {
      this.provider.client.repo(this.name).branches((err, data) => {
        if (err) {
          reject(err);
        } else {
          data.forEach(d => {
            const b = new this.provider.constructor.branchClass(this, d.name);
            this._branches.set(b.name, b);
          });
          resolve(this._branches);
        }
      });
    });
  }

  async createBranch(name, from = 'master') {
    const res = await github.json(
      'get',
      `/repos/${this.name}/git/refs/heads/${from}`,
      {},
      this.options
    );

    const nb = await github.json(
      'post',
      `/repos/${this.name}/git/refs`,
      {
        ref: `refs/heads/${name}`,
        sha: res.body.object.sha
      },
      this.options
    );

    const b = new this.provider.constructor.branchClass(this, name);
    this._branches.set(b.name, b);
    return b;
  }

  createPullRequest(from, to, msg) {
    return github.json(
      'post',
      `/repos/${to.user}/${to.repo}/pulls`,
      {
        title: msg.title,
        body: msg.body,
        base: from.branch,
        head: to.branch
      },
      this.options
    );
  }
}

export class GithubBranch extends Branch {
  get options() {
    return this.provider.options;
  }

  async writeBlob(blob) {
    const path = blob.path.replace(/\\/g, '/').replace(/^\//, '');
    const mode = blob.mode || '100644';
    const type = blob.type || 'blob';

    const res = await github.json(
      'post',
      `/repos/${this.repository.name}/git/blobs`,
      {
        content:
          typeof blob.content === 'string'
            ? blob.content
            : blob.content.toString('base64'),
        encoding: typeof blob.content === 'string' ? 'utf-8' : 'base64'
      },
      this.options
    );

    return {
      path,
      mode,
      type,
      sha: res.body.sha
    };
  }

  async commit(message, blobs, options = {}) {
    const updates = await Promise.all(blobs.map(b => this.writeBlob(b)));

    let res = await github.json(
      'get',
      `/repos/${this.repository.name}/git/refs/heads/${this.name}`,
      {},
      this.options
    );
    const shaLatestCommit = res.body.object.sha;

    console.log(`latest commit: ${shaLatestCommit}`);

    res = await github.json(
      'get',
      `/repos/${this.repository.name}/commits/${shaLatestCommit}`,
      {},
      this.options
    );
    const shaBaseTree = res.body.commit.tree.sha;

    console.log(`base tree ${shaBaseTree}`);

    res = await github.json(
      'post',
      `/repos/${this.repository.name}/git/trees`,
      {
        tree: updates,
        base_tree: shaBaseTree
      },
      this.options
    );

    console.log(`*** 5 ***`);

    const shaNewTree = res.body.sha;
    res = await github.json(
      'post',
      `/repos/${this.repository.name}/git/commits`,
      {
        message,
        tree: shaNewTree,
        parents: [shaLatestCommit]
      },
      this.options
    );

    console.log(`*** 6 ***`);

    const shaNewCommit = res.body.sha;
    return github.json(
      'patch',
      `/repos/${this.repository.name}/git/refs/heads/${this.name}`,
      {
        sha: shaNewCommit,
        force: options.force || false
      },
      this.options
    );
  }

  content(path, options = {}) {
    return new Promise((resolve, reject) =>
      this.repository.client
        .repo(this.repository.name)
        .contents(path, (err, status, body) => {
          if (err) {
            if (options.ignoreMissing) {
              resolve('');
            } else {
              reject(new Error(`${path}: ${err}`));
            }
          } else {
            const b = Buffer.from(status.content, 'base64');
            resolve(b.toString());
          }
        })
    );
  }
}
<|endoftext|>


<commit_before>import Core from './core';
import ReferenceSearchQuery from './reference-search-query.js';

class ReferenceSearch {

  constructor() {
    this.bible = Core.getBibleData();
  }

  // Search the Bible by reference name (e.g. "1 Corinthians 13:4-7")
  search(queryStr) {

    // Build a query object containing the individual parts of the query string
    let query = new ReferenceSearchQuery(queryStr);

  }

}

export default ReferenceSearch;
<commit_msg>WIP: write search result-building logic<commit_after>import Core from './core';
import ReferenceSearchQuery from './reference-search-query.js';

class ReferenceSearch {

  constructor() {
    this.bible = Core.getBibleData();
    this.chapters = Core.getChapterData();
  }

  // Search the Bible by reference name (e.g. "1 Corinthians 13:4-7"); return a
  // list of search results as JSON
  search(queryStr) {

    const results = [];
    // Build a query object containing the individual parts of the query string
    const query = new ReferenceSearchQuery(queryStr);
    // Ensure that bible/chapter data has loaded, then proceed to search for
    // Bible references matching the given query
    Promise.all([this.bible, this.chapters]).then(([bible, chapters]) => {
      const matchingBooks = this.getBooksMatchingQuery(bible.books, query);
      if (!query.chapter) {
        query.chapter = 1;
      }
      // Temporarily make the version always the same
      const chosenVersion = bible.versions[0];
      matchingBooks.forEach((book) => {
        // Ensure that chapter numbers are not out of range
        if (query.chapter <= chapters[book.id]) {
          results.push(this.getSearchResult(book, query, chosenVersion));
        }
      });
    });

  }

  // Filter a list of Bible books to only those matching the given query book
  getBooksMatchingQuery(books, query) {
    const matchingBooks = books.filter((book) => {
      const bookName = Core.normalizeQueryStr(book.name);
      return bookName.startsWith(query.book);
    });
    return matchingBooks;
  }

  // Build the JSON for a search result
  getSearchResult(book, query, version) {

    const result = {};

    result.uid = `${book.name}.${query.chapter}`;
    result.title = `${book.name} ${query.chapter}`;
    if (query.verse) {
      result.uid += `.${query.verse}`;
      result.title += `:${query.verse}`;
    }
    if (query.endverse && query.endverse > query.verse) {
      result.uid += '-${query.endverse}';
      result.title += '-${query.endverse}';
    }
    result.uid = `${version.id}/${result.uid}`;

  }

}

export default ReferenceSearch;
<|endoftext|>


<commit_before>'use strict';

var _ = require('underscore');

var auth = require('app/util/auth');
var user_config = require('app/config/user');
var server_config = require('app/config/server');
var logger_module = require('app/util/logger');
var logger = logger_module.get('app/api/session/router_impl');

//var keys_required_for_login = [user_config.local.username_field, user_config.local.password_field];
var keys_required_for_login = [user_config.local.username_field, user_config.local.password_field];
var keys_required_for_signup = keys_required_for_login.concat(
  _.map(keys_required_for_login, function(field) { return field + '_check'; })
);

module.exports = {
  /**
   * Returns user description - assumes that the requester must be logged in to access this API endpoint
   */
  get_user: function get_user(pr, req, res, next) {
    var result = {
      local_email: req.user.local_email,
      signup_date: req.user.sq_created_at,
      facebook_email: req.user.facebook_email,
      facebook_name: req.user.facebook_name,
      twitter_username: req.user.twitter_username,
      twitter_name: req.user.twitter_name,
      google_name: req.user.google_name,
      google_email: req.user.google_email
    };
    res.status(200).send(result);
  },

  /**
   * Logs user out and destroys session (the logic for this: if they're logging out then in user's mind this session
   * is over)
   */
  logout: function logout(req, res, next) {
    req.logout();
    res.clearCookie(user_config.logged_in_cookie_name);
    req.session.destroy(function() {
      // No req.flash message because we just destroyed the session: req.flash('message', 'Logged out');
      res.redirect(server_config.util_route_success);
    });
  },

  /**
   * Initiates requests for Google authentication, using passport to redirect to Google - this API endpoint should
   * be access directly by the browser, not via AJAX
   * @type {Function}
   */
  access_google_auth: function access_google_auth(req, res, next) {
    logger.debug('exports.access_google_auth -- redir request to Google (display mode: ' + req.query.diplay + ')');
    (auth.passport.authenticate('google-access', {
      scope: ['profile', 'email'],
      display: req.query.display
    }))(req, res, next);
  },

  /**
   * Completes requests for Google authentication for account signup
   * @type {Function}
   */
  access_google_callback: auth.passport.authenticate('google-auth', {
    successRedirect: '/profile',
    failureRedirect: '/access?reason=google_declined',
    failureFlash: true
  }),

  /**
   * Initiates requests for Facebook authentication, using passport to redirect to Facebook - this API endpoint should
   * be access directly by the browser, not via AJAX
   * @type {Function}
   */
  access_facebook_auth: function access_facebook_auth(req, res, next) {
    logger.debug('exports.access_facebook_auth -- redir request to FB (display mode: ' + req.query.display + ')');
    (auth.passport.authenticate('facebook-access', {
      scope: ['public_profile', 'email'],
      display: req.query.display
    }))(req, res, next);
  },

  /**
   * Completes requests for Facebook authentication for account signup
   * @type {Function}
   */
  access_facebook_callback: auth.passport.authenticate('facebook-access', {
    successRedirect: '/profile',
    failureRedirect: '/access?reason=fb_declined',
    failureFlash: true
  }),

  /**
   * Passport.js redirects without explanation on failure, this middleware should be run first to check that the
   * fields expected by the authentication strategy for local login are present - log if not
   */
  access_local_check_login_post: auth.mw_gen.check_post_has_req_fields(keys_required_for_login),

  /**
   * Passport.js redirects without explanation on failure, this middleware should be run first to check that the
   * fields expected by the authentication strategy for local signup are present - log if not
   */
  access_local_check_login_signup: auth.mw_gen.check_post_has_req_fields(keys_required_for_signup),

  /**
   * Handles requests for local access account login
   * @type {Function}
   */
  access_local_login: auth.passport.authenticate('local-login', {
    successRedirect: server_config.util_route_success,
    failureRedirect: server_config.util_route_failure,
    failureFlash: true
  }),

  /**
   * Handles requests for local access account signup
   * @type {Function}
   */
  access_local_signup: auth.passport.authenticate('local-signup', {
    successRedirect: server_config.util_route_success,
    failureRedirect: server_config.util_route_failure,
    failureFlash: true
  }),

  /**
   * Initiates requests for Twitter authentication, using passport to redirect to Twitter - this API endpoint should
   * be access directly by the browser, not via AJAX
   * @type {Function}
   */
  access_twitter_auth: auth.passport.authenticate('twitter-access'),

  /**
   * Completes request for Twitter authentication for account signup
   * @type {Function}
   */
  access_twitter_callback: auth.passport.authenticate('twitter-access', {
    successRedirect: '/profile',
    failureRedirect: '/access?reason=twitter_declined',
    failureFlash: true
  })
};
<commit_msg>server - user router_impl - send facebook_id, twitter_id, google_id to client<commit_after>'use strict';

var _ = require('underscore');

var auth = require('app/util/auth');
var user_config = require('app/config/user');
var server_config = require('app/config/server');
var logger_module = require('app/util/logger');
var logger = logger_module.get('app/api/session/router_impl');

//var keys_required_for_login = [user_config.local.username_field, user_config.local.password_field];
var keys_required_for_login = [user_config.local.username_field, user_config.local.password_field];
var keys_required_for_signup = keys_required_for_login.concat(
  _.map(keys_required_for_login, function(field) { return field + '_check'; })
);

module.exports = {
  /**
   * Returns user description - assumes that the requester must be logged in to access this API endpoint
   */
  get_user: function get_user(pr, req, res, next) {
    var result = {
      local_email: req.user.local_email,
      signup_date: req.user.sq_created_at,
      facebook_id: req.user.facebook_id,
      facebook_email: req.user.facebook_email,
      facebook_name: req.user.facebook_name,
      twitter_id: req.user.twitter_id,
      twitter_username: req.user.twitter_username,
      twitter_name: req.user.twitter_name,
      google_name: req.user.google_name,
      google_email: req.user.google_email,
      google_id: req.user.google_id
    };
    res.status(200).send(result);
  },

  /**
   * Logs user out and destroys session (the logic for this: if they're logging out then in user's mind this session
   * is over)
   */
  logout: function logout(req, res, next) {
    req.logout();
    res.clearCookie(user_config.logged_in_cookie_name);
    req.session.destroy(function() {
      // No req.flash message because we just destroyed the session: req.flash('message', 'Logged out');
      res.redirect(server_config.util_route_success);
    });
  },

  /**
   * Initiates requests for Google authentication, using passport to redirect to Google - this API endpoint should
   * be access directly by the browser, not via AJAX
   * @type {Function}
   */
  access_google_auth: function access_google_auth(req, res, next) {
    logger.debug('exports.access_google_auth -- redir request to Google (display mode: ' + req.query.diplay + ')');
    (auth.passport.authenticate('google-access', {
      scope: ['profile', 'email'],
      display: req.query.display
    }))(req, res, next);
  },

  /**
   * Completes requests for Google authentication for account signup
   * @type {Function}
   */
  access_google_callback: auth.passport.authenticate('google-auth', {
    successRedirect: '/profile',
    failureRedirect: '/access?reason=google_declined',
    failureFlash: true
  }),

  /**
   * Initiates requests for Facebook authentication, using passport to redirect to Facebook - this API endpoint should
   * be access directly by the browser, not via AJAX
   * @type {Function}
   */
  access_facebook_auth: function access_facebook_auth(req, res, next) {
    logger.debug('exports.access_facebook_auth -- redir request to FB (display mode: ' + req.query.display + ')');
    (auth.passport.authenticate('facebook-access', {
      scope: ['public_profile', 'email'],
      display: req.query.display
    }))(req, res, next);
  },

  /**
   * Completes requests for Facebook authentication for account signup
   * @type {Function}
   */
  access_facebook_callback: auth.passport.authenticate('facebook-access', {
    successRedirect: '/profile',
    failureRedirect: '/access?reason=fb_declined',
    failureFlash: true
  }),

  /**
   * Passport.js redirects without explanation on failure, this middleware should be run first to check that the
   * fields expected by the authentication strategy for local login are present - log if not
   */
  access_local_check_login_post: auth.mw_gen.check_post_has_req_fields(keys_required_for_login),

  /**
   * Passport.js redirects without explanation on failure, this middleware should be run first to check that the
   * fields expected by the authentication strategy for local signup are present - log if not
   */
  access_local_check_login_signup: auth.mw_gen.check_post_has_req_fields(keys_required_for_signup),

  /**
   * Handles requests for local access account login
   * @type {Function}
   */
  access_local_login: auth.passport.authenticate('local-login', {
    successRedirect: server_config.util_route_success,
    failureRedirect: server_config.util_route_failure,
    failureFlash: true
  }),

  /**
   * Handles requests for local access account signup
   * @type {Function}
   */
  access_local_signup: auth.passport.authenticate('local-signup', {
    successRedirect: server_config.util_route_success,
    failureRedirect: server_config.util_route_failure,
    failureFlash: true
  }),

  /**
   * Initiates requests for Twitter authentication, using passport to redirect to Twitter - this API endpoint should
   * be access directly by the browser, not via AJAX
   * @type {Function}
   */
  access_twitter_auth: auth.passport.authenticate('twitter-access'),

  /**
   * Completes request for Twitter authentication for account signup
   * @type {Function}
   */
  access_twitter_callback: auth.passport.authenticate('twitter-access', {
    successRedirect: '/profile',
    failureRedirect: '/access?reason=twitter_declined',
    failureFlash: true
  })
};
<|endoftext|>


<commit_before>'use strict';

var
  cwd = process.cwd(),
  path = require('path'),
  DIRECTORY_SEPARATOR = path.sep;

module.exports = function ( $grunt ) {

    function _writeAliasFile ( $data ) {
      var
        _fileDest = $data.dir,
        _fileSrc = $data.full,
        _index,
        _nesting = _fileDest.length,
        _prefix = '.'
          + DIRECTORY_SEPARATOR;

      _fileDest.push( $data.base ),

      _fileDest = _prefix
        + _fileDest.join( DIRECTORY_SEPARATOR );

      if( _nesting > 0 ) {
        _prefix = '.'
          + _prefix;

        for( _index = 1; _index < _nesting; _index ++ ) {
          _prefix += _prefix;
        }
      }

      $grunt.log.writeln(
        'Create forwarding ...\r\n* From: '
          + _fileDest.cyan
          + '\r\n* To:   '
          + (
              './'
                + _fileSrc
            ).cyan
          + '\r\n'
      ),

      $grunt.file.write(
        _fileDest,
        "module.exports = require('"
          + _prefix
          + _fileSrc.replace(
              $data.ext,
              ''
            )
          + "');"
      );
    }

    return $grunt.registerMultiTask(
        'alias',
        'Create forwardings to submodules that are not located in the topmost directory',
        function aliasNpmSubmodules () {
          var
            _count = 0,
            _filesSrc = this.filesSrc,
            _options = this.options(
                {
                  'levels': 1
                }
              ),
            _levels = Number( _options.levels );

          if(
            isNaN( _levels )
              || _levels < 1
          ) {
            _levels = 1;
          }

          if( Array.isArray(_filesSrc) && _filesSrc.length > 0 ) {
            _filesSrc.forEach(
              function ( $file, $index, $files ) {
                var
                  _dir,
                  _parsedPath;

                $file = path.normalize( $file );

                if( path.isAbsolute($file) ) {
                  $file = path.relative(
                      cwd,
                      $file
                    );
                }

                _parsedPath = path.parse( $file );

                if(
                  typeof _parsedPath !== 'object'
                    || _parsedPath === null

                  ||

                  typeof _parsedPath.dir !== 'string'
                ) {
                  return;
                }

                _parsedPath.dir = _parsedPath.dir.split( DIRECTORY_SEPARATOR );

                if(
                  !Array.isArray( _dir = _parsedPath.dir )
                    || _dir.length < 1
                ) {
                  return;
                }

                _parsedPath.dir = _dir.slice(
                    _levels > _dir.length ?
                      _dir.length : _levels
                  ),

                _parsedPath.full = $file,

                _writeAliasFile(
                  _parsedPath
                ),

                _count ++;
              }
            );

            if( _count > 0 ) {
              return $grunt.log.ok(
                  'Successfully aliased '
                    + String( _count ).green
                    + ' npm module'
                    + (
                        _count === 1 ?
                          '' : 's'
                      )
                    + '.'
                );
            }
          }

          $grunt.log.error('No files were aliased');
        }
      );

  };
<commit_msg>style(src): change wording<commit_after>'use strict';

var
  cwd = process.cwd(),
  path = require('path'),
  DIRECTORY_SEPARATOR = path.sep;

module.exports = function ( $grunt ) {

    function _writeAliasFile ( $data ) {
      var
        _fileDest = $data.dir,
        _fileSrc = $data.full,
        _index,
        _nesting = _fileDest.length,
        _prefix = '.'
          + DIRECTORY_SEPARATOR;

      _fileDest.push( $data.base ),

      _fileDest = _prefix
        + _fileDest.join( DIRECTORY_SEPARATOR );

      if( _nesting > 0 ) {
        _prefix = '.'
          + _prefix;

        for( _index = 1; _index < _nesting; _index ++ ) {
          _prefix += _prefix;
        }
      }

      $grunt.log.writeln(
        'Create forwarding ...\r\n* From: '
          + _fileDest.cyan
          + '\r\n* To:   '
          + (
              './'
                + _fileSrc
            ).cyan
          + '\r\n'
      ),

      $grunt.file.write(
        _fileDest,
        "module.exports = require('"
          + _prefix
          + _fileSrc.replace(
              $data.ext,
              ''
            )
          + "');"
      );
    }

    return $grunt.registerMultiTask(
        'alias',
        'Create forwardings to submodules that are not located in the topmost directory',
        function aliasNpmSubmodules () {
          var
            _count = 0,
            _filesSrc = this.filesSrc,
            _options = this.options(
                {
                  'levels': 1
                }
              ),
            _levels = Number( _options.levels );

          if(
            isNaN( _levels )
              || _levels < 1
          ) {
            _levels = 1;
          }

          if( Array.isArray(_filesSrc) && _filesSrc.length > 0 ) {
            _filesSrc.forEach(
              function ( $file, $index, $files ) {
                var
                  _dir,
                  _parsedPath;

                $file = path.normalize( $file );

                if( path.isAbsolute($file) ) {
                  $file = path.relative(
                      cwd,
                      $file
                    );
                }

                _parsedPath = path.parse( $file );

                if(
                  typeof _parsedPath !== 'object'
                    || _parsedPath === null

                  ||

                  typeof _parsedPath.dir !== 'string'
                ) {
                  return;
                }

                _parsedPath.dir = _parsedPath.dir.split( DIRECTORY_SEPARATOR );

                if(
                  !Array.isArray( _dir = _parsedPath.dir )
                    || _dir.length < 1
                ) {
                  return;
                }

                _parsedPath.dir = _dir.slice(
                    _levels > _dir.length ?
                      _dir.length : _levels
                  ),

                _parsedPath.full = $file,

                _writeAliasFile(
                  _parsedPath
                ),

                _count ++;
              }
            );

            if( _count > 0 ) {
              return $grunt.log.ok(
                  'Successfully aliased '
                    + String( _count ).green
                    + ' npm (sub-)module'
                    + (
                        _count === 1 ?
                          '' : 's'
                      )
                    + '.'
                );
            }
          }

          $grunt.log.error('No files were aliased');
        }
      );

  };
<|endoftext|>


<commit_before>/*
 * PEG.js runtime.
 *
 * Required by all parsers generated by PEG.js.
 */

PEG = {};

(function() {

/* ===== PEG.ArrayUtils ===== */

/* Array manipulation utility functions. */

PEG.ArrayUtils = {
  map: function(array, callback) {
    var result = [];
    var length = array.length;
    for (var i = 0; i < length; i++) {
      result[i] = callback(array[i]);
    }
    return result;
  }
};

/* ===== PEG.StringUtils ===== */

/* String manipulation utility functions. */

PEG.StringUtils = {
  /*
   * Surrounds the string with quotes and escapes characters inside so that the
   * result is a valid JavaScript string.
   */
  quote: function(s) {
    /*
     * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a string
     * literal except for the closing quote character, backslash, carriage
     * return, line separator, paragraph separator, and line feed. Any character
     * may appear in the form of an escape sequence.
     */
    return '"' + s
      .replace(/\\/g, '\\\\')        // backslash
      .replace(/"/g, '\\"')          // closing quote character
      .replace(/\r/g, '\\r')         // carriage return
      .replace(/\u2028/g, '\\u2028') // line separator
      .replace(/\u2029/g, '\\u2029') // paragraph separator
      .replace(/\n/g, '\\n')         // line feed
      + '"';
  }

};

/* ===== PEG.Parser ===== */

/* Prototype of all parsers generated by PEG.js. */

PEG.Parser = function(startRule) { this._startRule = startRule; }

PEG.Parser.prototype = {
  _matchFailed: function(failure) {
    if (this._pos > this._rightmostMatchFailuresPos) {
      this._rightmostMatchFailuresPos = this._pos;
      this._rightmostMatchFailures = [];
    }
    this._rightmostMatchFailures.push(failure);
  },

  /*
   * Parses the input with a generated parser. If the parsing is successfull,
   * returns a value explicitly or implicitly specified by the grammar from
   * which the parser was generated (see |PEG.buildParser|). If the parsing is
   * unsuccessful, throws |PEG.Parser.SyntaxError| describing the error.
   */
  parse: function(input) {
    var that = this;

    function initialize() {
      that._input = input;
      that._pos = 0;
      that._rightmostMatchFailuresPos = 0;
      that._rightmostMatchFailures = [];
      that._cache = {};
    }

    function buildErrorMessage() {
      function buildExpectedFromMatchFailures(failures) {
        switch (failures.length) {
          case 0:
            return "end of input";
          case 1:
            return failures[0].toString();
          default:
            return PEG.ArrayUtils.map(
                failures.slice(0, failures.length - 1),
                function(failure) { return failure.toString(); }
              ).join(", ")
              + " or "
              + failures[failures.length - 1].toString();
        }
      }

      var expected = buildExpectedFromMatchFailures(
        that._rightmostMatchFailures
      );
      var pos = Math.max(that._pos, that._rightmostMatchFailuresPos);
      var actual = pos < that._input.length
        ? PEG.StringUtils.quote(that._input.charAt(pos))
        : "end of input";

      return "Expected " + expected + " but " + actual + " found.";
    }

    function computeErrorPosition() {
      /*
       * The first idea was to use |String.split| to break the input up to the
       * error position along newlines and derive the line and column from
       * there. However IE's |split| implementation is so broken that it was
       * enough to prevent it.
       */

      var input = that._input;
      var pos = that._rightmostMatchFailuresPos;
      var line = 1;
      var column = 1;
      var seenCR = false;

      for (var i = 0; i < pos; i++) {
        var ch = input.charAt(i);
        if (ch === "\n") {
          if (!seenCR) { line++; }
          column = 1;
          seenCR = false;
        } else if (ch === "\r" | ch === "\u2028" || ch === "\u2029") {
          line++;
          column = 1;
          seenCR = true;
        } else {
          column++;
          seenCR = false;
        }
      }

      return { line: line, column: column };
    }

    initialize();

    var initialContext = {
      reportMatchFailures: true
    };

    var result = this["_parse_" + this._startRule](initialContext);

    /*
     * The parser is now in one of the following three states:
     *
     * 1. The parser successfully parsed the whole input.
     *
     *    - |result !== null|
     *    - |that._pos === input.length|
     *    - |that._rightmostMatchFailures.length| may or may not contain
     *      something
     *
     * 2. The parser successfully parsed only a part of the input.
     *
     *    - |result !== null|
     *    - |that._pos < input.length|
     *    - |that._rightmostMatchFailures.length| may or may not contain
     *      something
     *
     * 3. The parser did not successfully parse any part of the input.
     *
     *   - |result === null|
     *   - |that._pos === 0|
     *   - |that._rightmostMatchFailures.length| contains at least one failure
     *
     * All code following this comment (including called functions) must
     * handle these states.
     */
    if (result === null || this._pos !== input.length) {
      var errorPosition = computeErrorPosition();
      throw new PEG.Parser.SyntaxError(
        errorPosition.line,
        errorPosition.column,
        buildErrorMessage()
      );
    }

    return result;
  },

  /* Returns the parser source code. */
  toSource: function() { return this._source; }
};

/* ===== PEG.Parser.LiteralMatchFailure ===== */

/* Stores information about a literal match failure. */

PEG.Parser.LiteralMatchFailure = function(value) { this._value = value; };

PEG.Parser.LiteralMatchFailure.prototype = {
  toString: function() { return PEG.StringUtils.quote(this._value); }
};

/* ===== PEG.Parser.AnyMatchFailure ===== */

/* Stores information about a failure to match a "." expression. */

PEG.Parser.AnyMatchFailure = function() {}

PEG.Parser.AnyMatchFailure.prototype = {
  toString: function() { return "any character"; }
};

/* ===== PEG.Parser.NamedRuleMatchFailure ===== */

/* Stores information about a failure to match a named rule. */

PEG.Parser.NamedRuleMatchFailure = function(displayName) {
  this._displayName = displayName;
}

PEG.Parser.NamedRuleMatchFailure.prototype = {
  toString: function() { return this._displayName; }
};

/* ===== PEG.Parser.SyntaxError ===== */

/* Thrown when a parser encounters a syntax error. */

PEG.Parser.SyntaxError = function(line, column, message) {
  this.name = "PEG.Parser.SyntaxError";
  this.line = line;
  this.column = column;
  this.message = message;
};

PEG.Parser.SyntaxError.prototype = Error.prototype;

})();
<commit_msg>Updated PEG.js to the current development snapshot.<commit_after>/*
 * PEG.js runtime.
 *
 * Required by all parsers generated by PEG.js.
 */

PEG = {};

(function() {

/* ===== PEG.ArrayUtils ===== */

/* Array manipulation utility functions. */

PEG.ArrayUtils = {
  map: function(array, callback) {
    var result = [];
    var length = array.length;
    for (var i = 0; i < length; i++) {
      result[i] = callback(array[i]);
    }
    return result;
  }
};

/* ===== PEG.StringUtils ===== */

/* String manipulation utility functions. */

PEG.StringUtils = {
  /*
   * Surrounds the string with quotes and escapes characters inside so that the
   * result is a valid JavaScript string.
   */
  quote: function(s) {
    /*
     * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a string
     * literal except for the closing quote character, backslash, carriage
     * return, line separator, paragraph separator, and line feed. Any character
     * may appear in the form of an escape sequence.
     */
    return '"' + s
      .replace(/\\/g, '\\\\')        // backslash
      .replace(/"/g, '\\"')          // closing quote character
      .replace(/\r/g, '\\r')         // carriage return
      .replace(/\u2028/g, '\\u2028') // line separator
      .replace(/\u2029/g, '\\u2029') // paragraph separator
      .replace(/\n/g, '\\n')         // line feed
      + '"';
  }

};

/* ===== PEG.Parser ===== */

/* Prototype of all parsers generated by PEG.js. */

PEG.Parser = function(startRule) { this._startRule = startRule; }

PEG.Parser.prototype = {
  _matchFailed: function(failure) {
    if (this._pos > this._rightmostMatchFailuresPos) {
      this._rightmostMatchFailuresPos = this._pos;
      this._rightmostMatchFailures = [];
    }
    this._rightmostMatchFailures.push(failure);
  },

  /*
   * Parses the input with a generated parser. If the parsing is successfull,
   * returns a value explicitly or implicitly specified by the grammar from
   * which the parser was generated (see |PEG.buildParser|). If the parsing is
   * unsuccessful, throws |PEG.Parser.SyntaxError| describing the error.
   */
  parse: function(input) {
    var that = this;

    function initialize() {
      that._input = input;
      that._pos = 0;
      that._rightmostMatchFailuresPos = 0;
      that._rightmostMatchFailures = [];
      that._cache = {};
    }

    function buildErrorMessage() {
      function buildExpectedFromMatchFailures(failures) {
        switch (failures.length) {
          case 0:
            return "end of input";
          case 1:
            return failures[0].toString();
          default:
            return PEG.ArrayUtils.map(
                failures.slice(0, failures.length - 1),
                function(failure) { return failure.toString(); }
              ).join(", ")
              + " or "
              + failures[failures.length - 1].toString();
        }
      }

      var expected = buildExpectedFromMatchFailures(
        that._rightmostMatchFailures
      );
      var pos = Math.max(that._pos, that._rightmostMatchFailuresPos);
      var actual = pos < that._input.length
        ? PEG.StringUtils.quote(that._input.charAt(pos))
        : "end of input";

      return "Expected " + expected + " but " + actual + " found.";
    }

    function computeErrorPosition() {
      /*
       * The first idea was to use |String.split| to break the input up to the
       * error position along newlines and derive the line and column from
       * there. However IE's |split| implementation is so broken that it was
       * enough to prevent it.
       */

      var input = that._input;
      var pos = that._rightmostMatchFailuresPos;
      var line = 1;
      var column = 1;
      var seenCR = false;

      for (var i = 0; i < pos; i++) {
        var ch = input.charAt(i);
        if (ch === "\n") {
          if (!seenCR) { line++; }
          column = 1;
          seenCR = false;
        } else if (ch === "\r" | ch === "\u2028" || ch === "\u2029") {
          line++;
          column = 1;
          seenCR = true;
        } else {
          column++;
          seenCR = false;
        }
      }

      return { line: line, column: column };
    }

    initialize();

    var initialContext = {
      reportMatchFailures: true
    };

    var result = this["_parse_" + this._startRule](initialContext);

    /*
     * The parser is now in one of the following three states:
     *
     * 1. The parser successfully parsed the whole input.
     *
     *    - |result !== null|
     *    - |that._pos === input.length|
     *    - |that._rightmostMatchFailures.length| may or may not contain
     *      something
     *
     * 2. The parser successfully parsed only a part of the input.
     *
     *    - |result !== null|
     *    - |that._pos < input.length|
     *    - |that._rightmostMatchFailures.length| may or may not contain
     *      something
     *
     * 3. The parser did not successfully parse any part of the input.
     *
     *   - |result === null|
     *   - |that._pos === 0|
     *   - |that._rightmostMatchFailures.length| contains at least one failure
     *
     * All code following this comment (including called functions) must
     * handle these states.
     */
    if (result === null || this._pos !== input.length) {
      var errorPosition = computeErrorPosition();
      throw new PEG.Parser.SyntaxError(
        buildErrorMessage(),
        errorPosition.line,
        errorPosition.column
      );
    }

    return result;
  },

  /* Returns the parser source code. */
  toSource: function() { return this._source; }
};

/* ===== PEG.Parser.LiteralMatchFailure ===== */

/* Stores information about a literal match failure. */

PEG.Parser.LiteralMatchFailure = function(value) { this._value = value; };

PEG.Parser.LiteralMatchFailure.prototype = {
  toString: function() { return PEG.StringUtils.quote(this._value); }
};

/* ===== PEG.Parser.AnyMatchFailure ===== */

/* Stores information about a failure to match a "." expression. */

PEG.Parser.AnyMatchFailure = function() {}

PEG.Parser.AnyMatchFailure.prototype = {
  toString: function() { return "any character"; }
};

/* ===== PEG.Parser.NamedRuleMatchFailure ===== */

/* Stores information about a failure to match a named rule. */

PEG.Parser.NamedRuleMatchFailure = function(displayName) {
  this._displayName = displayName;
}

PEG.Parser.NamedRuleMatchFailure.prototype = {
  toString: function() { return this._displayName; }
};

/* ===== PEG.Parser.SyntaxError ===== */

/* Thrown when a parser encounters a syntax error. */

PEG.Parser.SyntaxError = function(message, line, column) {
  this.name = "PEG.Parser.SyntaxError";
  this.message = message;
  this.line = line;
  this.column = column;
};

PEG.Parser.SyntaxError.prototype = Error.prototype;

})();
<|endoftext|>


<commit_before><commit_msg>Adding future class<commit_after><|endoftext|>


<commit_before><commit_msg>Don't create a split if the tab cannot be placed in the pane<commit_after><|endoftext|>


<commit_before><commit_msg>Added a return to a callback and removed a return from another. Both in the error handling.<commit_after><|endoftext|>