<commit_before>'use strict';

var swig = require('swig'),
    mongoose = require('mongoose'),
    passport = require('passport'),
    container = require('dependable').container(),
    fs = require('fs'),
    path = require('path'),
    util = require('./util'),
    EventEmitter = require('events').EventEmitter;

var events = new EventEmitter(),
    Mean, modules = [],
    menus, config,
    allMenus = [],
    middleware = {
        before: {},
        after: {}
    },
    aggregated = {
        js: '',
        css: ''
    };

function Meanio() {
    if (this.active) return;
    Mean = this;
    this.events = events;
    this.version = require('../package').version;
}

Meanio.prototype.serve = function(options, callback) {

    if (this.active) return this;

    // Initializing system variables
    var defaultConfig = util.loadConfig();

    var database = mongoose.connect(defaultConfig.db ? defaultConfig.db : '');

    // Register database dependency
    this.register('database', {
        connection: database
    });

    this.config = new Config(function(err, config) {
        // Bootstrap Models, Dependencies, Routes and the app as an express app
        var app = require('./bootstrap')(passport, database);

        // Start the app by listening on <port>, optional hostname
        app.listen(config.port, config.hostname);
        console.log('Mean app started on port ' + config.port + ' (' + process.env.NODE_ENV + ')');

        findModules(function() {
            enableModules(function() {

            });
        });
        aggregate('js', null);

        Mean.name = config.app.name;
        Mean.app = app;

        menus = new Mean.Menus();
        Mean.menus = menus;

        callback(app, config);
    });

    Mean.active = true;
    Mean.options = options;

};

Meanio.prototype.loadConfig = util.loadConfig;

function Config(callback) {

    if (this.config) return this.config;

    loadSettings(this, callback);

    function verbose() {
        return config;
    }

    function update(settings, callback) {
        var Package = loadPackageModel();

        if (!Package) return callback(true, 'failed to load data model');

        Package.findOneAndUpdate({
            name: 'config'
        }, {
            $set: {
                settings: settings,
                updated: new Date()
            }
        }, {
            upsert: true,
            multi: false
        }, function(err, doc) {
            if (err) {
                console.log(err);
                return callback(true, 'Failed to update settings');
            }

            loadSettings(Mean.config, function(err, settings) {});

            return callback(null, doc.settings);
        });
    }

    function loadSettings(Config, callback) {

        var Package = loadPackageModel();

        var defaultConfig = util.loadConfig();

        if (!Package) return defaultConfig;

        Package.findOne({
            name: 'config'
        }, function(err, doc) {

            var original = JSON.flatten(defaultConfig, {
                default: true
            });

            var saved = JSON.flatten(doc ? doc.settings : defaultConfig, {});

            var merged = mergeConfig(original, saved);

            var clean = JSON.unflatten(merged.clean, {});

            var diff = JSON.unflatten(merged.diff, {});

            Config.verbose = {
                clean: clean,
                diff: diff,
                flat: merged
            };

            Config.clean = clean;
            Config.diff = diff;
            Config.flat = merged;
            callback(err, clean);
        });
    }

    function mergeConfig(original, saved) {

        var clean = {};

        for (var index in saved) {
            clean[index] = saved[index].value;
            if (original[index]) {
                original[index].value = saved[index].value;
            } else {
                original[index] = {
                    value: saved[index].value,
                };
            }

            original[index]['default'] = original[index]['default'] || saved[index]['default'];
        }

        return {
            diff: original,
            clean: clean
        };
    }

    function loadPackageModel() {

        var database = container.get('database');
        if (!database || !database.connection) {
            return null;
        }

        if (!database.connection.models.Package) {
            require('../modules/package')(database);
        }

        return database.connection.model('Package');
    }

    this.update = update;

}

Meanio.prototype.status = function() {
    return {
        active: this.active,
        name: this.name
    };
};

Meanio.prototype.register = container.register;

Meanio.prototype.resolve = container.resolve;

//confusing names, need to be refactored asap
Meanio.prototype.load = container.get;

Meanio.prototype.moduleEnabled = function(name) {
    return modules[name] ? true : false;
};

Meanio.prototype.modules = (function() {
    return modules;
})();

Meanio.prototype.aggregated = aggregated;

Meanio.prototype.Menus = function() {
    this.add = function(options) {
        if (!Array.isArray(options)) options = [options];

        options.forEach(function(opt) {
            opt.menu = opt.menu || 'main';
            opt.roles = opt.roles || ['anonymous'];
            allMenus[opt.menu] = allMenus[opt.menu] || [];
            allMenus[opt.menu].push(opt);
        });
        return menus;
    };

    this.get = function(options) {
        var allowed = [];
        options.menu = options.menu || 'main';
        options.roles = options.roles || ['anonymous'];

        if (!allMenus[options.menu] && !options.defaultMenu) return [];

        var items = options.defaultMenu.concat(allMenus[options.menu] || []);

        items.forEach(function(item) {

            var hasRole = false;
            options.roles.forEach(function(role) {
                if (role === 'admin' || item.roles.indexOf('anonymous') !== -1 || item.roles.indexOf(role) !== -1) {
                    hasRole = true;
                }
            });

            if (hasRole) {
                allowed.push(item);
            }
        });
        return allowed;
    };
};

Meanio.prototype.Module = function(name) {
    this.name = name.toLowerCase();
    this.menus = menus;

    // bootstrap models
    util.walk(modulePath(this.name, 'server'), 'model', null, function(model) {
        require(model);
    });

    this.render = function(view, options, callback) {
        swig.renderFile(modulePath(this.name, '/server/views/' + view + '.html'), options, callback);
    };

    // bootstrap routes
    this.routes = function() {
        var args = Array.prototype.slice.call(arguments);
        var that = this;
        util.walk(modulePath(this.name, 'server'), 'route', 'middlewares', function(route) {
            require(route).apply(that, [that].concat(args));
        });
    };

    this.aggregateAsset = function(type, asset, options) {
        aggregate(type, path.join(modules[this.name].source, this.name, 'public/assets', type, asset), options);
    };

    this.register = function(callback) {
        container.register(capitaliseFirstLetter(name), callback);
    };

    this.angularDependencies = function(dependencies) {
        this.angularDependencies = dependencies;
        modules[this.name].angularDependencies = dependencies;
    };

    this.settings = function() {

        if (!arguments.length) return;

        var database = container.get('database');
        if (!database || !database.connection) {
            return {
                err: true,
                message: 'No database connection'
            };
        }

        if (!database.connection.models.Package) {
            require('../modules/package')(database);
        }

        var Package = database.connection.model('Package');
        if (arguments.length === 2) return updateSettings(this.name, arguments[0], arguments[1]);
        if (arguments.length === 1 && typeof arguments[0] === 'object') return updateSettings(this.name, arguments[0], function() {});
        if (arguments.length === 1 && typeof arguments[0] === 'function') return getSettings(this.name, arguments[0]);

        function updateSettings(name, settings, callback) {
            Package.findOneAndUpdate({
                name: name
            }, {
                $set: {
                    settings: settings,
                    updated: new Date()
                }
            }, {
                upsert: true,
                multi: false
            }, function(err, doc) {
                if (err) {
                    console.log(err);
                    return callback(true, 'Failed to update settings');
                }
                return callback(null, doc);
            });
        }

        function getSettings(name, callback) {
            Package.findOne({
                name: name
            }, function(err, doc) {
                if (err) {
                    console.log(err);
                    return callback(true, 'Failed to retrieve settings');
                }
                return callback(null, doc);
            });
        }
    };
};

function capitaliseFirstLetter(string) {
    return string.charAt(0).toUpperCase() + string.slice(1);
}

function modulePath(name, plus) {
    return path.join(process.cwd(), modules[name].source, name, plus);
}

function findModules(callback) {

    function searchSource(source, callback) {
        fs.readdir(path.join(process.cwd(), source), function(err, files) {
            if (err || !files || !files.length) {
                if (err && err.code !== 'ENOENT') console.log(err);
                return callback();
            }
            files.forEach(function(file, index) {
                fs.readFile(path.join(process.cwd(), source, file, 'package.json'), function(fileErr, data) {
                    if (err) throw fileErr;
                    if (data) {
                        try {
                            var json = JSON.parse(data.toString());
                            if (json.mean) {
                                modules[json.name] = {
                                    version: json.version,
                                    source: source
                                };
                            }
                        } catch (err) {
                            return callback();
                        }
                    }
                    if (files.length - 1 === index) return callback();
                });
            });
        });
    }

    var sources = 2;

    function searchDone() {
        sources--;
        if (!sources) {
            events.emit('modulesFound');
            callback();
        }
    }
    searchSource('node_modules', searchDone);
    searchSource('packages', searchDone);
}

function enableModules(callback) {
    var name, remaining = 0;

    for (name in modules) {
        remaining++;
        require(path.join(process.cwd(), modules[name].source, name, 'app.js'));
    }

    for (name in modules) {
        name = capitaliseFirstLetter(name);
        container.resolve.apply(container, [name]);
        container.get(name);
        remaining--;
        if (!remaining) {
            events.emit('modulesEnabled');
            callback(modules);
        }
    }
}

//will do compression and mingify/uglify soon
function aggregate(ext, aggPath, options) {
    options = options || {};

    //Allow libs
    var libs = true;
    if (aggPath) return readFile(ext, path.join(process.cwd(), aggPath));

    //this redoes all the aggregation for the extention type
    aggregated[ext] = '';

    //Deny Libs
    libs = false;
    events.on('modulesFound', function() {
        for (var name in modules) {
            readFiles(ext, path.join(process.cwd(), modules[name].source, name, 'public'));
        }
    });

    function readFiles(ext, filepath) {
        fs.readdir(filepath, function(err, files) {
            if (err) return;
            files.forEach(function(file) {
                if (!libs && file !== 'assets') {
                    readFile(ext, path.join(filepath, file));
                }
            });
        });
    }

    function readFile(ext, filepath) {
        fs.readdir(filepath, function(err, files) {
            if (files) return readFiles(ext, filepath);
            if (path.extname(filepath) !== '.' + ext) return;
            fs.readFile(filepath, function(fileErr, data) {
                //add some exists and refactor
                //if (fileErr) console.log(fileErr)

                if (!data) {
                    readFiles(ext, filepath);
                } else {
                    aggregated[ext] += (ext === 'js' && !options.global) ? ('(function(){' + data.toString() + '})();') : data.toString() + '\n';
                }
            });
        });
    }
}

Meanio.prototype.chainware = {

    add: function(event, weight, func) {
        middleware[event].splice(weight, 0, {
            weight: weight,
            func: func
        });
        middleware[event].join();
        middleware[event].sort(function(a, b) {
            if (a.weight < b.weight) {
                a.next = b.func;
            } else {
                b.next = a.func;
            }
            return (a.weight - b.weight);
        });
    },

    before: function(req, res, next) {
        if (!middleware.before.length) return next();
        this.chain('before', 0, req, res, next);
    },

    after: function(req, res, next) {
        if (!middleware.after.length) return next();
        this.chain('after', 0, req, res, next);
    },

    chain: function(operator, index, req, res, next) {
        var args = [req, res,
            function() {
                if (middleware[operator][index + 1]) {
                    this.chain('before', index + 1, req, res, next);
                } else {
                    next();
                }
            }
        ];

        middleware[operator][index].func.apply(this, args);
    }
};

module.exports = exports = new Meanio();
<commit_msg>allow absolute path in assets options<commit_after>'use strict';

var swig = require('swig'),
    mongoose = require('mongoose'),
    passport = require('passport'),
    container = require('dependable').container(),
    fs = require('fs'),
    path = require('path'),
    util = require('./util'),
    EventEmitter = require('events').EventEmitter;

var events = new EventEmitter(),
    Mean, modules = [],
    menus, config,
    allMenus = [],
    middleware = {
        before: {},
        after: {}
    },
    aggregated = {
        js: '',
        css: ''
    };

function Meanio() {
    if (this.active) return;
    Mean = this;
    this.events = events;
    this.version = require('../package').version;
}

Meanio.prototype.serve = function(options, callback) {

    if (this.active) return this;

    // Initializing system variables
    var defaultConfig = util.loadConfig();

    var database = mongoose.connect(defaultConfig.db ? defaultConfig.db : '');

    // Register database dependency
    this.register('database', {
        connection: database
    });

    this.config = new Config(function(err, config) {
        // Bootstrap Models, Dependencies, Routes and the app as an express app
        var app = require('./bootstrap')(passport, database);

        // Start the app by listening on <port>, optional hostname
        app.listen(config.port, config.hostname);
        console.log('Mean app started on port ' + config.port + ' (' + process.env.NODE_ENV + ')');

        findModules(function() {
            enableModules(function() {

            });
        });
        aggregate('js', null);

        Mean.name = config.app.name;
        Mean.app = app;

        menus = new Mean.Menus();
        Mean.menus = menus;

        callback(app, config);
    });

    Mean.active = true;
    Mean.options = options;

};

Meanio.prototype.loadConfig = util.loadConfig;

function Config(callback) {

    if (this.config) return this.config;

    loadSettings(this, callback);

    function update(settings, callback) {

        var Package = loadPackageModel();

        if (!Package) return callback(true, 'failed to load data model');

        Package.findOneAndUpdate({
            name: 'config'
        }, {
            $set: {
                settings: settings,
                updated: new Date()
            }
        }, {
            upsert: true,
            multi: false
        }, function(err, doc) {
            if (err) {
                console.log(err);
                return callback(true, 'Failed to update settings');
            }

            loadSettings(Mean.config, function(err, settings) {});

            return callback(null, doc.settings);
        });
    }

    function loadSettings(Config, callback) {

        var Package = loadPackageModel();

        var defaultConfig = util.loadConfig();

        if (!Package) return defaultConfig;

        Package.findOne({
            name: 'config'
        }, function(err, doc) {

            var original = JSON.flatten(defaultConfig, {
                default: true
            });

            var saved = JSON.flatten(doc ? doc.settings : defaultConfig, {});

            var merged = mergeConfig(original, saved);

            var clean = JSON.unflatten(merged.clean, {});

            var diff = JSON.unflatten(merged.diff, {});

            Config.verbose = {
                clean: clean,
                diff: diff,
                flat: merged
            };

            Config.clean = clean;
            Config.diff = diff;
            Config.flat = merged;
            callback(err, clean);
        });
    }

    function mergeConfig(original, saved) {

        var clean = {};

        for (var index in saved) {
            clean[index] = saved[index].value;
            if (original[index]) {
                original[index].value = saved[index].value;
            } else {
                original[index] = {
                    value: saved[index].value,
                };
            }

            original[index]['default'] = original[index]['default'] || saved[index]['default'];
        }

        return {
            diff: original,
            clean: clean
        };
    }

    function loadPackageModel() {

        var database = container.get('database');
        if (!database || !database.connection) {
            return null;
        }

        if (!database.connection.models.Package) {
            require('../modules/package')(database);
        }

        return database.connection.model('Package');
    }

    this.update = update;

}

Meanio.prototype.status = function() {
    return {
        active: this.active,
        name: this.name
    };
};

Meanio.prototype.register = container.register;

Meanio.prototype.resolve = container.resolve;

//confusing names, need to be refactored asap
Meanio.prototype.load = container.get;

Meanio.prototype.moduleEnabled = function(name) {
    return modules[name] ? true : false;
};

Meanio.prototype.modules = (function() {
    return modules;
})();

Meanio.prototype.aggregated = aggregated;

Meanio.prototype.Menus = function() {
    this.add = function(options) {
        if (!Array.isArray(options)) options = [options];

        options.forEach(function(opt) {
            opt.menu = opt.menu || 'main';
            opt.roles = opt.roles || ['anonymous'];
            allMenus[opt.menu] = allMenus[opt.menu] || [];
            allMenus[opt.menu].push(opt);
        });
        return menus;
    };

    this.get = function(options) {
        var allowed = [];
        options.menu = options.menu || 'main';
        options.roles = options.roles || ['anonymous'];

        if (!allMenus[options.menu] && !options.defaultMenu) return [];

        var items = options.defaultMenu.concat(allMenus[options.menu] || []);

        items.forEach(function(item) {

            var hasRole = false;
            options.roles.forEach(function(role) {
                if (role === 'admin' || item.roles.indexOf('anonymous') !== -1 || item.roles.indexOf(role) !== -1) {
                    hasRole = true;
                }
            });

            if (hasRole) {
                allowed.push(item);
            }
        });
        return allowed;
    };
};

Meanio.prototype.Module = function(name) {
    this.name = name.toLowerCase();
    this.menus = menus;

    // bootstrap models
    util.walk(modulePath(this.name, 'server'), 'model', null, function(model) {
        require(model);
    });

    this.render = function(view, options, callback) {
        swig.renderFile(modulePath(this.name, '/server/views/' + view + '.html'), options, callback);
    };

    // bootstrap routes
    this.routes = function() {
        var args = Array.prototype.slice.call(arguments);
        var that = this;
        util.walk(modulePath(this.name, 'server'), 'route', 'middlewares', function(route) {
            require(route).apply(that, [that].concat(args));
        });
    };

    this.aggregateAsset = function(type, asset, options) {
        aggregate(type, (options && options.absolute ? asset : path.join(modules[this.name].source, this.name, 'public/assets', type, asset)), options);
    };

    this.register = function(callback) {
        container.register(capitaliseFirstLetter(name), callback);
    };

    this.angularDependencies = function(dependencies) {
        this.angularDependencies = dependencies;
        modules[this.name].angularDependencies = dependencies;
    };

    this.settings = function() {

        if (!arguments.length) return;

        var database = container.get('database');
        if (!database || !database.connection) {
            return {
                err: true,
                message: 'No database connection'
            };
        }

        if (!database.connection.models.Package) {
            require('../modules/package')(database);
        }

        var Package = database.connection.model('Package');
        if (arguments.length === 2) return updateSettings(this.name, arguments[0], arguments[1]);
        if (arguments.length === 1 && typeof arguments[0] === 'object') return updateSettings(this.name, arguments[0], function() {});
        if (arguments.length === 1 && typeof arguments[0] === 'function') return getSettings(this.name, arguments[0]);

        function updateSettings(name, settings, callback) {
            Package.findOneAndUpdate({
                name: name
            }, {
                $set: {
                    settings: settings,
                    updated: new Date()
                }
            }, {
                upsert: true,
                multi: false
            }, function(err, doc) {
                if (err) {
                    console.log(err);
                    return callback(true, 'Failed to update settings');
                }
                return callback(null, doc);
            });
        }

        function getSettings(name, callback) {
            Package.findOne({
                name: name
            }, function(err, doc) {
                if (err) {
                    console.log(err);
                    return callback(true, 'Failed to retrieve settings');
                }
                return callback(null, doc);
            });
        }
    };
};

function capitaliseFirstLetter(string) {
    return string.charAt(0).toUpperCase() + string.slice(1);
}

function modulePath(name, plus) {
    return path.join(process.cwd(), modules[name].source, name, plus);
}

function findModules(callback) {

    function searchSource(source, callback) {
        fs.readdir(path.join(process.cwd(), source), function(err, files) {
            if (err || !files || !files.length) {
                if (err && err.code !== 'ENOENT') console.log(err);
                return callback();
            }
            files.forEach(function(file, index) {
                fs.readFile(path.join(process.cwd(), source, file, 'package.json'), function(fileErr, data) {
                    if (err) throw fileErr;
                    if (data) {
                        try {
                            var json = JSON.parse(data.toString());
                            if (json.mean) {
                                modules[json.name] = {
                                    version: json.version,
                                    source: source
                                };
                            }
                        } catch (err) {
                            return callback();
                        }
                    }
                    if (files.length - 1 === index) return callback();
                });
            });
        });
    }

    var sources = 2;

    function searchDone() {
        sources--;
        if (!sources) {
            events.emit('modulesFound');
            callback();
        }
    }
    searchSource('node_modules', searchDone);
    searchSource('packages', searchDone);
}

function enableModules(callback) {
    var name, remaining = 0;

    for (name in modules) {
        remaining++;
        require(path.join(process.cwd(), modules[name].source, name, 'app.js'));
    }

    for (name in modules) {
        name = capitaliseFirstLetter(name);
        container.resolve.apply(container, [name]);
        container.get(name);
        remaining--;
        if (!remaining) {
            events.emit('modulesEnabled');
            callback(modules);
        }
    }
}

//will do compression and mingify/uglify soon
function aggregate(ext, aggPath, options) {
    options = options || {};

    //Allow libs
    var libs = true;
    if (aggPath) return readFile(ext, path.join(process.cwd(), aggPath));

    //this redoes all the aggregation for the extention type
    aggregated[ext] = '';

    //Deny Libs
    libs = false;
    events.on('modulesFound', function() {
        for (var name in modules) {
            readFiles(ext, path.join(process.cwd(), modules[name].source, name, 'public'));
        }
    });

    function readFiles(ext, filepath) {
        fs.readdir(filepath, function(err, files) {
            if (err) return;
            files.forEach(function(file) {
                if (!libs && file !== 'assets') {
                    readFile(ext, path.join(filepath, file));
                }
            });
        });
    }

    function readFile(ext, filepath) {
        fs.readdir(filepath, function(err, files) {
            if (files) return readFiles(ext, filepath);
            if (path.extname(filepath) !== '.' + ext) return;
            fs.readFile(filepath, function(fileErr, data) {
                //add some exists and refactor
                //if (fileErr) console.log(fileErr)

                if (!data) {
                    readFiles(ext, filepath);
                } else {
                    aggregated[ext] += (ext === 'js' && !options.global) ? ('(function(){' + data.toString() + '})();') : data.toString() + '\n';
                }
            });
        });
    }
}

Meanio.prototype.chainware = {

    add: function(event, weight, func) {
        middleware[event].splice(weight, 0, {
            weight: weight,
            func: func
        });
        middleware[event].join();
        middleware[event].sort(function(a, b) {
            if (a.weight < b.weight) {
                a.next = b.func;
            } else {
                b.next = a.func;
            }
            return (a.weight - b.weight);
        });
    },

    before: function(req, res, next) {
        if (!middleware.before.length) return next();
        this.chain('before', 0, req, res, next);
    },

    after: function(req, res, next) {
        if (!middleware.after.length) return next();
        this.chain('after', 0, req, res, next);
    },

    chain: function(operator, index, req, res, next) {
        var args = [req, res,
            function() {
                if (middleware[operator][index + 1]) {
                    this.chain('before', index + 1, req, res, next);
                } else {
                    next();
                }
            }
        ];

        middleware[operator][index].func.apply(this, args);
    }
};

module.exports = exports = new Meanio();
<|endoftext|>


<commit_before>/******** Project - Final *********************************
Authors: Eric Wooley, Tandra Felly, Lauryn Loudermilk
Description: Javascript automata engine.
**********************************************************/

function changeCursor(id){
	var elem = document.getElementById("main");
	switch(id)
	{
		case "draw":
			elem.style.cursor = "move";
			touch_layer.show();
			dfa_layer.setDraggable(false);
			draw();
			break;
		case "move":
			elem.style.cursor = "move";
			touch_layer.hide();
			dfa_layer.setDraggable(true);
			move();
			break;
		case "remove":
			touch_layer.hide();
			elem.style.cursor = "not-allowed";
			remove();
			break;
		case "rename":
			touch_layer.hide();
			elem.style.cursor = "text";
			rename();
			break;
		case "clear":
			clearscreen();
			getElementById("draw").
			break;
		default:
			alert("this button has no purpose");
	}
}

function move(){
	//ondragstart or ondrag
	alert("i made it")
	whiteboard.on('dblclick', function (e) {
		alert("here")
        var mousePos = stage.getMousePosition();
        var x = mousePos.x;
        var y = mousePos.y;
    });
}

function delete(){

}

function rename(){

}

function clearscreen(){

	var answer = confirm("Are you sure you want to clear the screen?")
	if (answer){

       // This will remove the states and transition lines on the dfa layer
       dfa_layer.destroyChildren()

       // This will remove the labels on the transitions that are put on the tooltip layer
       tooltip_layer.destroyChildren()
	}
	else{
        return
	}

}<commit_msg>left a stray delete<commit_after>/******** Project - Final *********************************
Authors: Eric Wooley, Tandra Felly, Lauryn Loudermilk
Description: Javascript automata engine.
**********************************************************/

function changeCursor(id){
	var elem = document.getElementById("main");
	switch(id)
	{
		case "draw":
			elem.style.cursor = "move";
			touch_layer.show();
			dfa_layer.setDraggable(false);
			draw();
			break;
		case "move":
			elem.style.cursor = "move";
			touch_layer.hide();
			dfa_layer.setDraggable(true);
			move();
			break;
		case "remove":
			touch_layer.hide();
			elem.style.cursor = "not-allowed";
			remove();
			break;
		case "rename":
			touch_layer.hide();
			elem.style.cursor = "text";
			rename();
			break;
		case "clear":
			clearscreen();
			getElementById("draw").
			break;
		default:
			alert("this button has no purpose");
	}
}

function move(){
	//ondragstart or ondrag
	alert("i made it")
	whiteboard.on('dblclick', function (e) {
		alert("here")
        var mousePos = stage.getMousePosition();
        var x = mousePos.x;
        var y = mousePos.y;
    });
}

function remove(){

}

function rename(){

}

function clearscreen(){

	var answer = confirm("Are you sure you want to clear the screen?")
	if (answer){

       // This will remove the states and transition lines on the dfa layer
       dfa_layer.destroyChildren()

       // This will remove the labels on the transitions that are put on the tooltip layer
       tooltip_layer.destroyChildren()
	}
	else{
        return
	}

}<|endoftext|>


<commit_before>/**
 * class NDoc
 *
 * Handles documentation tree.
 **/

'use strict';

// Node < 0.8 shims
if (!require('fs').exists) {
  require('fs').exists = require('path').exists;
}
if (!require('fs').existsSync) {
  require('fs').existsSync = require('path').existsSync;
}

// stdlib
var path = require('path');

// 3rd-party
var _     = require('underscore');
var async = require('async');

// internal
var template    = require('./ndoc/common').template;
var renderers   = require('./ndoc/renderers');
var parsers     = require('./ndoc/parsers');

////////////////////////////////////////////////////////////////////////////////

var NDoc = module.exports = {};

////////////////////////////////////////////////////////////////////////////////

// parse all files and prepare a "raw list of nodes
function parse_files(files, options, callback) {
  var nodes = {
    // root section node
    '': {
      id: '',
      type: 'section',
      children: [],
      description: '',
      short_description: '',
      href: '#',
      root: true,
      file: '',
      line: 0
    }
  };

  async.forEachSeries(files, function (file, next_file) {
    var fn = parsers[path.extname(file)];

    if (!fn) {
      console.warn('No parser found for file: ' + file);
      next_file();
      return;
    }

    console.info('Parsing file: ' + file);
    fn(file, options, function (err, file_nodes) {
      // TODO:  fail on name clash here as well -- as we might get name clash
      //        from different parsers, or even differnret files
      _.extend(nodes, file_nodes);
      next_file(err);
    });
  }, function (err) {
    callback(err, nodes);
  });
}

function build_tree(nodes, options) {
  var tree, parted, sections, children;

  //
  // preprocess nodes
  //

  _.each(nodes, function (node) {
    if (!node.href && !node.root && options.linkFormat) {
      node.href = template(options.linkFormat, {
        'package' : options.package,
        'file'    : node.file.replace(/\\/g, '/'),
        'line'    : node.line
      });
    }
  });

  //
  // for each element with undefined section try to guess the section
  // E.g. for ".Ajax.Updater" we try to find "SECTION.Ajax" element.
  // If found, rename ".Ajax.Updater" to "SECTION.Ajax.Updater"
  //

  // prepare nodes of sections
  // N.B. starting with 1 we skip "" section
  parted = _.keys(nodes).sort().slice(1).map(function (id) {
    return {id: id, parted: id.split(/[.#@]/), node: nodes[id]};
  });

  _.each(parted, function (data) {
    var found;

    // leave only ids without defined section
    if ('' !== data.parted[0]) {
      return;
    }

    found = _.find(parted, function (other) {
      return !!other.parted[0] && other.parted[1] === data.parted[1];
    });

    if (found) {
      delete nodes[data.id];

      data.node.id    = found.parted[0] + data.id;
      data.parted[0]  = found.parted[0];

      nodes[data.node.id] = data.node;
    }
  });

  // sort elements in case-insensitive manner
  tree = {};

  sections = _.keys(nodes).sort(function (a, b) {
    a = a.toLowerCase();
    b = b.toLowerCase();
    return a === b ? 0 : a < b ? -1 : 1;
  });

  sections.forEach(function (id) {
    tree[id] = nodes[id];
  });

  // rebuild the tree from the end to beginning.
  // N.B. since the nodes we iterate over is sorted, we can determine precisely
  // the parent of any element.
  _.each(sections.slice(0).reverse(), function (id) {
    var idx, parent;

    // parent name is this element's name without portion after
    // the last '.' for class member, last '#' for instance member,
    // or first '@' for events
    // first check for event, because event name can contain '.', '#' and '@'
    idx = id.indexOf('@');

    if (idx === -1) {
      idx = Math.max(id.lastIndexOf('.'), id.lastIndexOf('#'));
    }

    // get parent element
    parent = tree[id.substring(0, idx)];

    // no '.' or '#' or '@' found or no parent? -- top level section. skip it
    if (-1 === idx || !parent) {
      return;
    }

    // parent element found. move this element to parent's children nodes,
    // maintaing order
    parent.children.unshift(tree[id]);
    delete tree[id];
  });

  // cleanup nodes, reassign right ids after we resolved
  // to which sections every element belongs
  _.each(nodes, function (node, id) {
    var idx = node.id.indexOf('@'); // get position of @event start

    delete nodes[id];

    // compose new id
    node.id = id.replace(/^[^.]*\./, '');

    // First check for event, because event name can contain '.' and '#'
    // Otherwise get property/method delimiter position
    if (idx === -1) {
      idx = Math.max(node.id.lastIndexOf('.'), node.id.lastIndexOf('#'));
    }

    if (-1 === idx) {
      node.name =  node.id;
    } else {
      node.name = node.id.substring(idx + 1);
      node.name_prefix = node.id.substring(0, idx + 1);
    }

    // sections have lowercased ids, to not clash with other elements
    if ('section' === node.type) {
      node.id = node.id.toLowerCase();
    }

    // prototype members have different paths
    node.path = node.id.replace(/#/g, '.prototype.');

    // events have different paths as well, but only first '@' separates event name
    node.path = node.path.replace(/@/, '.event.');

    delete node.section;

    // prune sections from nodes
    if ('section' !== node.type) {
      nodes[node.id] = node;
    }
  });

  // assign aliases, subclasses, constructors
  // correct method types (class or entity)
  _.each(nodes, function (node, id) {
    // aliases
    if (node.alias_of && nodes[node.alias_of]) {
      nodes[node.alias_of].aliases.push(node.id);
    }

    // classes hierarchy
    if ('class' === node.type) {
      //if (d.superclass) console.log('SUPER', id, d.superclass)
      if (node.superclass && nodes[node.superclass]) {
        nodes[node.superclass].subclasses.push(node.id);
      }

      return;
    }

    if ('constructor' === node.type) {
      node.id = 'new ' + node.id.replace(/\.new$/, '');
      return;
    }

    // methods and properties
    if ('method' === node.type || 'property' === node.type) {
      // FIXME: shouldn't it be assigned by parser?

      if (node.id.match(/^\$/)) {
        node.type = 'utility';
        return;
      }

      // first check for event, because event name can contain '.' and '#'
      if (node.id.indexOf('@') >= 0) {
        node.type = 'event';
        return;
      }

      if (node.id.indexOf('#') >= 0) {
        node.type = 'instance ' + node.type;
        return;
      }

      if (node.id.indexOf('.') >= 0) {
        node.type = 'class ' + node.type;
        return;
      }
    }
  });

  // tree is hash of sections.
  // convert sections to uniform children array of tree top level
  children = [];

  _.each(tree, function (node, id) {
    if (id === '') {
      children = children.concat(node.children);
    } else {
      children.push(node);
    }

    delete tree[id];
  });

  tree.children = children;

  return {list: nodes, tree: tree};
}

////////////////////////////////////////////////////////////////////////////////

/**
 *  NDoc.parse(files, options, callback) -> Void
 *  - files (Array): Files to be parsed
 *  - options (Object): Parser options
 *  - callback (Function): Notifies parsing is finished with `callback(err, ast)`
 *
 *  Execute `name` parser against `files` with given options.
 *
 *
 *  ##### Options
 *
 *  - **linkFormat**: Format for link to source file. This can have variables:
 *    - `{file}`: Current file
 *    - `{line}`: Current line
 *    - `{package.*}`: Any package.json variable
 **/
NDoc.parse = function parse(files, options, callback) {
  parse_files(files, options, function (err, nodes) {
    callback(err, build_tree(nodes, options));
  });
};

/**
 *  NDoc.render(name, ast, options, callback) -> Void
 *  - name (String): Renderer name
 *  - ast (Object): Parsed AST (should consist of `list` and `tree`)
 *  - options (Object): Renderer options
 *  - callback (Function): Notifies rendering is finished with `callback(err)`
 *
 *  Execute `name` renderer for `ast` with given options.
 **/
NDoc.render = function render(name, ast, options, callback) {
  if (!renderers[name]) {
    callback("Unknown renderer: " + name);
    return;
  }

  renderers[name](ast, options, callback);
};

/**
 *  NDoc.cli -> cli
 **/
NDoc.cli = require('./ndoc/cli');

/**
 *  NDoc.VERSION -> String
 *
 *  NDoc version.
 **/
NDoc.VERSION = require('./ndoc/version');

/**
 *  NDoc.use(plugin) -> Void
 *  - plugin (Function): Infection `plugin(NDocClass)`
 *
 *  Runs given `plugin` against NDoc base class.
 *
 *
 *  ##### Examples
 *
 *      NDoc.use(require('my-renderer'));
 **/
NDoc.use = function use(plugin) {
  plugin(this);
};

/**
 *  NDoc.registerRenderer(name, func) -> Void
 *  - name (String): Name of the renderer, e.g. `'html'`
 *  - func (Function): Renderer function `func(ast, options, callback)`
 *
 *  Registers given function as `name` renderer.
 **/
NDoc.registerRenderer = function (name, func) {
  renderers[name] = func;
};

/**
 *  NDoc.registerParser(extension, func) -> Void
 *  - extension (String): Extension suitable for the parser, e.g. `'js'`
 *  - func (Function): Parser function `func(source, options, callback)`
 *
 *  Registers given function as `name` renderer.
 **/
NDoc.registerParser = function (extension, func) {
  extension = path.extname('name.' + extension);

  delete parsers[extension];
  parsers[extension] = func;
};

/**
 *  NDoc.extensionAlias(alias, extension) -> Void
 *  - alias (String): Extension as for the parser, e.g. `'cc'`
 *  - extension (String): Extension as for the parser, e.g. `'js'`
 *
 *  Registers `alias` of the `extension` parser.
 *
 *
 *  ##### Example
 *
 *  Parse all `*.cc` files with parser registered for `*.js`
 *
 *  ``` javascript
 *  ndoc.extensionAlias('cc', 'js');
 *  ```
 *
 *
 *  ##### See Also
 *
 *  - [[NDoc.registerParser]]
 **/
NDoc.extensionAlias = function (alias, extension) {
  alias     = path.extname('name.' + alias);
  extension = path.extname('name.' + extension);

  Object.defineProperty(parsers, alias, {
    get:          function ()   { return parsers[extension]; },
    set:          function (fn) { NDoc.registerParser(alias, fn); },
    configurable: true
  });
};

//
// require base plugins
//

NDoc.use(require(__dirname + '/ndoc/plugins/parsers/javascript'));
NDoc.use(require(__dirname + '/ndoc/plugins/renderers/html'));
NDoc.use(require(__dirname + '/ndoc/plugins/renderers/json'));
<commit_msg>Fix register parser and extension alias<commit_after>/**
 * class NDoc
 *
 * Handles documentation tree.
 **/

'use strict';

// Node < 0.8 shims
if (!require('fs').exists) {
  require('fs').exists = require('path').exists;
}
if (!require('fs').existsSync) {
  require('fs').existsSync = require('path').existsSync;
}

// stdlib
var path = require('path');

// 3rd-party
var _     = require('underscore');
var async = require('async');

// internal
var template    = require('./ndoc/common').template;
var renderers   = require('./ndoc/renderers');
var parsers     = require('./ndoc/parsers');

////////////////////////////////////////////////////////////////////////////////

var NDoc = module.exports = {};

////////////////////////////////////////////////////////////////////////////////

// parse all files and prepare a "raw list of nodes
function parse_files(files, options, callback) {
  var nodes = {
    // root section node
    '': {
      id: '',
      type: 'section',
      children: [],
      description: '',
      short_description: '',
      href: '#',
      root: true,
      file: '',
      line: 0
    }
  };

  async.forEachSeries(files, function (file, next_file) {
    var fn = parsers[path.extname(file)];

    if (!fn) {
      console.warn('No parser found for file: ' + file);
      next_file();
      return;
    }

    console.info('Parsing file: ' + file);
    fn(file, options, function (err, file_nodes) {
      // TODO:  fail on name clash here as well -- as we might get name clash
      //        from different parsers, or even differnret files
      _.extend(nodes, file_nodes);
      next_file(err);
    });
  }, function (err) {
    callback(err, nodes);
  });
}

function build_tree(nodes, options) {
  var tree, parted, sections, children;

  //
  // preprocess nodes
  //

  _.each(nodes, function (node) {
    if (!node.href && !node.root && options.linkFormat) {
      node.href = template(options.linkFormat, {
        'package' : options.package,
        'file'    : node.file.replace(/\\/g, '/'),
        'line'    : node.line
      });
    }
  });

  //
  // for each element with undefined section try to guess the section
  // E.g. for ".Ajax.Updater" we try to find "SECTION.Ajax" element.
  // If found, rename ".Ajax.Updater" to "SECTION.Ajax.Updater"
  //

  // prepare nodes of sections
  // N.B. starting with 1 we skip "" section
  parted = _.keys(nodes).sort().slice(1).map(function (id) {
    return {id: id, parted: id.split(/[.#@]/), node: nodes[id]};
  });

  _.each(parted, function (data) {
    var found;

    // leave only ids without defined section
    if ('' !== data.parted[0]) {
      return;
    }

    found = _.find(parted, function (other) {
      return !!other.parted[0] && other.parted[1] === data.parted[1];
    });

    if (found) {
      delete nodes[data.id];

      data.node.id    = found.parted[0] + data.id;
      data.parted[0]  = found.parted[0];

      nodes[data.node.id] = data.node;
    }
  });

  // sort elements in case-insensitive manner
  tree = {};

  sections = _.keys(nodes).sort(function (a, b) {
    a = a.toLowerCase();
    b = b.toLowerCase();
    return a === b ? 0 : a < b ? -1 : 1;
  });

  sections.forEach(function (id) {
    tree[id] = nodes[id];
  });

  // rebuild the tree from the end to beginning.
  // N.B. since the nodes we iterate over is sorted, we can determine precisely
  // the parent of any element.
  _.each(sections.slice(0).reverse(), function (id) {
    var idx, parent;

    // parent name is this element's name without portion after
    // the last '.' for class member, last '#' for instance member,
    // or first '@' for events
    // first check for event, because event name can contain '.', '#' and '@'
    idx = id.indexOf('@');

    if (idx === -1) {
      idx = Math.max(id.lastIndexOf('.'), id.lastIndexOf('#'));
    }

    // get parent element
    parent = tree[id.substring(0, idx)];

    // no '.' or '#' or '@' found or no parent? -- top level section. skip it
    if (-1 === idx || !parent) {
      return;
    }

    // parent element found. move this element to parent's children nodes,
    // maintaing order
    parent.children.unshift(tree[id]);
    delete tree[id];
  });

  // cleanup nodes, reassign right ids after we resolved
  // to which sections every element belongs
  _.each(nodes, function (node, id) {
    var idx = node.id.indexOf('@'); // get position of @event start

    delete nodes[id];

    // compose new id
    node.id = id.replace(/^[^.]*\./, '');

    // First check for event, because event name can contain '.' and '#'
    // Otherwise get property/method delimiter position
    if (idx === -1) {
      idx = Math.max(node.id.lastIndexOf('.'), node.id.lastIndexOf('#'));
    }

    if (-1 === idx) {
      node.name =  node.id;
    } else {
      node.name = node.id.substring(idx + 1);
      node.name_prefix = node.id.substring(0, idx + 1);
    }

    // sections have lowercased ids, to not clash with other elements
    if ('section' === node.type) {
      node.id = node.id.toLowerCase();
    }

    // prototype members have different paths
    node.path = node.id.replace(/#/g, '.prototype.');

    // events have different paths as well, but only first '@' separates event name
    node.path = node.path.replace(/@/, '.event.');

    delete node.section;

    // prune sections from nodes
    if ('section' !== node.type) {
      nodes[node.id] = node;
    }
  });

  // assign aliases, subclasses, constructors
  // correct method types (class or entity)
  _.each(nodes, function (node, id) {
    // aliases
    if (node.alias_of && nodes[node.alias_of]) {
      nodes[node.alias_of].aliases.push(node.id);
    }

    // classes hierarchy
    if ('class' === node.type) {
      //if (d.superclass) console.log('SUPER', id, d.superclass)
      if (node.superclass && nodes[node.superclass]) {
        nodes[node.superclass].subclasses.push(node.id);
      }

      return;
    }

    if ('constructor' === node.type) {
      node.id = 'new ' + node.id.replace(/\.new$/, '');
      return;
    }

    // methods and properties
    if ('method' === node.type || 'property' === node.type) {
      // FIXME: shouldn't it be assigned by parser?

      if (node.id.match(/^\$/)) {
        node.type = 'utility';
        return;
      }

      // first check for event, because event name can contain '.' and '#'
      if (node.id.indexOf('@') >= 0) {
        node.type = 'event';
        return;
      }

      if (node.id.indexOf('#') >= 0) {
        node.type = 'instance ' + node.type;
        return;
      }

      if (node.id.indexOf('.') >= 0) {
        node.type = 'class ' + node.type;
        return;
      }
    }
  });

  // tree is hash of sections.
  // convert sections to uniform children array of tree top level
  children = [];

  _.each(tree, function (node, id) {
    if (id === '') {
      children = children.concat(node.children);
    } else {
      children.push(node);
    }

    delete tree[id];
  });

  tree.children = children;

  return {list: nodes, tree: tree};
}

////////////////////////////////////////////////////////////////////////////////

/**
 *  NDoc.parse(files, options, callback) -> Void
 *  - files (Array): Files to be parsed
 *  - options (Object): Parser options
 *  - callback (Function): Notifies parsing is finished with `callback(err, ast)`
 *
 *  Execute `name` parser against `files` with given options.
 *
 *
 *  ##### Options
 *
 *  - **linkFormat**: Format for link to source file. This can have variables:
 *    - `{file}`: Current file
 *    - `{line}`: Current line
 *    - `{package.*}`: Any package.json variable
 **/
NDoc.parse = function parse(files, options, callback) {
  parse_files(files, options, function (err, nodes) {
    callback(err, build_tree(nodes, options));
  });
};

/**
 *  NDoc.render(name, ast, options, callback) -> Void
 *  - name (String): Renderer name
 *  - ast (Object): Parsed AST (should consist of `list` and `tree`)
 *  - options (Object): Renderer options
 *  - callback (Function): Notifies rendering is finished with `callback(err)`
 *
 *  Execute `name` renderer for `ast` with given options.
 **/
NDoc.render = function render(name, ast, options, callback) {
  if (!renderers[name]) {
    callback("Unknown renderer: " + name);
    return;
  }

  renderers[name](ast, options, callback);
};

/**
 *  NDoc.cli -> cli
 **/
NDoc.cli = require('./ndoc/cli');

/**
 *  NDoc.VERSION -> String
 *
 *  NDoc version.
 **/
NDoc.VERSION = require('./ndoc/version');

/**
 *  NDoc.use(plugin) -> Void
 *  - plugin (Function): Infection `plugin(NDocClass)`
 *
 *  Runs given `plugin` against NDoc base class.
 *
 *
 *  ##### Examples
 *
 *      NDoc.use(require('my-renderer'));
 **/
NDoc.use = function use(plugin) {
  plugin(this);
};

/**
 *  NDoc.registerRenderer(name, func) -> Void
 *  - name (String): Name of the renderer, e.g. `'html'`
 *  - func (Function): Renderer function `func(ast, options, callback)`
 *
 *  Registers given function as `name` renderer.
 **/
NDoc.registerRenderer = function (name, func) {
  renderers[name] = func;
};

/**
 *  NDoc.registerParser(extension, func) -> Void
 *  - extension (String): Extension suitable for the parser, e.g. `'js'`
 *  - func (Function): Parser function `func(source, options, callback)`
 *
 *  Registers given function as `name` renderer.
 **/
NDoc.registerParser = function (extension, func) {
  extension = path.extname('name.' + extension);

  Object.defineProperty(parsers, extension, {
    get: function () { return func; },
    configurable: true
  });
};

/**
 *  NDoc.extensionAlias(alias, extension) -> Void
 *  - alias (String): Extension as for the parser, e.g. `'cc'`
 *  - extension (String): Extension as for the parser, e.g. `'js'`
 *
 *  Registers `alias` of the `extension` parser.
 *
 *
 *  ##### Example
 *
 *  Parse all `*.cc` files with parser registered for `*.js`
 *
 *  ``` javascript
 *  ndoc.extensionAlias('cc', 'js');
 *  ```
 *
 *
 *  ##### See Also
 *
 *  - [[NDoc.registerParser]]
 **/
NDoc.extensionAlias = function (alias, extension) {
  alias     = path.extname('name.' + alias);
  extension = path.extname('name.' + extension);

  Object.defineProperty(parsers, alias, {
    get: function () { return parsers[extension]; },
    configurable: true
  });
};

//
// require base plugins
//

NDoc.use(require(__dirname + '/ndoc/plugins/parsers/javascript'));
NDoc.use(require(__dirname + '/ndoc/plugins/renderers/html'));
NDoc.use(require(__dirname + '/ndoc/plugins/renderers/json'));
<|endoftext|>


<commit_before>module.exports = (function (async) {
    var Flow = function () {
        this.stack = [];
    }

    Flow.prototype.next = function (func) {
        this.stack.push(func);
        return this;
    }

    Flow.prototype.parallel = function (func) {

        if (this.stack[this.stack.length - 1] instanceof Array)
            this.stack[this.stack.length - 1].push(func);
        else
            this.stack.push([func]);
        return this;
    }

    Flow.prototype.done = function (func) {
        var self = this
            , stack = [];

        for (var i in this.stack) {
            if (this.stack[i]instanceof Array) {
                var parallelWrapper = function () {
                    var arg = Array.prototype.slice.call(arguments, 0, arguments.length - 1)
                        , parallelStack = [];
                    for (var j in self.stack[i]) {
                        (function (func) {
                            parallelStack.push(function (done) {
                                func.apply(func, Array.prototype.concat.call(arg, [done]));
                            });
                        })(self.stack[i][j]);
                    }

                    async.parallel(parallelStack, arguments[arguments.length - 1]);
                }

                stack.push(parallelWrapper);
            } else {
                stack.push(this.stack[i]);
            }
        }

        async.waterfall(stack, func);
    }

    return {
        next: function (func) {
            return (new Flow()).next(func);
        },
        parallel: function (func) {
            return (new Flow()).parallel(func);
        }
    }

})(require('async'));<commit_msg>fix bug with parallel flow<commit_after>module.exports = (function (async) {
    var Flow = function () {
        this.stack = [];
    }

    Flow.prototype.next = function (func) {
        this.stack.push(func);
        return this;
    }

    Flow.prototype.parallel = function (func) {

        if (this.stack[this.stack.length - 1] instanceof Array)
            this.stack[this.stack.length - 1].push(func);
        else
            this.stack.push([func]);
        return this;
    }

    Flow.prototype.done = function (func) {
        var stack = [];

        for (var i in this.stack) {
            if (this.stack[i]instanceof Array) {
                var parallelWrapper = (function (subStack) {
                    return function () {
                        var arg = Array.prototype.slice.call(arguments, 0, arguments.length - 1)
                            , parallelStack = [];
                        for (var j in subStack) {
                            (function (func) {
                                parallelStack.push(function (done) {
                                    func.apply(func, Array.prototype.concat.call(arg, [done]));
                                });
                            })(subStack[j]);
                        }

                        async.parallel(parallelStack, arguments[arguments.length - 1]);
                    }
                })(this.stack[i]);

                stack.push(parallelWrapper);
            } else {
                stack.push(this.stack[i]);
            }

        }
        async.waterfall(stack, func);
    }

    return {
        next: function (func) {
            return (new Flow()).next(func);
        },
        parallel: function (func) {
            return (new Flow()).parallel(func);
        }
    }

})(require('async'));<|endoftext|>


<commit_before>var child_process = require('child_process');
var path = require('path');

/**
 * Creates a Nix object that captures common properties for Nix language
 * constructs for which is no equivalent JavaScript type available.
 *
 * @constructor
 * @param {string} value Value of the reference
 */
function NixObject(value) {
    this.value = value;
};

exports.NixObject = NixObject;

/**
 * Creates a Nix file object that gets imported into the Nix store. Paths to a
 * file may be absolute (starting with a /) or relative. For relative paths a
 * module reference must be given so that it can be correctly resolved to a
 * correct absolute path.
 *
 * @constructor
 * @param {object} args Arguments to this function
 * @param {string} args.value An absolute of relative path to a file
 * @param {Module} args.module Reference to the CommonJS module that refers to a relative path (not needed for absolute paths)
 */
function NixFile(args) {
    NixObject.call(this, args.value);
    this.module = args.module;
};

exports.NixFile = NixFile;

/**
 * Creates a Nix URL object that gets validates by the Nix expression evaluator.
 *
 * @constructor
 * @param {string} value Value containing a URL
 */
function NixURL(value) {
    NixObject.call(this, value);
};

exports.NixURL = NixURL;

/**
 * Creates a Nix object that contains an already generated Nix expression.
 *
 * @constructor
 * @param {string} value Value containing a Nix expression
 */
function NixExpression(value) {
    NixObject.call(this, value);
};

exports.NixExpression = NixExpression;

/**
 * Creates a recursive attribute set in which members can refer to each other.
 *
 * @param {object} value An aribitrary object that should be represented as a recursive attribute set
 * @constructor
 */
function NixRecursiveAttrSet(value) {

    for(var attrName in value) {
        var attrValue = value[attrName];
        this[attrName] = attrValue;
    }
}

exports.NixRecursiveAttrSet = NixRecursiveAttrSet;

/**
 * Converts a collection of JavaScript objects to a sementically equivalent or
 * similar Nix expression language object.
 *
 * @param {...*} var_args A variable amount of parameters that can be of any JavaScript object type
 * @return {string} A string containing the converted Nix expression language object
 */
function jsToNix() {
    var expr = "";

    for(var i = 0; i < arguments.length; i++) {

        var arg = arguments[i];

        if(i > 0)
            expr += " "; /* Add white space between every argument */

        if(arg === null) {
            expr += "null"; /* We must check for the null reference explicitly */
        } else {

            /* Use a type match to determine the conversion from a JavaScript object to a Nix expression language object */
            var type = typeof arg;

            switch(type) {
                case "boolean":
                    if(arg)
                        expr += "true";
                    else
                        expr += "false";

                    break;

                case "number":
                    expr += arg;
                    break;

                case "string":
                    expr = '"'+arg.replace(/\"/g, '\\"')+'"';
                    break;

                case "object":
                    if(Array.isArray(arg)) { /* Arrays are also objects, but this will tell us the difference */
                        var str = "[\n";

                        for(var i = 0; i < arg.length; i++)
                            str += "("+exports.jsToNix(arg[i]) + ")\n";

                        str += "]";

                        expr += str;
                        break;

                    } else if(arg instanceof NixURL) {
                        expr += arg.value;
                        break;

                    } else if(arg instanceof NixFile) {
                        var dir = "";

                        /*
                         * If the path does not start with a / and a module is
                         * defined, we consider the file to have a relative path
                         * and we have to add the module's dirname as prefix
                         */

                        if(arg.value.substring(0, 1) != '/' && arg.module !== undefined)
                            dir = path.dirname(arg.module.filename) + "/";

                        /* Generate Nix file object */
                        if(dir.indexOf(" ") == -1 && arg.value.indexOf(" ") == -1)
                            expr += dir + arg.value; /* Filenames without spaces can be placed verbatim */
                        else
                            expr += '/. + "' + dir.replace(/\"/g, '\\"') + arg.value.replace(/\"/g, '\\"') + '"'; /* Filenames with spaces require some conversion */

                        break;

                    } else if(arg instanceof NixExpression) {
                        expr += "(" + arg.value + ")";
                        break;

                    } else {
                        var str = "";

                        if(arg instanceof NixRecursiveAttrSet)
                            str += "rec {\n";
                        else
                            str += "{\n";

                        for(var attrName in arg) {
                            var attrValue = exports.jsToNix(arg[attrName]);
                            str += "  "+attrName+" = "+attrValue+";\n";
                        }

                        str += "}";

                        expr += str;
                        break;
                    }

                case "function":
                    var str = "";

                    for(var i = 0; i < arg.length; i++)
                        str += "arg" + i + ":\n";

                    str += "nijsFunProxy {\n";
                    str += "  function = ''"+arg.toString()+"'';\n";
                    str += "  args = [\n";

                    for(var i = 0; i < arg.length; i++)
                        str += "    arg" + i + "\n";

                    str += "  ];\n";
                    str += "}\n";

                    expr += str;
                    break;

                case "xml":
                    expr += '"'+arg.toXMLString().replace(/\"/g, '\\"')+'"';
                    break;

                case "undefined":
                    throw "We cannot convert something that is undefined!";
            }
        }
    }

    return expr;
}

exports.jsToNix = jsToNix;

/**
 * Invokes the nix-build process to evaluate a given nix object containing a Nix
 * expression. As a side-effect, the declared package gets build.
 *
 * @param {object} args Nix build parameters
 * @param {NixExpression} args.nixObject An object instance of the NixExpression prototype, with a string value that contains a Nix expression
 * @param {Array.<string>} args.params An array of strings representing command-line parameters passed to nix-build
 * @param {function(string)} args.onSuccess Callback function that gets called with the resulting Nix store path, if the build succeeds
 * @param {function(number)} args.onFailure Callback function that gets called with the resulting non-zero exit status, if the build fails
 */
exports.nixBuild = function(args) {
    var output = "";

    var nixBuildProcess = child_process.spawn("nix-build", args.params.concat(["-"]));

    nixBuildProcess.stdin.write(args.expression);
    nixBuildProcess.stdin.end();

    nixBuildProcess.stdout.on("data", function(data) {
        output += data; /* Capture the Nix store path */
    });

    nixBuildProcess.stderr.on("data", function(data) {
        process.stderr.write(data);
    });

    nixBuildProcess.on("exit", function(code) {
        if(code == 0)
            args.onSuccess(output.substring(0, output.length - 1));
        else
            args.onFailure(code);
    });
};

/**
 * Augments a given Nix object with a Nix expression with a Nixpkgs and NiJS
 * reference and executes nix-build to evaluate the expression.
 *
 * @param {object} args Nix build parameters
 * @param {NixExpression} args.nixObject An object instance of the NixExpression prototype, with a string value that contains a Nix expression
 * @param {Array.<string>} args.params An array of strings representing command-line parameters passed to nix-build
 * @param {function(string)} args.onSuccess Callback function that gets called with the resulting Nix store path, if the build succeeds
 * @param {function(number)} args.onFailure Callback function that gets called with the resulting non-zero exit status, if the build fails
 */
exports.callNixBuild = function(args) {
    var expression = "let\n"+
      "  pkgs = import <nixpkgs> {};\n"+
      "  nijsFunProxy = import <nijs/lib/funProxy.nix> { inherit (pkgs) stdenv nodejs; };\n"+
      "in\n" + args.nixObject.value;

    exports.nixBuild({
        expression : expression,
        params : args.params,
        onSuccess : args.onSuccess,
        onFailure : args.onFailure
    });
}
<commit_msg>- Use prototype inheritance for the alien language constructs - Fix conversion of recursive attribute sets<commit_after>var child_process = require('child_process');
var path = require('path');

/**
 * Do a simulated class inheritance using a function representing the
 * constructor of a base class and a function representing the constructor of
 * a child class. I could (of course) use yet another particular library to do
 * this, but this will also introduce another dependency on another package.
 * Therefore, I did it myself.
 *
 * I don't dislike the concept of prototypes, but the way it's implemented in
 * JavaScript is just too crazy. You have to do some crazy stuff to properly set
 * prototypes, as we cannot control them directly. Anyway, this function
 * abstracts over that burden so that we don't have to repeat this every time.
 *
 * @param {function} parent Constructor function of the simulated parent class
 * @param {function} child Constructor function of the simulated child class
 */

function inherit(parent, child) {
    function F() {}; /* Dummy constructor function used to create an empty object with the parent's prototype */
    F.prototype = parent.prototype; /* Assign the parent constructor function's prototype property (not the real prototype) to the dummy constructor function. */
    child.prototype = new F(); /* Create an instance of the dummy custructor. This call returns an empty object, which has the parent's prototype */
    child.prototype.constructor = child; /* Set the constructor to our child constructor function again, as it has been changed by the parent's prototype */
}

/**
 * Creates a Nix object that captures common properties for Nix language
 * constructs for which is no equivalent JavaScript type available.
 *
 * @constructor
 * @param {...} value Value of the reference
 */
function NixObject(value) {
    this.value = value;
};

exports.NixObject = NixObject;

/**
 * Creates a Nix file object that gets imported into the Nix store. Paths to a
 * file may be absolute (starting with a /) or relative. For relative paths a
 * module reference must be given so that it can be correctly resolved to a
 * correct absolute path.
 *
 * @constructor
 * @param {object} args Arguments to this function
 * @param {string} args.value An absolute or relative path to a file
 * @param {Module} args.module Reference to the CommonJS module that refers to a relative path (not needed for absolute paths)
 */

function NixFile(args) {
    NixObject.call(this, args.value);
    this.module = args.module;
};

inherit(NixObject, NixFile);

exports.NixFile = NixFile;

/**
 * Creates a Nix URL object that gets validates by the Nix expression evaluator.
 *
 * @constructor
 * @param {string} value Value containing a URL
 */

function NixURL(value) {
    NixObject.call(this, value);
};

inherit(NixObject, NixURL);

exports.NixURL = NixURL;

/**
 * Creates a Nix object that contains an already generated Nix expression.
 *
 * @constructor
 * @param {string} value Value containing a Nix expression
 */
function NixExpression(value) {
    NixObject.call(this, value);
};

inherit(NixObject, NixExpression);

exports.NixExpression = NixExpression;

/**
 * Creates a recursive attribute set in which members can refer to each other.
 *
 * @param {object} value An aribitrary object that should be represented as a recursive attribute set. This object is stored as a reference.
 * @constructor
 */
function NixRecursiveAttrSet(value) {
    NixObject.call(this, value);
}

inherit(NixObject, NixRecursiveAttrSet);

exports.NixRecursiveAttrSet = NixRecursiveAttrSet;

/**
 * Converts members of an object to members of an attribute set
 *
 * @param {object} obj Object to convert
 * @return {string} A string containing the Nix attribute set members
 */
function objectMembersToAttrsMembers(obj) {
    var str = "";

    for(var attrName in obj) {
        var attrValue = jsToNix(obj[attrName]);
            str += "  "+attrName+" = "+attrValue+";\n";
    }

    return str;
}

/**
 * Converts a collection of JavaScript objects to a sementically equivalent or
 * similar Nix expression language object.
 *
 * @param {...*} var_args A variable amount of parameters that can be of any JavaScript object type
 * @return {string} A string containing the converted Nix expression language object
 */
function jsToNix() {
    var expr = "";

    for(var i = 0; i < arguments.length; i++) {

        var arg = arguments[i];

        if(i > 0)
            expr += " "; /* Add white space between every argument */

        if(arg === null) {
            expr += "null"; /* We must check for the null reference explicitly */
        } else {

            /* Use a type match to determine the conversion from a JavaScript object to a Nix expression language object */
            var type = typeof arg;

            switch(type) {
                case "boolean":
                    if(arg)
                        expr += "true";
                    else
                        expr += "false";

                    break;

                case "number":
                    expr += arg;
                    break;

                case "string":
                    expr = '"'+arg.replace(/\"/g, '\\"')+'"';
                    break;

                case "object":
                    if(Array.isArray(arg)) { /* Arrays are also objects, but this will tell us the difference */
                        var str = "[\n";

                        for(var i = 0; i < arg.length; i++)
                            str += "("+exports.jsToNix(arg[i]) + ")\n";

                        str += "]";

                        expr += str;
                        break;

                    } else if(arg instanceof NixURL) {
                        expr += arg.value;
                        break;

                    } else if(arg instanceof NixFile) {
                        var dir = "";

                        /*
                         * If the path does not start with a / and a module is
                         * defined, we consider the file to have a relative path
                         * and we have to add the module's dirname as prefix
                         */

                        if(arg.value.substring(0, 1) != '/' && arg.module !== undefined)
                            dir = path.dirname(arg.module.filename) + "/";

                        /* Generate Nix file object */
                        if(dir.indexOf(" ") == -1 && arg.value.indexOf(" ") == -1)
                            expr += dir + arg.value; /* Filenames without spaces can be placed verbatim */
                        else
                            expr += '/. + "' + dir.replace(/\"/g, '\\"') + arg.value.replace(/\"/g, '\\"') + '"'; /* Filenames with spaces require some conversion */

                        break;

                    } else if(arg instanceof NixExpression) {
                        expr += "(" + arg.value + ")";
                        break;
                    } else if(arg instanceof NixRecursiveAttrSet) {

                        var str = "rec {\n" + objectMembersToAttrsMembers(arg.value) + "}";
                        expr += str;
                        break;

                    } else {
                        var str = "{\n" + objectMembersToAttrsMembers(arg) + "}";
                        expr += str;
                        break;
                    }

                case "function":
                    var str = "";

                    for(var i = 0; i < arg.length; i++)
                        str += "arg" + i + ":\n";

                    str += "nijsFunProxy {\n";
                    str += "  function = ''"+arg.toString()+"'';\n";
                    str += "  args = [\n";

                    for(var i = 0; i < arg.length; i++)
                        str += "    arg" + i + "\n";

                    str += "  ];\n";
                    str += "}\n";

                    expr += str;
                    break;

                case "xml":
                    expr += '"'+arg.toXMLString().replace(/\"/g, '\\"')+'"';
                    break;

                case "undefined":
                    throw "We cannot convert something that is undefined!";
            }
        }
    }

    return expr;
}

exports.jsToNix = jsToNix;

/**
 * Invokes the nix-build process to evaluate a given nix object containing a Nix
 * expression. As a side-effect, the declared package gets build.
 *
 * @param {object} args Nix build parameters
 * @param {NixExpression} args.nixObject An object instance of the NixExpression prototype, with a string value that contains a Nix expression
 * @param {Array.<string>} args.params An array of strings representing command-line parameters passed to nix-build
 * @param {function(string)} args.onSuccess Callback function that gets called with the resulting Nix store path, if the build succeeds
 * @param {function(number)} args.onFailure Callback function that gets called with the resulting non-zero exit status, if the build fails
 */
exports.nixBuild = function(args) {
    var output = "";

    var nixBuildProcess = child_process.spawn("nix-build", args.params.concat(["-"]));

    nixBuildProcess.stdin.write(args.expression);
    nixBuildProcess.stdin.end();

    nixBuildProcess.stdout.on("data", function(data) {
        output += data; /* Capture the Nix store path */
    });

    nixBuildProcess.stderr.on("data", function(data) {
        process.stderr.write(data);
    });

    nixBuildProcess.on("exit", function(code) {
        if(code == 0)
            args.onSuccess(output.substring(0, output.length - 1));
        else
            args.onFailure(code);
    });
};

/**
 * Augments a given Nix object with a Nix expression with a Nixpkgs and NiJS
 * reference and executes nix-build to evaluate the expression.
 *
 * @param {object} args Nix build parameters
 * @param {NixExpression} args.nixObject An object instance of the NixExpression prototype, with a string value that contains a Nix expression
 * @param {Array.<string>} args.params An array of strings representing command-line parameters passed to nix-build
 * @param {function(string)} args.onSuccess Callback function that gets called with the resulting Nix store path, if the build succeeds
 * @param {function(number)} args.onFailure Callback function that gets called with the resulting non-zero exit status, if the build fails
 */
exports.callNixBuild = function(args) {
    var expression = "let\n"+
      "  pkgs = import <nixpkgs> {};\n"+
      "  nijsFunProxy = import <nijs/lib/funProxy.nix> { inherit (pkgs) stdenv nodejs; };\n"+
      "in\n" + args.nixObject.value;

    exports.nixBuild({
        expression : expression,
        params : args.params,
        onSuccess : args.onSuccess,
        onFailure : args.onFailure
    });
}
<|endoftext|>


<commit_before>
var _ = require('./util.js');
var exports = module.exports;
var child_process = require('child_process');
var spawn = child_process.spawn;
var resPath = __dirname + '/node';

exports.run = function(opt) {
    process.stdout.write('starting fis-server .');
    var timeout = Math.max(opt.timeout * 1000, 5000); delete opt.timeout;
    var errMsg = 'fis-server fails to start at port [' + opt.port + '], error: ';

    if(opt.rewrite && !opt.script){
        opt.script = 'index.js';
    }

    var script = fis.util(opt.root, opt.script);

    var args = [
        resPath + '/master.js'
    ];

    var ready = false;
    var log = '';
    fis.util.map(opt, function(key, value){
        args.push('--' + key, String(value));
    });
    var server = spawn('node', args, { cwd : __dirname, detached: true});
    server.stderr.on('data', function(chunk){
        //console.log(chunk.toString('utf8'));
        if(ready) return;
        chunk = chunk.toString('utf8');
        log += chunk;
        process.stdout.write('.');
        if(chunk.indexOf('master is running') >= 0){
            ready = true;
            process.stdout.write(' at port [' + opt.port + ']\n');

            //copy fis ico
            var favicon = fis.util(opt.root, 'favicon.ico');
            if(!fis.util.exists(favicon)){
                fis.util.copy(resPath + '/vendor/favicon.ico', favicon);
            }

            //copy script
            if(opt.rewrite){
                if(!fis.util.exists(script)){
                    fis.util.copy(resPath + '/vendor/' + opt.script, script);
                }
            }
            setTimeout(function(){
                _.open('http://127.0.0.1' + (opt.port == 80 ? '/' : ':' + opt.port + '/'), function(){
                    process.exit();
                });
            }, 200);
        }
        else if(chunk.indexOf('Exception') > 0) {
            process.stdout.write(' fail\n');
            try { process.kill(server.pid, 'SIGINT'); } catch(e){}
            var match = chunk.match(/exception:?\s+([^\r\n]+)/i);
            if(match){
                errMsg += match[1];
            } else {
                errMsg += 'unknown';
            }
            console.log(log);
            fis.log.error(errMsg);
        }
    });
    server.on('error', function(err){
        try {
            process.kill(server.pid, 'SIGINT');
        } catch(e){}
        fis.log.error(err);
    });
    server.unref();
    fis.util.write(_.getPidFile(), server.pid);
    setTimeout(function(){
        process.stdout.write(' fail\n');
        if(log) console.log(log);
        fis.log.error(errMsg + 'timeout');
    }, timeout);
};<commit_msg>update<commit_after>
var _ = require('./util.js');
var exports = module.exports;
var child_process = require('child_process');
var spawn = child_process.spawn;
var resPath = __dirname + '/node';

exports.run = function(opt) {
    process.stdout.write('starting fis-server .');
    var timeout = Math.max(opt.timeout * 1000, 5000); delete opt.timeout;
    var errMsg = 'fis-server fails to start at port [' + opt.port + '], error: ';

    if(opt.rewrite && !opt.script){
        opt.script = 'index.js';
    }

    var script = fis.util(opt.root, opt.script);

    var args = [
        resPath + '/master.js'
    ];

    var ready = false;
    var log = '';
    fis.util.map(opt, function(key, value){
        args.push('--' + key, String(value));
    });
    var server = spawn('node', args, { cwd : __dirname, detached: true});
    server.stderr.on('data', function(chunk){
        //console.log(chunk.toString('utf8'));
        if(ready) return;
        chunk = chunk.toString('utf8');
        log += chunk;
        process.stdout.write('.');
        if(chunk.indexOf('master is running') >= 0){
            ready = true;
            process.stdout.write(' at port [' + opt.port + ']\n');

            //copy fis ico
            var favicon = fis.util(opt.root, 'favicon.ico');
            if(!fis.util.exists(favicon)){
                fis.util.copy(resPath + '/vendor/favicon.ico', favicon);
            }

            //copy script
            if(opt.rewrite){
                if(!fis.util.exists(script)){
                    fis.util.copy(resPath + '/vendor/' + opt.script, script);
                }
            }
            setTimeout(function(){
                _.open('http://127.0.0.1' + (opt.port == 80 ? '/' : ':' + opt.port + '/'), function(){
                    process.exit();
                });
            }, 200);
        }
        else if(chunk.indexOf('Exception') > 0) {
            errMsg = chunk;
            fis.log.error(errMsg);
        }
    });
    server.on('error', function(err){
        try {
            process.kill(server.pid, 'SIGINT');
        } catch(e){}
        fis.log.error(err);
    });
    server.unref();
    fis.util.write(_.getPidFile(), server.pid);
    setTimeout(function(){
        process.stdout.write(' fail\n');
        if(log) console.log(log);
        fis.log.error(errMsg + 'timeout');
    }, timeout);
};
<|endoftext|>


<commit_before>/**
 * Created by nuintun on 2015/11/24.
 */

'use strict';

// if bold is broken, we can't
// use it in the terminal.
function isBoldBroken(){
  var el = document.createElement('span');

  el.innerHTML = 'hello world';

  document.body.appendChild(el);

  var w1 = el.scrollWidth;

  el.style.fontWeight = 'bold';

  var w2 = el.scrollWidth;

  document.body.removeChild(el);

  return w1 !== w2;
}

module.exports = function (Terminal){
  /**
   * open
   */
  Terminal.prototype.open = function (){
    var div;
    var i = 0;

    this.element = document.createElement('div');
    this.element.className = 'ui-terminal';
    this.element.style.outline = 'none';

    this.element.setAttribute('tabindex', '0');
    this.element.setAttribute('spellcheck', 'false');

    // sync default bg/fg colors
    this.element.style.backgroundColor = this.bgColor;
    this.element.style.color = this.fgColor;

    // Create the lines for our terminal.
    this.children = [];

    for (; i < this.rows; i++) {
      div = document.createElement('div');

      this.element.appendChild(div);
      this.children.push(div);
    }

    this.refresh(0, this.rows - 1);

    // XXX - hack, move this somewhere else.
    if (Terminal.brokenBold === null) {
      Terminal.brokenBold = isBoldBroken();
    }
  };
};
<commit_msg>add files<commit_after>/**
 * Created by nuintun on 2015/11/24.
 */

'use strict';

// if bold is broken, we can't
// use it in the terminal.
function isBoldBroken(){
  var el = document.createElement('span');

  el.innerHTML = 'hello world';

  document.body.appendChild(el);

  var w1 = el.scrollWidth;

  el.style.fontWeight = 'bold';

  var w2 = el.scrollWidth;

  document.body.removeChild(el);

  return w1 !== w2;
}

module.exports = function (Terminal){
  /**
   * open
   */
  Terminal.prototype.open = function (){
    var div;
    var i = 0;

    this.element = document.createElement('div');
    this.element.className = 'ui-terminal';
    this.element.style.outline = 'none';

    this.element.setAttribute('tabindex', '0');
    this.element.setAttribute('spellcheck', 'false');

    // sync default bg/fg colors
    this.element.style.backgroundColor = this.bgColor;
    this.element.style.color = this.fgColor;

    // Create the lines for our terminal.
    this.children = [];

    for (; i < this.rows; i++) {
      div = document.createElement('div');

      this.element.appendChild(div);
      this.children.push(div);
    }

    // XXX - hack, move this somewhere else.
    if (Terminal.brokenBold === null) {
      Terminal.brokenBold = isBoldBroken();
    }

    this.refresh(0, this.rows - 1);
  };
};
<|endoftext|>