<commit_before>/* jshint node: true */
'use strict';

module.exports = function (grunt) {

    // Load grunt tasks automatically
    require('load-grunt-tasks')(grunt);

    // Time how long tasks take. Can help when optimizing build times
    require('time-grunt')(grunt);

    require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        config: {
            staticCss: 'static/css',
            staticJs: 'static/js',
        },

        phplint: {
            options: {
                phpCmd: "/usr/bin/php",
                phpArgs: {
                    "-l": null
                },
                spawnLimit: 10
            },

            bootstrap: ["bootstrap.php"],
            bundle: ["bundle/*.php"],
            controllers: ["controllers/*.php"],
            engine: ["engine/*.php"],
            engineTests: ["engine/Tests/*.php"],
            models: ["models/*.php"],
            public: ["public/*.php"],
            views: ["views/*.php"],
        },

        csslint: {
            strict: {
                src: ['<%= config.staticCss %>/*.css']
            }
        },

        cssmin: {
            combine: {
                options: {
                    'banner': '/* <%= pkg.name %> - v<%= pkg.version %> - ' + '<%= grunt.template.today(\'yyyy-mm-dd\') %> */\n',
                },
                files: {
                    '<%= config.staticCss %>/min/script.css': ['<%= config.staticCss %>/*.css']
                }
            }
        },

        uglify: {
            options: {
                'banner': '/* <%= pkg.name %> - v<%= pkg.version %> - ' + '<%= grunt.template.today(\'yyyy-mm-dd\') %> */\n',
                'preserveComments': false
            },
            js: {
                files: [{
                    src: '<%= config.staticJs %>/*.js',
                    dest: '<%= config.staticJs %>/min/script.js'
                }]
            }
        },

        jshint: {
            options: {
                'node': true,
                'browser': true,
                'esnext': true,
                'bitwise': true,
                'camelcase': true,
                'curly': true,
                'eqeqeq': true,
                'immed': true,
                'indent': 2,
                'latedef': false,
                'newcap': true,
                'noarg': true,
                'quotmark': 'single',
                'regexp': true,
                'undef': true,
                'unused': false,
                'strict': false,
                'trailing': true,
                'smarttabs': true,
                'globals': {
                    'angular': false
                },
                reporter: require('jshint-stylish')
            },
            js: ['Gruntfile.js', '<%= config.staticJs %>/*.js']
        }

    });

    grunt.registerTask('default', ['jshint', 'uglify', 'csslint', 'cssmin']);

};<commit_msg>Update Gruntfile<commit_after>/* jshint node: true */
'use strict';

module.exports = function (grunt) {

    // Load grunt tasks automatically
    require('load-grunt-tasks')(grunt);

    // Time how long tasks take. Can help when optimizing build times
    require('time-grunt')(grunt);

    require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        config: {
            staticCss: 'static/css',
            staticJs: 'static/js',
        },

        phplint: {
            options: {
                phpCmd: '/usr/bin/php',
                phpArgs: {
                    '-l': null
                },
                spawnLimit: 10
            },

            bootstrap: ['bootstrap.php'],
            bundle: ['bundle/*.php'],
            controllers: ['controllers/*.php'],
            engine: ['engine/*.php'],
            engineTests: ['engine/Tests/*.php'],
            models: ['models/*.php'],
            public: ['public/*.php'],
            views: ['views/*.php'],
        },

        csslint: {
            strict: {
                src: ['<%= config.staticCss %>/*.css']
            }
        },

        cssmin: {
            combine: {
                options: {
                    'banner': '/* <%= pkg.name %> - v<%= pkg.version %> - ' + '<%= grunt.template.today(\'yyyy-mm-dd\') %> */',
                },
                files: {
                    '<%= config.staticCss %>/min/styles.css': ['<%= config.staticCss %>/*.css']
                }
            }
        },

        uglify: {
            options: {
                'banner': '/* <%= pkg.name %> - v<%= pkg.version %> - ' + '<%= grunt.template.today(\'yyyy-mm-dd\') %> */\n',
                'preserveComments': false
            },
            js: {
                files: [{
                    src: '<%= config.staticJs %>/*.js',
                    dest: '<%= config.staticJs %>/min/script.js'
                }]
            }
        },

        jshint: {
            options: {
                'node': true,
                'browser': true,
                'esnext': true,
                'bitwise': true,
                'camelcase': true,
                'curly': true,
                'eqeqeq': true,
                'immed': true,
                'indent': 2,
                'latedef': false,
                'newcap': true,
                'noarg': true,
                'quotmark': 'single',
                'regexp': true,
                'undef': true,
                'unused': false,
                'strict': false,
                'trailing': true,
                'smarttabs': true,
                'globals': {
                    'angular': false
                },
                reporter: require('jshint-stylish')
            },
            js: ['Gruntfile.js', '<%= config.staticJs %>/*.js']
        }

    });

    grunt.registerTask('default', ['jshint', 'uglify', 'csslint', 'cssmin', 'phplint']);

};<|endoftext|>


<commit_before>var rewire = require('rewire'),
    sinon = require('sinon'),
    expect = require('chai').expect,
    io = require('socket.io-client'),
    Factory = require('../spec_helper').FactoryGirl,
    docker = require('../spec_helper').docker,
    server = rewire('../../lib/server');

var socket = {
    port: 8080,
    URL: 'http://127.0.0.1:8080',
    options: { transports: ['websocket'], 'force new connection': true }
}

describe('Connection', function() {
    var sleepCode  = Factory.create('sleepCode'),
        stdoutCode = Factory.create('stdoutCode');

    before(function() {
        server.__set__('logger', { log: sinon.stub() });
        server.listen(socket.port, docker);
    });

    beforeEach(function(){
        client = io.connect(socket.URL, socket.options);
    });

    afterEach(function(){
        client.disconnect();
    });

    it('can be establisehd', function(done) {
        client.on('connect', function(data) { done(); });
    });

    it('accepts run request and replies with output', function(done) {
        var i = 0;
        client.on('connect', function(data) {
            client.on('run', function(data){
                expect(data).to.deep.equal(stdoutCode.output[i]);
                ++i;

                if (data.stream === 'status') done();
            });
            client.emit('run', stdoutCode.input);
        });
    });

    it('stops previous run request when running a new run', function(done) {
        client.on('connect', function(data) {
            client.on('run', function(data){
                if (data.stream === 'status') done();
            });
            client.emit('run', sleepCode.input);
            setTimeout(function() {
                client.emit('run', stdoutCode.input);
            }, 600);
        });
    });

    context('when run request is empty', function() {
        var params = null;
        itRespondsWithBadRequestError(params);
    });

    context('when language code is empty', function() {
        var params = { code: 'puts "lol"' };
        itRespondsWithBadRequestError(params);
    });

    context('when code is empty', function() {
        it('accepts run request', function(done) {
            client.on('connect', function(data) {
                client.on('run', function(data){
                    if (data.stream === 'status') done();
                });
                client.emit('run', { language: 'ruby' });
            });
        });
    });

    it('prevents run request spam', function(done) {
        client.on('connect', function(data) {
            client.on('run', function(data){
                if (data.stream === 'ignored') done();
            });
            client.emit('run', stdoutCode.input);
            client.emit('run', stdoutCode.input);
        });
    });

    function itRespondsWithBadRequestError(params) {
        it('responds with a bad request error', function(done) {
            client.on('connect', function(data) {
                client.on('run', function(data){
                    if (data.stream === 'error') {
                        expect(data.chunk).to.eq('Bad request.');
                        done();
                    }
                });
                client.emit('run', params);
            });
        });
    }
});
<commit_msg>cleanup connection test<commit_after>var rewire = require('rewire'),
    sinon = require('sinon'),
    expect = require('chai').expect,
    io = require('socket.io-client'),
    Factory = require('../spec_helper').FactoryGirl,
    docker = require('../spec_helper').docker,
    server = rewire('../../lib/server');

var socket = {
    port: 8080,
    URL: 'http://127.0.0.1:8080',
    options: { transports: ['websocket'], 'force new connection': true }
}

describe('Connection', function() {
    var sleepCode  = Factory.create('sleepCode'),
        stdoutCode = Factory.create('stdoutCode');

    before(function() {
        server.__set__('logger', { log: sinon.stub() });
        server.listen(socket.port, docker);
    });

    beforeEach(function(){
        client = io.connect(socket.URL, socket.options);
    });

    afterEach(function(){
        client.disconnect();
    });

    it('can be establisehd', function(done) {
        client.on('connect', function(data) { done(); });
    });

    it('accepts run request and replies with output', function(done) {
        var i = 0;
        client.on('connect', function(data) {
            client.on('run', function(data){
                expect(data).to.deep.equal(stdoutCode.output[i]);
                ++i;

                if (data.stream === 'status') done();
            });
            client.emit('run', stdoutCode.input);
        });
    });

    it('stops previous run request when running a new run', function(done) {
        client.on('connect', function(data) {
            client.on('run', function(data){
                if (data.stream === 'status') done();
            });
            client.emit('run', sleepCode.input);
            setTimeout(function() {
                client.emit('run', stdoutCode.input);
            }, 600);
        });
    });

    context('when run request is empty', function() {
        beforeEach(function() {
            params = null;
        });
        expectBadRequestError();
    });

    context('when language code is empty', function() {
        beforeEach(function() {
            params = { code: 'puts "lol"' };
        });
        expectBadRequestError();
    });

    context('when code is empty', function() {
        it('accepts run request', function(done) {
            client.on('connect', function(data) {
                client.on('run', function(data){
                    if (data.stream === 'status') done();
                });
                client.emit('run', { language: 'ruby' });
            });
        });
    });

    it('prevents run request spam', function(done) {
        client.on('connect', function(data) {
            client.on('run', function(data){
                if (data.stream === 'ignored') done();
            });
            client.emit('run', stdoutCode.input);
            client.emit('run', stdoutCode.input);
        });
    });

    function expectBadRequestError() {
        it('responds with a bad request error', function(done) {
            client.on('connect', function(data) {
                client.on('run', function(data){
                    if (data.stream === 'error') {
                        expect(data.chunk).to.eq('Bad request.');
                        done();
                    }
                });
                client.emit('run', params);
            });
        });
    }
});
<|endoftext|>


<commit_before>var assert = require('assert');
var tjs = require('../teslajs');

describe('TeslaJS', function() {
	describe('#login()', function() {
		it('should succeed with valid pwd', function() {
			assert(true);
		});
		it('should fail with invalid pwd', function() {
			assert(true);
		});
	});
});<commit_msg>debug require issue<commit_after>var assert = require('assert');

console.log("Home: " + process.env.HOME);

var tjs = require('../teslajs');

describe('TeslaJS', function() {
	describe('#login()', function() {
		it('should succeed with valid pwd', function() {
			assert(true);
		});
		it('should fail with invalid pwd', function() {
			assert(true);
		});
	});
});<|endoftext|>


<commit_before>/* global describe, it, expect, window */
"use strict";

describe('add', function () {
  it('should add two numbers and return the result', function () {
    expect(window.add(1, 2)).toBe(3);
  });
});

describe('subtract', function () {
  it('should subtract two numbers', function () {
    expect(window.subtract(2, 1)).toBe(1);
  });
});

describe('updateAppState', function () {
  it('should push a new state into the browser history', function () {
    window.updateAppState({
      message: 'hi'
    });
    expect(window.history.state).toEqual({
      message: 'hi'
    });
  });
});
<commit_msg>Add before/after blocks<commit_after>/* global describe, it, expect, window, beforeEach, beforeAll, afterEach, afterAll */
"use strict";

describe('math', function () {
  beforeAll(function () {
    console.log("Math: beforeAll()");
  });

  afterAll(function () {
    console.log("Math: afterAll()");
  });

  beforeEach(function () {
    console.log("Math: before()");
  });

  afterEach(function () {
    console.log("Math: after()");
  });

  it('should add two numbers', function () {
    expect(window.add(1, 2)).toBe(3);
  });

  it('should subtract two numbers', function () {
    expect(window.subtract(2, 1)).toBe(1);
  });
});

describe('updateAppState', function () {
  it('should push a new state into the browser history', function () {
    window.updateAppState({
      message: 'hi'
    });
    expect(window.history.state).toEqual({
      message: 'hi'
    });
  });
});
<|endoftext|>


<commit_before>/**
 * Module dependencies
 */

var fs = require('fs');
var util = require('util');
var responses = require('./lib/responses');
var generateView = false;

/**
 * sails-generate-responses
 *
 * Usage:
 * `sails generate response`
 *
 * @description Generates a response
 * @help See http://links.sailsjs.org/docs/generators
 */

module.exports = {

  /**
   * `before()` is run before executing any of the `targets`
   * defined below.
   *
   * This is where we can validate user input, configure default
   * scope variables, get extra dependencies, and so on.
   *
   * @param  {Object} scope
   * @param  {Function} cb    [callback]
   */

  before: function (scope, cb) {

    if (!scope.args[0]) {
      return cb( new Error('Please provide the name for this response using the status code, camel cased description. e.g: 201 or created; 204 or noContent') );
    }

    // The first command-line argument will be the response to generate
    scope.response = responses.getData(scope.args[0]);

    if( !scope.response )
    {
      return cb( new Error('Please provide one of the allowed response codes: 201, 204, 304, 401, 409') );
    }

    // scope.rootPath is the base path for this generator
    //
    // e.g. if this generator specified the target:
    // './Foobar.md': { copy: 'Foobar.md' }
    //
    // And someone ran this generator from `/Users/dbowie/sailsStuff`,
    // then `/Users/dbowie/sailsStuff/Foobar.md` would be created.
    if (!scope.rootPath) {
      return cb( INVALID_SCOPE_VARIABLE('rootPath') );
    }

    // Path to responses dir within the project
    scope.responsesDirectory = 'api/responses';

    // Decide the output filename for use in targets below:
    scope.responseFilename = scope.response.camelCasedDescription + '.js';

    if( !scope['no-view'] )
    {
      scope.viewsDirectory = 'views';
      scope.viewFilename = scope.response.code + '.ejs';
      var viewPath = scope.viewsDirectory + '/' + scope.viewFilename;
      if (fs.existsSync(this.templatesDirectory + '/' + viewPath))
      {
        this.targets['./:viewsDirectory/:viewFilename'] = { copy: viewPath };
      }
    }

    // Log type within the response: silent, error, warn, debug, info, verbose, silly
    // (set using --log-level)
    scope.response.logLevel = scope['log-level'] || scope.response.logLevel;

    // When finished, we trigger a callback with no error
    // to begin generating files/folders as specified by
    // the `targets` below.
    cb();
  },

  /**
   * The files/folders to generate.
   * @type {Object}
   */

  targets: {

    // Usage:
    // './path/to/destination.foo': { someHelper: opts }
    './:responsesDirectory/:responseFilename': { template: 'response.js' }

  },

  /**
   * The absolute path to the `templates` for this generator
   * (for use with the `template` helper)
   *
   * @type {String}
   */
  templatesDirectory: require('path').resolve(__dirname, './templates')
};

/**
 * INVALID_SCOPE_VARIABLE()
 *
 * Helper method to put together a nice error about a missing or invalid
 * scope variable. We should always validate any required scope variables
 * to avoid inadvertently smashing someone's filesystem.
 *
 * @param {String} varname [the name of the missing/invalid scope variable]
 * @param {String} details [optional - additional details to display on the console]
 * @param {String} message [optional - override for the default message]
 * @return {Error}
 * @api private
 */

function INVALID_SCOPE_VARIABLE (varname, details, message) {
  var DEFAULT_MESSAGE =
  'Issue encountered in generator "response":\n'+
  'Missing required scope variable: `%s`"\n' +
  'If you are the author of `sails-generate-response`, please resolve this '+
  'issue and publish a new patch release.';

  message = (message || DEFAULT_MESSAGE) + (details ? '\n'+details : '');
  message = util.inspect(message, varname);

  return new Error(message);
}<commit_msg>improved error messages<commit_after>/**
 * Module dependencies
 */

var fs = require('fs');
var util = require('util');
var responses = require('./lib/responses');
var generateView = false;

/**
 * sails-generate-responses
 *
 * Usage:
 * `sails generate response`
 *
 * @description Generates a response
 * @help See http://links.sailsjs.org/docs/generators
 */

module.exports = {

  /**
   * `before()` is run before executing any of the `targets`
   * defined below.
   *
   * This is where we can validate user input, configure default
   * scope variables, get extra dependencies, and so on.
   *
   * @param  {Object} scope
   * @param  {Function} cb    [callback]
   */

  before: function (scope, cb) {

    if (!scope.args[0]) {
      return cb( new Error('Please provide the response using the status code or camel cased description. e.g: sails generate response 204 or sails generate response noContent') );
    }

    // The first command-line argument will be the response to generate
    scope.response = responses.getData(scope.args[0]);

    if( !scope.response )
    {
      return cb( new Error('Please provide one of the allowed responses: ' + Object.keys(responses.data).join(', ') ) );
    }

    // scope.rootPath is the base path for this generator
    //
    // e.g. if this generator specified the target:
    // './Foobar.md': { copy: 'Foobar.md' }
    //
    // And someone ran this generator from `/Users/dbowie/sailsStuff`,
    // then `/Users/dbowie/sailsStuff/Foobar.md` would be created.
    if (!scope.rootPath) {
      return cb( INVALID_SCOPE_VARIABLE('rootPath') );
    }

    // Path to responses dir within the project
    scope.responsesDirectory = 'api/responses';

    // Decide the output filename for use in targets below:
    scope.responseFilename = scope.response.camelCasedDescription + '.js';

    if( !scope['no-view'] )
    {
      scope.viewsDirectory = 'views';
      scope.viewFilename = scope.response.code + '.ejs';
      var viewPath = scope.viewsDirectory + '/' + scope.viewFilename;
      if (fs.existsSync(this.templatesDirectory + '/' + viewPath))
      {
        this.targets['./:viewsDirectory/:viewFilename'] = { copy: viewPath };
      }
    }

    // Log type within the response: silent, error, warn, debug, info, verbose, silly
    // (set using --log-level)
    scope.response.logLevel = scope['log-level'] || scope.response.logLevel;

    // When finished, we trigger a callback with no error
    // to begin generating files/folders as specified by
    // the `targets` below.
    cb();
  },

  /**
   * The files/folders to generate.
   * @type {Object}
   */

  targets: {

    // Usage:
    // './path/to/destination.foo': { someHelper: opts }
    './:responsesDirectory/:responseFilename': { template: 'response.js' }

  },

  /**
   * The absolute path to the `templates` for this generator
   * (for use with the `template` helper)
   *
   * @type {String}
   */
  templatesDirectory: require('path').resolve(__dirname, './templates')
};

/**
 * INVALID_SCOPE_VARIABLE()
 *
 * Helper method to put together a nice error about a missing or invalid
 * scope variable. We should always validate any required scope variables
 * to avoid inadvertently smashing someone's filesystem.
 *
 * @param {String} varname [the name of the missing/invalid scope variable]
 * @param {String} details [optional - additional details to display on the console]
 * @param {String} message [optional - override for the default message]
 * @return {Error}
 * @api private
 */

function INVALID_SCOPE_VARIABLE (varname, details, message) {
  var DEFAULT_MESSAGE =
  'Issue encountered in generator "response":\n'+
  'Missing required scope variable: `%s`"\n' +
  'If you are the author of `sails-generate-response`, please resolve this '+
  'issue and publish a new patch release.';

  message = (message || DEFAULT_MESSAGE) + (details ? '\n'+details : '');
  message = util.inspect(message, varname);

  return new Error(message);
}<|endoftext|>


<commit_before>"use strict";

module.exports = function (grunt) {

    grunt.initConfig({

        pkg: grunt.file.readJSON("package.json"),

        config: {
            outputDir: "dist/",

            applicationFiles: [
                "app/js/sn-example-app/app.js",
                "app/js/*.js",
                "app/js/**/*.js",
                "app/js/**/**/*.js"
            ],

            vendorFiles: [
                "app/components/angular/angular.js",
                "app/components/angular-mocks/angular-mocks.js",
                "app/components/angular-route/angular-route.js",
            ]
        },

        connect: {
            server: {
                options: {
                    hostname: "0.0.0.0",
                    port: 8000,
                    livereload: true,
                    open: "http://localhost:8000/app/"
                }
            },
            servertest: {
                options: {
                    keepalive: false,
                    hostname: "0.0.0.0",
                    port: 8000,
                    livereload: false,
                    open: "http://localhost:8000/app/"
                }
            }
        },

        watch: {
            css: {
                files: [
                    "app/index.html",
                    "app/less/*.less",
                    "app/less/**/*.less",
                    "app/less/**/**/*.less",
                    "app/modules/*.html",
                    "app/modules/**/*.html",
                    "app/modules/**/**/*.html",
                    "app/partials/*.html",
                    "app/partials/**/*.html",
                    "app/partials/**/**/*.html"
                ],
                tasks: ["less:development"],
                options: {
                    nospawn: false,
                    livereload: true
                }
            },
            javascript: {
                files: [
                    "app/js/*.js",
                    "app/js/**/*.js",
                    "app/js/**/**/*.js",
                    "test/unit/**/*.js",
                    "test/unit/**/**/*.js",
                    "test/unit/**/**/**/*.js"
                ],
                tasks: ["jshint", "jasmine"],
                options: {
                    nospawn: false,
                    livereload: true
                }
            }
        },

        less: {
            development: {
                options: {
                    paths: ["app/less/"],
                    cleancss: false
                },
                files: {
                    "app/css/all.css": "app/less/main.less"
                }
            },
            production: {
                options: {
                    paths: ["app/less/"],
                    cleancss: true
                },
                files: {
                    "<%= config.outputDir %>/css/all.min.css": "app/less/main.less"
                }
            }
        },

        jshint: {
            dist: {
                src: ["<%= config.applicationFiles %>"]
            },
            options: {
                strict: false,
                browser: true,
                devel: true,
                asi: true,
                globalstrict: true,
                globals: {
                    "angular": true
                }
            }
        },

        jasmine: {
            dist: {
                src: ["<%= config.applicationFiles %>"],
                options: {
                    specs: ["tests/unit/**/*.js"],
                    keepRunner: true,
                    vendor: "<%= config.vendorFiles %>"
                }
            }
        },

        protractor: {
            options: {
                configFile: "node_modules/protractor/referenceConf.js", // Default config file
                keepAlive: true, // If false, the grunt process stops when the test fails.
                noColor: false, // If true, protractor will not use colors in its output.
                args: {
                    // Arguments passed to the command
                }
            },
            dist: {   // Grunt requires at least one target to run so you can simply put 'all: {}' here too.
                options: {
                    configFile: "tests/e2e/e2e.conf.js", // Target-specific config file
                    args: {} // Target-specific arguments
                }
            }
        },

        protractor_webdriver: {
            dist: {
                options: {

                }
            }
        },

        concat: {
            options: {
                separator: ";",
            },
            dist: {
                src: ["<%= config.vendorFiles %>", "<%= config.applicationFiles %>"],
                dest: "<%= config.outputDir %>/js/app.js",
            }
        },

        uglify: {
            dist: {
                files: {
                    "<%= config.outputDir %>/js/app.min.js": ["<%= config.vendorFiles %>", "<%= config.applicationFiles %>"]
                }
            }
        },

        copy: {
            images: {
                files: [{
                    expand: true,
                    cwd: "app/img",
                    src: ["**/*"],
                    dest: "<%= config.outputDir %>/img/"
                }]
            },
            javascript: {
                files: [{
                    expand: true,
                    cwd: "app/components",
                    src: ["**/*"],
                    dest: "<%= config.outputDir %>/components/"
                },
                {
                    expand: true,
                    cwd: "app/js",
                    src: ["**/*"],
                    dest: "<%= config.outputDir %>/js/"
                }]
            },
            css: {
                files: [{
                    expand: true,
                    cwd: "app/css",
                    src: ["*.css"],
                    dest: "<%= config.outputDir %>/css/"
                }]
            },
            partials: {
                files: [{
                    expand: true,
                    cwd: "app/partials",
                    src: ["*.html"],
                    dest: "<%= config.outputDir %>/partials/"
                }]
            }
        },

        clean: {
            beforeBuild: {
                src: ["<%= config.outputDir %>"]
            }
        },

        processhtml: {
            options: {
                data: {
                    message: "processing 'index.html' file"
                }
            },
            development: {
                files: {
                    "<%= config.outputDir %>/index.html": ["app/index.html"]
                }
            },
            dist: {
                files: {
                    "<%= config.outputDir %>/index.html": ["app/index.html"]
                }
            }
        },

        yuidoc: {
            compile: {
                name: "<%= pkg.name %>",
                description: "<%= pkg.description %>",
                version: "<%= pkg.version %>",
                url: "<%= pkg.homepage %>",
                options: {
                    paths: "app/js/",
                	themedir: "node_modules/yuidoc-bootstrap-theme",
        			helpers: ["node_modules/yuidoc-bootstrap-theme/helpers/helpers.js"],
                    outdir: "docs/"
                }
            }
        }

    });

    grunt.loadNpmTasks("grunt-contrib-copy");
    grunt.loadNpmTasks("grunt-contrib-clean");
    grunt.loadNpmTasks("grunt-contrib-concat");
    grunt.loadNpmTasks("grunt-contrib-uglify");
    grunt.loadNpmTasks("grunt-contrib-less");
    grunt.loadNpmTasks("grunt-contrib-watch");
    grunt.loadNpmTasks("grunt-contrib-connect");
    grunt.loadNpmTasks("grunt-contrib-jshint");
    grunt.loadNpmTasks('grunt-contrib-yuidoc');
    grunt.loadNpmTasks("grunt-contrib-jasmine");
    grunt.loadNpmTasks('grunt-protractor-runner');
    grunt.loadNpmTasks('grunt-protractor-webdriver');
    grunt.loadNpmTasks("grunt-processhtml");

    grunt.registerTask("build", [
        "jshint",
        "jasmine",
        "e2e",
        "clean:beforeBuild",
        "yuidoc",
        "less:production",
        "uglify",
        "copy:images",
        "copy:partials",
        "processhtml:dist"
    ]);

    grunt.registerTask("stage", [
        "jshint",
        "jasmine",
        "e2e",
        "clean:beforeBuild",
        "yuidoc",
        "less:development",
        "copy",
        "processhtml:development"
    ]);

    grunt.registerTask("server", [
        "less:development",
        "connect:server",
        "watch:css"
    ]);

    grunt.registerTask("serverall", [
        "less:development",
        "connect:server",
        "watch"
    ]);

    grunt.registerTask("test", [
        "jshint",
        "jasmine"
    ]);

    grunt.registerTask("e2e", [
        "connect:servertest",
        "protractor_webdriver",
        "protractor"
    ]);

    grunt.registerTask("default", ["stage"]);
    grunt.registerTask("release", ["build"]);

};
<commit_msg>updating jshint options<commit_after>"use strict";

module.exports = function (grunt) {

    grunt.initConfig({

        pkg: grunt.file.readJSON("package.json"),

        config: {
            outputDir: "dist/",

            applicationFiles: [
                "app/js/sn-example-app/app.js",
                "app/js/*.js",
                "app/js/**/*.js",
                "app/js/**/**/*.js"
            ],

            vendorFiles: [
                "app/components/angular/angular.js",
                "app/components/angular-mocks/angular-mocks.js",
                "app/components/angular-route/angular-route.js",
            ]
        },

        connect: {
            server: {
                options: {
                    hostname: "0.0.0.0",
                    port: 8000,
                    livereload: true,
                    open: "http://localhost:8000/app/"
                }
            },
            servertest: {
                options: {
                    keepalive: false,
                    hostname: "0.0.0.0",
                    port: 8000,
                    livereload: false,
                    open: "http://localhost:8000/app/"
                }
            }
        },

        watch: {
            css: {
                files: [
                    "app/index.html",
                    "app/less/*.less",
                    "app/less/**/*.less",
                    "app/less/**/**/*.less",
                    "app/modules/*.html",
                    "app/modules/**/*.html",
                    "app/modules/**/**/*.html",
                    "app/partials/*.html",
                    "app/partials/**/*.html",
                    "app/partials/**/**/*.html"
                ],
                tasks: ["less:development"],
                options: {
                    nospawn: false,
                    livereload: true
                }
            },
            javascript: {
                files: [
                    "app/js/*.js",
                    "app/js/**/*.js",
                    "app/js/**/**/*.js",
                    "test/unit/**/*.js",
                    "test/unit/**/**/*.js",
                    "test/unit/**/**/**/*.js"
                ],
                tasks: ["jshint", "jasmine"],
                options: {
                    nospawn: false,
                    livereload: true
                }
            }
        },

        less: {
            development: {
                options: {
                    paths: ["app/less/"],
                    cleancss: false
                },
                files: {
                    "app/css/all.css": "app/less/main.less"
                }
            },
            production: {
                options: {
                    paths: ["app/less/"],
                    cleancss: true
                },
                files: {
                    "<%= config.outputDir %>/css/all.min.css": "app/less/main.less"
                }
            }
        },

        jshint: {
            dist: {
                src: ["<%= config.applicationFiles %>"]
            },
            options: {
                strict: false,
                browser: true,
                devel: true,
                asi: true,
                curly: true,
                noarg: true,
                quotmark: "double",
				undef: true,
				unused: true,
                globalstrict: true,
                globals: {
                    "angular": true
                }
            }
        },

        jasmine: {
            dist: {
                src: ["<%= config.applicationFiles %>"],
                options: {
                    specs: ["tests/unit/**/*.js"],
                    keepRunner: true,
                    vendor: "<%= config.vendorFiles %>"
                }
            }
        },

        protractor: {
            options: {
                configFile: "node_modules/protractor/referenceConf.js", // Default config file
                keepAlive: false, // If false, the grunt process stops when the test fails.
                noColor: false, // If true, protractor will not use colors in its output.
                args: {
                    // Arguments passed to the command
                }
            },
            dist: {   // Grunt requires at least one target to run so you can simply put 'all: {}' here too.
                options: {
                    configFile: "tests/e2e/e2e.conf.js", // Target-specific config file
                    args: {} // Target-specific arguments
                }
            }
        },

        protractor_webdriver: {
            dist: {
                options: {

                }
            }
        },

        concat: {
            options: {
                separator: ";",
            },
            dist: {
                src: ["<%= config.vendorFiles %>", "<%= config.applicationFiles %>"],
                dest: "<%= config.outputDir %>/js/app.js",
            }
        },

        uglify: {
            dist: {
                files: {
                    "<%= config.outputDir %>/js/app.min.js": ["<%= config.vendorFiles %>", "<%= config.applicationFiles %>"]
                }
            }
        },

        copy: {
            images: {
                files: [{
                    expand: true,
                    cwd: "app/img",
                    src: ["**/*"],
                    dest: "<%= config.outputDir %>/img/"
                }]
            },
            javascript: {
                files: [{
                    expand: true,
                    cwd: "app/components",
                    src: ["**/*"],
                    dest: "<%= config.outputDir %>/components/"
                },
                {
                    expand: true,
                    cwd: "app/js",
                    src: ["**/*"],
                    dest: "<%= config.outputDir %>/js/"
                }]
            },
            css: {
                files: [{
                    expand: true,
                    cwd: "app/css",
                    src: ["*.css"],
                    dest: "<%= config.outputDir %>/css/"
                }]
            },
            partials: {
                files: [{
                    expand: true,
                    cwd: "app/partials",
                    src: ["*.html"],
                    dest: "<%= config.outputDir %>/partials/"
                }]
            }
        },

        clean: {
            beforeBuild: {
                src: ["<%= config.outputDir %>"]
            }
        },

        processhtml: {
            options: {
                data: {
                    message: "processing 'index.html' file"
                }
            },
            development: {
                files: {
                    "<%= config.outputDir %>/index.html": ["app/index.html"]
                }
            },
            dist: {
                files: {
                    "<%= config.outputDir %>/index.html": ["app/index.html"]
                }
            }
        },

        yuidoc: {
            compile: {
                name: "<%= pkg.name %>",
                description: "<%= pkg.description %>",
                version: "<%= pkg.version %>",
                url: "<%= pkg.homepage %>",
                options: {
                    paths: "app/js/",
                	themedir: "node_modules/yuidoc-bootstrap-theme",
        			helpers: ["node_modules/yuidoc-bootstrap-theme/helpers/helpers.js"],
                    outdir: "docs/"
                }
            }
        }

    });

    grunt.loadNpmTasks("grunt-contrib-copy");
    grunt.loadNpmTasks("grunt-contrib-clean");
    grunt.loadNpmTasks("grunt-contrib-concat");
    grunt.loadNpmTasks("grunt-contrib-uglify");
    grunt.loadNpmTasks("grunt-contrib-less");
    grunt.loadNpmTasks("grunt-contrib-watch");
    grunt.loadNpmTasks("grunt-contrib-connect");
    grunt.loadNpmTasks("grunt-contrib-jshint");
    grunt.loadNpmTasks('grunt-contrib-yuidoc');
    grunt.loadNpmTasks("grunt-contrib-jasmine");
    grunt.loadNpmTasks('grunt-protractor-runner');
    grunt.loadNpmTasks('grunt-protractor-webdriver');
    grunt.loadNpmTasks("grunt-processhtml");

    grunt.registerTask("build", [
        "jshint",
        "jasmine",
        "e2e",
        "clean:beforeBuild",
        "yuidoc",
        "less:production",
        "uglify",
        "copy:images",
        "copy:partials",
        "processhtml:dist"
    ]);

    grunt.registerTask("stage", [
        "jshint",
        "jasmine",
        "e2e",
        "clean:beforeBuild",
        "yuidoc",
        "less:development",
        "copy",
        "processhtml:development"
    ]);

    grunt.registerTask("server", [
        "less:development",
        "connect:server",
        "watch:css"
    ]);

    grunt.registerTask("serverall", [
        "less:development",
        "connect:server",
        "watch"
    ]);

    grunt.registerTask("test", [
        "jshint",
        "jasmine"
    ]);

    grunt.registerTask("e2e", [
        "connect:servertest",
        "protractor_webdriver",
        "protractor"
    ]);

    grunt.registerTask("default", ["stage"]);
    grunt.registerTask("release", ["build"]);

};
<|endoftext|>


<commit_before>'use strict';
var path = require('path');
var nock = require('nock');
var test = require('ava');
var pathExists = require('path-exists');
var BinBuild = require('../');
var fixture = path.join.bind(null, __dirname, 'fixtures');

test('expose a constructor', function (t) {
	t.plan(1);
	t.assert(typeof BinBuild === 'function', typeof BinBuild);
});

test('set source file', function (t) {
	t.plan(1);

	var build = new BinBuild()
		.src('src.tar.gz');

	t.assert(build._src === 'src.tar.gz', build._src);
});

test('add commands to run', function (t) {
	t.plan(2);

	var build = new BinBuild()
		.cmd('make')
		.cmd('make install');

	t.assert(build._cmd[0] === 'make', build._cmd[0]);
	t.assert(build._cmd[1] === 'make install', build._cmd[1]);
});

test('download and build source', function (t) {
	t.plan(3);

	var tmp = path.join(__dirname, 'tmp');
	var scope = nock('http://foo.com')
		.get('/gifsicle.tar.gz')
		.replyWithFile(200, fixture('test.tar.gz'));

	new BinBuild()
		.src('http://foo.com/gifsicle.tar.gz')
		.cmd('autoreconf -ivf')
		.cmd([
			'./configure --disable-gifview --disable-gifdiff',
			'--prefix="' + tmp + '" --bindir="' + tmp + '"'
		].join(' '))
		.cmd('make install')
		.run(function (err) {
			t.assert(!err, err);
			t.assert(scope.isDone());
			t.assert(pathExists.sync(path.join(tmp, 'gifsicle')));
		});
});

test('build source from existing archive', function (t) {
	t.plan(3);

	var tmp = path.join(__dirname, 'tmp');
	var scope = nock('http://foo.com')
		.get('/gifsicle.tar.gz')
		.replyWithFile(200, fixture('test.tar.gz'));

	new BinBuild()
		.src(fixture('test.tar.gz'))
		.cmd('autoreconf -ivf')
		.cmd([
			'./configure --disable-gifview --disable-gifdiff',
			'--prefix="' + tmp + '" --bindir="' + tmp + '"'
		].join(' '))
		.cmd('make install')
		.run(function (err) {
			t.assert(!err, err);
			t.assert(scope.isDone());
			t.assert(pathExists.sync(path.join(tmp, 'gifsicle')));
		});
});

test('pass the command error to the callback', function (t) {
	t.plan(2);

	nock('http://foo.com')
		.get('/gifsicle.tar.gz')
		.replyWithFile(200, fixture('test.tar.gz'));

	var build = new BinBuild()
		.src('http://foo.com/gifsicle.tar.gz')
		.cmd('autoreconf -ivf')
		.cmd('unknown-command')
		.cmd('./configure')
		.cmd('make install');

	build.run(function (err) {
		t.assert(err, err);
		t.assert(err.message.indexOf(build.cmd().join(' && ')) !== -1);
	});
});
<commit_msg>Remove unnecessary HTTP mock<commit_after>'use strict';
var path = require('path');
var nock = require('nock');
var test = require('ava');
var pathExists = require('path-exists');
var BinBuild = require('../');
var fixture = path.join.bind(null, __dirname, 'fixtures');

test('expose a constructor', function (t) {
	t.plan(1);
	t.assert(typeof BinBuild === 'function', typeof BinBuild);
});

test('set source file', function (t) {
	t.plan(1);

	var build = new BinBuild()
		.src('src.tar.gz');

	t.assert(build._src === 'src.tar.gz', build._src);
});

test('add commands to run', function (t) {
	t.plan(2);

	var build = new BinBuild()
		.cmd('make')
		.cmd('make install');

	t.assert(build._cmd[0] === 'make', build._cmd[0]);
	t.assert(build._cmd[1] === 'make install', build._cmd[1]);
});

test('download and build source', function (t) {
	t.plan(3);

	var tmp = path.join(__dirname, 'tmp');
	var scope = nock('http://foo.com')
		.get('/gifsicle.tar.gz')
		.replyWithFile(200, fixture('test.tar.gz'));

	new BinBuild()
		.src('http://foo.com/gifsicle.tar.gz')
		.cmd('autoreconf -ivf')
		.cmd([
			'./configure --disable-gifview --disable-gifdiff',
			'--prefix="' + tmp + '" --bindir="' + tmp + '"'
		].join(' '))
		.cmd('make install')
		.run(function (err) {
			t.assert(!err, err);
			t.assert(scope.isDone());
			t.assert(pathExists.sync(path.join(tmp, 'gifsicle')));
		});
});

test('build source from existing archive', function (t) {
	t.plan(2);

	var tmp = path.join(__dirname, 'tmp');

	new BinBuild()
		.src(fixture('test.tar.gz'))
		.cmd('autoreconf -ivf')
		.cmd([
			'./configure --disable-gifview --disable-gifdiff',
			'--prefix="' + tmp + '" --bindir="' + tmp + '"'
		].join(' '))
		.cmd('make install')
		.run(function (err) {
			t.assert(!err, err);
			t.assert(pathExists.sync(path.join(tmp, 'gifsicle')));
		});
});

test('pass the command error to the callback', function (t) {
	t.plan(2);

	nock('http://foo.com')
		.get('/gifsicle.tar.gz')
		.replyWithFile(200, fixture('test.tar.gz'));

	var build = new BinBuild()
		.src('http://foo.com/gifsicle.tar.gz')
		.cmd('autoreconf -ivf')
		.cmd('unknown-command')
		.cmd('./configure')
		.cmd('make install');

	build.run(function (err) {
		t.assert(err, err);
		t.assert(err.message.indexOf(build.cmd().join(' && ')) !== -1);
	});
});
<|endoftext|>


<commit_before>/* global Y */
'use strict'

function extend (Y) {
  class YArray {
    constructor (os, _model, idArray, valArray) {
      this.os = os
      this._model = _model
      // Array of all the operation id's
      this.idArray = idArray
      // Array of all the values
      this.valArray = valArray
      this.eventHandler = new Y.utils.EventHandler(ops => {
        var userEvents = []
        for (var i in ops) {
          var op = ops[i]
          if (op.struct === 'Insert') {
            let pos
            // we check op.left only!,
            // because op.right might not be defined when this is called
            if (op.left === null) {
              pos = 0
            } else {
              var sid = JSON.stringify(op.left)
              pos = this.idArray.indexOf(sid) + 1
              if (pos <= 0) {
                throw new Error('Unexpected operation!')
              }
            }
            this.idArray.splice(pos, 0, JSON.stringify(op.id))
            this.valArray.splice(pos, 0, op.content)
            userEvents.push({
              type: 'insert',
              object: this,
              index: pos,
              value: op.content,
              length: 1
            })
          } else if (op.struct === 'Delete') {
            let pos = this.idArray.indexOf(JSON.stringify(op.target))
            if (pos >= 0) {
              var val = this.valArray[pos]
              this.idArray.splice(pos, 1)
              this.valArray.splice(pos, 1)
              userEvents.push({
                type: 'delete',
                object: this,
                index: pos,
                value: val,
                length: 1
              })
            }
          } else {
            throw new Error('Unexpected struct!')
          }
        }
        this.eventHandler.callEventListeners(userEvents)
      })
    }
    get length () {
      return this.idArray.length
    }
    get (pos) {
      if (pos == null || typeof pos !== 'number') {
        throw new Error('pos must be a number!')
      }
      return this.valArray[pos]
    }
    toArray () {
      return this.valArray.slice()
    }
    push (contents) {
      this.insert(this.idArray.length, contents)
    }
    insert (pos, contents) {
      if (typeof pos !== 'number') {
        throw new Error('pos must be a number!')
      }
      if (!(contents instanceof Array)) {
        throw new Error('contents must be an Array of objects!')
      }
      if (contents.length === 0) {
        return
      }
      if (pos > this.idArray.length || pos < 0) {
        throw new Error('This position exceeds the range of the array!')
      }
      var mostLeft = pos === 0 ? null : JSON.parse(this.idArray[pos - 1])

      var ops = []
      var prevId = mostLeft
      for (var i = 0; i < contents.length; i++) {
        var op = {
          left: prevId,
          origin: prevId,
          // right: mostRight,
          // NOTE: I intentionally do not define right here, because it could be deleted
          // at the time of creating this operation, and is therefore not defined in idArray
          parent: this._model,
          content: contents[i],
          struct: 'Insert',
          id: this.os.getNextOpId()
        }
        ops.push(op)
        prevId = op.id
      }
      var eventHandler = this.eventHandler
      eventHandler.awaitAndPrematurelyCall(ops)
      this.os.requestTransaction(function *() {
        // now we can set the right reference.
        var mostRight
        if (mostLeft != null) {
          mostRight = (yield* this.getOperation(mostLeft)).right
        } else {
          mostRight = (yield* this.getOperation(ops[0].parent)).start
        }
        for (var j in ops) {
          ops[j].right = mostRight
        }
        yield* this.applyCreatedOperations(ops)
        eventHandler.awaitedInserts(ops.length)
      })
    }
    delete (pos, length) {
      if (length == null) { length = 1 }
      if (typeof length !== 'number') {
        throw new Error('pos must be a number!')
      }
      if (typeof pos !== 'number') {
        throw new Error('pos must be a number!')
      }
      if (pos + length > this.idArray.length || pos < 0 || length < 0) {
        throw new Error('The deletion range exceeds the range of the array!')
      }
      if (length === 0) {
        return
      }
      var eventHandler = this.eventHandler
      var newLeft = pos > 0 ? JSON.parse(this.idArray[pos - 1]) : null
      var dels = []
      for (var i = 0; i < length; i++) {
        dels.push({
          target: JSON.parse(this.idArray[pos + i]),
          struct: 'Delete'
        })
      }
      eventHandler.awaitAndPrematurelyCall(dels)
      this.os.requestTransaction(function *() {
        yield* this.applyCreatedOperations(dels)
        eventHandler.awaitedDeletes(dels.length, newLeft)
      })
    }
    observe (f) {
      this.eventHandler.addEventListener(f)
    }
    * _changed (transaction, op) {
      if (!op.deleted) {
        if (op.struct === 'Insert') {
          var l = op.left
          var left
          while (l != null) {
            left = yield* transaction.getOperation(l)
            if (!left.deleted) {
              break
            }
            l = left.left
          }
          op.left = l
        }
        this.eventHandler.receivedOp(op)
      }
    }
  }

  Y.extend('Array', new Y.utils.CustomType({
    name: 'Array', // TODO: copy the name when extending the object.. (see one line above)
    class: YArray,
    struct: 'List',
    initType: function * YArrayInitializer (os, model) {
      var valArray = []
      var idArray = yield* Y.Struct.List.map.call(this, model, function (c) {
        valArray.push(c.content)
        return JSON.stringify(c.id)
      })
      return new YArray(os, model.id, idArray, valArray)
    }
  }))
}

module.exports = extend
if (typeof Y !== 'undefined') {
  extend(Y)
}
<commit_msg>idArray -> _content<commit_after>/* global Y */
'use strict'

function extend (Y) {
  class YArray {
    constructor (os, _model, _content) {
      this.os = os
      this._model = _model
      // Array of all the neccessary content (includes id (string formatted, and element value))
      this._content = _content
      this.eventHandler = new Y.utils.EventHandler(ops => {
        var userEvents = []
        for (var i in ops) {
          var op = ops[i]
          if (op.struct === 'Insert') {
            let pos
            // we check op.left only!,
            // because op.right might not be defined when this is called
            if (op.left === null) {
              pos = 0
            } else {
              let sid = JSON.stringify(op.left)
              pos = 1 + this._content.findIndex(function (c) {
                return c.id === sid
              })
              if (pos <= 0) {
                throw new Error('Unexpected operation!')
              }
            }
            this._content.splice(pos, 0, {
              id: JSON.stringify(op.id),
              val: op.content
            })
            userEvents.push({
              type: 'insert',
              object: this,
              index: pos,
              value: op.content,
              length: 1
            })
          } else if (op.struct === 'Delete') {
            let sid = JSON.stringify(op.target)
            let pos = this._content.findIndex(function (c) {
              return c.id === sid
            })
            if (pos >= 0) {
              var val = this._content[pos].val
              this._content.splice(pos, 1)
              userEvents.push({
                type: 'delete',
                object: this,
                index: pos,
                value: val,
                length: 1
              })
            }
          } else {
            throw new Error('Unexpected struct!')
          }
        }
        this.eventHandler.callEventListeners(userEvents)
      })
    }
    get length () {
      return this._content.length
    }
    get (pos) {
      if (pos == null || typeof pos !== 'number') {
        throw new Error('pos must be a number!')
      }
      return this._content[pos].val
    }
    toArray () {
      return this._content.map(function (x) {
        return x.val
      })
    }
    push (contents) {
      this.insert(this._content.length, contents)
    }
    insert (pos, contents) {
      if (typeof pos !== 'number') {
        throw new Error('pos must be a number!')
      }
      if (!(contents instanceof Array)) {
        throw new Error('contents must be an Array of objects!')
      }
      if (contents.length === 0) {
        return
      }
      if (pos > this._content.length || pos < 0) {
        throw new Error('This position exceeds the range of the array!')
      }
      var mostLeft = pos === 0 ? null : JSON.parse(this._content[pos - 1].id)

      var ops = []
      var prevId = mostLeft
      for (var i = 0; i < contents.length; i++) {
        var op = {
          left: prevId,
          origin: prevId,
          // right: mostRight,
          // NOTE: I intentionally do not define right here, because it could be deleted
          // at the time of inserting this operation (when we get the transaction),
          // and would therefore not defined in this._conten
          parent: this._model,
          content: contents[i],
          struct: 'Insert',
          id: this.os.getNextOpId()
        }
        ops.push(op)
        prevId = op.id
      }
      var eventHandler = this.eventHandler
      eventHandler.awaitAndPrematurelyCall(ops)
      this.os.requestTransaction(function *() {
        // now we can set the right reference.
        var mostRight
        if (mostLeft != null) {
          mostRight = (yield* this.getOperation(mostLeft)).right
        } else {
          mostRight = (yield* this.getOperation(ops[0].parent)).start
        }
        for (var j in ops) {
          ops[j].right = mostRight
        }
        yield* this.applyCreatedOperations(ops)
        eventHandler.awaitedInserts(ops.length)
      })
    }
    delete (pos, length) {
      if (length == null) { length = 1 }
      if (typeof length !== 'number') {
        throw new Error('pos must be a number!')
      }
      if (typeof pos !== 'number') {
        throw new Error('pos must be a number!')
      }
      if (pos + length > this._content.length || pos < 0 || length < 0) {
        throw new Error('The deletion range exceeds the range of the array!')
      }
      if (length === 0) {
        return
      }
      var eventHandler = this.eventHandler
      var newLeft = pos > 0 ? JSON.parse(this._content[pos - 1].id) : null
      var dels = []
      for (var i = 0; i < length; i++) {
        dels.push({
          target: JSON.parse(this._content[pos + i].id),
          struct: 'Delete'
        })
      }
      eventHandler.awaitAndPrematurelyCall(dels)
      this.os.requestTransaction(function *() {
        yield* this.applyCreatedOperations(dels)
        eventHandler.awaitedDeletes(dels.length, newLeft)
      })
    }
    observe (f) {
      this.eventHandler.addEventListener(f)
    }
    * _changed (transaction, op) {
      if (!op.deleted) {
        if (op.struct === 'Insert') {
          var l = op.left
          var left
          while (l != null) {
            left = yield* transaction.getOperation(l)
            if (!left.deleted) {
              break
            }
            l = left.left
          }
          op.left = l
        }
        this.eventHandler.receivedOp(op)
      }
    }
  }

  Y.extend('Array', new Y.utils.CustomType({
    name: 'Array', // TODO: copy the name when extending the object.. (see one line above)
    class: YArray,
    struct: 'List',
    initType: function * YArrayInitializer (os, model) {
      var _content = yield* Y.Struct.List.map.call(this, model, function (c) {
        return {
          id: JSON.stringify(c.id),
          val: c.content
        }
      })
      return new YArray(os, model.id, _content)
    }
  }))
}

module.exports = extend
if (typeof Y !== 'undefined') {
  extend(Y)
}
<|endoftext|>


<commit_before>/*!
 *  Grunt Configurations
 */
module.exports = function (grunt) {
    'use strict';

    // ----------------------------
    //  GRUNT CONFIG
    // ----------------------------

    let babelFiles = [{
        expand: true,
        cwd: './src',
        src: ['./**/*.js'],
        dest: './build/'
        // ext: '.js'
    }];

    grunt.initConfig({
        // read in the project settings from the `package.json` file into the
        // `pkg` property
        pkg: grunt.file.readJSON('package.json'),

        'clean': {
            options: {
                force: false
            },
            build: [
                './build/**/*'
            ]
        },

        'babel': {
            options: {
                sourceMap: false,
                presets: ['es2015']
            },
            build: {
                options: {
                    retainLines: true
                },
                files: babelFiles
            },
            release: {
                options: {
                    retainLines: false
                },
                files: babelFiles
            }
        },

        'jasmine_nodejs': {
            options: {
                specNameSuffix: 'spec.js',
                helperNameSuffix: 'helper.js',
                useHelpers: false,
                random: false,
                seed: null,
                defaultTimeout: null,
                stopOnFailure: false,
                traceFatal: true,
                reporters: {
                    console: {
                        colors: true,
                        cleanStack: 3,
                        verbosity: 4,
                        listStyle: 'indent',
                        activity: false
                    }
                }
            },
            all: {
                specs: ['./test/**/*.spec.js']
            }
        },

        'docma': {
            traceFatal: true,
            options: {
                config: './docma.config.json'
            }
        }
    });

    // ----------------------------
    //  LOAD GRUNT PLUGINS
    // ----------------------------

    // load grunt plugins
    require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

    // ----------------------------
    //  REGISTER TASKS
    // ----------------------------

    grunt.registerTask('test', ['jasmine_nodejs']);
    grunt.registerTask('build', ['clean:build', 'babel:build', 'test']);
    grunt.registerTask('release', ['clean:build', 'babel:release', 'test', 'docma']);
    grunt.registerTask('default', ['build']);

};
<commit_msg>remove grunt<commit_after><|endoftext|>


<commit_before>/**
 * Test runner for nexe
 *
 * @author Jared Allard <jaredallard@outlook.com>
 * @license MIT
 **/

'use strict';

const assert = require('assert');
const fs     = require('fs');
const path   = require('path');
const spawn  = require('child_process').spawn;

// our vars
const NEXE_VERSION = require('../package.json').version;
const testBase = __dirname;
const LOG_FILE = path.join(testBase, 'test.log');

if(fs.existsSync(LOG_FILE)) {
  fs.unlinkSync(LOG_FILE);
}

let logfile = fs.createWriteStream(LOG_FILE, {
  autoClose: false
});

const compileTest = function(test, cb) {
  let testDir = path.join(testBase, test);
  if(!fs.existsSync(testDir)) {
    throw new Error('Test not found');
    return cb(false);
  }

  let npminst = spawn('npm', ['install'], {
    cwd: testDir
  });

  npminst.on('error', function() {
    throw new Error('Failed to execute NPM');
    return cb(false);
  });

  npminst.on('close', function(code) {
    if(code !== 0) {
      throw new Error('NPM exited with non-zero status');
      return cb(false);
    }

    let testinst = spawn('../../bin/nexe', [], {
      cwd: testDir
    });

    testinst.on('error', function() {
      throw new Error('Test failed to compile');
      return cb(false);
    });

    testinst.on('close', function(code) {
      let err = null;
      if(code !== 0) {
        throw new Error('Test gave non-zero code');
        err = false;
      }

      logfile = fs.createWriteStream(LOG_FILE);

      return cb(err);
    });
  });
};

/**
 * Run a test-generated binary
 *
 * @param {string} test - test name (dir)
 * @param {array} optional args - array of args to pass to the binary
 * @param {function} cb - callback
 **/
const runTest = function(test, args, cb) {
  let testDir = path.join(testBase, test);
  let testBin = path.join(testDir, 'test.nex')

  // check params
  if(!Array.isArray(args)) {
    cb = args;
    args = [];
  }

  if(!fs.existsSync(testDir)) {
    throw new Error('Test not found');
    return cb(false);
  }

  if(!fs.existsSync(testBin)) {
    throw new Error('Test binary not found');
    return cb(false);
  }

  let returned = false;
  let testinst = spawn(testBin, args, {
    cwd: testDir
  })

  testinst.stdout.on('data', function(d) {
    let status = d.toString('ascii');

    if(status === true || status === 'true' || status === 'true\n') {
      testinst.stdin.pause();
      testinst.kill();

      // make it know we returned.
      returned = true;

      return cb();
    }
  })

  testinst.on('close', function(c) {
    if(returned !== true) {
      throw new Error('Test failed (stdout never contained true)');
      return cb(false);
    }
  });

  testinst.stdout.on('data', function(d) {
    process.stdout.write(d.toString('ascii'));
  })
}

console.log('NOTICE: The first test may take awhile as it may compile Node.js');
console.log('        Monitor the log file (test.log) for progress.');

after(function() {
  console.log('notice: closing test.log file descriptor.')
  logfile.end();
});

/**
 * Tests express compatability.
 **/
describe('nexe can bundle express', function() {
  let testname = 'express-test';

  describe('build', function () {
    it('compiles without errors', function (next) {
      compileTest(testname, function(err) {
        return next(err);
      });
    });

    it('runs successfully', function(next) {
      runTest(testname, function(err) {
        return next(err);
      });
    });
  });
});

describe('nexe and embedding files', function() {
  let testname = 'embeded-files';

  describe('build', function () {
    it('compiles without errors', function (next) {
      compileTest(testname, function(err) {
        return next(err);
      });
    });

    it('runs successfully', function(next) {
      runTest(testname, function(err) {
        return next(err);
      });
    });
  });
});

describe('v8 flags test (strict mode)', function() {
  let testname = 'flags-test';

  describe('build', function () {
    it('compiles without errors', function (next) {
      compileTest(testname, function(err) {
        return next(err);
      });
    });

    it('runs successfully', function(next) {
      runTest(testname, function(err) {
        return next(err);
      });
    });
  });
});

describe('nexe can be utilized in gulp test', function() {
  let testname = 'gulp-test-170';

  describe('build', function () {
    it('compiles without errors', function (next) {
      compileTest(testname, function(err) {
        return next(err);
      });
    });

    it('runs successfully', function(next) {
      runTest(testname, function(err) {
        return next(err);
      });
    });
  });
});

describe('nexe can ignore node.js flags test', function() {
  let testname = 'ignoreFlags-test';

  describe('build', function () {
    it('compiles without errors', function (next) {
      compileTest(testname, function(err) {
        return next(err);
      });
    });

    it('runs successfully', function(next) {
      runTest(testname, ['--help'], function(err) {
        return next(err);
      });
    });
  });
});

describe('nexe supports js-yaml test', function() {
  let testname = 'js-yaml-148';

  describe('build', function () {
    it('compiles without errors', function (next) {
      compileTest(testname, function(err) {
        return next(err);
      });
    });

    it('runs successfully', function(next) {
      runTest(testname, function(err) {
        return next(err);
      });
    });
  });
});
<commit_msg>tests: actually output from the right command<commit_after>/**
 * Test runner for nexe
 *
 * @author Jared Allard <jaredallard@outlook.com>
 * @license MIT
 **/

'use strict';

const assert = require('assert');
const fs     = require('fs');
const path   = require('path');
const spawn  = require('child_process').spawn;

// our vars
const NEXE_VERSION = require('../package.json').version;
const testBase = __dirname;
const LOG_FILE = path.join(testBase, 'test.log');

if(fs.existsSync(LOG_FILE)) {
  fs.unlinkSync(LOG_FILE);
}

let logfile = fs.createWriteStream(LOG_FILE, {
  autoClose: false
});

const compileTest = function(test, cb) {
  let testDir = path.join(testBase, test);
  if(!fs.existsSync(testDir)) {
    throw new Error('Test not found');
    return cb(false);
  }

  let npminst = spawn('npm', ['install'], {
    cwd: testDir
  });

  npminst.on('error', function() {
    throw new Error('Failed to execute NPM');
    return cb(false);
  });

  npminst.on('close', function(code) {
    if(code !== 0) {
      throw new Error('NPM exited with non-zero status');
      return cb(false);
    }

    let testinst = spawn('../../bin/nexe', [], {
      cwd: testDir
    });

    testinst.on('error', function() {
      throw new Error('Test failed to compile');
      return cb(false);
    });

    testinst.on('close', function(code) {
      let err = null;
      if(code !== 0) {
        throw new Error('Test gave non-zero code');
        err = false;
      }

      logfile = fs.createWriteStream(LOG_FILE);

      return cb(err);
    });

    testinst.stdout.on('data', function(d) {
      process.stdout.write(d.toString('ascii'));
    });
  });
};

/**
 * Run a test-generated binary
 *
 * @param {string} test - test name (dir)
 * @param {array} optional args - array of args to pass to the binary
 * @param {function} cb - callback
 **/
const runTest = function(test, args, cb) {
  let testDir = path.join(testBase, test);
  let testBin = path.join(testDir, 'test.nex')

  // check params
  if(!Array.isArray(args)) {
    cb = args;
    args = [];
  }

  if(!fs.existsSync(testDir)) {
    throw new Error('Test not found');
    return cb(false);
  }

  if(!fs.existsSync(testBin)) {
    throw new Error('Test binary not found');
    return cb(false);
  }

  let returned = false;
  let testinst = spawn(testBin, args, {
    cwd: testDir
  })

  testinst.stdout.on('data', function(d) {
    let status = d.toString('ascii');

    if(status === true || status === 'true' || status === 'true\n') {
      testinst.stdin.pause();
      testinst.kill();

      // make it know we returned.
      returned = true;

      return cb();
    }
  })

  testinst.on('close', function(c) {
    if(returned !== true) {
      throw new Error('Test failed (stdout never contained true)');
      return cb(false);
    }
  });
}

console.log('NOTICE: The first test may take awhile as it may compile Node.js');
console.log('        Monitor the log file (test.log) for progress.');

after(function() {
  console.log('notice: closing test.log file descriptor.')
  logfile.end();
});

/**
 * Tests express compatability.
 **/
describe('nexe can bundle express', function() {
  let testname = 'express-test';

  describe('build', function () {
    it('compiles without errors', function (next) {
      compileTest(testname, function(err) {
        return next(err);
      });
    });

    it('runs successfully', function(next) {
      runTest(testname, function(err) {
        return next(err);
      });
    });
  });
});

describe('nexe and embedding files', function() {
  let testname = 'embeded-files';

  describe('build', function () {
    it('compiles without errors', function (next) {
      compileTest(testname, function(err) {
        return next(err);
      });
    });

    it('runs successfully', function(next) {
      runTest(testname, function(err) {
        return next(err);
      });
    });
  });
});

describe('v8 flags test (strict mode)', function() {
  let testname = 'flags-test';

  describe('build', function () {
    it('compiles without errors', function (next) {
      compileTest(testname, function(err) {
        return next(err);
      });
    });

    it('runs successfully', function(next) {
      runTest(testname, function(err) {
        return next(err);
      });
    });
  });
});

describe('nexe can be utilized in gulp test', function() {
  let testname = 'gulp-test-170';

  describe('build', function () {
    it('compiles without errors', function (next) {
      compileTest(testname, function(err) {
        return next(err);
      });
    });

    it('runs successfully', function(next) {
      runTest(testname, function(err) {
        return next(err);
      });
    });
  });
});

describe('nexe can ignore node.js flags test', function() {
  let testname = 'ignoreFlags-test';

  describe('build', function () {
    it('compiles without errors', function (next) {
      compileTest(testname, function(err) {
        return next(err);
      });
    });

    it('runs successfully', function(next) {
      runTest(testname, ['--help'], function(err) {
        return next(err);
      });
    });
  });
});

describe('nexe supports js-yaml test', function() {
  let testname = 'js-yaml-148';

  describe('build', function () {
    it('compiles without errors', function (next) {
      compileTest(testname, function(err) {
        return next(err);
      });
    });

    it('runs successfully', function(next) {
      runTest(testname, function(err) {
        return next(err);
      });
    });
  });
});
<|endoftext|>


<commit_before>/*
 * This file is part of gorilla-repl. Copyright (C) 2014-, Jony Hudson.
 *
 * gorilla-repl is licenced to you under the MIT licence. See the file LICENCE.txt for full details.
 */

// ** The worksheet wrapper **

// The main view model is wrapped in a wrapper. It exists mainly for historical reasons. It handles the UI elements that
// aren't really part of the worksheet (status etc), and contains info related to the server-side (like filename).

var worksheetWrapper = function (worksheet) {
    var self = {};

    self.worksheet = ko.observable(worksheet);

    // the filename that the worksheet corresponds to, if the worksheet was not loaded, or has never been saved,
    // this will be the empty string.
    self.filename = ko.observable("");
    self.title = ko.computed(function () {
        if (self.filename() === "") return "Gorilla REPL";
        else return "Gorilla REPL : " + self.filename();
    });

    // status indicator
    self.status = ko.observable("");
    // A message queue could be useful here, although I'm not sure it'll ever come up in practice.
    self.flashStatusMessage = function (message, displayMillis) {
        var millis = displayMillis ? displayMillis : 700;
        self.status(message);
        setTimeout(function () {self.status("");}, millis);
    };

    self.showStatusMessage = function (message) {
        self.status(message);
    };

    return self;
};

// ** The worksheet **

// this viewmodel represents the worksheet document itself. Code to manage the "cursor" that is, the highlight on the
// active segment, and the position of the editor cursors, is in the worksheet, as it needs to know about the
// relationship between the segments.
var worksheet = function () {
    var self = {};

    // the content of the worksheet is a list of segments.
    self.segments = ko.observableArray();

    // serialises the worksheet for saving. The result is valid clojure code, marked up with some magic comments.
    self.toClojure = function () {
        return ";; gorilla-repl.fileformat = 1\n\n" +
            self.segments().map(function (s) {
                return s.toClojure()
            }).join('\n');
    };

    // ** Segment management **

    self.segmentIndexForID = function (id) {
        // so, this is not perhaps the most efficient way you could think of doing this, but for reasonable conditions
        // it will be fine.
        for (var i = 0; i < self.segments().length; i++) {
            if (self.segments()[i].id == id) return i;
        }
        // this had better never happen!
        return -1;
    };

    self.getSegmentForID = function (id) {
        var index = self.segmentIndexForID(id);
        if (index >= 0) return self.segments()[index];
        else return null;
    };

    self.activeSegmentIndex = null;

    self.getActiveSegment = function () {
        if (self.activeSegmentIndex != null) return self.segments()[self.activeSegmentIndex];
        else return null;
    };

    self.activateSegment = function (index, fromTop) {
        self.segments()[index].activate(fromTop);
        self.activeSegmentIndex = index;
    };

    self.deactivateSegment = function (index) {
        self.segments()[index].deactivate();
        self.activeSegmentIndex = null;
    };

    self.deleteSegment = function (index) {
        self.segments.splice(index, 1);
        // after deletion, should activate segment after, unless it was the last segment, or there are no segments
        // remaining.
        if (self.segments().length == 0) return;
        if (index == self.segments().length) self.activateSegment(self.segments().length - 1, true);
        else self.activateSegment(index, false);
    };

    // ** Event handlers **
    // TODO: this is slightly nasty. The event handlers close over worksheet properties, so need to be removed and re-
    // TODO: added whenever the worksheet is changed. Maybe they shouldn't live here?

    // We store a list of added event types, by using this helper function to add events. This allows us to cleanly
    // deregister all the event handlers if the worksheet is to be replaced.
    var eventTypeList = [];
    var addEventHandler = function (event, callback) {
        eventTypeList.push(event);
        eventBus.on(event, callback);
    };
    // remove all worksheet event handlers from the bus - note that this will remove event handlers for _all_ worksheets
    // that exist, not just this one!
    self.removeEventHandlers = function () {
        eventTypeList.map(function (e) {eventBus.off(e);});
    };

    // * Activation cursor / focus handling *

    // activation/deactivation and focusing of segments.
    addEventHandler("worksheet:leaveForward", function () {
        var leavingIndex = self.activeSegmentIndex;
        // can't leave the bottom segment forwards
        if (leavingIndex == self.segments().length - 1) return;
        self.deactivateSegment(leavingIndex);
        self.activateSegment(leavingIndex + 1, true);
    });

    addEventHandler("worksheet:leaveBack", function () {
        var leavingIndex = self.activeSegmentIndex;
        // can't leave the top segment upwards
        if (leavingIndex == 0) return;
        self.deactivateSegment(leavingIndex);
        self.activateSegment(leavingIndex - 1, false);
    });

    addEventHandler("worksheet:delete", function () {
        // if there's only one segment, don't delete it
        if (self.segments().length == 1) return;
        var deleteIndex = self.activeSegmentIndex;
        self.deleteSegment(deleteIndex);
    });

    addEventHandler("worksheet:newBelow", function () {
        // do nothing if no segment is active
        if (self.activeSegmentIndex == null) return;
        var seg = codeSegment("");
        var currentIndex = self.activeSegmentIndex;
        self.deactivateSegment(currentIndex);
        self.segments.splice(currentIndex + 1, 0, seg);
        self.activateSegment(currentIndex + 1);
    });

    // the event for this action contains the segment id
    addEventHandler("worksheet:segment-clicked", function (e, d) {
        if (self.activeSegmentIndex != null) self.deactivateSegment(self.activeSegmentIndex);
        var focusIndex = self.segmentIndexForID(d.id);
        self.activateSegment(focusIndex, true);
    });

    // * Changing segment types *

    // a helper function that changes the type of the active segment
    var changeActiveSegmentType = function (newType, newSegmentConstructor) {
        var index = self.activeSegmentIndex;
        if (index == null) return;
        var seg = self.segments()[index];
        // if the segment is already a free segment, do nothing.
        if (seg.type == newType) return;

        var contents = seg.getContents();
        var newSeg = newSegmentConstructor(contents);
        self.segments.splice(index, 1, newSeg);
        self.activateSegment(index, true);
    };

    addEventHandler("worksheet:changeToFree", function () {
        changeActiveSegmentType("free", freeSegment);
    });

    addEventHandler("worksheet:changeToCode", function () {
        changeActiveSegmentType("code", codeSegment);
    });

    // * Toggling live mode *

    addEventHandler("worksheet:toggle-live", function () {
        var seg = self.getActiveSegment();
        if (seg == null) return;

        if (seg.type == "code") {
            var oldVal = seg.liveEvaluationMode();
            seg.liveEvaluationMode(!oldVal);
        }
    });

    // * Evaluation *

    // The evaluation command will fire this event. The worksheet will then send a message to the evaluator
    // to do the evaluation itself.
    addEventHandler("worksheet:evaluate", function () {
        // check that a segment is active
        var seg = self.getActiveSegment();
        if (seg == null) return;

        if (seg.type == "code") {
            // if this is a code segment, then evaluate the contents
            var code = seg.getContents();
            // clear the output
            seg.clearOutput();
            seg.clearErrorAndConsole();
            seg.runningIndicator(true);

            eventBus.trigger("evaluator:evaluate", {code: code, segmentID: seg.id});
        }

        // if this isn't the last segment, move to the next
        if (self.activeSegmentIndex != self.segments().length - 1) eventBus.trigger("command:worksheet:leaveForward");
        // if it is the last, create a new one at the end
        else eventBus.trigger("worksheet:newBelow")
    });

    // A minimal evaluation handler that is called when in live mode. The output is not cleared each time.
    addEventHandler("worksheet:live-evaluate", function () {
        // check that a segment is active
        var seg = self.getActiveSegment();
        if (seg == null) return;

        if (seg.type == "code") {
            // if this is a code segment, then evaluate the contents
            var code = seg.getContents();
            seg.clearErrorAndConsole();
            eventBus.trigger("evaluator:evaluate", {code: code, segmentID: seg.id});
        }
    });

    // messages from the evaluator

    addEventHandler("evaluator:value-response", function (e, d) {
        var segID = d.segmentID;
        var seg = self.getSegmentForID(segID);
        seg.output(d.value);
    });

    addEventHandler("evaluator:console-response", function (e, d) {
        var segID = d.segmentID;
        var seg = self.getSegmentForID(segID);
        var oldText = seg.consoleText();
        // note that no escaping is done to console strings - you could cause havoc by returning inappropriate HTML
        // if you were so minded.
        seg.consoleText(oldText + d.out);
    });

    addEventHandler("evaluator:done-response", function (e, d) {
        var segID = d.segmentID;
        var seg = self.getSegmentForID(segID);
        seg.runningIndicator(false);
    });

    addEventHandler("evaluator:error-response output:output-error", function (e, d) {
        var segID = d.segmentID;
        var seg = self.getSegmentForID(segID);
        seg.errorText(d.error);
    });

    // * Auto-completion *

    addEventHandler("worksheet:completions", function (e, d) {
        // check that a segment is active
        var seg = self.getActiveSegment();
        if (seg == null) return;
        if (seg.type == "code") {
            seg.content.complete(clojureCompleter);
        }
     });

    return self;
};<commit_msg>Clean up organisation of worksheet event handlers.<commit_after>/*
 * This file is part of gorilla-repl. Copyright (C) 2014-, Jony Hudson.
 *
 * gorilla-repl is licenced to you under the MIT licence. See the file LICENCE.txt for full details.
 */

// ** The worksheet wrapper **

// The main view model is wrapped in a wrapper. It exists mainly for historical reasons. It handles the UI elements that
// aren't really part of the worksheet (status etc), and contains info related to the server-side (like filename).

var worksheetWrapper = function (worksheet) {
    var self = {};

    self.worksheet = ko.observable(worksheet);

    // the filename that the worksheet corresponds to, if the worksheet was not loaded, or has never been saved,
    // this will be the empty string.
    self.filename = ko.observable("");
    self.title = ko.computed(function () {
        if (self.filename() === "") return "Gorilla REPL";
        else return "Gorilla REPL : " + self.filename();
    });

    // status indicator
    self.status = ko.observable("");
    // A message queue could be useful here, although I'm not sure it'll ever come up in practice.
    self.flashStatusMessage = function (message, displayMillis) {
        var millis = displayMillis ? displayMillis : 700;
        self.status(message);
        setTimeout(function () {self.status("");}, millis);
    };

    self.showStatusMessage = function (message) {
        self.status(message);
    };

    return self;
};

// ** The worksheet **

// this viewmodel represents the worksheet document itself. Code to manage the "cursor" that is, the highlight on the
// active segment, and the position of the editor cursors, is in the worksheet, as it needs to know about the
// relationship between the segments.
var worksheet = function () {
    var self = {};

    // the content of the worksheet is a list of segments.
    self.segments = ko.observableArray();

    // serialises the worksheet for saving. The result is valid clojure code, marked up with some magic comments.
    self.toClojure = function () {
        return ";; gorilla-repl.fileformat = 1\n\n" +
            self.segments().map(function (s) {
                return s.toClojure()
            }).join('\n');
    };

    // ** Segment management **

    self.segmentIndexForID = function (id) {
        // so, this is not perhaps the most efficient way you could think of doing this, but for reasonable conditions
        // it will be fine.
        for (var i = 0; i < self.segments().length; i++) {
            if (self.segments()[i].id == id) return i;
        }
        // this had better never happen!
        return -1;
    };

    self.getSegmentForID = function (id) {
        var index = self.segmentIndexForID(id);
        if (index >= 0) return self.segments()[index];
        else return null;
    };

    self.activeSegmentIndex = null;

    self.getActiveSegment = function () {
        if (self.activeSegmentIndex != null) return self.segments()[self.activeSegmentIndex];
        else return null;
    };

    self.activateSegment = function (index, fromTop) {
        self.segments()[index].activate(fromTop);
        self.activeSegmentIndex = index;
    };

    self.deactivateSegment = function (index) {
        self.segments()[index].deactivate();
        self.activeSegmentIndex = null;
    };

    self.deleteSegment = function (index) {
        self.segments.splice(index, 1);
        // after deletion, should activate segment after, unless it was the last segment, or there are no segments
        // remaining.
        if (self.segments().length == 0) return;
        if (index == self.segments().length) self.activateSegment(self.segments().length - 1, true);
        else self.activateSegment(index, false);
    };

    // ** Event handlers **
    // TODO: this is slightly nasty. The event handlers close over worksheet properties, so need to be removed and re-
    // TODO: added whenever the worksheet is changed. Maybe they shouldn't live here?

    // We store a list of added event types, by using this helper function to add events. This allows us to cleanly
    // deregister all the event handlers if the worksheet is to be replaced.
    var eventTypeList = [];
    var addEventHandler = function (event, callback) {
        eventTypeList.push(event);
        eventBus.on(event, callback);
    };
    // remove all worksheet event handlers from the bus - note that this will remove event handlers for _all_ worksheets
    // that exist, not just this one!
    self.removeEventHandlers = function () {
        eventTypeList.map(function (e) {eventBus.off(e);});
    };

    // * Activation cursor / focus handling *

    // activation/deactivation and focusing of segments.
    addEventHandler("worksheet:leaveForward", function () {
        var leavingIndex = self.activeSegmentIndex;
        // can't leave the bottom segment forwards
        if (leavingIndex == self.segments().length - 1) return;
        self.deactivateSegment(leavingIndex);
        self.activateSegment(leavingIndex + 1, true);
    });

    addEventHandler("worksheet:leaveBack", function () {
        var leavingIndex = self.activeSegmentIndex;
        // can't leave the top segment upwards
        if (leavingIndex == 0) return;
        self.deactivateSegment(leavingIndex);
        self.activateSegment(leavingIndex - 1, false);
    });

    // the event for this action contains the segment id
    addEventHandler("worksheet:segment-clicked", function (e, d) {
        if (self.activeSegmentIndex != null) self.deactivateSegment(self.activeSegmentIndex);
        var focusIndex = self.segmentIndexForID(d.id);
        self.activateSegment(focusIndex, true);
    });

    // * Manipulating segments *

    addEventHandler("worksheet:delete", function () {
        // if there's only one segment, don't delete it
        if (self.segments().length == 1) return;
        var deleteIndex = self.activeSegmentIndex;
        self.deleteSegment(deleteIndex);
    });

    addEventHandler("worksheet:newBelow", function () {
        // do nothing if no segment is active
        if (self.activeSegmentIndex == null) return;
        var seg = codeSegment("");
        var currentIndex = self.activeSegmentIndex;
        self.deactivateSegment(currentIndex);
        self.segments.splice(currentIndex + 1, 0, seg);
        self.activateSegment(currentIndex + 1);
    });

    // * Changing segment types *

    // a helper function that changes the type of the active segment
    var changeActiveSegmentType = function (newType, newSegmentConstructor) {
        var index = self.activeSegmentIndex;
        if (index == null) return;
        var seg = self.segments()[index];
        // if the segment is already a free segment, do nothing.
        if (seg.type == newType) return;

        var contents = seg.getContents();
        var newSeg = newSegmentConstructor(contents);
        self.segments.splice(index, 1, newSeg);
        self.activateSegment(index, true);
    };

    addEventHandler("worksheet:changeToFree", function () {
        changeActiveSegmentType("free", freeSegment);
    });

    addEventHandler("worksheet:changeToCode", function () {
        changeActiveSegmentType("code", codeSegment);
    });

    // * Toggling live mode *

    addEventHandler("worksheet:toggle-live", function () {
        var seg = self.getActiveSegment();
        if (seg == null) return;

        if (seg.type == "code") {
            var oldVal = seg.liveEvaluationMode();
            seg.liveEvaluationMode(!oldVal);
        }
    });

    // * Evaluation *

    // The evaluation command will fire this event. The worksheet will then send a message to the evaluator
    // to do the evaluation itself.
    addEventHandler("worksheet:evaluate", function () {
        // check that a segment is active
        var seg = self.getActiveSegment();
        if (seg == null) return;

        if (seg.type == "code") {
            // if this is a code segment, then evaluate the contents
            var code = seg.getContents();
            // clear the output
            seg.clearOutput();
            seg.clearErrorAndConsole();
            seg.runningIndicator(true);

            eventBus.trigger("evaluator:evaluate", {code: code, segmentID: seg.id});
        }

        // if this isn't the last segment, move to the next
        if (self.activeSegmentIndex != self.segments().length - 1) eventBus.trigger("command:worksheet:leaveForward");
        // if it is the last, create a new one at the end
        else eventBus.trigger("worksheet:newBelow")
    });

    // A minimal evaluation handler that is called when in live mode. The output is not cleared each time.
    addEventHandler("worksheet:live-evaluate", function () {
        // check that a segment is active
        var seg = self.getActiveSegment();
        if (seg == null) return;

        if (seg.type == "code") {
            // if this is a code segment, then evaluate the contents
            var code = seg.getContents();
            seg.clearErrorAndConsole();
            eventBus.trigger("evaluator:evaluate", {code: code, segmentID: seg.id});
        }
    });

    // messages from the evaluator

    addEventHandler("evaluator:value-response", function (e, d) {
        var segID = d.segmentID;
        var seg = self.getSegmentForID(segID);
        seg.output(d.value);
    });

    addEventHandler("evaluator:console-response", function (e, d) {
        var segID = d.segmentID;
        var seg = self.getSegmentForID(segID);
        var oldText = seg.consoleText();
        // note that no escaping is done to console strings - you could cause havoc by returning inappropriate HTML
        // if you were so minded.
        seg.consoleText(oldText + d.out);
    });

    addEventHandler("evaluator:done-response", function (e, d) {
        var segID = d.segmentID;
        var seg = self.getSegmentForID(segID);
        seg.runningIndicator(false);
    });

    addEventHandler("evaluator:error-response output:output-error", function (e, d) {
        var segID = d.segmentID;
        var seg = self.getSegmentForID(segID);
        seg.errorText(d.error);
    });

    // * Auto-completion *

    addEventHandler("worksheet:completions", function (e, d) {
        // check that a segment is active
        var seg = self.getActiveSegment();
        if (seg == null) return;
        if (seg.type == "code") {
            seg.content.complete(clojureCompleter);
        }
     });

    return self;
};<|endoftext|>


<commit_before>HospitalCheckup.module("InfectionsApp.Show", function(Show, HospitalCheckup, Backbone, Marionette, $, _){
  Show.Controller = {
    showHospital: function(id, aboutView, chartsView){ //received URL with ID parameter, or selected from viz

      var fetchingHospital = HospitalCheckup.request("hospital:entity", id);
      $.when(fetchingHospital).done(function(hospital){
        if(hospital !== undefined){
          aboutView.model = hospital;
          chartsView.collection.reset(chartsView.get_hospital_models(hospital));
        } else {
           //we should only end up here if someone goes to a URL
          //with an ID that none of our hospitals have (that shouldn't happen);
          aboutView = new Show.MissingHospital();
        }

        aboutView.render();
        chartsView.render();
      });
    }
  }
});<commit_msg>Don't rerender hospital details if model hasn't changed<commit_after>HospitalCheckup.module("InfectionsApp.Show", function(Show, HospitalCheckup, Backbone, Marionette, $, _){
  Show.Controller = {
    showHospital: function(id, aboutView, chartsView){ //received URL with ID parameter, or selected from viz

      var fetchingHospital = HospitalCheckup.request("hospital:entity", id);
      $.when(fetchingHospital).done(function(hospital){
        if(hospital !== undefined){
          if(aboutView.model){
            if(aboutView.model.get("id") !== hospital.get("id")){ //don't rerender if active hospital clicked again
              changeModels();
            }
          } else {
            changeModels();
          }
        } else {
           //we should only end up here if someone goes to a URL
          //with an ID that none of our hospitals have (that shouldn't happen);
          aboutView = new Show.MissingHospital().render();
        }

        function changeModels(){
          aboutView.model = hospital;
          chartsView.collection.reset(chartsView.get_hospital_models(hospital));
          aboutView.render();
        }
      });
    }
  }
});<|endoftext|>


<commit_before>import test from 'ava';
import stripAnsi from 'strip-ansi';
import m from '../';
import defaultFixture from './fixtures/default';
import deprecationsFixture from './fixtures/deprecations';
import invalidOptionsFixture from './fixtures/invalidOptions';

test('output', t => {
  const output = m(defaultFixture);
  console.log(output);
  t.regex(stripAnsi(output), /first\.css:3:12\n/);
  t.regex(stripAnsi(output), /✖[ ]{3}3:12[ ]{2}Unexpected leading zero[ ]{26}number-leading-zero/);
});

test('deprecations', t => {
  const output = m(deprecationsFixture);
  console.log(output);
  t.regex(stripAnsi(output), /Stylelint Configuration\n/);
  t.regex(stripAnsi(output), /ℹ time-no-imperceptible has been deprecated and in 8.0 will be removed. Instead use time-min-milliseconds with 100 as its primary option./);
  t.regex(stripAnsi(output), /ℹ block-no-single-line has been deprecated and in 8.0 will be removed. Instead use block-opening-brace-newline-after and block-closing-brace-newline-before with the always option./);
  t.regex(stripAnsi(output), /2 deprecations/);
});

test('invalid options', t => {
  const output = m(invalidOptionsFixture);
  console.log(output);
  t.regex(stripAnsi(output), /Stylelint Configuration\n/);
  t.regex(stripAnsi(output), /✖ Invalid option value snakeCase for rule value-keyword-case/);
  t.regex(stripAnsi(output), /✖ Unexpected option value always for rule no-unknown-animations/);
  t.regex(stripAnsi(output), /2 invalid options/);
});
<commit_msg>Add tests for empty or invalid Stylelint data, refs #2.<commit_after>import test from 'ava';
import stripAnsi from 'strip-ansi';
import m from '../';
import defaultFixture from './fixtures/default';
import deprecationsFixture from './fixtures/deprecations';
import invalidOptionsFixture from './fixtures/invalidOptions';

test('output', t => {
  const output = m(defaultFixture);
  t.regex(stripAnsi(output), /first\.css:3:12\n/);
  t.regex(stripAnsi(output), /✖[ ]{3}3:12[ ]{2}Unexpected leading zero[ ]{26}number-leading-zero/);
});

test('deprecations', t => {
  const output = m(deprecationsFixture);
  t.regex(stripAnsi(output), /Stylelint Configuration\n/);
  t.regex(stripAnsi(output), /ℹ time-no-imperceptible has been deprecated and in 8.0 will be removed. Instead use time-min-milliseconds with 100 as its primary option./);
  t.regex(stripAnsi(output), /ℹ block-no-single-line has been deprecated and in 8.0 will be removed. Instead use block-opening-brace-newline-after and block-closing-brace-newline-before with the always option./);
  t.regex(stripAnsi(output), /2 deprecations/);
});

test('invalid options', t => {
  const output = m(invalidOptionsFixture);
  t.regex(stripAnsi(output), /Stylelint Configuration\n/);
  t.regex(stripAnsi(output), /✖ Invalid option value snakeCase for rule value-keyword-case/);
  t.regex(stripAnsi(output), /✖ Unexpected option value always for rule no-unknown-animations/);
  t.regex(stripAnsi(output), /2 invalid options/);
});

test('empty results', t => {
  const output = m([]);
  t.is(stripAnsi(output), '');
});

test('invalid Stylelint output', t => {
  const output = m('foobar');
  t.is(stripAnsi(output), '');
});
<|endoftext|>