<commit_before>// Require Backbone, underscore, if we're on the server.
// @TODO if we use the keyword 'var' in front of Backbone, _, IE will wipe the
// globally defined Backbone and underscore leaving us with broken objects.
// This is obviously not ideal.
if (typeof require !== 'undefined') {
    Backbone = require('./backbone');
    _ = require('underscore')._;
}

/**
 * Model: Settings
 *
 * Settings model. Stores any user-specific configuration related to the app.
 */
var Settings = Backbone.Model.extend({
    /**
     * Model name used for storage.
     */
    type: 'settings',
    /**
     * Override url() method for convenience so we don't always need a
     * collection reference around for CRUD operations on a single model.
     */
    url: function() {
        return '/api/Settings/' + this.id;
    },
    /**
     * Validate settings.
     */
    validate: function(attributes) {
        if (typeof attributes.mode !== 'undefined' && attributes.mode !== 'normal' && attributes.mode !== 'minimal') {
            return 'Invalid editor mode specified.';
        }
    }
});

/**
 * Model: Stylesheet
 *
 * This model is *not* backed directly by the server.
 * It is a child model of Project and is saved serialized as part of the parent
 * Project model.
 */
var Stylesheet = Backbone.Model.extend({
    initialize: function() {
        if (!this.get('data')) {
            this.set({ 'data': '' });
        }
    },
    validate: function(attributes) {
        if (/^[a-z0-9\-_.]+$/i.test(attributes.id) === false) {
            return 'Name must contain no space and only letters, numbers, dashes, underscores and periods.';
        }
    }
});

/**
 * Collection: StylesheetList
 *
 * This collection is *not* backed directly by the server.
 * This collection is a child of the Project model. When it is updated
 * (add/remove events) it updates the attributes of its parent model as well.
 */
var StylesheetList = Backbone.Collection.extend({
    model: Stylesheet,
    initialize: function(models, options) {
        var that = this;
        this.parent = options.parent;
        this.bind('change', function() {
            this.parent.set({ 'Stylesheet': that });
            this.parent.change();
        });
        this.bind('add', function() {
            this.parent.set({ 'Stylesheet': that });
            this.parent.change();
        });
        this.bind('remove', function() {
            this.parent.set({ 'Stylesheet': that });
            this.parent.change();
        });
    }
});

/**
 * Model: Layer
 *
 * This model is *not* backed directly by the server.
 * It is a child model of Project and is saved serialized as part of the parent
 * Project model.
 */
var Layer = Backbone.Model.extend({
    // @TODO either as a feature or a bug, object attributes are not set
    // automatically when passed to the constructor. We set it manually here.
    initialize: function(attributes) {
        this.set({'Datasource': attributes.Datasource});
    },
    validate: function(attributes) {
        if (/^[a-z0-9\-_]+$/i.test(attributes.id) === false) {
            return 'ID must contain only letters, numbers, dashes, and underscores.';
        }
        if (attributes['class'] && /^[a-z0-9\-_ ]+$/i.test(attributes['class']) === false) {
            return 'Class must contain only letters, numbers, dashes, and underscores.';
        }
        if (attributes.Datasource && !attributes.Datasource.file) {
            return 'Supplying a datasource is required.';
        }
    }
});

/**
 * Collection: LayerList
 *
 * This collection is *not* backed directly by the server.
 * This collection is a child of the Project model. When it is updated
 * (add/remove events) it updates the attributes of its parent model as well.
 */
var LayerList = Backbone.Collection.extend({
    model: Layer,
    initialize: function(models, options) {
        var self = this;
        this.parent = options.parent;
        this.bind('change', function() {
            this.parent.set({ 'Layer': self });
            this.parent.change();
        });
        this.bind('add', function() {
            this.parent.set({ 'Layer': self });
            this.parent.change();
        });
        this.bind('remove', function() {
            this.parent.set({ 'Layer': self });
            this.parent.change();
        });
    }
});

/**
 * Model: LayerFields
 *
 * This is a read-only model of inspection metadata about a map layer.
 */
var LayerFields = Backbone.Model.extend({
    // @TODO either as a feature or a bug, object attributes are not set
    // automatically when passed to the constructor. We set it manually here.
    initialize: function(attributes, options) {
        this.set({'fields': attributes.fields});
        this.project = options.project;
    },
    url: function() {
        return '/' + this.project.project64({ signed: true }) + '/' + this.id;
    }
});

/**
 * Model: Project
 *
 * This model represents a single TileMill project. It is used both client-side
 * and server-side for setting defaults and handling validation.
 */
var Project = Backbone.Model.extend({
    SRS_DEFAULT: '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 '
    + '+lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs',
    STYLESHEET_DEFAULT: [{
        id: 'style.mss',
        data: 'Map {\n'
            + '  background-color: #fff;\n'
            + '}\n\n'
            + '#world {\n'
            + '  polygon-fill: #eee;\n'
            + '  line-color: #ccc;\n'
            + '  line-width: 0.5;\n'
            + '}'
    }],
    LAYER_DEFAULT: [{
        id: 'world',
        name: 'world',
        srs: '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 '
        + '+lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs',
        Datasource: {
            file: 'http://tilemill-data.s3.amazonaws.com/world_borders_merc.zip',
            type: 'shape'
        }
    }],
    /**
     * Model name used for storage.
     */
    type: 'project',
    /**
     * Custom setDefaults() method for creating a project with default layers,
     * stylesheets, etc. Note that we do not use Backbone native initialize()
     * or defaults(), both of which make default values far pervasive than the
     * expected use here.
     */
    setDefaults: function() {
        if (!this.get('srs')) {
            this.set({'srs': this.SRS_DEFAULT});
        }
        if (!this.get('Stylesheet')) {
            this.set({
                'Stylesheet': new StylesheetList(this.STYLESHEET_DEFAULT, {
                    parent: this
                })
            });
        }
        if (!this.get('Layer')) {
            this.set({
                'Layer': new LayerList(this.LAYER_DEFAULT, {
                    parent: this
                })
            });
        }
    },
    /**
     * Instantiate StylesheetList and LayerList collections from JSON lists
     * of plain JSON objects.
     */
    parse: function(response) {
        var self = this;
        response.Stylesheet = new StylesheetList(response.Stylesheet ?
                response.Stylesheet :
                [], { parent: this });
        response.Layer = new LayerList(response.Layer ?
                response.Layer : [], { parent: this });
        return response;
    },
    /**
     * Override url() method for convenience so we don't always need a
     * collection reference around for CRUD operations on a single model.
     */
    url: function() {
        return '/api/Project/' + this.id;
    },
    /**
     * Base64 encode this project's MML URL.
     */
    project64: function(options) {
        // `window.location.origin` is not available in all browsers like
        // Firefox. @TODO This approach won't allow TileMill to be installed in
        // a subdirectory. Fix.
        var url = [
            window.location.protocol,
            window.location.host].join('//') + this.url();
        if (options.signed) {
            var md5 = new MD5();
            url += '?' + md5.digest(JSON.stringify(this)).substr(0, 6);
        }
        return Base64.urlsafe_encode(url);
    },
    /**
     * Layer URL based on the model URL.
     */
    layerURL: function(options) {
        return [window.location.protocol, window.location.host].join('//')
            + '/tile/'
            + this.project64(options)
            + '/${z}/${x}/${y}.png';
    },
    /**
     * Native Backbone validation method.
     */
    validate: function(attributes) {
        // Test character set of model ID.
        if (typeof attributes.id !== 'undefined') {
            if (/^[a-z0-9\-_]+$/i.test(attributes.id) === false) {
                return 'Name must contain only letters, numbers, dashes, '
                    + 'and underscores.';
            }
        }
        // Test that there is at least one stylesheet.
        if (typeof attributes.Stylesheet !== 'undefined') {
            var stylesheet = attributes.Stylesheet instanceof StylesheetList
                ? attributes.Stylesheet.models
                : attributes.Stylesheet;
            if (stylesheet.length === 0) {
                return 'No stylesheets found.';
            }
            // Test that each stylesheet has a unique ID.
            var counts = _.reduce(_.pluck(stylesheet, 'id'), function(memo, val) {
                memo[val] = memo[val] ? memo[val] + 1 : 1;
                return memo;
            }, {});
            if (_.max(_.values(counts)) > 1) {
                return 'Stylesheet IDs must be unique.';
            }
        }
    },
    /**
     * Custom validation method that allows for asynchronous processing.
     * Expects options.success and options.error callbacks to be consistent
     * with other Backbone methods.
     */
    validateAsync: function(options) {
        // If client-side, pass-through.
        if (typeof require === 'undefined') { options.success(this, null) }

        var Step = require('step');
        var mess = require('mess');
        var that = this;
        var stylesheets = this.get('Stylesheet');
        var stylesheets = stylesheets instanceof StylesheetList
            ? stylesheets.toJSON()
            : stylesheets;

        Step(
            function() {
                var group = this.group();
                if (stylesheets.length !== 0) {
                    _.each(stylesheets, function(stylesheet) {
                        new(mess.Parser)({
                            filename: stylesheet.id
                        }).parse(stylesheet.data, function(err, tree) {
                            if (!err) {
                                try {
                                    var errors = tree.toCSS({ compress: false, returnErrors: true });
                                    if (Array.isArray(errors)) {
                                        group()(errors);
                                    }
                                    else {
                                        group()(null);
                                    }
                                } catch (e) {
                                    group()([ e ]);
                                }
                            } else {
                                group()([ err ]);
                            }
                        });
                    });
                }
                else {
                    group()('No stylesheets found.');
                }
            },
            function(err, res) {
                if (err) {
                    options.error(that, err);
                }
                else {
                    options.success(that, null);
                }
            }
        );
    }
});

/**
 * Collection: ProjectList
 *
 * Collection of project models.
 */
var ProjectList = Backbone.Collection.extend({
    model: Project,
    url: '/api/Project',
    /**
     * Model name used for storage.
     */
    type: 'project',
    comparator: function(project) {
        return project.get('id');
    }
});

/**
 * Model: ExportJob
 *
 * Job model.
 */
var ExportJob = Backbone.Model.extend({
    /**
     * Model name used for storage.
     */
    type: 'exportjob',
    initialize: function() {
        if (typeof MD5 !== 'undefined') {
            var md5 = new MD5();
            var date = new Date();
            md5.digest(JSON.stringify(this)).substr(0, 6);
            this.set({'id': md5.digest(JSON.stringify(this) + date.getTime()).substr(0, 6)});
        }
    },
    defaults: {
        'progress': 0,
        'status': 'waiting'
    }
});

/**
 * Collection: ExportJobList
 *
 * A queue of job models.
 */
var ExportJobList = Backbone.Collection.extend({
    model: ExportJob,
    url: '/api/ExportJob',
    /**
     * Model name used for storage.
     */
    type: 'exportjob'
});

if (typeof module !== 'undefined') {
    module.exports = {
        Project: Project,
        ProjectList: ProjectList,
        ExportJob: ExportJob,
        ExportJobList: ExportJobList,
        Settings: Settings
    };
}

<commit_msg>Add timestamp to Job model and comparator to job collection.<commit_after>// Require Backbone, underscore, if we're on the server.
// @TODO if we use the keyword 'var' in front of Backbone, _, IE will wipe the
// globally defined Backbone and underscore leaving us with broken objects.
// This is obviously not ideal.
if (typeof require !== 'undefined') {
    Backbone = require('./backbone');
    _ = require('underscore')._;
}

/**
 * Model: Settings
 *
 * Settings model. Stores any user-specific configuration related to the app.
 */
var Settings = Backbone.Model.extend({
    /**
     * Model name used for storage.
     */
    type: 'settings',
    /**
     * Override url() method for convenience so we don't always need a
     * collection reference around for CRUD operations on a single model.
     */
    url: function() {
        return '/api/Settings/' + this.id;
    },
    /**
     * Validate settings.
     */
    validate: function(attributes) {
        if (typeof attributes.mode !== 'undefined' && attributes.mode !== 'normal' && attributes.mode !== 'minimal') {
            return 'Invalid editor mode specified.';
        }
    }
});

/**
 * Model: Stylesheet
 *
 * This model is *not* backed directly by the server.
 * It is a child model of Project and is saved serialized as part of the parent
 * Project model.
 */
var Stylesheet = Backbone.Model.extend({
    initialize: function() {
        if (!this.get('data')) {
            this.set({ 'data': '' });
        }
    },
    validate: function(attributes) {
        if (/^[a-z0-9\-_.]+$/i.test(attributes.id) === false) {
            return 'Name must contain no space and only letters, numbers, dashes, underscores and periods.';
        }
    }
});

/**
 * Collection: StylesheetList
 *
 * This collection is *not* backed directly by the server.
 * This collection is a child of the Project model. When it is updated
 * (add/remove events) it updates the attributes of its parent model as well.
 */
var StylesheetList = Backbone.Collection.extend({
    model: Stylesheet,
    initialize: function(models, options) {
        var that = this;
        this.parent = options.parent;
        this.bind('change', function() {
            this.parent.set({ 'Stylesheet': that });
            this.parent.change();
        });
        this.bind('add', function() {
            this.parent.set({ 'Stylesheet': that });
            this.parent.change();
        });
        this.bind('remove', function() {
            this.parent.set({ 'Stylesheet': that });
            this.parent.change();
        });
    }
});

/**
 * Model: Layer
 *
 * This model is *not* backed directly by the server.
 * It is a child model of Project and is saved serialized as part of the parent
 * Project model.
 */
var Layer = Backbone.Model.extend({
    // @TODO either as a feature or a bug, object attributes are not set
    // automatically when passed to the constructor. We set it manually here.
    initialize: function(attributes) {
        this.set({'Datasource': attributes.Datasource});
    },
    validate: function(attributes) {
        if (/^[a-z0-9\-_]+$/i.test(attributes.id) === false) {
            return 'ID must contain only letters, numbers, dashes, and underscores.';
        }
        if (attributes['class'] && /^[a-z0-9\-_ ]+$/i.test(attributes['class']) === false) {
            return 'Class must contain only letters, numbers, dashes, and underscores.';
        }
        if (attributes.Datasource && !attributes.Datasource.file) {
            return 'Supplying a datasource is required.';
        }
    }
});

/**
 * Collection: LayerList
 *
 * This collection is *not* backed directly by the server.
 * This collection is a child of the Project model. When it is updated
 * (add/remove events) it updates the attributes of its parent model as well.
 */
var LayerList = Backbone.Collection.extend({
    model: Layer,
    initialize: function(models, options) {
        var self = this;
        this.parent = options.parent;
        this.bind('change', function() {
            this.parent.set({ 'Layer': self });
            this.parent.change();
        });
        this.bind('add', function() {
            this.parent.set({ 'Layer': self });
            this.parent.change();
        });
        this.bind('remove', function() {
            this.parent.set({ 'Layer': self });
            this.parent.change();
        });
    }
});

/**
 * Model: LayerFields
 *
 * This is a read-only model of inspection metadata about a map layer.
 */
var LayerFields = Backbone.Model.extend({
    // @TODO either as a feature or a bug, object attributes are not set
    // automatically when passed to the constructor. We set it manually here.
    initialize: function(attributes, options) {
        this.set({'fields': attributes.fields});
        this.project = options.project;
    },
    url: function() {
        return '/' + this.project.project64({ signed: true }) + '/' + this.id;
    }
});

/**
 * Model: Project
 *
 * This model represents a single TileMill project. It is used both client-side
 * and server-side for setting defaults and handling validation.
 */
var Project = Backbone.Model.extend({
    SRS_DEFAULT: '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 '
    + '+lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs',
    STYLESHEET_DEFAULT: [{
        id: 'style.mss',
        data: 'Map {\n'
            + '  background-color: #fff;\n'
            + '}\n\n'
            + '#world {\n'
            + '  polygon-fill: #eee;\n'
            + '  line-color: #ccc;\n'
            + '  line-width: 0.5;\n'
            + '}'
    }],
    LAYER_DEFAULT: [{
        id: 'world',
        name: 'world',
        srs: '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 '
        + '+lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs',
        Datasource: {
            file: 'http://tilemill-data.s3.amazonaws.com/world_borders_merc.zip',
            type: 'shape'
        }
    }],
    /**
     * Model name used for storage.
     */
    type: 'project',
    /**
     * Custom setDefaults() method for creating a project with default layers,
     * stylesheets, etc. Note that we do not use Backbone native initialize()
     * or defaults(), both of which make default values far pervasive than the
     * expected use here.
     */
    setDefaults: function() {
        if (!this.get('srs')) {
            this.set({'srs': this.SRS_DEFAULT});
        }
        if (!this.get('Stylesheet')) {
            this.set({
                'Stylesheet': new StylesheetList(this.STYLESHEET_DEFAULT, {
                    parent: this
                })
            });
        }
        if (!this.get('Layer')) {
            this.set({
                'Layer': new LayerList(this.LAYER_DEFAULT, {
                    parent: this
                })
            });
        }
    },
    /**
     * Instantiate StylesheetList and LayerList collections from JSON lists
     * of plain JSON objects.
     */
    parse: function(response) {
        var self = this;
        response.Stylesheet = new StylesheetList(response.Stylesheet ?
                response.Stylesheet :
                [], { parent: this });
        response.Layer = new LayerList(response.Layer ?
                response.Layer : [], { parent: this });
        return response;
    },
    /**
     * Override url() method for convenience so we don't always need a
     * collection reference around for CRUD operations on a single model.
     */
    url: function() {
        return '/api/Project/' + this.id;
    },
    /**
     * Base64 encode this project's MML URL.
     */
    project64: function(options) {
        // `window.location.origin` is not available in all browsers like
        // Firefox. @TODO This approach won't allow TileMill to be installed in
        // a subdirectory. Fix.
        var url = [
            window.location.protocol,
            window.location.host].join('//') + this.url();
        if (options.signed) {
            var md5 = new MD5();
            url += '?' + md5.digest(JSON.stringify(this)).substr(0, 6);
        }
        return Base64.urlsafe_encode(url);
    },
    /**
     * Layer URL based on the model URL.
     */
    layerURL: function(options) {
        return [window.location.protocol, window.location.host].join('//')
            + '/tile/'
            + this.project64(options)
            + '/${z}/${x}/${y}.png';
    },
    /**
     * Native Backbone validation method.
     */
    validate: function(attributes) {
        // Test character set of model ID.
        if (typeof attributes.id !== 'undefined') {
            if (/^[a-z0-9\-_]+$/i.test(attributes.id) === false) {
                return 'Name must contain only letters, numbers, dashes, '
                    + 'and underscores.';
            }
        }
        // Test that there is at least one stylesheet.
        if (typeof attributes.Stylesheet !== 'undefined') {
            var stylesheet = attributes.Stylesheet instanceof StylesheetList
                ? attributes.Stylesheet.models
                : attributes.Stylesheet;
            if (stylesheet.length === 0) {
                return 'No stylesheets found.';
            }
            // Test that each stylesheet has a unique ID.
            var counts = _.reduce(_.pluck(stylesheet, 'id'), function(memo, val) {
                memo[val] = memo[val] ? memo[val] + 1 : 1;
                return memo;
            }, {});
            if (_.max(_.values(counts)) > 1) {
                return 'Stylesheet IDs must be unique.';
            }
        }
    },
    /**
     * Custom validation method that allows for asynchronous processing.
     * Expects options.success and options.error callbacks to be consistent
     * with other Backbone methods.
     */
    validateAsync: function(options) {
        // If client-side, pass-through.
        if (typeof require === 'undefined') { options.success(this, null) }

        var Step = require('step');
        var mess = require('mess');
        var that = this;
        var stylesheets = this.get('Stylesheet');
        var stylesheets = stylesheets instanceof StylesheetList
            ? stylesheets.toJSON()
            : stylesheets;

        Step(
            function() {
                var group = this.group();
                if (stylesheets.length !== 0) {
                    _.each(stylesheets, function(stylesheet) {
                        new(mess.Parser)({
                            filename: stylesheet.id
                        }).parse(stylesheet.data, function(err, tree) {
                            if (!err) {
                                try {
                                    var errors = tree.toCSS({ compress: false, returnErrors: true });
                                    if (Array.isArray(errors)) {
                                        group()(errors);
                                    }
                                    else {
                                        group()(null);
                                    }
                                } catch (e) {
                                    group()([ e ]);
                                }
                            } else {
                                group()([ err ]);
                            }
                        });
                    });
                }
                else {
                    group()('No stylesheets found.');
                }
            },
            function(err, res) {
                if (err) {
                    options.error(that, err);
                }
                else {
                    options.success(that, null);
                }
            }
        );
    }
});

/**
 * Collection: ProjectList
 *
 * Collection of project models.
 */
var ProjectList = Backbone.Collection.extend({
    model: Project,
    url: '/api/Project',
    /**
     * Model name used for storage.
     */
    type: 'project',
    comparator: function(project) {
        return project.get('id');
    }
});

/**
 * Model: ExportJob
 *
 * Job model.
 */
var ExportJob = Backbone.Model.extend({
    /**
     * Model name used for storage.
     */
    type: 'exportjob',
    initialize: function() {
        if (typeof MD5 !== 'undefined') {
            var md5 = new MD5();
            var date = new Date();
            md5.digest(JSON.stringify(this)).substr(0, 6);
            this.set({'id': md5.digest(JSON.stringify(this) + date.getTime()).substr(0, 6)});
        }
    },
    defaults: {
        progress: 0,
        status: 'waiting',
        timestamp: new Date().getTime()
    }
});

/**
 * Collection: ExportJobList
 *
 * A queue of job models.
 */
var ExportJobList = Backbone.Collection.extend({
    model: ExportJob,
    url: '/api/ExportJob',
    /**
     * Model name used for storage.
     */
    type: 'exportjob',
    comparator: function(job) {
        return job.get('timestamp');
    }
});

if (typeof module !== 'undefined') {
    module.exports = {
        Project: Project,
        ProjectList: ProjectList,
        ExportJob: ExportJob,
        ExportJobList: ExportJobList,
        Settings: Settings
    };
}

<|endoftext|>


<commit_before>'use strict';
(function(root) {
    /****************************
     Public Constructor
     ****************************/

    function Promise(resolver) {
        var promise = new PendingPromise();
        var self = this;

        this.then = function then(onFulfilled, onRejected) {
            var deferred = createDeferred(self.constructor);
            return promise.resolve(deferred, onFulfilled, onRejected) || self;
        };

        var _reject = function reject(reason) {
            _resolve = _reject = noop;
            var p = new RejectedPromise(reason);
            promise.resolveQueued(p);
            promise = p;
        };
        var _resolve = function resolve(value) {
            var deferred = {
                promise: self,
                reject: _reject,
                resolve: function(value) {
                    var p = new FulfilledPromise(value);
                    promise.resolveQueued(p);
                    promise = p;
                }
            };
            _resolve = _reject = noop;
            doResolve(deferred, function() { return value; });
        };

        resolver(function(value) {
            _resolve(value);
        }, function(reason) {
            _reject(reason);
        });
    }

    /****************************
     Public Instance Methods
     ****************************/

    Promise.prototype.catch = function(onRejected) {
        return this.then(void 0, onRejected);
    };

    Promise.prototype.throw = function() {
        return this.catch(function(error) {
            // Defer it, so our promise doesn't catch
            // it and turn it into a rejected promise.
            defer(function() {
                throw error;
            });

            throw error;
        });
    };

    /****************************
     Public Static Methods
     ****************************/

    Promise.resolve = function resolve(value) {
        return new this(function(resolve) {
            resolve(value);
        });
    };

    Promise.reject = function reject(reason) {
        return new this(function(_, reject) {
            reject(reason);
        });
    };

    Promise.deferred = function deferred() {
        return createDeferred(this);
    };

    Promise.cast = function cast(obj) {
        if (isObject(obj) && obj.constructor === this) {
            return obj;
        }

        return new this(function(resolve) {
            resolve(obj);
        });
    };

    Promise.all = function all(promises) {
        var Constructor = this;
        return new Constructor(function(resolve, reject) {
            var l = promises.length;
            var values = Array(l);
            var resolveAfter = after(l + 1, function() {
                resolve(values);
            });
            resolveAfter();

            var promise;
            for (var i = 0; i < l; i++) {
                promise = promises[i];
                Constructor.cast(promise).then(fillSlot(values, i, resolveAfter), reject);
            }
        });
    };

    Promise.race = function race(promises) {
        var Constructor = this;
        return new Constructor(function(resolve, reject) {
            var promise;
            for (var i = 0, l = promises.length; i < l; i++) {
                promise = promises[i];
                Constructor.cast(promise).then(resolve, reject);
            }
        });
    };

    /****************************
      Private functions
     ****************************/

    function FulfilledPromise(value) {
        this.value = value;
    }
    FulfilledPromise.prototype.resolve = function(deferred, onFulfilled) {
        if (!isFunction(onFulfilled)) { return; }
        var value = this.value;

        defer(function() { doResolve(deferred, function() { return onFulfilled(value); }); });
        return deferred.promise;
    };

    function RejectedPromise(reason) {
        this.reason = reason;
    }
    RejectedPromise.prototype.resolve = function(deferred, _, onRejected) {
        if (!isFunction(onRejected)) { return; }
        var reason = this.reason;

        defer(function() { doResolve(deferred, function() { return onRejected(reason); }); });
        return deferred.promise;
    };

    function PendingPromise() {
        this.queue = [];
    }
    PendingPromise.prototype.resolve = function(deferred, onFulfilled, onRejected) {
        this.queue.push(
            deferred,
            isFunction(onFulfilled) ? onFulfilled : identity,
            isFunction(onRejected) ? onRejected : rejectIdentity
        );
        return deferred.promise;
    };
    PendingPromise.prototype.resolveQueued = function(promise) {
        var queue = this.queue;
        for (var i = 0, l = queue.length; i < l; i += 3) {
            promise.resolve(queue[i], queue[i + 1], queue[i + 2]);
        }
    };

    function noop() {}
    function identity(x) { return x; }
    function rejectIdentity(x) { throw x; }
    function isFunction(fn) {
        return typeof fn === 'function';
    }
    function isObject(obj) {
        return obj && (typeof obj === 'object' || typeof obj === 'function');
    }
    function after(times, fn) {
        return function() {
            if (--times < 1) { fn(); }
        };
    }
    function fillSlot(array, index, fn) {
        return function(value) {
            array[index] = value;
            fn();
        };
    }
    function createDeferred(Promise) {
        var deferred = {
            promise: void 0,
            resolve: void 0,
            reject: void 0
        };
        deferred.promise = new Promise(function(resolve, reject) {
            deferred.resolve = resolve;
            deferred.reject = reject;
        });
        return deferred;
    }

    var nextTick = typeof process !== 'undefined' && isFunction(process.nextTick) ? process.nextTick
        : typeof setImmediate !== 'undefined' ? setImmediate
        : function(fn) { setTimeout(fn, 1); };
    var defer = (function() {
        var queue = [];
        function flush() {
            // Do **NOT** cache queue.length.
            // Any callback in the queue can append to the queue,
            // and we want to handle them too.
            for (var i = 0; i < queue.length; i++) {
                queue[i]();
            }
            queue = [];
        }
        return function defer(fn) {
            if (queue.push(fn) === 1) {
                nextTick(flush);
            }
        };
    })();

    function doResolve(deferred, xFn) {
        var _reject = deferred.reject;
        var _resolve;
        var then;
        var x;
        try {
            x = xFn();
            if (x === deferred.promise) {
                throw new TypeError('A promise cannot be fulfilled with itself.');
            }
            if (isObject(x) && (then = x.then) && isFunction(then)) {
                _resolve = function resolvePromise(y) {
                    _resolve = _reject = noop;
                    doResolve(deferred, function() { return y; });
                };
                _reject = function rejectPromise(reason) {
                    _resolve = _reject = noop;
                    deferred.reject(reason);
                };
                then.call(
                    x,
                    function(y) { _resolve(y); },
                    function(r) { _reject(r); }
                );
            } else {
                deferred.resolve(x);
            }
        } catch (e) {
            _reject(e);
        }
    }

    if (typeof exports !== 'undefined') {
        if (typeof module !== 'undefined' && module.exports) {
            exports = module.exports = Promise;
        }
        exports.Promise = Promise;
    } else {
        root.Promise = Promise;
    }
})(this);
<commit_msg>Pass undefined to #resolve if not a function<commit_after>'use strict';
(function(root) {
    /****************************
     Public Constructor
     ****************************/

    function Promise(resolver) {
        var promise = new PendingPromise();
        var self = this;

        this.then = function then(onFulfilled, onRejected) {
            var deferred = createDeferred(self.constructor);
            return promise.resolve(
                deferred,
                isFunction(onFulfilled) ? onFulfilled : void 0,
                isFunction(onRejected) ? onRejected : void 0
            ) || self;
        };

        var _reject = function reject(reason) {
            _resolve = _reject = noop;
            var p = new RejectedPromise(reason);
            promise.resolveQueued(p);
            promise = p;
        };
        var _resolve = function resolve(value) {
            var deferred = {
                promise: self,
                reject: _reject,
                resolve: function(value) {
                    var p = new FulfilledPromise(value);
                    promise.resolveQueued(p);
                    promise = p;
                }
            };
            _resolve = _reject = noop;
            doResolve(deferred, function() { return value; });
        };

        resolver(function(value) {
            _resolve(value);
        }, function(reason) {
            _reject(reason);
        });
    }

    /****************************
     Public Instance Methods
     ****************************/

    Promise.prototype.catch = function(onRejected) {
        return this.then(void 0, onRejected);
    };

    Promise.prototype.throw = function() {
        return this.catch(function(error) {
            // Defer it, so our promise doesn't catch
            // it and turn it into a rejected promise.
            defer(function() {
                throw error;
            });

            throw error;
        });
    };

    /****************************
     Public Static Methods
     ****************************/

    Promise.resolve = function resolve(value) {
        return new this(function(resolve) {
            resolve(value);
        });
    };

    Promise.reject = function reject(reason) {
        return new this(function(_, reject) {
            reject(reason);
        });
    };

    Promise.deferred = function deferred() {
        return createDeferred(this);
    };

    Promise.cast = function cast(obj) {
        if (isObject(obj) && obj.constructor === this) {
            return obj;
        }

        return new this(function(resolve) {
            resolve(obj);
        });
    };

    Promise.all = function all(promises) {
        var Constructor = this;
        return new Constructor(function(resolve, reject) {
            var l = promises.length;
            var values = Array(l);
            var resolveAfter = after(l + 1, function() {
                resolve(values);
            });
            resolveAfter();

            var promise;
            for (var i = 0; i < l; i++) {
                promise = promises[i];
                Constructor.cast(promise).then(fillSlot(values, i, resolveAfter), reject);
            }
        });
    };

    Promise.race = function race(promises) {
        var Constructor = this;
        return new Constructor(function(resolve, reject) {
            var promise;
            for (var i = 0, l = promises.length; i < l; i++) {
                promise = promises[i];
                Constructor.cast(promise).then(resolve, reject);
            }
        });
    };

    /****************************
      Private functions
     ****************************/

    function FulfilledPromise(value) {
        this.value = value;
    }
    FulfilledPromise.prototype.resolve = function(deferred, onFulfilled) {
        if (!onFulfilled) { return; }
        var value = this.value;

        defer(function() { doResolve(deferred, function() { return onFulfilled(value); }); });
        return deferred.promise;
    };

    function RejectedPromise(reason) {
        this.reason = reason;
    }
    RejectedPromise.prototype.resolve = function(deferred, _, onRejected) {
        if (!onRejected) { return; }
        var reason = this.reason;

        defer(function() { doResolve(deferred, function() { return onRejected(reason); }); });
        return deferred.promise;
    };

    function PendingPromise() {
        this.queue = [];
    }
    PendingPromise.prototype.resolve = function(deferred, onFulfilled, onRejected) {
        this.queue.push(
            deferred,
            isFunction(onFulfilled) ? onFulfilled : identity,
            isFunction(onRejected) ? onRejected : rejectIdentity
        );
        return deferred.promise;
    };
    PendingPromise.prototype.resolveQueued = function(promise) {
        var queue = this.queue;
        for (var i = 0, l = queue.length; i < l; i += 3) {
            promise.resolve(queue[i], queue[i + 1], queue[i + 2]);
        }
    };

    function noop() {}
    function identity(x) { return x; }
    function rejectIdentity(x) { throw x; }
    function isFunction(fn) {
        return typeof fn === 'function';
    }
    function isObject(obj) {
        return obj && (typeof obj === 'object' || typeof obj === 'function');
    }
    function after(times, fn) {
        return function() {
            if (--times < 1) { fn(); }
        };
    }
    function fillSlot(array, index, fn) {
        return function(value) {
            array[index] = value;
            fn();
        };
    }
    function createDeferred(Promise) {
        var deferred = {
            promise: void 0,
            resolve: void 0,
            reject: void 0
        };
        deferred.promise = new Promise(function(resolve, reject) {
            deferred.resolve = resolve;
            deferred.reject = reject;
        });
        return deferred;
    }

    var nextTick = typeof process !== 'undefined' && isFunction(process.nextTick) ? process.nextTick
        : typeof setImmediate !== 'undefined' ? setImmediate
        : function(fn) { setTimeout(fn, 1); };
    var defer = (function() {
        var queue = [];
        function flush() {
            // Do **NOT** cache queue.length.
            // Any callback in the queue can append to the queue,
            // and we want to handle them too.
            for (var i = 0; i < queue.length; i++) {
                queue[i]();
            }
            queue = [];
        }
        return function defer(fn) {
            if (queue.push(fn) === 1) {
                nextTick(flush);
            }
        };
    })();

    function doResolve(deferred, xFn) {
        var _reject = deferred.reject;
        var _resolve;
        var then;
        var x;
        try {
            x = xFn();
            if (x === deferred.promise) {
                throw new TypeError('A promise cannot be fulfilled with itself.');
            }
            if (isObject(x) && (then = x.then) && isFunction(then)) {
                _resolve = function resolvePromise(y) {
                    _resolve = _reject = noop;
                    doResolve(deferred, function() { return y; });
                };
                _reject = function rejectPromise(reason) {
                    _resolve = _reject = noop;
                    deferred.reject(reason);
                };
                then.call(
                    x,
                    function(y) { _resolve(y); },
                    function(r) { _reject(r); }
                );
            } else {
                deferred.resolve(x);
            }
        } catch (e) {
            _reject(e);
        }
    }

    if (typeof exports !== 'undefined') {
        if (typeof module !== 'undefined' && module.exports) {
            exports = module.exports = Promise;
        }
        exports.Promise = Promise;
    } else {
        root.Promise = Promise;
    }
})(this);
<|endoftext|>


<commit_before>'use strict';

const WebMergeAPI = require('.');

function promiseFromCallback(fn) {
  return new Promise((resolve, reject) => {
    fn((err, response) => {
      if (err) return reject(err);
      return resolve(response);
    });
  });
}

class WebMergePromiseAPI extends WebMergeAPI {
  getDocuments(opts) {
    return promiseFromCallback(cb => super.getDocuments(opts, cb));
  }

  getDocument(id) {
    return promiseFromCallback(cb => super.getDocument(id, cb));
  }

  getDocumentFields(id) {
    return promiseFromCallback(cb => super.getDocumentFields(id, cb));
  }
}

module.exports = WebMergePromiseAPI;
<commit_msg>Refactor Promise API.<commit_after>'use strict';

const WebMergeAPI = require('.');

function promiseFromCallback(fn) {
  return new Promise((resolve, reject) => {
    fn((err, response) => {
      if (err) return reject(err);
      return resolve(response);
    });
  });
}

function promisify(fn, ...args) {
  return promiseFromCallback(cb => fn(...args, cb));
}

class WebMergePromiseAPI extends WebMergeAPI {
  mergeDocument(...args) {
    return promisify(super.mergeDocument, ...args);
  }

  createDocument(...args) {
    return promisify(super.createDocument, ...args);
  }

  updateDocument(...args) {
    return promisify(super.updateDocument, ...args);
  }

  getDocuments(...args) {
    return promisify(super.getDocuments, ...args);
  }

  getDocument(...args) {
    return promisify(super.getDocument, ...args);
  }

  getDocumentFields(...args) {
    return promisify(super.getDocumentFields, ...args);
  }
}

module.exports = WebMergePromiseAPI;
<|endoftext|>


<commit_before>
(function (exports) {

    var _doNotInit  = {},
        O           = Object,
        OP          = O.prototype,
        hasOwnProp  = OP.hasOwnProperty,
        propertySpecKeys = [
            "value", "get", "set", "writable", "enumerable", "configurable"
        ],
        openSpec   = {
            enumerable: true,
            configurable: true
        },
        propertySpec,
        Proteus
    ;

    function _slice () {
        var o = arguments[0] ? arguments[0] : 0;
        return Array.prototye.slice.call(arguments, o);
    }

    /**
     * @param receiver {object}
     * @param arg2..argN-1 {object} list of suppliers
     * @param argN {boolean} optional, overwrite, defaults to true
     * @returns {object} the receiver modified by supplier
     */
    function _merge (receiver /*, arg2..argN, overwrite */) {
        var len = arguments.length,
            hasOwn = hasOwnProp,
            overwrite = true,
            supplier,
            i, prop
        ;

        if (len > 2 && typeof arguments[len-1] === "boolean") {
            len -= 1;
            overwrite = arguments[len];
        }

        for (i = 1; i < len; i++) {
            supplier = arguments[i];
            for (prop in supplier) {
                if (hasOwn.call(supplier, prop) &&
                    (!hasOwn.call(receiver, prop) || overwrite)
                ) {
                    receiver[prop] = supplier[prop];
                }
            }
        }

        return receiver;
    }

    function _augment (r, s) {
        var O = O,
            p, len, i
        ;

        p = O.getOwnPropertyNames(s);
        len = p.length;
        i = 0;

        for (; i < len; i++) {
            O.defineProperty(r, p, O.getOwnPropertyDescriptor(s, p[i]));
        }

        return r;
    }

    function _isSpecLike (obj) {
        var list = propertySpecKeys,
            i = list.length,
            hasOwn = hasOwnProp,
            count = 0
        ;

        while (i--) {
            if (hasOwn.call(obj, list[i])) {
                // configurable, writable, enumerable => definitely a spec
                if (i > 2) {
                    return true;
                }
                // value, get, set => hard to tell
                else {
                    count += 1;
                }
            }
        }

        return count;
    }

    function _defineProperty (obj, name, spec) {
        O.defineProperty(obj, name, spec);
    }

    /**
     *
     * @param proto {obj} description
     * @param fn {type} description
     * @returns {type}
     */
    function _createObj (proto, fn) {
        var obj, P;

        if (!fn) {
            fn = obj;
            obj = OP;
        }

        obj = O.create(OP);
        P = O.create(Proteus, {
            proto: {value: obj},
            _super: {value: O.create(proto)}
        });

        fn.call(P, P.meta, P._super);

        return obj;
    }

    propertySpec = _merge({writable: true}, openSpec);

    function _property (obj, name, val, spec) {
        if (!spec && !val instanceof Array &&
            typeof val === "object" && _isSpecLike(val)
        ) {
            spec = val;
            val = undefined;
        }
        _defineProperty(
            obj,
            name,
            _merge({value: val}, propertySpec, spec)
        );
    }

    function _method (obj, name, fn, spec) {
        spec = typeof fn !== "function" ? fn : spec;
        _defineProperty(obj, name, _merge({value: fn}, openSpec, spec));
    }

    function _getter (obj, name, fn, spec) {
        spec = typeof fn !== "function" ? fn : spec;
        _defineProperty(
            obj,
            name,
            _merge({get: fn}, openSpec, spec)
        );
    }

    function _setter (obj, name, fn, spec) {
            spec = typeof fn !== "function" ? fn : spec;
            _defineProperty(
                obj,
                name,
                _merge({set: fn}, openSpec, spec)
            );
    }

    function _getset () {
        var len = arguments.length,
            name = arguments[1],
            getter, setter, spec
        ;

        switch (len) {
            case 4:
                getter = arguments[2];
                setter = arguments[3];
                spec = arguments[4];
                break;
            case 3:
                getter = setter = arguments[2];
                spec = arguments[3];
                break;
            case 2:
                spec = arguments[2];
                break;
        }

        spec = _merge(
            getter || setter ? {get: getter, set: setter} : {},
            openSpec,
            spec
        );

        _defineProperty(arguments[0], name, spec);
    }

    _merge(exports, {
        create: _createObj,

        define: function () {

        },

        extend: function (obj, fn) {

        }
    });
}(
    exports ? exports : (window.Protues = {})
));
<commit_msg>Getting there...<commit_after>
(function (exports) {

    var _doNotInit  = {},
        O           = Object,
        OP          = O.prototype,
        hasOwnProp  = OP.hasOwnProperty,
        propertySpecKeys = [
            "value", "get", "set", "writable", "enumerable", "configurable"
        ],
        openSpec   = {
            enumerable: true,
            configurable: true
        },
        propertySpec,
        Proteus
    ;

    function _slice () {
        var o = arguments[0] ? arguments[0] : 0;
        return Array.prototye.slice.call(arguments, o);
    }

    /**
     * @param receiver {object}
     * @param arg2..argN-1 {object} list of suppliers
     * @param argN {boolean} optional, overwrite, defaults to true
     * @returns {object} the receiver modified by supplier
     */
    function _merge (receiver /*, arg2..argN, overwrite */) {
        var len = arguments.length,
            hasOwn = hasOwnProp,
            overwrite = true,
            supplier,
            i, prop
        ;

        if (len > 2 && typeof arguments[len-1] === "boolean") {
            len -= 1;
            overwrite = arguments[len];
        }

        for (i = 1; i < len; i++) {
            supplier = arguments[i];
            for (prop in supplier) {
                if (hasOwn.call(supplier, prop) &&
                    (!hasOwn.call(receiver, prop) || overwrite)
                ) {
                    receiver[prop] = supplier[prop];
                }
            }
        }

        return receiver;
    }

    function _augment (r, s) {
        var p, len, i
        ;

        p = O.getOwnPropertyNames(s);
        len = p.length;
        i = 0;

        for (; i < len; i++) {
            O.defineProperty(r, p, O.getOwnPropertyDescriptor(s, p[i]));
        }

        return r;
    }

    function _isSpecLike (obj) {
        var list = propertySpecKeys,
            i = list.length,
            hasOwn = hasOwnProp,
            count = 0
        ;

        while (i--) {
            if (hasOwn.call(obj, list[i])) {
                // configurable, writable, enumerable => definitely a spec
                if (i > 2) {
                    return true;
                }
                // value, get, set => hard to tell
                else {
                    count += 1;
                }
            }
        }

        return count;
    }

    function _defineProperty (obj, name, spec) {
        O.defineProperty(obj, name, spec);
    }

    propertySpec = _merge({writable: true}, openSpec);

    function _makeAccessor (obj, props) {
        var accessor = {
            extend: function (obj) {

            },

            property: function (name, val, spec) {
                if (!spec && !val instanceof Array &&
                    typeof val === "object" && _isSpecLike(val)
                ) {
                    spec = val;
                    val = undefined;
                }
                _defineProperty(
                    obj,
                    name,
                    _merge({value: val}, propertySpec, spec)
                );
            },

            method: function (name, fn, spec) {
                spec = typeof fn !== "function" ? fn : spec;
                _defineProperty(obj, name, _merge({value: fn}, openSpec, spec));
            },

            getter: function (name, fn, spec) {
                spec = typeof fn !== "function" ? fn : spec;
                _defineProperty(
                    obj,
                    name,
                    _merge({get: fn}, openSpec, spec)
                );
            },

            setter: function (name, fn, spec) {
                    spec = typeof fn !== "function" ? fn : spec;
                    _defineProperty(
                        obj,
                        name,
                        _merge({set: fn}, openSpec, spec)
                    );
            },

            getset: function () {
                var len = arguments.length,
                    name = arguments[0],
                    getter, setter, spec
                ;

                switch (len) {
                    case 4:
                        getter = arguments[1];
                        setter = arguments[2];
                        spec = arguments[3];
                        break;
                    case 3:
                        getter = setter = arguments[1];
                        spec = arguments[2];
                        break;
                    case 2:
                        spec = arguments[1];
                        break;
                }

                spec = _merge(
                    getter || setter ? {get: getter, set: setter} : {},
                    openSpec,
                    spec
                );

                _defineProperty(name, spec);
            }
        };

        if (props) {
            _augment(accessor, props);
        }

        return accessor;
    }
    /**
     *
     * @param proto {obj} description
     * @param fn {type} description
     * @returns {type}
     */
    function _createObject (proto, fn) {
        var obj, meta, P;

        if (!fn) {
            fn = proto;
            proto = OP;
        }

        meta = _makeAccessor(proto);

        obj = O.create(proto);
        P = _makeAccessor(obj, O.create(OP, {
            meta: {
                get: function () {
                    return meta;
                }
            }
        }));

        fn.call(P, meta, obj, proto);

        return obj;
    }

    _merge(exports, {
        create: _createObject,

        define: function (fn) {
            var Ctor = function () {
                    var initialize = arguments[0] !== _doNotInit,
                        init = this.init
                    ;

                    if (initialize) {
                        if (init) {
                            init.apply(this, arguments);
                        }

                        if (Ctor.initialize) {
                            Ctor.initialize.call(Ctor, arguments);
                        }
                    }
                }
            ;

            Ctor.constructor = Ctor;
            Ctor.extend = this.extend;
            return _createClass(Ctor, fn);
        },

        extend: function (obj, fn) {
            var Ctor, proto;

            if (arguments.length === 2 && typeof obj === "function") {
                // constructor
                return _createClass(new obj(_doNotInit), fn);
            }
            else if (arguments.length === 1 && typeof this === "function") {
                return _createClass(new this(_doNotInit), fn);
            }
            else if (arguments.length === 1 && typeof obj === "function") {
                // extend an object of Object.prototype
                return _createObject(fn);
            }

            return _createObject(obj, fn);
        }
    });
}(
    exports ? exports : (window.Protues = {})
));
<|endoftext|>


<commit_before>var path = require('path');
var fs = require('fs');
var fileUtils = require('../utils/filepath-utils.js');

var appConfigUtils = require('../utils/module-config-init.js');

var directoriesUtil = require('../tools/directories-utils.js');

var VirtualModulePlugin;
function initVirtualModulePlugin(){
	if(!VirtualModulePlugin){
		VirtualModulePlugin = require('virtual-module-webpack-plugin');
	}
}

var isPartialView = function(name){
	return name.charAt(0) == '~';
};
var regExprFileExt = /\.ehtml$/i;

function readDir(dir, list, options){

	var files = fs.readdirSync(dir);
	var dirs = [];
	// console.log('read dir "'+dir+'" -> ', files);

	files.forEach(function(p){
		var absPath = path.join(dir, p);
		if(fileUtils.isDirectory(absPath)){
			var name = path.basename(absPath);
			var isLayout = /layouts/i.test(name);
			if(!isLayout && name){
				name = name[0].toUpperCase() + name.substring(1);
			}
			dirs.push({dir: absPath, ctrlName: name, isLayout: isLayout});
		} else {
			console.log('view-utils.addFromDirectory(): unknow file in view root path: ', absPath);
		}
	});

	// console.log('read sub-dirs -> ', dirs);
	var size = dirs.length;
	if(size > 0){
		for(var i = 0; i < size; ++i){
			readSubDir(dirs[i], list, options);
		}
	}
}

function readSubDir(dirs, list, _options){

	var dir = dirs.dir;
	var files = fs.readdirSync(dir);
	// console.log('read dir "'+dir+'" -> ', files);

	files.forEach(function(p){
		var absPath = path.join(dir, p);
		if(fileUtils.isDirectory(absPath)){
			console.log('view-utils.addFromDirectory(): invalid sub-directory in view-directory: ', absPath);
		} else if(regExprFileExt.test(absPath)) {

			var normalized = fileUtils.normalizePath(absPath);
			var fileName = path.basename(normalized).replace(/\.ehtml/i, '');
			var isLayout = dirs.isLayout;

			var isPartial = false;
			var ctrlName, viewName;
			if(isLayout && fileName){
				ctrlName = fileName[0].toUpperCase() + fileName.substring(1);
				viewName = ctrlName;
			} else {
				ctrlName = dirs.ctrlName;
				viewName = fileName;
				isPartial = isPartialView(viewName);
				if(isPartial){
					viewName = viewName.substring(1);
				}
			}

			list.push({
				id: dirs.ctrlName.toLowerCase() + '/' + fileName,
				ctrlName: ctrlName,
				viewName: viewName,
				file: normalized,
				viewImpl: isLayout? 'mmirf/layout' : isPartial? 'mmirf/partial' : 'mmirf/view',
				isLayout: isLayout,
				isPartial: isPartial
			});

		} else {
			console.log('view-utils.addFromDirectory(): unknown view template file: ', absPath);
		}
	});
	// console.log('results for dir "'+dir+'" -> ', ids, views);
}

function toAliasPath(view){
	return path.normalize(view.file);//.replace(/\.ehtml$/i, '')
}

function toAliasId(view){
	return 'mmirf/view/' + view.id;//FIXME formalize IDs for loading views in webpack (?)
}

function containsCtrl(ctrlName, ctrlList){
	return ctrlList.findIndex(function(c){
		return c.name === ctrlName;
	}) !== -1;
}

function addCtrlStub(view, ctrlList, ctrlMap){

	if(view.isLayout){
		return;
	}

	if(containsCtrl(view.ctrlName, ctrlList)){
		return;
	}

	var ctrl = ctrlMap.get(view.ctrlName);
	var isDebug = true;//DEBUG TODO make configurable/settable via options
	if(!ctrl){
		ctrl = {
			moduleName: 'mmirf/controller/'+view.ctrlName[0].toLowerCase()+view.ctrlName.substring(1),
			contents: 'function '+view.ctrlName+'(){'+(isDebug? 'console.log("created stub controller '+view.ctrlName+'");' : '')+'}; ' +
									view.ctrlName + '.prototype.on_page_load = function(){'+(isDebug? 'console.log("invoked on_page_load() on stub controller '+view.ctrlName+'");' : '')+'};' +
									// 'window.'+view.ctrlName+' = '+view.ctrlName+';' +
									'module.exports = '+view.ctrlName+';'
		};
		ctrlMap.set(view.ctrlName, ctrl);
	}
}

module.exports = {

	/**
	 * add views from a base-directory that adheres to the structure:
	 *

	 * <dir>/<controller name 1>/view1.ehtml
	 *                          /view2.ehtml
	 *                          ...
	 * <dir>/<controller name 2>/view1.ehtml
	 *                          /view2.ehtml
	 *                          ...
	 * ...
	 * <dir>/layouts/default.ehtml
	 *              /<controller name 1>.ehtml
	 *              ...
	 *

	 * @param  {String} dir the direcotry from which to parse/collect the views
	 * @param {String} appRootDir the root directory of the app (against which relative paths will be resolved)
	 * @param  {ViewOptionMap} [options] OPTIONAL
	 * 										unsupported TODO
	 * @return {Array<ViewEntry>} a list of ViewEntry objects:
	 * 									{
	 * 										id: String
	 * 										ctrlName: String,
	 * 										viewName: String,
	 * 										file: String,
	 * 										viewImpl: 'mmirf/layout' | 'mmirf/partial' | 'mmirf/view',
	 * 										isLayout: Boolean
	 * 										isPartial: Boolean
	 * 									}
	 */
	viewTemplatesFromDir: function(dir, appRootDir, options){

		if(!path.isAbsolute(dir)){
			dir = path.resolve(appRootDir, dir);
		}
		var list = [];
		readDir(dir, list, options);

		return list;
	},

	/**
	 * add views to (webpack) app build configuration
	 *
	 * @param  {Array<ViewEntry>} view list of ViewEntry objects:
	 * 										view.id {String}: the view id
	 * 										view.file {String}: the path to the eHTML view template (from which the executable view will be created)
	 * @param  {Array<ControllerEntry>} ctrls list of ControllerEntry objects:
	 * 										ctrl.id {String}: the controller id
	 * @param  {[type]} appConfig the app configuration to which the views will be added
	 * @param  {[type]} directories the directories.json representation
	 * @param  {ResourcesConfig} resources the resources configuration
	 * @param  {[type]} runtimeConfiguration the configuration.json representation
	 */
	addViewsToAppConfig: function(views, ctrls, appConfig, directories, resources, _runtimeConfiguration){

		if(!views || views.length < 1){
			return;
		}

		var stubCtrlMap = new Map();

		views.forEach(function(v){

			var aliasId = toAliasId(v);
			appConfigUtils.addIncludeModule(appConfig, aliasId, toAliasPath(v));
			directoriesUtil.addView(directories, aliasId);

			addCtrlStub(v, ctrls, stubCtrlMap);
		});

		// include dependencies for loading & rendering views:
		appConfig.includeModules.push('mmirf/storageUtils', 'mmirf/renderUtils');
		appConfig.includeModules.push('mmirf/yield', 'mmirf/layout', 'mmirf/view', 'mmirf/partial');//TODO only include types that were actually parsed

		//FIXME set simpleViewEngine TODO support setting engine via appConfig
		resources.paths['mmirf/simpleViewEngine'] = 'env/view/simpleViewEngine';

		if(!appConfig.paths){
			appConfig.paths = {};
		}

		// replace default viewLoader with webpack-viewLoader:
		appConfig.paths['mmirf/viewLoader'] = path.resolve(__dirname, '..', 'runtime', 'webpackViewLoader.js');

		// appConfig.paths['mmirf/controllerManager'] = path.resolve(__dirname, '..', 'runtime', 'webpackCtlrManager.js');
		// appConfig.paths['mmirf/viewLoader'] = path.join(path.dirname(require.resolve('mmir-lib')), 'env/view/viewLoader');

		//add generated stub controllers if necessary:
		if(stubCtrlMap.size > 0){

			initVirtualModulePlugin();

			if(!appConfig.webpackPlugins){
				appConfig.webpackPlugins = [];
			}

			stubCtrlMap.forEach(function(ctrl, name){
				var id = ctrl.moduleName;
				console.log('adding view controller stub "'+name+'": ', id, ' -> ', ctrl);//DEBUG
				// appConfig.paths[id] = id;// path.resolve('./viewParser/webpackGenCtrl.js');
				// appConfig.includeModules.push(id);
				appConfigUtils.addIncludeModule(appConfig, id, id);

				directoriesUtil.addCtrl(directories, ctrl.moduleName);
				appConfig.webpackPlugins.push(new VirtualModulePlugin(ctrl));
			});
		}
	},

	getCtrlImpl: function(){
		if(controllers.size < 1){
			return [];
		}
		var list = [];
		controllers.forEach(function(ctrl){
			list.push(ctrl)
		});
		return list;
	}
};
<commit_msg>removed unused code<commit_after>var path = require('path');
var fs = require('fs');
var fileUtils = require('../utils/filepath-utils.js');

var appConfigUtils = require('../utils/module-config-init.js');

var directoriesUtil = require('../tools/directories-utils.js');

var VirtualModulePlugin;
function initVirtualModulePlugin(){
	if(!VirtualModulePlugin){
		VirtualModulePlugin = require('virtual-module-webpack-plugin');
	}
}

var isPartialView = function(name){
	return name.charAt(0) == '~';
};
var regExprFileExt = /\.ehtml$/i;

function readDir(dir, list, options){

	var files = fs.readdirSync(dir);
	var dirs = [];
	// console.log('read dir "'+dir+'" -> ', files);

	files.forEach(function(p){
		var absPath = path.join(dir, p);
		if(fileUtils.isDirectory(absPath)){
			var name = path.basename(absPath);
			var isLayout = /layouts/i.test(name);
			if(!isLayout && name){
				name = name[0].toUpperCase() + name.substring(1);
			}
			dirs.push({dir: absPath, ctrlName: name, isLayout: isLayout});
		} else {
			console.log('view-utils.addFromDirectory(): unknow file in view root path: ', absPath);
		}
	});

	// console.log('read sub-dirs -> ', dirs);
	var size = dirs.length;
	if(size > 0){
		for(var i = 0; i < size; ++i){
			readSubDir(dirs[i], list, options);
		}
	}
}

function readSubDir(dirs, list, _options){

	var dir = dirs.dir;
	var files = fs.readdirSync(dir);
	// console.log('read dir "'+dir+'" -> ', files);

	files.forEach(function(p){
		var absPath = path.join(dir, p);
		if(fileUtils.isDirectory(absPath)){
			console.log('view-utils.addFromDirectory(): invalid sub-directory in view-directory: ', absPath);
		} else if(regExprFileExt.test(absPath)) {

			var normalized = fileUtils.normalizePath(absPath);
			var fileName = path.basename(normalized).replace(/\.ehtml/i, '');
			var isLayout = dirs.isLayout;

			var isPartial = false;
			var ctrlName, viewName;
			if(isLayout && fileName){
				ctrlName = fileName[0].toUpperCase() + fileName.substring(1);
				viewName = ctrlName;
			} else {
				ctrlName = dirs.ctrlName;
				viewName = fileName;
				isPartial = isPartialView(viewName);
				if(isPartial){
					viewName = viewName.substring(1);
				}
			}

			list.push({
				id: dirs.ctrlName.toLowerCase() + '/' + fileName,
				ctrlName: ctrlName,
				viewName: viewName,
				file: normalized,
				viewImpl: isLayout? 'mmirf/layout' : isPartial? 'mmirf/partial' : 'mmirf/view',
				isLayout: isLayout,
				isPartial: isPartial
			});

		} else {
			console.log('view-utils.addFromDirectory(): unknown view template file: ', absPath);
		}
	});
	// console.log('results for dir "'+dir+'" -> ', ids, views);
}

function toAliasPath(view){
	return path.normalize(view.file);//.replace(/\.ehtml$/i, '')
}

function toAliasId(view){
	return 'mmirf/view/' + view.id;//FIXME formalize IDs for loading views in webpack (?)
}

function containsCtrl(ctrlName, ctrlList){
	return ctrlList.findIndex(function(c){
		return c.name === ctrlName;
	}) !== -1;
}

function addCtrlStub(view, ctrlList, ctrlMap){

	if(view.isLayout){
		return;
	}

	if(containsCtrl(view.ctrlName, ctrlList)){
		return;
	}

	var ctrl = ctrlMap.get(view.ctrlName);
	var isDebug = true;//DEBUG TODO make configurable/settable via options
	if(!ctrl){
		ctrl = {
			moduleName: 'mmirf/controller/'+view.ctrlName[0].toLowerCase()+view.ctrlName.substring(1),
			contents: 'function '+view.ctrlName+'(){'+(isDebug? 'console.log("created stub controller '+view.ctrlName+'");' : '')+'}; ' +
									view.ctrlName + '.prototype.on_page_load = function(){'+(isDebug? 'console.log("invoked on_page_load() on stub controller '+view.ctrlName+'");' : '')+'};' +
									// 'window.'+view.ctrlName+' = '+view.ctrlName+';' +
									'module.exports = '+view.ctrlName+';'
		};
		ctrlMap.set(view.ctrlName, ctrl);
	}
}

module.exports = {

	/**
	 * add views from a base-directory that adheres to the structure:
	 *

	 * <dir>/<controller name 1>/view1.ehtml
	 *                          /view2.ehtml
	 *                          ...
	 * <dir>/<controller name 2>/view1.ehtml
	 *                          /view2.ehtml
	 *                          ...
	 * ...
	 * <dir>/layouts/default.ehtml
	 *              /<controller name 1>.ehtml
	 *              ...
	 *

	 * @param  {String} dir the direcotry from which to parse/collect the views
	 * @param {String} appRootDir the root directory of the app (against which relative paths will be resolved)
	 * @param  {ViewOptionMap} [options] OPTIONAL
	 * 										unsupported TODO
	 * @return {Array<ViewEntry>} a list of ViewEntry objects:
	 * 									{
	 * 										id: String
	 * 										ctrlName: String,
	 * 										viewName: String,
	 * 										file: String,
	 * 										viewImpl: 'mmirf/layout' | 'mmirf/partial' | 'mmirf/view',
	 * 										isLayout: Boolean
	 * 										isPartial: Boolean
	 * 									}
	 */
	viewTemplatesFromDir: function(dir, appRootDir, options){

		if(!path.isAbsolute(dir)){
			dir = path.resolve(appRootDir, dir);
		}
		var list = [];
		readDir(dir, list, options);

		return list;
	},

	/**
	 * add views to (webpack) app build configuration
	 *
	 * @param  {Array<ViewEntry>} view list of ViewEntry objects:
	 * 										view.id {String}: the view id
	 * 										view.file {String}: the path to the eHTML view template (from which the executable view will be created)
	 * @param  {Array<ControllerEntry>} ctrls list of ControllerEntry objects:
	 * 										ctrl.id {String}: the controller id
	 * @param  {[type]} appConfig the app configuration to which the views will be added
	 * @param  {[type]} directories the directories.json representation
	 * @param  {ResourcesConfig} resources the resources configuration
	 * @param  {[type]} runtimeConfiguration the configuration.json representation
	 */
	addViewsToAppConfig: function(views, ctrls, appConfig, directories, resources, _runtimeConfiguration){

		if(!views || views.length < 1){
			return;
		}

		var stubCtrlMap = new Map();

		views.forEach(function(v){

			var aliasId = toAliasId(v);
			appConfigUtils.addIncludeModule(appConfig, aliasId, toAliasPath(v));
			directoriesUtil.addView(directories, aliasId);

			addCtrlStub(v, ctrls, stubCtrlMap);
		});

		// include dependencies for loading & rendering views:
		appConfig.includeModules.push('mmirf/storageUtils', 'mmirf/renderUtils');
		appConfig.includeModules.push('mmirf/yield', 'mmirf/layout', 'mmirf/view', 'mmirf/partial');//TODO only include types that were actually parsed

		//FIXME set simpleViewEngine TODO support setting engine via appConfig
		resources.paths['mmirf/simpleViewEngine'] = 'env/view/simpleViewEngine';

		if(!appConfig.paths){
			appConfig.paths = {};
		}

		// replace default viewLoader with webpack-viewLoader:
		appConfig.paths['mmirf/viewLoader'] = path.resolve(__dirname, '..', 'runtime', 'webpackViewLoader.js');

		//add generated stub controllers if necessary:
		if(stubCtrlMap.size > 0){

			initVirtualModulePlugin();

			if(!appConfig.webpackPlugins){
				appConfig.webpackPlugins = [];
			}

			stubCtrlMap.forEach(function(ctrl, name){
				var id = ctrl.moduleName;
				console.log('adding view controller stub "'+name+'": ', id, ' -> ', ctrl);//DEBUG
				// appConfig.paths[id] = id;// path.resolve('./viewParser/webpackGenCtrl.js');
				// appConfig.includeModules.push(id);
				appConfigUtils.addIncludeModule(appConfig, id, id);

				directoriesUtil.addCtrl(directories, ctrl.moduleName);
				appConfig.webpackPlugins.push(new VirtualModulePlugin(ctrl));
			});
		}
	},

	getCtrlImpl: function(){
		if(controllers.size < 1){
			return [];
		}
		var list = [];
		controllers.forEach(function(ctrl){
			list.push(ctrl)
		});
		return list;
	}
};
<|endoftext|>


<commit_before>
require('html-element')
var h = require('hyperscript')

function a (href, linked, classes) {
  return h('a'+(classes || ''), {href: href}, linked)
}

function img (src, width, classes) {
  return h('img'+(classes || ''), {src: src, width: width ? width+'px' : null})
}

//okay, so funders object should also have data about the iteration.
//that is the wallet, the tasks, etc.
//we want to show the state at the top (fundedness, started, finished)
//which can also be represented within the progress bar.
//given that, it will be easy to generate the detailed progress bar.

module.exports = function (iteration) {
  var total = 0
  var funders = iteration.funders
  return h('div',
    h('h1',
      a(
        iteration.html_url,
        h('span', iteration.title)
      )
    ),

    h('h3', 'Funding', iteration.state.funded ? ' (Funded)' : ''),
    h('div', img(iteration.badge_url, null, '.badge')),
    a('bitcoin:' + iteration.wallet, 'bitcoin: '+ iteration.wallet),

    h('h3', 'Tasks', iteration.state.complete ? '(Complete)' : ''),
    h('div',
      h('ul',
        iteration.links.map(function (l) {
          var url = l.url.replace('https://api.github.com/repos', 'https://github.com')
          return h('li', a(url, url), l.closed ? h('bold',' (DONE)') : null)
        })
      )
    ),

    h('h3', 'Funders',
        ' ('+iteration.sum.toPrecision(4) +'btc, '
        + (100 * iteration.progress)
        + '% funded)'
    ),
    h('div.row',
      funders.map(function (funder) {
        total += funder.sum

        /*
        +----+
        |THMB| USERNAME   0.123
        |    |
        +----+ trx,...
        */

        return h('div.ib',
          h('div.funder',
            a(funder.html_url, img(funder.avatar_url || '/grumpy.jpg', 80), '.avatar'),
            h('div.uline.fit',
              h('span.pad10',
                h('span.i2', a(funder.html_url, funder.login)),
                h('span', funder.sum/1e8)
              )
            ),
            h('div.v1.pad10',
              funder.txs.map(function (e) {
                return h('div.sm', a('https://blockchain.info/tx/' + e.hash, e.hash.substring(0, 45)+'...'))
              })
            )
          )
        )
      })
    )
  )
}
<commit_msg>show the percent funded<commit_after>
require('html-element')
var h = require('hyperscript')

function a (href, linked, classes) {
  return h('a'+(classes || ''), {href: href}, linked)
}

function img (src, width, classes) {
  return h('img'+(classes || ''), {src: src, width: width ? width+'px' : null})
}

//okay, so funders object should also have data about the iteration.
//that is the wallet, the tasks, etc.
//we want to show the state at the top (fundedness, started, finished)
//which can also be represented within the progress bar.
//given that, it will be easy to generate the detailed progress bar.

module.exports = function (iteration) {
  var total = 0
  var funders = iteration.funders
  return h('div',
    h('h1',
      a(
        iteration.html_url,
        h('span', iteration.title)
      )
    ),

    h('h3', 'Funding', iteration.state.funded ? ' (Funded)' : ''),
    h('div', img(iteration.badge_url, null, '.badge')),
    a('bitcoin:' + iteration.wallet, 'bitcoin: '+ iteration.wallet),

    h('h3', 'Tasks', iteration.state.complete ? '(Complete)' : ''),
    h('div',
      h('ul',
        iteration.links.map(function (l) {
          var url = l.url.replace('https://api.github.com/repos', 'https://github.com')
          return h('li', a(url, url), l.closed ? h('bold',' (DONE)') : null)
        })
      )
    ),

    h('h3', 'Funders',
        ' ('+iteration.sum.toPrecision(4) +' btc, '
        + (100*iteration.progress).toPrecision(4)
        + '% funded)'
    ),
    h('div.row',
      funders.map(function (funder) {
        total += funder.sum

        /*
        +----+
        |THMB| USERNAME   0.123
        |    |
        +----+ trx,...
        */

        return h('div.ib',
          h('div.funder',
            a(funder.html_url, img(funder.avatar_url || '/grumpy.jpg', 80), '.avatar'),
            h('div.uline.fit',
              h('span.pad10',
                h('span.i2', a(funder.html_url, funder.login)),
                h('span', funder.sum/1e8)
              )
            ),
            h('div.v1.pad10',
              funder.txs.map(function (e) {
                return h('div.sm', a('https://blockchain.info/tx/' + e.hash, e.hash.substring(0, 45)+'...'))
              })
            )
          )
        )
      })
    )
  )
}
<|endoftext|>


<commit_before>/*jslint node: true */
var http = require("http");
var Promise = require("bluebird");
var cheerio = require('cheerio');
var request = require('request');
var iconv = require('iconv');
// Main modules
var TorrentParser = require('./TorrentParser'); // Return "class function" - use with `new`
var torrentTypeParser = require('./torrentTypes.js');
var uri = require('../uri');

var torrentService = (function() {
    "use strict";

    // Private

    // TODO: Cache some common results!
    // HTML parser operations are slow. Requests to zamunda.net too.
    var cache = {};

    var ZAMUNDA_URL = 'www.zamunda.net',
        ZAMUNDA_URI = 'http://www.zamunda.net';

    // Exposed

    /**
     * Get recommended torrents
     * @param  {String} cookies [Cookies for user authentication]
     * @return {Promise}         Promise that resolves with Array of torrents
     */
    var getRecommended = function getRecomenddedTorrents(cookies) {
        return new Promise(function(resolve, reject) {
            var options = {
                url: ZAMUNDA_URI + '/bananas',
                headers: {
                    cookie: cookies
                },
                encoding: 'binary'
            };

            request(options, function(err, res, body) {
                if (err) reject(err);

                body = new Buffer(body, 'binary');
                var conv = new iconv.Iconv('windows-1251', 'utf-8//IGNORE');
                var utf8_body = conv.convert(body).toString();

                var $ = cheerio.load(utf8_body);
                var torrentParser = new TorrentParser();
                var torrents = [];
                if (cookies === undefined) {
                    torrents = torrentParser.parseTable($('.test.bottom tr'));
                } else {
                    torrents = torrentParser.parseTable($('#div1 tr'));
                }
                resolve(torrents);
            });
        });
    };

    /**
     * @param  {JSON} reqData [The data sent in the request]
     * @param  {String} cookies [Cookies for specific user]
     * @return {Promise}
     */
    var search = function search(reqData, cookies) {
        return new Promise(function(resolve, reject) {
            if (typeof reqData.searchString === 'undefined') {
                reject({status: 400, error: 'reqData.searchString is not defined'});
            }
            if (typeof reqData.page !== 'number') {
                reject({status: 400, error: 'Page must be a number'});
            }
            if (reqData.page > 30000) {
                reject({status: 400, error: 'The page cannot be accessed.'});
            }

            var options = {
                url: ZAMUNDA_URI + '/bananas',
                headers: {
                    cookie: cookies
                },
                qs: {
                    search: reqData.searchString,
                    page: reqData.page || 0, // Zamunda pages start from 0
                    field: 'name'
                },
                encoding: 'binary'
            };

            request(options, function(err, res, body) {
                if (err) reject(err);

                body = new Buffer(body, 'binary');
                var conv = new iconv.Iconv('windows-1251', 'utf-8//IGNORE');
                var utf8_body = conv.convert(body).toString();

                var $ = cheerio.load(utf8_body);
                var torrentParser = new TorrentParser();
                var torrents = torrentParser.parseTable($('.test.bottom tr'));
                var pagesEl = $('a[name="position"]').parent().find('font.red');
                var pagination = torrentParser.getPagination(pagesEl);
                resolve({
                    torrents: torrents,
                    pagination: pagination
                });
            });
        });
    };

    function getTorrentDescriptionHTML(url, cookies) {
        if (!url) throw new ReferenceError('url is not defined');

        return new Promise(function(resolve, reject) {
            var options = {
                url: url,
                headers: {
                    cookie: cookies
                },
                encoding: 'binary'
            };
            request(options, function(err, res, body){
                if (err) reject(err);

                body = new Buffer(body, 'binary');
                var conv = new iconv.Iconv('windows-1251', 'utf-8//IGNORE');
                var utf8_body = conv.convert(body).toString();

                resolve(utf8_body);
            });
        });
    }

    function autoComplete(str) {
        // TODO
    }

    return {
        getRecommended: getRecommended,
        getTorrentDescriptionHTML: getTorrentDescriptionHTML,
        search: search
    };
}());

module.exports = torrentService;<commit_msg>bugfix: home page now shows torrents while the client doesn't have uid cookie instead of doesn't have any cookies<commit_after>/*jslint node: true */
var http = require("http");
var Promise = require("bluebird");
var cheerio = require('cheerio');
var request = require('request');
var iconv = require('iconv');
// Main modules
var TorrentParser = require('./TorrentParser'); // Return "class function" - use with `new`
var torrentTypeParser = require('./torrentTypes.js');
var uri = require('../uri');

var torrentService = (function() {
    "use strict";

    // Private

    // TODO: Cache some common results!
    // HTML parser operations are slow. Requests to zamunda.net too.
    var cache = {};

    var ZAMUNDA_URL = 'www.zamunda.net',
        ZAMUNDA_URI = 'http://www.zamunda.net';

    // Exposed

    /**
     * Get recommended torrents
     * @param  {String} cookies [Cookies for user authentication]
     * @return {Promise}         Promise that resolves with Array of torrents
     */
    var getRecommended = function getRecomenddedTorrents(cookies) {
        return new Promise(function(resolve, reject) {
            var options = {
                url: ZAMUNDA_URI + '/bananas',
                headers: {
                    cookie: cookies
                },
                encoding: 'binary'
            };

            request(options, function(err, res, body) {
                if (err) reject(err);

                body = new Buffer(body, 'binary');
                var conv = new iconv.Iconv('windows-1251', 'utf-8//IGNORE');
                var utf8_body = conv.convert(body).toString();

                var $ = cheerio.load(utf8_body);
                var torrentParser = new TorrentParser();
                var torrents = [];
                if (cookies.indexOf('uid=') === -1) {
                    torrents = torrentParser.parseTable($('.test.bottom tr'));
                } else {
                    torrents = torrentParser.parseTable($('#div1 tr'));
                }
                resolve(torrents);
            });
        });
    };

    /**
     * @param  {JSON} reqData [The data sent in the request]
     * @param  {String} cookies [Cookies for specific user]
     * @return {Promise}
     */
    var search = function search(reqData, cookies) {
        return new Promise(function(resolve, reject) {
            if (typeof reqData.searchString === 'undefined') {
                reject({status: 400, error: 'reqData.searchString is not defined'});
            }
            if (typeof reqData.page !== 'number') {
                reject({status: 400, error: 'Page must be a number'});
            }
            if (reqData.page > 30000) {
                reject({status: 400, error: 'The page cannot be accessed.'});
            }

            var options = {
                url: ZAMUNDA_URI + '/bananas',
                headers: {
                    cookie: cookies
                },
                qs: {
                    search: reqData.searchString,
                    page: reqData.page || 0, // Zamunda pages start from 0
                    field: 'name'
                },
                encoding: 'binary'
            };

            request(options, function(err, res, body) {
                if (err) reject(err);

                body = new Buffer(body, 'binary');
                var conv = new iconv.Iconv('windows-1251', 'utf-8//IGNORE');
                var utf8_body = conv.convert(body).toString();

                var $ = cheerio.load(utf8_body);
                var torrentParser = new TorrentParser();
                var torrents = torrentParser.parseTable($('.test.bottom tr'));
                var pagesEl = $('a[name="position"]').parent().find('font.red');
                var pagination = torrentParser.getPagination(pagesEl);
                resolve({
                    torrents: torrents,
                    pagination: pagination
                });
            });
        });
    };

    function getTorrentDescriptionHTML(url, cookies) {
        if (!url) throw new ReferenceError('url is not defined');

        return new Promise(function(resolve, reject) {
            var options = {
                url: url,
                headers: {
                    cookie: cookies
                },
                encoding: 'binary'
            };
            request(options, function(err, res, body){
                if (err) reject(err);

                body = new Buffer(body, 'binary');
                var conv = new iconv.Iconv('windows-1251', 'utf-8//IGNORE');
                var utf8_body = conv.convert(body).toString();

                resolve(utf8_body);
            });
        });
    }

    function autoComplete(str) {
        // TODO
    }

    return {
        getRecommended: getRecommended,
        getTorrentDescriptionHTML: getTorrentDescriptionHTML,
        search: search
    };
}());

module.exports = torrentService;<|endoftext|>


<commit_before>import error404 from './error404.jsx';

export default error404;
<commit_msg>Delete index.js<commit_after><|endoftext|>


<commit_before>var svgContainer = d3.select("body").append("svg")
  .attr("width", 140500)
  .attr("height", 2000);

var rectangle_elems = []
chloroplast["elements"].forEach(function(elem) {
    if (elem["rectangle"]) {
      rectangle_elems.push(elem["rectangle"]);
    }
});

var rectangles = svgContainer.selectAll("rect")
  .data(rectangle_elems)
  .enter()
  .append("rect");
  var rectangleAttributes =
                          rectangles
                          .attr("x", function (d) { return d.x; })
                          .attr("y", function (d) { return d.y; })
                          .attr("height", function (d) { return d.height; })
                          .attr("width", function (d) { return d.width; })
                          .style("fill", function(d) { return "red"; });
<commit_msg>Working on zooming in and out with label scaling<commit_after>var linearScale = d3.scale.linear()
.domain([0,100])
.range([0,10]);
var scale = d3.scale.linear()
    .domain([0,1])
    .range([150, 16]);

var svgContainer = d3.select("body").append("svg")
  .attr("width", window.innerWidth)
  .attr("height", window.innerHeight);

var rectangle_elems = []
var line_elems = []
var text_elems = []
chloroplast["elements"].forEach(function(elem) {
    if (elem["rectangle"]) {
      rectangle_elems.push(elem["rectangle"]);
    }
    if (elem["line"]) {
      line_elems.push(elem["line"]);
    }
    if (elem["text"]) {
      text_elems.push(elem["text"]);
    }
});

var lines = svgContainer.selectAll("line")
.data(line_elems)
.enter()
.append("line")

var lineAttributes = lines
.attr("x1", function (d) { return linearScale(d.x1); })
.attr("y1", function (d) { return linearScale(d.y1); })
.attr("x2", function (d) { return linearScale(d.x2); })
.attr("y2", function (d) { return linearScale(d.y2); })
.style("stroke", function(d) { return "black"; });

var rectangles = svgContainer.selectAll("rect")
.data(rectangle_elems)
.enter()
.append("rect");

var rectangleAttributes = rectangles
.attr("x", function (d) { return linearScale(d.x); })
.attr("y", function (d) { return linearScale(d.y); })
.attr("height", function (d) { return linearScale(d.height); })
.attr("width", function (d) { return linearScale(d.width); })
.style("fill", function(d) { return "red"; })

var labels = svgContainer.selectAll("text")
.data(text_elems)
.enter()
.append("text")

var labelAttributes = labels
.attr("x", function (d) { return linearScale(d.x); })
.attr("y", function (d) { return linearScale(d.y); })
.style("fill", function(d) { return "black"; })
.text(function (d) { return d.seq; });

function zoomed() {
  svgContainer.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
  labelAttributes
  .attr("y", function (d) { return linearScale(d.y) - (d3.event.scale * 20 * Math.PI); })
  .style("font-size", function () {
    var size = d3.select(this).style("font-size").replace(/px/, "");
    var increment = scale(d3.event.scale);
    if (increment <= 16) {
      return "16px";
    }
    //if (increment >= 48) {
    //  return "48px";
    //}

    return increment + "px";
  })
  .attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
  rectangleAttributes.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
  lineAttributes.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}

var zoom = d3.behavior.zoom()
.on("zoom", zoomed);

var body = d3.select("svg").call(zoom);

<|endoftext|>


<commit_before>const request = require("snekfetch");

exports.run = async (client, msg) => {
  const { facts } = await request.get("http://catfacts-api.appspot.com/api/facts").then(data => JSON.parse(data.text));
  return msg.channel.send(`📢 **Catfact:** *${facts[0]}*`);
};

exports.conf = {
  enabled: true,
  selfbot: false,
  runIn: ["text", "dm", "group"],
  aliases: ["catfact", "kittenfact"],
  permLevel: 0,
  botPerms: [],
  requiredFuncs: [],
  requiredModules: ["snekfetch"],
};

exports.help = {
  name: "catfacts",
  description: "Let me tell you a misterious cat fact.",
  usage: "",
  usageDelim: "",
  type: "commands",
};
<commit_msg>Added catfacts as the old api/endpoint was broken <commit_after>const snekfetch = require("snekfetch");

exports.run = async (client, msg) => {
  snekfetch.get("https://catfact.ninja/fact").then(res => msg.channel.send(`📢 **Catfact:** *${res.body.fact}*`));
};

exports.conf = {
  enabled: true,
  selfbot: false,
  runIn: ["text", "dm", "group"],
  aliases: ["catfact", "kittenfact"],
  permLevel: 0,
  botPerms: [],
  requiredFuncs: [],
  requiredModules: ["snekfetch"],
};

exports.help = {
  name: "catfacts",
  description: "Let me tell you a misterious cat fact.",
  usage: "",
  usageDelim: "",
  type: "commands",
};
<|endoftext|>


<commit_before>$(document).ready(function() {

    //Ladda.bind( 'input[type=submit]', { timeout: 2000 } );

    var _sidebar = $('#js_sidebar');
    var _header = $('#js_sidebar header');
    var _section = $('.main-content');

    _header.click(function() {

        if(!_sidebar.hasClass('disabled'))
        {
            _sidebar.animate({
                width: 20
            }, 100, function() {
                _sidebar.removeAttr('style');
            });
            _sidebar.addClass('disabled');
            _section.removeClass('is-open')
        }
        else
        {
            _sidebar.animate({
                width: 250
            }, 100, function() {
                // Animation complete.
                _section.addClass('is-open')
                _sidebar.removeClass('disabled');
                _sidebar.removeAttr('style');
            });
        }
    });
});<commit_msg>js changes<commit_after>$(document).ready(function() {

    //Ladda.bind( 'input[type=submit]', { timeout: 2000 } );

    var _sidebar = $('#js_sidebar');
    var _header = $('#js_sidebar header');
    var _section = $('.main-content');

    _header.click(function() {

        if(!_sidebar.hasClass('disabled'))
        {
            _sidebar.addClass('disabled');
            _section.removeClass('is-open')
        }
        else
        {
            _section.addClass('is-open')
            _sidebar.removeClass('disabled');
        }
    });
});<|endoftext|>